0

Now i create product edit page Frequently Bought Together Products tab and add Frequently Bought Together button click product sidebar open and display product grid add select product so it's work but issue selected product save button click then database table save but Frequently Bought Together Products tab grid not display. i think modifyData() function issue.

so please advance thanks for help

app/code/vendor/BoughtTogether/Ui/DataProvider/Product/Form/Modifier/Bought.php

<?php

namespace vendor\BoughtTogether\Ui\DataProvider\Product\Form\Modifier;

use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\Data\ProductLinkInterface;
use Magento\Catalog\Api\ProductLinkRepositoryInterface;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Model\Locator\LocatorInterface;
use Magento\Eav\Api\AttributeSetRepositoryInterface;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Phrase;
use Magento\Framework\UrlInterface;
use Magento\Ui\Component\DynamicRows;
use Magento\Ui\Component\Form\Element\DataType\Number;
use Magento\Ui\Component\Form\Element\DataType\Text;
use Magento\Ui\Component\Form\Element\Input;
use Magento\Ui\Component\Form\Field;
use Magento\Ui\Component\Form\Fieldset;
use Magento\Ui\Component\Modal;
use Magento\Catalog\Helper\Image as ImageHelper;
use Magento\Catalog\Model\Product\Attribute\Source\Status;


class Bought extends \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Related
{
    const DATA_SCOPE = '';
    const DATA_SCOPE_BOUGHTTYPE = 'boughttype';
    const GROUP_BOUGHTTYPE = 'boughttype';

     /**
     * @var string
     */
    private static $previousGroup = 'search-engine-optimization';

    /**
     * @var int
     */
    private static $sortOrder = 90;

    /**
     * @var LocatorInterface
     * @since 101.0.0
     */
    protected $locator;

    /**
     * @var UrlInterface
     * @since 101.0.0
     */
    protected $urlBuilder;

    /**
     * @var ProductLinkRepositoryInterface
     * @since 101.0.0
     */
    protected $productLinkRepository;

    /**
     * @var ProductRepositoryInterface
     * @since 101.0.0
     */
    protected $productRepository;

    /**
     * @var ImageHelper
     * @since 101.0.0
     */
    protected $imageHelper;

    /**
     * @var Status
     * @since 101.0.0
     */
    protected $status;

    /**
     * @var AttributeSetRepositoryInterface
     * @since 101.0.0
     */
    protected $attributeSetRepository;

    /**
     * @var string
     * @since 101.0.0
     */
    protected $scopeName;

    /**
     * @var string
     * @since 101.0.0
     */
    protected $scopePrefix;

    protected $plCollection;

    /**
     * @var \Magento\Catalog\Ui\Component\Listing\Columns\Price
     */
    private $priceModifier;

    /**
     * @param LocatorInterface $locator
     * @param UrlInterface $urlBuilder
     * @param ProductLinkRepositoryInterface $productLinkRepository
     * @param ProductRepositoryInterface $productRepository
     * @param ImageHelper $imageHelper
     * @param Status $status
     * @param AttributeSetRepositoryInterface $attributeSetRepository
     * @param string $scopeName
     * @param string $scopePrefix
     */
    public function __construct(
        \Magento\Catalog\Model\ResourceModel\Product\Link\CollectionFactory $plCollection,
        LocatorInterface $locator,
        UrlInterface $urlBuilder,
        ProductLinkRepositoryInterface $productLinkRepository,
        ProductRepositoryInterface $productRepository,
        ImageHelper $imageHelper,
        Status $status,
        AttributeSetRepositoryInterface $attributeSetRepository,
        $scopeName = '',
        $scopePrefix = ''
    ) {
        $this->_plCollection = $plCollection;
        $this->locator = $locator;
        $this->urlBuilder = $urlBuilder;
        $this->productLinkRepository = $productLinkRepository;
        $this->productRepository = $productRepository;
        $this->imageHelper = $imageHelper;
        $this->status = $status;
        $this->attributeSetRepository = $attributeSetRepository;
        $this->scopeName = $scopeName;
        $this->scopePrefix = $scopePrefix;
    }

