259 lines
7.8 KiB
PHP
Executable File
259 lines
7.8 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* @author Olegnax
|
|
* @package Olegnax_LayeredNavigation
|
|
* @copyright Copyright (c) 2019 Olegnax (http://olegnax.com/). All rights reserved.
|
|
* @license Proprietary License https://olegnax.com/license/
|
|
*/
|
|
|
|
namespace Olegnax\LayeredNavigation\Plugin;
|
|
|
|
use Magento\Catalog\Block\Product\ListProduct;
|
|
use Magento\Framework\App\ObjectManager;
|
|
use Magento\Framework\App\Request\Http;
|
|
use Magento\Framework\Controller\Result\RawFactory;
|
|
use Magento\Framework\DataObject\IdentityInterface;
|
|
use Magento\Framework\Exception\LocalizedException;
|
|
use Magento\Framework\Registry;
|
|
use Magento\Framework\Serialize\Serializer\Json;
|
|
use Magento\Framework\Url\DecoderInterface;
|
|
use Magento\Framework\Url\Helper\Data as UrlHelper;
|
|
use Magento\Framework\View\LayoutInterface;
|
|
use Magento\Framework\View\Result\Page;
|
|
use Magento\PageCache\Model\Cache\Type;
|
|
use Olegnax\LayeredNavigation\Helper\Helper;
|
|
|
|
class Ajax
|
|
{
|
|
const AJAX_ATTR = 'navAjax';
|
|
|
|
const BLOCK_PRODUCTS = 'category.products.list';
|
|
const BLOCK_PRODUCTS_SEARCH = 'search_result_list';
|
|
const BLOCK_TITLE = 'page.main.title';
|
|
const BLOCK_NAVIGATION = 'catalog.leftnav';
|
|
const BLOCK_NAVIGATION_SEARCH = 'catalogsearch.leftnav';
|
|
const BLOCK_BREADCRUMBS = 'breadcrumbs';
|
|
const REGEX_URLS = '@aHR0c(Dov|HM6)[A-Za-z0-9_-]+@u';
|
|
|
|
/**
|
|
* @var Helper
|
|
*/
|
|
protected $helper;
|
|
/**
|
|
* @var RawFactory
|
|
*/
|
|
protected $resultRaw;
|
|
/**
|
|
* @var Http
|
|
*/
|
|
protected $request;
|
|
/**
|
|
* @var Json
|
|
*/
|
|
protected $json;
|
|
/**
|
|
* @var DecoderInterface
|
|
*/
|
|
protected $urlDecoder;
|
|
/**
|
|
* @var UrlHelper
|
|
*/
|
|
private $urlHelper;
|
|
/**
|
|
* @var Registry
|
|
*/
|
|
protected $registry;
|
|
|
|
public function __construct(
|
|
Helper $helper,
|
|
RawFactory $resultRaw,
|
|
Http $request,
|
|
UrlHelper $urlHelper,
|
|
DecoderInterface $urlDecoder,
|
|
Registry $registry,
|
|
Json $json
|
|
) {
|
|
$this->helper = $helper;
|
|
$this->resultRaw = $resultRaw;
|
|
$this->request = $request;
|
|
$this->urlHelper = $urlHelper;
|
|
$this->urlDecoder = $urlDecoder;
|
|
$this->registry = $registry;
|
|
$this->json = $json;
|
|
}
|
|
|
|
/**
|
|
* @param string $html
|
|
* @return string
|
|
*/
|
|
public function removeArgs($html)
|
|
{
|
|
$html = str_replace(['?' . static::AJAX_ATTR . '=1&', '?' . static::AJAX_ATTR . '=1&'], '?', $html);
|
|
$html = str_replace([
|
|
'?' . static::AJAX_ATTR . '=1',
|
|
'&' . static::AJAX_ATTR . '=1',
|
|
'&' . static::AJAX_ATTR . '=1'
|
|
], '', $html);
|
|
|
|
return $html;
|
|
}
|
|
|
|
public function removeEncodedArgsItem($match)
|
|
{
|
|
$code_string = $match[0];
|
|
$url = $this->urlDecoder->decode($code_string);
|
|
if (false !== $url) {
|
|
$newUrl = $this->urlHelper->removeRequestParam($url, static::AJAX_ATTR);
|
|
$newUrl = $this->removeEncodedArgs($newUrl);
|
|
|
|
if ($url != $newUrl) {
|
|
$code_string = $this->urlHelper->getEncodedUrl($newUrl);
|
|
}
|
|
}
|
|
return $code_string;
|
|
}
|
|
|
|
/**
|
|
* @param string $html
|
|
* @return string
|
|
*/
|
|
public function removeEncodedArgs($html)
|
|
{
|
|
$_html = preg_replace_callback(static::REGEX_URLS, [$this, 'removeEncodedArgsItem'], $html);
|
|
if ($_html) {
|
|
$html = $_html;
|
|
}
|
|
|
|
return $html;
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
protected function isAjax()
|
|
{
|
|
return $this->helper->isEnabled() &&
|
|
$this->request->isXmlHttpRequest() &&
|
|
$this->request->isAjax() &&
|
|
$this->request->getParam(static::AJAX_ATTR, '');
|
|
}
|
|
|
|
protected function getAjaxContent(Page $page)
|
|
{
|
|
/** @var LayoutInterface $layout */
|
|
$layout = $page->getLayout();
|
|
$layout->getOutput(); // @todo temporary fix: magenta ignoring the product limit parameter per page, per page with ajax request
|
|
$title = $page->getConfig()->getTitle()->get();
|
|
|
|
$blocks = $this->getLayoutBlock($layout);
|
|
|
|
$productsCount = 0;
|
|
$currentCategory = 0;
|
|
if ($blocks['products']) {
|
|
$productsCount = $this->getProductCount($blocks['products']);
|
|
if ($blocks['products']->getLayer()) {
|
|
$currentCategory = $blocks['products']->getLayer()->getCurrentCategory();
|
|
$currentCategory = $currentCategory ? $currentCategory->getId() : 0;
|
|
}
|
|
}
|
|
|
|
$html = [];
|
|
$cache_tags = [];
|
|
foreach ($blocks as $key => $block) {
|
|
$cache_tags = $this->addIdentities($block, $cache_tags);
|
|
|
|
$html[$key] = $block ? $block->toHtml() : '';
|
|
}
|
|
|
|
$response = compact('productsCount', 'currentCategory', 'title', 'html');
|
|
$response['html']['_before'] = '';
|
|
$response['html']['_after'] = '';
|
|
try {
|
|
$response = $this->prepareForPlugins($response, $blocks);
|
|
} catch (\Exception $exception){
|
|
// @todo do nothing or log
|
|
}
|
|
$response = $this->changeResponse($response, $cache_tags, $page);
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* @param LayoutInterface $layout
|
|
* @return array
|
|
*/
|
|
protected function getLayoutBlock($layout)
|
|
{
|
|
return [
|
|
'products' => $layout->getBlock(self::BLOCK_PRODUCTS) ?: $layout->getBlock(self::BLOCK_PRODUCTS_SEARCH),
|
|
'leftnav' => $layout->getBlock(self::BLOCK_NAVIGATION) ?: $layout->getBlock(self::BLOCK_NAVIGATION_SEARCH),
|
|
'title' => $layout->getBlock(self::BLOCK_TITLE),
|
|
'breadcrumbs' => $layout->getBlock(self::BLOCK_BREADCRUMBS),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param ListProduct $block
|
|
* @return int
|
|
*/
|
|
protected function getProductCount($block)
|
|
{
|
|
return (int)$block->getLoadedProductCollection()->getSize();
|
|
}
|
|
|
|
protected function addIdentities($block, array $data = [])
|
|
{
|
|
if ($block instanceof IdentityInterface) {
|
|
$data = array_merge($data, $block->getIdentities());
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
protected function changeResponse($response, $cache_tags)
|
|
{
|
|
$cache_tags[] = Type::CACHE_TAG;
|
|
$cache_tags = array_unique($cache_tags);
|
|
$cache_tags = implode(',', $cache_tags);
|
|
|
|
$response['cache_tags'] = $cache_tags;
|
|
$response['html'] = array_map([$this, 'removeArgs'], $response['html']);
|
|
$response['html'] = array_map([$this, 'removeEncodedArgs'], $response['html']);
|
|
|
|
return $response;
|
|
}
|
|
|
|
protected function json(array $data)
|
|
{
|
|
$response = $this->resultRaw->create();
|
|
$response->setHeader('Content-type', 'application/json');
|
|
if (array_key_exists('cache_tags', $data)) {
|
|
if (!empty($data['cache_tags'])) {
|
|
$response->setHeader('X-Magento-Tags', $data['cache_tags']);
|
|
}
|
|
unset($data['cache_tags']);
|
|
}
|
|
$data = $this->json->serialize($data);
|
|
$response->setContents($data);
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* @param array $response
|
|
* @param array $blocks
|
|
* @return array
|
|
* @throws LocalizedException
|
|
*/
|
|
protected function prepareForPlugins(array $response, array $blocks)
|
|
{
|
|
if (array_key_exists('products', $blocks) && class_exists('\Amasty\Label\Plugin\Catalog\Product\ListProduct')) {
|
|
/** @var \Amasty\Label\Plugin\Catalog\Product\ListProduct $amastyLabelListProduct */
|
|
$amastyLabelListProduct = ObjectManager::getInstance()->get('\Amasty\Label\Plugin\Catalog\Product\ListProduct');
|
|
$this->registry->register('amlabel_category_observer', false);
|
|
$blocks['products']->setIsAmLabelObserved(false);
|
|
$response['html']['_after'] .= $amastyLabelListProduct->afterToHtml($blocks['products'], '');
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
}
|