From e96391e19da145049f8047640a00d3112d8d9b96 Mon Sep 17 00:00:00 2001 From: Georges Date: Tue, 9 Jan 2024 08:31:00 +0100 Subject: [PATCH] Improved extension mechanism performances --- lib/Phpfastcache/CacheManager.php | 26 +++++--- ...PhpfastcacheExtensionNotFoundException.php | 2 +- ...astcacheExtensionNotInstalledException.php | 21 ++++++ lib/Phpfastcache/ExtensionManager.php | 64 +++++++++--------- tests/cases/ExtensionManager.test.php | 66 +++++++++++++++++++ .../Drivers/Extensiontest/Config.php | 42 ++++++++++++ .../Drivers/Extensiontest/Driver.php | 21 ++++++ .../Extensions/Drivers/Extensiontest/Item.php | 22 +++++++ 8 files changed, 222 insertions(+), 42 deletions(-) create mode 100644 lib/Phpfastcache/Exceptions/PhpfastcacheExtensionNotInstalledException.php create mode 100644 tests/cases/ExtensionManager.test.php create mode 100644 tests/mock/Phpfastcache/Extensions/Drivers/Extensiontest/Config.php create mode 100644 tests/mock/Phpfastcache/Extensions/Drivers/Extensiontest/Driver.php create mode 100644 tests/mock/Phpfastcache/Extensions/Drivers/Extensiontest/Item.php diff --git a/lib/Phpfastcache/CacheManager.php b/lib/Phpfastcache/CacheManager.php index c5ac7343..842fa5ab 100644 --- a/lib/Phpfastcache/CacheManager.php +++ b/lib/Phpfastcache/CacheManager.php @@ -23,6 +23,7 @@ use Phpfastcache\Exceptions\PhpfastcacheDriverException; use Phpfastcache\Exceptions\PhpfastcacheDriverNotFoundException; use Phpfastcache\Exceptions\PhpfastcacheExtensionNotFoundException; +use Phpfastcache\Exceptions\PhpfastcacheExtensionNotInstalledException; use Phpfastcache\Exceptions\PhpfastcacheInstanceNotFoundException; use Phpfastcache\Exceptions\PhpfastcacheInvalidArgumentException; use Phpfastcache\Exceptions\PhpfastcacheLogicException; @@ -59,6 +60,11 @@ class CacheManager */ protected static array $driverCustoms = []; + /** + * @var string[] + */ + protected static array $driverExtensions = []; + /** * @param string $instanceId * @return ExtendedCacheItemPoolInterface @@ -91,6 +97,7 @@ public static function getInstances(): array * @throws PhpfastcacheDriverCheckException * @throws PhpfastcacheDriverException * @throws PhpfastcacheDriverNotFoundException + * @throws PhpfastcacheExtensionNotInstalledException * @throws PhpfastcacheLogicException */ public static function getInstance(string $driver, ?ConfigurationOptionInterface $config = null, ?string $instanceId = null): ExtendedCacheItemPoolInterface @@ -116,22 +123,19 @@ public static function getInstance(string $driver, ?ConfigurationOptionInterface ); } else { try { - ExtensionManager::loadExtension($driver); + self::$driverExtensions[$driver] = ExtensionManager::getExtension($driver); return CacheManager::getInstance($driver, $config, $instanceId); } catch (PhpfastcacheExtensionNotFoundException) { - // Temporary check until v10 - $extensionWarning = ''; - if (in_array($driver, ['Arangodb', 'Couchdb', 'Dynamodb', 'Firestore', 'Mongodb', 'Solr'], true)) { - $extensionWarning .= sprintf( - 'However, it seems that you are using a driver which is now an extension. Run the following command to solve this issue: %s', + if (in_array($driver, ExtensionManager::KNOWN_EXTENSION_NAMES, true)) { + throw new PhpfastcacheExtensionNotInstalledException(sprintf( + 'You requested a driver which is now an extension. Run the following command to solve this issue: %s', sprintf('composer install phpfastcache/%s-extension', strtolower($driver)) - ); + )); } throw new PhpfastcacheDriverNotFoundException(sprintf( - 'The driver "%s" does not exist or does not implement %s. %s', + 'The driver "%s" does not exist or does not implement %s.', $driver, ExtendedCacheItemPoolInterface::class, - $extensionWarning, )); } } @@ -191,7 +195,9 @@ public static function normalizeDriverName(string $driverName): string */ public static function getDriverClass(string $driverName): string { - if (!empty(self::$driverCustoms[$driverName])) { + if (!empty(self::$driverExtensions[$driverName])) { + $driverClass = self::$driverExtensions[$driverName]; + } elseif (!empty(self::$driverCustoms[$driverName])) { $driverClass = self::$driverCustoms[$driverName]; } elseif (!empty(self::$driverOverrides[$driverName])) { $driverClass = self::$driverOverrides[$driverName]; diff --git a/lib/Phpfastcache/Exceptions/PhpfastcacheExtensionNotFoundException.php b/lib/Phpfastcache/Exceptions/PhpfastcacheExtensionNotFoundException.php index b222ae76..605e00e3 100644 --- a/lib/Phpfastcache/Exceptions/PhpfastcacheExtensionNotFoundException.php +++ b/lib/Phpfastcache/Exceptions/PhpfastcacheExtensionNotFoundException.php @@ -16,6 +16,6 @@ namespace Phpfastcache\Exceptions; -class PhpfastcacheExtensionNotFoundException extends PhpfastcacheDriverException +class PhpfastcacheExtensionNotFoundException extends PhpfastcacheDriverNotFoundException { } diff --git a/lib/Phpfastcache/Exceptions/PhpfastcacheExtensionNotInstalledException.php b/lib/Phpfastcache/Exceptions/PhpfastcacheExtensionNotInstalledException.php new file mode 100644 index 00000000..b0f43bc5 --- /dev/null +++ b/lib/Phpfastcache/Exceptions/PhpfastcacheExtensionNotInstalledException.php @@ -0,0 +1,21 @@ + + * @author Contributors https://github.com/PHPSocialNetwork/phpfastcache/graphs/contributors + */ + +declare(strict_types=1); + +namespace Phpfastcache\Exceptions; + +class PhpfastcacheExtensionNotInstalledException extends PhpfastcacheDriverNotFoundException +{ +} diff --git a/lib/Phpfastcache/ExtensionManager.php b/lib/Phpfastcache/ExtensionManager.php index c81acc0d..bf016a6a 100644 --- a/lib/Phpfastcache/ExtensionManager.php +++ b/lib/Phpfastcache/ExtensionManager.php @@ -16,17 +16,30 @@ namespace Phpfastcache; -use Phpfastcache\Exceptions\PhpfastcacheDriverNotFoundException; use Phpfastcache\Exceptions\PhpfastcacheExtensionNotFoundException; use Phpfastcache\Exceptions\PhpfastcacheInvalidArgumentException; use Phpfastcache\Exceptions\PhpfastcacheLogicException; use Phpfastcache\Exceptions\PhpfastcacheUnsupportedOperationException; use Phpfastcache\Helper\UninstanciableObjectTrait; +/** + * @internal This extension manager is meant to manager officials Phpfastcache's extensions. + * @see \Phpfastcache\CacheManager::addCustomDriver() to add you own drivers. + */ final class ExtensionManager { use UninstanciableObjectTrait; + public const KNOWN_EXTENSION_NAMES = [ + 'Arangodb', + 'Couchbasev4', + 'Couchdb', + 'Dynamodb', + 'Firestore', + 'Mongodb', + 'Solr' + ]; + /** * @var array */ @@ -34,47 +47,36 @@ final class ExtensionManager public static function registerExtension(string $extensionName, string $driverClassName): void { + if (!str_starts_with($driverClassName, ltrim('Phpfastcache\\Extensions\\', '\\'))) { + throw new PhpfastcacheInvalidArgumentException( + 'Only extensions from "\\Phpfastcache\\Extensions\\" namespace are allowed. Use CacheManager::addCustomDriver() to create your own extensions.' + ); + } self::$registeredExtensions[$extensionName] = $driverClassName; } - /** - * Autoload all the discoverable extensions. - * - * @return void - * @throws PhpfastcacheExtensionNotFoundException - * @throws PhpfastcacheInvalidArgumentException - * @throws PhpfastcacheLogicException - * @throws PhpfastcacheUnsupportedOperationException - */ - public static function autoloadExtensions(): void + public static function extensionExists(string $extensionName): bool { - foreach (self::$registeredExtensions as $extension) { - self::loadExtension($extension); - } + return isset(self::$registeredExtensions[$extensionName]); } /** * @param string $name - * @return void + * @return string * @throws PhpfastcacheExtensionNotFoundException - * @throws PhpfastcacheInvalidArgumentException - * @throws PhpfastcacheLogicException - * @throws PhpfastcacheUnsupportedOperationException */ - public static function loadExtension(string $name): void + public static function getExtension(string $name): string { - if (!CacheManager::customDriverExists($name)) { - if (isset(self::$registeredExtensions[$name])) { - CacheManager::addCustomDriver($name, self::$registeredExtensions[$name]); - } else { - throw new PhpfastcacheExtensionNotFoundException( - sprintf( - 'Unable too find the %s extension. Make sure that you you added through composer: `composer require phpfastcache/%s-extension`', - $name, - strtolower($name) - ) - ); - } + if (isset(self::$registeredExtensions[$name])) { + return self::$registeredExtensions[$name]; + } else { + throw new PhpfastcacheExtensionNotFoundException( + sprintf( + 'Unable too find the %s extension. Make sure that you you added through composer: `composer require phpfastcache/%s-extension`', + $name, + strtolower($name) + ) + ); } } } diff --git a/tests/cases/ExtensionManager.test.php b/tests/cases/ExtensionManager.test.php new file mode 100644 index 00000000..bdff618a --- /dev/null +++ b/tests/cases/ExtensionManager.test.php @@ -0,0 +1,66 @@ + + * @author Contributors https://github.com/PHPSocialNetwork/phpfastcache/graphs/contributors + */ + +use Phpfastcache\CacheManager; +use Phpfastcache\Exceptions\PhpfastcacheDriverNotFoundException; +use Phpfastcache\Exceptions\PhpfastcacheInvalidArgumentException; +use Phpfastcache\Exceptions\PhpfastcacheExtensionNotInstalledException; +use Phpfastcache\Tests\Helper\TestHelper; + +chdir(__DIR__); +require_once __DIR__ . '/../../vendor/autoload.php'; +require_once __DIR__ . '/../mock/Autoload.php'; +$testHelper = new TestHelper('Apcu test (CRUD)'); + +try { + $pool = CacheManager::getInstance('Arangodb'); + $testHelper->assertFail('CacheManager didnt thrown an Exception'); +} catch (PhpfastcacheExtensionNotInstalledException) { + $testHelper->assertPass('CacheManager thrown a PhpfastcacheExtensionNotInstalledException.'); +} catch (\Throwable $e) { + $testHelper->assertFail('CacheManager thrown a ' . $e::class); +} + +try { + $pool = CacheManager::getInstance(bin2hex(random_bytes(8))); + $testHelper->assertFail('CacheManager didnt thrown an Exception'); +} catch (PhpfastcacheDriverNotFoundException $e) { + if ($e::class === PhpfastcacheDriverNotFoundException::class) { + $testHelper->assertPass('CacheManager thrown a PhpfastcacheDriverNotFoundException.'); + } else { + $testHelper->assertFail('CacheManager thrown a ' . $e::class); + } +} catch (\Throwable $e) { + $testHelper->assertFail('CacheManager thrown a ' . $e::class); +} + +try { + \Phpfastcache\ExtensionManager::registerExtension( + 'Extensiontest', + \Phpfastcache\Extensions\Drivers\Extensiontest\Driver::class + ); + $testHelper->assertPass('Registered a test extension.'); +} catch (PhpfastcacheInvalidArgumentException) { + $testHelper->assertFail('Failed to register a test extension.'); +} + +try { + CacheManager::getInstance('Extensiontest'); + $testHelper->assertPass('Retrieved a test extension cache pool.'); +} catch (PhpfastcacheDriverNotFoundException) { + $testHelper->assertFail('Failed to retrieve a test extension cache pool.'); +} + + +$testHelper->terminateTest(); diff --git a/tests/mock/Phpfastcache/Extensions/Drivers/Extensiontest/Config.php b/tests/mock/Phpfastcache/Extensions/Drivers/Extensiontest/Config.php new file mode 100644 index 00000000..1afb9bc1 --- /dev/null +++ b/tests/mock/Phpfastcache/Extensions/Drivers/Extensiontest/Config.php @@ -0,0 +1,42 @@ + + * @author Contributors https://github.com/PHPSocialNetwork/phpfastcache/graphs/contributors + */ + +namespace Phpfastcache\Extensions\Drivers\Extensiontest; + +use Phpfastcache\Drivers\Files\Config as FilesConfig; + +class Config extends FilesConfig +{ + /** + * @var bool + */ + protected bool $customOption = true; + + /** + * @return bool + */ + public function isCustomOption(): bool + { + return $this->customOption; + } + + /** + * @param bool $customOption + * @return Config + */ + public function setCustomOption(bool $customOption): Config + { + $this->customOption = $customOption; + return $this; + } +} diff --git a/tests/mock/Phpfastcache/Extensions/Drivers/Extensiontest/Driver.php b/tests/mock/Phpfastcache/Extensions/Drivers/Extensiontest/Driver.php new file mode 100644 index 00000000..0e964782 --- /dev/null +++ b/tests/mock/Phpfastcache/Extensions/Drivers/Extensiontest/Driver.php @@ -0,0 +1,21 @@ + + * @author Contributors https://github.com/PHPSocialNetwork/phpfastcache/graphs/contributors + */ + +namespace Phpfastcache\Extensions\Drivers\Extensiontest; + +use Phpfastcache\Drivers\Files\Driver as FilesDriver; + +class Driver extends FilesDriver +{ + +} diff --git a/tests/mock/Phpfastcache/Extensions/Drivers/Extensiontest/Item.php b/tests/mock/Phpfastcache/Extensions/Drivers/Extensiontest/Item.php new file mode 100644 index 00000000..3ea8ad05 --- /dev/null +++ b/tests/mock/Phpfastcache/Extensions/Drivers/Extensiontest/Item.php @@ -0,0 +1,22 @@ + + * @author Contributors https://github.com/PHPSocialNetwork/phpfastcache/graphs/contributors + */ + +namespace Phpfastcache\Extensions\Drivers\Extensiontest; + +use Phpfastcache\Drivers\Files\Item as FilesItem; + + +class Item extends FilesItem +{ + +}