Skip to content
This repository has been archived by the owner on Mar 1, 2023. It is now read-only.

Commit

Permalink
[RELEASE] Release 1.5.1
Browse files Browse the repository at this point in the history
  • Loading branch information
romm committed Mar 2, 2017
2 parents afd294e + 732ecbf commit a9b633c
Show file tree
Hide file tree
Showing 11 changed files with 316 additions and 18 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,16 @@
# ![Configuration Object](Documentation/Images/configuration-object-icon@medium.png) Configuration Object – ChangeLog

1.5.1 - 2017-03-02
------------------

An issue concerning the cache handling has been solved. Upgrading is recommended!

- **[[#12](https://github.com/romm/configuration_object/pull/12)] [BUGFIX] Fix incorrect cache handling**

This commit refactors a major part of how "dynamic" caches are handled by Configuration Object API. In the provided cache service that can be attached to a configuration object, it is possible to declare the options for this cache; it means the cache is registered long after TYPO3 initialization, resulting in issues like caches entries not being deleted on caches flush.

A new internal cache service has been introduced, which will handle these "dynamic" caches: when one of these caches is used, its configuration is saved in the internal cache: in further request, the cache will be properly registered during TYPO3 initialization.

1.5.0 - 2017-02-27
------------------

Expand Down
28 changes: 26 additions & 2 deletions Classes/Core/Core.php
Expand Up @@ -13,6 +13,7 @@

namespace Romm\ConfigurationObject\Core;

use Romm\ConfigurationObject\Core\Service\CacheService;
use Romm\ConfigurationObject\Exceptions\MethodNotFoundException;
use Romm\ConfigurationObject\Service\Items\Parents\ParentsUtility;
use Romm\ConfigurationObject\Service\ServiceFactory;
Expand All @@ -32,7 +33,6 @@
*/
class Core implements SingletonInterface
{

/**
* @var Core
*/
Expand Down Expand Up @@ -63,6 +63,11 @@ class Core implements SingletonInterface
*/
protected $parentsUtility;

/**
* @var CacheService
*/
protected $cacheService;

/**
* @var array
*/
Expand Down Expand Up @@ -173,7 +178,10 @@ protected function isPropertyGettable($object, $propertyName)
*/
public function getServiceFactoryInstance()
{
return GeneralUtility::makeInstance(ServiceFactory::class);
/** @var ServiceFactory $serviceFactory */
$serviceFactory = GeneralUtility::makeInstance(ServiceFactory::class);

return $serviceFactory;
}

/**
Expand Down Expand Up @@ -255,4 +263,20 @@ public function injectParentsUtility(ParentsUtility $parentsUtility)
{
$this->parentsUtility = $parentsUtility;
}

/**
* @return CacheService
*/
public function getCacheService()
{
return $this->cacheService;
}

/**
* @param CacheService $cacheService
*/
public function injectCacheService(CacheService $cacheService)
{
$this->cacheService = $cacheService;
}
}
127 changes: 127 additions & 0 deletions Classes/Core/Service/CacheService.php
@@ -0,0 +1,127 @@
<?php
/*
* 2017 Romain CANON <romain.hydrocanon@gmail.com>
*
* This file is part of the TYPO3 Configuration Object project.
* It is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License, either
* version 3 of the License, or any later version.
*
* For the full copyright and license information, see:
* http://www.gnu.org/licenses/gpl-3.0.html
*/

namespace Romm\ConfigurationObject\Core\Service;

use TYPO3\CMS\Core\Cache\Backend\FileBackend;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
use TYPO3\CMS\Core\Cache\Frontend\VariableFrontend;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;

class CacheService implements SingletonInterface
{
const CACHE_IDENTIFIER = 'cache_configuration_object';
const CACHE_TAG_DYNAMIC_CACHE = 'dynamic-cache';

/**
* Options for the internal cache.
*
* @var array
*/
protected $cacheOptions = [
'backend' => FileBackend::class,
'frontend' => VariableFrontend::class,
'groups' => ['all', 'system']
];

/**
* Function called from `ext_localconf` file which will register the
* internal cache earlier.
*
* @internal
*/
public function registerInternalCache()
{
$this->getCacheManager()
->setCacheConfigurations([self::CACHE_IDENTIFIER => $this->cacheOptions]);
}

/**
* This function will take care of initializing all caches that were defined
* previously by the `CacheService` which allows dynamic caches to be used
* for every configuration object type.
*
* @see \Romm\ConfigurationObject\Service\Items\Cache\CacheService::initialize()
* @internal
*/
public function registerDynamicCaches()
{
$dynamicCaches = $this->getCache()->getByTag(self::CACHE_TAG_DYNAMIC_CACHE);

foreach ($dynamicCaches as $cacheData) {
$identifier = $cacheData['identifier'];
$options = $cacheData['options'];

$this->registerCacheInternal($identifier, $options);
}
}

/**
* Registers a new dynamic cache: the cache will be added to the cache
* manager after this function is executed. Its configuration will also be
* remembered so the cache will be registered properly during the cache
* framework initialization in further requests.
*
* @param string $identifier
* @param array $options
*/
public function registerDynamicCache($identifier, array $options)
{
if (false === $this->getCache()->has($identifier)) {
$this->getCache()->set(
$identifier,
[
'identifier' => $identifier,
'options' => $options
],
[self::CACHE_TAG_DYNAMIC_CACHE]
);
}

$this->registerCacheInternal($identifier, $options);
}

/**
* @param string $identifier
* @param array $options
*/
protected function registerCacheInternal($identifier, array $options)
{
$cacheManager = $this->getCacheManager();

if (false === $cacheManager->hasCache($identifier)) {
$cacheManager->setCacheConfigurations([$identifier => $options]);
}
}

/**
* @return FrontendInterface
*/
protected function getCache()
{
return $this->getCacheManager()->getCache(self::CACHE_IDENTIFIER);
}

/**
* @return CacheManager
*/
protected function getCacheManager()
{
/** @var CacheManager $cacheManager */
$cacheManager = GeneralUtility::makeInstance(CacheManager::class);

return $cacheManager;
}
}
21 changes: 10 additions & 11 deletions Classes/Service/Items/Cache/CacheService.php
Expand Up @@ -52,7 +52,7 @@ class CacheService extends AbstractService implements ConfigurationObjectBeforeS
/**
* Default identifier of the cache instance.
*/
const DEFAULT_CACHE_IDENTIFIER = 'cache_configuration_object';
const DEFAULT_CACHE_IDENTIFIER = 'cache_configuration_object_default';

/**
* Default backend cache class name.
Expand Down Expand Up @@ -119,18 +119,17 @@ class CacheService extends AbstractService implements ConfigurationObjectBeforeS
public function initialize()
{
$this->cacheIdentifier = $this->options[self::OPTION_CACHE_NAME];
$options = [
'backend' => $this->options[self::OPTION_CACHE_BACKEND],
'frontend' => VariableFrontend::class,
'groups' => $this->options[self::OPTION_CACHE_GROUPS],
'options' => $this->options[self::OPTION_CACHE_OPTIONS]
];

// Adds the cache to the list of TYPO3 caches.
$this->getCacheManager()->setCacheConfigurations(
[
$this->cacheIdentifier => [
'backend' => $this->options[self::OPTION_CACHE_BACKEND],
'frontend' => VariableFrontend::class,
'groups' => $this->options[self::OPTION_CACHE_GROUPS],
'options' => $this->options[self::OPTION_CACHE_OPTIONS]
]
]
);
Core::get()
->getCacheService()
->registerDynamicCache($this->cacheIdentifier, $options);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions Documentation/Settings.yml
Expand Up @@ -6,8 +6,8 @@
conf.py:
copyright: 2016
project: Configuration Object
version: 1.5.0
release: 1.5.0
version: 1.5.1
release: 1.5.1
latex_documents:
- - Index
- configuration_object.tex
Expand Down
10 changes: 10 additions & 0 deletions Tests/Unit/ConfigurationObjectUnitTestUtility.php
Expand Up @@ -4,6 +4,7 @@
use Romm\ConfigurationObject\ConfigurationObjectFactory;
use Romm\ConfigurationObject\ConfigurationObjectMapper;
use Romm\ConfigurationObject\Core\Core;
use Romm\ConfigurationObject\Core\Service\CacheService as InternalCacheService;
use Romm\ConfigurationObject\Service\Items\Cache\CacheService;
use Romm\ConfigurationObject\Service\Items\Parents\ParentsUtility;
use Romm\ConfigurationObject\Service\ServiceFactory;
Expand All @@ -12,6 +13,7 @@
use TYPO3\CMS\Core\Cache\Backend\TransientMemoryBackend;
use TYPO3\CMS\Core\Cache\CacheFactory;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Cache\Frontend\VariableFrontend;
use TYPO3\CMS\Core\Utility\VersionNumberUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
use TYPO3\CMS\Extbase\Object\Container\Container;
Expand Down Expand Up @@ -79,6 +81,7 @@ private function setUpConfigurationObjectCore()
$this->configurationObjectCoreMock->injectReflectionService(new ReflectionService);
$this->configurationObjectCoreMock->injectValidatorResolver(new ValidatorResolver);
$this->configurationObjectCoreMock->injectParentsUtility(new ParentsUtility);
$this->configurationObjectCoreMock->injectCacheService(new InternalCacheService);

$this->configurationObjectCoreMock->method('getServiceFactoryInstance')
->will(
Expand Down Expand Up @@ -116,6 +119,13 @@ function (array $service) {
$cacheManager->injectCacheFactory($cacheFactory);
}

$cacheManager->setCacheConfigurations([
InternalCacheService::CACHE_IDENTIFIER => [
'backend' => TransientMemoryBackend::class,
'frontend' => VariableFrontend::class
]
]);

$this->configurationObjectCoreMock->injectCacheManager($cacheManager);

$reflectedCore = new \ReflectionClass(Core::class);
Expand Down
101 changes: 101 additions & 0 deletions Tests/Unit/Core/Service/CacheServiceTest.php
@@ -0,0 +1,101 @@
<?php
namespace Romm\ConfigurationObject\Tests\Unit\Core\Service\Cache;

use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Romm\ConfigurationObject\Core\Service\CacheService;
use Romm\ConfigurationObject\Tests\Unit\AbstractUnitTest;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Cache\Frontend\VariableFrontend;

class CacheServiceTest extends AbstractUnitTest
{
/**
* Checks that the internal cache used by the API is properly registered
* during TYPO3 initialization.
*
* @test
*/
public function internalCacheIsRegisteredProperly()
{
$cacheManager = new CacheManager;

/** @var CacheService|\PHPUnit_Framework_MockObject_MockObject $cacheServiceMock */
$cacheServiceMock = $this->getMockBuilder(CacheService::class)
->setMethods(['getCacheManager'])
->getMock();

$cacheServiceMock->method('getCacheManager')
->willReturn($cacheManager);

$this->assertFalse($cacheManager->hasCache(CacheService::CACHE_IDENTIFIER));
$cacheServiceMock->registerInternalCache();
$this->assertTrue($cacheManager->hasCache(CacheService::CACHE_IDENTIFIER));
}

/**
* Checks that a cache can be registered dynamically, and only once per
* request.
*
* @test
*/
public function registerDynamicCacheWorksProperly()
{
$cacheIdentifier = 'foo';
$cacheOptions = ['bar' => 'baz'];

/** @var CacheService|\PHPUnit_Framework_MockObject_MockObject $cacheServiceMock */
$cacheServiceMock = $this->getMockBuilder(CacheService::class)
->setMethods(['getCache', 'getCacheManager'])
->getMock();

/** @var VariableFrontend|ObjectProphecy $cacheProphecy */
$cacheProphecy = $this->prophesize(VariableFrontend::class);

$cacheProphecy->has($cacheIdentifier)
->shouldBeCalledTimes(2)
->will(function () use ($cacheProphecy, $cacheIdentifier, $cacheOptions) {
$cacheProphecy->set($cacheIdentifier, Argument::type('array'), [CacheService::CACHE_TAG_DYNAMIC_CACHE])
->shouldBeCalledTimes(1);

$cacheProphecy->has($cacheIdentifier)
->willReturn(true);

return false;
});

$cacheProphecy->getByTag(CacheService::CACHE_TAG_DYNAMIC_CACHE)
->shouldBeCalledTimes(1)
->willReturn([
'foo' => [
'identifier' => 'foo',
'options' => []
]
]);

$cacheServiceMock->method('getCache')
->willReturn($cacheProphecy->reveal());

/** @var CacheManager|ObjectProphecy $cacheManagerProphecy */
$cacheManagerProphecy = $this->prophesize(CacheManager::class);

$cacheManagerProphecy->hasCache($cacheIdentifier)
->shouldBeCalledTimes(3)
->will(function () use ($cacheManagerProphecy, $cacheIdentifier) {
$cacheManagerProphecy->hasCache($cacheIdentifier)
->willReturn(true);

$cacheManagerProphecy->setCacheConfigurations(Argument::type('array'))
->shouldBeCalledTimes(1);

return false;
});

$cacheServiceMock->method('getCacheManager')
->willReturn($cacheManagerProphecy->reveal());

$cacheServiceMock->registerDynamicCache($cacheIdentifier, $cacheOptions);
$cacheServiceMock->registerDynamicCache($cacheIdentifier, $cacheOptions);
$cacheServiceMock->registerDynamicCaches();
}
}

0 comments on commit a9b633c

Please sign in to comment.