Skip to content

Commit 34cce06

Browse files
committed
[TASK] Fix CGL and introduce an event after clear cache pages
1 parent 3102751 commit 34cce06

4 files changed

Lines changed: 71 additions & 166 deletions

File tree

Classes/Controller/CloudinaryWebHookController.php

Lines changed: 34 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
* LICENSE.md file that was distributed with this source code.
1010
*/
1111

12-
use Causal\Cloudflare\Services\CloudflareService;
12+
use Psr\EventDispatcher\EventDispatcherInterface;
1313
use Psr\Http\Message\ResponseInterface;
1414
use TYPO3\CMS\Core\Cache\CacheManager;
15-
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
1615
use TYPO3\CMS\Core\Database\ConnectionPool;
1716
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
17+
use TYPO3\CMS\Core\Exception;
1818
use TYPO3\CMS\Core\Log\Logger;
1919
use TYPO3\CMS\Core\Log\LogManager;
2020
use TYPO3\CMS\Core\Package\PackageManager;
@@ -24,6 +24,7 @@
2424
use TYPO3\CMS\Core\Resource\ResourceStorage;
2525
use TYPO3\CMS\Core\Utility\GeneralUtility;
2626
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
27+
use Visol\Cloudinary\Events\ClearCachePageEvent;
2728
use Visol\Cloudinary\Exceptions\CloudinaryNotFoundException;
2829
use Visol\Cloudinary\Exceptions\PublicIdMissingException;
2930
use Visol\Cloudinary\Exceptions\UnknownRequestTypeException;
@@ -52,6 +53,12 @@ class CloudinaryWebHookController extends ActionController
5253

5354
protected PackageManager $packageManager;
5455

56+
/**
57+
* @var EventDispatcherInterface
58+
*/
59+
protected $eventDispatcher;
60+
61+
5562
protected function initializeAction(): void
5663
{
5764
$this->checkEnvironment();
@@ -60,6 +67,9 @@ protected function initializeAction(): void
6067
$resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class);
6168

