Skip to content

Commit 178dbdd

Browse files
authored
ENGCOM-3243: Write intercepted mapping to generated/metadata during compilation #18648
2 parents f3ece45 + 25962d1 commit 178dbdd

File tree

14 files changed

+520
-76
lines changed

14 files changed

+520
-76
lines changed

app/etc/di.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
<preference for="Magento\Framework\App\CacheInterface" type="Magento\Framework\App\Cache\Proxy" />
2929
<preference for="Magento\Framework\App\Cache\StateInterface" type="Magento\Framework\App\Cache\State" />
3030
<preference for="Magento\Framework\App\Cache\TypeListInterface" type="Magento\Framework\App\Cache\TypeList" />
31+
<preference for="Magento\Framework\App\ObjectManager\ConfigWriterInterface" type="Magento\Framework\App\ObjectManager\ConfigWriter\Filesystem" />
3132
<preference for="Magento\Store\Model\StoreManagerInterface" type="Magento\Store\Model\StoreManager" />
3233
<preference for="Magento\Framework\View\DesignInterface" type="Magento\Theme\Model\View\Design\Proxy" />
3334
<preference for="Magento\Framework\View\Design\ThemeInterface" type="Magento\Theme\Model\Theme" />
@@ -413,6 +414,11 @@
413414
<argument name="cacheId" xsi:type="string">interception</argument>
414415
</arguments>
415416
</type>
417+
<type name="Magento\Framework\Interception\Config\CacheManager">
418+
<arguments>
419+
<argument name="cache" xsi:type="object">Magento\Framework\App\Cache\Type\Config</argument>
420+
</arguments>
421+
</type>
416422
<type name="Magento\Framework\Interception\PluginList\PluginList">
417423
<arguments>
418424
<argument name="cache" xsi:type="object">Magento\Framework\App\Cache\Type\Config</argument>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Framework\App\ObjectManager\ConfigWriter;
10+
11+
class FilesystemTest extends \PHPUnit\Framework\TestCase
12+
{
13+
const CACHE_KEY = 'filesystemtest';
14+
15+
/**
16+
* @var \Magento\Framework\App\ObjectManager\ConfigWriter\Filesystem
17+
*/
18+
private $configWriter;
19+
20+
/**
21+
* @var \Magento\Framework\App\ObjectManager\ConfigLoader
22+
*/
23+
private $configReader;
24+
25+
protected function setUp()
26+
{
27+
$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
28+
$this->configWriter = $objectManager->create(
29+
\Magento\Framework\App\ObjectManager\ConfigWriter\Filesystem::class
30+
);
31+
$this->configReader = $objectManager->create(
32+
\Magento\Framework\App\ObjectManager\ConfigLoader\Compiled::class
33+
);
34+
}
35+
36+
public function testWrite()
37+
{
38+
$sampleData = [
39+
'classA' => true,
40+
'classB' => false,
41+
];
42+
43+
$this->configWriter->write(self::CACHE_KEY, $sampleData);
44+
$this->assertEquals($sampleData, $this->configReader->load(self::CACHE_KEY));
45+
}
46+
47+
public function testOverwrite()
48+
{
49+
$this->configWriter->write(self::CACHE_KEY, ['hello' => 'world']);
50+
51+
$sampleData = [
52+
'classC' => false,
53+
'classD' => true,
54+
];
55+
56+
$this->configWriter->write(self::CACHE_KEY, $sampleData);
57+
$this->assertEquals($sampleData, $this->configReader->load(self::CACHE_KEY));
58+
}
59+
}

dev/tests/integration/testsuite/Magento/Framework/Interception/AbstractPlugin.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,35 @@
77

