55 */
66namespace Magento \CatalogUrlRewrite \Observer ;
77
8+ use Magento \Catalog \Api \Data \ProductInterface ;
89use Magento \Catalog \Model \Product ;
10+ use Magento \Catalog \Model \Product \Visibility ;
11+ use Magento \Catalog \Model \ResourceModel \Product \CollectionFactory ;
12+ use Magento \CatalogUrlRewrite \Model \ProductScopeRewriteGenerator ;
913use Magento \CatalogUrlRewrite \Model \ProductUrlPathGenerator ;
1014use Magento \CatalogUrlRewrite \Model \ProductUrlRewriteGenerator ;
11- use Magento \Framework \App \ObjectManager ;
15+ use Magento \Framework \Event \Observer ;
16+ use Magento \UrlRewrite \Model \Exception \UrlAlreadyExistsException ;
17+ use Magento \UrlRewrite \Model \Storage \DeleteEntitiesFromStores ;
1218use Magento \UrlRewrite \Model \UrlPersistInterface ;
1319use Magento \Framework \Event \ObserverInterface ;
20+ use Magento \Store \Model \StoreManagerInterface ;
1421
1522/**
1623 * Class ProductProcessUrlRewriteSavingObserver
24+ *
25+ * Observer to update the Rewrite URLs for a product.
26+ * This observer is triggered on the save function when making changes
27+ * to the products website on the Product Edit page.
1728 */
1829class ProductProcessUrlRewriteSavingObserver implements ObserverInterface
1930{
@@ -32,30 +43,62 @@ class ProductProcessUrlRewriteSavingObserver implements ObserverInterface
3243 */
3344 private $ productUrlPathGenerator ;
3445
46+ /**
47+ * @var StoreManagerInterface
48+ */
49+ private $ storeManager ;
50+
51+ /**
52+ * @var ProductScopeRewriteGenerator
53+ */
54+ private $ productScopeRewriteGenerator ;
55+
56+ /**
57+ * @var DeleteEntitiesFromStores
58+ */
59+ private $ deleteEntitiesFromStores ;
60+
61+ /**
62+ * @var CollectionFactory
63+ */
64+ private $ collectionFactory ;
65+
3566 /**
3667 * @param ProductUrlRewriteGenerator $productUrlRewriteGenerator
3768 * @param UrlPersistInterface $urlPersist
38- * @param ProductUrlPathGenerator|null $productUrlPathGenerator
69+ * @param ProductUrlPathGenerator $productUrlPathGenerator
70+ * @param StoreManagerInterface $storeManager
71+ * @param ProductScopeRewriteGenerator $productScopeRewriteGenerator
72+ * @param DeleteEntitiesFromStores $deleteEntitiesFromStores
73+ * @param CollectionFactory $collectionFactory
3974 */
4075 public function __construct (
4176 ProductUrlRewriteGenerator $ productUrlRewriteGenerator ,
4277 UrlPersistInterface $ urlPersist ,
43- ProductUrlPathGenerator $ productUrlPathGenerator = null
78+ ProductUrlPathGenerator $ productUrlPathGenerator ,
79+ StoreManagerInterface $ storeManager ,
80+ ProductScopeRewriteGenerator $ productScopeRewriteGenerator ,
81+ DeleteEntitiesFromStores $ deleteEntitiesFromStores ,
82+ CollectionFactory $ collectionFactory
4483 ) {
4584 $ this ->productUrlRewriteGenerator = $ productUrlRewriteGenerator ;
4685 $ this ->urlPersist = $ urlPersist ;
47- $ this ->productUrlPathGenerator = $ productUrlPathGenerator ?: ObjectManager::getInstance ()
48- ->get (ProductUrlPathGenerator::class);
86+ $ this ->productUrlPathGenerator = $ productUrlPathGenerator ;
87+ $ this ->storeManager = $ storeManager ;
88+ $ this ->productScopeRewriteGenerator = $ productScopeRewriteGenerator ;
89+ $ this ->deleteEntitiesFromStores = $ deleteEntitiesFromStores ;
90+ $ this ->collectionFactory = $ collectionFactory ;
4991 }
5092
5193 /**
5294 * Generate urls for UrlRewrite and save it in storage
5395 *
54- * @param \Magento\Framework\Event\ Observer $observer
96+ * @param Observer $observer
5597 * @return void
56- * @throws \Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException
98+ * @throws UrlAlreadyExistsException
99+ * @SuppressWarnings(PHPMD.CyclomaticComplexity)
57100 */
58- public function execute (\ Magento \ Framework \ Event \ Observer $ observer )
101+ public function execute (Observer $ observer )
59102 {
60103 /** @var Product $product */
61104 $ product = $ observer ->getEvent ()->getProduct ();
@@ -65,11 +108,49 @@ public function execute(\Magento\Framework\Event\Observer $observer)
65108 || $ product ->getIsChangedWebsites ()
66109 || $ product ->dataHasChangedFor ('visibility ' )
67110 ) {
68- if ($ product ->isVisibleInSiteVisibility ()) {
69- $ product ->unsUrlPath ();
70- $ product ->setUrlPath ($ this ->productUrlPathGenerator ->getUrlPath ($ product ));
111+ //Refresh rewrite urls
112+ $ product ->unsUrlPath ();
113+ $ product ->setUrlPath ($ this ->productUrlPathGenerator ->getUrlPath ($ product ));
114+ if (!empty ($ this ->productUrlRewriteGenerator ->generate ($ product ))) {
71115 $ this ->urlPersist ->replace ($ this ->productUrlRewriteGenerator ->generate ($ product ));
72116 }
117+
118+ $ storeIdsToRemove = [];
119+ $ productWebsiteMap = array_flip ($ product ->getWebsiteIds ());
120+ $ storeVisibilities = $ this ->collectionFactory ->create ()
121+ ->getAllAttributeValues (ProductInterface::VISIBILITY );
122+ if ($ this ->productScopeRewriteGenerator ->isGlobalScope ($ product ->getStoreId ())) {
123+ //Remove any rewrite URLs for websites the product is not in, or is not visible in. Global Scope.
124+ foreach ($ this ->storeManager ->getStores () as $ store ) {
125+ $ websiteId = $ store ->getWebsiteId ();
126+ $ storeId = $ store ->getStoreId ();
127+ if (!isset ($ productWebsiteMap [$ websiteId ])) {
128+ $ storeIdsToRemove [] = $ storeId ;
129+ continue ;
130+ }
131+ //Check the visibility of the product in each store.
132+ if (isset ($ storeVisibilities [$ product ->getId ()][$ storeId ])
133+ && ($ storeVisibilities [$ product ->getId ()][$ storeId ] === Visibility::VISIBILITY_NOT_VISIBLE )) {
134+ $ storeIdsToRemove [] = $ storeId ;
135+ }
136+ }
137+ } else {
138+ //Only remove rewrite for current scope
139+ $ websiteId = $ product ->getStore ()->getWebsiteId ();
140+ $ storeId = $ product ->getStoreId ();
141+ if (!isset ($ productWebsiteMap [$ websiteId ]) ||
142+ (isset ($ storeVisibilities [$ product ->getId ()][$ storeId ])
143+ && ($ storeVisibilities [$ product ->getId ()][$ storeId ] === Visibility::VISIBILITY_NOT_VISIBLE ))) {
144+ $ storeIdsToRemove [] = $ storeId ;
145+ }
146+ }
147+ if (count ($ storeIdsToRemove )) {
148+ $ this ->deleteEntitiesFromStores ->execute (
149+ $ storeIdsToRemove ,
150+ [$ product ->getId ()],
151+ ProductUrlRewriteGenerator::ENTITY_TYPE
152+ );
153+ }
73154 }
74155 }
75156}
0 commit comments