    /**
     * {@inheritdoc}
     */
    public function modifyMeta(array $meta)
    {
        $meta = array_replace_recursive(
            $meta,
            [
                static::GROUP_BOUGHTTYPE => [
                    'children' => [
                        $this->scopePrefix . static::DATA_SCOPE_BOUGHTTYPE => $this->getBoughtTypeFieldset()
                    ],
                    'arguments' => [
                        'data' => [
                            'config' => [
                                'label' => __('Frequently Bought Together Products'),
                                'collapsible' => true,
                                'componentType' => Fieldset::NAME,
                                'dataScope' => static::DATA_SCOPE,
                                'sortOrder' =>
                                    $this->getNextGroupSortOrder(
                                        $meta,
                                        self::$previousGroup,
                                        self::$sortOrder
                                    ),
                            ],
                        ],

                    ],
                ],
            ]
        );

        return $meta;
    }

    /**
     * {@inheritdoc}
     * @since 101.0.0
     */
    public function modifyData(array $data)
    {
        /** @var \Magento\Catalog\Model\Product $product */
        $product = $this->locator->getProduct();
        $productId = $product->getId();

        if (!$productId) {
            return $data;
        }
        $link_type_id = 6;
        $plCollection = $this->_plCollection->create();
        $plCollection->addFieldToFilter('product_id',$productId);
        $plCollection->addFieldToFilter('link_type_id',$link_type_id);
        $availableProduct = $plCollection->getColumnValues('linked_product_id');

        //print_r($availableProduct);

        /* echo "<pre>";
        print_r($plCollection->getData());
        echo "</pre>";
         */

        $priceModifier = $this->getPriceModifier();
        /**
         * Set field name for modifier
         */
        $priceModifier->setData('name', 'price');

        foreach ($this->getDataScopes() as $dataScope) {
            $data[$productId]['links'][$dataScope] = [];
            foreach ($this->productLinkRepository->getList($product) as $linkItem) {
                if ($linkItem->getLinkType() !== $dataScope) {
                    continue;
                }

                /** @var \Magento\Catalog\Model\Product $linkedProduct */
                $linkedProduct = $this->productRepository->get(
                    $linkItem->getLinkedProductSku(),
                    false,
                    $this->locator->getStore()->getId()
                );
                $data[$productId]['links'][$dataScope][] = $this->fillData($linkedProduct, $linkItem);
            }
            if (!empty($data[$productId]['links'][$dataScope])) {
                $dataMap = $priceModifier->prepareDataSource([
                    'data' => [
                        'items' => $data[$productId]['links'][$dataScope]
                    ]
                ]);
                $data[$productId]['links'][$dataScope] = $dataMap['data']['items'];
            }
        }

        $data[$productId][self::DATA_SOURCE_DEFAULT]['current_product_id'] = $productId;
        $data[$productId][self::DATA_SOURCE_DEFAULT]['current_store_id'] = $this->locator->getStore()->getId();

        return $data;
    }

    /**
     * Get price modifier
     *
     * @return \Magento\Catalog\Ui\Component\Listing\Columns\Price
     * @deprecated 101.0.0
     */
    private function getPriceModifier()
    {
        if (!$this->priceModifier) {
            $this->priceModifier = ObjectManager::getInstance()->get(
                \Magento\Catalog\Ui\Component\Listing\Columns\Price::class
            );
        }
        return $this->priceModifier;
    }

    /**
     * Prepares config for the Custom type products fieldset
     *
     * @return array
     */
    protected function getBoughtTypeFieldset()
    {
        $content = __(
            'Bought Together products are shown to customers in addition to the item the customer is looking at.'
        );

        return [
            'children' => [
                'button_set' => $this->getButtonSet(
                    $content,
                    __('Add Bought Together Products'),
                    $this->scopePrefix . static::DATA_SCOPE_BOUGHTTYPE
                ),
                'modal' => $this->getGenericModal(
                    __('Add Bought Together Products'),
                    $this->scopePrefix . static::DATA_SCOPE_BOUGHTTYPE
                ),
                static::DATA_SCOPE_BOUGHTTYPE => $this->getGrid($this->scopePrefix . static::DATA_SCOPE_BOUGHTTYPE),
            ],
            'arguments' => [
                'data' => [
                    'config' => [
                        'additionalClasses' => 'admin__fieldset-section',
                        'label' => __('Frequently Bought Together Products'),
                        'collapsible' => false,
                        'componentType' => Fieldset::NAME,
                        'dataScope' => '',
                        'sortOrder' => 90,
                    ],
                ],
            ]
        ];
    }

