Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 10 additions & 40 deletions Observer/AddAlgoliaAssetsObserver.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@

use Algolia\AlgoliaSearch\Exceptions\AlgoliaException;
use Algolia\AlgoliaSearch\Helper\ConfigHelper;
use Algolia\AlgoliaSearch\Registry\CurrentCategory;
use Algolia\AlgoliaSearch\Service\AlgoliaCredentialsManager;
use Magento\Catalog\Model\Category;
use Algolia\AlgoliaSearch\Service\RenderingManager;
use Magento\Framework\App\Request\Http;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\View\Layout;
use Magento\Framework\View\Page\Config as PageConfig;
use Magento\Store\Model\StoreManagerInterface;

/**
Expand All @@ -22,13 +20,11 @@ class AddAlgoliaAssetsObserver implements ObserverInterface
{
public function __construct(
protected ConfigHelper $config,
protected CurrentCategory $category,
protected RenderingManager $renderingManager,
protected StoreManagerInterface $storeManager,
protected PageConfig $pageConfig,
protected Http $request,
protected AlgoliaCredentialsManager $algoliaCredentialsManager
)
{}
) {}

/**
* @throws NoSuchEntityException|AlgoliaException
Expand All @@ -39,42 +35,16 @@ public function execute(Observer $observer): void
if ($actionName === 'swagger_index_index') {
return;
}
$storeId = $this->storeManager->getStore()->getId();
if ($this->config->isEnabledFrontEnd($storeId)) {
if ($this->algoliaCredentialsManager->checkCredentials($storeId)) {
if ($this->config->isAutoCompleteEnabled($storeId) || $this->config->isInstantEnabled($storeId)) {
/** @var Layout $layout */
$layout = $observer->getData('layout');
$layout->getUpdate()->addHandle('algolia_search_handle');

$this->loadPreventBackendRenderingHandle($layout, $storeId);
}
}
}
}

private function loadPreventBackendRenderingHandle(Layout $layout, int $storeId): void
{
if (!$this->config->preventBackendRendering($storeId)) {
return;
}

$category = $this->category->get();

if (!$category->getId()) {
return;
}
$storeId = $this->storeManager->getStore()->getId();

if (!$this->config->replaceCategories($storeId)) {
return;
}
if ($this->config->isEnabledFrontEnd($storeId) && $this->algoliaCredentialsManager->checkCredentials($storeId)) {
/** @var Layout $layout */
$layout = $observer->getData('layout');

$displayMode = $this->config->getBackendRenderingDisplayMode($storeId);
if ($displayMode === 'only_products'
&& $category->getData('display_mode') === \Magento\Catalog\Model\Category::DM_PAGE) {
return;
$this->renderingManager->handleFrontendAssets($layout, $storeId);
$this->renderingManager->handleBackendRendering($layout, $actionName, $storeId);
}

$layout->getUpdate()->addHandle('algolia_search_handle_prevent_backend_rendering');
}

}
97 changes: 97 additions & 0 deletions Service/RenderingManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

namespace Algolia\AlgoliaSearch\Service;

use Algolia\AlgoliaSearch\Helper\ConfigHelper;
use Algolia\AlgoliaSearch\Helper\Configuration\AutocompleteHelper;
use Algolia\AlgoliaSearch\Helper\Configuration\InstantSearchHelper;
use Algolia\AlgoliaSearch\Registry\CurrentCategory;
use Magento\Catalog\Model\Category;
use Magento\Framework\View\Layout;
use Magento\Store\Model\StoreManagerInterface;

