diff --git a/cfo-info.php b/cfo-info.php index e93ce1d7..524f5f7c 100644 --- a/cfo-info.php +++ b/cfo-info.php @@ -1,5 +1,5 @@ { }); let cfoMarkets = document.getElementById('cfo-purge-container')?.children; - for (const cfoMarketButton of cfoMarkets) { - cfoMarketButton.onclick = function () { - if (confirm("Are you sure you want to clear the cache for " + cfoMarketButton.children[0].innerHTML)) { - purgeMarket(cfoMarketButton.dataset.cfoMarket); - } - }; + if (cfoMarkets != null) { + for (const cfoMarketButton of cfoMarkets) { + cfoMarketButton.onclick = function () { + if (confirm("Are you sure you want to clear the cache for " + cfoMarketButton.children[0].innerHTML)) { + purgeMarket(cfoMarketButton.dataset.cfoMarket); + } + }; + } } async function purgeMarket(marketID) { @@ -51,4 +53,43 @@ document.addEventListener('DOMContentLoaded', () => { console.error(error); } } + + let CPTTagsContainer = document.getElementById('global-cfo_CPTtags'); + if (CPTTagsContainer != null) { + ectractCurrentValue(CPTTagsContainer); + let contentEditables = CPTTagsContainer.querySelectorAll('[contenteditable]'); + contentEditables.forEach(el => { + el.addEventListener('input', (e) => { + compileCPTTags(CPTTagsContainer); + }); + }); + } + function ectractCurrentValue(CPTTagsContainer) { + let CPTTagCurrentValue = document.getElementById('global-cfo_customCPTTags').value; + if (CPTTagCurrentValue) { + let decodedCurrentValue = JSON.parse(CPTTagCurrentValue); + if (decodedCurrentValue) { + let CPTRows = CPTTagsContainer.querySelectorAll('tr.global-cfo_tags-row'); + CPTRows.forEach(CTPRow => { + let tagItems = CTPRow.querySelectorAll('td'); + let CPT = tagItems[0].innerHTML; + if (Object.hasOwn(decodedCurrentValue, CPT)) { + let valueForRow = decodedCurrentValue[CPT]; + if (valueForRow) { + tagItems[1].innerHTML = valueForRow; + } + } + }); + } + } + } + function compileCPTTags(CPTTagsContainer) { + let CPTRows = CPTTagsContainer.querySelectorAll('tr.global-cfo_tags-row'); + let CPTTags = {}; + CPTRows.forEach(CTPRow => { + let tagItems = CTPRow.querySelectorAll('td'); + CPTTags[tagItems[0].innerHTML] = tagItems[1].innerHTML; + }); + document.getElementById('global-cfo_customCPTTags').value = JSON.stringify(CPTTags); + } }); \ No newline at end of file diff --git a/global-cfo.php b/global-cfo.php index 315b4073..b1ff44e5 100644 --- a/global-cfo.php +++ b/global-cfo.php @@ -18,7 +18,7 @@ * Plugin Name: Global CFO * Plugin URI: https://github.com/TotalOnion/cloudflareonion * Description: Cloudflare cache handling plugin - * Version: 0.0.13 + * Version: 1.1.0 * Author: Johann Biteghe * Author URI: https://totalonion.com * License: GPL-2.0+ diff --git a/src/Controllers/Admin/CacheClearancePage.php b/src/Controllers/Admin/CacheClearancePage.php index 340f63f1..55c74368 100644 --- a/src/Controllers/Admin/CacheClearancePage.php +++ b/src/Controllers/Admin/CacheClearancePage.php @@ -123,7 +123,7 @@ public function handleFormSubmission($input) 'warning' ); - $this->cfoManager->registerSavedItem($url); + $this->cfoManager->registerSavedItemURL($url); } } diff --git a/src/Controllers/Admin/CacheTags.php b/src/Controllers/Admin/CacheTags.php new file mode 100644 index 00000000..5fb6f8fe --- /dev/null +++ b/src/Controllers/Admin/CacheTags.php @@ -0,0 +1,63 @@ +getTagsToPurge($postID); + $body = json_encode([ + 'tags' => $tags + ]); + return $body; + } + + public function printCacheTagsHeader(): void + { + $postID = get_the_ID(); + $cacheTags = $this->getTagsToPrint($postID); + $tagsString = implode(',', $cacheTags); + header('Cache-Tag: ' . $tagsString); + } + + private function getTagsToPrint($postID): array { + $tags = []; + $tags[] = $this->getIDTag($postID); + return $tags; + } + + private function getTagsToPurge($postID): array { + $tags = []; + $tags[] = $this->getIDTag($postID); + $cptTag = $this->getCptTag($postID); + if ($cptTag) { + $tags[] = $this->getCptTag($postID); + } + return $tags; + } + + private function getIDTag($postID): string { + return 'cfo-' . $postID; + } + + private function getCptTag($postID): string { + $cptTag = ''; + $postType = get_post_type($postID); + $cptTagsEncoded = get_option(GLOBAL_CFO_NAME.'_customCPTTags'); + if ($cptTagsEncoded) { + $cptTags = json_decode($cptTagsEncoded); + if ($postType && is_object($cptTags) && property_exists($cptTags, $postType)) { + $cptTag = $cptTags->{$postType}; + } + } + return $cptTag; + } +} \ No newline at end of file diff --git a/src/Controllers/Admin/CacheTagsPage.php b/src/Controllers/Admin/CacheTagsPage.php new file mode 100644 index 00000000..3f0c8643 --- /dev/null +++ b/src/Controllers/Admin/CacheTagsPage.php @@ -0,0 +1,109 @@ + 'number', + 'description' => 'Whether or not to enable Cache Tags based purging', + 'sanitize_callback' => 'sanitize_text_field', + 'show_in_rest' => true, + 'default' => '' + ] + ); + add_settings_field( + GLOBAL_CFO_NAME.'_enableCacheTags', + 'Enable Tags based purging', + [$this, 'renderField'], + GLOBAL_CFO_NAME.'_cache-tags-page', + GLOBAL_CFO_NAME.'_options_section_tags', + [ + 'id' => GLOBAL_CFO_NAME.'_enableCacheTags', + 'type' => 'checkbox' + ] + ); + + add_option(GLOBAL_CFO_NAME.'_customCPTTags'); + register_setting( + GLOBAL_CFO_NAME.'_tags_options', + GLOBAL_CFO_NAME.'_customCPTTags', + [ + 'type' => 'text', + 'description' => 'Custom tag to purge when a specific post type is saved', + 'sanitize_callback' => 'sanitize_text_field', + 'show_in_rest' => true, + 'default' => '' + ] + ); + add_settings_field( + GLOBAL_CFO_NAME.'_customCPTTags', + 'Tags to purge by PostType', + [$this, 'renderField'], + GLOBAL_CFO_NAME.'_cache-tags-page', + GLOBAL_CFO_NAME.'_options_section_tags', + [ + 'id' => GLOBAL_CFO_NAME.'_customCPTTags', + 'type' => 'CPTTable', + 'CPTs' => get_option(GLOBAL_CFO_NAME.'_purgePostTypes', '') + ] + ); + } + + public function registerSettings() + { + $this->registerCacheTagsFields(); + } + + public function renderSectionIntro() + { + echo __('', GLOBAL_CFO_NAME); + } + + public function renderField($fieldParameters) + { + echo $this->render( + 'forms:fields/'.$fieldParameters['type'].'.php', + [ + 'id' => $fieldParameters['id'], + 'name' => $fieldParameters['id'], + 'currentValue' => get_option($fieldParameters['id']) ?? '', + 'cssClass' => $fieldParameters['cssClass'] ?? '', + 'choices' => $fieldParameters['choices'] ?? '', + 'CPTs' => $fieldParameters['CPTs'] ?? '' + ] + ); + } + + public function renderPage() + { + echo $this->render('forms:settingsPage.php'); + } +} diff --git a/src/Controllers/Admin/CfoManager.php b/src/Controllers/Admin/CfoManager.php index a0b79903..60bb571f 100644 --- a/src/Controllers/Admin/CfoManager.php +++ b/src/Controllers/Admin/CfoManager.php @@ -3,18 +3,21 @@ use GlobalCfo\Controllers\AbstractController; use GlobalCfo\Controllers\Admin\Logger; +use GlobalCfo\Controllers\Admin\CacheTags; class CfoManager extends AbstractController { private Logger $logger; + private CacheTags $cacheTags; public function __construct($pluginName, $version) { $this->logger = new Logger($version, $pluginName); + $this->cacheTags = new CacheTags($version, $pluginName); parent::__construct($pluginName, $version); } - public function registerSavedItem($url) + public function registerSavedItemURL($url) { $this->sendPurgeRequest($this->getPurgeBodyUrl($url)); @@ -23,6 +26,17 @@ public function registerSavedItem($url) } } + public function registerSavedItemCacheTags($postID) + { + $purgeBody = $this->cacheTags->getPurgeBody($postID); + $this->sendPurgeRequest($purgeBody); + } + + public function printCacheTagsHeader() + { + $this->cacheTags->printCacheTagsHeader(); + } + public function registerSavedPost($postID) { if (wp_is_post_revision($postID) || wp_is_post_autosave($postID) || !$this->getCFEnabled()) { @@ -33,12 +47,18 @@ public function registerSavedPost($postID) $postTypesToPurge = $this->getPostTypesOption(); // Skipping purge for post types not in the list - if (!in_array($postType, $postTypesToPurge)) { + if ((empty($postTypesToPurge)) || (!empty($postTypesToPurge) && !in_array($postType, $postTypesToPurge))) { return; } - $postUrl = get_permalink($postID); - $this->registerSavedItem($postUrl); + $cacheTagsEnabled = $this->getCacheTagsEnabled(); + + if ( $cacheTagsEnabled ) { + $this->registerSavedItemCacheTags($postID); + } else { + $postUrl = get_permalink($postID); + $this->registerSavedItemURL($postUrl); + } } public function purgeMarket($marketId) @@ -156,4 +176,9 @@ protected function getDomainReplace(): string { return get_option(GLOBAL_CFO_NAME.'_replace_domain'); } + + private function getCacheTagsEnabled(): string + { + return get_option(GLOBAL_CFO_NAME.'_enableCacheTags'); + } } diff --git a/src/GlobalCfo.php b/src/GlobalCfo.php index 9057eb26..6eb5df12 100644 --- a/src/GlobalCfo.php +++ b/src/GlobalCfo.php @@ -98,14 +98,20 @@ private function defineAdminHooks() $this->loader->addAction('admin_menu', $settingsPage, 'registerPage'); $this->loader->addAction('admin_init', $settingsPage, 'registerSettings'); - // Add the cache page + // Add the cache clearance page $cacheClearancePage = new Admin\CacheClearancePage($this->getPluginName(), $this->getVersion()); $this->loader->addAction('admin_menu', $cacheClearancePage, 'registerPage'); $this->loader->addAction('admin_init', $cacheClearancePage, 'registerSettings'); + // Add the cache tags page + $cacheTagsPage = new Admin\CacheTagsPage($this->getPluginName(), $this->getVersion()); + $this->loader->addAction('admin_menu', $cacheTagsPage, 'registerPage'); + $this->loader->addAction('admin_init', $cacheTagsPage, 'registerSettings'); + // Add the forms post type etc $cfoManager = new Admin\CfoManager($this->getPluginName(), $this->getVersion()); $this->loader->addAction('save_post', $cfoManager, 'registerSavedPost'); + $this->loader->addAction('wp_head', $cfoManager, 'printCacheTagsHeader'); // Add the endpoints $API = new Admin\CfoAPI($this->getPluginName(), $this->getVersion(), $cfoManager); diff --git a/src/Resources/views/forms/fields/CPTTable.php b/src/Resources/views/forms/fields/CPTTable.php new file mode 100644 index 00000000..2667d079 --- /dev/null +++ b/src/Resources/views/forms/fields/CPTTable.php @@ -0,0 +1,23 @@ + + + + + + + + + + + + +
Post TypeTag to Clear
+ + diff --git a/src/Resources/views/forms/settingsPage.php b/src/Resources/views/forms/settingsPage.php index c07963bb..984ba3b7 100644 --- a/src/Resources/views/forms/settingsPage.php +++ b/src/Resources/views/forms/settingsPage.php @@ -14,6 +14,10 @@ class="nav-tab "> Clear Cache + + Cache Tags + @@ -32,7 +36,7 @@ class="nav-tab

Cache Clearance

@@ -42,6 +46,17 @@ class="nav-tab
+ +

Cache Tags

+
+ +