Skip to content

Commit

Permalink
Merge pull request #858 from Nosto/feature/category-indexer
Browse files Browse the repository at this point in the history
Init category indexer
  • Loading branch information
supercid authored Feb 17, 2025
2 parents bb9e0b0 + c49c92a commit 5abb05c
Show file tree
Hide file tree
Showing 34 changed files with 1,228 additions and 95 deletions.
49 changes: 49 additions & 0 deletions Exception/ParentCategoryDisabledException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
/**
* Copyright (c) 2020, Nosto Solutions Ltd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @author Nosto Solutions Ltd <[email protected]>
* @copyright 2020 Nosto Solutions Ltd
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause
*
*/

namespace Nosto\Tagging\Exception;

use Nosto\NostoException;
use Throwable;

class ParentCategoryDisabledException extends NostoException
{
public function __construct($categoryId, $code = 0, Throwable $previous = null)
{
$message = "Parent category is disabled for category with id: " . $categoryId;
parent::__construct($message, $code, $previous);
}
}
7 changes: 0 additions & 7 deletions Model/Category/CollectionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
use Magento\Catalog\Model\ResourceModel\Category\Collection as MagentoCategoryCollection;
use Nosto\Tagging\Model\Category\Builder as NostoCategoryBuilder;
use Nosto\Tagging\Model\ResourceModel\Magento\Category\CollectionBuilder as CategoryCollectionBuilder;
use Nosto\Tagging\Model\Service\Product\Category\CategoryServiceInterface;
use Traversable;

/**
Expand All @@ -59,28 +58,22 @@ class CollectionBuilder
/** @var CategoryCollectionBuilder */
private CategoryCollectionBuilder $categoryCollectionBuilder;

/** @var CategoryServiceInterface */
private CategoryServiceInterface $categoryService;

/** @var NostoLogger */
private NostoLogger $logger;

/**
* Collection constructor.
* @param NostoCategoryBuilder $categoryBuilder
* @param CategoryCollectionBuilder $categoryCollectionBuilder
* @param CategoryServiceInterface $categoryService
* @param NostoLogger $logger
*/
public function __construct(
NostoCategoryBuilder $categoryBuilder,
CategoryCollectionBuilder $categoryCollectionBuilder,
CategoryServiceInterface $categoryService,
NostoLogger $logger
) {
$this->categoryBuilder = $categoryBuilder;
$this->categoryCollectionBuilder = $categoryCollectionBuilder;
$this->categoryService = $categoryService;
$this->logger = $logger;
}

Expand Down
116 changes: 116 additions & 0 deletions Model/Category/Repository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?php
/**
* Copyright (c) 2020, Nosto Solutions Ltd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @author Nosto Solutions Ltd <[email protected]>
* @copyright 2020 Nosto Solutions Ltd
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause
*
*/

namespace Nosto\Tagging\Model\Category;

use Magento\Catalog\Api\Data\CategoryInterface;
use Nosto\Tagging\Exception\ParentCategoryDisabledException;

/**
* Repository wrapper class for fetching categories
*/
class Repository
{
private array $parentCategoryIdCache = [];

/**
* Gets the parent category ID's for a given category
*
* @param CategoryInterface $category
* @return string[]|null
*
* @throws ParentCategoryDisabledException
*/
public function resolveParentCategoryIds(CategoryInterface $category): ?array
{
if ($this->getParentIdsFromCache($category)) {
return $this->getParentIdsFromCache($category);
}

if ($category->getLevel() < 1 && !$category->getIsActive()) {
throw new ParentCategoryDisabledException(
sprintf(
'Category with id %s is disabled',
$category->getId()
)
);
}

$parentCategoryIds = null;
if ($category->getLevel() >= 1) {
$parentCategoryIds = $this->getCategoryParentIds($category->getPath());
$this->saveParentIdsToCache($category, $parentCategoryIds);
}

return $parentCategoryIds;
}

/**
* Get Parent Category IDS
*
* @param string $path
* @return array
*/
private function getCategoryParentIds(string $path): array
{
$parentCategories = explode('/', $path);
array_pop($parentCategories);
return $parentCategories;
}

/**
* Get parent ids from cache. Return null if the cache is not available
*
* @param CategoryInterface $category
* @return string[]|null
*/
private function getParentIdsFromCache(CategoryInterface $category)
{
return $this->parentCategoryIdCache[$category->getId()] ?? null;
}

/**
* Saves the parents category ids to internal cache to avoid redundant
* database queries
*
* @param CategoryInterface $category
* @param string[] $parentCategoryIds
*/
private function saveParentIdsToCache(CategoryInterface $category, array $parentCategoryIds)
{
$this->parentCategoryIdCache[$category->getId()] = $parentCategoryIds;
}
}
2 changes: 1 addition & 1 deletion Model/Indexer/AbstractIndexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
use Nosto\Tagging\Helper\Scope as NostoHelperScope;
use Nosto\Tagging\Logger\Logger as NostoLogger;
use Nosto\Tagging\Model\Indexer\Dimensions\AbstractDimensionModeConfiguration as DimensionModeConfiguration;
use Nosto\Tagging\Model\Indexer\Dimensions\ModeSwitcherInterface;
use Nosto\Tagging\Model\Indexer\Dimensions\ModeSwitcher\ModeSwitcherInterface;
use Nosto\Tagging\Model\Indexer\Dimensions\StoreDimensionProvider;
use Nosto\Tagging\Model\Service\Indexer\IndexerStatusServiceInterface;
use Nosto\Tagging\Util\Benchmark;
Expand Down
160 changes: 160 additions & 0 deletions Model/Indexer/CategoryIndexer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<?php
/**
* Copyright (c) 2020, Nosto Solutions Ltd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @author Nosto Solutions Ltd <[email protected]>
* @copyright 2020 Nosto Solutions Ltd
* @license http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause
*
*/