class RenderingManager
{
public function __construct(
protected ConfigHelper $config,
protected AutocompleteHelper $autocompleteConfigHelper,
protected InstantSearchHelper $instantSearchConfigHelper,
protected CurrentCategory $category,
protected StoreManagerInterface $storeManager
) {}

/**
* @param Layout $layout
* @param int $storeId
* @return void
*/
public function handleFrontendAssets(Layout $layout, int $storeId): void
{
// If an Algolia frontend feature is enabled, add the frontend assets
if (!$this->hasAlgoliaFrontend($storeId)) {
return;
}

$this->addHandle($layout,'algolia_search_handle');
}

/**
* @param Layout $layout
* @param string $actionName
* @param int $storeId
* @return void
*/
public function handleBackendRendering(Layout $layout, string $actionName, int $storeId): void
{
// If the page is not a category or the catalogsearch page or if no Algolia frontend feature is enabled, no need to go further
if (!$this->isSearchPage($actionName) || !$this->hasAlgoliaFrontend($storeId)) {
return;
}

// @todo replace this check with the new backend rendering feature (MAGE-1325)
if (!$this->config->preventBackendRendering($storeId)) {
return;
}

$category = $this->category->get();
// Legacy check regarding category display mode (we don't want to hide the static blocks if there's not product list
if ($category->getId() && $this->instantSearchConfigHelper->shouldReplaceCategories($storeId)) {
$displayMode = $this->config->getBackendRenderingDisplayMode($storeId);

if ($displayMode === 'only_products' && $category->getDisplayMode() === Category::DM_PAGE) {
return;
}
}

$this->addHandle($layout, 'algolia_search_handle_prevent_backend_rendering');
}

/**
* @param Layout $layout
* @param string $handleName
* @return void
*/
protected function addHandle(Layout $layout, string $handleName): void
{
$layout->getUpdate()->addHandle($handleName);
}

/**
* @param int $storeId
* @return bool
*/
protected function hasAlgoliaFrontend(int $storeId): bool
{
return $this->autocompleteConfigHelper->isEnabled($storeId) ||
$this->instantSearchConfigHelper->isEnabled($storeId);
}

/**
* @param string $actionName
* @return bool
*/
protected function isSearchPage(string $actionName): bool
{
return $actionName === 'catalog_category_view' || $actionName === 'catalogsearch_result_index';
}
}
155 changes: 155 additions & 0 deletions Test/Unit/Service/RenderingManagerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<?php

namespace Algolia\AlgoliaSearch\Test\Unit\Service;

use Algolia\AlgoliaSearch\Helper\ConfigHelper;
use Algolia\AlgoliaSearch\Helper\Configuration\AutocompleteHelper;
use Algolia\AlgoliaSearch\Helper\Configuration\InstantSearchHelper;
use Algolia\AlgoliaSearch\Registry\CurrentCategory;
use Algolia\AlgoliaSearch\Service\RenderingManager;
use Magento\Catalog\Model\Category;
use Magento\Framework\View\Layout;
use Magento\Framework\View\Layout\ProcessorInterface;
use Magento\Store\Model\StoreManagerInterface;
use PHPUnit\Framework\TestCase;

