0

I want to override Magento\PageBuilder\Model\Catalog\Sorting\SimpleOption.php file. Please check the code below,

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\PageBuilder\Model\Catalog\Sorting\SimpleOption" type="CompanyName\ModuleName\Model\Catalog\Sorting\SimpleOption" />
</config>

This is Model File,

<?php

namespace CompanyName\ModuleName\Model\Catalog\Sorting;
use Magento\Framework\DB\Select;

class SimpleOption extends \Magento\PageBuilder\Model\Catalog\Sorting\SimpleOption
{
     /**
     * @var string
     */
    private $label;

    /**
     * @var string
     */
    private $sortDirection;

    /**
     * @var string
     */
    private $secondarySortDirection;

    /**
     * @var string
     */
    private $attributeField;

    public function __construct(
        string $label,
        string $sortDirection = null,
        string $attributeField = null,
        string $secondarySortDirection = null
    ){
        $this->secondarySortDirection = $secondarySortDirection ?? $sortDirection;
        parent::__construct(
        $label,
        $sortDirection,
        $attributeField
        );
        
    }

public function sort(
        \Magento\Catalog\Model\ResourceModel\Product\Collection $collection
    ): \Magento\Catalog\Model\ResourceModel\Product\Collection {
        
        if ($this->attributeField && $this->sortDirection) {
            $collection->getSelect()->reset(Select::ORDER);
            $collection->addAttributeToSort($this->attributeField, $this->sortDirection);
            $collection->addAttributeToSort('test_id', $this->secondarySortDirection);
        }
        return $collection;
   }

}

It seems not working. Can you guys please check and let me know what is the wrong in this file or any alternate way? Thanks,

2 Answers 2

1

\Magento\PageBuilder\Model\Catalog\Sorting\SimpleOption class is not created directly by \Magento\Framework\ObjectManager\FactoryInterface so preference does not work.

Since you want to replace the sort method (a public method) in Magento\PageBuilder\Model\Catalog\Sorting\SimpleOption class, there are 3 approaches available:

  • Use around plugin
  • Override virtual types to replace the type which is assigned to Magento\PageBuilder\Model\Catalog\Sorting\SimpleOption. Eg:

<virtualType name="Magento\PageBuilder\Model\Catalog\Sorting\Date\NewestTop" type="Magetu\Pagebuilder\Model\Catalog\Sorting\SimpleOption"/>

This approach requires you to apply this change to all virtual types which assigned to Magento\PageBuilder\Model\Catalog\Sorting\SimpleOption.

  • Create a custom composer patch to replace the core file vendor/magento/module-page-builder/Model/Catalog/Sorting/SimpleOption.php.

Because sort is a public method, you should use around plugin instead of preference.

<Your module dir>/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\PageBuilder\Model\Catalog\Sorting\SimpleOption">
        <plugin name="UseCustomEntityForSorting"
                type="Magetu\PageBuilder\Plugin\UseCustomEntityForSorting"/>
    </type>
</config>

<Your module dir>/Plugin/UseCustomEntityForSorting.php

<?php
namespace Magetu\PageBuilder\Plugin;

use Magento\Catalog\Model\ResourceModel\Product\Collection;
use Magento\PageBuilder\Model\Catalog\Sorting\SimpleOption;

class UseCustomEntityForSorting
{
    /**
     * @param SimpleOption $subject
     * @param callable $proceed
     * @param Collection $collection
     * @return Collection
     */
    public function aroundSort(SimpleOption $subject, callable $proceed, Collection $collection): Collection
    {
        // Write your override for the `sort` method here
        return $collection;
    }
}

In above files, I've used Magetu as vendor name, PageBuilder as module name, you should replace it to your vendor name, module name.


More details about how \Magento\PageBuilder\Model\Catalog\Sorting\SimpleOption class is created: when Magento\PageBuilder\Model\Catalog\Sorting class (Sorting of Catalog Widget Products) is initiating, it initiates sortInstances via sortClasses argument:

/**
 * @param Sorting\Factory $factory
 * @param array $sortClasses
 * @throws \Magento\Framework\Exception\LocalizedException
 */
public function __construct(
    Sorting\Factory $factory,
    array $sortClasses
) {
    $this->sortClasses = $sortClasses;
    $this->factory = $factory;
    foreach ($this->sortClasses as $key => $className) {
        $this->sortInstances[$key] = $this->factory->create($className);
    }
}

which is passed in <Magento_PageBuilder module dir>/etc/di.xml:

<type name="Magento\PageBuilder\Model\Catalog\Sorting">
    <arguments>
        <argument name="sortClasses" xsi:type="array">
            <item name="position" xsi:type="string">Magento\PageBuilder\Model\Catalog\Sorting\Position\Ascending</item>
            <item name="position_by_sku" xsi:type="string">Magento\PageBuilder\Model\Catalog\Sorting\PositionBySku</item>
            <item name="date_newest_top" xsi:type="string">Magento\PageBuilder\Model\Catalog\Sorting\Date\NewestTop</item>
            <item name="date_oldest_top" xsi:type="string">Magento\PageBuilder\Model\Catalog\Sorting\Date\OldestTop</item>
            <item name="name_ascending" xsi:type="string">Magento\PageBuilder\Model\Catalog\Sorting\Name\Ascending</item>
            <item name="name_descending" xsi:type="string">Magento\PageBuilder\Model\Catalog\Sorting\Name\Descending</item>
            <item name="sku_ascending" xsi:type="string">Magento\PageBuilder\Model\Catalog\Sorting\Sku\Ascending</item>
            <item name="sku_descending" xsi:type="string">Magento\PageBuilder\Model\Catalog\Sorting\Sku\Descending</item>
            <item name="low_stock_first" xsi:type="string">Magento\PageBuilder\Model\Catalog\Sorting\Stock\Ascending</item>
            <item name="high_stock_first" xsi:type="string">Magento\PageBuilder\Model\Catalog\Sorting\Stock\Descending</item>
            <item name="price_high_to_low" xsi:type="string">Magento\PageBuilder\Model\Catalog\Sorting\Price\Descending</item>
            <item name="price_low_to_high" xsi:type="string">Magento\PageBuilder\Model\Catalog\Sorting\Price\Ascending</item>
        </argument>
    </arguments>
</type>

For example, class date_newest_top is assigned to Magento\PageBuilder\Model\Catalog\Sorting\Date\NewestTop class, whenever factory creates that class, it calls Magento\PageBuilder\Model\Catalog\Sorting\SimpleOption instead as the config defined in <Magento_PageBuilder module dir>/etc/di.xml:

<virtualType name="Magento\PageBuilder\Model\Catalog\Sorting\Date\NewestTop" type="Magento\PageBuilder\Model\Catalog\Sorting\SimpleOption">
    <arguments>
        <argument name="label" xsi:type="string">Newest products first</argument>
        <argument name="sortDirection" xsi:type="const">\Magento\Framework\DB\Select::SQL_DESC</argument>
        <argument name="attributeField" xsi:type="string">entity_id</argument>
    </arguments>
</virtualType>

Here Magento\PageBuilder\Model\Catalog\Sorting\SimpleOption is not created directly from factory so preference does not work.

6
  • I am not getting this $this->secondarySortDirection value dynamically in plugin file, $collection->addAttributeToSort('row_id', $this->secondarySortDirection); Commented Mar 29, 2023 at 8:57
  • $this is the variable for the plugin class, not for the original class, to call the original class, you should use $subject. But secondarySortDirection, sortDirection, and attributeField are private properties so you can't call them from the plugin class. And these properties are passing via di.xml so you can't get them in the plugin. So you should go with another approach, please let me if you have any questions.
    – Tu Van
    Commented Mar 29, 2023 at 9:33
  • 1
    Yes, I used virtual type and it works for me. Thanks!! Commented Mar 29, 2023 at 9:35
  • You're welcome. Cheers!
    – Tu Van
    Commented Mar 29, 2023 at 9:39
  • Can you please look into this and guide me? magento.stackexchange.com/questions/365303/… Commented Mar 29, 2023 at 12:58
0

Try this code as your Model File

<?php
    
    namespace CompanyName\ModuleName\Model\Catalog\Sorting;
    use Magento\Framework\DB\Select;
    
    class SimpleOption extends \Magento\PageBuilder\Model\Catalog\Sorting\SimpleOption
    {
         /**
         * @var string
         */
        private $label;
    
        /**
         * @var string
         */
        private $sortDirection;
    
        /**
         * @var string
         */
        private $secondarySortDirection;
    
        /**
         * @var string
         */
        private $attributeField;
    
        public function __construct(
            string $label,
            string $sortDirection = null,
            string $attributeField = null,
            string $secondarySortDirection = 'asc'
        ){
            $this->secondarySortDirection = $secondarySortDirection;
            parent::__construct(
            $label,
            $sortDirection,
            $attributeField
            );
            
        }
    
    public function sort(
            \Magento\Catalog\Model\ResourceModel\Product\Collection $collection
        ): \Magento\Catalog\Model\ResourceModel\Product\Collection {
            
            if ($this->attributeField && $this->sortDirection) {
                $collection->getSelect()->reset(Select::ORDER);
                $collection->addAttributeToSort($this->attributeField, $this->sortDirection);
                $collection->addAttributeToSort('test_id', $this->secondarySortDirection);
            }
            return $collection;
       }
    
    }

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.