Skip to content

Commit

Permalink
Support for eZ kernel 7.0 (#122)
Browse files Browse the repository at this point in the history
* Allow installation on eZ kernel 7.0

* Implement reset method in data collector

* Remove usage of deprecated GatewayCachePurger

* Replace Stash cache pool with Symfony one

* Remove generating of Stash configuration

* Update tests

* Require only eZ kernel 7.0

* Refactor cache code for symfony cache implementation of persistence cache

* Fix cache purger tests
  • Loading branch information
emodric authored and andrerom committed Dec 18, 2017
1 parent 0116fce commit cbe31ca
Show file tree
Hide file tree
Showing 14 changed files with 147 additions and 294 deletions.
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ language: php

# run tests on php misc php versions
php:
- 5.6
- 7.0
- 7.1
- 7.2

cache:
directories:
Expand Down
133 changes: 70 additions & 63 deletions bundle/Cache/PersistenceCachePurger.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@
*/
namespace eZ\Bundle\EzPublishLegacyBundle\Cache;

use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;
use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface;
use eZ\Publish\API\Repository\Exceptions\NotFoundException as APINotFoundException;
use eZ\Publish\SPI\Persistence\Content\Location\Handler as LocationHandlerInterface;
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentType;
use eZ\Publish\Core\Base\Exceptions\NotFoundException;
use eZ\Publish\Core\Persistence\Cache\CacheServiceDecorator;
use Psr\Log\LoggerInterface;

/**
* Class PersistenceCachePurger.
Expand All @@ -23,7 +22,7 @@ class PersistenceCachePurger implements CacheClearerInterface
use Switchable;

/**
* @var \eZ\Publish\Core\Persistence\Cache\CacheServiceDecorator
* @var \Symfony\Component\Cache\Adapter\TagAwareAdapterInterface
*/
protected $cache;

Expand All @@ -33,34 +32,29 @@ class PersistenceCachePurger implements CacheClearerInterface
protected $locationHandler;

/**
* Avoid clearing sub elements if all cache is already cleared, avoids redundant calls to Stash.
* Avoid clearing sub elements if all cache is already cleared, avoids redundant calls to cache.
*
* @var bool
*/
protected $allCleared = false;

/**
* @var \Psr\Log\LoggerInterface
*/
protected $logger;

/**
* Setups current handler with everything needed.
*
* @param \eZ\Publish\Core\Persistence\Cache\CacheServiceDecorator $cache
* @param \eZ\Publish\SPI\Persistence\Content\Location\Handler $locationHandler
* @param \Psr\Log\LoggerInterface $logger
* @param \Symfony\Component\Cache\Adapter\TagAwareAdapterInterface $cache
* @param \eZ\Publish\SPI\Persistence\Content\Location\Handler $locationHandler (using SPI cache instance so calls are cached)
*/
public function __construct(CacheServiceDecorator $cache, LocationHandlerInterface $locationHandler, LoggerInterface $logger)
public function __construct(TagAwareAdapterInterface $cache, LocationHandlerInterface $locationHandler)
{
$this->cache = $cache;
$this->locationHandler = $locationHandler;
$this->logger = $logger;
}

/**
* Clear all persistence cache.
*
* In legacy kernel used when user presses clear all cache button in admin interface.
*
* Sets a internal flag 'allCleared' to avoid clearing cache several times
*/
public function all()
Expand Down Expand Up @@ -98,7 +92,9 @@ public function resetAllCleared()
/**
* Clear all content persistence cache, or by locationIds (legacy content/cache mechanism is location based).
*
* Either way all location and urlAlias cache is cleared as well.
* In legacy kernel used when any kind of event triggers cache clearing for content.
* If amount of accepted nodes goes over threshold, or in case where all content cache is cleared from admin
* interface, argument will be empty.
*
* @param int|int[]|null $locationIds Ids of location we need to purge content cache for. Purges all content cache if null
*
Expand All @@ -113,43 +109,41 @@ public function content($locationIds = null)
}

if ($locationIds === null) {
$this->cache->clear('content');
goto relatedCache;
} elseif (!is_array($locationIds)) {
$locationIds = array($locationIds);
$this->cache->clear();

return $locationIds;
}

if (!is_array($locationIds)) {
$locationIds = [$locationIds];
}

$tags = [];
foreach ($locationIds as $id) {
if (!is_scalar($id)) {
throw new InvalidArgumentType('$id', 'int[]|null', $id);
}

$tags[] = 'location-' . $id;
$tags[] = 'urlAlias-location-' . $id;

try {
$location = $this->locationHandler->load($id);
$this->cache->clear('content', $location->contentId);
$this->cache->clear('content', 'info', $location->contentId);
$this->cache->clear('content', 'info', 'remoteId');
$this->cache->clear('content', 'locations', $location->contentId);
$this->cache->clear('user', 'role', 'assignments', 'byGroup', $location->contentId);
$this->cache->clear('user', 'role', 'assignments', 'byGroup', 'inherited', $location->contentId);
} catch (NotFoundException $e) {
$this->logger->notice(
"Unable to load the location with the id '$id' to clear its cache"
);
$tags[] = 'content-' . $location->contentId;
} catch (APINotFoundException $e) {
// Location might be deleted, so catch and we clear by location id which is ok for most cases.
}
}

// clear content related cache as well
relatedCache:
$this->cache->clear('urlAlias');
$this->cache->clear('location');
$this->cache->invalidateTags($tags);

return $locationIds;
}

/**
* Clears persistence cache for given $contentId and $versionNo.
*
* In legacy kernel used when storing a draft.
*
* @param int $contentId
* @param int $versionNo
*/
Expand All @@ -159,12 +153,16 @@ public function contentVersion($contentId, $versionNo)
return;
}

