From 3f0509c95f7793d81d47c8861a51ca5df6811fa1 Mon Sep 17 00:00:00 2001 From: Taylor Daughtry Date: Thu, 8 Jul 2021 21:32:19 -0500 Subject: [PATCH 1/3] Handle cases where an element is deleted by another plugin This stems from the acclaro/translations plugin running the `deleteAutoPropagatedDrafts()` method. --- src/EventRegistrar.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/EventRegistrar.php b/src/EventRegistrar.php index a83dc57..48b3b3a 100644 --- a/src/EventRegistrar.php +++ b/src/EventRegistrar.php @@ -212,8 +212,12 @@ protected static function handleUpdateEvent(Event $event) } // Prevent purge on updates of drafts or revisions - if (ElementHelper::isDraftOrRevision($event->element)) { - return; + try { + if (ElementHelper::isDraftOrRevision($event->element)) { + return; + } + } catch (\Exception $e) { + \Craft::warning("Failed to determine whether element is a Draft or Revision.", "upper"); } // Prevent purge on resaving From 771f8c174507b2f0abe2610585e6be574e080f57 Mon Sep 17 00:00:00 2001 From: Taylor Daughtry Date: Mon, 13 Dec 2021 10:33:10 -0600 Subject: [PATCH 2/3] Ensure new versions of live preview bypass the cache --- composer.json | 2 +- src/EventRegistrar.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 913f2a1..9409263 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ } ], "require": { - "craftcms/cms": "^3.2.0", + "craftcms/cms": "^3.2.1", "guzzlehttp/guzzle": "^6.5.5|^7.2.0" }, "require-dev": { diff --git a/src/EventRegistrar.php b/src/EventRegistrar.php index 48b3b3a..6adbbcc 100644 --- a/src/EventRegistrar.php +++ b/src/EventRegistrar.php @@ -61,7 +61,7 @@ public static function registerFrontendEvents() // Don't cache CP, LivePreview, Action, Non-GET requests if ($request->getIsCpRequest() || - $request->getIsLivePreview() || + $request->getIsPreview() || $request->getIsActionRequest() || !$request->getIsGet() ) { From 96d04c7b27e1aa656d10ed030299d1b12a1bc7cb Mon Sep 17 00:00:00 2001 From: Jeremy Greenawalt Date: Thu, 18 Aug 2022 08:53:00 -0500 Subject: [PATCH 3/3] [multisite] Added optional multisite support Signed-off-by: Jeremy Greenawalt --- src/config.example.php | 10 ++++ src/drivers/Cloudflare.php | 95 +++++++++++++++++++++++++++----------- 2 files changed, 79 insertions(+), 26 deletions(-) diff --git a/src/config.example.php b/src/config.example.php index c1724e2..4be03fb 100644 --- a/src/config.example.php +++ b/src/config.example.php @@ -57,6 +57,16 @@ 'apiToken' => getenv('CLOUDFLARE_API_TOKEN'), 'zoneId' => getenv('CLOUDFLARE_ZONE_ID'), 'domain' => getenv('CLOUDFLARE_DOMAIN'), + 'sites' => [ + 'defaultId' => [ + 'zoneId' => getenv('CLOUDFLARE_ZONE_ID'), + 'domain' => getenv('CLOUDFLARE_DOMAIN'), + ], + 'alternateId' => [ + 'zoneId' => getenv('ALT_CLOUDFLARE_ZONE_ID'), + 'domain' => getenv('ALT_CLOUDFLARE_DOMAIN'), + ], + ], // deprecated, do not use for new installs 'apiKey' => getenv('CLOUDFLARE_API_KEY'), 'apiEmail' => getenv('CLOUDFLARE_API_EMAIL'), diff --git a/src/drivers/Cloudflare.php b/src/drivers/Cloudflare.php index 6e5ab33..68f8ebe 100644 --- a/src/drivers/Cloudflare.php +++ b/src/drivers/Cloudflare.php @@ -4,6 +4,7 @@ use GuzzleHttp\Client; use GuzzleHttp\Exception\BadResponseException; use ostark\upper\exceptions\CloudflareApiException; +use ostark\upper\Plugin; /** * Class Cloudflare Driver @@ -29,6 +30,7 @@ class Cloudflare extends AbstractPurger implements CachePurgeInterface public $domain; + public $sites; /** * @param string $tag @@ -55,20 +57,48 @@ public function purgeTag(string $tag) */ public function purgeUrls(array $urls) { - if (strpos($this->domain, 'http') !== 0) { - throw new \InvalidArgumentException("'domain' must include the protocol, e.g. https://www.foo.com"); - } - - // prefix urls with domain - $files = array_map(function($url) { - return rtrim($this->domain, '/') . $url; - }, $urls); - - // Chunk larger collections to meet the API constraints - foreach (array_chunk($files, self::MAX_URLS_PER_PURGE) as $fileGroup) { - $this->sendRequest('DELETE', 'purge_cache', [ - 'files' => $fileGroup - ]); + if ($this->sites) { + foreach ($urls as $uid => $url) { + $sql ="SELECT siteId FROM %s WHERE uid = '%s'"; + $sql = sprintf( + $sql, + \Craft::$app->getDb()->quoteTableName(Plugin::CACHE_TABLE), + $uid + ); + $result = \Craft::$app->getDb() + ->createCommand($sql) + ->queryOne(); + $siteId = $result['siteId']; + if (strpos($this->sites[$siteId]['domain'], 'http') !== 0) { + throw new \InvalidArgumentException("'domain' must include the protocol, e.g. https://www.foo.com"); + } + $files[$siteId][] = rtrim($this->sites[$siteId]['domain'], '/') . $url; + } + + // Chunk larger collections to meet the API constraints + foreach ($files as $siteId => $siteFiles) { + foreach (array_chunk($siteFiles, self::MAX_URLS_PER_PURGE) as $fileGroup) { + $this->sendRequest('DELETE', 'purge_cache', [ + 'files' => $fileGroup + ], [$this->sites[$siteId]['zoneId']]); + } + } + } else { + if (strpos($this->domain, 'http') !== 0) { + throw new \InvalidArgumentException("'domain' must include the protocol, e.g. https://www.foo.com"); + } + + // prefix urls with domain + $files = array_map(function($url) { + return rtrim($this->domain, '/') . $url; + }, $urls); + + // Chunk larger collections to meet the API constraints + foreach (array_chunk($files, self::MAX_URLS_PER_PURGE) as $fileGroup) { + $this->sendRequest('DELETE', 'purge_cache', [ + 'files' => $fileGroup + ]); + } } return true; @@ -81,9 +111,16 @@ public function purgeUrls(array $urls) */ public function purgeAll() { + $zoneIds = []; + if ($this->sites) { + foreach ($this->sites as $site) { + $zoneIds[] = $site['zoneId']; + } + } + $success = $this->sendRequest('DELETE', 'purge_cache', [ - 'purge_everything' => true - ]); + 'purge_everything' => true, + ], $zoneIds); if ($this->useLocalTags && $success === true) { $this->clearLocalCache(); @@ -101,20 +138,26 @@ public function purgeAll() * @return bool * @throws \ostark\upper\exceptions\CloudflareApiException */ - protected function sendRequest($method = 'DELETE', string $type, array $params = []) + protected function sendRequest($method = 'DELETE', string $type, array $params = [], $zoneIds = []) { $client = $this->getClient(); - try { - $uri = "zones/{$this->zoneId}/$type"; - $options = (count($params)) ? ['json' => $params] : []; - $client->request($method, $uri, $options); - } catch (BadResponseException $e) { + if (empty($zoneIds)) { + $zoneIds[] = $this->zoneId; + } - throw CloudflareApiException::create( - $e->getRequest(), - $e->getResponse() - ); + foreach ($zoneIds as $zoneId) { + try { + $uri = "zones/$zoneId/$type"; + $options = (count($params)) ? ['json' => $params] : []; + $client->request($method, $uri, $options); + } catch (BadResponseException $e) { + + throw CloudflareApiException::create( + $e->getRequest(), + $e->getResponse() + ); + } } return true;