6269
$storage = $resourceFactory->getStorageObject((int)$this->settings['storage']);
70+
71+
$this->eventDispatcher = GeneralUtility::makeInstance(EventDispatcherInterface::class);
72+
6373
$this->cloudinaryResourceService = GeneralUtility::makeInstance(
6474
CloudinaryResourceService::class,
6575
$storage,
@@ -85,7 +95,7 @@ protected function initializeAction(): void
8595
public function processAction(): ResponseInterface
8696
{
8797
$parsedBody = (string)file_get_contents('php://input');
88-
$payload = json_decode($parsedBody, true);
98+
$payload = (array)json_decode($parsedBody, true);
8999
self::getLogger()->debug($parsedBody);
90100

91101
if ($this->shouldStopProcessing($payload)) {
@@ -101,11 +111,11 @@ public function processAction(): ResponseInterface
101111
foreach ($publicIds as $publicId) {
102112

103113
if ($requestType === self::NOTIFICATION_TYPE_DELETE) {
104-
if (strpos($publicId, '_processed_') === null) {
114+
if (str_contains($publicId, '_processed_')) {
115+
$message = 'Processed file deleted. Nothing to do, stopping here...';
116+
} else {
105117
$message = sprintf('Deleted file "%s", this should not happen. A file is going to be missing.', $publicId);
106118
self::getLogger()->warning($message);
107-
} else {
108-
$message = 'Processed file deleted. Nothing to do, stopping here...';
109119
}
110120

111121
// early return
@@ -117,6 +127,7 @@ public function processAction(): ResponseInterface
117127
$this->cloudinaryResourceService->delete($publicId);
118128

119129
// Fetch the new cloudinary resource
130+
/** @var string $nextPublicId */
120131
$nextPublicId = $payload['to_public_id'];
121132
$previousCloudinaryResource = $cloudinaryResource = $this->getCloudinaryResource($nextPublicId);
122133

@@ -151,51 +162,10 @@ public function processAction(): ResponseInterface
151162
]);
152163
}
153164

154-
return $this->sendResponse(['result' => 'ok', 'message' => 'I did my job with success!']);
165+
return $this->sendResponse(['result' => 'ok', 'message' => 'Success! I did my job.']);
155166
}
156167

157-
protected function flushCloudflareCdn(array $tags): void
158-
{
159-
$config = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('cloudflare');
160-
161-
/** @var CloudflareService $cloudflareService */
162-
$cloudflareService = GeneralUtility::makeInstance(CloudflareService::class, $config);
163-
164-
$domains = $config['domains'] ? GeneralUtility::trimExplode(',', $config['domains'], true) : [];
165-
166-
foreach ($domains as $domain) {
167-
try {
168-
[$identifier, $zoneName] = explode('|', $domain, 2);
169-
$result = $cloudflareService->send(
170-
'/zones/' . $identifier . '/purge_cache',
171-
[
172-
'tags' => $tags,
173-
],
174-
'DELETE'
175-
);
176-
177-
if (is_array($result) && $result['success']) {
178-
$message = vsprintf('Cleared the cache on Cloudflare using Cache-Tag (domain: "%s")', [$zoneName, implode(LF, $result['errors'])]);
179-
self::getLogger()->info($message);
180-
} else {
181-
if (is_array($result['errors'])) {
182-
foreach ($result['errors'] as $error) {
183-
$message = vsprintf('Failed to clear the cache on Cloudflare using Cache-Tag (domain: "%s"): code %s, %s', [$zoneName, $error['code'], $error['message']]);
184-
self::getLogger()->warning($message);
185-
}
186-
} else {
187-
$message = vsprintf('Failed to clear the cache on Cloudflare using Cache-Tag (domain: "%s")', [$zoneName]);
188-
self::getLogger()->warning($message);
189-
}
190-
}
191-
} catch (\RuntimeException $e) {
192-
self::getLogger()->error($e->getMessage());
193-
}
194-
}
195-
196-
}
197-
198-
protected function flushCloudinaryCdn($publicId): void
168+
protected function flushCloudinaryCdn(string $publicId): void
199169
{
200170
// Invalidate CDN cache
201171
\Cloudinary\Uploader::explicit(
@@ -223,7 +193,13 @@ protected function handleFileRename(string $previousFileIdentifier, string $next
223193
protected function getFile(array $cloudinaryResource): File
224194
{
225195
$fileIdentifier = $this->cloudinaryPathService->computeFileIdentifier($cloudinaryResource);
226-
return $this->storage->getFileByIdentifier($fileIdentifier);
196+
/** @var File|null $file */
197+
$file = $this->storage->getFileByIdentifier($fileIdentifier);
198+
199+
if (!$file) {
200+
throw new Exception('No file could be fine for file identifier ' . $fileIdentifier);
201+
}
202+
return $file;
227203
}
228204

229205
protected function getRequestInfo(array $payload): array
@@ -297,15 +273,15 @@ protected function clearCachePages(File $file): void
297273
GeneralUtility::makeInstance(CacheManager::class)
298274
->flushCachesInGroupByTags('pages', $tags);
299275

300-
// #. flush cloudinary cdn cache if extension is available
301-
if ($this->packageManager->isPackageAvailable('cloudflare')) {
302-
$this->flushCloudflareCdn($tags);
303-
}
276+
$this->eventDispatcher->dispatch(
277+
new ClearCachePageEvent($tags)
278+
);
304279
}
305280

306281
protected function findPagesWithFileReferences(File $file): array
307282
{
308283
$queryBuilder = $this->getQueryBuilder('sys_file_reference');
284+
// @phpstan-ignore-next-line
309285
return $queryBuilder
310286
->select('pid')
311287
->from('sys_file_reference')
@@ -363,7 +339,7 @@ protected function isRequestDelete(mixed $payload): bool
363339
protected function sendResponse(array $data): ResponseInterface
364340
{
365341
return $this->jsonResponse(
366-
json_encode($data)
342+
(string)json_encode($data)
367343
);
368344
}
369345

@@ -375,7 +351,7 @@ protected function checkEnvironment(): void
375351
}
376352
}
377353

378-
protected function getQueryBuilder($tableName): QueryBuilder
354+
protected function getQueryBuilder(string $tableName): QueryBuilder
379355
{
380356
/** @var ConnectionPool $connectionPool */
381357
$connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
@@ -386,7 +362,9 @@ protected static function getLogger(): Logger
386362
{
387363
/** @var Logger $logger */
388364
static $logger = null;
365+
// @phpstan-ignore-next-line
389366
if ($logger === null) {
367+
/** @var LogManager $logger */
390368
$logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
391369
}
392370
return $logger;
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace Visol\Cloudinary\Events;
4+
5+
/*
6+
* This file is part of the Visol/Cloudinary project under GPLv2 or later.
7+
*
8+
* For the full copyright and license information, please read the
9+
* LICENSE.md file that was distributed with this source code.
10+
*/
11+
12+
final class ClearCachePageEvent
13+
{
14+
protected array $tags = [];
15+
16+
public function __construct(array $tags)
17+
{
18+
$this->tags = $tags;
19+
}
20+
21+
public function getTags(): array
22+
{
23+
return $this->tags;
24+
}
25+
26+
public function setTags(array $tags): ClearCachePageEvent
27+
{
28+
$this->tags = $tags;
29+
return $this;
30+
}
31+
32+
}

phpstan-baseline.neon

Lines changed: 0 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -470,116 +470,6 @@ parameters:
470470
count: 1
471471
path: Classes/Controller/CloudinaryScanController.php
472472

473-
-
474-
message: "#^Call to an undefined method object\\:\\:flushCachesInGroupByTags\\(\\)\\.$#"
475-
count: 1
476-
path: Classes/Controller/CloudinaryWebHookController.php
477-
478-
-
479-
message: "#^Call to an undefined method object\\:\\:get\\(\\)\\.$#"
480-
count: 1
481-
path: Classes/Controller/CloudinaryWebHookController.php
482-
483-
-
484-
message: "#^Call to an undefined method object\\:\\:getLogger\\(\\)\\.$#"
485-
count: 1
486-
path: Classes/Controller/CloudinaryWebHookController.php
487-
488-
-
489-
message: "#^Call to method send\\(\\) on an unknown class Causal\\\\Cloudflare\\\\Services\\\\CloudflareService\\.$#"
490-
count: 1
491-
path: Classes/Controller/CloudinaryWebHookController.php
492-
493-
-
494-
message: "#^Cannot access offset 'to_public_id' on mixed\\.$#"
495-
count: 1
496-
path: Classes/Controller/CloudinaryWebHookController.php
497-
498-
-
499-
message: "#^Cannot call method fetchAllAssociative\\(\\) on Doctrine\\\\DBAL\\\\Result\\|int\\.$#"
500-
count: 1
501-
path: Classes/Controller/CloudinaryWebHookController.php
502-
503-
-
504-
message: "#^Class Causal\\\\Cloudflare\\\\Services\\\\CloudflareService not found\\.$#"
505-
count: 1
506-
path: Classes/Controller/CloudinaryWebHookController.php
507-
508-
-
509-
message: "#^Constant LF not found\\.$#"
510-
count: 1
511-
path: Classes/Controller/CloudinaryWebHookController.php
512-
513-
-
514-
message: "#^Method Visol\\\\Cloudinary\\\\Controller\\\\CloudinaryWebHookController\\:\\:flushCloudinaryCdn\\(\\) has parameter \\$publicId with no type specified\\.$#"
515-
count: 1
516-
path: Classes/Controller/CloudinaryWebHookController.php
517-
518-
-
519-
message: "#^Method Visol\\\\Cloudinary\\\\Controller\\\\CloudinaryWebHookController\\:\\:getFile\\(\\) should return TYPO3\\\\CMS\\\\Core\\\\Resource\\\\File but returns TYPO3\\\\CMS\\\\Core\\\\Resource\\\\File\\|TYPO3\\\\CMS\\\\Core\\\\Resource\\\\ProcessedFile\\|null\\.$#"
520-
count: 1
521-
path: Classes/Controller/CloudinaryWebHookController.php
522-
523-
-
524-
message: "#^Method Visol\\\\Cloudinary\\\\Controller\\\\CloudinaryWebHookController\\:\\:getQueryBuilder\\(\\) has parameter \\$tableName with no type specified\\.$#"
525-
count: 1
526-
path: Classes/Controller/CloudinaryWebHookController.php
527-
528-
-
529-
message: "#^PHPDoc tag @var for variable \\$cloudflareService contains unknown class Causal\\\\Cloudflare\\\\Services\\\\CloudflareService\\.$#"
530-
count: 1
531-
path: Classes/Controller/CloudinaryWebHookController.php
532-
533-
-
534-
message: "#^Parameter \\#1 \\$json of method TYPO3\\\\CMS\\\\Extbase\\\\Mvc\\\\Controller\\\\ActionController\\:\\:jsonResponse\\(\\) expects string\\|null, string\\|false given\\.$#"
535-
count: 1
536-
path: Classes/Controller/CloudinaryWebHookController.php
537-
538-
-
539-
message: "#^Parameter \\#1 \\$message of method Psr\\\\Log\\\\AbstractLogger\\:\\:warning\\(\\) expects string, int given\\.$#"
540-
count: 1
541-
path: Classes/Controller/CloudinaryWebHookController.php
542-
543-
-
544-
message: "#^Parameter \\#1 \\$payload of method Visol\\\\Cloudinary\\\\Controller\\\\CloudinaryWebHookController\\:\\:getRequestInfo\\(\\) expects array, mixed given\\.$#"
545-
count: 1
546-
path: Classes/Controller/CloudinaryWebHookController.php
547-
548-
-
549-
message: "#^Property Visol\\\\Cloudinary\\\\Controller\\\\CloudinaryWebHookController\\:\\:\\$cloudinaryPathService \\(Visol\\\\Cloudinary\\\\Services\\\\CloudinaryPathService\\) does not accept object\\.$#"
550-
count: 1
551-
path: Classes/Controller/CloudinaryWebHookController.php
552-
553-
-
554-
message: "#^Property Visol\\\\Cloudinary\\\\Controller\\\\CloudinaryWebHookController\\:\\:\\$cloudinaryResourceService \\(Visol\\\\Cloudinary\\\\Services\\\\CloudinaryResourceService\\) does not accept object\\.$#"
555-
count: 1
556-
path: Classes/Controller/CloudinaryWebHookController.php
557-
558-
-
559-
message: "#^Property Visol\\\\Cloudinary\\\\Controller\\\\CloudinaryWebHookController\\:\\:\\$packageManager \\(TYPO3\\\\CMS\\\\Core\\\\Package\\\\PackageManager\\) does not accept object\\.$#"
560-
count: 1
561-
path: Classes/Controller/CloudinaryWebHookController.php
562-
563-
-
564-
message: "#^Property Visol\\\\Cloudinary\\\\Controller\\\\CloudinaryWebHookController\\:\\:\\$processedFileRepository \\(TYPO3\\\\CMS\\\\Core\\\\Resource\\\\ProcessedFileRepository\\) does not accept object\\.$#"
565-
count: 1
566-
path: Classes/Controller/CloudinaryWebHookController.php
567-
568-
-
569-
message: "#^Property Visol\\\\Cloudinary\\\\Controller\\\\CloudinaryWebHookController\\:\\:\\$scanService \\(Visol\\\\Cloudinary\\\\Services\\\\CloudinaryScanService\\) does not accept object\\.$#"
570-
count: 1
571-
path: Classes/Controller/CloudinaryWebHookController.php
572-
573-
-
574-
message: "#^Strict comparison using \\=\\=\\= between TYPO3\\\\CMS\\\\Core\\\\Log\\\\Logger and null will always evaluate to false\\.$#"
575-
count: 1
576-
path: Classes/Controller/CloudinaryWebHookController.php
577-
578-
-
579-
message: "#^Strict comparison using \\=\\=\\= between int\\<0, max\\>\\|false and null will always evaluate to false\\.$#"
580-
count: 1
581-
path: Classes/Controller/CloudinaryWebHookController.php
582-
583473
-
584474
message: "#^Call to an undefined method object\\:\\:getPropertyFromAspect\\(\\)\\.$#"
585475
count: 2

phpstan.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,8 @@ parameters:
77
- Configuration
88
checkMissingIterableValueType: false
99
reportUnmatchedIgnoredErrors: false
10+
ignoreErrors:
11+
-
12+
message: '#does not accept object.$#'
13+
-
14+
message: '#^Call to an undefined method object#'

0 commit comments

Comments
 (0)