88
/**
99
* Class GeneralTest
10+
*
1011
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1112
*/
1213
abstract class AbstractPlugin extends \PHPUnit\Framework\TestCase
1314
{
1415
/**
16+
* Config reader
17+
*
1518
* @var \PHPUnit_Framework_MockObject_MockObject
1619
*/
1720
protected $_configReader;
1821

1922
/**
23+
* Object Manager
24+
*
2025
* @var \Magento\Framework\ObjectManagerInterface
2126
*/
2227
protected $_objectManager;
2328

2429
/**
30+
* Applicartion Object Manager
31+
*
2532
* @var \Magento\Framework\ObjectManagerInterface
2633
*/
2734
private $applicationObjectManager;
2835

36+
/**
37+
* Set up
38+
*/
2939
public function setUp()
3040
{
3141
if (!$this->_objectManager) {
@@ -36,11 +46,19 @@ public function setUp()
3646
\Magento\Framework\App\ObjectManager::setInstance($this->_objectManager);
3747
}
3848

49+
/**
50+
* Tear down
51+
*/
3952
public function tearDown()
4053
{
4154
\Magento\Framework\App\ObjectManager::setInstance($this->applicationObjectManager);
4255
}
4356

57+
/**
58+
* Set up Interception Config
59+
*
60+
* @param array $pluginConfig
61+
*/
4462
public function setUpInterceptionConfig($pluginConfig)
4563
{
4664
$config = new \Magento\Framework\Interception\ObjectManager\Config\Developer();
@@ -59,7 +77,8 @@ public function setUpInterceptionConfig($pluginConfig)
5977
$areaList->expects($this->any())->method('getCodes')->will($this->returnValue([]));
6078
$configScope = new \Magento\Framework\Config\Scope($areaList, 'global');
6179
$cache = $this->createMock(\Magento\Framework\Config\CacheInterface::class);
62-
$cache->expects($this->any())->method('load')->will($this->returnValue(false));
80+
$cacheManager = $this->createMock(\Magento\Framework\Interception\Config\CacheManager::class);
81+
$cacheManager->method('load')->willReturn(null);
6382
$definitions = new \Magento\Framework\ObjectManager\Definition\Runtime();
6483
$relations = new \Magento\Framework\ObjectManager\Relations\Runtime();
6584
$interceptionConfig = new Config\Config(
@@ -68,7 +87,10 @@ public function setUpInterceptionConfig($pluginConfig)
6887
$cache,
6988
$relations,
7089
$config,
71-
$definitions
90+
$definitions,
91+
'interception',
92+
null,
93+
$cacheManager
7294
);
7395
$interceptionDefinitions = new Definition\Runtime();
7496
$json = new \Magento\Framework\Serialize\Serializer\Json();
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Framework\Interception\Config;
10+
11+
use Magento\Framework\App\Filesystem\DirectoryList;
12+
13+
class CacheManagerTest extends \PHPUnit\Framework\TestCase
14+
{
15+
const CACHE_ID = 'interceptiontest';
16+
17+
/**
18+
* @var \Magento\Framework\ObjectManagerInterface
19+
*/
20+
private $objectManager;
21+
22+
/**
23+
* @var \Magento\Framework\Serialize\SerializerInterface
24+
*/
25+
private $serializer;
26+
27+
/**
28+
* @var \Magento\Framework\Cache\FrontendInterface
29+
*/
30+
private $cache;
31+
32+
/**
33+
* @var \Magento\Framework\App\ObjectManager\ConfigWriterInterface
34+
*/
35+
private $configWriter;
36+
37+
protected function setUp()
38+
{
39+
$this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
40+
41+
$this->serializer = $this->objectManager->get(\Magento\Framework\Serialize\SerializerInterface::class);
42+
$this->cache = $this->objectManager->get(\Magento\Framework\App\CacheInterface::class);
43+
$this->configWriter =
44+
$this->objectManager->get(\Magento\Framework\App\ObjectManager\ConfigWriter\Filesystem::class);
45+
46+
$this->initializeMetadataDirectory();
47+
}
48+
49+
/**
50+
* Delete compiled file if it was created and clear cache data
51+
*/
52+
protected function tearDown()
53+
{
54+
$compiledPath = \Magento\Framework\App\ObjectManager\ConfigLoader\Compiled::getFilePath(self::CACHE_ID);
55+
if (file_exists($compiledPath)) {
56+
unlink($compiledPath);
57+
}
58+
59+
$this->cache->remove(self::CACHE_ID);
60+
}
61+
62+
/**
63+
* Test load interception cache from generated/metadata
64+
* @dataProvider interceptionCompiledConfigDataProvider
65+
* @param array $testConfig
66+
*/
67+
public function testInstantiateFromCompiled(array $testConfig)
68+
{
69+
$this->configWriter->write(self::CACHE_ID, $testConfig);
70+
$config = $this->getConfig();
71+
72+
$this->assertEquals($testConfig, $config->load(self::CACHE_ID));
73+
}
74+
75+
/**
76+
* Test load interception cache from backend cache
77+
* @dataProvider interceptionCacheConfigDataProvider
78+
* @param array $testConfig
79+
*/
80+
public function testInstantiateFromCache(array $testConfig)
81+
{
82+
$this->cache->save($this->serializer->serialize($testConfig), self::CACHE_ID);
83+
$config = $this->getConfig();
84+
85+
$this->assertEquals($testConfig, $config->load(self::CACHE_ID));
86+
}
87+
88+
public function interceptionCompiledConfigDataProvider()
89+
{
90+
return [
91+
[['classA' => true, 'classB' => false]],
92+
[['classA' => false, 'classB' => true]],
93+
];
94+
}
95+
96+
public function interceptionCacheConfigDataProvider()
97+
{
98+
return [
99+
[['classC' => true, 'classD' => false]],
100+
[['classC' => false, 'classD' => true]],
101+
];
102+
}
103+
104+
/**
105+
* Ensure generated/metadata exists
106+
*/
107+
private function initializeMetadataDirectory()
108+
{
109+
$diPath = DirectoryList::getDefaultConfig()[DirectoryList::GENERATED_METADATA][DirectoryList::PATH];
110+
$fullPath = BP . DIRECTORY_SEPARATOR . $diPath;
111+
if (!file_exists($fullPath)) {
112+
mkdir($fullPath);
113+
}
114+
}
115+
116+
/**
117+
* Create instance of Config class with specific cacheId. This is done to prevent our test
118+
* from altering the interception config that may have been generated during application
119+
* installation. Inject a new instance of the compileLoaded to bypass it's caching.
120+
*
121+
* @return \Magento\Framework\Interception\Config\CacheManager
122+
*/
123+
private function getConfig()
124+
{
125+
return $this->objectManager->create(
126+
\Magento\Framework\Interception\Config\CacheManager::class,
127+
[
128+
'cacheId' => self::CACHE_ID,
129+
'compiledLoader' => $this->objectManager->create(
130+
\Magento\Framework\App\ObjectManager\ConfigLoader\Compiled::class
131+
),
132+
]
133+
);
134+
}
135+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Framework\App\ObjectManager\ConfigWriter;
10+
11+
use Magento\Framework\App\Filesystem\DirectoryList;
12+
use Magento\Framework\App\ObjectManager\ConfigWriterInterface;
13+
14+
/**
15+
* @inheritdoc
16+
*/
17+
class Filesystem implements ConfigWriterInterface
18+
{
19+
/**
20+
* @var DirectoryList
21+
*/
22+
private $directoryList;
23+
24+
/**
25+
* @param DirectoryList $directoryList
26+
*/
27+
public function __construct(
28+
DirectoryList $directoryList
29+
) {
30+
$this->directoryList = $directoryList;
31+
}
32+
33+
/**
34+
* Writes config in storage
35+
*
36+
* @param string $key
37+
* @param array $config
38+
* @return void
39+
*/
40+
public function write(string $key, array $config)
41+
{
42+
$this->initialize();
43+
$configuration = sprintf('<?php return %s;', var_export($config, true));
44+
file_put_contents(
45+
$this->directoryList->getPath(DirectoryList::GENERATED_METADATA) . '/' . $key . '.php',
46+
$configuration
47+
);
48+
}
49+
50+
/**
51+
* Initializes writer
52+
*
53+
* @return void
54+
*/
55+
private function initialize()
56+
{
57+
if (!file_exists($this->directoryList->getPath(DirectoryList::GENERATED_METADATA))) {
58+
mkdir($this->directoryList->getPath(DirectoryList::GENERATED_METADATA));
59+
}
60+
}
61+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Framework\App\ObjectManager;
10+
11+
/**
12+
* Write compiled object manager configuration to storage
13+
*/
14+
interface ConfigWriterInterface
15+
{
16+
/**
17+
* Writes config in storage
18+
*
19+
* @param string $key
20+
* @param array $config
21+
* @return void
22+
*/
23+
public function write(string $key, array $config);
24+
}

0 commit comments

Comments
 (0)