88namespace Magento \UrlRewrite \Model ;
99
1010use Magento \Framework \App \ObjectManager ;
11+ use Magento \Framework \Data \Collection \AbstractDb ;
12+ use Magento \Framework \EntityManager \EventManager ;
13+ use Magento \Framework \Indexer \CacheContext ;
14+ use Magento \Framework \Model \AbstractModel ;
15+ use Magento \Framework \Model \Context ;
16+ use Magento \Framework \Model \ResourceModel \AbstractResource ;
17+ use Magento \Framework \Registry ;
1118use Magento \Framework \Serialize \Serializer \Json ;
19+ use Magento \UrlRewrite \Controller \Adminhtml \Url \Rewrite ;
20+ use Magento \UrlRewrite \Model \ResourceModel \UrlRewriteCollection ;
21+ use Magento \UrlRewrite \Service \V1 \Data \UrlRewrite as UrlRewriteService ;
1222
1323/**
1424 * UrlRewrite model class
2737 * @method UrlRewrite setStoreId($value)
2838 * @method UrlRewrite setDescription($value)
2939 */
30- class UrlRewrite extends \ Magento \ Framework \ Model \ AbstractModel
40+ class UrlRewrite extends AbstractModel
3141{
3242 /**
3343 * @var Json
3444 */
3545 private $ serializer ;
3646
47+ /**
48+ * @var CacheContext|mixed|null
49+ */
50+ private $ cacheContext ;
51+
52+ /**
53+ * @var EventManager|mixed|null
54+ */
55+ private $ eventManager ;
56+
57+ /**
58+ * @var array
59+ */
60+ private $ entityToCacheTagMap ;
61+
62+ /**
63+ * @var UrlFinderInterface
64+ */
65+ private $ urlFinder ;
66+
3767 /**
3868 * UrlRewrite constructor.
3969 *
40- * @param \Magento\Framework\Model\ Context $context
41- * @param \Magento\Framework\ Registry $registry
42- * @param \Magento\Framework\Model\ResourceModel\ AbstractResource|null $resource
43- * @param \Magento\Framework\Data\Collection\ AbstractDb|null $resourceCollection
70+ * @param Context $context
71+ * @param Registry $registry
72+ * @param AbstractResource|null $resource
73+ * @param AbstractDb|null $resourceCollection
4474 * @param array $data
45- * @param Json $serializer
75+ * @param Json|null $serializer
76+ * @param CacheContext|null $cacheContext
77+ * @param EventManager|null $eventManager
78+ * @param UrlFinderInterface|null $urlFinder
79+ * @param array $entityToCacheTagMap
4680 */
4781 public function __construct (
48- \ Magento \ Framework \ Model \ Context $ context ,
49- \ Magento \ Framework \ Registry $ registry ,
50- \ Magento \ Framework \ Model \ ResourceModel \ AbstractResource $ resource = null ,
51- \ Magento \ Framework \ Data \ Collection \ AbstractDb $ resourceCollection = null ,
82+ Context $ context ,
83+ Registry $ registry ,
84+ AbstractResource $ resource = null ,
85+ AbstractDb $ resourceCollection = null ,
5286 array $ data = [],
53- Json $ serializer = null
54- ) {
87+ Json $ serializer = null ,
88+ CacheContext $ cacheContext = null ,
89+ EventManager $ eventManager = null ,
90+ UrlFinderInterface $ urlFinder = null ,
91+ array $ entityToCacheTagMap = []
92+ )
93+ {
5594 $ this ->serializer = $ serializer ?: ObjectManager::getInstance ()->get (Json::class);
95+ $ this ->cacheContext = $ cacheContext ?: ObjectManager::getInstance ()->get (CacheContext::class);
96+ $ this ->eventManager = $ eventManager ?: ObjectManager::getInstance ()->get (EventManager::class);
97+ $ this ->urlFinder = $ urlFinder ?: ObjectManager::getInstance ()->get (UrlFinderInterface::class);
98+ $ this ->entityToCacheTagMap = $ entityToCacheTagMap ;
5699 parent ::__construct ($ context , $ registry , $ resource , $ resourceCollection , $ data );
57100 }
58101
@@ -63,8 +106,8 @@ public function __construct(
63106 */
64107 protected function _construct ()
65108 {
66- $ this ->_init (\ Magento \ UrlRewrite \ Model \ ResourceModel \UrlRewrite::class);
67- $ this ->_collectionName = \ Magento \ UrlRewrite \ Model \ ResourceModel \ UrlRewriteCollection::class;
109+ $ this ->_init (ResourceModel \UrlRewrite::class);
110+ $ this ->_collectionName = UrlRewriteCollection::class;
68111 }
69112
70113 /**
@@ -92,4 +135,101 @@ public function setMetadata($metadata)
92135 }
93136 return $ this ->setData (\Magento \UrlRewrite \Service \V1 \Data \UrlRewrite::METADATA , $ metadata );
94137 }
138+
139+ /**
140+ * Gets final target UrlRewrite for custom rewrite record
141+ *
142+ * @param string $path
143+ * @param int $storeId
144+ * @return UrlRewriteService|null
145+ */
146+ private function getFinalTargetUrlRewrite (string $ path , int $ storeId ): ?UrlRewriteService
147+ {
148+ $ urlRewriteTarget = $ this ->urlFinder ->findOneByData (
149+ [
150+ 'request_path ' => $ path ,
151+ 'store_id ' => $ storeId
152+ ]
153+ );
154+
155+ while (
156+ $ urlRewriteTarget &&
157+ $ urlRewriteTarget ->getTargetPath () !== $ urlRewriteTarget ->getRequestPath () &&
158+ $ urlRewriteTarget ->getRedirectType () > 0
159+ ) {
160+ $ urlRewriteTarget = $ this ->urlFinder ->findOneByData (
161+ [
162+ 'request_path ' => $ urlRewriteTarget ->getTargetPath (),
163+ 'store_id ' => $ urlRewriteTarget ->getStoreId ()
164+ ]
165+ );
166+ }
167+
168+ return $ urlRewriteTarget ;
169+ }
170+
171+ /**
172+ * Clean the cache for entities affected by current rewrite
173+ */
174+ public function cleanEntitiesCache ()
175+ {
176+ if (!$ this ->isEmpty ()) {
177+ if ($ this ->getEntityType () === Rewrite::ENTITY_TYPE_CUSTOM ) {
178+ $ urlRewrite = $ this ->getFinalTargetUrlRewrite (
179+ $ this ->getTargetPath (),
180+ (int )$ this ->getStoreId ()
181+ );
182+
183+ if ($ urlRewrite ) {
184+ $ this ->cleanCacheForEntity ($ urlRewrite ->getEntityType (), (int ) $ urlRewrite ->getEntityId ());
185+ }
186+
187+ if ($ this ->getOrigData () && $ this ->getOrigData ('target_path ' ) !== $ this ->getTargetPath ()) {
188+ $ origUrlRewrite = $ this ->getFinalTargetUrlRewrite (
189+ $ this ->getOrigData ('target_path ' ),
190+ (int )$ this ->getOrigData ('store_id ' )
191+ );
192+
193+ if ($ origUrlRewrite ) {
194+ $ this ->cleanCacheForEntity ($ origUrlRewrite ->getEntityType (), (int ) $ origUrlRewrite ->getEntityId ());
195+ }
196+ }
197+ } else {
198+ $ this ->cleanCacheForEntity ($ this ->getEntityType (), (int ) $ this ->getEntityId ());
199+ }
200+ }
201+ }
202+
203+ /**
204+ * Clean cache for specified entity type by id
205+ *
206+ * @param string $entityType
207+ * @param int $entityId
208+ */
209+ private function cleanCacheForEntity (string $ entityType , int $ entityId )
210+ {
211+ if (array_key_exists ($ entityType , $ this ->entityToCacheTagMap )) {
212+ $ cacheKey = $ this ->entityToCacheTagMap [$ entityType ];
213+ $ this ->cacheContext ->registerEntities ($ cacheKey , [$ entityId ]);
214+ $ this ->eventManager ->dispatch ('clean_cache_by_tags ' , ['object ' => $ this ->cacheContext ]);
215+ }
216+ }
217+
218+ /**
219+ * @inheritdoc
220+ */
221+ public function afterDelete ()
222+ {
223+ $ this ->_getResource ()->addCommitCallback ([$ this , 'cleanEntitiesCache ' ]);
224+ return parent ::afterDelete ();
225+ }
226+
227+ /**
228+ * @inheritdoc
229+ */
230+ public function afterSave ()
231+ {
232+ $ this ->_getResource ()->addCommitCallback ([$ this , 'cleanEntitiesCache ' ]);
233+ return parent ::afterSave ();
234+ }
95235}
0 commit comments