From 069d62a69eeeb97f8559d7623ab137774863e7e0 Mon Sep 17 00:00:00 2001 From: Daniel Melchior Date: Wed, 17 Jul 2024 00:11:37 +0200 Subject: [PATCH] chore: remove dependency on thecodingmachine/cache-utils (#695) * chore: remove dependency on thecodingmachine/cache-utils The package seems to be unmaintained and prevents usage due to old psr/simple-cache. This removes the dependency on that package. The package provided cache clearance on Classes and ParentClasses when their files changed. This functionality can still be achieved by creating a custom implementation of `TheCodingMachine\GraphQLite\Utils\Cache\ClassBoundCacheContractFactoryInterface`. fixes thecodingmachine/graphqlite#693 * fix: correctly escape `|` in phpstan ignoreErrors * fix: sync min symfony/cache version of library to example and solve deprecation This is necessary because symfony/cache is not compatible with every supported version of psr/simple-cache. More info here: https://github.com/symfony/symfony/issues/44738 --- composer.json | 1 - examples/no-framework/composer.json | 3 +- examples/no-framework/index.php | 5 ++- phpstan.neon | 2 +- src/Cache/ClassBoundCacheContract.php | 43 +++++++++++++++++++ src/Cache/ClassBoundCacheContractFactory.php | 15 +++++++ ...lassBoundCacheContractFactoryInterface.php | 12 ++++++ .../ClassBoundCacheContractInterface.php | 13 ++++++ src/FactoryContext.php | 7 +++ src/Mappers/AbstractTypeMapper.php | 26 ++++------- src/Mappers/GlobTypeMapper.php | 3 ++ src/Mappers/StaticClassListTypeMapper.php | 3 ++ .../StaticClassListTypeMapperFactory.php | 1 + src/SchemaFactory.php | 17 +++++++- tests/FactoryContextTest.php | 5 ++- 15 files changed, 131 insertions(+), 25 deletions(-) create mode 100644 src/Cache/ClassBoundCacheContract.php create mode 100644 src/Cache/ClassBoundCacheContractFactory.php create mode 100644 src/Cache/ClassBoundCacheContractFactoryInterface.php create mode 100644 src/Cache/ClassBoundCacheContractInterface.php diff --git a/composer.json b/composer.json index 5f89d4d2be..5b47aa1049 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,6 @@ "psr/simple-cache": "^1.0.1 || ^2 || ^3", "symfony/cache": "^4.3 || ^5 || ^6 || ^7", "symfony/expression-language": "^4 || ^5 || ^6 || ^7", - "thecodingmachine/cache-utils": "^1", "webonyx/graphql-php": "^v15.0", "kcs/class-finder": "^0.5.0" }, diff --git a/examples/no-framework/composer.json b/examples/no-framework/composer.json index 91c4da4444..27ea1ab713 100644 --- a/examples/no-framework/composer.json +++ b/examples/no-framework/composer.json @@ -7,7 +7,8 @@ "require": { "thecodingmachine/graphqlite": "@dev", "mouf/picotainer": "^1.1", - "symfony/cache": "^4.2" + "symfony/cache": "^4.3", + "psr/simple-cache": "^1.0" }, "repositories": [ { diff --git a/examples/no-framework/index.php b/examples/no-framework/index.php index 356c631175..b8f43ee18b 100644 --- a/examples/no-framework/index.php +++ b/examples/no-framework/index.php @@ -4,7 +4,8 @@ use TheCodingMachine\GraphQLite\SchemaFactory; use TheCodingMachine\GraphQLite\Context\Context; -use Symfony\Component\Cache\Simple\FilesystemCache; +use Symfony\Component\Cache\Adapter\FilesystemAdapter; +use Symfony\Component\Cache\Psr16Cache; use Mouf\Picotainer\Picotainer; use GraphQL\Utils\SchemaPrinter; use App\Controllers\MyController; @@ -12,7 +13,7 @@ require_once __DIR__ . '/vendor/autoload.php'; // $cache is any PSR-16 compatible cache. -$cache = new FilesystemCache(); +$cache = new Psr16Cache(new FilesystemAdapter());; // $container is any PSR-11 compatible container which has // been populated with your controller classes. diff --git a/phpstan.neon b/phpstan.neon index 803977c572..86c9770f50 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -34,7 +34,7 @@ parameters: message: '#Unreachable statement - code above always terminates.#' path: src/Http/WebonyxGraphqlMiddleware.php - - message: '#Property TheCodingMachine\\GraphQLite\\Annotations\\Type::\$class \(class-string\\|null\) does not accept string.#' + message: '#Property TheCodingMachine\\GraphQLite\\Annotations\\Type::\$class \(class-string\|null\) does not accept string.#' path: src/Annotations/Type.php - message: '#Method TheCodingMachine\\GraphQLite\\AnnotationReader::(getMethodAnnotations|getPropertyAnnotations)\(\) should return array but returns array.#' diff --git a/src/Cache/ClassBoundCacheContract.php b/src/Cache/ClassBoundCacheContract.php new file mode 100644 index 0000000000..3509794a19 --- /dev/null +++ b/src/Cache/ClassBoundCacheContract.php @@ -0,0 +1,43 @@ +cachePrefix = str_replace(['\\', '{', '}', '(', ')', '/', '@', ':'], '_', $cachePrefix); + } + + /** + * @param string $key An optional key to differentiate between cache items attached to the same class. + * + * @throws InvalidArgumentException + */ + public function get(ReflectionClass $reflectionClass, callable $resolver, string $key = '', int|null $ttl = null): mixed + { + $cacheKey = $reflectionClass->getName() . '__' . $key; + $cacheKey = $this->cachePrefix . str_replace(['\\', '{', '}', '(', ')', '/', '@', ':'], '_', $cacheKey); + + $item = $this->classBoundCache->get($cacheKey); + if ($item !== null) { + return $item; + } + + $item = $resolver(); + + $this->classBoundCache->set($cacheKey, $item, $ttl); + + return $item; + } +} diff --git a/src/Cache/ClassBoundCacheContractFactory.php b/src/Cache/ClassBoundCacheContractFactory.php new file mode 100644 index 0000000000..0c2dfc7750 --- /dev/null +++ b/src/Cache/ClassBoundCacheContractFactory.php @@ -0,0 +1,15 @@ +cache; } + public function getClassBoundCacheContractFactory(): ClassBoundCacheContractFactoryInterface|null + { + return $this->classBoundCacheContractFactory; + } + public function getInputTypeValidator(): InputTypeValidatorInterface|null { return $this->inputTypeValidator; diff --git a/src/Mappers/AbstractTypeMapper.php b/src/Mappers/AbstractTypeMapper.php index db3946d532..7e09f01ed5 100644 --- a/src/Mappers/AbstractTypeMapper.php +++ b/src/Mappers/AbstractTypeMapper.php @@ -15,12 +15,10 @@ use ReflectionMethod; use Symfony\Component\Cache\Adapter\Psr16Adapter; use Symfony\Contracts\Cache\CacheInterface as CacheContractInterface; -use TheCodingMachine\CacheUtils\ClassBoundCache; -use TheCodingMachine\CacheUtils\ClassBoundCacheContract; -use TheCodingMachine\CacheUtils\ClassBoundCacheContractInterface; -use TheCodingMachine\CacheUtils\ClassBoundMemoryAdapter; -use TheCodingMachine\CacheUtils\FileBoundCache; use TheCodingMachine\GraphQLite\AnnotationReader; +use TheCodingMachine\GraphQLite\Cache\ClassBoundCacheContractFactory; +use TheCodingMachine\GraphQLite\Cache\ClassBoundCacheContractFactoryInterface; +use TheCodingMachine\GraphQLite\Cache\ClassBoundCacheContractInterface; use TheCodingMachine\GraphQLite\InputTypeGenerator; use TheCodingMachine\GraphQLite\InputTypeUtils; use TheCodingMachine\GraphQLite\NamingStrategyInterface; @@ -66,23 +64,15 @@ public function __construct( private readonly CacheInterface $cache, protected int|null $globTTL = 2, private readonly int|null $mapTTL = null, + ClassBoundCacheContractFactoryInterface|null $classBoundCacheContractFactory = null, ) { $this->cacheContract = new Psr16Adapter($this->cache, $cachePrefix, $this->globTTL ?? 0); - $classToAnnotationsCache = new ClassBoundCache( - new FileBoundCache($this->cache, 'classToAnnotations_' . $cachePrefix), - ); - $this->mapClassToAnnotationsCache = new ClassBoundCacheContract( - new ClassBoundMemoryAdapter($classToAnnotationsCache), - ); - - $classToExtendedAnnotationsCache = new ClassBoundCache( - new FileBoundCache($this->cache, 'classToExtendAnnotations_' . $cachePrefix), - ); - $this->mapClassToExtendAnnotationsCache = new ClassBoundCacheContract( - new ClassBoundMemoryAdapter($classToExtendedAnnotationsCache), - ); + $classBoundCacheContractFactory = $classBoundCacheContractFactory ?? new ClassBoundCacheContractFactory(); + + $this->mapClassToAnnotationsCache = $classBoundCacheContractFactory->make($cache, 'classToAnnotations_' . $cachePrefix); + $this->mapClassToExtendAnnotationsCache = $classBoundCacheContractFactory->make($cache, 'classToExtendAnnotations_' . $cachePrefix); } /** diff --git a/src/Mappers/GlobTypeMapper.php b/src/Mappers/GlobTypeMapper.php index 132673b898..f094eb7359 100644 --- a/src/Mappers/GlobTypeMapper.php +++ b/src/Mappers/GlobTypeMapper.php @@ -8,6 +8,7 @@ use Psr\SimpleCache\CacheInterface; use ReflectionClass; use TheCodingMachine\GraphQLite\AnnotationReader; +use TheCodingMachine\GraphQLite\Cache\ClassBoundCacheContractFactoryInterface; use TheCodingMachine\GraphQLite\InputTypeGenerator; use TheCodingMachine\GraphQLite\InputTypeUtils; use TheCodingMachine\GraphQLite\NamingStrategyInterface; @@ -44,6 +45,7 @@ public function __construct( CacheInterface $cache, int|null $globTTL = 2, int|null $mapTTL = null, + ClassBoundCacheContractFactoryInterface|null $classBoundCacheContractFactory = null, ) { $cachePrefix = str_replace( ['\\', '{', '}', '(', ')', '/', '@', ':'], @@ -63,6 +65,7 @@ public function __construct( $cache, $globTTL, $mapTTL, + $classBoundCacheContractFactory, ); } diff --git a/src/Mappers/StaticClassListTypeMapper.php b/src/Mappers/StaticClassListTypeMapper.php index eec76c3097..f5fb0139b0 100644 --- a/src/Mappers/StaticClassListTypeMapper.php +++ b/src/Mappers/StaticClassListTypeMapper.php @@ -8,6 +8,7 @@ use Psr\SimpleCache\CacheInterface; use ReflectionClass; use TheCodingMachine\GraphQLite\AnnotationReader; +use TheCodingMachine\GraphQLite\Cache\ClassBoundCacheContractFactoryInterface; use TheCodingMachine\GraphQLite\GraphQLRuntimeException; use TheCodingMachine\GraphQLite\InputTypeGenerator; use TheCodingMachine\GraphQLite\InputTypeUtils; @@ -45,6 +46,7 @@ public function __construct( CacheInterface $cache, int|null $globTTL = 2, int|null $mapTTL = null, + ClassBoundCacheContractFactoryInterface|null $classBoundCacheContractFactory = null, ) { $cachePrefix = str_replace( ['\\', '{', '}', '(', ')', '/', '@', ':'], @@ -64,6 +66,7 @@ public function __construct( $cache, $globTTL, $mapTTL, + $classBoundCacheContractFactory, ); } diff --git a/src/Mappers/StaticClassListTypeMapperFactory.php b/src/Mappers/StaticClassListTypeMapperFactory.php index ff8becbc6f..774c59c2b7 100644 --- a/src/Mappers/StaticClassListTypeMapperFactory.php +++ b/src/Mappers/StaticClassListTypeMapperFactory.php @@ -38,6 +38,7 @@ public function create(FactoryContext $context): TypeMapperInterface $context->getCache(), $context->getGlobTTL(), $context->getMapTTL(), + $context->getClassBoundCacheContractFactory(), ); } } diff --git a/src/SchemaFactory.php b/src/SchemaFactory.php index a4c2bd2c6d..029c5eada8 100644 --- a/src/SchemaFactory.php +++ b/src/SchemaFactory.php @@ -13,6 +13,7 @@ use Psr\SimpleCache\CacheInterface; use Symfony\Component\Cache\Adapter\Psr16Adapter; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; +use TheCodingMachine\GraphQLite\Cache\ClassBoundCacheContractFactoryInterface; use TheCodingMachine\GraphQLite\Mappers\CompositeTypeMapper; use TheCodingMachine\GraphQLite\Mappers\GlobTypeMapper; use TheCodingMachine\GraphQLite\Mappers\Parameters\ContainerParameterHandler; @@ -120,7 +121,7 @@ class SchemaFactory private string $cacheNamespace; - public function __construct(private readonly CacheInterface $cache, private readonly ContainerInterface $container) + public function __construct(private readonly CacheInterface $cache, private readonly ContainerInterface $container, private ClassBoundCacheContractFactoryInterface|null $classBoundCacheContractFactory = null) { $this->cacheNamespace = substr(md5(Versions::getVersion('thecodingmachine/graphqlite')), 0, 8); } @@ -259,6 +260,18 @@ public function setGlobTTL(int|null $globTTL): self return $this; } + /** + * Set a custom ClassBoundCacheContractFactory. + * This is used to create CacheContracts that store reflection results. + * Set this to "null" to use the default fallback factory. + */ + public function setClassBoundCacheContractFactory(ClassBoundCacheContractFactoryInterface|null $classBoundCacheContractFactory): self + { + $this->classBoundCacheContractFactory = $classBoundCacheContractFactory; + + return $this; + } + /** * Sets GraphQLite in "prod" mode (cache settings optimized for best performance). * @@ -430,6 +443,7 @@ public function createSchema(): Schema $recursiveTypeMapper, $namespacedCache, $this->globTTL, + classBoundCacheContractFactory: $this->classBoundCacheContractFactory, )); } @@ -447,6 +461,7 @@ public function createSchema(): Schema $namespacedCache, $this->inputTypeValidator, $this->globTTL, + classBoundCacheContractFactory: $this->classBoundCacheContractFactory, ); } diff --git a/tests/FactoryContextTest.php b/tests/FactoryContextTest.php index fec72a6ddd..9f02729924 100644 --- a/tests/FactoryContextTest.php +++ b/tests/FactoryContextTest.php @@ -4,6 +4,7 @@ use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Cache\Psr16Cache; +use TheCodingMachine\GraphQLite\Cache\ClassBoundCacheContractFactory; use TheCodingMachine\GraphQLite\Containers\EmptyContainer; use TheCodingMachine\GraphQLite\Fixtures\Inputs\Validator; @@ -16,6 +17,7 @@ public function testContext(): void $namingStrategy = new NamingStrategy(); $container = new EmptyContainer(); $arrayCache = new Psr16Cache(new ArrayAdapter()); + $classBoundCacheContractFactory = new ClassBoundCacheContractFactory(); $validator = new Validator(); $context = new FactoryContext( @@ -30,7 +32,8 @@ public function testContext(): void $container, $arrayCache, $validator, - self::GLOB_TTL_SECONDS + self::GLOB_TTL_SECONDS, + classBoundCacheContractFactory: $classBoundCacheContractFactory, ); $this->assertSame($this->getAnnotationReader(), $context->getAnnotationReader());