namespace Nosto\Tagging\Model\Indexer;

use Exception;
use Magento\Indexer\Model\ProcessManager;
use Magento\Store\Model\App\Emulation;
use Magento\Store\Model\Store;
use Nosto\NostoException;
use Nosto\Tagging\Helper\Scope as NostoHelperScope;
use Nosto\Tagging\Logger\Logger as NostoLogger;
use Nosto\Tagging\Model\Indexer\Dimensions\ModeSwitcher\ModeSwitcher as CategoryModeSwitcher;
use Nosto\Tagging\Model\Indexer\Dimensions\ModeSwitcher\ModeSwitcherInterface;
use Nosto\Tagging\Model\Indexer\Dimensions\StoreDimensionProvider;
use Nosto\Tagging\Model\ResourceModel\Magento\Category\Collection as CategoryCollection;
use Nosto\Tagging\Model\ResourceModel\Magento\Category\CollectionBuilder;
use Nosto\Tagging\Model\Service\Indexer\IndexerStatusServiceInterface;
use Nosto\Tagging\Model\Service\Update\CategoryUpdateService;
use Symfony\Component\Console\Input\InputInterface;

/**
* Class CategoryIndexer
* Fetches category ID's from CL tables and create entries in the message queue
*/
class CategoryIndexer extends AbstractIndexer
{
public const INDEXER_ID = 'nosto_index_category';

/** @var CategoryUpdateService */
private CategoryUpdateService $categoryUpdateService;

/** @var CategoryModeSwitcher */
private CategoryModeSwitcher $modeSwitcher;

/** @var CollectionBuilder */
private CollectionBuilder $categoryCollectionBuilder;

/**
* Constructor.
* @param NostoHelperScope $nostoHelperScope
* @param CategoryUpdateService $categoryUpdateService
* @param NostoLogger $logger
* @param CollectionBuilder $categoryCollectionBuilder
* @param CategoryModeSwitcher $modeSwitcher
* @param StoreDimensionProvider $dimensionProvider
* @param Emulation $storeEmulation
* @param ProcessManager $processManager
* @param InputInterface $input
* @param IndexerStatusServiceInterface $indexerStatusService
*/
public function __construct(
NostoHelperScope $nostoHelperScope,
CategoryUpdateService $categoryUpdateService,
NostoLogger $logger,
CollectionBuilder $categoryCollectionBuilder,
CategoryModeSwitcher $modeSwitcher,
StoreDimensionProvider $dimensionProvider,
Emulation $storeEmulation,
ProcessManager $processManager,
InputInterface $input,
IndexerStatusServiceInterface $indexerStatusService
) {
$this->categoryUpdateService = $categoryUpdateService;
$this->modeSwitcher = $modeSwitcher;
$this->categoryCollectionBuilder = $categoryCollectionBuilder;

parent::__construct(
$nostoHelperScope,
$logger,
$dimensionProvider,
$storeEmulation,
$input,
$indexerStatusService,
$processManager
);
}

/**
* @inheritDoc
*/
public function getModeSwitcher(): ModeSwitcherInterface
{
return $this->modeSwitcher;
}

/**
* @inheritDoc
* @throws NostoException
* @throws Exception
*/
public function doIndex(Store $store, array $ids = [])
{
$collection = $this->getCollection($store, $ids);

$this->categoryUpdateService->addCollectionToUpdateMessageQueue(
$collection,
$store
);
}

/**
* @inheritDoc
*/
public function getIndexerId(): string
{
return self::INDEXER_ID;
}

/**
* @param Store $store
* @param array $ids
* @return CategoryCollection
*/
public function getCollection(Store $store, array $ids = []) : CategoryCollection
{
$this->categoryCollectionBuilder->initDefault($store);

if (!empty($ids)) {
$this->categoryCollectionBuilder->withIds($ids);
} else {
$this->categoryCollectionBuilder->withStore($store);
}

return $this->categoryCollectionBuilder->build();
}
}
Loading

0 comments on commit 5abb05c

Please sign in to comment.