    /**
     * Prepare data column
     *
     * @param ProductInterface $linkedProduct
     * @param ProductLinkInterface $linkItem
     * @return array
     * @since 101.0.0
     */
    protected function fillData(ProductInterface $linkedProduct, ProductLinkInterface $linkItem)
    {
        return [
            'id' => $linkedProduct->getId(),
            'thumbnail' => $this->imageHelper->init($linkedProduct, 'product_listing_thumbnail')->getUrl(),
            'name' => $linkedProduct->getName(),
            'status' => $this->status->getOptionText($linkedProduct->getStatus()),
            'attribute_set' => $this->attributeSetRepository
                ->get($linkedProduct->getAttributeSetId())
                ->getAttributeSetName(),
            'sku' => $linkItem->getLinkedProductSku(),
            'price' => $linkedProduct->getPrice(),
            'position' => $linkItem->getPosition(),
        ];
    }

    /**
     * Retrieve all data scopes
     *
     * @return array
     */
    protected function getDataScopes()
    {
        return [
            static::DATA_SCOPE_BOUGHTTYPE
        ];
    }

    /**
     * Retrieve button set
     *
     * @param Phrase $content
     * @param Phrase $buttonTitle
     * @param string $scope
     * @return array
     * @since 101.0.0
     */
    protected function getButtonSet(Phrase $content, Phrase $buttonTitle, $scope)
    {
        $modalTarget = $this->scopeName . '.' . static::GROUP_BOUGHTTYPE . '.' . $scope . '.modal';

        return [
            'arguments' => [
                'data' => [
                    'config' => [
                        'formElement' => 'container',
                        'componentType' => 'container',
                        'label' => false,
                        'content' => $content,
                        'template' => 'ui/form/components/complex',
                    ],
                ],
            ],
            'children' => [
                'button_' . $scope => [
                    'arguments' => [
                        'data' => [
                            'config' => [
                                'formElement' => 'container',
                                'componentType' => 'container',
                                'component' => 'Magento_Ui/js/form/components/button',
                                'actions' => [
                                    [
                                        'targetName' => $modalTarget,
                                        'actionName' => 'toggleModal',
                                    ],
                                    [
                                        'targetName' => $modalTarget . '.' . $scope . '_product_listing',
                                        'actionName' => 'render',
                                    ]
                                ],
                                'title' => $buttonTitle,
                                'provider' => null,
                            ],
                        ],
                    ],

                ],
            ],
        ];
    }

     /**
     * Prepares config for modal slide-out panel
     *
     * @param Phrase $title
     * @param string $scope
     * @return array
     * @since 101.0.0
     */
    protected function getGenericModal(Phrase $title, $scope)
    {
        $listingTarget = $scope . '_product_listing';

        $modal = [
            'arguments' => [
                'data' => [
                    'config' => [
                        'componentType' => Modal::NAME,
                        'dataScope' => '',
                        'options' => [
                            'title' => $title,
                            'buttons' => [
                                [
                                    'text' => __('Cancel'),
                                    'actions' => [
                                        'closeModal'
                                    ]
                                ],
                                [
                                    'text' => __('Add Selected Products'),
                                    'class' => 'action-primary',
                                    'actions' => [
                                        [
                                            'targetName' => 'index = ' . $listingTarget,
                                            'actionName' => 'save'
                                        ],
                                        'closeModal'
                                    ]
                                ],
                            ],
                        ],
                    ],
                ],
            ],
            'children' => [
                $listingTarget => [
                    'arguments' => [
                        'data' => [
                            'config' => [
                                'autoRender' => false,
                                'componentType' => 'insertListing',
                                'dataScope' => $listingTarget,
                                'externalProvider' => $listingTarget . '.' . $listingTarget . '_data_source',
                                'selectionsProvider' => $listingTarget . '.' . $listingTarget . '.product_columns.ids',
                                'ns' => $listingTarget,
                                'render_url' => $this->urlBuilder->getUrl('mui/index/render'),
                                'realTimeLink' => true,
                                'dataLinks' => [
                                    'imports' => false,
                                    'exports' => true
                                ],
                                'behaviourType' => 'simple',
                                'externalFilterMode' => true,
                                'imports' => [
                                    'productId' => '${ $.provider }:data.product.current_product_id',
                                    'storeId' => '${ $.provider }:data.product.current_store_id',
                                ],
                                'exports' => [
                                    'productId' => '${ $.externalProvider }:params.current_product_id',
                                    'storeId' => '${ $.externalProvider }:params.current_store_id',
                                ]
                            ],
                        ],
                    ],
                ],
            ],
        ];

        return $modal;
    }

