Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/mage 725 - category versioning #1434

Open
wants to merge 52 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
416df01
Merge pull request #1393 from algolia/release/3.11.0-beta
mohitalgolia Aug 4, 2023
ac7bd8e
Merge pull request #1413 from algolia/develop
mohitalgolia Sep 26, 2023
c8c9f33
Merge pull request #1415 from algolia/develop
mohitalgolia Sep 26, 2023
fc882c0
Set arbitrary limit to override default for hierarchicalMenu to preve…
cammonro Oct 4, 2023
dd89eb8
INTEG-707 Simplify application of root category
cammonro Oct 13, 2023
3476bde
MAGE-773
cammonro Oct 16, 2023
3ade12f
MAGE-773 Remove hard coded separator
cammonro Oct 16, 2023
ec758f9
MAGE-725 Add new db schema for category change tracking
cammonro Oct 17, 2023
10a3781
MAGE-725 Fix data types
cammonro Oct 17, 2023
2ee3793
MAGE-725 Add foreign key relationships
cammonro Oct 17, 2023
fd5d298
MAGE-725 Add repository to block
cammonro Oct 19, 2023
4562614
MAGE-725 Tweak database schema
cammonro Oct 19, 2023
e60f0c2
MAGE-725 Add interfaces
cammonro Oct 19, 2023
1744b0d
MAGE-725 Add concrete model classes for category versions
cammonro Oct 19, 2023
bcbeb81
MAGE-725 Add category version repository base implementation
cammonro Oct 19, 2023
afdd504
MAGE-725 Stub out attribute interface
cammonro Oct 19, 2023
786c2ca
MAGE-725 Fix typo in interface return type
cammonro Oct 19, 2023
a657bfb
MAGE-725 Define preferences for category version interfaces
cammonro Oct 19, 2023
556458b
MAGE-725 Add category version attribute preference
cammonro Oct 19, 2023
f2d4ae5
MAGE-725 Stub out extension attribute and plugin for retrieval
cammonro Oct 19, 2023
ebe1777
MAGE-725 Add feature flag for category version tracking
cammonro Oct 19, 2023
5262407
MAGE-725 Simplify change check logic
cammonro Oct 30, 2023
5028da5
MAGE-725 Stub category version logger
cammonro Oct 30, 2023
3017f15
MAGE-725 Get applicable stores for log
cammonro Oct 31, 2023
a4f12f0
MAGE-725 Add logic to not log change for overridden category
cammonro Oct 31, 2023
f8994a7
MAGE-725 Add version interface attributes
cammonro Oct 31, 2023
4f48d64
MAGE-725 Save version to change log
cammonro Oct 31, 2023
e1416e3
MAGE-725 Declare exceptions
cammonro Oct 31, 2023
29b19d0
MAGE-725 Refactor to log previous category hierarchy by store scope
cammonro Oct 31, 2023
2c6739b
MAGE-725 Add support to category version repo for SearchCriteria
cammonro Oct 31, 2023
68bf8e9
MAGE-725 deduplicate change log insert
cammonro Oct 31, 2023
2d791e8
MAGE-725 Add logger to afterSave plugin
cammonro Oct 31, 2023
625d4e8
MAGE-725 Update modified timestamp
cammonro Oct 31, 2023
97ac211
MAGE-725 Reformat code
cammonro Oct 31, 2023
bb6d9a4
MAGE-725 Fix hierarchy path bug
cammonro Oct 31, 2023
2950225
MAGE-725 Add category move plugin
cammonro Oct 31, 2023
26e2d2d
MAGE-725 Introduce discrete move logging method due to alternate stor…
cammonro Oct 31, 2023
e9f7e04
MAGE-725 Relocate constants for API layer
cammonro Oct 31, 2023
8174850
MAGE-725 Remove path monitoring from save plugin (it never changes in…
cammonro Oct 31, 2023
2abeccf
MAGE-725 Adopt core Magento naming convention for field constants
cammonro Oct 31, 2023
3b500f0
MAGE-725 Bug fix for save operations from multiple admin tabs (catego…
cammonro Oct 31, 2023
917d1d9
MAGE-791 Add alt registry for current category
cammonro Oct 31, 2023
25a0051
MAGE-791 Load current category via new custom registry
cammonro Oct 31, 2023
b2f9592
Merge branch 'develop' into feature/MAGE-725
cammonro Oct 31, 2023
dc03078
Merge branch 'feature/MAGE-791' into feature/MAGE-725
cammonro Oct 31, 2023
3a119e3
MAGE-725 Add state to category version extension attribute
cammonro Oct 31, 2023
a687f26
MAGE-725 Implement boolean check for available version plus search cr…
cammonro Oct 31, 2023
ad9e401
MAGE-725 Add alternate search filter extraction logic
cammonro Oct 31, 2023
9f10484
MAGE-725 Add multi filter support to InstantSearch based on category …
cammonro Nov 1, 2023
3e4c88a
MAGE-725 Fix dedupe logic on category version logging
cammonro Nov 1, 2023
5f1d8af
MAGE-725 Adjust path building to pull correct scope for parent catego…
cammonro Nov 1, 2023
9fa3970
MAGE-725 Ensure proper array casting in JS
cammonro Nov 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions Api/CategoryVersionLoggerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Algolia\AlgoliaSearch\Api;

use Magento\Catalog\Model\Category;
use Magento\Framework\Exception\AlreadyExistsException;
use Magento\Framework\Exception\NoSuchEntityException;

interface CategoryVersionLoggerInterface
{
/**
* Category save events are store scope sensitive.
*
* @param Category $category
* @param int $storedId
* @return void
* @throws NoSuchEntityException
* @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;
}
37 changes: 37 additions & 0 deletions Api/CategoryVersionRepositoryInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

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
{
/**
* @param int $id
* @return CategoryVersionInterface
* @throws NoSuchEntityException
*/
public function getById(int $id): CategoryVersionInterface;

/**
* @return CategoryVersionInterface
*/
public function getNew(): CategoryVersionInterface;

/**
* @param CategoryVersionInterface $version
* @return CategoryVersionInterface
* @throws AlreadyExistsException
*/
public function save(CategoryVersionInterface $version): CategoryVersionInterface;

/**
* @param SearchCriteriaInterface|null $searchCriteria
* @return CategoryVersionSearchResultsInterface
*/
public function getList(SearchCriteriaInterface $searchCriteria = null): CategoryVersionSearchResultsInterface;
}
36 changes: 36 additions & 0 deletions Api/Data/CategoryVersionAttributeInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Algolia\AlgoliaSearch\Api\Data;

use Algolia\AlgoliaSearch\Api\Data\CategoryVersionInterface;

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(int $storeId = null): bool;

/**
* Get all versions of this category
* @param int|null $storeId
* @return CategoryVersionInterface[]
*/
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(int $storeId = null): array;

}
33 changes: 33 additions & 0 deletions Api/Data/CategoryVersionInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Algolia\AlgoliaSearch\Api\Data;

use Magento\Framework\Api\ExtensibleDataInterface;

interface CategoryVersionInterface extends ExtensibleDataInterface
{
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;

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;

public function getUpdatedAt(): string;
public function setUpdatedAt(?string $val): CategoryVersionInterface;

}
24 changes: 24 additions & 0 deletions Api/Data/CategoryVersionSearchResultsInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Algolia\AlgoliaSearch\Api\Data;

use Magento\Framework\Api\SearchResultsInterface;

interface CategoryVersionSearchResultsInterface extends SearchResultsInterface
{

/**
* Get list of category versions
*
* @return CategoryVersionInterface[]
*/
public function getItems();

/**
* Set category version list
*
* @param CategoryVersionInterface[] $items
* @return $this
*/
public function setItems(array $items);
}
10 changes: 9 additions & 1 deletion Block/Algolia.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -25,6 +26,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
{
Expand Down Expand Up @@ -97,6 +99,9 @@ class Algolia extends Template implements CollectionDataSourceInterface
*/
protected $date;

/** @var CurrentCategory */
protected CurrentCategory $currentCategory;

protected $priceKey;

/**
Expand All @@ -119,6 +124,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,
Expand All @@ -139,6 +145,7 @@ public function __construct(
PersonalizationHelper $personalizationHelper,
CheckoutSession $checkoutSession,
DateTime $date,
CurrentCategory $currentCategory,
array $data = []
) {
$this->config = $config;
Expand All @@ -158,6 +165,7 @@ public function __construct(
$this->personalizationHelper = $personalizationHelper;
$this->checkoutSession = $checkoutSession;
$this->date = $date;
$this->currentCategory = $currentCategory;

parent::__construct($context, $data);
}
Expand Down Expand Up @@ -255,7 +263,7 @@ public function getStoreId()

public function getCurrentCategory()
{
return $this->registry->registry('current_category');
return $this->currentCategory->get();
}

/** @return Product */
Expand Down
20 changes: 20 additions & 0 deletions Block/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ public function getConfiguration()
if ($config->isInstantEnabled()
&& $config->replaceCategories()
&& $request->getControllerName() === 'category') {

$category = $this->getCurrentCategory();

if ($category && $category->getDisplayMode() !== 'PAGE') {
Expand Down Expand Up @@ -278,6 +279,8 @@ public function getConfiguration()
'level' => $level,
'parentCategory' => $parentCategoryName,
'childCategories' => $childCategories,
'hasCategoryVersions' => $this->hasCategoryVersions(),
'alternatePaths' => array_values($this->getAlternatePaths($path)),
'url' => $this->getUrl('*/*/*', ['_use_rewrite' => true, '_forced_secure' => true])
],
'showCatsNotIncludedInNavigation' => $config->showCatsNotIncludedInNavigation(),
Expand Down Expand Up @@ -427,4 +430,21 @@ protected function getLandingPageConfiguration()
{
return $this->isLandingPage() ? $this->getCurrentLandingPage()->getConfiguration() : json_encode([]);
}

protected function hasCategoryVersions(): bool
{
if (!$this->config->isCategoryVersionTrackingEnabled()) return false;
return (bool) $this->getCurrentCategory()->getExtensionAttributes()->getAlgoliaCategoryVersions()?->hasVersions();
}

protected function getAlternatePaths(string $mainPath): array
{
if (!$this->config->isCategoryVersionTrackingEnabled() || !$this->hasCategoryVersions()) return [];
return array_unique(
array_merge(
[$mainPath],
$this->getCurrentCategory()->getExtensionAttributes()->getAlgoliaCategoryVersions()->getSearchFilters()
)
);
}
}
10 changes: 10 additions & 0 deletions Helper/ConfigHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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
Expand Down
77 changes: 77 additions & 0 deletions Model/CategoryVersion.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

namespace Algolia\AlgoliaSearch\Model;

use Algolia\AlgoliaSearch\Api\Data\CategoryVersionInterface;
use Magento\Framework\DataObject\IdentityInterface;
use Magento\Framework\Model\AbstractExtensibleModel;

class CategoryVersion extends AbstractExtensibleModel implements IdentityInterface, CategoryVersionInterface
{
const CACHE_TAG = 'algoliasearch_category_version';
protected $_cacheTag = self::CACHE_TAG;
protected $_eventPrefix = 'algoliasearch_category_version';

protected function _construct()
{
$this->_init(ResourceModel\CategoryVersion::class);
}

/**
* @inheritDoc
*/
public function getIdentities(): array
{
return [self::CACHE_TAG . '_' . $this->getId()];
}

public function getCategoryId(): int
{
return $this->getData(CategoryVersionInterface::KEY_CATEGORY_ID);
}

public function setCategoryId(int $categoryId): CategoryVersionInterface
{
return $this->setData(CategoryVersionInterface::KEY_CATEGORY_ID, $categoryId);
}

public function getStoreId(): int
{
return $this->getData(CategoryVersionInterface::KEY_STORE_ID);
}

public function setStoreId(int $storeId): CategoryVersionInterface
{
return $this->setData(CategoryVersionInterface::KEY_STORE_ID, $storeId);
}

public function getOldValue(): string
{
return $this->getData(CategoryVersionInterface::KEY_OLD_VALUE);
}

public function setOldValue(string $val): CategoryVersionInterface
{
return $this->setData(CategoryVersionInterface::KEY_OLD_VALUE, $val);
}

public function getNewValue(): string
{
return $this->getData(CategoryVersionInterface::KEY_NEW_VALUE);
}

public function setNewValue(string $val): CategoryVersionInterface
{
return $this->setData(CategoryVersionInterface::KEY_NEW_VALUE, $val);
}

public function getUpdatedAt(): string
{
return $this->getData(CategoryVersionInterface::KEY_UPDATED_AT);
}

public function setUpdatedAt(?string $val): CategoryVersionInterface
{
return $this->setData(CategoryVersionInterface::KEY_UPDATED_AT, $val);
}
}
Loading