1

i am changing the structure of grid.phtml file and i want to know from where the product collection is coming when we add the products sku's in the product widget settings.

when i am checking the grid.phtml file from Magento_CatalogWidget its looking like

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

use Magento\Framework\App\Action\Action;

/** @var \Magento\CatalogWidget\Block\Product\ProductsList $block */

// phpcs:disable Generic.Files.LineLength.TooLong
// phpcs:disable Magento2.Templates.ThisInTemplate.FoundHelper
?>
<?php if ($exist = ($block->getProductCollection() && $block->getProductCollection()->getSize())): ?>

But when i checked the Magento\CatalogWidget\Block\Product\ProductsList am not seeing getProductCollection() method.

How can i know from which file this method is coming, and where the conditions are applied for the "Select Products By" option in product widget settings.

My custom block file

<?php

namespace MageMastery\HomePageTopSellers\Block;

use Magento\Catalog\Block\Product\Context;
use Magento\Framework\View\Element\Template;
use Magento\Catalog\Model\Product;
use Magento\Framework\Pricing\Render;
use Magento\Catalog\Pricing\Price\FinalPrice;
use Magento\Store\Model\ScopeInterface;
use Magento\Widget\Helper\Conditions;

/**
 * 
 */
class TopSellers extends Template
{
     /**
     * @var \Magento\Framework\App\Http\Context
     */
    protected $httpContext;

    protected $_customerSession;

    protected $conditionsHelper;

    public function __construct(
        Context $context,
        \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory, 
        \Magento\Store\Model\StoreManagerInterface $storemanager,
        \MageMastery\Catalog\Helper\Data $mdcHelper,
        \Magedelight\Catalog\Helper\Data $helperCatalog,
        \Magento\Wishlist\Helper\Data $whishtListHelper,
        \Magento\Catalog\Helper\Product\Compare $compareHelper,
        \Magento\Catalog\Block\Product\ListProduct $listProduct,
        \Magento\Framework\Data\Helper\PostHelper $postDataHelper,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
        \Magento\Framework\App\Http\Context $httpContext,
        \Magento\Customer\Model\Session $customerSession,
        \Magento\CatalogWidget\Block\Product\ProductsList $productslist,
        array $data = []
    )
    {
        $this->_productCollectionFactory = $productCollectionFactory;
        $this->_storeManager = $storemanager;
        $this->mdcHelper = $mdcHelper;
        $this->helperCatalog = $helperCatalog;
        $this->whishtListHelper = $whishtListHelper;
        $this->compareHelper = $compareHelper;
        $this->listProduct = $listProduct;
        $this->postDataHelper = $postDataHelper;
        $this->scopeConfig = $scopeConfig;
        $this->httpContext = $httpContext;
        $this->_customerSession = $customerSession;
        $this->productslist = $productslist;
        parent::__construct($context,$data);
    }

    public function _construct()
    {
        parent::_construct();

        $this->setTemplate('MageMastery_HomePageTopSellers::topsellers.phtml');
    }

    public function getProductCollection()
    {
        $collection = $this->_productCollectionFactory->create();

        $collection->addAttributeToSelect('*');
        $collection->addAttributeToFilter('status',\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED);
        $collection->joinField(
        'stock_status', 'cataloginventory_stock_status', 'stock_status', 'product_id=entity_id', '{{table}}.stock_id=1', 'left'
    )->addFieldToFilter('stock_status', array('eq' => \Magento\CatalogInventory\Model\Stock\Status::STATUS_IN_STOCK));
        $collection->getSelect()
            ->joinLeft(
                ['cpei' => 'catalog_product_entity_int'],
                'e.entity_id = cpei.row_id AND cpei.attribute_id = ( select attribute_id
                                from eav_attribute where attribute_code = \'is_available\')',
                []
            )->joinLeft(
                ['eaov' => 'eav_attribute_option_value'],
                'cpei.value = eaov.option_id',
                ['eaov.value as is_available'])
            ->where('!( eaov.value = \'New Product\' OR eaov.value = \'Delisted\')');
        $collection->setPageSize(3);
        return $collection;
    }

    public function getProductPriceHtml(
        Product $product,
        $priceType = null,
        $renderZone = Render::ZONE_ITEM_LIST,
        array $arguments = []
    ) {
        if (!isset($arguments['zone'])) {
            $arguments['zone'] = $renderZone;
        }
        $arguments['price_id']              = isset($arguments['price_id'])
            ? $arguments['price_id']
            : 'old-price-' . $product->getId() . '-' . $priceType;
        $arguments['include_container']     = isset($arguments['include_container'])
            ? $arguments['include_container']
            : true;
        $arguments['display_minimal_price'] = isset($arguments['display_minimal_price'])
            ? $arguments['display_minimal_price']
            : true;

        /** @var Render $priceRender */
        $priceRender = $this->getPriceRender();
        if (!$priceRender) {
            $priceRender = $this->getLayout()->createBlock(
                Render::class,
                'product.price.render.default',
                ['data' => ['price_render_handle' => 'catalog_product_prices']]
            );
        }

        return $priceRender->render(
            FinalPrice::PRICE_CODE,
            $product,
            $arguments
        );
    }

    protected function getPriceRender()
    {
        return $this->getLayout()->getBlock('product.price.render.default');
    }

    public function getImageUrl(){
        $store = $this->_storeManager->getStore();

        if($this->isMediaBaseUrlAdded()){

            $imgBaseUrl = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
        }else{
            $imgBaseUrl = $store->getBaseUrl()."media/".'catalog/product';
        }

        return $imgBaseUrl;
    }