    /**
     * Retrieve grid
     *
     * @param string $scope
     * @return array
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     * @since 101.0.0
     */
    protected function getGrid($scope)
    {
        $dataProvider = $scope . '_product_listing';

        return [
            'arguments' => [
                'data' => [
                    'config' => [
                        'additionalClasses' => 'admin__field-wide',
                        'componentType' => DynamicRows::NAME,
                        'label' => null,
                        'columnsHeader' => false,
                        'columnsHeaderAfterRender' => true,
                        'renderDefaultRecord' => false,
                        'template' => 'ui/dynamic-rows/templates/grid',
                        'component' => 'Magento_Ui/js/dynamic-rows/dynamic-rows-grid',
                        'addButton' => false,
                        'recordTemplate' => 'record',
                        'dataScope' => 'data.links',
                        'deleteButtonLabel' => __('Remove'),
                        'dataProvider' => $dataProvider,
                        'map' => [
                            'id' => 'entity_id',
                            'name' => 'name',
                            'status' => 'status_text',
                            'attribute_set' => 'attribute_set_text',
                            'sku' => 'sku',
                            'price' => 'price',
                            'thumbnail' => 'thumbnail_src',
                        ],
                        'links' => [
                            'insertData' => '${ $.provider }:${ $.dataProvider }'
                        ],
                        'sortOrder' => 2,
                    ],
                ],
            ],
            'children' => [
                'record' => [
                    'arguments' => [
                        'data' => [
                            'config' => [
                                'componentType' => 'container',
                                'isTemplate' => true,
                                'is_collection' => true,
                                'component' => 'Magento_Ui/js/dynamic-rows/record',
                                'dataScope' => '',
                            ],
                        ],
                    ],
                    'children' => $this->fillMeta(),
                ],
            ],
        ];
    }

    /**
     * Retrieve meta column
     *
     * @return array
     * @since 101.0.0
     */
    protected function fillMeta()
    {
        return [
            'id' => $this->getTextColumn('id', false, __('ID'), 0),
            'thumbnail' => [
                'arguments' => [
                    'data' => [
                        'config' => [
                            'componentType' => Field::NAME,
                            'formElement' => Input::NAME,
                            'elementTmpl' => 'ui/dynamic-rows/cells/thumbnail',
                            'dataType' => Text::NAME,
                            'dataScope' => 'thumbnail',
                            'fit' => true,
                            'label' => __('Thumbnail'),
                            'sortOrder' => 10,
                        ],
                    ],
                ],
            ],
            'name' => $this->getTextColumn('name', false, __('Name'), 20),
            'status' => $this->getTextColumn('status', true, __('Status'), 30),
            'attribute_set' => $this->getTextColumn('attribute_set', false, __('Attribute Set'), 40),
            'sku' => $this->getTextColumn('sku', true, __('SKU'), 50),
            'price' => $this->getTextColumn('price', true, __('Price'), 60),
            'actionDelete' => [
                'arguments' => [
                    'data' => [
                        'config' => [
                            'additionalClasses' => 'data-grid-actions-cell',
                            'componentType' => 'actionDelete',
                            'dataType' => Text::NAME,
                            'label' => __('Actions'),
                            'sortOrder' => 70,
                            'fit' => true,
                        ],
                    ],
                ],
            ],
            'position' => [
                'arguments' => [
                    'data' => [
                        'config' => [
                            'dataType' => Number::NAME,
                            'formElement' => Input::NAME,
                            'componentType' => Field::NAME,
                            'dataScope' => 'position',
                            'sortOrder' => 80,
                            'visible' => false,
                        ],
                    ],
                ],
            ],
        ];
    }

