25. Araxis Merge File Comparison Report

Produced by Araxis Merge on 2023-07-12 04:42:37 +0000. See www.araxis.com for information about Merge. This report uses XHTML and CSS2, and is best viewed with a modern standards-compliant browser. For optimum results when printing this report, use landscape orientation and enable printing of background images and colours in your browser.

25.1 Files compared

#LocationFileLast Modified
12023-07-12 04:42:37 +0000
2Porto v4.0.6/Theme Files/Porto Theme/app/code/Mageplaza/LayeredNavigation/Model/ResourceModel/Fulltext/CollectionSearchResultApplier.php2023-05-05 02:25:46 +0000

25.2 Comparison summary

DescriptionBetween
Files 1 and 2
Text BlocksLines
Unchanged00
Changed00
Inserted1330
Removed00

25.3 Comparison options

WhitespaceConsecutive whitespace is treated as a single space
Character caseDifferences in character case are significant
Line endingsDifferences in line endings (CR and LF characters) are ignored
CR/LF charactersNot shown in the comparison detail
Active line-pairing rules

25.4 Active regular expressions

No regular expressions were active.

25.5 Comparison detail

    1 <?php
    2 /**
    3  * Mageplaza
    4  *
    5  * NOTICE OF LICENSE
    6  *
    7  * This source file is subject to the Mageplaza.com license that is
    8  * available through the world-wide-web at this URL:
    9  * https://www.mageplaza.com/LICENSE.txt
    10  *
    11  * DISCLAIMER
    12  *
    13  * Do not edit or add to this file if you wish to upgrade this extension to newer
    14  * version in the future.
    15  *
    16  * @category    Mageplaza
    17  * @package     Mageplaza_LayeredNavigation
    18  * @copyright   Copyright (c) Mageplaza (https://www.mageplaza.com/)
    19  * @license     https://www.mageplaza.com/LICENSE.txt
    20  */
    21 
    22 namespace Mageplaza\LayeredNavigation\Model\ResourceModel\Fulltext\Collection;
    23 
    24 use Magento\Catalog\Api\Data\ProductInterface;
    25 use Magento\CatalogInventory\Model\Configuration;
    26 use Magento\CatalogInventory\Model\ResourceModel\StockStatusFilterInterface;
    27 use Magento\CatalogInventory\Model\StockStatusApplierInterface;
    28 use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchResultApplierInterface;
    29 use Magento\Framework\Api\Search\SearchResultInterface;
    30 use Magento\Framework\App\Config\ScopeConfigInterface;
    31 use Magento\Framework\App\ObjectManager;
    32 use Magento\Framework\Data\Collection;
    33 use Magento\Framework\DB\Select;
    34 use Magento\Framework\EntityManager\MetadataPool;
    35 use Magento\Framework\Exception\LocalizedException;
    36 use Magento\Store\Model\ScopeInterface;
    37 use Zend_Db_Expr;
    38 use Zend_Db_Select_Exception;
    39 
    40 /**
    41  * Resolve specific attributes for search criteria.
    42  *
    43  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
    44  */
    45 class SearchResultApplier implements SearchResultApplierInterface
    46 {
    47     /**
    48      * @var Collection|\Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection
    49      */
    50     private $collection;
    51 
    52     /**
    53      * @var SearchResultInterface
    54      */
    55     private $searchResult;
    56 
    57     /**
    58      * @var int
    59      */
    60     private $size;
    61 
    62     /**
    63      * @var int
    64      */
    65     private $currentPage;
    66 
    67     /**
    68      * @var ScopeConfigInterface
    69      */
    70     private $scopeConfig;
    71 
    72     /**
    73      * @var MetadataPool
    74      */
    75     private $metadataPool;
    76 
    77     /**
    78      * @var StockStatusFilterInterface
    79      */
    80     private $stockStatusFilter;
    81 
    82     /**
    83      * @var StockStatusApplierInterface
    84      */
    85     private $stockStatusApplier;
    86 
    87     /**
    88      * SearchResultApplier constructor.
    89      *
    90      * @param Collection $collection
    91      * @param SearchResultInterface $searchResult
    92      * @param int $size
    93      * @param int $currentPage
    94      * @param ScopeConfigInterface|null $scopeConfig
    95      * @param MetadataPool|null $metadataPool
    96      * @param StockStatusFilterInterface|null $stockStatusFilter
    97      * @param StockStatusApplierInterface|null $stockStatusApplier
    98      */
    99     public function __construct(
    100         Collection $collection,
    101         SearchResultInterface $searchResult,
    102         int $size,
    103         int $currentPage,
    104         ?ScopeConfigInterface $scopeConfig = null,
    105         ?MetadataPool $metadataPool = null,
    106         ?StockStatusFilterInterface $stockStatusFilter = null,
    107         ?StockStatusApplierInterface $stockStatusApplier = null
    108     ) {
    109         $this->collection         = $collection;
    110         $this->searchResult       = $searchResult;
    111         $this->size               = $size;
    112         $this->currentPage        = $currentPage;
    113         $this->scopeConfig        = $scopeConfig ?? ObjectManager::getInstance()->get(ScopeConfigInterface::class);
    114         $this->metadataPool       = $metadataPool ?? ObjectManager::getInstance()->get(MetadataPool::class);
    115         $this->stockStatusFilter  = $stockStatusFilter
    116             ?? ObjectManager::getInstance()->get(StockStatusFilterInterface::class);
    117         $this->stockStatusApplier = $stockStatusApplier
    118             ?? ObjectManager::getInstance()->get(StockStatusApplierInterface::class);
    119     }
    120 
    121     /**
    122      * @inheritdoc
    123      */
    124     public function apply()
    125     {
    126         if (empty($this->searchResult->getItems())) {
    127             $this->collection->getSelect()->where('NULL');
    128 
    129             return;
    130         }
    131 
    132         //        $ids = $this->getProductIdsBySaleability();
    133         $ids = [];
    134 
    135         if (count($ids) == 0) {
    136             $items = $this->sliceItems($this->searchResult->getItems(), $this->size, $this->currentPage);
    137             foreach ($items as $item) {
    138                 $ids[] = (int) $item->getId();
    139             }
    140         }
    141         $this->collection->getSelect()
    142             ->where('e.entity_id IN (?)', $ids);
    143         try {
    144             $isHasOrder = $this->collection->getSelect()->getPart('order');
    145         } catch (Zend_Db_Select_Exception $e) {
    146             $isHasOrder = false;
    147         }
    148         if (!$isHasOrder) {
    149             $orderList = implode(',', $ids);
    150             $this->collection->getSelect()->reset(Select::ORDER)
    151                 ->order(new Zend_Db_Expr("FIELD(e.entity_id,$orderList)"));
    152         }
    153     }
    154 
    155     /**
    156      * Slice current items
    157      *
    158      * @param array $items
    159      * @param int $size
    160      * @param int $currentPage
    161      *
    162      * @return array
    163      */
    164     private function sliceItems(array $items, int $size, int $currentPage): array
    165     {
    166         if ($size !== 0) {
    167             // Check that current page is in a range of allowed page numbers, based on items count and items per page,
    168             // than calculate offset for slicing items array.
    169             $itemsCount           = count($items);
    170             $maxAllowedPageNumber = ceil($itemsCount / $size);
    171             if ($currentPage < 1) {
    172                 $currentPage = 1;
    173             }
    174             if ($currentPage > $maxAllowedPageNumber) {
    175                 $currentPage = $maxAllowedPageNumber;
    176             }
    177 
    178             $offset = $this->getOffset($currentPage, $size);
    179             $items  = array_slice($items, $offset, $size);
    180         }
    181 
    182         return $items;
    183     }
    184 
    185     /**
    186      * Get offset for given page.
    187      *
    188      * @param int $pageNumber
    189      * @param int $pageSize
    190      *
    191      * @return int
    192      */
    193     private function getOffset(int $pageNumber, int $pageSize): int
    194     {
    195         return ($pageNumber - 1) * $pageSize;
    196     }
    197 
    198     /**
    199      * Fetch filtered product ids sorted by the saleability and other applied sort orders
    200      *
    201      * @return array
    202      */
    203     private function getProductIdsBySaleability(): array
    204     {
    205         $ids = [];
    206 
    207         if ($this->hasShowOutOfStockStatus()) {
    208             return $ids;
    209         }
    210 
    211         if ($this->collection->getFlag('has_stock_status_filter')
    212             || $this->collection->getFlag('has_category_filter')) {
    213             $categoryId     = null;
    214             $searchCriteria = $this->searchResult->getSearchCriteria();
    215             foreach ($searchCriteria->getFilterGroups() as $filterGroup) {
    216                 foreach ($filterGroup->getFilters() as $filter) {
    217                     if ($filter->getField() === 'category_ids') {
    218                         $categoryId = $filter->getValue();
    219                         break 2;
    220                     }
    221                 }
    222             }
    223 
    224             if ($categoryId) {
    225                 $resultSet = $this->categoryProductByCustomSortOrder((int) $categoryId);
    226                 foreach ($resultSet as $item) {
    227                     $ids[] = (int) $item['entity_id'];
    228                 }
    229             }
    230         }
    231 
    232         return $ids;
    233     }
    234 
    235     /**
    236      * Fetch product results by custom sort orders
    237      *
    238      * @param int $categoryId
    239      *
    240      * @return array
    241      * @throws LocalizedException
    242      * @throws Zend_Db_Select_Exception
    243      */
    244     private function categoryProductByCustomSortOrder(int $categoryId): array
    245     {
    246         $storeId        = $this->collection->getStoreId();
    247         $searchCriteria = $this->searchResult->getSearchCriteria();
    248         $sortOrders     = $searchCriteria->getSortOrders() ?? [];
    249         $sortOrders     = array_merge(['is_salable' => Select::SQL_DESC], $sortOrders);
    250 
    251         $connection = $this->collection->getConnection();
    252         $query      = clone $connection->select()
    253             ->reset(Select::ORDER)
    254             ->reset(Select::LIMIT_COUNT)
    255             ->reset(Select::LIMIT_OFFSET)
    256             ->reset(Select::COLUMNS);
    257         $query->from(
    258             ['e' => $this->collection->getTable('catalog_product_entity')],
    259             ['e.entity_id']
    260         );
    261         $this->stockStatusApplier->setSearchResultApplier(true);
    262         $query = $this->stockStatusFilter->execute($query, 'e', 'stockItem');
    263         $query->join(
    264             ['cat_index' => $this->collection->getTable('catalog_category_product_index_store' . $storeId)],
    265             'cat_index.product_id = e.entity_id'
    266             . ' AND cat_index.category_id = ' . $categoryId
    267             . ' AND cat_index.store_id = ' . $storeId,
    268             ['cat_index.position']
    269         );
    270 
    271         $productIds = [];
    272         foreach ($this->searchResult->getItems() as $item) {
    273             $productIds[] = $item->getId();
    274         }
    275 
    276         $query->where('e.entity_id IN(?)', $productIds);
    277 
    278         foreach ($sortOrders as $field => $dir) {
    279             if ($field === 'name') {
    280                 $entityTypeId   = $this->collection->getEntity()->getTypeId();
    281                 $entityMetadata = $this->metadataPool->getMetadata(ProductInterface::class);
    282                 $linkField      = $entityMetadata->getLinkField();
    283                 $query->joinLeft(
    284                     ['product_var' => $this->collection->getTable('catalog_product_entity_varchar')],
    285                     "product_var.{$linkField} = e.{$linkField} AND product_var.attribute_id =
    286                     (SELECT attribute_id FROM eav_attribute WHERE entity_type_id={$entityTypeId}
    287                     AND attribute_code='name')",
    288                     ['product_var.value AS name']
    289                 );
    290             } elseif ($field === 'price') {
    291                 $query->joinLeft(
    292                     ['price_index' => $this->collection->getTable('catalog_product_index_price')],
    293                     'price_index.entity_id = e.entity_id'
    294                     . ' AND price_index.customer_group_id = 0'
    295                     . ' AND price_index.website_id = (Select website_id FROM store WHERE store_id = '
    296                     . $storeId . ')',
    297                     ['price_index.max_price AS price']
    298                 );
    299             }
    300             $columnFilters = [];
    301             $columnsParts  = $query->getPart('columns');
    302             foreach ($columnsParts as $columns) {
    303                 $columnFilters[] = $columns[2] ?? $columns[1];
    304             }
    305             if (in_array($field, $columnFilters, true)) {
    306                 $query->order(new Zend_Db_Expr("{$field} {$dir}"));
    307             }
    308         }
    309 
    310         $query->limit(
    311             $searchCriteria->getPageSize(),
    312             $searchCriteria->getCurrentPage() * $searchCriteria->getPageSize()
    313         );
    314 
    315         return $connection->fetchAssoc($query) ?? [];
    316     }
    317 
    318     /**
    319      * Returns if display out of stock status set or not in catalog inventory
    320      *
    321      * @return bool
    322      */
    323     private function hasShowOutOfStockStatus(): bool
    324     {
    325         return (bool) $this->scopeConfig->getValue(
    326             Configuration::XML_PATH_SHOW_OUT_OF_STOCK,
    327             ScopeInterface::SCOPE_STORE
    328         );
    329     }
    330 }