Skip to content

Creating a new custom filter in the first position in the layered navigation

I need to create a new filter that concerns the publication dates in my page called new products. This filter is based on an attribute (frist_publication_data) that concerns the first publication date of a product. This filter should have a range
0 – 3 months
3 – 6 months
6 – 9 months.

I would like to recreate the functionality of the magento price present in the layered navigation but I can’t trace the logic behind it to be able to show it on the frontend. Could anyone help me?
I also already have the filterList.php linked to its di.xml and I created the module with the filter like this::

`<?php
namespace VendorTimeRangeFilterModelLayerFilter;

use MagentoCatalogModelLayerFilterAbstractFilter;
use MagentoFrameworkAppRequestInterface;
use MagentoCatalogModelLayer;
use MagentoFrameworkStdlibDateTimeTimezoneInterface;
use MagentoFrameworkViewElementTemplateContext;

class TimeRange extends AbstractFilter
{
protected $request;
protected $timezone;

public function __construct(
    Context $context,
    RequestInterface $request,
    LayerFilterItemFactory $filterItemFactory,
    Layer $layer,
    TimezoneInterface $timezone,
    array $data = []
) {
    $this->request = $request;
    $this->timezone = $timezone;
    parent::__construct($context, $filterItemFactory, $layer, $data);
}

public function apply(RequestInterface $request)
{
    $value = $request->getParam($this->_requestVar);
    if (!$value) {
        return $this;
    }

    $range = $this->getRangeDates($value);
    $collection = $this->getLayer()->getProductCollection();

    if ($range['from']) {
        $collection->addFieldToFilter('first_publication_date', ['gteq' => $range['from']]);
    }
    if ($range['to']) {
        $collection->addFieldToFilter('first_publication_date', ['lteq' => $range['to']]);
    }

    $this->getLayer()->getState()->addFilter($this->_createItem($this->getLabel(), $value));
    return $this;
}

public function getName()
{
    return __('Time Range');
}

public function getItems()
{
    $productCollection = $this->getLayer()->getProductCollection();

    $ranges = [
        '0-3' => __('0-3 months'),
        '3-6' => __('3-6 months'),
        '6-9' => __('6-9 months'),
        '9-12' => __('9-12 months'),
        '12+' => __('12 months and above'),
    ];

    $result = [];
    foreach ($ranges as $key => $label) {
        $range = $this->getRangeDates($key);

        $clone = clone $productCollection;
        if ($range['from'] && $range['to']) {
            $clone->addFieldToFilter('first_publication_date', ['from' => $range['from'], 'to' => $range['to']]);
        } elseif ($range['from']) {
            $clone->addFieldToFilter('first_publication_date', ['from' => $range['from']]);
        } elseif ($range['to']) {
            $clone->addFieldToFilter('first_publication_date', ['to' => $range['to']]);
        }

        $count = $clone->getSize();
        $result[] = $this->_createItem($label, $key)->setCount($count);
    }

    return $result;
}

public function getRangeDates($rangeKey)
{
    $now = $this->timezone->date()->format('Y-m-d H:i:s');
    $today = new DateTime($now);

    $map = [
        '0-3'  => ['from' => (clone $today)->modify('-3 months')->format('Y-m-d H:i:s'), 'to' => $today->format('Y-m-d H:i:s')],
        '3-6'  => ['from' => (clone $today)->modify('-6 months')->format('Y-m-d H:i:s'), 'to' => (clone $today)->modify('-3 months')->format('Y-m-d H:i:s')],
        '6-9'  => ['from' => (clone $today)->modify('-9 months')->format('Y-m-d H:i:s'), 'to' => (clone $today)->modify('-6 months')->format('Y-m-d H:i:s')],
        '9-12' => ['from' => (clone $today)->modify('-12 months')->format('Y-m-d H:i:s'), 'to' => (clone $today)->modify('-9 months')->format('Y-m-d H:i:s')],
        '12+'  => ['from' => null, 'to' => (clone $today)->modify('-12 months')->format('Y-m-d H:i:s')],
    ];

    return $map[$rangeKey] ?? ['from' => null, 'to' => null];
}

protected function _initItems()
{
    $this->_items = $this->getItems();
    return $this;
}

}
`