    /**
     * Retrieve text column structure
     *
     * @param string $dataScope
     * @param bool $fit
     * @param Phrase $label
     * @param int $sortOrder
     * @return array
     * @since 101.0.0
     */
    protected function getTextColumn($dataScope, $fit, Phrase $label, $sortOrder)
    {
        $column = [
            'arguments' => [
                'data' => [
                    'config' => [
                        'componentType' => Field::NAME,
                        'formElement' => Input::NAME,
                        'elementTmpl' => 'ui/dynamic-rows/cells/text',
                        'component' => 'Magento_Ui/js/form/element/text',
                        'dataType' => Text::NAME,
                        'dataScope' => $dataScope,
                        'fit' => $fit,
                        'label' => $label,
                        'sortOrder' => $sortOrder,
                    ],
                ],
            ],
        ];

        return $column;
    }

}

enter image description here

Database Table:

(1) catalog_product_link table images

enter image description here

(2) catalog_product_link_type table

enter image description here

3

1 Answer 1

0

>

<?php

namespace Vendor\BoughtTogether\Block;

class Bought extends \Magento\Framework\View\Element\Template
{
    protected $boughtHelper;

    protected $_registry;

    protected $_productRepository;

     protected $_storeManager;

    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        \Vendor\BoughtTogether\Helper\Data $boughtHelper,
        \Magento\Catalog\Model\ProductRepository $productRepository,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\Registry $registry,
        array $data = []
    ) {
        parent::__construct($context);
        $this->boughtHelper = $boughtHelper;
        $this->_storeManager = $storeManager;
        $this->_productRepository = $productRepository;
        $this->_registry = $registry;

    }

    public function getEnableBoughtproducts()
    {
        return $this->boughtHelper->getEnableBoughtproducts();
    }
    public function getDisplayBlockname()
    {
         return $this->boughtHelper->getDisplayBlockname();
    }

    public function _prepareLayout()
    {
        return parent::_prepareLayout();
    }

    public function getCurrentProduct()
    {        
        return $this->_registry->registry('current_product');
    } 

    public function getProductById($id)
    {
        return $this->_productRepository->getById($id);
    } 

    public function getStore()
    {
         return $this->_storeManager->getStore();
    }    
}

<?php

/**
 * @var \Vendor\BoughtTogether\Block\Bought $block
 */
?>

<?php

    $myBlock = \Magento\Framework\App\ObjectManager::getInstance()->get('Vendor\BoughtTogether\Block\Bought');

    $currentProduct = $myBlock->getCurrentProduct();
    $store = $block->getStore();   
    $catalog_media =   $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product';

    if ($currentProduct = $myBlock->getCurrentProduct()) {
    $boughttypeProducts = $currentProduct->getBoughttypeProducts();

        if (!empty($boughttypeProducts)) {
            $bought_products = array();
            foreach ($boughttypeProducts as $boughttypeProduct) {
                /* $boughturl = $boughttypeProducts->getProductUrl();
                print_r($boughturl); */
                $bought_products [] = $boughttypeProduct['entity_id'];
            }
        }    

    }
?>
<?php if ($block->getEnableBoughtproducts() && isset($bought_products)): ?>

