From fc882c0fec7524ae41a5ce113030630ce979b6eb Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 3 Oct 2023 22:51:21 -0400 Subject: [PATCH 01/47] Set arbitrary limit to override default for hierarchicalMenu to prevent premature truncation of available categories while determining root path --- view/frontend/web/instantsearch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/frontend/web/instantsearch.js b/view/frontend/web/instantsearch.js index 8eaeb72a2..ad1c95d96 100644 --- a/view/frontend/web/instantsearch.js +++ b/view/frontend/web/instantsearch.js @@ -475,7 +475,7 @@ define( separator : algoliaConfig.instant.categorySeparator, templates : templates, showParentLevel : true, - limit : algoliaConfig.maxValuesPerFacet, + limit : 999, // arbitrarily high number - as premature truncate of results can prevent preselection for large category lists sortBy : ['name:asc'], transformItems(items) { return (algoliaConfig.isCategoryPage) From dd89eb8e0940518268e89fa34604dc9c4944fd8c Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Fri, 13 Oct 2023 17:30:11 -0400 Subject: [PATCH 02/47] INTEG-707 Simplify application of root category --- view/frontend/web/instantsearch.js | 31 ++++++++---------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/view/frontend/web/instantsearch.js b/view/frontend/web/instantsearch.js index ad1c95d96..5df5f3a06 100644 --- a/view/frontend/web/instantsearch.js +++ b/view/frontend/web/instantsearch.js @@ -446,40 +446,25 @@ define( * Custom widgets can be added to this object like [attribute]: function(facet, templates) * Function must return an array [: string, : object] **/ - var customAttributeFacet = { + const customAttributeFacet = { categories: function (facet, templates) { - var hierarchical_levels = []; - for (var l = 0; l < 10; l++) { + const hierarchical_levels = []; + for (let l = 0; l < 10; l++) { hierarchical_levels.push('categories.level' + l.toString()); } - - //return array of items starting from root based on category - const findRoot = (items) => { - const root = items.find(element => algoliaConfig.request.path.startsWith(element.value)); - - if (!root) { - return items; - } - if (!root.data) { - return []; - } - - return findRoot(root.data); - - }; - - var hierarchicalMenuParams = { + const hierarchicalMenuParams = { container : facet.wrapper.appendChild(createISWidgetContainer(facet.attribute)), attributes : hierarchical_levels, separator : algoliaConfig.instant.categorySeparator, templates : templates, showParentLevel : true, - limit : 999, // arbitrarily high number - as premature truncate of results can prevent preselection for large category lists + limit : algoliaConfig.maxValuesPerFacet, + rootPath : algoliaConfig.request.path, sortBy : ['name:asc'], transformItems(items) { return (algoliaConfig.isCategoryPage) - ? findRoot(items).map( + ? items.map( item => { return { ...item, @@ -726,4 +711,4 @@ define( return options; } } -); \ No newline at end of file +); From 3476bdeb5fb9c50f4383b214b2c37a6a525b0eaf Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Mon, 16 Oct 2023 18:55:43 -0400 Subject: [PATCH 03/47] MAGE-773 From 3ade12fd581cf0cb2a8441ffe09c68e5ce8d2462 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Mon, 16 Oct 2023 19:02:38 -0400 Subject: [PATCH 04/47] MAGE-773 Remove hard coded separator --- view/frontend/web/internals/common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/frontend/web/internals/common.js b/view/frontend/web/internals/common.js index 93c0a13e6..da5138844 100755 --- a/view/frontend/web/internals/common.js +++ b/view/frontend/web/internals/common.js @@ -405,7 +405,7 @@ define(['jquery', 'algoliaBundle'], function ($, algoliaBundle) { if (algoliaConfig.isLandingPage && typeof uiStateProductIndex['hierarchicalMenu']['categories.level0'] === 'undefined' && 'categories.level0' in landingPageConfig) { - uiStateProductIndex['hierarchicalMenu']['categories.level0'] = landingPageConfig['categories.level0'].split(' /// '); + uiStateProductIndex['hierarchicalMenu']['categories.level0'] = landingPageConfig['categories.level0'].split(algoliaConfig.instant.categorySeparator); } } if (currentFacet.attribute == 'categories' && algoliaConfig.isCategoryPage) { From ec758f9199efc494d5b7870838a468f2d2814e46 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 17 Oct 2023 17:27:19 -0400 Subject: [PATCH 05/47] MAGE-725 Add new db schema for category change tracking --- etc/db_schema.xml | 21 +++++++++++++++++++++ etc/db_schema_whitelist.json | 20 ++++++++++++++++++++ etc/module.xml | 2 +- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/etc/db_schema.xml b/etc/db_schema.xml index b1a64de7d..3173f213f 100644 --- a/etc/db_schema.xml +++ b/etc/db_schema.xml @@ -92,6 +92,27 @@
+ + + + + + + + + + + + + + + + + + + +
+ diff --git a/etc/db_schema_whitelist.json b/etc/db_schema_whitelist.json index 56431ba85..43838ad93 100644 --- a/etc/db_schema_whitelist.json +++ b/etc/db_schema_whitelist.json @@ -98,5 +98,25 @@ "column": { "algoliasearch_query_param": true } + }, + "algoliasearch_category_versions": { + "column": { + "version_id": true, + "entity_id": true, + "store_id": true, + "old_value": true, + "new_value": true, + "created_at": true, + "updated_at": true, + "indexed_at": true, + "resolved_at": true + }, + "index": { + "ALGOLIASEARCH_CATEGORY_VERSIONS_CREATED_AT": true, + "ALGOLIASEARCH_CATEGORY_VERSIONS_UPDATED_AT": true + }, + "constraint": { + "PRIMARY": true + } } } \ No newline at end of file diff --git a/etc/module.xml b/etc/module.xml index 7e8028918..4cf5b46e7 100755 --- a/etc/module.xml +++ b/etc/module.xml @@ -1,6 +1,6 @@ - + From 10a37813bf37f162e81444ef1857a9aa96e0deb9 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 17 Oct 2023 17:39:02 -0400 Subject: [PATCH 06/47] MAGE-725 Fix data types --- etc/db_schema.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/etc/db_schema.xml b/etc/db_schema.xml index 3173f213f..0ec0e1912 100644 --- a/etc/db_schema.xml +++ b/etc/db_schema.xml @@ -96,8 +96,8 @@ - - + + From 2ee3793b27770528449e17a130a8d29c682cda7e Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 17 Oct 2023 18:58:28 -0400 Subject: [PATCH 07/47] MAGE-725 Add foreign key relationships --- etc/db_schema.xml | 7 ++++++- etc/db_schema_whitelist.json | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/etc/db_schema.xml b/etc/db_schema.xml index 0ec0e1912..b0594f51b 100644 --- a/etc/db_schema.xml +++ b/etc/db_schema.xml @@ -95,7 +95,7 @@ - + @@ -111,6 +111,11 @@ + +
diff --git a/etc/db_schema_whitelist.json b/etc/db_schema_whitelist.json index 43838ad93..70aa212dd 100644 --- a/etc/db_schema_whitelist.json +++ b/etc/db_schema_whitelist.json @@ -116,7 +116,9 @@ "ALGOLIASEARCH_CATEGORY_VERSIONS_UPDATED_AT": true }, "constraint": { - "PRIMARY": true + "PRIMARY": true, + "ALGOLIASRCH_CTGR_VERSIONS_ENTT_ID_CAT_CTGR_ENTT_ENTT_ID": true, + "ALGOLIASEARCH_CATEGORY_VERSIONS_STORE_ID_STORE_STORE_ID": true } } } \ No newline at end of file From fd5d298abdcb4d0baf3e61b6427678a6dcba5cb2 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Wed, 18 Oct 2023 20:32:38 -0400 Subject: [PATCH 08/47] MAGE-725 Add repository to block --- Block/Algolia.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Block/Algolia.php b/Block/Algolia.php index c87e58eef..abbd63538 100755 --- a/Block/Algolia.php +++ b/Block/Algolia.php @@ -25,6 +25,7 @@ use Magento\Framework\View\Element\Template; use Magento\Sales\Model\Order; use Magento\Search\Helper\Data as CatalogSearchHelper; +use Magento\Catalog\Api\CategoryRepositoryInterface; class Algolia extends Template implements CollectionDataSourceInterface { @@ -97,6 +98,11 @@ class Algolia extends Template implements CollectionDataSourceInterface */ protected $date; + /** + * @var CategoryRepositoryInterface + */ + protected CategoryRepositoryInterface $categoryRepository; + protected $priceKey; /** @@ -119,6 +125,7 @@ class Algolia extends Template implements CollectionDataSourceInterface * @param CheckoutSession $checkoutSession * @param DateTime $date * @param array $data + * @param CategoryRepositoryInterface $categoryRepository */ public function __construct( Template\Context $context, @@ -139,6 +146,7 @@ public function __construct( PersonalizationHelper $personalizationHelper, CheckoutSession $checkoutSession, DateTime $date, + CategoryRepositoryInterface $categoryRepository, array $data = [] ) { $this->config = $config; @@ -157,6 +165,7 @@ public function __construct( $this->landingPageHelper = $landingPageHelper; $this->personalizationHelper = $personalizationHelper; $this->checkoutSession = $checkoutSession; + $this->categoryRepository = $categoryRepository; $this->date = $date; parent::__construct($context, $data); From 4562614b9fed115e4e5dcd667f0566c7319fb533 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Wed, 18 Oct 2023 20:40:18 -0400 Subject: [PATCH 09/47] MAGE-725 Tweak database schema --- etc/db_schema.xml | 10 +++++----- etc/db_schema_whitelist.json | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/etc/db_schema.xml b/etc/db_schema.xml index b0594f51b..f140d0503 100644 --- a/etc/db_schema.xml +++ b/etc/db_schema.xml @@ -92,7 +92,7 @@
- +
@@ -105,16 +105,16 @@ - + - + - -
diff --git a/etc/db_schema_whitelist.json b/etc/db_schema_whitelist.json index 70aa212dd..4c89cac9f 100644 --- a/etc/db_schema_whitelist.json +++ b/etc/db_schema_whitelist.json @@ -99,7 +99,7 @@ "algoliasearch_query_param": true } }, - "algoliasearch_category_versions": { + "algoliasearch_category_version": { "column": { "version_id": true, "entity_id": true, @@ -112,13 +112,13 @@ "resolved_at": true }, "index": { - "ALGOLIASEARCH_CATEGORY_VERSIONS_CREATED_AT": true, - "ALGOLIASEARCH_CATEGORY_VERSIONS_UPDATED_AT": true + "ALGOLIASEARCH_CATEGORY_VERSION_CREATED_AT": true, + "ALGOLIASEARCH_CATEGORY_VERSION_UPDATED_AT": true }, "constraint": { "PRIMARY": true, - "ALGOLIASRCH_CTGR_VERSIONS_ENTT_ID_CAT_CTGR_ENTT_ENTT_ID": true, - "ALGOLIASEARCH_CATEGORY_VERSIONS_STORE_ID_STORE_STORE_ID": true + "ALGOLIASRCH_CTGR_VERSION_ENTT_ID_CAT_CTGR_ENTT_ENTT_ID": true, + "ALGOLIASEARCH_CATEGORY_VERSION_STORE_ID_STORE_STORE_ID": true } } } \ No newline at end of file From e60f0c2d9d57b6146c22778979dacda39aa7de3e Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Wed, 18 Oct 2023 20:41:09 -0400 Subject: [PATCH 10/47] MAGE-725 Add interfaces --- Api/CategoryVersionRepositoryInterface.php | 27 ++++++++++++++++++++++ Api/Data/CategoryVersionInterface.php | 10 ++++++++ 2 files changed, 37 insertions(+) create mode 100644 Api/CategoryVersionRepositoryInterface.php create mode 100644 Api/Data/CategoryVersionInterface.php diff --git a/Api/CategoryVersionRepositoryInterface.php b/Api/CategoryVersionRepositoryInterface.php new file mode 100644 index 000000000..cbc3ff75f --- /dev/null +++ b/Api/CategoryVersionRepositoryInterface.php @@ -0,0 +1,27 @@ + Date: Wed, 18 Oct 2023 20:42:22 -0400 Subject: [PATCH 11/47] MAGE-725 Add concrete model classes for category versions --- Model/CategoryVersion.php | 27 +++++++++++++++++++ Model/ResourceModel/CategoryVersion.php | 15 +++++++++++ .../CategoryVersion/Collection.php | 18 +++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 Model/CategoryVersion.php create mode 100644 Model/ResourceModel/CategoryVersion.php create mode 100644 Model/ResourceModel/CategoryVersion/Collection.php diff --git a/Model/CategoryVersion.php b/Model/CategoryVersion.php new file mode 100644 index 000000000..6b5953200 --- /dev/null +++ b/Model/CategoryVersion.php @@ -0,0 +1,27 @@ +_init( ResourceModel\CategoryVersion::class); + } + + /** + * @inheritDoc + */ + public function getIdentities(): array + { + return [self::CACHE_TAG . '_' . $this->getId()]; + } +} diff --git a/Model/ResourceModel/CategoryVersion.php b/Model/ResourceModel/CategoryVersion.php new file mode 100644 index 000000000..791e1c732 --- /dev/null +++ b/Model/ResourceModel/CategoryVersion.php @@ -0,0 +1,15 @@ +_init(self::TABLE_NAME, self::ID); + } +} diff --git a/Model/ResourceModel/CategoryVersion/Collection.php b/Model/ResourceModel/CategoryVersion/Collection.php new file mode 100644 index 000000000..4481f32f2 --- /dev/null +++ b/Model/ResourceModel/CategoryVersion/Collection.php @@ -0,0 +1,18 @@ +_init(\Algolia\AlgoliaSearch\Model\CategoryVersion::class, \Algolia\AlgoliaSearch\Model\ResourceModel\CategoryVersion::class); + } + +} From bcbeb81df3732cfaebd9c7aef13c6581fcdaaac6 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Wed, 18 Oct 2023 20:44:45 -0400 Subject: [PATCH 12/47] MAGE-725 Add category version repository base implementation --- .../CategoryVersionRepository.php | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 Model/CategoryVersion/CategoryVersionRepository.php diff --git a/Model/CategoryVersion/CategoryVersionRepository.php b/Model/CategoryVersion/CategoryVersionRepository.php new file mode 100644 index 000000000..4adc5f6b3 --- /dev/null +++ b/Model/CategoryVersion/CategoryVersionRepository.php @@ -0,0 +1,82 @@ +versionFactory = $versionFactory; + $this->versionResource = $versionResource; + } + + /** + * @inheritDoc + */ + public function getById(int $id): CategoryVersionInterface + { + if (!isset($this->versions[$id])) { + $version = $this->versionFactory->create(); + $this->versionResource->load($version, $id); + if (!$version->getId()) { + throw new NoSuchEntityException(__("No category version with id $id exists.")); + } + $this->versions[$version->getId()] = $version; + } + return $this->versions[$id]; + } + + /** + * @inheritDoc + */ + public function getNew() : CategoryVersionInterface { + return $this->versionFactory->create(); + } + + /** + * @inheritDoc + */ + public function save(CategoryVersionInterface $version): CategoryVersionInterface + { + $this->versionResource->save($version); + return $version; + } + + /** + * @inheritDoc + */ + public function delete(CategoryVersionInterface $version) : void + { + $this->versionResource->delete($version); + } + + /** + * @inheritDoc + */ + public function deleteById($id) : void + { + $version = $this->getById($id); + unset($this->versions[$id]); + $this->delete($version); + } + + +} From afdd5048fc7495126fe9a867f3d29ca43352613a Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Wed, 18 Oct 2023 20:56:39 -0400 Subject: [PATCH 13/47] MAGE-725 Stub out attribute interface --- .../CategoryVersionAttributeInterface.php | 27 +++++++++++++++ .../CategoryVersionAttribute.php | 33 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 Api/Data/CategoryVersionAttributeInterface.php create mode 100644 Model/CategoryVersion/CategoryVersionAttribute.php diff --git a/Api/Data/CategoryVersionAttributeInterface.php b/Api/Data/CategoryVersionAttributeInterface.php new file mode 100644 index 000000000..403ac7ada --- /dev/null +++ b/Api/Data/CategoryVersionAttributeInterface.php @@ -0,0 +1,27 @@ + Date: Wed, 18 Oct 2023 21:13:07 -0400 Subject: [PATCH 14/47] MAGE-725 Fix typo in interface return type --- Api/Data/CategoryVersionAttributeInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Api/Data/CategoryVersionAttributeInterface.php b/Api/Data/CategoryVersionAttributeInterface.php index 403ac7ada..8e1e57ddc 100644 --- a/Api/Data/CategoryVersionAttributeInterface.php +++ b/Api/Data/CategoryVersionAttributeInterface.php @@ -10,7 +10,7 @@ interface CategoryVersionAttributeInterface * Does this category have versions? * @return bool */ - public function hasVersions() : boolean; + public function hasVersions() : bool; /** * Get all versions of this category From a657bfbdcb33400bd754deb08c9efc642cfa6da0 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Wed, 18 Oct 2023 21:15:06 -0400 Subject: [PATCH 15/47] MAGE-725 Define preferences for category version interfaces --- etc/di.xml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/etc/di.xml b/etc/di.xml index 13ef1b1b3..4604e64af 100755 --- a/etc/di.xml +++ b/etc/di.xml @@ -13,7 +13,7 @@ - + @@ -33,6 +33,10 @@ + + + + @@ -140,4 +144,4 @@ Algolia\AlgoliaSearch\Model\ResourceModel\QueueArchive\Collection -
\ No newline at end of file + From 556458b5b067bcae8f9396b060e7c4e92f2e7946 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Wed, 18 Oct 2023 21:31:56 -0400 Subject: [PATCH 16/47] MAGE-725 Add category version attribute preference --- Model/CategoryVersion/CategoryVersionAttribute.php | 2 +- etc/di.xml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Model/CategoryVersion/CategoryVersionAttribute.php b/Model/CategoryVersion/CategoryVersionAttribute.php index 531205f0f..9289e397c 100644 --- a/Model/CategoryVersion/CategoryVersionAttribute.php +++ b/Model/CategoryVersion/CategoryVersionAttribute.php @@ -10,7 +10,7 @@ class CategoryVersionAttribute implements \Algolia\AlgoliaSearch\Api\Data\Catego /** * @inheritDoc */ - public function hasVersions(): boolean + public function hasVersions(): bool { // TODO: Implement hasVersions() method. } diff --git a/etc/di.xml b/etc/di.xml index 4604e64af..8cb03023f 100755 --- a/etc/di.xml +++ b/etc/di.xml @@ -13,7 +13,7 @@ - + @@ -36,6 +36,7 @@ + From f2d4ae5bd376c3ec0a145c5afd5e315613a7f527 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Wed, 18 Oct 2023 21:32:37 -0400 Subject: [PATCH 17/47] MAGE-725 Stub out extension attribute and plugin for retrieval --- Plugin/CategoryVersionPlugin.php | 57 ++++++++++++++++++++++++++++++++ etc/extension_attributes.xml | 7 ++++ etc/frontend/di.xml | 4 +++ 3 files changed, 68 insertions(+) create mode 100644 Plugin/CategoryVersionPlugin.php create mode 100644 etc/extension_attributes.xml diff --git a/Plugin/CategoryVersionPlugin.php b/Plugin/CategoryVersionPlugin.php new file mode 100644 index 000000000..930fa2053 --- /dev/null +++ b/Plugin/CategoryVersionPlugin.php @@ -0,0 +1,57 @@ +versionRepository = $versionRepository; + $this->extensionFactory = $extensionFactory; + $this->versionAttributeFactory = $versionAttributeFactory; + } + + /** + * @param CategoryRepositoryInterface $categoryRepository + * @param CategoryInterface $category + * @param int $categoryId + * @param int|null $storeId + * @return CategoryInterface + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + public function afterGet(CategoryRepositoryInterface $categoryRepository, CategoryInterface $category, int $categoryId, int $storeId = null): CategoryInterface { + $extensionAttributes = $category->getExtensionAttributes() ?? $this->extensionFactory->create(); + if (!$this->versionAttribute) { + $this->versionAttribute = $this->versionAttributeFactory->create(); + } + $extensionAttributes->setAlgoliaCategoryVersions($this->versionAttribute); + $category->setExtensionAttributes($extensionAttributes); + return $category; + } + + // Unsupported in admin by core + public function afterSave(CategoryRepositoryInterface $categoryRepository, CategoryInterface $result, CategoryInterface $category): CategoryInterface { + return $result; + } +} diff --git a/etc/extension_attributes.xml b/etc/extension_attributes.xml new file mode 100644 index 000000000..8296e7d95 --- /dev/null +++ b/etc/extension_attributes.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/etc/frontend/di.xml b/etc/frontend/di.xml index d14ad0439..26a3b65db 100644 --- a/etc/frontend/di.xml +++ b/etc/frontend/di.xml @@ -20,4 +20,8 @@ + + + + From ebe17777e402b791826c366ef59ce2af932753f5 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Thu, 19 Oct 2023 08:35:48 -0400 Subject: [PATCH 18/47] MAGE-725 Add feature flag for category version tracking --- Block/Configuration.php | 10 ++++++++++ Helper/ConfigHelper.php | 10 ++++++++++ Plugin/CategoryVersionPlugin.php | 10 +++++++++- etc/adminhtml/system.xml | 16 ++++++++++++++++ etc/config.xml | 1 + 5 files changed, 46 insertions(+), 1 deletion(-) diff --git a/Block/Configuration.php b/Block/Configuration.php index 1d770cfe3..e2442b63a 100755 --- a/Block/Configuration.php +++ b/Block/Configuration.php @@ -122,7 +122,17 @@ public function getConfiguration() if ($config->isInstantEnabled() && $config->replaceCategories() && $request->getControllerName() === 'category') { + + // BEGIN MOD - RETRIEVE ALL RELEVANT CATEGORY DATA $category = $this->getCurrentCategory(); +// $attr = $category->getExtensionAttributes(); // doesn't work - concrete class + if ($config->isCategoryVersionTrackingEnabled()) { + $categoryId = (int) $this->getRequest()->getParam('id', false); + $category = $this->categoryRepository->get($categoryId); + $attr = $category->getExtensionAttributes(); + $versionsAttr = $attr->getAlgoliaCategoryVersions(); + } + // END MOD if ($category && $category->getDisplayMode() !== 'PAGE') { $category->getUrlInstance()->setStore($this->getStoreId()); diff --git a/Helper/ConfigHelper.php b/Helper/ConfigHelper.php index af2b3312a..d1c2f0023 100755 --- a/Helper/ConfigHelper.php +++ b/Helper/ConfigHelper.php @@ -55,6 +55,7 @@ class ConfigHelper public const USE_ADAPTIVE_IMAGE = 'algoliasearch_products/products/use_adaptive_image'; public const ENABLE_VISUAL_MERCHANDISING = 'algoliasearch_products/products/enable_visual_merchandising'; public const CATEGORY_PAGE_ID_ATTRIBUTE_NAME = 'algoliasearch_products/products/category_page_id_attribute_name'; + public const ENABLE_CATEGORY_VERSIONS = 'algoliasearch_products/products/enable_category_versions'; public const CATEGORY_ATTRIBUTES = 'algoliasearch_categories/categories/category_additional_attributes'; public const CATEGORY_CUSTOM_RANKING = 'algoliasearch_categories/categories/custom_ranking_category_attributes'; @@ -910,6 +911,15 @@ public function getCategoryPageIdAttributeName($storeId = null): string return (string) $this->configInterface->getValue(self::CATEGORY_PAGE_ID_ATTRIBUTE_NAME, ScopeInterface::SCOPE_STORE, $storeId); } + /** + * @param $storeId + * @return bool + */ + public function isCategoryVersionTrackingEnabled($storeId = null): bool + { + return $this->configInterface->isSetFlag(self::ENABLE_CATEGORY_VERSIONS, ScopeInterface::SCOPE_STORE, $storeId); + } + /** * @param $storeId * @return mixed diff --git a/Plugin/CategoryVersionPlugin.php b/Plugin/CategoryVersionPlugin.php index 930fa2053..9c53c1f65 100644 --- a/Plugin/CategoryVersionPlugin.php +++ b/Plugin/CategoryVersionPlugin.php @@ -2,6 +2,7 @@ namespace Algolia\AlgoliaSearch\Plugin; +use Algolia\AlgoliaSearch\Helper\ConfigHelper; use Magento\Catalog\Api\CategoryRepositoryInterface; use Magento\Catalog\Api\Data\CategoryInterface; use Magento\Catalog\Api\Data\CategoryExtensionFactory; @@ -22,14 +23,19 @@ class CategoryVersionPlugin { /** @var CategoryVersionAttributeInterface */ protected $versionAttribute; + /** @var ConfigHelper */ + protected $config; + public function __construct( CategoryVersionRepositoryInterface $versionRepository, CategoryExtensionFactory $extensionFactory, - CategoryVersionAttributeInterfaceFactory $versionAttributeFactory + CategoryVersionAttributeInterfaceFactory $versionAttributeFactory, + ConfigHelper $config ) { $this->versionRepository = $versionRepository; $this->extensionFactory = $extensionFactory; $this->versionAttributeFactory = $versionAttributeFactory; + $this->config = $config; } /** @@ -41,6 +47,8 @@ public function __construct( * @throws \Magento\Framework\Exception\NoSuchEntityException */ public function afterGet(CategoryRepositoryInterface $categoryRepository, CategoryInterface $category, int $categoryId, int $storeId = null): CategoryInterface { + if (!$this->config->isCategoryVersionTrackingEnabled()) return $category; + $extensionAttributes = $category->getExtensionAttributes() ?? $this->extensionFactory->create(); if (!$this->versionAttribute) { $this->versionAttribute = $this->versionAttributeFactory->create(); diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index 6d8720563..8f696c0b3 100755 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -534,6 +534,22 @@ 1 + + + Magento\Config\Model\Config\Source\Yesno + +
+ Enable this setting to allow the Algolia extension to track the changes you make in Magento so that product records + can still be retrieved based on previous category identifiers. + ]]> +
+ + 1 + +
diff --git a/etc/config.xml b/etc/config.xml index bb3a1ffd3..a2d8446b6 100644 --- a/etc/config.xml +++ b/etc/config.xml @@ -37,6 +37,7 @@ 0 categoryPageId + 0 From 5262407001e5b1c5ccd2682bbdf6fd667ff2b2ef Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Sun, 29 Oct 2023 20:29:20 -0400 Subject: [PATCH 19/47] MAGE-725 Simplify change check logic --- Model/Indexer/CategoryObserver.php | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/Model/Indexer/CategoryObserver.php b/Model/Indexer/CategoryObserver.php index 8b969aa0b..75b29ea02 100755 --- a/Model/Indexer/CategoryObserver.php +++ b/Model/Indexer/CategoryObserver.php @@ -4,11 +4,13 @@ use Algolia\AlgoliaSearch\Helper\ConfigHelper; use Algolia\AlgoliaSearch\Model\Indexer\Category as CategoryIndexer; +use Magento\Catalog\Model\AbstractModel; use Magento\Catalog\Model\Category as CategoryModel; use Magento\Catalog\Model\ResourceModel\Category as CategoryResourceModel; use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection; use Magento\Framework\App\ResourceConnection; use Magento\Framework\Indexer\IndexerRegistry; +use Algolia\AlgoliaSearch\Helper\Logger; class CategoryObserver { @@ -24,6 +26,9 @@ class CategoryObserver /** @var ResourceConnection */ protected $resource; + protected $logger; + + /** * CategoryObserver constructor. * @@ -34,12 +39,29 @@ class CategoryObserver public function __construct( IndexerRegistry $indexerRegistry, ConfigHelper $configHelper, - ResourceConnection $resource + ResourceConnection $resource, + Logger $logger ) { $this->indexerRegistry = $indexerRegistry; $this->indexer = $indexerRegistry->get('algolia_categories'); $this->configHelper = $configHelper; $this->resource = $resource; + $this->logger = $logger; + } + + /** + * @param AbstractModel $model + * @param array $fields + * @return bool + */ + protected function isDataChanged(AbstractModel $model, array $fields): bool + { + foreach ($fields as $field) { + if ($model->getOrigData($field) !== $model->getData($field)) { + return true; + } + } + return false; } /** @@ -57,14 +79,12 @@ public function afterSave( $categoryResource->addCommitCallback(function () use ($category) { $collectionIds = []; // To reduce the indexing operation for products, only update if these values have changed - if ($category->getOrigData('name') !== $category->getData('name') - || $category->getOrigData('include_in_menu') !== $category->getData('include_in_menu') - || $category->getOrigData('is_active') !== $category->getData('is_active') - || $category->getOrigData('path') !== $category->getData('path')) { + if ($this->isDataChanged($category, ['name', 'path', 'include_in_menu', 'is_active'])) { /** @var ProductCollection $productCollection */ $productCollection = $category->getProductCollection(); $collectionIds = (array) $productCollection->getColumnValues('entity_id'); } + $changedProductIds = ($category->getChangedProductIds() !== null ? (array) $category->getChangedProductIds() : []); if (!$this->indexer->isScheduled()) { From 5028da5dfc785ce4b8da25cd0d2d17709f6714ee Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Mon, 30 Oct 2023 17:53:34 -0400 Subject: [PATCH 20/47] MAGE-725 Stub category version logger --- Api/CategoryVersionLoggerInterface.php | 15 ++++ .../CategoryVersion/CategoryVersionLogger.php | 84 +++++++++++++++++++ etc/adminhtml/di.xml | 1 + 3 files changed, 100 insertions(+) create mode 100644 Api/CategoryVersionLoggerInterface.php create mode 100644 Model/CategoryVersion/CategoryVersionLogger.php diff --git a/Api/CategoryVersionLoggerInterface.php b/Api/CategoryVersionLoggerInterface.php new file mode 100644 index 000000000..b26fe5760 --- /dev/null +++ b/Api/CategoryVersionLoggerInterface.php @@ -0,0 +1,15 @@ +config = $config; + $this->categoryRepository = $categoryRepository; + } + + /** + * @inheritDoc + */ + public function logCategoryChange(Category $category, int $storedId = 0): void + { + if (!$this->config->isCategoryVersionTrackingEnabled($storedId)) return; + // Build full path from category + $path = $this->getCategoryPath($category, $storedId); + ObjectManager::getInstance()->get(LoggerInterface::class)->info("---> Path: $path"); + // Build stores array if !$storeId + // Iterate through stores array + // Dedupe existing pending changes for this storeId + // Insert if not found + + } + + /** + * @param Category $category + * @param $storeId + * @return string + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + protected function getCategoryPath(Category $category, $storeId): string + { + + $path = $category->getName(); + foreach (array_slice(array_reverse($category->getPathIds()), 1) as $treeCategoryId) { + $level = $this->categoryRepository->get($treeCategoryId, $storeId); + $path = $level->getName() . $this->config->getCategorySeparator() . $path; + if ((int) $level->getLevel() === self::MIN_CATEGORY_LEVEL) break; + } + return $path; + } + + /** + * @param int $categoryId + * @param int $storeId + * @return CategoryInterface + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + protected function getCategory(int $categoryId, int $storeId): CategoryInterface + { + $key = "$categoryId-$storeId"; + if (!$this->categoryCache[$key]) { + $this->categoryCache[$key] = $this->categoryRepository->get($categoryId, $storeId); + } + return $this->categoryCache[$key]; + } +} diff --git a/etc/adminhtml/di.xml b/etc/adminhtml/di.xml index cabd4ec50..9297def2a 100755 --- a/etc/adminhtml/di.xml +++ b/etc/adminhtml/di.xml @@ -2,6 +2,7 @@ + From 3017f1565b04e06c0804a50811b5a8800034e141 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Mon, 30 Oct 2023 21:04:09 -0400 Subject: [PATCH 21/47] MAGE-725 Get applicable stores for log --- .../CategoryVersion/CategoryVersionLogger.php | 49 ++++++++++++++++--- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/Model/CategoryVersion/CategoryVersionLogger.php b/Model/CategoryVersion/CategoryVersionLogger.php index ee4dc2e55..969d0d675 100644 --- a/Model/CategoryVersion/CategoryVersionLogger.php +++ b/Model/CategoryVersion/CategoryVersionLogger.php @@ -3,10 +3,15 @@ namespace Algolia\AlgoliaSearch\Model\CategoryVersion; use Algolia\AlgoliaSearch\Api\CategoryVersionLoggerInterface; +use Algolia\AlgoliaSearch\Api\CategoryVersionRepositoryInterface; +use Algolia\AlgoliaSearch\Api\Data\CategoryVersionInterface; use Algolia\AlgoliaSearch\Helper\ConfigHelper; use Magento\Catalog\Api\CategoryRepositoryInterface; +use Magento\Catalog\Api\Data\CategoryInterface; use Magento\Catalog\Model\Category; use Magento\Framework\App\ObjectManager; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Store\Model\StoreManager; use Psr\Log\LoggerInterface; class CategoryVersionLogger implements CategoryVersionLoggerInterface @@ -22,15 +27,23 @@ class CategoryVersionLogger implements CategoryVersionLoggerInterface */ protected ConfigHelper $config; + protected StoreManager $storeManager; + + protected CategoryVersionRepositoryInterface $categoryVersionRepository; + protected array $categoryCache = []; public function __construct( - ConfigHelper $config, - CategoryRepositoryInterface $categoryRepository + ConfigHelper $config, + CategoryRepositoryInterface $categoryRepository, + CategoryVersionRepositoryInterface $categoryVersionRepository, + StoreManager $storeManager ) { $this->config = $config; $this->categoryRepository = $categoryRepository; + $this->categoryVersionRepository = $categoryVersionRepository; + $this->storeManager = $storeManager; } /** @@ -39,11 +52,15 @@ public function __construct( public function logCategoryChange(Category $category, int $storedId = 0): void { if (!$this->config->isCategoryVersionTrackingEnabled($storedId)) return; - // Build full path from category + $path = $this->getCategoryPath($category, $storedId); ObjectManager::getInstance()->get(LoggerInterface::class)->info("---> Path: $path"); - // Build stores array if !$storeId - // Iterate through stores array + + foreach ($this->getStoreIds($storedId) as $id) { + /** @var CategoryVersionInterface $version */ + ObjectManager::getInstance()->get(LoggerInterface::class)->info("---> Add log for store $id"); + $version = $this->categoryVersionRepository->getNew(); + } // Dedupe existing pending changes for this storeId // Insert if not found @@ -53,7 +70,7 @@ public function logCategoryChange(Category $category, int $storedId = 0): void * @param Category $category * @param $storeId * @return string - * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws NoSuchEntityException */ protected function getCategoryPath(Category $category, $storeId): string { @@ -67,11 +84,29 @@ protected function getCategoryPath(Category $category, $storeId): string return $path; } + /** + * Get applicable store ID's to log versions for + * @param int $storeId + * @return array|int[] + */ + protected function getStoreIds(int $storeId): array + { + if ($storeId) return [$storeId]; + + $storeIds = []; + foreach (array_keys($this->storeManager->getStores()) as $id) { + if ($this->config->isEnabledBackend($id) && $this->config->isCategoryVersionTrackingEnabled($id)) { + $storeIds[] = $id; + } + } + return $storeIds; + } + /** * @param int $categoryId * @param int $storeId * @return CategoryInterface - * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws NoSuchEntityException */ protected function getCategory(int $categoryId, int $storeId): CategoryInterface { From a4f12f004b543b866a15bb15b5be4ce9960c34fa Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Mon, 30 Oct 2023 21:10:51 -0400 Subject: [PATCH 22/47] MAGE-725 Add logic to not log change for overridden category --- .../CategoryVersion/CategoryVersionLogger.php | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/Model/CategoryVersion/CategoryVersionLogger.php b/Model/CategoryVersion/CategoryVersionLogger.php index 969d0d675..274ad41f6 100644 --- a/Model/CategoryVersion/CategoryVersionLogger.php +++ b/Model/CategoryVersion/CategoryVersionLogger.php @@ -56,7 +56,7 @@ public function logCategoryChange(Category $category, int $storedId = 0): void $path = $this->getCategoryPath($category, $storedId); ObjectManager::getInstance()->get(LoggerInterface::class)->info("---> Path: $path"); - foreach ($this->getStoreIds($storedId) as $id) { + foreach ($this->getStoreIds($category, $storedId) as $id) { /** @var CategoryVersionInterface $version */ ObjectManager::getInstance()->get(LoggerInterface::class)->info("---> Add log for store $id"); $version = $this->categoryVersionRepository->getNew(); @@ -85,23 +85,38 @@ protected function getCategoryPath(Category $category, $storeId): string } /** - * Get applicable store ID's to log versions for + * Get applicable store ID's to log versions for - either the specified store or all non overridden stores * @param int $storeId * @return array|int[] + * @throws NoSuchEntityException */ - protected function getStoreIds(int $storeId): array + protected function getStoreIds(CategoryInterface $category, int $storeId): array { if ($storeId) return [$storeId]; $storeIds = []; foreach (array_keys($this->storeManager->getStores()) as $id) { - if ($this->config->isEnabledBackend($id) && $this->config->isCategoryVersionTrackingEnabled($id)) { + if ($this->config->isEnabledBackend($id) + && $this->config->isCategoryVersionTrackingEnabled($id) + && !$this->isCategoryOverridden($category, $id)) { $storeIds[] = $id; } } return $storeIds; } - + + /** + * @param CategoryInterface $defaultCategory + * @param int $storeId + * @return bool + * @throws NoSuchEntityException + */ + protected function isCategoryOverridden(CategoryInterface $defaultCategory, int $storeId): bool + { + $storeScopedCategory = $this->categoryRepository->get($defaultCategory->getId(), $storeId); + return $storeScopedCategory->getName() !== $defaultCategory->getName(); + } + /** * @param int $categoryId * @param int $storeId From f8994a7bc1c9b58661fc807bd2b44f80a86b7b24 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Mon, 30 Oct 2023 21:39:59 -0400 Subject: [PATCH 23/47] MAGE-725 Add version interface attributes --- Api/Data/CategoryVersionInterface.php | 12 +++++++ Model/CategoryVersion.php | 43 ++++++++++++++++++++++++- Model/ResourceModel/CategoryVersion.php | 9 +++++- 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/Api/Data/CategoryVersionInterface.php b/Api/Data/CategoryVersionInterface.php index 0e6d17b5c..9fafef6d1 100644 --- a/Api/Data/CategoryVersionInterface.php +++ b/Api/Data/CategoryVersionInterface.php @@ -7,4 +7,16 @@ interface CategoryVersionInterface extends ExtensibleDataInterface { + public function getCategoryId(): int; + public function setCategoryId(int $categoryId): CategoryVersionInterface; + + public function getStoreId(): int; + public function setStoreId(int $storeId): CategoryVersionInterface; + + public function getOldValue(): string; + public function setOldValue(string $val): CategoryVersionInterface; + + public function getNewValue(): string; + public function setNewValue(string $val): CategoryVersionInterface; + } diff --git a/Model/CategoryVersion.php b/Model/CategoryVersion.php index 6b5953200..6afdad05f 100644 --- a/Model/CategoryVersion.php +++ b/Model/CategoryVersion.php @@ -3,6 +3,7 @@ namespace Algolia\AlgoliaSearch\Model; use Algolia\AlgoliaSearch\Api\Data\CategoryVersionInterface; +use Algolia\AlgoliaSearch\Model\ResourceModel\CategoryVersion as CategoryVersionResource; use Magento\Framework\DataObject\IdentityInterface; use Magento\Framework\Model\AbstractExtensibleModel; @@ -14,7 +15,7 @@ class CategoryVersion extends AbstractExtensibleModel implements IdentityInterfa protected function _construct() { - $this->_init( ResourceModel\CategoryVersion::class); + $this->_init(ResourceModel\CategoryVersion::class); } /** @@ -24,4 +25,44 @@ public function getIdentities(): array { return [self::CACHE_TAG . '_' . $this->getId()]; } + + public function getCategoryId(): int + { + return $this->getData(CategoryVersionResource::CATEGORY_ID); + } + + public function setCategoryId(int $categoryId): CategoryVersionInterface + { + return $this->setData(CategoryVersionResource::CATEGORY_ID, $categoryId); + } + + public function getStoreId(): int + { + return $this->getData(CategoryVersionResource::STORE_ID); + } + + public function setStoreId(int $storeId): CategoryVersionInterface + { + return $this->setData(CategoryVersionResource::STORE_ID, $storeId); + } + + public function getOldValue(): string + { + return $this->getData(CategoryVersionResource::OLD_VALUE); + } + + public function setOldValue(string $val): CategoryVersionInterface + { + return $this->setData(CategoryVersionResource::OLD_VALUE, $val); + } + + public function getNewValue(): string + { + return $this->getData(CategoryVersionResource::NEW_VALUE); + } + + public function setNewValue(string $val): CategoryVersionInterface + { + return $this->setData(CategoryVersionResource::NEW_VALUE, $val); + } } diff --git a/Model/ResourceModel/CategoryVersion.php b/Model/ResourceModel/CategoryVersion.php index 791e1c732..06083caa6 100644 --- a/Model/ResourceModel/CategoryVersion.php +++ b/Model/ResourceModel/CategoryVersion.php @@ -4,9 +4,16 @@ class CategoryVersion extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb { - const TABLE_NAME = 'algoliasearch_category_version'; const ID = 'version_id'; + const CATEGORY_ID = 'entity_id'; + const STORE_ID = 'store_id'; + const OLD_VALUE = 'old_value'; + const NEW_VALUE = 'new_value'; + const CREATED_AT = 'created_at'; + const UPDATED_AT = 'updated_at'; + const INDEXED_AT = 'indexed_at'; + const RESOLVED_AT = 'resolved_at'; protected function _construct() { From 4f48d647e8c3de3dffdaf209cd1538534999d919 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Mon, 30 Oct 2023 21:40:31 -0400 Subject: [PATCH 24/47] MAGE-725 Save version to change log --- Api/CategoryVersionLoggerInterface.php | 2 ++ Model/CategoryVersion/CategoryVersionLogger.php | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/Api/CategoryVersionLoggerInterface.php b/Api/CategoryVersionLoggerInterface.php index b26fe5760..a46c49715 100644 --- a/Api/CategoryVersionLoggerInterface.php +++ b/Api/CategoryVersionLoggerInterface.php @@ -3,6 +3,7 @@ namespace Algolia\AlgoliaSearch\Api; use Magento\Catalog\Model\Category; +use Magento\Framework\Exception\NoSuchEntityException; interface CategoryVersionLoggerInterface { @@ -10,6 +11,7 @@ interface CategoryVersionLoggerInterface * @param Category $category * @param int $storedId * @return void + * @throws NoSuchEntityException */ public function logCategoryChange(Category $category, int $storedId = 0): void; } diff --git a/Model/CategoryVersion/CategoryVersionLogger.php b/Model/CategoryVersion/CategoryVersionLogger.php index 274ad41f6..0393c2720 100644 --- a/Model/CategoryVersion/CategoryVersionLogger.php +++ b/Model/CategoryVersion/CategoryVersionLogger.php @@ -60,6 +60,11 @@ public function logCategoryChange(Category $category, int $storedId = 0): void /** @var CategoryVersionInterface $version */ ObjectManager::getInstance()->get(LoggerInterface::class)->info("---> Add log for store $id"); $version = $this->categoryVersionRepository->getNew(); + $version->setCategoryId($category->getId()); + $version->setStoreId($id); + $version->setOldValue($category->getOrigData('name')); + $version->setNewValue($path); + $this->categoryVersionRepository->save($version); } // Dedupe existing pending changes for this storeId // Insert if not found From e1416e3613425dc1956a022ca0e04cacc146c3a2 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Mon, 30 Oct 2023 22:12:03 -0400 Subject: [PATCH 25/47] MAGE-725 Declare exceptions --- Api/CategoryVersionLoggerInterface.php | 2 ++ Api/CategoryVersionRepositoryInterface.php | 10 ++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Api/CategoryVersionLoggerInterface.php b/Api/CategoryVersionLoggerInterface.php index a46c49715..e79ad4181 100644 --- a/Api/CategoryVersionLoggerInterface.php +++ b/Api/CategoryVersionLoggerInterface.php @@ -3,6 +3,7 @@ namespace Algolia\AlgoliaSearch\Api; use Magento\Catalog\Model\Category; +use Magento\Framework\Exception\AlreadyExistsException; use Magento\Framework\Exception\NoSuchEntityException; interface CategoryVersionLoggerInterface @@ -12,6 +13,7 @@ interface CategoryVersionLoggerInterface * @param int $storedId * @return void * @throws NoSuchEntityException + * @throws AlreadyExistsException */ public function logCategoryChange(Category $category, int $storedId = 0): void; } diff --git a/Api/CategoryVersionRepositoryInterface.php b/Api/CategoryVersionRepositoryInterface.php index cbc3ff75f..d8f7da31a 100644 --- a/Api/CategoryVersionRepositoryInterface.php +++ b/Api/CategoryVersionRepositoryInterface.php @@ -3,25 +3,27 @@ namespace Algolia\AlgoliaSearch\Api; use Algolia\AlgoliaSearch\Api\Data\CategoryVersionInterface; +use Magento\Framework\Exception\AlreadyExistsException; +use Magento\Framework\Exception\NoSuchEntityException; interface CategoryVersionRepositoryInterface { /** * @param int $id * @return CategoryVersionInterface - * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws NoSuchEntityException */ - public function getById(int $id) : CategoryVersionInterface; + public function getById(int $id): CategoryVersionInterface; /** * @return CategoryVersionInterface */ - public function getNew() : CategoryVersionInterface; + public function getNew(): CategoryVersionInterface; /** * @param CategoryVersionInterface $version * @return CategoryVersionInterface - * @throws \Magento\Framework\Exception\AlreadyExistsException + * @throws AlreadyExistsException */ public function save(CategoryVersionInterface $version): CategoryVersionInterface; } From 29b19d04a5715e1e1ec64cbfdbe40bfc98cf0285 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Mon, 30 Oct 2023 22:13:07 -0400 Subject: [PATCH 26/47] MAGE-725 Refactor to log previous category hierarchy by store scope --- .../CategoryVersion/CategoryVersionLogger.php | 67 ++++++++++++++----- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/Model/CategoryVersion/CategoryVersionLogger.php b/Model/CategoryVersion/CategoryVersionLogger.php index 0393c2720..9a4bb8eaa 100644 --- a/Model/CategoryVersion/CategoryVersionLogger.php +++ b/Model/CategoryVersion/CategoryVersionLogger.php @@ -31,6 +31,7 @@ class CategoryVersionLogger implements CategoryVersionLoggerInterface protected CategoryVersionRepositoryInterface $categoryVersionRepository; + /** @var CategoryInterface[] $categoryCache */ protected array $categoryCache = []; public function __construct( @@ -53,7 +54,7 @@ public function logCategoryChange(Category $category, int $storedId = 0): void { if (!$this->config->isCategoryVersionTrackingEnabled($storedId)) return; - $path = $this->getCategoryPath($category, $storedId); + $path = $this->getNewCategoryPath($category, $storedId); ObjectManager::getInstance()->get(LoggerInterface::class)->info("---> Path: $path"); foreach ($this->getStoreIds($category, $storedId) as $id) { @@ -62,7 +63,7 @@ public function logCategoryChange(Category $category, int $storedId = 0): void $version = $this->categoryVersionRepository->getNew(); $version->setCategoryId($category->getId()); $version->setStoreId($id); - $version->setOldValue($category->getOrigData('name')); + $version->setOldValue($this->getOldCategoryPath($category, $storedId)); $version->setNewValue($path); $this->categoryVersionRepository->save($version); } @@ -73,22 +74,58 @@ public function logCategoryChange(Category $category, int $storedId = 0): void /** * @param Category $category - * @param $storeId + * @param int $storeId * @return string * @throws NoSuchEntityException */ - protected function getCategoryPath(Category $category, $storeId): string + protected function getNewCategoryPath(Category $category, int $storeId): string { + return $this->getCategoryPath($category->getName(), $category->getPathIds(), $storeId); + } - $path = $category->getName(); - foreach (array_slice(array_reverse($category->getPathIds()), 1) as $treeCategoryId) { - $level = $this->categoryRepository->get($treeCategoryId, $storeId); + /** + * @param string $categoryName + * @param array $pathIds + * @param int $storeId + * @return string + * @throws NoSuchEntityException + */ + protected function getCategoryPath(string $categoryName, array $pathIds, int $storeId): string + { + $path = $categoryName; + foreach (array_slice(array_reverse($pathIds), 1) as $treeCategoryId) { + $level = $this->getCachedCategory($treeCategoryId, $storeId); $path = $level->getName() . $this->config->getCategorySeparator() . $path; if ((int) $level->getLevel() === self::MIN_CATEGORY_LEVEL) break; } return $path; } + /** + * @param int $categoryId + * @param int $storeId + * @return CategoryInterface + * @throws NoSuchEntityException + */ + protected function getCachedCategory(int $categoryId, int $storeId): CategoryInterface + { + $key = "$categoryId-$storeId"; + if (!array_key_exists($key, $this->categoryCache)) { + $this->categoryCache[$key] = $this->categoryRepository->get($categoryId, $storeId); + } + return $this->categoryCache[$key]; + } + + /** + * For extracting path ids from orig path data + * @param string|null $path + * @return int[] + */ + protected function getPathIds(string|null $path): array + { + return $path !== null ? explode('/', $path) : []; + } + /** * Get applicable store ID's to log versions for - either the specified store or all non overridden stores * @param int $storeId @@ -123,17 +160,17 @@ protected function isCategoryOverridden(CategoryInterface $defaultCategory, int } /** - * @param int $categoryId + * @param Category $category * @param int $storeId - * @return CategoryInterface + * @return string * @throws NoSuchEntityException */ - protected function getCategory(int $categoryId, int $storeId): CategoryInterface + protected function getOldCategoryPath(Category $category, int $storeId): string { - $key = "$categoryId-$storeId"; - if (!$this->categoryCache[$key]) { - $this->categoryCache[$key] = $this->categoryRepository->get($categoryId, $storeId); - } - return $this->categoryCache[$key]; + return $this->getCategoryPath( + $category->getOrigData(CategoryInterface::KEY_NAME), + $this->getPathIds($category->getOrigData(CategoryInterface::KEY_PATH)), + $storeId + ); } } From 2c6739b63a6544c8accc0d15509b97dee2b05686 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 01:17:02 -0400 Subject: [PATCH 27/47] MAGE-725 Add support to category version repo for SearchCriteria --- Api/CategoryVersionRepositoryInterface.php | 8 ++ .../CategoryVersionSearchResultsInterface.php | 24 +++++ .../CategoryVersionRepository.php | 98 +++++++++++++------ .../CategoryVersionSearchResults.php | 13 +++ etc/di.xml | 1 + 5 files changed, 112 insertions(+), 32 deletions(-) create mode 100644 Api/Data/CategoryVersionSearchResultsInterface.php create mode 100644 Model/CategoryVersion/CategoryVersionSearchResults.php diff --git a/Api/CategoryVersionRepositoryInterface.php b/Api/CategoryVersionRepositoryInterface.php index d8f7da31a..efe716459 100644 --- a/Api/CategoryVersionRepositoryInterface.php +++ b/Api/CategoryVersionRepositoryInterface.php @@ -3,8 +3,10 @@ namespace Algolia\AlgoliaSearch\Api; use Algolia\AlgoliaSearch\Api\Data\CategoryVersionInterface; +use Algolia\AlgoliaSearch\Api\Data\CategoryVersionSearchResultsInterface; use Magento\Framework\Exception\AlreadyExistsException; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Api\SearchCriteriaInterface; interface CategoryVersionRepositoryInterface { @@ -26,4 +28,10 @@ public function getNew(): CategoryVersionInterface; * @throws AlreadyExistsException */ public function save(CategoryVersionInterface $version): CategoryVersionInterface; + + /** + * @param SearchCriteriaInterface|null $searchCriteria + * @return CategoryVersionSearchResultsInterface + */ + public function getList(SearchCriteriaInterface $searchCriteria = null): CategoryVersionSearchResultsInterface; } diff --git a/Api/Data/CategoryVersionSearchResultsInterface.php b/Api/Data/CategoryVersionSearchResultsInterface.php new file mode 100644 index 000000000..54aece0f6 --- /dev/null +++ b/Api/Data/CategoryVersionSearchResultsInterface.php @@ -0,0 +1,24 @@ +versionFactory = $versionFactory; $this->versionResource = $versionResource; + $this->searchResultsFactory = $searchResultsFactory; + $this->categoryVersionCollectionFactory = $categoryVersionCollectionFactory; + $this->collectionProcessor = $collectionProcessor; } /** * @inheritDoc */ - public function getById(int $id): CategoryVersionInterface + public function getNew(): CategoryVersionInterface { - if (!isset($this->versions[$id])) { - $version = $this->versionFactory->create(); - $this->versionResource->load($version, $id); - if (!$version->getId()) { - throw new NoSuchEntityException(__("No category version with id $id exists.")); - } - $this->versions[$version->getId()] = $version; - } - return $this->versions[$id]; - } - - /** - * @inheritDoc - */ - public function getNew() : CategoryVersionInterface { return $this->versionFactory->create(); } @@ -63,20 +67,50 @@ public function save(CategoryVersionInterface $version): CategoryVersionInterfac /** * @inheritDoc */ - public function delete(CategoryVersionInterface $version) : void + public function deleteById($id): void { - $this->versionResource->delete($version); + $version = $this->getById($id); + unset($this->versions[$id]); + $this->delete($version); } /** * @inheritDoc */ - public function deleteById($id) : void + public function getById(int $id): CategoryVersionInterface { - $version = $this->getById($id); - unset($this->versions[$id]); - $this->delete($version); + if (!isset($this->versions[$id])) { + $version = $this->versionFactory->create(); + $this->versionResource->load($version, $id); + if (!$version->getId()) { + throw new NoSuchEntityException(__("No category version with id $id exists.")); + } + $this->versions[$version->getId()] = $version; + } + return $this->versions[$id]; } + /** + * @inheritDoc + */ + public function delete(CategoryVersionInterface $version): void + { + $this->versionResource->delete($version); + } + /** + * @inheritDoc + */ + public function getList(SearchCriteriaInterface $searchCriteria = null): CategoryVersionSearchResultsInterface + { + $collection = $this->categoryVersionCollectionFactory->create(); + $searchResults = $this->searchResultsFactory->create(); + if ($searchCriteria) { + $this->collectionProcessor->process($searchCriteria, $collection); + $searchResults->setSearchCriteria($searchCriteria); + } + $searchResults->setItems($collection->getItems()); + $searchResults->setTotalCount($collection->getSize()); + return $searchResults; + } } diff --git a/Model/CategoryVersion/CategoryVersionSearchResults.php b/Model/CategoryVersion/CategoryVersionSearchResults.php new file mode 100644 index 000000000..603269686 --- /dev/null +++ b/Model/CategoryVersion/CategoryVersionSearchResults.php @@ -0,0 +1,13 @@ + + From 68bf8e9693a1ba610ae7e8d27eae89f476ed6c32 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 01:18:25 -0400 Subject: [PATCH 28/47] MAGE-725 deduplicate change log insert --- .../CategoryVersion/CategoryVersionLogger.php | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/Model/CategoryVersion/CategoryVersionLogger.php b/Model/CategoryVersion/CategoryVersionLogger.php index 9a4bb8eaa..8ca1bd9a1 100644 --- a/Model/CategoryVersion/CategoryVersionLogger.php +++ b/Model/CategoryVersion/CategoryVersionLogger.php @@ -5,10 +5,14 @@ use Algolia\AlgoliaSearch\Api\CategoryVersionLoggerInterface; use Algolia\AlgoliaSearch\Api\CategoryVersionRepositoryInterface; use Algolia\AlgoliaSearch\Api\Data\CategoryVersionInterface; +use Algolia\AlgoliaSearch\Api\Data\CategoryVersionSearchResultsInterface; use Algolia\AlgoliaSearch\Helper\ConfigHelper; +use Algolia\AlgoliaSearch\Model\ResourceModel\CategoryVersion as CategoryVersionResource; use Magento\Catalog\Api\CategoryRepositoryInterface; use Magento\Catalog\Api\Data\CategoryInterface; +use Magento\Catalog\Api\Data\CategorySearchResultsInterface; use Magento\Catalog\Model\Category; +use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Store\Model\StoreManager; @@ -31,6 +35,8 @@ class CategoryVersionLogger implements CategoryVersionLoggerInterface protected CategoryVersionRepositoryInterface $categoryVersionRepository; + protected SearchCriteriaBuilder $searchCriteriaBuilder; + /** @var CategoryInterface[] $categoryCache */ protected array $categoryCache = []; @@ -38,13 +44,15 @@ public function __construct( ConfigHelper $config, CategoryRepositoryInterface $categoryRepository, CategoryVersionRepositoryInterface $categoryVersionRepository, - StoreManager $storeManager + StoreManager $storeManager, + SearchCriteriaBuilder $searchCriteriaBuilder ) { $this->config = $config; $this->categoryRepository = $categoryRepository; $this->categoryVersionRepository = $categoryVersionRepository; $this->storeManager = $storeManager; + $this->searchCriteriaBuilder = $searchCriteriaBuilder; } /** @@ -60,16 +68,34 @@ public function logCategoryChange(Category $category, int $storedId = 0): void foreach ($this->getStoreIds($category, $storedId) as $id) { /** @var CategoryVersionInterface $version */ ObjectManager::getInstance()->get(LoggerInterface::class)->info("---> Add log for store $id"); - $version = $this->categoryVersionRepository->getNew(); + $version = $this->getCategoryVersion($category->getId(), $path, $id); $version->setCategoryId($category->getId()); $version->setStoreId($id); $version->setOldValue($this->getOldCategoryPath($category, $storedId)); $version->setNewValue($path); $this->categoryVersionRepository->save($version); } - // Dedupe existing pending changes for this storeId - // Insert if not found + } + /** + * Get deduplicated record + * @param int $categoryId + * @param string $path + * @param int $storeId + * @return CategoryVersionInterface + */ + protected function getCategoryVersion(int $categoryId, string $path, int $storeId): CategoryVersionInterface { + $searchCriteria = $this->searchCriteriaBuilder + ->addFilter(CategoryVersionResource::CATEGORY_ID, $categoryId) + ->addFilter(CategoryVersionResource::NEW_VALUE, $path) + ->addFilter(CategoryVersionResource::STORE_ID, $storeId); + /* @var CategoryVersionSearchResultsInterface */ + $results = $this->categoryVersionRepository->getList($searchCriteria->create()); + if ($results->getTotalCount()) { + return array_values($results->getItems())[0]; + } else { + return $this->categoryVersionRepository->getNew(); + } } /** From 2d791e8aeb19513a122856b23dab0562776d69a9 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 01:21:00 -0400 Subject: [PATCH 29/47] MAGE-725 Add logger to afterSave plugin --- Model/Indexer/CategoryObserver.php | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Model/Indexer/CategoryObserver.php b/Model/Indexer/CategoryObserver.php index 75b29ea02..44176a4ea 100755 --- a/Model/Indexer/CategoryObserver.php +++ b/Model/Indexer/CategoryObserver.php @@ -11,6 +11,8 @@ use Magento\Framework\App\ResourceConnection; use Magento\Framework\Indexer\IndexerRegistry; use Algolia\AlgoliaSearch\Helper\Logger; +use Algolia\AlgoliaSearch\Api\CategoryVersionLoggerInterface; + class CategoryObserver { @@ -28,6 +30,9 @@ class CategoryObserver protected $logger; + protected $storeManager; + + protected $categoryVersionLogger; /** * CategoryObserver constructor. @@ -40,13 +45,17 @@ public function __construct( IndexerRegistry $indexerRegistry, ConfigHelper $configHelper, ResourceConnection $resource, - Logger $logger + Logger $logger, + \Magento\Store\Model\StoreManagerInterface $storeManager, + CategoryVersionLoggerInterface $categoryVersionLogger ) { $this->indexerRegistry = $indexerRegistry; $this->indexer = $indexerRegistry->get('algolia_categories'); $this->configHelper = $configHelper; $this->resource = $resource; $this->logger = $logger; + $this->storeManager = $storeManager; + $this->categoryVersionLogger = $categoryVersionLogger; } /** @@ -70,19 +79,24 @@ protected function isDataChanged(AbstractModel $model, array $fields): bool * @param CategoryModel $category * * @return CategoryResourceModel + * @throws \Magento\Framework\Exception\NoSuchEntityException */ public function afterSave( CategoryResourceModel $categoryResource, CategoryResourceModel $result, CategoryModel $category ) { - $categoryResource->addCommitCallback(function () use ($category) { + $storeId = $this->storeManager->getStore()->getId(); + $this->logger->log("-----> Store ID: $storeId"); + + $categoryResource->addCommitCallback(function () use ($category, $storeId) { $collectionIds = []; // To reduce the indexing operation for products, only update if these values have changed if ($this->isDataChanged($category, ['name', 'path', 'include_in_menu', 'is_active'])) { /** @var ProductCollection $productCollection */ $productCollection = $category->getProductCollection(); $collectionIds = (array) $productCollection->getColumnValues('entity_id'); + $this->categoryVersionLogger->logCategoryChange($category, $storeId); } $changedProductIds = ($category->getChangedProductIds() !== null ? (array) $category->getChangedProductIds() : []); From 625d4e8aa4a8b33fea5cf4826be2bd20af373e80 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 02:41:05 -0400 Subject: [PATCH 30/47] MAGE-725 Update modified timestamp --- Api/Data/CategoryVersionInterface.php | 3 +++ Model/CategoryVersion.php | 10 ++++++++++ Model/CategoryVersion/CategoryVersionLogger.php | 1 + 3 files changed, 14 insertions(+) diff --git a/Api/Data/CategoryVersionInterface.php b/Api/Data/CategoryVersionInterface.php index 9fafef6d1..fbe765f54 100644 --- a/Api/Data/CategoryVersionInterface.php +++ b/Api/Data/CategoryVersionInterface.php @@ -19,4 +19,7 @@ public function setOldValue(string $val): CategoryVersionInterface; public function getNewValue(): string; public function setNewValue(string $val): CategoryVersionInterface; + public function getUpdatedAt(): string; + public function setUpdatedAt(?string $val): CategoryVersionInterface; + } diff --git a/Model/CategoryVersion.php b/Model/CategoryVersion.php index 6afdad05f..0d6f5ad2e 100644 --- a/Model/CategoryVersion.php +++ b/Model/CategoryVersion.php @@ -65,4 +65,14 @@ public function setNewValue(string $val): CategoryVersionInterface { return $this->setData(CategoryVersionResource::NEW_VALUE, $val); } + + public function getUpdatedAt(): string + { + return $this->getData(CategoryVersionResource::UPDATED_AT); + } + + public function setUpdatedAt(?string $val): CategoryVersionInterface + { + return $this->setData(CategoryVersionResource::UPDATED_AT, $val); + } } diff --git a/Model/CategoryVersion/CategoryVersionLogger.php b/Model/CategoryVersion/CategoryVersionLogger.php index 8ca1bd9a1..ac8a2d9df 100644 --- a/Model/CategoryVersion/CategoryVersionLogger.php +++ b/Model/CategoryVersion/CategoryVersionLogger.php @@ -73,6 +73,7 @@ public function logCategoryChange(Category $category, int $storedId = 0): void $version->setStoreId($id); $version->setOldValue($this->getOldCategoryPath($category, $storedId)); $version->setNewValue($path); + $version->setUpdatedAt(null); $this->categoryVersionRepository->save($version); } } From 97ac21182b1e0ee22a8a99f24001bfc5a2688638 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 03:13:55 -0400 Subject: [PATCH 31/47] MAGE-725 Reformat code --- Model/Indexer/CategoryObserver.php | 115 ++++++++++++++--------------- 1 file changed, 57 insertions(+), 58 deletions(-) diff --git a/Model/Indexer/CategoryObserver.php b/Model/Indexer/CategoryObserver.php index 44176a4ea..5c75298ee 100755 --- a/Model/Indexer/CategoryObserver.php +++ b/Model/Indexer/CategoryObserver.php @@ -2,38 +2,34 @@ namespace Algolia\AlgoliaSearch\Model\Indexer; +use Algolia\AlgoliaSearch\Api\CategoryVersionLoggerInterface; use Algolia\AlgoliaSearch\Helper\ConfigHelper; +use Algolia\AlgoliaSearch\Helper\Logger; use Algolia\AlgoliaSearch\Model\Indexer\Category as CategoryIndexer; use Magento\Catalog\Model\AbstractModel; use Magento\Catalog\Model\Category as CategoryModel; use Magento\Catalog\Model\ResourceModel\Category as CategoryResourceModel; use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection; use Magento\Framework\App\ResourceConnection; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Indexer\IndexerRegistry; -use Algolia\AlgoliaSearch\Helper\Logger; -use Algolia\AlgoliaSearch\Api\CategoryVersionLoggerInterface; +use Magento\Store\Model\StoreManagerInterface; class CategoryObserver { + /** @var ResourceConnection */ + protected $resource; + protected $logger; + protected $storeManager; + protected $categoryVersionLogger; /** @var IndexerRegistry */ private $indexerRegistry; - /** @var CategoryIndexer */ private $indexer; - /** @var ConfigHelper */ private $configHelper; - /** @var ResourceConnection */ - protected $resource; - - protected $logger; - - protected $storeManager; - - protected $categoryVersionLogger; - /** * CategoryObserver constructor. * @@ -42,13 +38,14 @@ class CategoryObserver * @param ResourceConnection $resource */ public function __construct( - IndexerRegistry $indexerRegistry, - ConfigHelper $configHelper, - ResourceConnection $resource, - Logger $logger, - \Magento\Store\Model\StoreManagerInterface $storeManager, + IndexerRegistry $indexerRegistry, + ConfigHelper $configHelper, + ResourceConnection $resource, + Logger $logger, + StoreManagerInterface $storeManager, CategoryVersionLoggerInterface $categoryVersionLogger - ) { + ) + { $this->indexerRegistry = $indexerRegistry; $this->indexer = $indexerRegistry->get('algolia_categories'); $this->configHelper = $configHelper; @@ -58,34 +55,20 @@ public function __construct( $this->categoryVersionLogger = $categoryVersionLogger; } - /** - * @param AbstractModel $model - * @param array $fields - * @return bool - */ - protected function isDataChanged(AbstractModel $model, array $fields): bool - { - foreach ($fields as $field) { - if ($model->getOrigData($field) !== $model->getData($field)) { - return true; - } - } - return false; - } - /** * @param CategoryResourceModel $categoryResource * @param CategoryResourceModel $result * @param CategoryModel $category * * @return CategoryResourceModel - * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws NoSuchEntityException */ public function afterSave( CategoryResourceModel $categoryResource, CategoryResourceModel $result, - CategoryModel $category - ) { + CategoryModel $category + ) + { $storeId = $this->storeManager->getStore()->getId(); $this->logger->log("-----> Store ID: $storeId"); @@ -116,29 +99,18 @@ public function afterSave( } /** - * @param CategoryResourceModel $categoryResource - * @param CategoryResourceModel $result - * @param CategoryModel $category - * - * @return CategoryResourceModel + * @param AbstractModel $model + * @param array $fields + * @return bool */ - public function afterDelete( - CategoryResourceModel $categoryResource, - CategoryResourceModel $result, - CategoryModel $category - ) { - $categoryResource->addCommitCallback(function () use ($category) { - // mview should be able to handle the changes for catalog_category_product relationship - if (!$this->indexer->isScheduled()) { - /* we are using products position because getProductCollection() doesn't use correct store */ - $productCollection = $category->getProductsPosition(); - CategoryIndexer::$affectedProductIds = array_keys($productCollection); - - $this->indexer->reindexRow($category->getId()); + protected function isDataChanged(AbstractModel $model, array $fields): bool + { + foreach ($fields as $field) { + if ($model->getOrigData($field) !== $model->getData($field)) { + return true; } - }); - - return $result; + } + return false; } /** @@ -163,4 +135,31 @@ private function updateCategoryProducts(array $productIds) } } } + + /** + * @param CategoryResourceModel $categoryResource + * @param CategoryResourceModel $result + * @param CategoryModel $category + * + * @return CategoryResourceModel + */ + public function afterDelete( + CategoryResourceModel $categoryResource, + CategoryResourceModel $result, + CategoryModel $category + ) + { + $categoryResource->addCommitCallback(function () use ($category) { + // mview should be able to handle the changes for catalog_category_product relationship + if (!$this->indexer->isScheduled()) { + /* we are using products position because getProductCollection() doesn't use correct store */ + $productCollection = $category->getProductsPosition(); + CategoryIndexer::$affectedProductIds = array_keys($productCollection); + + $this->indexer->reindexRow($category->getId()); + } + }); + + return $result; + } } From bb6d9a492c3518ec08b1cdd6b5953429fcca59d0 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 03:14:37 -0400 Subject: [PATCH 32/47] MAGE-725 Fix hierarchy path bug --- Model/CategoryVersion/CategoryVersionLogger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Model/CategoryVersion/CategoryVersionLogger.php b/Model/CategoryVersion/CategoryVersionLogger.php index ac8a2d9df..530fa0e36 100644 --- a/Model/CategoryVersion/CategoryVersionLogger.php +++ b/Model/CategoryVersion/CategoryVersionLogger.php @@ -122,8 +122,8 @@ protected function getCategoryPath(string $categoryName, array $pathIds, int $st $path = $categoryName; foreach (array_slice(array_reverse($pathIds), 1) as $treeCategoryId) { $level = $this->getCachedCategory($treeCategoryId, $storeId); + if ((int) $level->getLevel() < self::MIN_CATEGORY_LEVEL) break; $path = $level->getName() . $this->config->getCategorySeparator() . $path; - if ((int) $level->getLevel() === self::MIN_CATEGORY_LEVEL) break; } return $path; } From 2950225cd049c9c1443b4280259ceac0f78b7d90 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 03:15:30 -0400 Subject: [PATCH 33/47] MAGE-725 Add category move plugin --- Plugin/CategoryMovePlugin.php | 53 +++++++++++++++++++++++++++++++++++ etc/adminhtml/di.xml | 3 ++ 2 files changed, 56 insertions(+) create mode 100644 Plugin/CategoryMovePlugin.php diff --git a/Plugin/CategoryMovePlugin.php b/Plugin/CategoryMovePlugin.php new file mode 100644 index 000000000..29bac6d89 --- /dev/null +++ b/Plugin/CategoryMovePlugin.php @@ -0,0 +1,53 @@ +logger = $logger; + $this->storeManager = $storeManager; + $this->categoryVersionLogger = $categoryVersionLogger; + } + + /** + * @param Category $subject + * @param Category $result + * @param int $parentId + * @param int|null $afterCategoryId + * @return Category + * @throws AlreadyExistsException + * @throws NoSuchEntityException + */ + public function afterMove(Category $subject, Category $result, int $parentId, null|int $afterCategoryId) + { + $this->logger->log("Moving the category to $parentId with after id $afterCategoryId"); + $this->logger->log("Original category path " . $result->getOrigData('path')); + $this->logger->log("New category path: " . $result->getData('path')); + + $storeId = $this->storeManager->getStore()->getId(); + $this->logger->log("Moving for store ID: $storeId"); + $this->categoryVersionLogger->logCategoryChange($result, $storeId); + return $result; + } +} diff --git a/etc/adminhtml/di.xml b/etc/adminhtml/di.xml index 9297def2a..d14ed4b4f 100755 --- a/etc/adminhtml/di.xml +++ b/etc/adminhtml/di.xml @@ -11,4 +11,7 @@ Magento\Framework\Url + + + From 26e2d2dc707d00cf9be60cc2cea6455dbc41ebe2 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 04:21:17 -0400 Subject: [PATCH 34/47] MAGE-725 Introduce discrete move logging method due to alternate store scope behaviors --- Api/CategoryVersionLoggerInterface.php | 12 +++ .../CategoryVersion/CategoryVersionLogger.php | 75 +++++++++++++------ Plugin/CategoryMovePlugin.php | 5 +- etc/adminhtml/di.xml | 4 +- 4 files changed, 67 insertions(+), 29 deletions(-) diff --git a/Api/CategoryVersionLoggerInterface.php b/Api/CategoryVersionLoggerInterface.php index e79ad4181..7fbf40dc9 100644 --- a/Api/CategoryVersionLoggerInterface.php +++ b/Api/CategoryVersionLoggerInterface.php @@ -9,6 +9,8 @@ interface CategoryVersionLoggerInterface { /** + * Category save events are store scope sensitive. + * * @param Category $category * @param int $storedId * @return void @@ -16,4 +18,14 @@ interface CategoryVersionLoggerInterface * @throws AlreadyExistsException */ public function logCategoryChange(Category $category, int $storedId = 0): void; + + /** + * Category move events are not store scoped and must be handled differently. + * + * @param Category $category + * @return void + * @throws NoSuchEntityException + * @throws AlreadyExistsException + */ + public function logCategoryMove(Category $category): void; } diff --git a/Model/CategoryVersion/CategoryVersionLogger.php b/Model/CategoryVersion/CategoryVersionLogger.php index 530fa0e36..e6b307e11 100644 --- a/Model/CategoryVersion/CategoryVersionLogger.php +++ b/Model/CategoryVersion/CategoryVersionLogger.php @@ -13,14 +13,13 @@ use Magento\Catalog\Api\Data\CategorySearchResultsInterface; use Magento\Catalog\Model\Category; use Magento\Framework\Api\SearchCriteriaBuilder; -use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Store\Model\StoreManager; -use Psr\Log\LoggerInterface; class CategoryVersionLogger implements CategoryVersionLoggerInterface { public const MIN_CATEGORY_LEVEL = 2; + public const DEFAULT_STORE = 0; /** * @var CategoryRepositoryInterface */ @@ -63,11 +62,9 @@ public function logCategoryChange(Category $category, int $storedId = 0): void if (!$this->config->isCategoryVersionTrackingEnabled($storedId)) return; $path = $this->getNewCategoryPath($category, $storedId); - ObjectManager::getInstance()->get(LoggerInterface::class)->info("---> Path: $path"); foreach ($this->getStoreIds($category, $storedId) as $id) { /** @var CategoryVersionInterface $version */ - ObjectManager::getInstance()->get(LoggerInterface::class)->info("---> Add log for store $id"); $version = $this->getCategoryVersion($category->getId(), $path, $id); $version->setCategoryId($category->getId()); $version->setStoreId($id); @@ -78,6 +75,32 @@ public function logCategoryChange(Category $category, int $storedId = 0): void } } + /** + * @inheritDoc + */ + public function logCategoryMove(Category $category): void { + $defaultStoreId = self::DEFAULT_STORE; + if (!$this->config->isCategoryVersionTrackingEnabled($defaultStoreId)) return; + foreach ($this->getStoreIds($category, $defaultStoreId, false) as $id) { + /** @var CategoryInterface */ + $scopedCategory = $this->getCachedCategory($category->getId(), $id); + $path = $this->getNewCategoryPath($scopedCategory, $id); + /** @var CategoryVersionInterface */ + $version = $this->getCategoryVersion($category->getId(), $path, $id); + $version->setCategoryId($category->getId()); + $version->setStoreId($id); + $version->setOldValue( + $this->getCategoryPath( + $scopedCategory->getName(), + $this->getPathIds($category->getOrigData(CategoryInterface::KEY_PATH)), + $id) + ); + $version->setNewValue($path); + $version->setUpdatedAt(null); + $this->categoryVersionRepository->save($version); + } + } + /** * Get deduplicated record * @param int $categoryId @@ -100,6 +123,7 @@ protected function getCategoryVersion(int $categoryId, string $path, int $storeI } /** + * Get the new category path for the category being updated * @param Category $category * @param int $storeId * @return string @@ -111,6 +135,23 @@ protected function getNewCategoryPath(Category $category, int $storeId): string } /** + * Get the old category path for a standard category save operation + * @param Category $category + * @param int $storeId + * @return string + * @throws NoSuchEntityException + */ + protected function getOldCategoryPath(Category $category, int $storeId): string + { + return $this->getCategoryPath( + $category->getOrigData(CategoryInterface::KEY_NAME), + $this->getPathIds($category->getOrigData(CategoryInterface::KEY_PATH)), + $storeId + ); + } + + /** + * Get the category path name (used for category page IDs) * @param string $categoryName * @param array $pathIds * @param int $storeId @@ -154,20 +195,23 @@ protected function getPathIds(string|null $path): array } /** - * Get applicable store ID's to log versions for - either the specified store or all non overridden stores - * @param int $storeId + * Get applicable store ID's to log versions for - either the specified store, all stores or all non overridden stores + * @param CategoryInterface $category + * @param int $storeId - specific store or 0 (for default) + * @param bool $filterOverride - whether to include overridden stores * @return array|int[] * @throws NoSuchEntityException */ - protected function getStoreIds(CategoryInterface $category, int $storeId): array + protected function getStoreIds(CategoryInterface $category, int $storeId, bool $filterOverride = true): array { + //specified store if ($storeId) return [$storeId]; $storeIds = []; foreach (array_keys($this->storeManager->getStores()) as $id) { if ($this->config->isEnabledBackend($id) && $this->config->isCategoryVersionTrackingEnabled($id) - && !$this->isCategoryOverridden($category, $id)) { + && (!$filterOverride || !$this->isCategoryOverridden($category, $id))) { $storeIds[] = $id; } } @@ -185,19 +229,4 @@ protected function isCategoryOverridden(CategoryInterface $defaultCategory, int $storeScopedCategory = $this->categoryRepository->get($defaultCategory->getId(), $storeId); return $storeScopedCategory->getName() !== $defaultCategory->getName(); } - - /** - * @param Category $category - * @param int $storeId - * @return string - * @throws NoSuchEntityException - */ - protected function getOldCategoryPath(Category $category, int $storeId): string - { - return $this->getCategoryPath( - $category->getOrigData(CategoryInterface::KEY_NAME), - $this->getPathIds($category->getOrigData(CategoryInterface::KEY_PATH)), - $storeId - ); - } } diff --git a/Plugin/CategoryMovePlugin.php b/Plugin/CategoryMovePlugin.php index 29bac6d89..4789297de 100644 --- a/Plugin/CategoryMovePlugin.php +++ b/Plugin/CategoryMovePlugin.php @@ -45,9 +45,8 @@ public function afterMove(Category $subject, Category $result, int $parentId, nu $this->logger->log("Original category path " . $result->getOrigData('path')); $this->logger->log("New category path: " . $result->getData('path')); - $storeId = $this->storeManager->getStore()->getId(); - $this->logger->log("Moving for store ID: $storeId"); - $this->categoryVersionLogger->logCategoryChange($result, $storeId); +// $this->logger->log("Moving for store ID: $storeId"); + $this->categoryVersionLogger->logCategoryMove($result); return $result; } } diff --git a/etc/adminhtml/di.xml b/etc/adminhtml/di.xml index d14ed4b4f..4171e5d4e 100755 --- a/etc/adminhtml/di.xml +++ b/etc/adminhtml/di.xml @@ -5,13 +5,11 @@ + Magento\Framework\Url - - - From e9f7e0417871697703f33aa95f25d53cd3adc52b Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 09:09:57 -0400 Subject: [PATCH 35/47] MAGE-725 Relocate constants for API layer --- Api/Data/CategoryVersionInterface.php | 8 +++++++ Model/CategoryVersion.php | 21 +++++++++---------- .../CategoryVersion/CategoryVersionLogger.php | 10 +++++---- Model/ResourceModel/CategoryVersion.php | 8 ------- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/Api/Data/CategoryVersionInterface.php b/Api/Data/CategoryVersionInterface.php index fbe765f54..e1f546481 100644 --- a/Api/Data/CategoryVersionInterface.php +++ b/Api/Data/CategoryVersionInterface.php @@ -6,6 +6,14 @@ interface CategoryVersionInterface extends ExtensibleDataInterface { + const CATEGORY_ID = 'entity_id'; + const STORE_ID = 'store_id'; + const OLD_VALUE = 'old_value'; + const NEW_VALUE = 'new_value'; + const CREATED_AT = 'created_at'; + const UPDATED_AT = 'updated_at'; + const INDEXED_AT = 'indexed_at'; + const RESOLVED_AT = 'resolved_at'; public function getCategoryId(): int; public function setCategoryId(int $categoryId): CategoryVersionInterface; diff --git a/Model/CategoryVersion.php b/Model/CategoryVersion.php index 0d6f5ad2e..9f92b9256 100644 --- a/Model/CategoryVersion.php +++ b/Model/CategoryVersion.php @@ -3,7 +3,6 @@ namespace Algolia\AlgoliaSearch\Model; use Algolia\AlgoliaSearch\Api\Data\CategoryVersionInterface; -use Algolia\AlgoliaSearch\Model\ResourceModel\CategoryVersion as CategoryVersionResource; use Magento\Framework\DataObject\IdentityInterface; use Magento\Framework\Model\AbstractExtensibleModel; @@ -28,51 +27,51 @@ public function getIdentities(): array public function getCategoryId(): int { - return $this->getData(CategoryVersionResource::CATEGORY_ID); + return $this->getData(CategoryVersionInterface::CATEGORY_ID); } public function setCategoryId(int $categoryId): CategoryVersionInterface { - return $this->setData(CategoryVersionResource::CATEGORY_ID, $categoryId); + return $this->setData(CategoryVersionInterface::CATEGORY_ID, $categoryId); } public function getStoreId(): int { - return $this->getData(CategoryVersionResource::STORE_ID); + return $this->getData(CategoryVersionInterface::STORE_ID); } public function setStoreId(int $storeId): CategoryVersionInterface { - return $this->setData(CategoryVersionResource::STORE_ID, $storeId); + return $this->setData(CategoryVersionInterface::STORE_ID, $storeId); } public function getOldValue(): string { - return $this->getData(CategoryVersionResource::OLD_VALUE); + return $this->getData(CategoryVersionInterface::OLD_VALUE); } public function setOldValue(string $val): CategoryVersionInterface { - return $this->setData(CategoryVersionResource::OLD_VALUE, $val); + return $this->setData(CategoryVersionInterface::OLD_VALUE, $val); } public function getNewValue(): string { - return $this->getData(CategoryVersionResource::NEW_VALUE); + return $this->getData(CategoryVersionInterface::NEW_VALUE); } public function setNewValue(string $val): CategoryVersionInterface { - return $this->setData(CategoryVersionResource::NEW_VALUE, $val); + return $this->setData(CategoryVersionInterface::NEW_VALUE, $val); } public function getUpdatedAt(): string { - return $this->getData(CategoryVersionResource::UPDATED_AT); + return $this->getData(CategoryVersionInterface::UPDATED_AT); } public function setUpdatedAt(?string $val): CategoryVersionInterface { - return $this->setData(CategoryVersionResource::UPDATED_AT, $val); + return $this->setData(CategoryVersionInterface::UPDATED_AT, $val); } } diff --git a/Model/CategoryVersion/CategoryVersionLogger.php b/Model/CategoryVersion/CategoryVersionLogger.php index e6b307e11..15e7a782c 100644 --- a/Model/CategoryVersion/CategoryVersionLogger.php +++ b/Model/CategoryVersion/CategoryVersionLogger.php @@ -7,7 +7,6 @@ use Algolia\AlgoliaSearch\Api\Data\CategoryVersionInterface; use Algolia\AlgoliaSearch\Api\Data\CategoryVersionSearchResultsInterface; use Algolia\AlgoliaSearch\Helper\ConfigHelper; -use Algolia\AlgoliaSearch\Model\ResourceModel\CategoryVersion as CategoryVersionResource; use Magento\Catalog\Api\CategoryRepositoryInterface; use Magento\Catalog\Api\Data\CategoryInterface; use Magento\Catalog\Api\Data\CategorySearchResultsInterface; @@ -30,10 +29,13 @@ class CategoryVersionLogger implements CategoryVersionLoggerInterface */ protected ConfigHelper $config; + /** @var StoreManager */ protected StoreManager $storeManager; + /** @var CategoryVersionRepositoryInterface */ protected CategoryVersionRepositoryInterface $categoryVersionRepository; + /** @var SearchCriteriaBuilder */ protected SearchCriteriaBuilder $searchCriteriaBuilder; /** @var CategoryInterface[] $categoryCache */ @@ -110,9 +112,9 @@ public function logCategoryMove(Category $category): void { */ protected function getCategoryVersion(int $categoryId, string $path, int $storeId): CategoryVersionInterface { $searchCriteria = $this->searchCriteriaBuilder - ->addFilter(CategoryVersionResource::CATEGORY_ID, $categoryId) - ->addFilter(CategoryVersionResource::NEW_VALUE, $path) - ->addFilter(CategoryVersionResource::STORE_ID, $storeId); + ->addFilter(CategoryVersionInterface::CATEGORY_ID, $categoryId) + ->addFilter(CategoryVersionInterface::NEW_VALUE, $path) + ->addFilter(CategoryVersionInterface::STORE_ID, $storeId); /* @var CategoryVersionSearchResultsInterface */ $results = $this->categoryVersionRepository->getList($searchCriteria->create()); if ($results->getTotalCount()) { diff --git a/Model/ResourceModel/CategoryVersion.php b/Model/ResourceModel/CategoryVersion.php index 06083caa6..546525593 100644 --- a/Model/ResourceModel/CategoryVersion.php +++ b/Model/ResourceModel/CategoryVersion.php @@ -6,14 +6,6 @@ class CategoryVersion extends \Magento\Framework\Model\ResourceModel\Db\Abstract { const TABLE_NAME = 'algoliasearch_category_version'; const ID = 'version_id'; - const CATEGORY_ID = 'entity_id'; - const STORE_ID = 'store_id'; - const OLD_VALUE = 'old_value'; - const NEW_VALUE = 'new_value'; - const CREATED_AT = 'created_at'; - const UPDATED_AT = 'updated_at'; - const INDEXED_AT = 'indexed_at'; - const RESOLVED_AT = 'resolved_at'; protected function _construct() { From 8174850bc424df80c7029cb358c70a51744ab081 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 09:57:42 -0400 Subject: [PATCH 36/47] MAGE-725 Remove path monitoring from save plugin (it never changes in this scenario). This is instead handled separately by the move plugin. --- Model/Indexer/CategoryObserver.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Model/Indexer/CategoryObserver.php b/Model/Indexer/CategoryObserver.php index 5c75298ee..9a17201fd 100755 --- a/Model/Indexer/CategoryObserver.php +++ b/Model/Indexer/CategoryObserver.php @@ -6,6 +6,7 @@ use Algolia\AlgoliaSearch\Helper\ConfigHelper; use Algolia\AlgoliaSearch\Helper\Logger; use Algolia\AlgoliaSearch\Model\Indexer\Category as CategoryIndexer; +use Magento\Catalog\Api\Data\CategoryInterface; use Magento\Catalog\Model\AbstractModel; use Magento\Catalog\Model\Category as CategoryModel; use Magento\Catalog\Model\ResourceModel\Category as CategoryResourceModel; @@ -70,12 +71,15 @@ public function afterSave( ) { $storeId = $this->storeManager->getStore()->getId(); - $this->logger->log("-----> Store ID: $storeId"); $categoryResource->addCommitCallback(function () use ($category, $storeId) { $collectionIds = []; // To reduce the indexing operation for products, only update if these values have changed - if ($this->isDataChanged($category, ['name', 'path', 'include_in_menu', 'is_active'])) { + if ($this->isDataChanged($category, [ + CategoryInterface::KEY_NAME, + CategoryInterface::KEY_INCLUDE_IN_MENU, + CategoryInterface::KEY_IS_ACTIVE + ])) { /** @var ProductCollection $productCollection */ $productCollection = $category->getProductCollection(); $collectionIds = (array) $productCollection->getColumnValues('entity_id'); From 2abeccff9c3ca289ccb13140bec39bbc5fe8764f Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 10:07:40 -0400 Subject: [PATCH 37/47] MAGE-725 Adopt core Magento naming convention for field constants --- Api/Data/CategoryVersionInterface.php | 16 +++++++-------- Model/CategoryVersion.php | 20 +++++++++---------- .../CategoryVersion/CategoryVersionLogger.php | 6 +++--- Plugin/CategoryMovePlugin.php | 10 ---------- 4 files changed, 21 insertions(+), 31 deletions(-) diff --git a/Api/Data/CategoryVersionInterface.php b/Api/Data/CategoryVersionInterface.php index e1f546481..5f2a4dd71 100644 --- a/Api/Data/CategoryVersionInterface.php +++ b/Api/Data/CategoryVersionInterface.php @@ -6,14 +6,14 @@ interface CategoryVersionInterface extends ExtensibleDataInterface { - const CATEGORY_ID = 'entity_id'; - const STORE_ID = 'store_id'; - const OLD_VALUE = 'old_value'; - const NEW_VALUE = 'new_value'; - const CREATED_AT = 'created_at'; - const UPDATED_AT = 'updated_at'; - const INDEXED_AT = 'indexed_at'; - const RESOLVED_AT = 'resolved_at'; + const KEY_CATEGORY_ID = 'entity_id'; + const KEY_STORE_ID = 'store_id'; + const KEY_OLD_VALUE = 'old_value'; + const KEY_NEW_VALUE = 'new_value'; + const KEY_CREATED_AT = 'created_at'; + const KEY_UPDATED_AT = 'updated_at'; + const KEY_INDEXED_AT = 'indexed_at'; + const KEY_RESOLVED_AT = 'resolved_at'; public function getCategoryId(): int; public function setCategoryId(int $categoryId): CategoryVersionInterface; diff --git a/Model/CategoryVersion.php b/Model/CategoryVersion.php index 9f92b9256..320713c39 100644 --- a/Model/CategoryVersion.php +++ b/Model/CategoryVersion.php @@ -27,51 +27,51 @@ public function getIdentities(): array public function getCategoryId(): int { - return $this->getData(CategoryVersionInterface::CATEGORY_ID); + return $this->getData(CategoryVersionInterface::KEY_CATEGORY_ID); } public function setCategoryId(int $categoryId): CategoryVersionInterface { - return $this->setData(CategoryVersionInterface::CATEGORY_ID, $categoryId); + return $this->setData(CategoryVersionInterface::KEY_CATEGORY_ID, $categoryId); } public function getStoreId(): int { - return $this->getData(CategoryVersionInterface::STORE_ID); + return $this->getData(CategoryVersionInterface::KEY_STORE_ID); } public function setStoreId(int $storeId): CategoryVersionInterface { - return $this->setData(CategoryVersionInterface::STORE_ID, $storeId); + return $this->setData(CategoryVersionInterface::KEY_STORE_ID, $storeId); } public function getOldValue(): string { - return $this->getData(CategoryVersionInterface::OLD_VALUE); + return $this->getData(CategoryVersionInterface::KEY_OLD_VALUE); } public function setOldValue(string $val): CategoryVersionInterface { - return $this->setData(CategoryVersionInterface::OLD_VALUE, $val); + return $this->setData(CategoryVersionInterface::KEY_OLD_VALUE, $val); } public function getNewValue(): string { - return $this->getData(CategoryVersionInterface::NEW_VALUE); + return $this->getData(CategoryVersionInterface::KEY_NEW_VALUE); } public function setNewValue(string $val): CategoryVersionInterface { - return $this->setData(CategoryVersionInterface::NEW_VALUE, $val); + return $this->setData(CategoryVersionInterface::KEY_NEW_VALUE, $val); } public function getUpdatedAt(): string { - return $this->getData(CategoryVersionInterface::UPDATED_AT); + return $this->getData(CategoryVersionInterface::KEY_UPDATED_AT); } public function setUpdatedAt(?string $val): CategoryVersionInterface { - return $this->setData(CategoryVersionInterface::UPDATED_AT, $val); + return $this->setData(CategoryVersionInterface::KEY_UPDATED_AT, $val); } } diff --git a/Model/CategoryVersion/CategoryVersionLogger.php b/Model/CategoryVersion/CategoryVersionLogger.php index 15e7a782c..d3bfb316e 100644 --- a/Model/CategoryVersion/CategoryVersionLogger.php +++ b/Model/CategoryVersion/CategoryVersionLogger.php @@ -112,9 +112,9 @@ public function logCategoryMove(Category $category): void { */ protected function getCategoryVersion(int $categoryId, string $path, int $storeId): CategoryVersionInterface { $searchCriteria = $this->searchCriteriaBuilder - ->addFilter(CategoryVersionInterface::CATEGORY_ID, $categoryId) - ->addFilter(CategoryVersionInterface::NEW_VALUE, $path) - ->addFilter(CategoryVersionInterface::STORE_ID, $storeId); + ->addFilter(CategoryVersionInterface::KEY_CATEGORY_ID, $categoryId) + ->addFilter(CategoryVersionInterface::KEY_NEW_VALUE, $path) + ->addFilter(CategoryVersionInterface::KEY_STORE_ID, $storeId); /* @var CategoryVersionSearchResultsInterface */ $results = $this->categoryVersionRepository->getList($searchCriteria->create()); if ($results->getTotalCount()) { diff --git a/Plugin/CategoryMovePlugin.php b/Plugin/CategoryMovePlugin.php index 4789297de..9ffe936e3 100644 --- a/Plugin/CategoryMovePlugin.php +++ b/Plugin/CategoryMovePlugin.php @@ -3,7 +3,6 @@ namespace Algolia\AlgoliaSearch\Plugin; use Algolia\AlgoliaSearch\Api\CategoryVersionLoggerInterface; -use Algolia\AlgoliaSearch\Helper\Logger; use Magento\Catalog\Model\Category; use Magento\Framework\Exception\AlreadyExistsException; use Magento\Framework\Exception\NoSuchEntityException; @@ -11,8 +10,6 @@ class CategoryMovePlugin { - protected $logger; - /** @var StoreManagerInterface */ protected StoreManagerInterface $storeManager; @@ -20,12 +17,10 @@ class CategoryMovePlugin protected CategoryVersionLoggerInterface $categoryVersionLogger; public function __construct( - Logger $logger, StoreManagerInterface $storeManager, CategoryVersionLoggerInterface $categoryVersionLogger ) { - $this->logger = $logger; $this->storeManager = $storeManager; $this->categoryVersionLogger = $categoryVersionLogger; } @@ -41,11 +36,6 @@ public function __construct( */ public function afterMove(Category $subject, Category $result, int $parentId, null|int $afterCategoryId) { - $this->logger->log("Moving the category to $parentId with after id $afterCategoryId"); - $this->logger->log("Original category path " . $result->getOrigData('path')); - $this->logger->log("New category path: " . $result->getData('path')); - -// $this->logger->log("Moving for store ID: $storeId"); $this->categoryVersionLogger->logCategoryMove($result); return $result; } From 3b500f0b9bfa8193dfd188dd4811d77c0b6aae5b Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 10:27:27 -0400 Subject: [PATCH 38/47] MAGE-725 Bug fix for save operations from multiple admin tabs (category path data can become out of sync) --- Model/Indexer/CategoryObserver.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Model/Indexer/CategoryObserver.php b/Model/Indexer/CategoryObserver.php index 9a17201fd..bc02001c1 100755 --- a/Model/Indexer/CategoryObserver.php +++ b/Model/Indexer/CategoryObserver.php @@ -77,13 +77,18 @@ public function afterSave( // To reduce the indexing operation for products, only update if these values have changed if ($this->isDataChanged($category, [ CategoryInterface::KEY_NAME, + CategoryInterface::KEY_PATH, CategoryInterface::KEY_INCLUDE_IN_MENU, CategoryInterface::KEY_IS_ACTIVE ])) { /** @var ProductCollection $productCollection */ $productCollection = $category->getProductCollection(); $collectionIds = (array) $productCollection->getColumnValues('entity_id'); - $this->categoryVersionLogger->logCategoryChange($category, $storeId); + if ($this->isDataChanged($category, [CategoryInterface::KEY_PATH])) { + $this->categoryVersionLogger->logCategoryMove($category); + } else { + $this->categoryVersionLogger->logCategoryChange($category, $storeId); + } } $changedProductIds = ($category->getChangedProductIds() !== null ? (array) $category->getChangedProductIds() : []); From 917d1d9812fd310b1a42ae069dfb10d7ba1587b4 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 11:29:47 -0400 Subject: [PATCH 39/47] MAGE-791 Add alt registry for current category --- Observer/RegisterCurrentCategoryObserver.php | 28 ++++++++++++++++++ Registry/CurrentCategory.php | 31 ++++++++++++++++++++ etc/frontend/events.xml | 5 ++++ 3 files changed, 64 insertions(+) create mode 100644 Observer/RegisterCurrentCategoryObserver.php create mode 100644 Registry/CurrentCategory.php diff --git a/Observer/RegisterCurrentCategoryObserver.php b/Observer/RegisterCurrentCategoryObserver.php new file mode 100644 index 000000000..a08c90b8e --- /dev/null +++ b/Observer/RegisterCurrentCategoryObserver.php @@ -0,0 +1,28 @@ +currentCategory = $currentCategory; + } + + /** + * @inheritDoc + */ + public function execute(Observer $observer) + { + /** @var CategoryInterface */ + $category = $observer->getEvent()->getData('category'); + $this->currentCategory->set($category); + } +} diff --git a/Registry/CurrentCategory.php b/Registry/CurrentCategory.php new file mode 100644 index 000000000..e7f19c77f --- /dev/null +++ b/Registry/CurrentCategory.php @@ -0,0 +1,31 @@ +categoryRepository = $categoryRepository; + $this->categoryFactory = $categoryFactory; + } + + public function set(CategoryInterface $category): void { + $this->category = $category; + } + + public function get(): CategoryInterface { + return $this->category ?? $this->categoryFactory->create(); + } +} diff --git a/etc/frontend/events.xml b/etc/frontend/events.xml index df4c060f1..90147b29f 100755 --- a/etc/frontend/events.xml +++ b/etc/frontend/events.xml @@ -23,4 +23,9 @@ + + + + + From 25a0051c30b8d78bcf5e3e282903df7a0301a49b Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 15:29:49 -0400 Subject: [PATCH 40/47] MAGE-791 Load current category via new custom registry --- Block/Algolia.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Block/Algolia.php b/Block/Algolia.php index c87e58eef..bc53a9224 100755 --- a/Block/Algolia.php +++ b/Block/Algolia.php @@ -10,6 +10,7 @@ use Algolia\AlgoliaSearch\Helper\Entity\ProductHelper; use Algolia\AlgoliaSearch\Helper\Entity\SuggestionHelper; use Algolia\AlgoliaSearch\Helper\LandingPageHelper; +use Algolia\AlgoliaSearch\Registry\CurrentCategory; use Magento\Catalog\Model\Product; use Magento\Checkout\Model\Session as CheckoutSession; use Magento\Customer\Model\Context as CustomerContext; @@ -97,6 +98,9 @@ class Algolia extends Template implements CollectionDataSourceInterface */ protected $date; + /** @var CurrentCategory */ + protected CurrentCategory $currentCategory; + protected $priceKey; /** @@ -139,6 +143,7 @@ public function __construct( PersonalizationHelper $personalizationHelper, CheckoutSession $checkoutSession, DateTime $date, + CurrentCategory $currentCategory, array $data = [] ) { $this->config = $config; @@ -158,6 +163,7 @@ public function __construct( $this->personalizationHelper = $personalizationHelper; $this->checkoutSession = $checkoutSession; $this->date = $date; + $this->currentCategory = $currentCategory; parent::__construct($context, $data); } @@ -255,7 +261,7 @@ public function getStoreId() public function getCurrentCategory() { - return $this->registry->registry('current_category'); + return $this->currentCategory->get(); } /** @return Product */ From 3a119e3a4d2ce349897ff5a8691b643e666f2666 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 17:54:23 -0400 Subject: [PATCH 41/47] MAGE-725 Add state to category version extension attribute --- .../CategoryVersionAttributeInterface.php | 15 ++++++++--- Block/Algolia.php | 1 - Block/Configuration.php | 3 --- .../CategoryVersionAttribute.php | 25 +++++++++++++++---- Plugin/CategoryVersionPlugin.php | 19 ++++++-------- 5 files changed, 40 insertions(+), 23 deletions(-) diff --git a/Api/Data/CategoryVersionAttributeInterface.php b/Api/Data/CategoryVersionAttributeInterface.php index 8e1e57ddc..97495b4c0 100644 --- a/Api/Data/CategoryVersionAttributeInterface.php +++ b/Api/Data/CategoryVersionAttributeInterface.php @@ -6,22 +6,31 @@ interface CategoryVersionAttributeInterface { + /** + * @param int|null $storeId + * @return CategoryVersionAttributeInterface + */ + public function load(int $categoryId, int $storeId = null): CategoryVersionAttributeInterface; + /** * Does this category have versions? + * @param int|null $storeId * @return bool */ - public function hasVersions() : bool; + public function hasVersions(int $storeId = null): bool; /** * Get all versions of this category + * @param int|null $storeId * @return CategoryVersionInterface[] */ - public function getVersions() : array; + public function getVersions(int $storeId = null): array; /** * Get all possible request paths that can be used as category filters + * @param int|null $storeId * @return string[] */ - public function getSearchFilters() : array; + public function getSearchFilters(int $storeId = null): array; } diff --git a/Block/Algolia.php b/Block/Algolia.php index 776d028c1..9f1765259 100755 --- a/Block/Algolia.php +++ b/Block/Algolia.php @@ -164,7 +164,6 @@ public function __construct( $this->landingPageHelper = $landingPageHelper; $this->personalizationHelper = $personalizationHelper; $this->checkoutSession = $checkoutSession; - $this->categoryRepository = $categoryRepository; $this->date = $date; $this->currentCategory = $currentCategory; diff --git a/Block/Configuration.php b/Block/Configuration.php index e2442b63a..af32c4b45 100755 --- a/Block/Configuration.php +++ b/Block/Configuration.php @@ -125,10 +125,7 @@ public function getConfiguration() // BEGIN MOD - RETRIEVE ALL RELEVANT CATEGORY DATA $category = $this->getCurrentCategory(); -// $attr = $category->getExtensionAttributes(); // doesn't work - concrete class if ($config->isCategoryVersionTrackingEnabled()) { - $categoryId = (int) $this->getRequest()->getParam('id', false); - $category = $this->categoryRepository->get($categoryId); $attr = $category->getExtensionAttributes(); $versionsAttr = $attr->getAlgoliaCategoryVersions(); } diff --git a/Model/CategoryVersion/CategoryVersionAttribute.php b/Model/CategoryVersion/CategoryVersionAttribute.php index 9289e397c..af118c0e5 100644 --- a/Model/CategoryVersion/CategoryVersionAttribute.php +++ b/Model/CategoryVersion/CategoryVersionAttribute.php @@ -2,15 +2,30 @@ namespace Algolia\AlgoliaSearch\Model\CategoryVersion; -use Algolia\AlgoliaSearch\Api\Data\CategoryVersionInterface; +use Algolia\AlgoliaSearch\Api\Data\CategoryVersionAttributeInterface; -class CategoryVersionAttribute implements \Algolia\AlgoliaSearch\Api\Data\CategoryVersionAttributeInterface +class CategoryVersionAttribute implements CategoryVersionAttributeInterface { + /** @var int|null */ + protected $storeId; + + /** @var int */ + protected $categoryId; + + /** + * @inheritDoc + */ + public function load(int $categoryId, int $storeId = null) : CategoryVersionAttributeInterface + { + $this->categoryId = $categoryId; + $this->storeId = $storeId; + return $this; + } /** * @inheritDoc */ - public function hasVersions(): bool + public function hasVersions(int $storeId = null): bool { // TODO: Implement hasVersions() method. } @@ -18,7 +33,7 @@ public function hasVersions(): bool /** * @inheritDoc */ - public function getVersions(): array + public function getVersions(int $storeId = null): array { // TODO: Implement getVersions() method. } @@ -26,7 +41,7 @@ public function getVersions(): array /** * @inheritDoc */ - public function getSearchFilters(): array + public function getSearchFilters(int $storeId = null): array { // TODO: Implement getSearchFilters() method. } diff --git a/Plugin/CategoryVersionPlugin.php b/Plugin/CategoryVersionPlugin.php index 9c53c1f65..eb8de38fb 100644 --- a/Plugin/CategoryVersionPlugin.php +++ b/Plugin/CategoryVersionPlugin.php @@ -12,19 +12,16 @@ class CategoryVersionPlugin { /** @var CategoryVersionRepositoryInterface */ - protected $versionRepository; + protected CategoryVersionRepositoryInterface $versionRepository; /** @var CategoryExtensionFactory */ - protected $extensionFactory; + protected CategoryExtensionFactory $extensionFactory; /** @var CategoryVersionAttributeInterfaceFactory */ - protected $versionAttributeFactory; - - /** @var CategoryVersionAttributeInterface */ - protected $versionAttribute; + protected CategoryVersionAttributeInterfaceFactory $versionAttributeFactory; /** @var ConfigHelper */ - protected $config; + protected ConfigHelper $config; public function __construct( CategoryVersionRepositoryInterface $versionRepository, @@ -48,18 +45,18 @@ public function __construct( */ public function afterGet(CategoryRepositoryInterface $categoryRepository, CategoryInterface $category, int $categoryId, int $storeId = null): CategoryInterface { if (!$this->config->isCategoryVersionTrackingEnabled()) return $category; + \Magento\Framework\App\ObjectManager::getInstance()->get(\Psr\Log\LoggerInterface::class)->debug("Category called for store id $storeId and category id $categoryId"); $extensionAttributes = $category->getExtensionAttributes() ?? $this->extensionFactory->create(); - if (!$this->versionAttribute) { - $this->versionAttribute = $this->versionAttributeFactory->create(); - } - $extensionAttributes->setAlgoliaCategoryVersions($this->versionAttribute); + $versionAttribute = $extensionAttributes->getAlgoliaCategoryVersions() ?? $this->versionAttributeFactory->create()->load($categoryId, $storeId); + $extensionAttributes->setAlgoliaCategoryVersions($versionAttribute); $category->setExtensionAttributes($extensionAttributes); return $category; } // Unsupported in admin by core public function afterSave(CategoryRepositoryInterface $categoryRepository, CategoryInterface $result, CategoryInterface $category): CategoryInterface { + \Magento\Framework\App\ObjectManager::getInstance()->get(\Psr\Log\LoggerInterface::class)->debug('Category save called'); return $result; } } From a687f267dc1aa044909a30e8fad9a4fb6f6c338e Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 18:46:48 -0400 Subject: [PATCH 42/47] MAGE-725 Implement boolean check for available version plus search criteria in attribute class --- Block/Configuration.php | 13 +++--- .../CategoryVersionAttribute.php | 44 +++++++++++++++++-- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/Block/Configuration.php b/Block/Configuration.php index af32c4b45..80f3770e8 100755 --- a/Block/Configuration.php +++ b/Block/Configuration.php @@ -123,13 +123,7 @@ public function getConfiguration() && $config->replaceCategories() && $request->getControllerName() === 'category') { - // BEGIN MOD - RETRIEVE ALL RELEVANT CATEGORY DATA $category = $this->getCurrentCategory(); - if ($config->isCategoryVersionTrackingEnabled()) { - $attr = $category->getExtensionAttributes(); - $versionsAttr = $attr->getAlgoliaCategoryVersions(); - } - // END MOD if ($category && $category->getDisplayMode() !== 'PAGE') { $category->getUrlInstance()->setStore($this->getStoreId()); @@ -285,6 +279,7 @@ public function getConfiguration() 'level' => $level, 'parentCategory' => $parentCategoryName, 'childCategories' => $childCategories, + 'hasCategoryVersions' => $this->hasCategoryVersions(), 'url' => $this->getUrl('*/*/*', ['_use_rewrite' => true, '_forced_secure' => true]) ], 'showCatsNotIncludedInNavigation' => $config->showCatsNotIncludedInNavigation(), @@ -434,4 +429,10 @@ protected function getLandingPageConfiguration() { return $this->isLandingPage() ? $this->getCurrentLandingPage()->getConfiguration() : json_encode([]); } + + protected function hasCategoryVersions() : bool + { + if (!$this->config->isCategoryVersionTrackingEnabled()) return false; + return $this->getCurrentCategory()->getExtensionAttributes()->getAlgoliaCategoryVersions()->hasVersions(); + } } diff --git a/Model/CategoryVersion/CategoryVersionAttribute.php b/Model/CategoryVersion/CategoryVersionAttribute.php index af118c0e5..c7c0f1291 100644 --- a/Model/CategoryVersion/CategoryVersionAttribute.php +++ b/Model/CategoryVersion/CategoryVersionAttribute.php @@ -2,15 +2,37 @@ namespace Algolia\AlgoliaSearch\Model\CategoryVersion; +use Algolia\AlgoliaSearch\Api\CategoryVersionRepositoryInterface; use Algolia\AlgoliaSearch\Api\Data\CategoryVersionAttributeInterface; +use Algolia\AlgoliaSearch\Api\Data\CategoryVersionInterface; +use Algolia\AlgoliaSearch\Api\Data\CategoryVersionSearchResultsInterface; +use Magento\Framework\Api\SearchCriteriaBuilder; class CategoryVersionAttribute implements CategoryVersionAttributeInterface { /** @var int|null */ - protected $storeId; + protected int|null $storeId; /** @var int */ - protected $categoryId; + protected int $categoryId; + + /** @var array|null */ + protected array|null $versions; + + /** @var CategoryVersionRepositoryInterface */ + protected CategoryVersionRepositoryInterface $categoryVersionRepository; + + /** @var SearchCriteriaBuilder */ + protected SearchCriteriaBuilder $searchCriteriaBuilder; + + public function __construct( + CategoryVersionRepositoryInterface $categoryVersionRepository, + SearchCriteriaBuilder $searchCriteriaBuilder + ) { + $this->categoryVersionRepository = $categoryVersionRepository; + $this->searchCriteriaBuilder = $searchCriteriaBuilder; + $this->versions = null; + } /** * @inheritDoc @@ -27,7 +49,10 @@ public function load(int $categoryId, int $storeId = null) : CategoryVersionAttr */ public function hasVersions(int $storeId = null): bool { - // TODO: Implement hasVersions() method. + $storeId ??= $this->storeId; + if (!$storeId) return false; + + return (bool) count($this->getVersions($storeId)); } /** @@ -35,7 +60,18 @@ public function hasVersions(int $storeId = null): bool */ public function getVersions(int $storeId = null): array { - // TODO: Implement getVersions() method. + $storeId ??= $this->storeId; + if (!$storeId) return false; + + if (!$this->versions) { + $searchCriteria = $this->searchCriteriaBuilder + ->addFilter(CategoryVersionInterface::KEY_CATEGORY_ID, $this->categoryId) + ->addFilter(CategoryVersionInterface::KEY_STORE_ID, $storeId); + /* @var CategoryVersionSearchResultsInterface */ + $this->versions = $this->categoryVersionRepository->getList($searchCriteria->create())->getItems(); + } + + return $this->versions; } /** From ad9e4019d2fa5a2dfb34666a4039beb541c5c512 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 19:24:05 -0400 Subject: [PATCH 43/47] MAGE-725 Add alternate search filter extraction logic --- Block/Configuration.php | 9 ++++++++- .../CategoryVersionAttribute.php | 17 +++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Block/Configuration.php b/Block/Configuration.php index 80f3770e8..147b8672a 100755 --- a/Block/Configuration.php +++ b/Block/Configuration.php @@ -280,6 +280,7 @@ public function getConfiguration() 'parentCategory' => $parentCategoryName, 'childCategories' => $childCategories, 'hasCategoryVersions' => $this->hasCategoryVersions(), + 'alternatePaths' => $this->getAlternatePaths(), 'url' => $this->getUrl('*/*/*', ['_use_rewrite' => true, '_forced_secure' => true]) ], 'showCatsNotIncludedInNavigation' => $config->showCatsNotIncludedInNavigation(), @@ -430,9 +431,15 @@ protected function getLandingPageConfiguration() return $this->isLandingPage() ? $this->getCurrentLandingPage()->getConfiguration() : json_encode([]); } - protected function hasCategoryVersions() : bool + protected function hasCategoryVersions(): bool { if (!$this->config->isCategoryVersionTrackingEnabled()) return false; return $this->getCurrentCategory()->getExtensionAttributes()->getAlgoliaCategoryVersions()->hasVersions(); } + + protected function getAlternatePaths(): array + { + if (!$this->config->isCategoryVersionTrackingEnabled()) return []; + return $this->getCurrentCategory()->getExtensionAttributes()->getAlgoliaCategoryVersions()->getSearchFilters(); + } } diff --git a/Model/CategoryVersion/CategoryVersionAttribute.php b/Model/CategoryVersion/CategoryVersionAttribute.php index c7c0f1291..c9d35779c 100644 --- a/Model/CategoryVersion/CategoryVersionAttribute.php +++ b/Model/CategoryVersion/CategoryVersionAttribute.php @@ -17,7 +17,7 @@ class CategoryVersionAttribute implements CategoryVersionAttributeInterface protected int $categoryId; /** @var array|null */ - protected array|null $versions; + private array|null $versions; /** @var CategoryVersionRepositoryInterface */ protected CategoryVersionRepositoryInterface $categoryVersionRepository; @@ -61,14 +61,14 @@ public function hasVersions(int $storeId = null): bool public function getVersions(int $storeId = null): array { $storeId ??= $this->storeId; - if (!$storeId) return false; + if (!$storeId) return []; if (!$this->versions) { $searchCriteria = $this->searchCriteriaBuilder ->addFilter(CategoryVersionInterface::KEY_CATEGORY_ID, $this->categoryId) ->addFilter(CategoryVersionInterface::KEY_STORE_ID, $storeId); /* @var CategoryVersionSearchResultsInterface */ - $this->versions = $this->categoryVersionRepository->getList($searchCriteria->create())->getItems(); + $this->versions = array_values($this->categoryVersionRepository->getList($searchCriteria->create())->getItems()); } return $this->versions; @@ -79,6 +79,15 @@ public function getVersions(int $storeId = null): array */ public function getSearchFilters(int $storeId = null): array { - // TODO: Implement getSearchFilters() method. + $storeId ??= $this->storeId; + if (!$storeId) return []; + + $values = array_map( + function(CategoryVersionInterface $version) { + return $version->getNewValue(); + }, + $this->getVersions($storeId) + ); + return $values; } } From 9f104846305328a5f24238a8d37ce57aadd7a769 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 20:37:04 -0400 Subject: [PATCH 44/47] MAGE-725 Add multi filter support to InstantSearch based on category versions --- Block/Configuration.php | 15 ++++++++++----- .../CategoryVersion/CategoryVersionAttribute.php | 2 +- view/frontend/web/instantsearch.js | 9 +++++++-- view/frontend/web/internals/common.js | 2 +- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/Block/Configuration.php b/Block/Configuration.php index 147b8672a..697525bc3 100755 --- a/Block/Configuration.php +++ b/Block/Configuration.php @@ -280,7 +280,7 @@ public function getConfiguration() 'parentCategory' => $parentCategoryName, 'childCategories' => $childCategories, 'hasCategoryVersions' => $this->hasCategoryVersions(), - 'alternatePaths' => $this->getAlternatePaths(), + 'alternatePaths' => $this->getAlternatePaths($path), 'url' => $this->getUrl('*/*/*', ['_use_rewrite' => true, '_forced_secure' => true]) ], 'showCatsNotIncludedInNavigation' => $config->showCatsNotIncludedInNavigation(), @@ -434,12 +434,17 @@ protected function getLandingPageConfiguration() protected function hasCategoryVersions(): bool { if (!$this->config->isCategoryVersionTrackingEnabled()) return false; - return $this->getCurrentCategory()->getExtensionAttributes()->getAlgoliaCategoryVersions()->hasVersions(); + return (bool) $this->getCurrentCategory()->getExtensionAttributes()->getAlgoliaCategoryVersions()?->hasVersions(); } - protected function getAlternatePaths(): array + protected function getAlternatePaths(string $mainPath): array { - if (!$this->config->isCategoryVersionTrackingEnabled()) return []; - return $this->getCurrentCategory()->getExtensionAttributes()->getAlgoliaCategoryVersions()->getSearchFilters(); + if (!$this->config->isCategoryVersionTrackingEnabled() || !$this->hasCategoryVersions()) return []; + return array_unique( + array_merge( + [$mainPath], + $this->getCurrentCategory()->getExtensionAttributes()->getAlgoliaCategoryVersions()->getSearchFilters() + ) + ); } } diff --git a/Model/CategoryVersion/CategoryVersionAttribute.php b/Model/CategoryVersion/CategoryVersionAttribute.php index c9d35779c..e08cc8d14 100644 --- a/Model/CategoryVersion/CategoryVersionAttribute.php +++ b/Model/CategoryVersion/CategoryVersionAttribute.php @@ -84,7 +84,7 @@ public function getSearchFilters(int $storeId = null): array $values = array_map( function(CategoryVersionInterface $version) { - return $version->getNewValue(); + return $version->getOldValue(); }, $this->getVersions($storeId) ); diff --git a/view/frontend/web/instantsearch.js b/view/frontend/web/instantsearch.js index 5df5f3a06..3545d87f8 100644 --- a/view/frontend/web/instantsearch.js +++ b/view/frontend/web/instantsearch.js @@ -111,8 +111,13 @@ define( } } + + const getCategoryPageIdFilter = (param, paths) => { + return paths.map(path => `${param}:'${path}'`).join(' OR '); + }; + if (algoliaConfig.instant.isVisualMerchEnabled && algoliaConfig.isCategoryPage ) { - searchParameters.filters = `${algoliaConfig.instant.categoryPageIdAttribute}:'${algoliaConfig.request.path}'`; + searchParameters.filters = getCategoryPageIdFilter(algoliaConfig.instant.categoryPageIdAttribute, algoliaConfig.request.alternatePaths); } instantsearchOptions = algolia.triggerHooks('beforeInstantsearchInit', instantsearchOptions, algoliaBundle); @@ -460,7 +465,7 @@ define( templates : templates, showParentLevel : true, limit : algoliaConfig.maxValuesPerFacet, - rootPath : algoliaConfig.request.path, + rootPath : algoliaConfig.request.hasCategoryVersions ? null : algoliaConfig.request.path, sortBy : ['name:asc'], transformItems(items) { return (algoliaConfig.isCategoryPage) diff --git a/view/frontend/web/internals/common.js b/view/frontend/web/internals/common.js index da5138844..3ad560a6e 100755 --- a/view/frontend/web/internals/common.js +++ b/view/frontend/web/internals/common.js @@ -408,7 +408,7 @@ define(['jquery', 'algoliaBundle'], function ($, algoliaBundle) { uiStateProductIndex['hierarchicalMenu']['categories.level0'] = landingPageConfig['categories.level0'].split(algoliaConfig.instant.categorySeparator); } } - if (currentFacet.attribute == 'categories' && algoliaConfig.isCategoryPage) { + if (currentFacet.attribute == 'categories' && algoliaConfig.isCategoryPage && !algoliaConfig.request.hasCategoryVersions) { uiStateProductIndex['hierarchicalMenu']['categories.level0'] = [algoliaConfig.request.path]; } // Handle sliders From 3e4c88ad4493ddb749fea86afa0ab70a4758c3af Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 20:55:02 -0400 Subject: [PATCH 45/47] MAGE-725 Fix dedupe logic on category version logging --- .../CategoryVersion/CategoryVersionLogger.php | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/Model/CategoryVersion/CategoryVersionLogger.php b/Model/CategoryVersion/CategoryVersionLogger.php index d3bfb316e..2a62b76ee 100644 --- a/Model/CategoryVersion/CategoryVersionLogger.php +++ b/Model/CategoryVersion/CategoryVersionLogger.php @@ -63,15 +63,16 @@ public function logCategoryChange(Category $category, int $storedId = 0): void { if (!$this->config->isCategoryVersionTrackingEnabled($storedId)) return; - $path = $this->getNewCategoryPath($category, $storedId); + $newPath = $this->getNewCategoryPath($category, $storedId); + $oldPath = $this->getOldCategoryPath($category, $storedId); foreach ($this->getStoreIds($category, $storedId) as $id) { /** @var CategoryVersionInterface $version */ - $version = $this->getCategoryVersion($category->getId(), $path, $id); + $version = $this->getCategoryVersion($category->getId(), $oldPath, $id); $version->setCategoryId($category->getId()); $version->setStoreId($id); - $version->setOldValue($this->getOldCategoryPath($category, $storedId)); - $version->setNewValue($path); + $version->setOldValue($oldPath); + $version->setNewValue($newPath); $version->setUpdatedAt(null); $this->categoryVersionRepository->save($version); } @@ -83,21 +84,22 @@ public function logCategoryChange(Category $category, int $storedId = 0): void public function logCategoryMove(Category $category): void { $defaultStoreId = self::DEFAULT_STORE; if (!$this->config->isCategoryVersionTrackingEnabled($defaultStoreId)) return; + foreach ($this->getStoreIds($category, $defaultStoreId, false) as $id) { /** @var CategoryInterface */ $scopedCategory = $this->getCachedCategory($category->getId(), $id); - $path = $this->getNewCategoryPath($scopedCategory, $id); + $newPath = $this->getNewCategoryPath($scopedCategory, $id); + $oldPath = $this->getCategoryPath( + $scopedCategory->getName(), + $this->getPathIds($category->getOrigData(CategoryInterface::KEY_PATH)), + $id + ); /** @var CategoryVersionInterface */ - $version = $this->getCategoryVersion($category->getId(), $path, $id); + $version = $this->getCategoryVersion($category->getId(), $oldPath, $id); $version->setCategoryId($category->getId()); $version->setStoreId($id); - $version->setOldValue( - $this->getCategoryPath( - $scopedCategory->getName(), - $this->getPathIds($category->getOrigData(CategoryInterface::KEY_PATH)), - $id) - ); - $version->setNewValue($path); + $version->setOldValue($oldPath); + $version->setNewValue($newPath); $version->setUpdatedAt(null); $this->categoryVersionRepository->save($version); } @@ -113,7 +115,7 @@ public function logCategoryMove(Category $category): void { protected function getCategoryVersion(int $categoryId, string $path, int $storeId): CategoryVersionInterface { $searchCriteria = $this->searchCriteriaBuilder ->addFilter(CategoryVersionInterface::KEY_CATEGORY_ID, $categoryId) - ->addFilter(CategoryVersionInterface::KEY_NEW_VALUE, $path) + ->addFilter(CategoryVersionInterface::KEY_OLD_VALUE, $path) ->addFilter(CategoryVersionInterface::KEY_STORE_ID, $storeId); /* @var CategoryVersionSearchResultsInterface */ $results = $this->categoryVersionRepository->getList($searchCriteria->create()); From 5f1d8afb30b99e4bdc86cdd5c186ed8ecf43fb56 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 21:15:39 -0400 Subject: [PATCH 46/47] MAGE-725 Adjust path building to pull correct scope for parent categories --- Model/CategoryVersion/CategoryVersionLogger.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Model/CategoryVersion/CategoryVersionLogger.php b/Model/CategoryVersion/CategoryVersionLogger.php index 2a62b76ee..9b3a801a4 100644 --- a/Model/CategoryVersion/CategoryVersionLogger.php +++ b/Model/CategoryVersion/CategoryVersionLogger.php @@ -63,10 +63,9 @@ public function logCategoryChange(Category $category, int $storedId = 0): void { if (!$this->config->isCategoryVersionTrackingEnabled($storedId)) return; - $newPath = $this->getNewCategoryPath($category, $storedId); - $oldPath = $this->getOldCategoryPath($category, $storedId); - foreach ($this->getStoreIds($category, $storedId) as $id) { + $newPath = $this->getNewCategoryPath($category, $id); + $oldPath = $this->getOldCategoryPath($category, $id); /** @var CategoryVersionInterface $version */ $version = $this->getCategoryVersion($category->getId(), $oldPath, $id); $version->setCategoryId($category->getId()); @@ -84,7 +83,7 @@ public function logCategoryChange(Category $category, int $storedId = 0): void public function logCategoryMove(Category $category): void { $defaultStoreId = self::DEFAULT_STORE; if (!$this->config->isCategoryVersionTrackingEnabled($defaultStoreId)) return; - + foreach ($this->getStoreIds($category, $defaultStoreId, false) as $id) { /** @var CategoryInterface */ $scopedCategory = $this->getCachedCategory($category->getId(), $id); From 9fa3970018d8a3fdc3b5a9cfde21f088f21501b3 Mon Sep 17 00:00:00 2001 From: Eric Wright Date: Tue, 31 Oct 2023 21:48:32 -0400 Subject: [PATCH 47/47] MAGE-725 Ensure proper array casting in JS --- Block/Configuration.php | 2 +- Model/CategoryVersion/CategoryVersionAttribute.php | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Block/Configuration.php b/Block/Configuration.php index 697525bc3..d8b1af57a 100755 --- a/Block/Configuration.php +++ b/Block/Configuration.php @@ -280,7 +280,7 @@ public function getConfiguration() 'parentCategory' => $parentCategoryName, 'childCategories' => $childCategories, 'hasCategoryVersions' => $this->hasCategoryVersions(), - 'alternatePaths' => $this->getAlternatePaths($path), + 'alternatePaths' => array_values($this->getAlternatePaths($path)), 'url' => $this->getUrl('*/*/*', ['_use_rewrite' => true, '_forced_secure' => true]) ], 'showCatsNotIncludedInNavigation' => $config->showCatsNotIncludedInNavigation(), diff --git a/Model/CategoryVersion/CategoryVersionAttribute.php b/Model/CategoryVersion/CategoryVersionAttribute.php index e08cc8d14..0b2f7f143 100644 --- a/Model/CategoryVersion/CategoryVersionAttribute.php +++ b/Model/CategoryVersion/CategoryVersionAttribute.php @@ -82,12 +82,11 @@ public function getSearchFilters(int $storeId = null): array $storeId ??= $this->storeId; if (!$storeId) return []; - $values = array_map( + return array_map( function(CategoryVersionInterface $version) { return $version->getOldValue(); }, $this->getVersions($storeId) ); - return $values; } }