| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 | 
							- <?php
 
- /**
 
-  * Copyright © Magento, Inc. All rights reserved.
 
-  * See COPYING.txt for license details.
 
-  */
 
- declare(strict_types=1);
 
- namespace Magento\CatalogUrlRewrite\Observer;
 
- use Magento\Catalog\Model\Product;
 
- use Magento\Catalog\Model\Category;
 
- use Magento\Catalog\Model\ResourceModel\Product\Collection;
 
- use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
 
- use Magento\CatalogUrlRewrite\Model\Category\ChildrenCategoriesProvider;
 
- use Magento\CatalogUrlRewrite\Model\CategoryProductUrlPathGenerator;
 
- use Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator;
 
- use Magento\CatalogUrlRewrite\Model\ProductScopeRewriteGenerator;
 
- use Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator;
 
- use Magento\Framework\App\ObjectManager;
 
- use Magento\Framework\Serialize\Serializer\Json;
 
- use Magento\UrlRewrite\Model\MergeDataProvider;
 
- use Magento\UrlRewrite\Model\MergeDataProviderFactory;
 
- use Magento\UrlRewrite\Model\UrlPersistInterface;
 
- use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
 
- /**
 
-  * Class for management url rewrites.
 
-  *
 
-  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 
-  */
 
- class UrlRewriteHandler
 
