vendor/ibexa/http-cache/src/lib/EventSubscriber/CachePurge/ContentEventsSubscriber.php line 172

Open in your IDE?
  1. <?php
  2. /**
  3. * @copyright Copyright (C) Ibexa AS. All rights reserved.
  4. * @license For full copyright and license information view LICENSE file distributed with this source code.
  5. */
  6. declare(strict_types=1);
  7. namespace Ibexa\HttpCache\EventSubscriber\CachePurge;
  8. use Ibexa\Contracts\Core\Persistence\Content\Handler as ContentHandler;
  9. use Ibexa\Contracts\Core\Persistence\Content\Location\Handler as LocationHandler;
  10. use Ibexa\Contracts\Core\Persistence\URL\Handler as UrlHandler;
  11. use Ibexa\Contracts\Core\Repository\Events\Content\CopyContentEvent;
  12. use Ibexa\Contracts\Core\Repository\Events\Content\CreateContentDraftEvent;
  13. use Ibexa\Contracts\Core\Repository\Events\Content\DeleteContentEvent;
  14. use Ibexa\Contracts\Core\Repository\Events\Content\DeleteVersionEvent;
  15. use Ibexa\Contracts\Core\Repository\Events\Content\HideContentEvent;
  16. use Ibexa\Contracts\Core\Repository\Events\Content\PublishVersionEvent;
  17. use Ibexa\Contracts\Core\Repository\Events\Content\RevealContentEvent;
  18. use Ibexa\Contracts\Core\Repository\Events\Content\UpdateContentEvent;
  19. use Ibexa\Contracts\Core\Repository\Events\Content\UpdateContentMetadataEvent;
  20. use Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException;
  21. use Ibexa\Contracts\Core\Repository\Values\ContentType\ContentType;
  22. use Ibexa\Contracts\Core\Repository\Values\ContentType\FieldDefinition;
  23. use Ibexa\Contracts\HttpCache\Handler\ContentTagInterface;
  24. use Ibexa\Contracts\HttpCache\PurgeClient\PurgeClientInterface;
  25. final class ContentEventsSubscriber extends AbstractSubscriber
  26. {
  27. /** @var \Ibexa\Contracts\Core\Persistence\Content\Handler */
  28. private $contentHandler;
  29. /** @var bool */
  30. private $isTranslationAware;
  31. public function __construct(
  32. PurgeClientInterface $purgeClient,
  33. LocationHandler $locationHandler,
  34. UrlHandler $urlHandler,
  35. ContentHandler $contentHandler,
  36. bool $isTranslationAware
  37. ) {
  38. parent::__construct($purgeClient, $locationHandler, $urlHandler);
  39. $this->isTranslationAware = $isTranslationAware;
  40. $this->contentHandler = $contentHandler;
  41. }
  42. public static function getSubscribedEvents(): array
  43. {
  44. return [
  45. CopyContentEvent::class => 'onCopyContentEvent',
  46. CreateContentDraftEvent::class => 'onCreateContentDraftEvent',
  47. DeleteContentEvent::class => 'onDeleteContentEvent',
  48. DeleteVersionEvent::class => 'onDeleteVersionEvent',
  49. HideContentEvent::class => 'onHideContentEvent',
  50. PublishVersionEvent::class => 'onPublishVersionEvent',
  51. RevealContentEvent::class => 'onRevealContentEvent',
  52. UpdateContentEvent::class => 'onUpdateContentEvent',
  53. UpdateContentMetadataEvent::class => 'onUpdateContentMetadataEvent',
  54. ];
  55. }
  56. public function onCopyContentEvent(CopyContentEvent $event): void
  57. {
  58. $contentId = $event->getContentInfo()->id;
  59. $parentLocationId = $event->getDestinationLocationCreateStruct()->parentLocationId;
  60. $this->purgeClient->purge([
  61. ContentTagInterface::CONTENT_PREFIX . $contentId,
  62. ContentTagInterface::LOCATION_PREFIX . $parentLocationId,
  63. ContentTagInterface::PATH_PREFIX . $parentLocationId,
  64. ]);
  65. }
  66. public function onCreateContentDraftEvent(CreateContentDraftEvent $event): void
  67. {
  68. $contentId = $event->getContentInfo()->id;
  69. $this->purgeClient->purge([
  70. ContentTagInterface::CONTENT_VERSION_PREFIX . $contentId,
  71. ]);
  72. }
  73. public function onDeleteContentEvent(DeleteContentEvent $event): void
  74. {
  75. $contentId = $event->getContentInfo()->id;
  76. $tags = $this->getContentTags($contentId);
  77. foreach ($event->getLocations() as $locationId) {
  78. $tags[] = ContentTagInterface::PATH_PREFIX . $locationId;
  79. }
  80. $this->purgeClient->purge($tags);
  81. }
  82. public function onDeleteVersionEvent(DeleteVersionEvent $event): void
  83. {
  84. $contentId = $event->getVersionInfo()->getContentInfo()->id;
  85. $this->purgeClient->purge([
  86. ContentTagInterface::CONTENT_VERSION_PREFIX . $contentId,
  87. ]);
  88. }
  89. public function onHideContentEvent(HideContentEvent $event): void
  90. {
  91. $contentId = $event->getContentInfo()->id;
  92. $tags = array_merge(
  93. $this->getContentTags($contentId),
  94. $this->getContentLocationsTags($contentId)
  95. );
  96. $this->purgeClient->purge($tags);
  97. }
  98. public function onPublishVersionEvent(PublishVersionEvent $event): void
  99. {
  100. $content = $event->getContent();
  101. $versionInfo = $content->getVersionInfo();
  102. $contentType = $content->getContentType();
  103. $contentId = $versionInfo->getContentInfo()->id;
  104. $tags = array_merge(
  105. $this->getContentTags($contentId),
  106. $this->getContentLocationsTags($contentId)
  107. );
  108. $initialLanguageCode = $versionInfo->getInitialLanguage()->languageCode;
  109. $mainLanguageCode = $versionInfo->getContentInfo()->mainLanguageCode;
  110. $isNewTranslation = true;
  111. try {
  112. $prevVersionInfo = $this->contentHandler->loadVersionInfo($contentId, $event->getVersionInfo()->getContentInfo()->currentVersionNo);
  113. $isNewTranslation = !in_array($initialLanguageCode, $prevVersionInfo->languageCodes);
  114. } catch (NotFoundException $e) {
  115. }
  116. if (
  117. !$this->isTranslationAware ||
  118. $isNewTranslation ||
  119. ($initialLanguageCode === $mainLanguageCode && !$this->isContentTypeFullyTranslatable($contentType))
  120. ) {
  121. $this->purgeClient->purge($tags);
  122. return;
  123. }
  124. $tags = array_map(static function (string $tag) use ($initialLanguageCode): string {
  125. return $tag . $initialLanguageCode;
  126. }, $tags);
  127. $tags[] = ContentTagInterface::CONTENT_ALL_TRANSLATIONS_PREFIX . $contentId;
  128. $this->purgeClient->purge($tags);
  129. }
  130. public function onRevealContentEvent(RevealContentEvent $event): void
  131. {
  132. $contentId = $event->getContentInfo()->id;
  133. $tags = array_merge(
  134. $this->getContentTags($contentId),
  135. $this->getContentLocationsTags($contentId)
  136. );
  137. $this->purgeClient->purge($tags);
  138. }
  139. public function onUpdateContentEvent(UpdateContentEvent $event): void
  140. {
  141. $contentId = $event->getContent()->getVersionInfo()->getContentInfo()->id;
  142. $this->purgeClient->purge([
  143. ContentTagInterface::CONTENT_VERSION_PREFIX . $contentId,
  144. ]);
  145. }
  146. public function onUpdateContentMetadataEvent(UpdateContentMetadataEvent $event): void
  147. {
  148. $contentId = $event->getContent()->getVersionInfo()->getContentInfo()->id;
  149. $this->purgeClient->purge(
  150. $this->getContentTags($contentId)
  151. );
  152. }
  153. private function isContentTypeFullyTranslatable(ContentType $contentType): bool
  154. {
  155. return !$contentType->getFieldDefinitions()->any(static function (FieldDefinition $fieldDefinition): bool {
  156. return !$fieldDefinition->isTranslatable;
  157. });
  158. }
  159. }
  160. class_alias(ContentEventsSubscriber::class, 'EzSystems\PlatformHttpCacheBundle\EventSubscriber\CachePurge\ContentEventsSubscriber');