Skip to content

Commit

Permalink
[BUGFIX] Invalidate sitemaps cache when site config changes
Browse files Browse the repository at this point in the history
  • Loading branch information
eliashaeussler committed Sep 11, 2023
1 parent d5ae2d1 commit ad3bd1b
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 0 deletions.
24 changes: 24 additions & 0 deletions Classes/Cache/SitemapsCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,30 @@ public function set(array $sitemaps): void
}
}

/**
* @internal
*/
public function remove(
Core\Site\Entity\Site $site,
Core\Site\Entity\SiteLanguage $siteLanguage = null,
): void {
$siteIdentifier = $site->getIdentifier();

// Remove whole site from cache
if ($siteLanguage === null) {
$this->cache->remove($siteIdentifier);

return;
}

$cacheData = $this->readCache($siteIdentifier);

// Remove specific site language from cache data
unset($cacheData[$siteLanguage->getLanguageId()]);

$this->writeCache($siteIdentifier, $cacheData);
}

/**
* @return array<int, list<string>>
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

/*
* This file is part of the TYPO3 CMS extension "warming".
*
* Copyright (C) 2023 Elias Häußler <elias@haeussler.dev>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

namespace EliasHaeussler\Typo3Warming\EventListener;

use EliasHaeussler\Typo3Warming\Cache;
use TYPO3\CMS\Core;

/**
* InvalidateSitemapsCacheOnChangedSiteConfigurationListener
*
* @author Elias Häußler <elias@haeussler.dev>
* @license GPL-2.0-or-later
*/
final class InvalidateSitemapsCacheOnChangedSiteConfigurationListener
{
public function __construct(
private readonly Cache\SitemapsCache $cache,
private readonly Core\Site\SiteFinder $siteFinder,
) {
}

public function __invoke(Core\Configuration\Event\SiteConfigurationBeforeWriteEvent $event): void
{
try {
$site = $this->siteFinder->getSiteByIdentifier($event->getSiteIdentifier());
} catch (Core\Exception\SiteNotFoundException) {
// Ignore new sites, they should not be cached anyway
return;
}

$this->cache->remove($site);
}
}
6 changes: 6 additions & 0 deletions Configuration/Services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ services:
EliasHaeussler\Typo3Warming\Crawler\Strategy\CrawlingStrategyFactory:
arguments:
$strategies: !tagged_locator { tag: 'warming.crawling_strategy', default_index_method: 'getName' }

EliasHaeussler\Typo3Warming\EventListener\InvalidateSitemapsCacheOnChangedSiteConfigurationListener:
tags:
- name: event.listener
identifier: 'warmingInvalidateSitemapsCacheOnChangedSiteConfigurationListener'

EliasHaeussler\Typo3Warming\Http\Client\ClientFactory:
public: true
EliasHaeussler\Typo3Warming\Service\CacheWarmupService:
Expand Down
90 changes: 90 additions & 0 deletions Tests/Functional/Cache/SitemapsCacheTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,30 @@ public function getReturnsEmptyArrayIfCacheOfGivenSiteIsEmpty(): void
self::assertSame([], $this->subject->get($site));
}

#[Framework\Attributes\Test]
public function getReturnsEmptyArrayIfCacheOfGivenSiteLanguageIsEmpty(): void
{
$site = new Core\Site\Entity\Site('baz', 1, []);

$this->cache->set(
'baz',
sprintf(
'return %s;',
var_export(
[
1 => [
'https://www.example.com/baz',
'https://www.example.com/bar',
],
],
true,
),
),
);

self::assertSame([], $this->subject->get($site));
}

#[Framework\Attributes\Test]
public function getReturnsCachedSitemapsForDefaultLanguage(): void
{
Expand Down Expand Up @@ -210,4 +234,70 @@ public function setStoresGivenSitemapInCache(): void
self::assertEquals($sitemaps, $this->subject->get($site, $site->getDefaultLanguage()));
self::assertTrue($this->cache->has('foo'));
}

#[Framework\Attributes\Test]
public function removeInitializesCacheIfCacheIsMissing(): void
{
self::assertFalse($this->cache->has('foo'));

$site = new Core\Site\Entity\Site('foo', 1, []);

$this->subject->remove($site);

self::assertFalse($this->cache->has('foo'));
}

#[Framework\Attributes\Test]
public function removeRemovesSitemapsOfGivenSiteFromCache(): void
{
$site = new Core\Site\Entity\Site('foo', 1, []);
$sitemaps = [
new Src\Sitemap\SiteAwareSitemap(
new Core\Http\Uri('https://www.example.com/baz'),
$site,
$site->getDefaultLanguage(),
),
new Src\Sitemap\SiteAwareSitemap(
new Core\Http\Uri('https://www.example.com/bar'),
$site,
$site->getDefaultLanguage(),
),
];

$this->subject->set($sitemaps);

self::assertTrue($this->cache->has('foo'));

$this->subject->remove($site);

self::assertFalse($this->cache->has('foo'));
}

#[Framework\Attributes\Test]
public function removeRemovesSitemapsOfGivenSiteAndSiteLanguageFromCache(): void
{
$site = new Core\Site\Entity\Site('foo', 1, []);
$siteLanguage = new Core\Site\Entity\SiteLanguage(1, 'de_DE.UTF-8', new Core\Http\Uri('https://example.com'), []);

$sitemaps = [
new Src\Sitemap\SiteAwareSitemap(
new Core\Http\Uri('https://www.example.com/'),
$site,
$site->getDefaultLanguage(),
),
new Src\Sitemap\SiteAwareSitemap(
new Core\Http\Uri('https://www.example.com/foo'),
$site,
$siteLanguage,
),
];

$this->subject->set($sitemaps);

self::assertTrue($this->cache->has('foo'));

$this->subject->remove($site, $siteLanguage);

self::assertCount(1, $this->cache->require('foo'));
}
}

0 comments on commit ad3bd1b

Please sign in to comment.