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

20434 consider url rewrite when change product visibility attribute 2 3 #20774

Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\CatalogUrlRewrite\Observer;

use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Model\Product\Visibility;
use Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator;
use Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator;
use Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException;
use Magento\UrlRewrite\Model\UrlPersistInterface;
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;

/**
* Class ProductProcessUrlRewriteSavingObserver
*/
class ProcessUrlRewriteOnChangeProductVisibilityObserver implements ObserverInterface
{
/**
* @var CollectionFactory
*/
private $productCollectionFactory;

/**
* @var ProductUrlRewriteGenerator
*/
private $urlRewriteGenerator;

/**
* @var UrlPersistInterface
*/
private $urlPersist;

/**
* @var ProductUrlPathGenerator
*/
private $urlPathGenerator;

/**
* @param CollectionFactory $collectionFactory
* @param ProductUrlRewriteGenerator $urlRewriteGenerator
* @param UrlPersistInterface $urlPersist
* @param ProductUrlPathGenerator|null $urlPathGenerator
*/
public function __construct(
CollectionFactory $collectionFactory,
ProductUrlRewriteGenerator $urlRewriteGenerator,
UrlPersistInterface $urlPersist,
ProductUrlPathGenerator $urlPathGenerator
) {
$this->productCollectionFactory = $collectionFactory;
$this->urlRewriteGenerator = $urlRewriteGenerator;
$this->urlPersist = $urlPersist;
$this->urlPathGenerator = $urlPathGenerator;
}

/**
* Generate urls for UrlRewrites and save it in storage
*
* @param Observer $observer
* @return array
* @throws UrlAlreadyExistsException
*/
public function execute(Observer $observer)
{
$event = $observer->getEvent();
$attrData = $event->getAttributesData();
$productIds = $event->getProductIds();
$storeId = $event->getStoreId();
$visibility = $attrData[ProductInterface::VISIBILITY] ?? null;

if (!$visibility) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@VitaliyBoyko I don't really get this logic. URL Rewrites for invisible products should still be created so that they can be made visible at any moment without conflict.

Please update description with current/changed behavior.

Copy link
Contributor Author

@VitaliyBoyko VitaliyBoyko Feb 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @orlangur
I've updated the PR description. Hope it is more comprehensive now. You may also check bugs
#10725
#20434 for additional information.
Thank you!

return [$attrData, $productIds, $storeId];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The interface method (\Magento\Framework\Event\ObserverInterface::execute) is void. Why do you need to return this array?

}

$productCollection = $this->productCollectionFactory->create();
$productCollection->addAttributeToSelect(ProductInterface::VISIBILITY);
$productCollection->addAttributeToSelect('url_key');
$productCollection->addFieldToFilter(
'entity_id',
['in' => array_unique($productIds)]
);

foreach ($productCollection as $product) {
if ($visibility == Visibility::VISIBILITY_NOT_VISIBLE) {
$this->urlPersist->deleteByData(
[
UrlRewrite::ENTITY_ID => $product->getId(),
UrlRewrite::ENTITY_TYPE => ProductUrlRewriteGenerator::ENTITY_TYPE,
]
);
} elseif ($visibility !== Visibility::VISIBILITY_NOT_VISIBLE) {
$product->setVisibility($visibility);
$productUrlPath = $this->urlPathGenerator->getUrlPath($product);
$productUrlRewrite = $this->urlRewriteGenerator->generate($product);
$product->unsUrlPath();
$product->setUrlPath($productUrlPath);
$this->urlPersist->replace($productUrlRewrite);
}
}

return [$attrData, $productIds, $storeId];
}
}
3 changes: 3 additions & 0 deletions app/code/Magento/CatalogUrlRewrite/etc/events.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
<event name="catalog_product_save_after">
<observer name="process_url_rewrite_saving" instance="Magento\CatalogUrlRewrite\Observer\ProductProcessUrlRewriteSavingObserver"/>
</event>
<event name="catalog_product_attribute_update_before">
<observer name="process_url_rewrite_on_change_product_visibility" instance="Magento\CatalogUrlRewrite\Observer\ProcessUrlRewriteOnChangeProductVisibilityObserver"/>
</event>
<event name="catalog_category_save_before">
<observer name="category_url_path_autogeneration" instance="Magento\CatalogUrlRewrite\Observer\CategoryUrlPathAutogeneratorObserver"/>
</event>
Expand Down