From cbf828a00a9a2287d7c7bb640f3c1078410b4de4 Mon Sep 17 00:00:00 2001 From: Patrick McLain Date: Wed, 24 Oct 2018 20:55:30 -0400 Subject: [PATCH] Separate interception config logic Moves the logic responsible for loading, saving, clearing the interception config cache into it's own class --- app/etc/di.xml | 6 + .../Framework/Interception/AbstractPlugin.php | 8 +- .../{ConfigTest.php => CacheManagerTest.php} | 15 +-- .../Interception/Config/CacheManager.php | 113 ++++++++++++++++++ .../Framework/Interception/Config/Config.php | 71 +++-------- .../Test/Unit/Config/ConfigTest.php | 42 ++----- 6 files changed, 157 insertions(+), 98 deletions(-) rename dev/tests/integration/testsuite/Magento/Framework/Interception/Config/{ConfigTest.php => CacheManagerTest.php} (87%) create mode 100644 lib/internal/Magento/Framework/Interception/Config/CacheManager.php diff --git a/app/etc/di.xml b/app/etc/di.xml index b374645240ff7..acdd48a393b5e 100755 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -28,6 +28,7 @@ + @@ -412,6 +413,11 @@ interception + + + Magento\Framework\App\Cache\Type\Config + + Magento\Framework\App\Cache\Type\Config diff --git a/dev/tests/integration/testsuite/Magento/Framework/Interception/AbstractPlugin.php b/dev/tests/integration/testsuite/Magento/Framework/Interception/AbstractPlugin.php index a85e5e7c89482..60eb511dcb6b5 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Interception/AbstractPlugin.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Interception/AbstractPlugin.php @@ -59,7 +59,8 @@ public function setUpInterceptionConfig($pluginConfig) $areaList->expects($this->any())->method('getCodes')->will($this->returnValue([])); $configScope = new \Magento\Framework\Config\Scope($areaList, 'global'); $cache = $this->createMock(\Magento\Framework\Config\CacheInterface::class); - $cache->expects($this->any())->method('load')->will($this->returnValue(false)); + $cacheManager = $this->createMock(\Magento\Framework\Interception\Config\CacheManager::class); + $cacheManager->method('load')->willReturn(null); $definitions = new \Magento\Framework\ObjectManager\Definition\Runtime(); $relations = new \Magento\Framework\ObjectManager\Relations\Runtime(); $interceptionConfig = new Config\Config( @@ -68,7 +69,10 @@ public function setUpInterceptionConfig($pluginConfig) $cache, $relations, $config, - $definitions + $definitions, + 'interception', + null, + $cacheManager ); $interceptionDefinitions = new Definition\Runtime(); $json = new \Magento\Framework\Serialize\Serializer\Json(); diff --git a/dev/tests/integration/testsuite/Magento/Framework/Interception/Config/ConfigTest.php b/dev/tests/integration/testsuite/Magento/Framework/Interception/Config/CacheManagerTest.php similarity index 87% rename from dev/tests/integration/testsuite/Magento/Framework/Interception/Config/ConfigTest.php rename to dev/tests/integration/testsuite/Magento/Framework/Interception/Config/CacheManagerTest.php index 1ece9189169bb..9d5abd1a8a6c6 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Interception/Config/ConfigTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Interception/Config/CacheManagerTest.php @@ -10,7 +10,7 @@ use Magento\Framework\App\Filesystem\DirectoryList; -class ConfigTest extends \PHPUnit\Framework\TestCase +class CacheManagerTest extends \PHPUnit\Framework\TestCase { const CACHE_ID = 'interceptiontest'; @@ -68,9 +68,7 @@ public function testInstantiateFromCompiled(array $testConfig) $this->configWriter->write(self::CACHE_ID, $testConfig); $config = $this->getConfig(); - foreach ($testConfig as $className => $hasPlugins) { - $this->assertEquals($hasPlugins, $config->hasPlugins($className)); - } + $this->assertEquals($testConfig, $config->load(self::CACHE_ID)); } /** @@ -83,9 +81,7 @@ public function testInstantiateFromCache(array $testConfig) $this->cache->save($this->serializer->serialize($testConfig), self::CACHE_ID); $config = $this->getConfig(); - foreach ($testConfig as $className => $hasPlugins) { - $this->assertEquals($hasPlugins, $config->hasPlugins($className)); - } + $this->assertEquals($testConfig, $config->load(self::CACHE_ID)); } public function interceptionCompiledConfigDataProvider() @@ -121,16 +117,15 @@ private function initializeMetadataDirectory() * from altering the interception config that may have been generated during application * installation. Inject a new instance of the compileLoaded to bypass it's caching. * - * @return \Magento\Framework\Interception\Config\Config + * @return \Magento\Framework\Interception\Config\CacheManager */ private function getConfig() { return $this->objectManager->create( - \Magento\Framework\Interception\Config\Config::class, + \Magento\Framework\Interception\Config\CacheManager::class, [ 'cacheId' => self::CACHE_ID, 'compiledLoader' => $this->objectManager->create(\Magento\Framework\App\ObjectManager\ConfigLoader\Compiled::class), - 'serializer' => $this->serializer, ] ); } diff --git a/lib/internal/Magento/Framework/Interception/Config/CacheManager.php b/lib/internal/Magento/Framework/Interception/Config/CacheManager.php new file mode 100644 index 0000000000000..cd16e2277d87a --- /dev/null +++ b/lib/internal/Magento/Framework/Interception/Config/CacheManager.php @@ -0,0 +1,113 @@ +cache = $cache; + $this->serializer = $serializer; + $this->configWriter = $configWriter; + $this->compiledLoader = $compiledLoader; + } + + /** + * Load the interception config from cache + * + * @param string $key + * @return array|null + */ + public function load(string $key): ?array + { + if ($this->isCompiled($key)) { + return $this->compiledLoader->load($key); + } + + $intercepted = $this->cache->load($key); + return $intercepted ? $this->serializer->unserialize($intercepted) : null; + } + + /** + * Save config to cache backend + * + * @param string $key + * @param array $data + */ + public function save(string $key, array $data) + { + $this->cache->save($this->serializer->serialize($data), $key); + } + + /** + * Save config to filesystem + * + * @param string $key + * @param array $data + */ + public function saveCompiled(string $key, array $data) + { + $this->configWriter->write($key, $data); + } + + /** + * Purge interception cache + * + * @param string $key + */ + public function clean(string $key) + { + $this->cache->clean(\Zend_Cache::CLEANING_MODE_MATCHING_TAG, [$key]); + } + + /** + * Check for the compiled config with the generated metadata + * + * @param string $key + * @return bool + */ + private function isCompiled(string $key): bool + { + return file_exists(\Magento\Framework\App\ObjectManager\ConfigLoader\Compiled::getFilePath($key)); + } +} diff --git a/lib/internal/Magento/Framework/Interception/Config/Config.php b/lib/internal/Magento/Framework/Interception/Config/Config.php index 9a7845e96006b..4eeed4788a05e 100644 --- a/lib/internal/Magento/Framework/Interception/Config/Config.php +++ b/lib/internal/Magento/Framework/Interception/Config/Config.php @@ -8,7 +8,6 @@ namespace Magento\Framework\Interception\Config; use Magento\Framework\Serialize\SerializerInterface; -use Magento\Framework\Serialize\Serializer\Serialize; class Config implements \Magento\Framework\Interception\ConfigInterface { @@ -35,7 +34,7 @@ class Config implements \Magento\Framework\Interception\ConfigInterface /** * Cache - * + * @deprecated * @var \Magento\Framework\Cache\FrontendInterface */ protected $_cache; @@ -74,33 +73,24 @@ class Config implements \Magento\Framework\Interception\ConfigInterface protected $_scopeList; /** - * @var SerializerInterface - */ - private $serializer; - - /** - * @var \Magento\Framework\App\ObjectManager\ConfigWriterInterface - */ - private $configWriter; - - /** - * @var \Magento\Framework\App\ObjectManager\ConfigLoader\Compiled + * @var CacheManager */ - private $compiledLoader; + private $cacheManager; /** * Config constructor * * @param \Magento\Framework\Config\ReaderInterface $reader * @param \Magento\Framework\Config\ScopeListInterface $scopeList - * @param \Magento\Framework\Cache\FrontendInterface $cache + * @param \Magento\Framework\Cache\FrontendInterface $cache @deprecated * @param \Magento\Framework\ObjectManager\RelationsInterface $relations * @param \Magento\Framework\Interception\ObjectManager\ConfigInterface $omConfig * @param \Magento\Framework\ObjectManager\DefinitionInterface $classDefinitions * @param string $cacheId - * @param SerializerInterface|null $serializer - * @param \Magento\Framework\App\ObjectManager\ConfigWriterInterface $configWriter - * @param \Magento\Framework\App\ObjectManager\ConfigLoader\Compiled $compiledLoader + * @param SerializerInterface|null $serializer @deprecated + * @param CacheManager $cacheManager + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( \Magento\Framework\Config\ReaderInterface $reader, @@ -111,8 +101,7 @@ public function __construct( \Magento\Framework\ObjectManager\DefinitionInterface $classDefinitions, $cacheId = 'interception', SerializerInterface $serializer = null, - \Magento\Framework\App\ObjectManager\ConfigWriterInterface $configWriter = null, - \Magento\Framework\App\ObjectManager\ConfigLoader\Compiled $compiledLoader = null + CacheManager $cacheManager = null ) { $this->_omConfig = $omConfig; $this->_relations = $relations; @@ -121,14 +110,9 @@ public function __construct( $this->_cacheId = $cacheId; $this->_reader = $reader; $this->_scopeList = $scopeList; - $this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(Serialize::class); - $this->configWriter = $configWriter ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Framework\App\ObjectManager\ConfigWriter\Filesystem::class); - $this->compiledLoader = $compiledLoader ?: \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Framework\App\ObjectManager\ConfigLoader\Compiled::class); - $intercepted = $this->loadIntercepted(); - if ($intercepted !== false) { + $this->cacheManager = $cacheManager ?? \Magento\Framework\App\ObjectManager::getInstance()->get(CacheManager::class); + $intercepted = $this->cacheManager->load($cacheId); + if ($intercepted !== null) { $this->_intercepted = $intercepted; } else { $this->initializeUncompiled($this->_classDefinitions->getClasses()); @@ -145,7 +129,7 @@ public function initialize($classDefinitions = []) { $this->generateIntercepted($classDefinitions); - $this->configWriter->write($this->_cacheId, $this->_intercepted); + $this->cacheManager->saveCompiled($this->_cacheId, $this->_intercepted); } /** @@ -199,11 +183,11 @@ public function hasPlugins($type) */ private function initializeUncompiled($classDefinitions = []) { - $this->_cache->clean(\Zend_Cache::CLEANING_MODE_MATCHING_TAG, [$this->_cacheId]); + $this->cacheManager->clean($this->_cacheId); $this->generateIntercepted($classDefinitions); - $this->_cache->save($this->serializer->serialize($this->_intercepted), $this->_cacheId); + $this->cacheManager->save($this->_cacheId, $this->_intercepted); } /** @@ -230,29 +214,4 @@ private function generateIntercepted($classDefinitions) $this->hasPlugins($class); } } - - /** - * Load the interception config from cache - * - * @return array|false - */ - private function loadIntercepted() - { - if ($this->isCompiled()) { - return $this->compiledLoader->load($this->_cacheId); - } - - $intercepted = $this->_cache->load($this->_cacheId); - return $intercepted ? $this->serializer->unserialize($intercepted) : false; - } - - /** - * Check for the compiled config with the generated metadata - * - * @return bool - */ - private function isCompiled() - { - return file_exists(\Magento\Framework\App\ObjectManager\ConfigLoader\Compiled::getFilePath($this->_cacheId)); - } } diff --git a/lib/internal/Magento/Framework/Interception/Test/Unit/Config/ConfigTest.php b/lib/internal/Magento/Framework/Interception/Test/Unit/Config/ConfigTest.php index fe8d29bd0d51d..61eb2e62091ea 100644 --- a/lib/internal/Magento/Framework/Interception/Test/Unit/Config/ConfigTest.php +++ b/lib/internal/Magento/Framework/Interception/Test/Unit/Config/ConfigTest.php @@ -31,11 +31,6 @@ class ConfigTest extends \PHPUnit\Framework\TestCase */ private $readerMock; - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - private $cacheMock; - /** * @var \PHPUnit_Framework_MockObject_MockObject */ @@ -51,8 +46,10 @@ class ConfigTest extends \PHPUnit\Framework\TestCase */ private $relationsMock; - /** @var SerializerInterface|\PHPUnit_Framework_MockObject_MockObject */ - private $serializerMock; + /** + * @var \Magento\Framework\Interception\Config\CacheManager|\PHPUnit_Framework_MockObject_MockObject + */ + private $cacheManagerMock; /** @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ private $objectManagerHelper; @@ -61,7 +58,6 @@ protected function setUp() { $this->readerMock = $this->createMock(\Magento\Framework\ObjectManager\Config\Reader\Dom::class); $this->configScopeMock = $this->createMock(\Magento\Framework\Config\ScopeListInterface::class); - $this->cacheMock = $this->createMock(\Magento\Framework\Cache\FrontendInterface::class); $this->omConfigMock = $this->getMockForAbstractClass( \Magento\Framework\Interception\ObjectManager\ConfigInterface::class ); @@ -69,7 +65,7 @@ protected function setUp() $this->relationsMock = $this->getMockForAbstractClass( \Magento\Framework\ObjectManager\RelationsInterface::class ); - $this->serializerMock = $this->createMock(SerializerInterface::class); + $this->cacheManagerMock = $this->createMock(\Magento\Framework\Interception\Config\CacheManager::class); $this->objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); } @@ -88,9 +84,9 @@ public function testHasPluginsWhenDataIsNotCached($expectedResult, $type, $entit ->method('getAllScopes') ->will($this->returnValue(['global', 'backend', 'frontend'])); // turn cache off - $this->cacheMock->expects($this->any()) + $this->cacheManagerMock->expects($this->any()) ->method('load') - ->will($this->returnValue(false)); + ->will($this->returnValue(null)); $this->omConfigMock->expects($this->any()) ->method('getOriginalInstanceType') ->will($this->returnValueMap( @@ -138,21 +134,15 @@ public function testHasPluginsWhenDataIsNotCached($expectedResult, $type, $entit $this->relationsMock->expects($this->any())->method('has')->will($this->returnValue($expectedResult)); $this->relationsMock->expects($this->any())->method('getParents')->will($this->returnValue($entityParents)); - $this->serializerMock->expects($this->once()) - ->method('serialize'); - - $this->serializerMock->expects($this->never())->method('unserialize'); - $model = $this->objectManagerHelper->getObject( \Magento\Framework\Interception\Config\Config::class, [ 'reader' => $this->readerMock, 'scopeList' => $this->configScopeMock, - 'cache' => $this->cacheMock, + 'cacheManager' => $this->cacheManagerMock, 'relations' => $this->relationsMock, 'omConfig' => $this->omConfigMock, 'classDefinitions' => $this->definitionMock, - 'serializer' => $this->serializerMock ] ); @@ -177,32 +167,24 @@ public function testHasPluginsWhenDataIsCached($expectedResult, $type) 'virtual_custom_item' => true ]; $this->readerMock->expects($this->never())->method('read'); - $this->cacheMock->expects($this->never())->method('save'); - $serializedValue = 'serializedData'; - $this->cacheMock->expects($this->any()) + $this->cacheManagerMock->expects($this->never())->method('save'); + $this->cacheManagerMock->expects($this->any()) ->method('load') ->with($cacheId) - ->will($this->returnValue($serializedValue)); - - $this->serializerMock->expects($this->never())->method('serialize'); - $this->serializerMock->expects($this->once()) - ->method('unserialize') - ->with($serializedValue) - ->willReturn($interceptionData); + ->will($this->returnValue($interceptionData)); $model = $this->objectManagerHelper->getObject( \Magento\Framework\Interception\Config\Config::class, [ 'reader' => $this->readerMock, 'scopeList' => $this->configScopeMock, - 'cache' => $this->cacheMock, + 'cacheManager' => $this->cacheManagerMock, 'relations' => $this->objectManagerHelper->getObject( \Magento\Framework\ObjectManager\Relations\Runtime::class ), 'omConfig' => $this->omConfigMock, 'classDefinitions' => $this->definitionMock, 'cacheId' => $cacheId, - 'serializer' => $this->serializerMock ] );