5
5
*/
6
6
namespace Magento \CatalogUrlRewrite \Observer ;
7
7
8
+ use Magento \Catalog \Api \Data \ProductInterface ;
8
9
use 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 ;
9
13
use Magento \CatalogUrlRewrite \Model \ProductUrlPathGenerator ;
10
14
use 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 ;
12
18
use Magento \UrlRewrite \Model \UrlPersistInterface ;
13
19
use Magento \Framework \Event \ObserverInterface ;
20
+ use Magento \Store \Model \StoreManagerInterface ;
14
21
15
22
/**
16
23
* 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.
17
28
*/
18
29
class ProductProcessUrlRewriteSavingObserver implements ObserverInterface
19
30
{
@@ -32,30 +43,62 @@ class ProductProcessUrlRewriteSavingObserver implements ObserverInterface
32
43
*/
33
44
private $ productUrlPathGenerator ;
34
45
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
+
35
66
/**
36
67
* @param ProductUrlRewriteGenerator $productUrlRewriteGenerator
37
68
* @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
39
74
*/
40
75
public function __construct (
41
76
ProductUrlRewriteGenerator $ productUrlRewriteGenerator ,
42
77
UrlPersistInterface $ urlPersist ,
43
- ProductUrlPathGenerator $ productUrlPathGenerator = null
78
+ ProductUrlPathGenerator $ productUrlPathGenerator ,
79
+ StoreManagerInterface $ storeManager ,
80
+ ProductScopeRewriteGenerator $ productScopeRewriteGenerator ,
81
+ DeleteEntitiesFromStores $ deleteEntitiesFromStores ,
82
+ CollectionFactory $ collectionFactory
44
83
) {
45
84
$ this ->productUrlRewriteGenerator = $ productUrlRewriteGenerator ;
46
85
$ 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 ;
49
91
}
50
92
51
93
/**
52
94
* Generate urls for UrlRewrite and save it in storage
53
95
*
54
- * @param \Magento\Framework\Event\ Observer $observer
96
+ * @param Observer $observer
55
97
* @return void
56
- * @throws \Magento\UrlRewrite\Model\Exception\UrlAlreadyExistsException
98
+ * @throws UrlAlreadyExistsException
99
+ * @SuppressWarnings(PHPMD.CyclomaticComplexity)
57
100
*/
58
- public function execute (\ Magento \ Framework \ Event \ Observer $ observer )
101
+ public function execute (Observer $ observer )
59
102
{
60
103
/** @var Product $product */
61
104
$ product = $ observer ->getEvent ()->getProduct ();
@@ -65,11 +108,49 @@ public function execute(\Magento\Framework\Event\Observer $observer)
65
108
|| $ product ->getIsChangedWebsites ()
66
109
|| $ product ->dataHasChangedFor ('visibility ' )
67
110
) {
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 ))) {
71
115
$ this ->urlPersist ->replace ($ this ->productUrlRewriteGenerator ->generate ($ product ));
72
116
}
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
+ }
73
154
}
74
155
}
75
156
}
0 commit comments