Magento 2 – Module Not Working, Override Fails

extensionsmagento-2.1magento2moduleoverrides

I am trying to write a module that filters products in a product collection. For that I have tried to override Magento\Catalog\Model\Layer. These are the files in the module:

/Viking/FilterProducts/registration.php

<?php 
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Viking_FilterProducts',
    __DIR__
);
?>

/Viking/FilterProducts/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">
    <preference for="Magento\Catalog\Model\Layer" type="Viking\FilterProducts\Model\Layer" />
</config>

/Viking/FilterProducts/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Viking_FilterProducts" setup_version="1.0.0"/>
</config>

/Viking/FilterProducts/Module/Layer.php

<?php

namespace Viking\FilterProducts\Model;


class Layer extends \Magento\Catalog\Model\Layer{

    protected $_customerSession;

    protected $_resource;

    public function __construct(
        \Magento\Catalog\Model\Layer\ContextInterface $context,
        \Magento\Catalog\Model\Layer\StateFactory $layerStateFactory,
        AttributeCollectionFactory $attributeCollectionFactory,
        \Magento\Catalog\Model\ResourceModel\Product $catalogProduct,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\Registry $registry,
        CategoryRepositoryInterface $categoryRepository,
        array $data = []
        ) {
            $this->_resource = $resource;
            $this->_customerSession = $customerSession; 
            parent::__construct(
                $context,
                $layerStateFactory,
                $attrubuteCollectionFactory,
                $catalogProduct,
                $registry,
                $categoryRopository,
                $data
            );
    }

    //Old funciton with print statement
    public function getProductCollection(){

        if (isset($this->_productCollections[$this->getCurrentCategory()->getId()])) {
            $collection = $this->_productCollections[$this->getCurrentCategory()->getId()];
        } else {
            $collection = $this->collectionProvider->getCollection($this->getCurrentCategory());
            //Will filter products here
            $this->prepareProductCollection($collection);
            $this->_productCollections[$this->getCurrentCategory()->getId()] = $collection;
        }

        echo 'New Layer <br />';

        return $collection;
    }




}
?>

It is still the old Layer that is called. I have overridden other classes in the same way but this time it doesn't work and I don't know why.Been stuck at this point really long now. No error messages.

removing constructor (which will be used) does not make any difference.

Edit

I changed the module.xml file as @dersam suggested but it did not help. I also added an composer.json file in Viking/FilterProducts that look like this:

{
    "name": "Viking/FilterProducts",
    "type": "magento2-module",
    "version": "1.0.0",
    "require": {
        "php": "~5.5.0|~5.6.0|~7.0.0",
        "magento/module-catalog": "~100.0"
    }
}

This did not make any difference either but I am not sure if it is correct. (I ran disable/enable command and then setup and compile commands). The module shows up as enabled when running module:status.

Best Answer

I think I know the problem. You are overriding the incorrect class. Layer model used in layered navigation is created in a constructor of Magento\LayeredNavigation\Block\Navigation class by this piece of code

public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \Magento\Catalog\Model\Layer\Resolver $layerResolver,
    \Magento\Catalog\Model\Layer\FilterList $filterList,
    \Magento\Catalog\Model\Layer\AvailabilityFlagInterface $visibilityFlag,
    array $data = []
) {
    $this->_catalogLayer = $layerResolver->get();
    $this->filterList = $filterList;
    $this->visibilityFlag = $visibilityFlag;
    parent::__construct($context, $data);
}

$layoutResolver->get() method looks like this:

public function get()
{
    if (!isset($this->layer)) {
        $this->layer = $this->objectManager->create($this->layersPool[self::CATALOG_LAYER_CATEGORY]);
    }
    return $this->layer;
}

So it creates a class based on a list of layerPool property which is set in layoutResover class constructor. By default this array contain 2 values:

[
     'category' => 'Magento\Catalog\Model\Layer\Category',
     'search' => 'Magento\Catalog\Model\Layer\Search'
]

So either create a preference for the class you want to change it, probably Magento\Catalog\Model\Layer\Category or change the class name passed to layoutResolver class. The original setup can be found in Magento_Catalog/etc/di.xml:

<type name="Magento\Catalog\Model\Layer\Resolver">
    <arguments>
        <argument name="layersPool" xsi:type="array">
            <item name="category" xsi:type="string">Magento\Catalog\Model\Layer\Category</item>
            <item name="search" xsi:type="string">Magento\Catalog\Model\Layer\Search</item>
        </argument>
    </arguments>
</type>