Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
AfterImportDataObserver.php
Go to the documentation of this file.
1 <?php
7 
11 use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory as CategoryCollectionFactory;
19 use Magento\UrlRewrite\Model\MergeDataProviderFactory;
24 use Magento\UrlRewrite\Service\V1\Data\UrlRewriteFactory;
25 
33 {
37  const URL_KEY_ATTRIBUTE_CODE = 'url_key';
38 
42  protected $storeViewService;
43 
47  protected $product;
48 
53 
57  protected $products = [];
58 
63 
67  protected $productCategories;
68 
72  protected $urlFinder;
73 
77  protected $storeManager;
78 
82  protected $urlPersist;
83 
87  protected $urlRewriteFactory;
88 
92  protected $import;
93 
98 
103 
108 
113 
117  protected $storesCache = [];
118 
122  protected $categoryCache = [];
123 
127  protected $websiteCache = [];
128 
133  'sku',
134  'url_key',
135  'url_path',
136  'name',
137  'visibility',
138  ];
139 
143  private $mergeDataProviderPrototype;
144 
150  private $categoryCollectionFactory;
151 
157  private $categoriesCache = [];
158 
172  public function __construct(
173  \Magento\Catalog\Model\ProductFactory $catalogProductFactory,
174  \Magento\CatalogUrlRewrite\Model\ObjectRegistryFactory $objectRegistryFactory,
176  \Magento\CatalogUrlRewrite\Service\V1\StoreViewService $storeViewService,
179  UrlRewriteFactory $urlRewriteFactory,
181  MergeDataProviderFactory $mergeDataProviderFactory = null,
182  CategoryCollectionFactory $categoryCollectionFactory = null
183  ) {
184  $this->urlPersist = $urlPersist;
185  $this->catalogProductFactory = $catalogProductFactory;
186  $this->objectRegistryFactory = $objectRegistryFactory;
187  $this->productUrlPathGenerator = $productUrlPathGenerator;
188  $this->storeViewService = $storeViewService;
189  $this->storeManager = $storeManager;
190  $this->urlRewriteFactory = $urlRewriteFactory;
191  $this->urlFinder = $urlFinder;
192  if (!isset($mergeDataProviderFactory)) {
193  $mergeDataProviderFactory = ObjectManager::getInstance()->get(MergeDataProviderFactory::class);
194  }
195  $this->mergeDataProviderPrototype = $mergeDataProviderFactory->create();
196  $this->categoryCollectionFactory = $categoryCollectionFactory ?:
197  ObjectManager::getInstance()->get(CategoryCollectionFactory::class);
198  }
199 
208  public function execute(Observer $observer)
209  {
210  $this->import = $observer->getEvent()->getAdapter();
211  if ($products = $observer->getEvent()->getBunch()) {
212  foreach ($products as $product) {
213  $this->_populateForUrlGeneration($product);
214  }
215  $productUrls = $this->generateUrls();
216  if ($productUrls) {
217  $this->urlPersist->replace($productUrls);
218  }
219  }
220  }
221 
230  protected function _populateForUrlGeneration($rowData)
231  {
232  $newSku = $this->import->getNewSku($rowData[ImportProduct::COL_SKU]);
233  if (empty($newSku) || !isset($newSku['entity_id'])) {
234  return null;
235  }
236  if ($this->import->getRowScope($rowData) == ImportProduct::SCOPE_STORE
237  && empty($rowData[self::URL_KEY_ATTRIBUTE_CODE])) {
238  return null;
239  }
240  $rowData['entity_id'] = $newSku['entity_id'];
241 
242  $product = $this->catalogProductFactory->create();
243  $product->setId($rowData['entity_id']);
244 
245  foreach ($this->vitalForGenerationFields as $field) {
246  if (isset($rowData[$field])) {
247  $product->setData($field, $rowData[$field]);
248  }
249  }
250 
251  $this->categoryCache[$rowData['entity_id']] = $this->import->getProductCategories($rowData['sku']);
252  $this->websiteCache[$rowData['entity_id']] = $this->import->getProductWebsites($rowData['sku']);
253  foreach ($this->websiteCache[$rowData['entity_id']] as $websiteId) {
254  if (!isset($this->websitesToStoreIds[$websiteId])) {
255  $this->websitesToStoreIds[$websiteId] = $this->storeManager->getWebsite($websiteId)->getStoreIds();
256  }
257  }
258 
259  $this->setStoreToProduct($product, $rowData);
260 
261  if ($this->isGlobalScope($product->getStoreId())) {
263  } else {
264  $this->addProductToImport($product, $product->getStoreId());
265  }
266  return $this;
267  }
268 
274  protected function setStoreToProduct(\Magento\Catalog\Model\Product $product, array $rowData)
275  {
276  if (!empty($rowData[ImportProduct::COL_STORE])
277  && ($storeId = $this->import->getStoreIdByCode($rowData[ImportProduct::COL_STORE]))
278  ) {
279  $product->setStoreId($storeId);
280  } elseif (!$product->hasData(\Magento\Catalog\Model\Product::STORE_ID)) {
281  $product->setStoreId(Store::DEFAULT_STORE_ID);
282  }
283  }
284 
292  protected function addProductToImport($product, $storeId)
293  {
294  if ($product->getVisibility() == (string)Visibility::getOptionArray()[Visibility::VISIBILITY_NOT_VISIBLE]) {
295  return $this;
296  }
297  if (!isset($this->products[$product->getId()])) {
298  $this->products[$product->getId()] = [];
299  }
300  $this->products[$product->getId()][$storeId] = $product;
301  return $this;
302  }
303 
310  protected function populateGlobalProduct($product)
311  {
312  foreach ($this->import->getProductWebsites($product->getSku()) as $websiteId) {
313  foreach ($this->websitesToStoreIds[$websiteId] as $storeId) {
314  $this->storesCache[$storeId] = true;
315  if (!$this->isGlobalScope($storeId)) {
316  $this->addProductToImport($product, $storeId);
317  }
318  }
319  }
320  return $this;
321  }
322 
328  protected function generateUrls()
329  {
330  $mergeDataProvider = clone $this->mergeDataProviderPrototype;
331  $mergeDataProvider->merge($this->canonicalUrlRewriteGenerate());
332  $mergeDataProvider->merge($this->categoriesUrlRewriteGenerate());
333  $mergeDataProvider->merge($this->currentUrlRewritesRegenerate());
334  $this->productCategories = null;
335 
336  unset($this->products);
337  $this->products = [];
338 
339  return $mergeDataProvider->getData();
340  }
341 
348  protected function isGlobalScope($storeId)
349  {
350  return null === $storeId || $storeId == Store::DEFAULT_STORE_ID;
351  }
352 
358  protected function canonicalUrlRewriteGenerate()
359  {
360  $urls = [];
361  foreach ($this->products as $productId => $productsByStores) {
362  foreach ($productsByStores as $storeId => $product) {
363  if ($this->productUrlPathGenerator->getUrlPath($product)) {
364  $urls[] = $this->urlRewriteFactory->create()
366  ->setEntityId($productId)
367  ->setRequestPath($this->productUrlPathGenerator->getUrlPathWithSuffix($product, $storeId))
368  ->setTargetPath($this->productUrlPathGenerator->getCanonicalUrlPath($product))
369  ->setStoreId($storeId);
370  }
371  }
372  }
373 
374  return $urls;
375  }
376 
382  protected function categoriesUrlRewriteGenerate()
383  {
384  $urls = [];
385  foreach ($this->products as $productId => $productsByStores) {
386  foreach ($productsByStores as $storeId => $product) {
387  foreach ($this->categoryCache[$productId] as $categoryId) {
388  $category = $this->getCategoryById($categoryId, $storeId);
389  if ($category->getParentId() == Category::TREE_ROOT_ID) {
390  continue;
391  }
392  $requestPath = $this->productUrlPathGenerator->getUrlPathWithSuffix($product, $storeId, $category);
393  $urls[] = $this->urlRewriteFactory->create()
395  ->setEntityId($productId)
396  ->setRequestPath($requestPath)
397  ->setTargetPath($this->productUrlPathGenerator->getCanonicalUrlPath($product, $category))
398  ->setStoreId($storeId)
399  ->setMetadata(['category_id' => $category->getId()]);
400  }
401  }
402  }
403  return $urls;
404  }
405 
411  protected function currentUrlRewritesRegenerate()
412  {
413  $currentUrlRewrites = $this->urlFinder->findAllByData(
414  [
415  UrlRewrite::STORE_ID => array_keys($this->storesCache),
416  UrlRewrite::ENTITY_ID => array_keys($this->products),
418  ]
419  );
420 
421  $urlRewrites = [];
422  foreach ($currentUrlRewrites as $currentUrlRewrite) {
423  $category = $this->retrieveCategoryFromMetadata($currentUrlRewrite);
424  if ($category === false) {
425  continue;
426  }
427  $url = $currentUrlRewrite->getIsAutogenerated()
428  ? $this->generateForAutogenerated($currentUrlRewrite, $category)
429  : $this->generateForCustom($currentUrlRewrite, $category);
430  $urlRewrites = array_merge($urlRewrites, $url);
431  }
432 
433  $this->product = null;
434  $this->productCategories = null;
435  return $urlRewrites;
436  }
437 
444  {
445  $storeId = $url->getStoreId();
446  $productId = $url->getEntityId();
447  if (isset($this->products[$productId][$storeId])) {
448  $product = $this->products[$productId][$storeId];
449  if (!$product->getData('save_rewrites_history')) {
450  return [];
451  }
452  $targetPath = $this->productUrlPathGenerator->getUrlPathWithSuffix($product, $storeId, $category);
453  if ($url->getRequestPath() === $targetPath) {
454  return [];
455  }
456  return [
457  $this->urlRewriteFactory->create()
459  ->setEntityId($productId)
460  ->setRequestPath($url->getRequestPath())
461  ->setTargetPath($targetPath)
462  ->setRedirectType(OptionProvider::PERMANENT)
463  ->setStoreId($storeId)
464  ->setDescription($url->getDescription())
465  ->setIsAutogenerated(0)
466  ->setMetadata($url->getMetadata())
467  ];
468  }
469  return [];
470  }
471 
477  protected function generateForCustom($url, $category)
478  {
479  $storeId = $url->getStoreId();
480  $productId = $url->getEntityId();
481  if (isset($this->products[$productId][$storeId])) {
482  $product = $this->products[$productId][$storeId];
483  $targetPath = $url->getRedirectType()
484  ? $this->productUrlPathGenerator->getUrlPathWithSuffix($product, $storeId, $category)
485  : $url->getTargetPath();
486  if ($url->getRequestPath() === $targetPath) {
487  return [];
488  }
489  return [
490  $this->urlRewriteFactory->create()
492  ->setEntityId($productId)
493  ->setRequestPath($url->getRequestPath())
494  ->setTargetPath($targetPath)
495  ->setRedirectType($url->getRedirectType())
496  ->setStoreId($storeId)
497  ->setDescription($url->getDescription())
498  ->setIsAutogenerated(0)
499  ->setMetadata($url->getMetadata())
500  ];
501  }
502  return [];
503  }
504 
509  protected function retrieveCategoryFromMetadata($url)
510  {
511  $metadata = $url->getMetadata();
512  if (isset($metadata['category_id'])) {
513  $category = $this->import->getCategoryProcessor()->getCategoryById($metadata['category_id']);
514  return $category === null ? false : $category;
515  }
516  return null;
517  }
518 
525  {
526  if (isset($this->acceptableCategories[$storeId]) &&
527  isset($this->acceptableCategories[$storeId][$category->getId()])) {
528  return $this->acceptableCategories[$storeId][$category->getId()];
529  }
530  $acceptable = false;
532  list(, $rootCategoryId) = $category->getParentIds();
533  $acceptable = ($rootCategoryId == $this->storeManager->getStore($storeId)->getRootCategoryId());
534  }
535  if (!isset($this->acceptableCategories[$storeId])) {
536  $this->acceptableCategories[$storeId] = [];
537  }
538  $this->acceptableCategories[$storeId][$category->getId()] = $acceptable;
539  return $acceptable;
540  }
541 
549  private function getCategoryById($categoryId, $storeId)
550  {
551  if (!isset($this->categoriesCache[$categoryId][$storeId])) {
553  $categoryCollection = $this->categoryCollectionFactory->create();
554  $categoryCollection->addIdFilter([$categoryId])
555  ->setStoreId($storeId)
556  ->addAttributeToSelect('name')
557  ->addAttributeToSelect('url_key')
558  ->addAttributeToSelect('url_path');
559  $this->categoriesCache[$categoryId][$storeId] = $categoryCollection->getFirstItem();
560  }
561 
562  return $this->categoriesCache[$categoryId][$storeId];
563  }
564 }
setStoreToProduct(\Magento\Catalog\Model\Product $product, array $rowData)
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
return false
Definition: gallery.phtml:36
__construct(\Magento\Catalog\Model\ProductFactory $catalogProductFactory, \Magento\CatalogUrlRewrite\Model\ObjectRegistryFactory $objectRegistryFactory, \Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator $productUrlPathGenerator, \Magento\CatalogUrlRewrite\Service\V1\StoreViewService $storeViewService, \Magento\Store\Model\StoreManagerInterface $storeManager, UrlPersistInterface $urlPersist, UrlRewriteFactory $urlRewriteFactory, UrlFinderInterface $urlFinder, MergeDataProviderFactory $mergeDataProviderFactory=null, CategoryCollectionFactory $categoryCollectionFactory=null)