$this->cache->clear('content', $contentId, $versionNo);
$this->cache->deleteItem("ez-content-version-info-${contentId}-${versionNo}");
$this->cache->invalidateTags(["content-${contentId}-version-list"]);
}

/**
* Clear all contentType persistence cache, or by id.
*
* In legacy kernel used when editing content type, in this case we get id.
* Also used when clearing content type meta data cache in admin cache interface (no id).
*
* @param int|null $id Purges all contentType cache if null
* @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentType On invalid $id type
*/
Expand All @@ -175,63 +173,61 @@ public function contentType($id = null)
}

if ($id === null) {
$this->cache->clear('contentType');
$this->cache->invalidateTags(['type-map']);
} elseif (is_scalar($id)) {
$this->cache->clear('contentType', $id);
$this->cache->invalidateTags(['type-' . $id]);
} else {
throw new InvalidArgumentType('$id', 'int|null', $id);
}
}

/**
* Clear all contentTypeGroup persistence cache, or by id.
* Clear contentTypeGroup persistence cache by id.
*
* Either way, contentType cache is also cleared as it contains the relation to contentTypeGroups
* In legacy kernel used when editing/removing content type group, so there is always an id.
*
* @param int|null $id Purges all contentTypeGroup cache if null
* @param int $id
* @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentType On invalid $id type
*/
public function contentTypeGroup($id = null)
public function contentTypeGroup($id)
{
if ($this->allCleared === true || $this->isSwitchedOff()) {
return;
}

if ($id === null) {
$this->cache->clear('contentTypeGroup');
} elseif (is_scalar($id)) {
$this->cache->clear('contentTypeGroup', $id);
if (is_scalar($id)) {
// @todo should also clear content type cache for items themselves in case of link/unlink changes, kernel should have a "type-all" tag for this
$this->cache->invalidateTags(['type-group-' . $id, 'type-map']);
} else {
throw new InvalidArgumentType('$id', 'int|null', $id);
}

// clear content type in case of changes as it contains the relation to groups
$this->cache->clear('contentType');
}

/**
* Clear all section persistence cache, or by id.
* Clear section persistence cache by id.
*
* @param int|null $id Purges all section cache if null
* In legacy kernel used when editing section, so there is always an id.
*
* @param int $id
* @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentType On invalid $id type
*/
public function section($id = null)
public function section($id)
{
if ($this->allCleared === true || $this->isSwitchedOff()) {
return;
}

if ($id === null) {
$this->cache->clear('section');
} elseif (is_scalar($id)) {
$this->cache->clear('section', $id);
if (is_scalar($id)) {
$this->cache->invalidateTags(['section-' . $id]);
} else {
throw new InvalidArgumentType('$id', 'int|null', $id);
}
}

/**
* Clear all language persistence cache, or by id.
* Clear language persistence cache by id.
*
* In legacy kernel used when editing language, so there is always an id.
*
* @param array|int $ids
*/
Expand All @@ -242,27 +238,34 @@ public function languages($ids)
}

$ids = (array)$ids;
$tags = [];
foreach ($ids as $id) {
$this->cache->clear('language', $id);
$tags[] = 'language-' . $id;
}

$this->cache->invalidateTags($tags);
}