    public function isMediaBaseUrlAdded(){

        $mediaBaseUrl = $this->scopeConfig->getValue(
            'web/secure/base_media_url',
            ScopeInterface::SCOPE_WEBSITE
        );
        if( NULL != $mediaBaseUrl){
            return true;
        }else{
            return false;
        }
        
    }

    public function getAddToCartPostParams($product){
        return $this->mdcHelper->getAddToCartPostParams($product);
    }

    public function getDefaultVendorId($productId){
        return $this->helperCatalog->getDefaultVendorId($productId);
    }

    public function getAjaxAddToCartUrl()
    {
        return $this->mdcHelper->getAjaxAddToCartUrl();
    }

    public function getWishListAllow(){
        return $this->whishtListHelper->isAllow();
    }

    public function getAddToWishlistParams($product)
    {
        return $this->whishtListHelper->getAddParams($product);
    }

    public function getAddToCompareUrl(){
        return $this->compareHelper->getAddUrl();
    }

    public function getPostDataParams($product){
        return $this->compareHelper->getPostDataParams($product);
    }

    public function getAddToCartUrl($product){

        return $this->listProduct->getAddToCartUrl($product);
    }

    public function getPostDataToAddCart($data,$item){
        return $this->postDataHelper->getPostData($data,$item);

    }
    public function checkProductInWishlist($productId)
    {   
        $wishlistDataArray = [];
        $wishlistCollection = $this->whishtListHelper->getWishlistItemCollection();
        $wishlistDataArray = $wishlistCollection->getColumnValues('product_id');
        if (in_array($productId, $wishlistDataArray)) {
            return true;
        }
        return false;
    }
    /**
     * @return boolean
     */
    public function isCustomerLoggedIn() {
        return $this->_customerSession->isLoggedIn();
    }
    public function getCustomerEmail(){
        return $this->_customerSession->getCustomer()->getEmail(); 
    }
    public function getWidgetCollection(){
        $widgetCollection = $this->productslist->createCollection();
        return $widgetCollection;
    }
    
}   

in the above code getCollection() method iam using to show topseller,

i also need the collection of products added using product element in the page builder.

iam trying by getWidgetCollection() to get the product element collection but its not working (facing this error - Error filtering template: Warning: Invalid argument supplied for foreach() in /var/www/html/apetito-ltd/vendor/magento/module-catalog-widget/Block/Product/ProductsList.php on line 406 ).

How can i get the product element collection in above file.

Thank you..!

1 Answer 1

0

The information here is based on Magento 2.3, I cannot confirm if it is the same for Magento 2.4

The \Magento\CatalogWidget\Block\Product\ProductsList contains calls to getProductCollection, which seems to be built like this:

  1. _beforeToHtml() function builds the collection via a call to createCollection().

  2. createCollection() builds and setups all the criteria, Ids, page sizes etc

  3. At the end (before returning from the function $collection->distinct(true) is called, trying to filter and remove duplicate records (let's assume by SKU and various other criteria).

  4. It then returns the collection, of type \Magento\Catalog\Model\ResourceModel\Product\Collection.

Getting the SQL

What you probably want to know is what data is returned, and how. You might want to investigate the SQL query generated; and you might be able to do this:

You can get SQL for most Magento 2 Collections like this (as they derive from the same base class):

Create a Plugin/Override this class and try to investigate the SQL query:

echo $collection->getSelect()->__toString()

(topic on Plugins/Overrides which you can search for anywhere on magento.stackexchange)

The above is the complete generated SQL query, and very useful most of the time to find out those obscure data Magento 2 returns. You can perhaps do a before DISTINCT SQL query as well to check the difference.

I would imagine a custom implementation that you want to modify would be to override createCollection and build your own custom filters.

EDIT:

Inserting a widget using the backend (Static CMS Blocks/Pages)

If the only thing you wanted to do was to 'insert the widget collection' as part of another block, you may be able to use the backend for Static Blocks / Pages

Two options directly from the backend:

Static Blocks/Pages: Navigate to Content -> Elements -> Pages/Blocks Use this to insert the widget into Static Block/Pages; select the WYSIWIG editor and insert the Widget you need

Layout Updates: Navigate to : Content -> Elements -> Widgets Use this to do a layout update: specify the Page you want to insert it.

Inserting using Custom block templates/Layout updates (non-CMS Blocks)

You will need to find the applicable xml layout file or .phtml template file where you want to insert the widget block and insert the \Magento\CatalogWidget\Block\Product\ProductsList as child block. The problem is that you will have to give all the parameters needed, for instance the template etc.

This answer might guide you on how to set the template for the widget:

Creating custom widget, how to use existing block like "RECENTLY VIEWED PRODUCTS" for a custom block, so that It should support all magento themes

8
  • HI @CvRChameleon, thanks for your explanation, i want to use createCollection() or i want to get product widget collection in other block file, how can i achieve that.
    – Mani
    Aug 29, 2022 at 9:25
  • Just to make sure, you want to use the current results as you see them, but just inside another location/template? Aug 29, 2022 at 9:46
  • yes @CvRChameleon, how can i achive that
    – Mani
    Aug 29, 2022 at 9:59
  • @Mani I updated my answer; as I do not know which type of 'block' you are referring to, CMS block and custom block implementations are different. I hope this guides with the information you need. Aug 29, 2022 at 10:12
  • hi @CvRChameleon , i just want to get the collection whatever the products we are added in using product element in the pagebuilder in my custom block.php file. Could you please tell me how can i get that exact collection in the custom block.php file
    – Mani
    Aug 29, 2022 at 10:21

Your Answer

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

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