<div class="widget block block-static-block">
    <div>
        <div class="mcs-frequently-bought-together-block">
        <hr>
            <div class="mcs-fbt-title block-title title">
                <h2 id="block-mcs-fbt-heading">
                    <?php echo $block->getDisplayBlockname(); ?>
                </h2>
            </div>

            <div class="mcs-fbt-content">
                <form id="mcs-fbt-form" method="post" action="" novalidate="novalidate">
                <div class="wrapper grid products-grid">
                    <ol class="mcs-fbt-image-box">
                        <li class="item product first-item product-item mcs-fbt-item-<?php echo $currentProduct->getId() ?>">
                            <span>
                                <span class="product-image-container" style="width:152px;">
                                    <span class="product-image-wrapper" style="padding-bottom: 125%;">
                                        <img class="product-image-photo" src="<?php echo $catalog_media.$currentProduct->getImage();?>" width="100px" height="190px" alt="<?php echo $currentProduct->getName();?>" />

                                    </span>
                                </span>
                            </span>
                        </li>
                        <li class="product-item-plus mcs-fbt-plus-<?php echo $currentProduct->getId() ?>">
                            <span>+</span>
                        </li>

                        <?php 
                        foreach($bought_products as $_id){       
                            $item = $block->getProductById($_id);
                            //$boughturl = $item->getProductUrl();
                            //$boughturl = $item->getUrlModel()->getProductUrl($item);
                            $boughturl = $item->getProductUrl();
                            /* echo "<pre>";
                            print_r(get_class_methods($item->getUrlModel()));
                            echo "</pre>"; */

                        ?>
                        <li class="item product first-item product-item mcs-fbt-item-<?php echo $item->getId() ?>">
                            <span>
                                <a href="<?php echo $boughturl; ?>" class="product photo product-item-photo mcs-fbt-url-product">
                                <span class="product-image-container" style="width:152px;">
                                    <span class="product-image-wrapper" style="padding-bottom: 125%;">
                                        <img class="product-image-photo" src="<?php echo $catalog_media.$item->getImage();?>" width="100px" height="190px" alt="<?php echo $item->getName();?>" />

                                    </span>
                                </span>
                                </a>
                            </span>
                        </li>
                        <li class="product-item-plus mcs-fbt-plus-<?php echo $item->getId() ?>">
                            <span>+</span>
                        </li>
                       <?php  } ?>
                    </ol>
                </div>
                <div class="mcs-fbt-rows">
                    <ul>
                        <li>
                            <input type="checkbox" class="checkbox custom-checkbox" id="custom-checkbox<?php echo $currentProduct->getId() ?>" name="custom_products[]" value="<?php echo $currentProduct->getId() ?>" />
                            <span>
                                <div class="mcs-fbt-checkbox-label">
                                <strong>This item:</strong>
                                <span class="mcs-fbt-name-<?php echo $currentProduct->getId() ?>"><?php echo $currentProduct->getName();?></span>
                                <span class="item-price mcs-fbt-price-<?php echo $currentProduct->getId() ?>"><?php echo $currentProduct->getPrice();?></span>
                                </div>
                            </span>
                        </li>
                        <?php 
                        foreach($bought_products as $_id){       
                            $item = $block->getProductById($_id);
                            $boughturl = $item->getProductUrl();
                        ?>
                        <li>
                            <input type="checkbox" class="checkbox custom-checkbox" id="custom-checkbox<?php echo $item->getId() ?>" name="custom_products[]" value="<?php echo $item->getId() ?>" />
                            <span>
                                <div class="mcs-fbt-checkbox-label">
                                <a href="<?php echo $boughturl;?>">
                                <span class="mcs-fbt-name-<?php echo $item->getId() ?>"><?php echo $item->getName();?></span></a>
                                <span class="item-price mcs-fbt-price-<?php echo $item->getId() ?>"><?php echo $item->getPrice();?></span>
                                </div>
                            </span>
                        </li>
                        <?php } ?>
                    </ul>
                </div>
                </form>
            </div>
        </div>
    </div>
</div>

<?php endif;  ?>
<style>
.product-item-plus {
    display: inline-block;
    line-height: 125px;
    font-size: 22px;
    color: #757575;
}
.mcs-fbt-image-box {
    width: auto;
    max-width: 80%;
    margin: 0;
}
.product-image-photo {
    bottom: 0;
    display: block;
    height: auto;
    left: 0;
    margin: auto;
    max-width: 100%;
    position: absolute;
    right: 0;
    top: 0;
}
.mcs-fbt-rows {
    clear: left;
}
.mcs-fbt-rows .mcs-fbt-checkbox-label {
    display: inline-block;
}
.mcs-fbt-rows ul li {
    list-style: none;
}
</style>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.