From 619b7285d8006f176550fd896aaefe3b5b688700 Mon Sep 17 00:00:00 2001 From: Bogdan Rancichi Date: Fri, 16 Dec 2016 12:05:18 +0200 Subject: [PATCH 01/11] initial cache class start --- .../Annotation/CacheExpression.php | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/CacheBundle/Annotation/CacheExpression.php diff --git a/src/CacheBundle/Annotation/CacheExpression.php b/src/CacheBundle/Annotation/CacheExpression.php new file mode 100644 index 0000000..ef90b2e --- /dev/null +++ b/src/CacheBundle/Annotation/CacheExpression.php @@ -0,0 +1,46 @@ +getExpressionLanguage()->evaluate($this->cache, ['this' => $this]); + + return ''; + } + + /** + * @return ExpressionLanguage + * + * @throws CacheException + */ + private function getExpressionLanguage() + { + if (null === $this->expressionLanguage) { + if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { + throw new CacheException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); + } + + $this->expressionLanguage = new ExpressionLanguage(); + } + + return $this->expressionLanguage; + } +} \ No newline at end of file From e1b97862042978ff7905407c3dde380a95ee66f1 Mon Sep 17 00:00:00 2001 From: Bogdan Rancichi Date: Tue, 27 Dec 2016 14:14:14 +0200 Subject: [PATCH 02/11] implement cache expression fully --- .../Annotation/CacheExpression.php | 38 ++++++++++++++++--- .../ProxyManager/CacheableClassTrait.php | 4 ++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/CacheBundle/Annotation/CacheExpression.php b/src/CacheBundle/Annotation/CacheExpression.php index ef90b2e..2823842 100644 --- a/src/CacheBundle/Annotation/CacheExpression.php +++ b/src/CacheBundle/Annotation/CacheExpression.php @@ -5,6 +5,7 @@ namespace CacheBundle\Annotation; use CacheBundle\Exception\CacheException; +use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; /** @@ -13,17 +14,44 @@ */ class CacheExpression extends Cache { - /** @var ExpressionLanguage */ + /** + * @var ExpressionLanguage + */ protected $expressionLanguage; + /** + * @var object + */ + private $context; + + /** + * @var bool + */ + private $hasEvaluation = false; + /** * @inheritDoc */ public function getCache() : string { - $this->getExpressionLanguage()->evaluate($this->cache, ['this' => $this]); + if (!$this->hasEvaluation) { + $this->cache = $this->getExpressionLanguage()->evaluate($this->cache, ['this' => $this->context]); + $this->hasEvaluation = true; + } + + return $this->cache; + } + + /** + * @param object $context + * + * @return CacheExpression + */ + public function setContext($context) : self + { + $this->context = $context; - return ''; + return $this; } /** @@ -31,14 +59,14 @@ public function getCache() : string * * @throws CacheException */ - private function getExpressionLanguage() + private function getExpressionLanguage() : ExpressionLanguage { if (null === $this->expressionLanguage) { if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { throw new CacheException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } - $this->expressionLanguage = new ExpressionLanguage(); + $this->expressionLanguage = new ExpressionLanguage(new FilesystemAdapter('expr_cache')); } return $this->expressionLanguage; diff --git a/src/CacheBundle/ProxyManager/CacheableClassTrait.php b/src/CacheBundle/ProxyManager/CacheableClassTrait.php index fef5aff..f4f0891 100644 --- a/src/CacheBundle/ProxyManager/CacheableClassTrait.php +++ b/src/CacheBundle/ProxyManager/CacheableClassTrait.php @@ -4,6 +4,7 @@ use CacheBundle\Annotation\Cache; +use CacheBundle\Annotation\CacheExpression; use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\Common\Annotations\Reader; use Psr\Cache\CacheItemPoolInterface; @@ -46,6 +47,9 @@ public function getCached(\ReflectionMethod $method, $params) /** @var Cache $annotation */ $annotation = $this->readerForCacheMethod->getMethodAnnotation($method, Cache::class); + if ($annotation instanceof CacheExpression) { + $annotation->setContext($this); + } $cacheKey = $this->getCacheKey($method, $params, $annotation); $cacheItem = $this->cacheServiceForMethod->getItem($cacheKey); From 837a4989f112bcbcb9bf907ef078570cbd8eb814 Mon Sep 17 00:00:00 2001 From: Bogdan Rancichi Date: Tue, 27 Dec 2016 15:00:27 +0200 Subject: [PATCH 03/11] added symfony/expression as a dependecy --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index e0b3f60..3539936 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,8 @@ "ocramius/proxy-manager": "2.*", "psr/log": "1.*", "psr/cache": "1.0.*", - "doctrine/annotations": "1.3.*" + "doctrine/annotations": "1.3.*", + "symfony/expression-language": "3.*" }, "suggest": { "symfony/cache": "3.*" From 0c8645c597cc434f4e2572e7d2031cd1567039e3 Mon Sep 17 00:00:00 2001 From: Bogdan Rancichi Date: Tue, 27 Dec 2016 15:00:40 +0200 Subject: [PATCH 04/11] created a test for sf expressions --- tests/CacheWrapperTest.php | 17 +++++++++++++++++ tests/Helpers/CacheableClass.php | 21 +++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/tests/CacheWrapperTest.php b/tests/CacheWrapperTest.php index a4676ca..dd3bac3 100644 --- a/tests/CacheWrapperTest.php +++ b/tests/CacheWrapperTest.php @@ -1,6 +1,9 @@ container->get('cache.testservice'); + $objectReflectionClass = new \ReflectionClass($object); + $annotationReader = new AnnotationReader(); + /** @var CacheExpression $cacheExpressionAnnotation */ + $cacheExpressionAnnotation = $annotationReader->getMethodAnnotation(new \ReflectionMethod($objectReflectionClass->getParentClass()->getName(), 'getCachePrefixFromExpression'), CacheExpression::class); + $cacheExpressionAnnotation->setContext($object); + + $this->assertContains($object->calculateCachePrefix(), $cacheExpressionAnnotation->getCache()); + $this->assertEquals(0, strpos($cacheExpressionAnnotation->getCache(), $object->calculateCachePrefix())); + } + /** * Get TestHandler object * diff --git a/tests/Helpers/CacheableClass.php b/tests/Helpers/CacheableClass.php index b09c2cd..56ad4ab 100644 --- a/tests/Helpers/CacheableClass.php +++ b/tests/Helpers/CacheableClass.php @@ -1,10 +1,9 @@ Date: Tue, 3 Jan 2017 21:40:26 +0200 Subject: [PATCH 05/11] move to new namespace --- src/Annotation/CacheExpression.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Annotation/CacheExpression.php b/src/Annotation/CacheExpression.php index 2823842..578f98a 100644 --- a/src/Annotation/CacheExpression.php +++ b/src/Annotation/CacheExpression.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace CacheBundle\Annotation; +namespace Emag\CacheBundle\Annotation; -use CacheBundle\Exception\CacheException; +use Emag\CacheBundle\Exception\CacheException; use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; From 1aeedbe22b498fdc6ed091e9ba9a7ed72aa08f92 Mon Sep 17 00:00:00 2001 From: Bogdan Rancichi Date: Tue, 3 Jan 2017 22:05:16 +0200 Subject: [PATCH 06/11] expression language will be injected --- src/Annotation/CacheExpression.php | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/Annotation/CacheExpression.php b/src/Annotation/CacheExpression.php index 578f98a..31ff527 100644 --- a/src/Annotation/CacheExpression.php +++ b/src/Annotation/CacheExpression.php @@ -4,8 +4,6 @@ namespace Emag\CacheBundle\Annotation; -use Emag\CacheBundle\Exception\CacheException; -use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; /** @@ -35,7 +33,7 @@ class CacheExpression extends Cache public function getCache() : string { if (!$this->hasEvaluation) { - $this->cache = $this->getExpressionLanguage()->evaluate($this->cache, ['this' => $this->context]); + $this->cache = $this->expressionLanguage->evaluate($this->cache, ['this' => $this->context]); $this->hasEvaluation = true; } @@ -55,20 +53,14 @@ public function setContext($context) : self } /** - * @return ExpressionLanguage + * @param ExpressionLanguage $language * - * @throws CacheException + * @return CacheExpression */ - private function getExpressionLanguage() : ExpressionLanguage + public function setExpressionLanguage(ExpressionLanguage $language) : self { - if (null === $this->expressionLanguage) { - if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { - throw new CacheException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); - } - - $this->expressionLanguage = new ExpressionLanguage(new FilesystemAdapter('expr_cache')); - } + $this->expressionLanguage = $language; - return $this->expressionLanguage; + return $this; } -} \ No newline at end of file +} From 48aea7e92b208c78466425b220db79044e799808 Mon Sep 17 00:00:00 2001 From: Bogdan Rancichi Date: Tue, 3 Jan 2017 22:05:48 +0200 Subject: [PATCH 07/11] add expression language from configuration of the bundle --- .../Compiler/CacheCompilerPass.php | 2 ++ src/DependencyInjection/Configuration.php | 1 + .../EmagCacheExtension.php | 20 +++++++++++++++++++ src/ProxyManager/CacheableClassTrait.php | 13 +++++++++++- 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/DependencyInjection/Compiler/CacheCompilerPass.php b/src/DependencyInjection/Compiler/CacheCompilerPass.php index b146321..41fab1a 100644 --- a/src/DependencyInjection/Compiler/CacheCompilerPass.php +++ b/src/DependencyInjection/Compiler/CacheCompilerPass.php @@ -43,6 +43,7 @@ protected function analyzeServicesTobeCached(ContainerBuilder $container) $proxyWarmup = $container->getDefinition('emag.cache.warmup'); $cacheProxyFactory = new Reference('emag.cache.proxy.factory'); $cacheServiceReference = new Reference($container->getParameter('emag.cache.service')); + $expressionLanguage = $container->hasParameter('emag.cache.expression.language') ? new Reference($container->getParameter('emag.cache.expression.language')) : null; foreach ($container->getDefinitions() as $serviceId => $definition) { if (!class_exists($definition->getClass()) || $this->isFromIgnoredNamespace($container, $definition->getClass())) { @@ -74,6 +75,7 @@ protected function analyzeServicesTobeCached(ContainerBuilder $container) ->setProperties($definition->getProperties()) ->addMethodCall('setReaderForCacheMethod', [$annotationReaderReference]) ->addMethodCall('setCacheServiceForMethod', [$cacheServiceReference]) + ->addMethodCall('setExpressionLanguage', [$expressionLanguage]) ; $proxyWarmup->addMethodCall('addClassToGenerate', [$definition->getClass()]); diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index f922f7b..896d4f4 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -38,6 +38,7 @@ public function getConfigTreeBuilder() $rootNode ->children() ->scalarNode('provider')->cannotBeEmpty()->isRequired()->end() + ->scalarNode('expression_language')->defaultNull()->end() ->arrayNode('ignore_namespaces') ->prototype('scalar')->end() ->end() diff --git a/src/DependencyInjection/EmagCacheExtension.php b/src/DependencyInjection/EmagCacheExtension.php index 1d810a1..b0f3d4c 100644 --- a/src/DependencyInjection/EmagCacheExtension.php +++ b/src/DependencyInjection/EmagCacheExtension.php @@ -4,10 +4,12 @@ use Emag\CacheBundle\Exception\CacheException; use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; use Symfony\Component\DependencyInjection\Loader; +use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\HttpKernel\DependencyInjection\Extension; /** @@ -31,6 +33,19 @@ public function prepend(ContainerBuilder $container) if (!$provider->implementsInterface(CacheItemPoolInterface::class)) { throw new CacheException(sprintf('You\'ve referenced a service "%s" that can not be used for caching!', $config['provider'])); } + + if (!$config['expression_language']) { + return; + } + + if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { + throw new CacheException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); + } + + $expressionLanguage = new \ReflectionClass($container->getDefinition($config['expression_language'])->getClass()); + if (!$expressionLanguage->isSubclassOf(ExpressionLanguage::class) || !($expressionLanguage instanceof ExpressionLanguage::class)) { + throw new CacheException(sprintf('You must provide a valid Expression Language service')); + } } /** @@ -43,6 +58,11 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter('emag.cache.service', $config['provider']); $container->setParameter('emag.cache.ignore.namespaces', $config['ignore_namespaces']); + if (!$config['expression_language'] && class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { + $container->setParameter('emag.cache.expression.language', new ExpressionLanguage(new FilesystemAdapter('expr_cache'))); + } elseif ($config['expression_language']) { + $container->setParameter('emag.cache.expression.language', $config['expression_language']); + } $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('services.yml'); diff --git a/src/ProxyManager/CacheableClassTrait.php b/src/ProxyManager/CacheableClassTrait.php index 50d289f..c8f20d1 100644 --- a/src/ProxyManager/CacheableClassTrait.php +++ b/src/ProxyManager/CacheableClassTrait.php @@ -8,6 +8,7 @@ use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\Common\Annotations\Reader; use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\ExpressionLanguage\ExpressionLanguage; trait CacheableClassTrait { @@ -24,6 +25,8 @@ trait CacheableClassTrait */ protected $readerForCacheMethod; + protected $__expressionLanguage; + /** * @param CacheItemPoolInterface $cacheServiceForMethod */ @@ -40,6 +43,11 @@ public function setReaderForCacheMethod(Reader $readerForCacheMethod) $this->readerForCacheMethod = $readerForCacheMethod; } + public function setExpressionLanguage(ExpressionLanguage $language = null) + { + $this->__expressionLanguage = $language; + } + public function getCached(\ReflectionMethod $method, $params) { $method->setAccessible(true); @@ -47,7 +55,10 @@ public function getCached(\ReflectionMethod $method, $params) $annotation = $this->readerForCacheMethod->getMethodAnnotation($method, Cache::class); if ($annotation instanceof CacheExpression) { - $annotation->setContext($this); + $annotation + ->setContext($this) + ->setExpressionLanguage($this->__expressionLanguage) + ; } $cacheKey = $this->getCacheKey($method, $params, $annotation); From 968484a677035f263bec5b6ea4c22c56362565e9 Mon Sep 17 00:00:00 2001 From: Bogdan Rancichi Date: Tue, 3 Jan 2017 22:26:58 +0200 Subject: [PATCH 08/11] moved to suggest & require-dev for expression_language --- composer.json | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 74519fe..66e5ff9 100644 --- a/composer.json +++ b/composer.json @@ -14,11 +14,11 @@ "ocramius/proxy-manager": "2.*", "psr/log": "1.*", "psr/cache": "1.0.*", - "doctrine/annotations": "1.3.*", - "symfony/expression-language": "3.*" + "doctrine/annotations": "1.3.*" }, "suggest": { - "symfony/cache": "3.*" + "symfony/cache": "3.*", + "symfony/expression-language": "3.*" }, "require-dev": { "phpunit/phpunit": "5.*", @@ -29,7 +29,8 @@ "symfony/cache": "3.*", "satooshi/php-coveralls": "~1.0", "symfony/monolog-bundle": "@stable", - "symfony/framework-bundle": "@stable" + "symfony/framework-bundle": "@stable", + "symfony/expression-language": "3.*" }, "autoload": { "psr-4": { "Emag\\CacheBundle\\": "src/" }, From db875ca8d5abd640c650b11b645358afacdd7ec3 Mon Sep 17 00:00:00 2001 From: Bogdan Rancichi Date: Sat, 7 Jan 2017 15:38:43 +0200 Subject: [PATCH 09/11] make incorrect cache service configuration file more clear --- ...g_incorrect_service.yml => config_incorrect_cache_service.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{config_incorrect_service.yml => config_incorrect_cache_service.yml} (100%) diff --git a/tests/config_incorrect_service.yml b/tests/config_incorrect_cache_service.yml similarity index 100% rename from tests/config_incorrect_service.yml rename to tests/config_incorrect_cache_service.yml From 619689032fda1421208eda098b0cc4650a813876 Mon Sep 17 00:00:00 2001 From: Bogdan Rancichi Date: Sat, 7 Jan 2017 15:39:01 +0200 Subject: [PATCH 10/11] complete cache expressions --- .../Compiler/CacheCompilerPass.php | 7 +- .../EmagCacheExtension.php | 11 ++- tests/CacheExpressionDefaultTest.php | 82 +++++++++++++++++++ tests/CacheWrapperTest.php | 13 ++- tests/Helpers/CacheableExpressionClass.php | 34 ++++++++ tests/IncorrectCachingServiceTest.php | 6 +- ...ncorrectExpressiongLanguageServiceTest.php | 47 +++++++++++ tests/config.yml | 4 +- tests/config_default_expression.yml | 13 +++ tests/config_incorrect_expr_lang_service.yml | 9 ++ 10 files changed, 215 insertions(+), 11 deletions(-) create mode 100644 tests/CacheExpressionDefaultTest.php create mode 100644 tests/Helpers/CacheableExpressionClass.php create mode 100644 tests/IncorrectExpressiongLanguageServiceTest.php create mode 100644 tests/config_default_expression.yml create mode 100644 tests/config_incorrect_expr_lang_service.yml diff --git a/src/DependencyInjection/Compiler/CacheCompilerPass.php b/src/DependencyInjection/Compiler/CacheCompilerPass.php index 41fab1a..35847ea 100644 --- a/src/DependencyInjection/Compiler/CacheCompilerPass.php +++ b/src/DependencyInjection/Compiler/CacheCompilerPass.php @@ -43,7 +43,7 @@ protected function analyzeServicesTobeCached(ContainerBuilder $container) $proxyWarmup = $container->getDefinition('emag.cache.warmup'); $cacheProxyFactory = new Reference('emag.cache.proxy.factory'); $cacheServiceReference = new Reference($container->getParameter('emag.cache.service')); - $expressionLanguage = $container->hasParameter('emag.cache.expression.language') ? new Reference($container->getParameter('emag.cache.expression.language')) : null; + $expressionLanguage = $container->hasDefinition('emag.cache.expression.language') || $container->hasAlias('emag.cache.expression.language') ? new Reference('emag.cache.expression.language') : null; foreach ($container->getDefinitions() as $serviceId => $definition) { if (!class_exists($definition->getClass()) || $this->isFromIgnoredNamespace($container, $definition->getClass())) { @@ -101,4 +101,9 @@ private function isFromIgnoredNamespace(ContainerBuilder $container, $className) } return false; } + + private function getExpressionLanguage() + { + + } } diff --git a/src/DependencyInjection/EmagCacheExtension.php b/src/DependencyInjection/EmagCacheExtension.php index b0f3d4c..a7e15ac 100644 --- a/src/DependencyInjection/EmagCacheExtension.php +++ b/src/DependencyInjection/EmagCacheExtension.php @@ -7,8 +7,10 @@ use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; use Symfony\Component\DependencyInjection\Loader; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\HttpKernel\DependencyInjection\Extension; @@ -43,7 +45,7 @@ public function prepend(ContainerBuilder $container) } $expressionLanguage = new \ReflectionClass($container->getDefinition($config['expression_language'])->getClass()); - if (!$expressionLanguage->isSubclassOf(ExpressionLanguage::class) || !($expressionLanguage instanceof ExpressionLanguage::class)) { + if ($expressionLanguage->getName() !== ExpressionLanguage::class) { throw new CacheException(sprintf('You must provide a valid Expression Language service')); } } @@ -59,9 +61,12 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter('emag.cache.service', $config['provider']); $container->setParameter('emag.cache.ignore.namespaces', $config['ignore_namespaces']); if (!$config['expression_language'] && class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { - $container->setParameter('emag.cache.expression.language', new ExpressionLanguage(new FilesystemAdapter('expr_cache'))); + $container->addDefinitions([ + 'emag.cache.filesystem.adapter' => (new Definition(FilesystemAdapter::class))->addArgument('expr_cache'), + 'emag.cache.expression.language'=> (new Definition(ExpressionLanguage::class))->addArgument(new Reference('emag.cache.filesystem.adapter')), + ]); } elseif ($config['expression_language']) { - $container->setParameter('emag.cache.expression.language', $config['expression_language']); + $container->setAlias('emag.cache.expression.language', $config['expression_language']); } $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); diff --git a/tests/CacheExpressionDefaultTest.php b/tests/CacheExpressionDefaultTest.php new file mode 100644 index 0000000..c75f643 --- /dev/null +++ b/tests/CacheExpressionDefaultTest.php @@ -0,0 +1,82 @@ + 'test_expr_lang_default']); + $this->container = self::$kernel->getContainer(); + } + + protected static function getKernelClass() + { + return get_class(new class('test_expr_lang_default', []) extends Kernel + { + public function registerBundles() + { + return [ + new \Emag\CacheBundle\EmagCacheBundle() + ]; + } + + public function registerContainerConfiguration(LoaderInterface $loader) + { + $loader->load(__DIR__ . '/config_default_expression.yml'); + } + + public function __construct($environment, $debug) + { + parent::__construct($environment, $debug); + + $loader = require __DIR__ . '/../vendor/autoload.php'; + + AnnotationRegistry::registerLoader(array($loader, 'loadClass')); + $this->rootDir = __DIR__ . '/app/'; + } + }); + } + + public function testDefaultExpressionLanguage() + { + /** @var CacheableExpressionClass $object */ + $object = $this->container->get('cache.expr.test.service'); + $methodName = 'getIntenseResult'; + $objectReflectionClass = new \ReflectionClass($object); + $annotationReader = $this->container->get('annotation_reader'); + /** @var CacheExpression $cacheExpressionAnnotation */ + $cacheExpressionAnnotation = $annotationReader->getMethodAnnotation(new \ReflectionMethod($objectReflectionClass->getParentClass()->getName(), $methodName), CacheExpression::class); + $cacheExpressionAnnotation + ->setExpressionLanguage($this->container->get('emag.cache.expression.language')) + ->setContext($object) + ; + + $result = $object->$methodName(); + $this->assertContains($object->buildCachePrefix(), $cacheExpressionAnnotation->getCache()); + $this->assertEquals(0, strpos($cacheExpressionAnnotation->getCache(), $object->buildCachePrefix())); + $this->assertEquals($result, $object->$methodName()); + } + + public function tearDown() + { + static::$class = null; + } +} diff --git a/tests/CacheWrapperTest.php b/tests/CacheWrapperTest.php index d351978..7b251cc 100644 --- a/tests/CacheWrapperTest.php +++ b/tests/CacheWrapperTest.php @@ -155,14 +155,21 @@ public function testCachePrefixExpressions() { /** @var CacheableClass $object */ $object = $this->container->get('cache.testservice'); + $methodName = 'getCachePrefixFromExpression'; $objectReflectionClass = new \ReflectionClass($object); - $annotationReader = new AnnotationReader(); + $annotationReader = $this->container->get('annotation_reader'); /** @var CacheExpression $cacheExpressionAnnotation */ - $cacheExpressionAnnotation = $annotationReader->getMethodAnnotation(new \ReflectionMethod($objectReflectionClass->getParentClass()->getName(), 'getCachePrefixFromExpression'), CacheExpression::class); - $cacheExpressionAnnotation->setContext($object); + $cacheExpressionAnnotation = $annotationReader->getMethodAnnotation(new \ReflectionMethod($objectReflectionClass->getParentClass()->getName(), $methodName), CacheExpression::class); + $cacheExpressionAnnotation + ->setExpressionLanguage($this->container->get('emag.cache.expression.language')) + ->setContext($object) + ; + $result = $object->$methodName(); $this->assertContains($object->calculateCachePrefix(), $cacheExpressionAnnotation->getCache()); $this->assertEquals(0, strpos($cacheExpressionAnnotation->getCache(), $object->calculateCachePrefix())); + sleep(1); + $this->assertEquals($result, $object->$methodName()); } /** diff --git a/tests/Helpers/CacheableExpressionClass.php b/tests/Helpers/CacheableExpressionClass.php new file mode 100644 index 0000000..2c84665 --- /dev/null +++ b/tests/Helpers/CacheableExpressionClass.php @@ -0,0 +1,34 @@ +prefix = $prefix; + } + + /** + * @eMAG\CacheExpression(cache="this.buildCachePrefix()") + * + * @return int + */ + public function getIntenseResult() : int + { + return rand(); + } + + /** + * @return string + */ + public function buildCachePrefix() : string + { + return sprintf('_expr[%s]', $this->prefix); + } +} diff --git a/tests/IncorrectCachingServiceTest.php b/tests/IncorrectCachingServiceTest.php index 67ba766..54954a3 100644 --- a/tests/IncorrectCachingServiceTest.php +++ b/tests/IncorrectCachingServiceTest.php @@ -10,7 +10,7 @@ class IncorrectCachingServiceTest extends KernelTestCase { protected static function getKernelClass() { - return get_class(new class('test_incorrect_service', []) extends Kernel + return get_class(new class('test_incorrect_cache_service', []) extends Kernel { public function registerBundles() { @@ -21,7 +21,7 @@ public function registerBundles() public function registerContainerConfiguration(LoaderInterface $loader) { - $loader->load(__DIR__ . '/config_incorrect_service.yml'); + $loader->load(__DIR__ . '/config_incorrect_cache_service.yml'); } public function __construct($environment, $debug) @@ -42,6 +42,6 @@ public function __construct($environment, $debug) public function testIncorrectService() { static::$class = null; - self::bootKernel(['environment' => 'test_incorrect_service']); + self::bootKernel(['environment' => 'test_incorrect_cache_service']); } } \ No newline at end of file diff --git a/tests/IncorrectExpressiongLanguageServiceTest.php b/tests/IncorrectExpressiongLanguageServiceTest.php new file mode 100644 index 0000000..da290fe --- /dev/null +++ b/tests/IncorrectExpressiongLanguageServiceTest.php @@ -0,0 +1,47 @@ +load(__DIR__ . '/config_incorrect_expr_lang_service.yml'); + } + + public function __construct($environment, $debug) + { + require __DIR__ . '/../vendor/autoload.php'; + + parent::__construct($environment, $debug); + + $this->rootDir = __DIR__ . '/app/'; + } + }); + } + + /** + * @expectedException \Emag\CacheBundle\Exception\CacheException + * @expectedExceptionMessage You must provide a valid Expression Language service + */ + public function testIncorrectService() + { + static::$class = null; + self::bootKernel(['environment' => 'test_incorrect_expr_lang_service']); + } +} \ No newline at end of file diff --git a/tests/config.yml b/tests/config.yml index 499ea5e..889a916 100644 --- a/tests/config.yml +++ b/tests/config.yml @@ -1,5 +1,4 @@ parameters: - cache.service: cache.service max.value: 20 monolog: @@ -9,6 +8,7 @@ monolog: level: info emag_cache: provider: cache.service + expression_language: expr.lang.service services: cache_warmer: @@ -23,3 +23,5 @@ services: class: Emag\CacheBundle\Tests\Helpers\ExtendedCacheableClass annotation_reader: class: Doctrine\Common\Annotations\AnnotationReader + expr.lang.service: + class: Symfony\Component\ExpressionLanguage\ExpressionLanguage diff --git a/tests/config_default_expression.yml b/tests/config_default_expression.yml new file mode 100644 index 0000000..54ca2ad --- /dev/null +++ b/tests/config_default_expression.yml @@ -0,0 +1,13 @@ +emag_cache: + provider: cache.service + +services: + cache_warmer: + class: Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate + cache.service: + class: Symfony\Component\Cache\Adapter\ArrayAdapter + cache.expr.test.service: + class: Emag\CacheBundle\Tests\Helpers\CacheableExpressionClass + arguments: ["prefix_cache"] + annotation_reader: + class: Doctrine\Common\Annotations\AnnotationReader diff --git a/tests/config_incorrect_expr_lang_service.yml b/tests/config_incorrect_expr_lang_service.yml new file mode 100644 index 0000000..e19fc4a --- /dev/null +++ b/tests/config_incorrect_expr_lang_service.yml @@ -0,0 +1,9 @@ +emag_cache: + provider: cache.service + expression_language: expr.lang.fake + +services: + expr.lang.fake: + class: Emag\CacheBundle\Tests\Helpers\CacheableClass + cache.service: + class: Symfony\Component\Cache\Adapter\ArrayAdapter From ac8f56a1d692d98bdaa2330a4d24c98f8b01dc4e Mon Sep 17 00:00:00 2001 From: Bogdan Rancichi Date: Sat, 7 Jan 2017 15:46:36 +0200 Subject: [PATCH 11/11] added README --- README.md | 58 ++++++++++++++++++++++ tests/Helpers/CacheableExpressionClass.php | 2 +- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 15d9d23..c54b4a7 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,10 @@ You have to configure the name of the service that is PSR6 compliant, that means ## How to use +EmagCacheBundle comes with 2 different ways you can add annotation cache to your service: + +1. @Cache annotation + Add @Cache annotation to the methods you want to be cached: @@ -106,6 +110,60 @@ Here is an example from a service: } ``` +2. @CacheExpression annotation witch uses [Symfony ExpressionLanguage](http://symfony.com/doc/current/components/expression_language.html) +component: + + ```php + + use Emag\CacheBundle\Annotation\CacheExpression; + + /** + * @CacheExpression(cache="", [key="", [ttl=600, [reset=true ]]]) + */ + ``` + + +Here is an example from a service: + +```php + + namespace AppCacheBundle\Service; + + use Emag\CacheBundle\Annotation as eMAG; + + class AppService + { + /** @var string */ + private $prefix; + + public function __construct(string $prefix) + { + $this->prefix = $prefix; + } + + /** + * @eMAG\CacheExpression(cache="this.buildCachePrefix()") + * + * @return int + */ + public function getIntenseResult() : int + { + // 'Simulate a time consuming operation'; + sleep(20); + + return rand(); + } + + /** + * @return string + */ + public function buildCachePrefix() : string + { + return sprintf('_expr[%s]', $this->prefix); + } + } +``` + ## Want to contribute? Submit a PR and join the fun. diff --git a/tests/Helpers/CacheableExpressionClass.php b/tests/Helpers/CacheableExpressionClass.php index 2c84665..6ccc419 100644 --- a/tests/Helpers/CacheableExpressionClass.php +++ b/tests/Helpers/CacheableExpressionClass.php @@ -9,7 +9,7 @@ class CacheableExpressionClass /** @var string */ private $prefix; - public function __construct($prefix) + public function __construct(string $prefix) { $this->prefix = $prefix; }