class RenderingManagerTest extends TestCase
{
protected ?ConfigHelper $configHelper;
protected ?AutocompleteHelper $autocompleteConfigHelper;
protected ?InstantSearchHelper $instantSearchConfigHelper;
protected ?CurrentCategory $category;
protected ?StoreManagerInterface $storeManager;

protected ?RenderingManager $renderingManager;

public function setUp(): void
{
$this->configHelper = $this->createMock(ConfigHelper::class);
$this->autocompleteConfigHelper = $this->createMock(AutocompleteHelper::class);
$this->instantSearchConfigHelper = $this->createMock(InstantSearchHelper::class);
$this->category = $this->createMock(CurrentCategory::class);
$this->storeManager = $this->createMock(StoreManagerInterface::class);

$this->renderingManager = new RenderingManager(
$this->configHelper,
$this->autocompleteConfigHelper,
$this->instantSearchConfigHelper,
$this->category,
$this->storeManager
);
}

/**
* @dataProvider frontendValuesProvider
*/
public function testFrontendAssets($isAutocompleteEnabled, $isInstantSearchEnabled, $isLayoutUpdated): void
{
$this->autocompleteConfigHelper->method('isEnabled')->willReturn($isAutocompleteEnabled);
$this->instantSearchConfigHelper->method('isEnabled')->willReturn($isInstantSearchEnabled);

$layout = $this->createMock(Layout::class);
$update = $this->createMock(ProcessorInterface::class);
$layout->method('getUpdate')->willReturn($update);

if ($isLayoutUpdated) {
$update->expects($this->once())
->method('addHandle')
->with('algolia_search_handle');
} else {
$update->expects($this->never())
->method('addHandle');
}

$this->renderingManager->handleFrontendAssets($layout, 0);
}

/**
* @dataProvider backendValuesProvider
*/
public function testBackendRendering($actionName, $preventBackendRendering, $isLayoutUpdated): void
{
$this->autocompleteConfigHelper->method('isEnabled')->willReturn(true);
$this->instantSearchConfigHelper->method('isEnabled')->willReturn(true);
$this->configHelper->method('preventBackendRendering')->willReturn($preventBackendRendering);

$layout = $this->createMock(Layout::class);
$update = $this->createMock(ProcessorInterface::class);
$layout->method('getUpdate')->willReturn($update);

if ($isLayoutUpdated) {
$update->expects($this->once())
->method('addHandle')
->with('algolia_search_handle_prevent_backend_rendering');
} else {
$update->expects($this->never())
->method('addHandle');
}

$this->renderingManager->handleBackendRendering($layout, $actionName, 0);
}

/**
* @dataProvider displayValuesProvider
*/
public function testDisplayMode($displayMode, $categoryDisplayMode, $isLayoutUpdated): void
{
$this->autocompleteConfigHelper->method('isEnabled')->willReturn(true);
$this->instantSearchConfigHelper->method('isEnabled')->willReturn(true);
$this->instantSearchConfigHelper->method('shouldReplaceCategories')->willReturn(true);
$this->configHelper->method('preventBackendRendering')->willReturn(true);
$this->configHelper->method('getBackendRenderingDisplayMode')->willReturn($displayMode);

$currentCategory = $this->createMock(Category::class);
$this->category->method('get')->willReturn($currentCategory);
$currentCategory->method('getId')->willReturn(1);
$currentCategory->method('getDisplayMode')->willReturn($categoryDisplayMode);

$layout = $this->createMock(Layout::class);
$update = $this->createMock(ProcessorInterface::class);
$layout->method('getUpdate')->willReturn($update);

if ($isLayoutUpdated) {
$update->expects($this->once())
->method('addHandle')
->with('algolia_search_handle_prevent_backend_rendering');
} else {
$update->expects($this->never())
->method('addHandle');
}

$this->renderingManager->handleBackendRendering($layout, 'catalog_category_view', 0);
}

public static function frontendValuesProvider(): array
{
return [
['isAutocompleteEnabled' => true, 'isInstantSearchEnabled' => true, 'isLayoutUpdated' => true],
['isAutocompleteEnabled' => false, 'isInstantSearchEnabled' => true, 'isLayoutUpdated' => true],
['isAutocompleteEnabled' => true, 'isInstantSearchEnabled' => false, 'isLayoutUpdated' => true],
['isAutocompleteEnabled' => false, 'isInstantSearchEnabled' => false, 'isLayoutUpdated' => false]
];
}

public static function backendValuesProvider(): array
{
return [
['actionName' => 'catalog_category_view','preventBackendRendering' => true, 'isLayoutUpdated' => true],
['actionName' => 'catalogsearch_result_index', 'preventBackendRendering' => true, 'isLayoutUpdated' => true],
['actionName' => 'foo_bar', 'preventBackendRendering' => true, 'isLayoutUpdated' => false],
['actionName' => 'catalog_category_view', 'preventBackendRendering' => false, 'isLayoutUpdated' => false]
];
}

public static function displayValuesProvider(): array
{
return [
['displayMode' => 'all', 'categoryDisplayMode' => 'PAGE', 'isLayoutUpdated' => true],
['displayMode' => 'all', 'categoryDisplayMode' => 'PRODUCTS', 'isLayoutUpdated' => true],
['displayMode' => 'all', 'categoryDisplayMode' => 'PRODUCTS_AND_PAGE', 'isLayoutUpdated' => true],
['displayMode' => 'only_products', 'categoryDisplayMode' => 'PAGE', 'isLayoutUpdated' => false],
['displayMode' => 'only_products', 'categoryDisplayMode' => 'PRODUCTS', 'isLayoutUpdated' => true],
['displayMode' => 'only_products', 'categoryDisplayMode' => 'PRODUCTS_AND_PAGE', 'isLayoutUpdated' => true],
];
}
}