Pergunta

I have to show out of stock products only in certain categories by hiding them in all other categories.

used below plugin to implement, that is not working.

Vendor/Module/etc/di.xml

<type name="Magento\Catalog\Model\Layer">
    <plugin name="Vendor_Module_Layer" type="Vendor\Module\Plugin\CatalogInventoryLayer" sortOrder="10" disabled="false"  />
</type>

Then

Vendor/Module/Plugin/CatalogInventoryLayer.php

<?php

namespace Vendor\Module\Plugin;

use Magento\Catalog\Model\Layer as CatalogLayer;
use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection;

class CatalogInventoryLayer {
protected $_logger;
public function __construct( 
    \Psr\Log\LoggerInterface $logger
    ){
        $this->_logger = $logger;
    }
public function aroundPrepareProductCollection(CatalogLayer $subject, \Closure $proceed, $collection)
{
    $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/customlog.log');
    $logger = new \Zend\Log\Logger();
    $logger->addWriter($writer);        
    $categoryId = $subject->getCurrentCategory()->getId();      
    $proceed($collection);
    if ($categoryId == 4){
        $collection->getSelect()->joinLeft(
                 ['_inventory_table' => 'cataloginventory_stock_item'], 
                 "_inventory_table.product_id = e.entity_id", ['is_in_stock']
        );
        $collection->addFieldToFilter('is_in_stock',array('eq'=>'0'));

    }       

    return $this;
    }
  }

Update:

Vendor/Module/etc/di.xml

<type name="Magento\CatalogInventory\Helper\Stock">
  <plugin name="Vendor_Extension_Stock_Helper" type="Vendor\Extension\Plugin\Helper\Stock" sortOrder="10" disabled="false"  />
</type>

Vendor/Module/Plugin/Helper/Stock.php

<?php 
namespace Vendor\Module\Plugin\Helper;
use Magento\CatalogInventory\Model\ResourceModel\Stock\StatusFactory;
class Stock
{    
private $logger;
protected $_registry;
protected $request;
protected $stockStatusResource;
protected $stockStatusFactory;
public function __construct(
    \Psr\Log\LoggerInterface $logger,
    \Magento\Framework\Registry $registry,
    \Magento\Framework\App\Request\Http $request,
    StatusFactory $stockStatusFactory
) {
    $this->logger = $logger;
    $this->_registry = $registry;
    $this->request = $request;
    $this->stockStatusFactory  = $stockStatusFactory;
}
public function aroundAddIsInStockFilterToCollection(\Magento\CatalogInventory\Helper\Stock $subject, \Closure $proceed, $collection)
{
    try{
        $category = $this->_registry->registry('current_category');//get current category
        $currentPage = $this->request->getFullActionName(); //catalogsearch_result_index
        if(!is_null($category) && $currentPage!= 'catalogsearch_result_index')
        {
            $stockFlag = 'has_stock_status_filter';
            $categoryId = $category->getId();                   
            $parentCategoryId =  $category->getParentCategory()->getId();               
            if($categoryId == 10 || $parentCategoryId == 10)
            {
            $resource = $this->getStockStatusResource();                
                $resource->addStockDataToCollection(
                        $collection,
                        false
                ); 
            }
            $collection->setFlag($stockFlag, true);
        } 
        return $this;
    }catch(\Exception $e){
        return $e->getMessage();
        $this->logger->info('--exception--'.$e->getMessage());
    }
}

public function getStockStatusResource(){
    if (empty($this->stockStatusResource)) {
        $this->stockStatusResource = $this->stockStatusFactory->create();
    }
    return $this->stockStatusResource;
   }
}

I have to display them only when we visit some specific categories by hiding them in all other categories

The updated code is working in category page, but search result page out of stock from other categories also visible,

Is there any way to show only out of stock products which belongs to category id '10'.

Can anyone please check and update me if there is any other way to implement the above functionality. Thanks!!

Foi útil?

Solução

To do above things, you need to do this things.

  1. Vendor\Extension\etc\di.xml
<type name="Magento\CatalogInventory\Helper\Stock">
    <plugin name="Vendor_Extension_Stock_Helper" type="Vendor\Extension\Plugin\Helper\Stock" sortOrder="10" disabled="false"  />
</type>
  1. Create the Helper File with arround plugin.

Vendor\Extension\Plugin\Helper\Stock.php

<?php
namespace Vendor\Extension\Plugin\Helper;

class Stock
{    
    public function aroundAddIsInStockFilterToCollection(\Magento\CatalogInventory\Helper\Stock $subject, \Closure $proceed, $collection)
    {
       // Do your Logic Here
        return $returnValue;
    }
}

Outras dicas

You should extend the original function ( Magento\CatalogInventory\Model\ProductCollectionStockCondition::apply() ) which is checking the stock configuration.

"Display out of stock products" config in store > Config > catalog > inventory.

You can use preference to extend that apply() function and add additional condition like that.

from:
$this->stockHelper->addIsInStockFilterToCollection($collection);

to:
if(in_array(category_id, ur_list_of_ids))
$this->stockHelper->addIsInStockFilterToCollection($collection);

In this way, you can enable out of stock products in some of the category only.

You can display **ONLY Out Of Stock products for particular category page**, first, you need to set configuration for Display Out of Stock Products, Go to Stores > Configuration > Catalog > Inventory > Stock Options->Display Out of Stock Products set as Yes, because for category page and product page product is not visible or not in collection if it's set as No, I'm not sure why Out Of Stock products is not available in Collection without "Display Out of Stock Products" configuration.

But for display Out Of Stock products for a particular category, you can change aroundPrepareProductCollection() as per below or replace your plugin file, I have checked it displays only Out Of Stock product only on the Category page.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Vendor\Module\Plugin;

use Magento\Catalog\Model\Layer as CatalogLayer;

class CatalogInventoryLayer
{
    public function aroundPrepareProductCollection(CatalogLayer $subject, \Closure $proceed, $collection)
    {
        $categoryId = $subject->getCurrentCategory()->getId();
        $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/OutOfStock_Product.log');
        $logger = new \Zend\Log\Logger();
        $logger->addWriter($writer);

        //Get Out Of Stock Products
        $collection->addFieldToSelect('*')
            ->setFlag('has_stock_status_filter', true)
            ->joinField('stock_item', 'cataloginventory_stock_item', 'is_in_stock', 'product_id=entity_id', 'is_in_stock=0');
        $collection->addCategoriesFilter(['eq' => $categoryId]); // Current category filter, it's not require, because PrepareProductCollection() automatically apply filter for current category. 

        $logger->info(print_r($collection->getData(), true));

        return $collection;
    }
}

Out of stock products of Bags category, you can see in screenshots.

enter image description here

enter image description here

I hope it will helpful for you.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a magento.stackexchange
scroll top