/**
* Clear object state assignment persistence cache by content id.
*
* In legacy kernel used when assigning statet to an content.
*
* @param int $contentId
*/
public function stateAssign($contentId)
{
if ($this->allCleared === true || $this->enabled === false) {
if ($this->allCleared === true || $this->isSwitchedOff()) {
return;
}

$this->cache->clear('objectstate', 'byContent', $contentId);
$this->cache->invalidateTags(['content-' . $contentId]);
}

/**
* Clear all user persistence cache.
* Clear meta info on users in Persistence.
*
* In legacy kernel used when clearing meta info cache on users in eZUser, never with id.
*
* @param int|null $id Purges all users cache if null
* @throws \eZ\Publish\Core\Base\Exceptions\InvalidArgumentType On invalid $id type
Expand All @@ -274,9 +277,11 @@ public function user($id = null)
}

if ($id === null) {
$this->cache->clear('user');
// @todo From the looks of usage in legacy we only need to clear meta data here, and there is no such thing
// in persistence so we ignore it for now.
//$this->cache->clear();
} elseif (is_scalar($id)) {
$this->cache->clear('user', $id);
$this->cache->invalidateTags(['user-' . $id]);
} else {
throw new InvalidArgumentType('$id', 'int|null', $id);
}
Expand All @@ -285,6 +290,8 @@ public function user($id = null)
/**
* Clears any caches necessary.
*
* Used by symfony cache clear command.
*
* @param string $cacheDir the cache directory
*/
public function clear($cacheDir)
Expand Down
30 changes: 19 additions & 11 deletions bundle/Cache/SwitchableHttpCachePurger.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,23 @@
*/
namespace eZ\Bundle\EzPublishLegacyBundle\Cache;

use eZ\Publish\Core\MVC\Symfony\Cache\GatewayCachePurger;
use EzSystems\PlatformHttpCacheBundle\PurgeClient\PurgeClientInterface;

/**
* A GatewayCachePurger decorator that allows the actual purger to be switched on/off.
* A PurgeClient decorator that allows the actual purger to be switched on/off.
*/
class SwitchableHttpCachePurger implements GatewayCachePurger
class SwitchableHttpCachePurger implements PurgeClientInterface
{
use Switchable;

/** @var \eZ\Publish\Core\MVC\Symfony\Cache\GatewayCachePurger */
private $gatewayCachePurger;
/**
* @var \EzSystems\PlatformHttpCacheBundle\PurgeClient\PurgeClientInterface
*/
private $purgeClient;

public function __construct(GatewayCachePurger $gatewayCachePurger)
public function __construct(PurgeClientInterface $purgeClient)
{
$this->gatewayCachePurger = $gatewayCachePurger;
$this->purgeClient = $purgeClient;
}

public function purge($locationIds)
Expand All @@ -30,7 +32,7 @@ public function purge($locationIds)
return $locationIds;
}

return $this->gatewayCachePurger->purge($locationIds);
return $this->purgeClient->purge($locationIds);
}

public function purgeAll()
Expand All @@ -39,15 +41,21 @@ public function purgeAll()
return;
}

$this->gatewayCachePurger->purgeAll();
$this->purgeClient->purgeAll();
}

/**
* Implemented for BC with deprecated PurgeClientInterface::purgeForContent from eZ kernel.
*
* @param int $contentId
* @param array $locationIds
*/
public function purgeForContent($contentId, $locationIds = array())
{
if ($this->isSwitchedOff()) {
if ($this->isSwitchedOff() || !method_exists($this->purgeClient, 'purgeForContent')) {
return;
}

$this->gatewayCachePurger->purgeForContent($contentId, $locationIds);
$this->purgeClient->purgeForContent($contentId, $locationIds);
}
}
5 changes: 5 additions & 0 deletions bundle/Collector/LegacyTemplatesCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,9 @@ public function getLegacyTemplates()
{
return $this->data['legacyTemplates'];
}

public function reset()
{
$this->data = ['legacyTemplates' => []];
}
}
Loading

0 comments on commit cbe31ca

Please sign in to comment.