- {
 
-     /**
 
-      * @var ChildrenCategoriesProvider
 
-      */
 
-     protected $childrenCategoriesProvider;
 
-     /**
 
-      * @var CategoryUrlRewriteGenerator
 
-      */
 
-     protected $categoryUrlRewriteGenerator;
 
-     /**
 
-      * @var ProductUrlRewriteGenerator
 
-      */
 
-     protected $productUrlRewriteGenerator;
 
-     /**
 
-      * @var UrlPersistInterface
 
-      */
 
-     protected $urlPersist;
 
-     /**
 
-      * @var array
 
-      */
 
-     protected $isSkippedProduct;
 
-     /**
 
-      * @var CollectionFactory
 
-      */
 
-     protected $productCollectionFactory;
 
-     /**
 
-      * @var CategoryProductUrlPathGenerator
 
-      */
 
-     private $categoryBasedProductRewriteGenerator;
 
-     /**
 
-      * @var MergeDataProvider
 
-      */
 
-     private $mergeDataProviderPrototype;
 
-     /**
 
-      * @var Json
 
-      */
 
-     private $serializer;
 
-     /**
 
-      * @var ProductScopeRewriteGenerator
 
-      */
 
-     private $productScopeRewriteGenerator;
 
-     /**
 
-      * @param ChildrenCategoriesProvider $childrenCategoriesProvider
 
-      * @param CategoryUrlRewriteGenerator $categoryUrlRewriteGenerator
 
-      * @param ProductUrlRewriteGenerator $productUrlRewriteGenerator
 
-      * @param UrlPersistInterface $urlPersist
 
-      * @param CollectionFactory $productCollectionFactory
 
-      * @param CategoryProductUrlPathGenerator $categoryBasedProductRewriteGenerator
 
-      * @param MergeDataProviderFactory|null $mergeDataProviderFactory
 
-      * @param Json|null $serializer
 
-      * @param ProductScopeRewriteGenerator|null $productScopeRewriteGenerator
 
-      */
 
-     public function __construct(
 
-         ChildrenCategoriesProvider $childrenCategoriesProvider,
 
-         CategoryUrlRewriteGenerator $categoryUrlRewriteGenerator,
 
-         ProductUrlRewriteGenerator $productUrlRewriteGenerator,
 
-         UrlPersistInterface $urlPersist,
 
-         CollectionFactory $productCollectionFactory,
 
-         CategoryProductUrlPathGenerator $categoryBasedProductRewriteGenerator,
 
-         MergeDataProviderFactory $mergeDataProviderFactory = null,
 
-         Json $serializer = null,
 
-         ProductScopeRewriteGenerator $productScopeRewriteGenerator = null
 
-     ) {
 
-         $this->childrenCategoriesProvider = $childrenCategoriesProvider;
 
-         $this->categoryUrlRewriteGenerator = $categoryUrlRewriteGenerator;
 
-         $this->productUrlRewriteGenerator = $productUrlRewriteGenerator;
 
-         $this->urlPersist = $urlPersist;
 
-         $this->productCollectionFactory = $productCollectionFactory;
 
-         $this->categoryBasedProductRewriteGenerator = $categoryBasedProductRewriteGenerator;
 
-         $objectManager = ObjectManager::getInstance();
 
-         $mergeDataProviderFactory = $mergeDataProviderFactory ?: $objectManager->get(MergeDataProviderFactory::class);
 
-         $this->mergeDataProviderPrototype = $mergeDataProviderFactory->create();
 
-         $this->serializer = $serializer ?: $objectManager->get(Json::class);
 
-         $this->productScopeRewriteGenerator = $productScopeRewriteGenerator
 
-             ?: $objectManager->get(ProductScopeRewriteGenerator::class);
 
-     }
 
-     /**
 
-      * Generates URL rewrites for products assigned to category.
 
-      *
 
-      * @param Category $category
 
-      * @return array
 
-      */
 
-     public function generateProductUrlRewrites(Category $category): array
 
-     {
 
-         $mergeDataProvider = clone $this->mergeDataProviderPrototype;
 
-         $this->isSkippedProduct[$category->getEntityId()] = [];
 
-         $saveRewriteHistory = (bool)$category->getData('save_rewrites_history');
 
-         $storeId = (int)$category->getStoreId();
 
-         if ($category->getChangedProductIds()) {
 
-             $this->generateChangedProductUrls($mergeDataProvider, $category, $storeId, $saveRewriteHistory);
 
-         } else {
 
-             $mergeDataProvider->merge(
 
-                 $this->getCategoryProductsUrlRewrites(
 
-                     $category,
 
-                     $storeId,
 
-                     $saveRewriteHistory,
 
-                     $category->getEntityId()
 
-                 )
 
-             );
 
-         }
 
-         foreach ($this->childrenCategoriesProvider->getChildren($category, true) as $childCategory) {
 
-             $mergeDataProvider->merge(
 
-                 $this->getCategoryProductsUrlRewrites(
 
-                     $childCategory,
 
-                     $storeId,
 
-                     $saveRewriteHistory,
 
-                     $category->getEntityId()
 
-                 )
 
-             );
 
-         }
 
-         return $mergeDataProvider->getData();
 
-     }
 
-     /**
 
-      * Update product url rewrites for changed product.
 
-      *
 
-      * @param Category $category
 
-      * @return array
 
-      */
 
-     public function updateProductUrlRewritesForChangedProduct(Category $category): array
 
-     {
 
-         $mergeDataProvider = clone $this->mergeDataProviderPrototype;
 
-         $this->isSkippedProduct[$category->getEntityId()] = [];
 
-         $saveRewriteHistory = (bool)$category->getData('save_rewrites_history');
 
-         $storeIds = $this->getCategoryStoreIds($category);
 
-         if ($category->getChangedProductIds()) {
 
-             foreach ($storeIds as $storeId) {
 
-                 $this->generateChangedProductUrls($mergeDataProvider, $category, (int)$storeId, $saveRewriteHistory);
 
-             }
 
-         }
 
-         return $mergeDataProvider->getData();
 
-     }
 
-     /**
 
-      * Delete category rewrites for children.
 
-      *
 
-      * @param Category $category
 
-      * @return void
 
-      */
 
-     public function deleteCategoryRewritesForChildren(Category $category)
 
-     {
 
-         $categoryIds = $this->childrenCategoriesProvider->getChildrenIds($category, true);
 
-         $categoryIds[] = $category->getId();
 
-         foreach ($categoryIds as $categoryId) {
 
-             $this->urlPersist->deleteByData(
 
-                 [
 
-                     UrlRewrite::ENTITY_ID =>
 
-                         $categoryId,
 
-                     UrlRewrite::ENTITY_TYPE =>
 
-                         CategoryUrlRewriteGenerator::ENTITY_TYPE,
 
-                 ]
 
-             );
 
-             $this->urlPersist->deleteByData(
 
-                 [
 
-                     UrlRewrite::METADATA =>
 
-                         $this->serializer->serialize(['category_id' => $categoryId]),
 
-                     UrlRewrite::ENTITY_TYPE =>
 
-                         ProductUrlRewriteGenerator::ENTITY_TYPE,
 
-                 ]
 
-             );
 
-         }
 
-     }
 
-     /**
 
-      * Get category products url rewrites.
 
-      *
 
-      * @param Category $category
 
-      * @param int $storeId
 
-      * @param bool $saveRewriteHistory
 
-      * @param int|null $rootCategoryId
 
-      * @return array
 
-      */
 
-     private function getCategoryProductsUrlRewrites(
 
-         Category $category,
 
-         $storeId,
 
-         $saveRewriteHistory,
 
-         $rootCategoryId = null
 
-     ) {
 
-         $mergeDataProvider = clone $this->mergeDataProviderPrototype;
 
-         /** @var Collection $productCollection */
 
-         $productCollection = $this->productCollectionFactory->create();
 
-         $productCollection->addCategoriesFilter(['eq' => [$category->getEntityId()]])
 
-             ->setStoreId($storeId)
 
-             ->addAttributeToSelect('name')
 
-             ->addAttributeToSelect('visibility')
 
-             ->addAttributeToSelect('url_key')
 
-             ->addAttributeToSelect('url_path');
 
-         foreach ($productCollection as $product) {
 
-             if (isset($this->isSkippedProduct[$category->getEntityId()]) &&
 
-                 in_array($product->getId(), $this->isSkippedProduct[$category->getEntityId()])
 
-             ) {
 
-                 continue;
 
-             }
 
-             $this->isSkippedProduct[$category->getEntityId()][] = $product->getId();
 
-             $product->setStoreId($storeId);
 
-             $product->setData('save_rewrites_history', $saveRewriteHistory);
 
-             $mergeDataProvider->merge(
 
-                 $this->categoryBasedProductRewriteGenerator->generate($product, $rootCategoryId)
 
-             );
 
-         }
 
-         return $mergeDataProvider->getData();
 
-     }
 
-     /**
 
-      * Generates product URL rewrites.
 
-      *
 
-      * @param MergeDataProvider $mergeDataProvider
 
-      * @param Category $category
 
-      * @param int $storeId
 
-      * @param bool $saveRewriteHistory
 
-      * @return void
 
-      */
 
-     private function generateChangedProductUrls(
 
-         MergeDataProvider $mergeDataProvider,
 
-         Category $category,
 
-         int $storeId,
 
-         bool $saveRewriteHistory
 
-     ) {
 
-         $this->isSkippedProduct[$category->getEntityId()] = $category->getAffectedProductIds();
 
-         $categoryStoreIds = [$storeId];
 
-         // If category is changed in the Global scope when need to regenerate product URL rewrites for all other scopes.
 
-         if ($this->productScopeRewriteGenerator->isGlobalScope($storeId)) {
 
-             $categoryStoreIds = $this->getCategoryStoreIds($category);
 
-         }
 
-         foreach ($categoryStoreIds as $categoryStoreId) {
 
-             /* @var Collection $collection */
 
-             $collection = $this->productCollectionFactory->create()
 
-                 ->setStoreId($categoryStoreId)
 
-                 ->addIdFilter($category->getAffectedProductIds())
 
-                 ->addAttributeToSelect('visibility')
 
-                 ->addAttributeToSelect('name')
 
-                 ->addAttributeToSelect('url_key')
 
-                 ->addAttributeToSelect('url_path');
 
-             $collection->setPageSize(1000);
 
-             $pageCount = $collection->getLastPageNumber();
 
-             $currentPage = 1;
 
-             while ($currentPage <= $pageCount) {
 
-                 $collection->setCurPage($currentPage);
 
-                 foreach ($collection as $product) {
 
-                     $product->setData('save_rewrites_history', $saveRewriteHistory);
 
-                     $product->setStoreId($categoryStoreId);
 
-                     $mergeDataProvider->merge(
 
-                         $this->productUrlRewriteGenerator->generate($product, $category->getEntityId())
 
-                     );
 
-                 }
 
-                 $collection->clear();
 
-                 $currentPage++;
 
-             }
 
-         }
 
-     }
 
-     /**
 
-      * Gets category store IDs without Global Store.
 
-      *
 
-      * @param Category $category
 
-      * @return array
 
-      */
 
-     private function getCategoryStoreIds(Category $category): array
 
-     {
 
-         $ids = $category->getStoreIds();
 
-         return array_filter($ids);
 
-     }
 
- }
 
 
  |