1616use Ymir \Plugin \CloudStorage \PrivateCloudStorageStreamWrapper ;
1717use Ymir \Plugin \CloudStorage \PublicCloudStorageStreamWrapper ;
1818use Ymir \Plugin \EventManagement \SubscriberInterface ;
19+ use Ymir \Plugin \PageCache \ContentDeliveryNetworkPageCacheClientInterface ;
1920use Ymir \Plugin \Support \Collection ;
2021
2122/**
@@ -37,6 +38,20 @@ class WooCommerceSubscriber implements SubscriberInterface
3738 */
3839 private $ isImageProcessingEnabled ;
3940
41+ /**
42+ * Client interacting with the content delivery network handling page caching.
43+ *
44+ * @var ContentDeliveryNetworkPageCacheClientInterface
45+ */
46+ private $ pageCacheClient ;
47+
48+ /**
49+ * The page caching options.
50+ *
51+ * @var array
52+ */
53+ private $ pageCachingOptions ;
54+
4055 /**
4156 * WordPress site URL.
4257 *
@@ -47,10 +62,12 @@ class WooCommerceSubscriber implements SubscriberInterface
4762 /**
4863 * Constructor.
4964 */
50- public function __construct (string $ siteUrl , string $ assetsUrl = '' , bool $ isImageProcessingEnabled = false )
65+ public function __construct (ContentDeliveryNetworkPageCacheClientInterface $ pageCacheClient , string $ siteUrl , string $ assetsUrl = '' , bool $ isImageProcessingEnabled = false , array $ pageCachingOptions = [] )
5166 {
5267 $ this ->assetsUrl = rtrim ($ assetsUrl , '/ ' );
5368 $ this ->isImageProcessingEnabled = $ isImageProcessingEnabled ;
69+ $ this ->pageCacheClient = $ pageCacheClient ;
70+ $ this ->pageCachingOptions = $ pageCachingOptions ;
5471 $ this ->siteUrl = rtrim ($ siteUrl , '/ ' );
5572 }
5673
@@ -66,6 +83,8 @@ public static function getSubscribedEvents(): array
6683 'woocommerce_log_directory ' => 'changeLogDirectory ' ,
6784 'woocommerce_product_csv_importer_check_import_file_path ' => 'disableCheckImportFilePath ' ,
6885 'woocommerce_resize_images ' => 'disableImageResizeWithImageProcessing ' ,
86+ 'woocommerce_update_product ' => 'clearCacheOnProductUpdate ' ,
87+ 'woocommerce_update_product_variation ' => 'clearCacheOnProductVariationUpdate ' ,
6988 ];
7089 }
7190
@@ -79,6 +98,26 @@ public function changeLogDirectory($logDirectory)
7998 : $ logDirectory ;
8099 }
81100
101+ /**
102+ * Clear all the related product URLs when a product is updated.
103+ */
104+ public function clearCacheOnProductUpdate ($ productId )
105+ {
106+ $ this ->clearProductUrls ($ productId );
107+ }
108+
109+ /**
110+ * Clear all the related product URLs when a product variation is updated.
111+ */
112+ public function clearCacheOnProductVariationUpdate ($ variationId , $ variation )
113+ {
114+ if (!is_object ($ variation ) || !method_exists ($ variation , 'get_parent_id ' )) {
115+ return ;
116+ }
117+
118+ $ this ->clearProductUrls ($ variation ->get_parent_id ());
119+ }
120+
82121 /**
83122 * Disable "check import file path" so that imports work with S3 storage.
84123 */
@@ -120,4 +159,50 @@ public function fixAssetUrlPathsInCachedScriptData($value)
120159
121160 return wp_json_encode ($ cachedScriptData );
122161 }
162+
163+ /**
164+ * Clear all the URLs related to the given product from the page cache.
165+ */
166+ private function clearProductUrls ($ productId )
167+ {
168+ if (empty ($ this ->pageCachingOptions ['invalidation_enabled ' ])) {
169+ return ;
170+ } elseif (!empty ($ this ->pageCachingOptions ['clear_all_on_post_update ' ])) {
171+ $ this ->pageCacheClient ->clearAll ();
172+
173+ return ;
174+ }
175+
176+ $ permalink = get_permalink ($ productId );
177+
178+ if (!is_string ($ permalink )) {
179+ return ;
180+ }
181+
182+ $ urlsToClear = new Collection ();
183+
184+ $ urlsToClear [] = rtrim ($ permalink , '/ ' ).'/ ' ;
185+
186+ if (function_exists ('wc_get_page_permalink ' )) {
187+ $ urlsToClear [] = rtrim (wc_get_page_permalink ('shop ' ), '/ ' ).'/* ' ;
188+ }
189+
190+ // Product category URLs
191+ $ productCategories = (new Collection (get_the_terms ($ productId , 'product_cat ' )))->filter (function ($ category ) {
192+ return $ category instanceof \WP_Term;
193+ });
194+ $ urlsToClear = $ urlsToClear ->merge ($ productCategories ->map (function (\WP_Term $ category ) {
195+ return rtrim (get_term_link ($ category ), '/ ' ).'/* ' ;
196+ }));
197+
198+ // Product tag URLs
199+ $ productTags = (new Collection (get_the_terms ($ productId , 'product_tag ' )))->filter (function ($ category ) {
200+ return $ category instanceof \WP_Term;
201+ });
202+ $ urlsToClear = $ urlsToClear ->merge ($ productTags ->map (function (\WP_Term $ tag ) {
203+ return rtrim (get_term_link ($ tag ), '/ ' ).'/* ' ;
204+ }));
205+
206+ $ this ->pageCacheClient ->clearUrls ($ urlsToClear );
207+ }
123208}
0 commit comments