8000 [DI] Generate one file per service factory · symfony/symfony@719e8c1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 719e8c1

Browse files
[DI] Generate one file per service factory
1 parent 0f2563c commit 719e8c1

File tree

19 files changed

+778
-235
lines changed

19 files changed

+778
-235
lines changed

src/Symfony/Bridge/Doctrine/ManagerRegistry.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,12 @@ function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) {
5959
if (isset($this->aliases[$name])) {
6060
$name = $this->aliases[$name];
6161
}
62-
$method = !isset($this->methodMap[$name]) ? 'get'.strtr($name, $this->underscoreMap).'Service' : $this->methodMap[$name];
63-
$wrappedInstance = $this->{$method}(false);
62+
if (isset($this->fileMap[$name])) {
63+
$wrappedInstance = $this->load($this->fileMap[$name], false);
64+
} else {
65+
$method = !isset($this->methodMap[$name]) ? 'get'.strtr($name, $this->underscoreMap).'Service' : $this->methodMap[$name];
66+
$wrappedInstance = $this->{$method}(false);
67+
}
6468

6569
$manager->setProxyInitializer(null);
6670

src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,24 +81,21 @@ public function getProxyFactoryCode(Definition $definition, $id, $factoryCode =
8181
}
8282
$proxyClass = $this->getProxyClassName($definition);
8383

84-
$generatedClass = $this->generateProxyClass($definition);
84+
$hasStaticConstructor = $this->generateProxyClass($definition)->hasMethod('staticProxyConstructor');
8585

86-
$constructorCall = $generatedClass->hasMethod('staticProxyConstructor')
87-
? $proxyClass.'::staticProxyConstructor'
88-
: 'new '.$proxyClass;
86+
$constructorCall = sprintf($hasStaticConstructor ? '%s::staticProxyConstructor' : 'new %s', '\\'.$proxyClass);
8987

9088
return <<<EOF
9189
if (\$lazyLoad) {
92-
93-
$instantiation $constructorCall(
94-
function (&\$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface \$proxy) {
90+
$instantiation \$this->createProxy('$proxyClass', function () {
91+
return $constructorCall(function (&\$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface \$proxy) {
9592
\$wrappedInstance = $factoryCode;
9693
9794
\$proxy->setProxyInitializer(null);
9895
9996
return true;
100-
}
101-
);
97+
});
98+
});
10299
}
103100
104101
@@ -122,7 +119,7 @@ public function getProxyCode(Definition $definition)
122119
*/
123120
private function getProxyClassName(Definition $definition)
124121
{
125-
return str_replace('\\', '', $definition->getClass()).'_'.spl_object_hash($definition).$this->salt;
122+
return preg_replace('/^.*\\\\/', '', $definition->getClass()).'_'.substr(hash('sha256', spl_object_hash($definition).$this->salt), -7);
126123
}
127124

128125
/**

src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,18 @@
33
use %a
44
class LazyServiceProjectServiceContainer extends Container
55
{%a
6-
p%s function getFooService($lazyLoad = true)
6+
protected function getFooService($lazyLoad = true)
77
{
88
if ($lazyLoad) {
9-
10-
return $this->services['foo'] =%sstdClass_%s(
11-
function (&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) {
9+
return $this->services['foo'] = $this->createProxy('stdClass_%s', function () {
10+
return %S\stdClass_%s(function (&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) {
1211
$wrappedInstance = $this->getFooService(false);
1312

1413
$proxy->setProxyInitializer(null);
1514

1615
return true;
17-
}
18-
);
16+
});
17+
});
1918
}
2019

2120
return new \stdClass();

src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,13 @@ public function testGetProxyCode()
5555
$code = $this->dumper->getProxyCode($definition);
5656

5757
7802 $this->assertStringMatchesFormat(
58-
'%Aclass SymfonyBridgeProxyManagerTestsLazyProxyPhpDumperProxyDumperTest%aextends%w'
58+
'%Aclass ProxyDumperTest%aextends%w'
5959
.'\Symfony\Bridge\ProxyManager\Tests\LazyProxy\PhpDumper\ProxyDumperTest%a',
6060
$code
6161
);
6262
}
6363

64-
public function testGetProxyFactoryCodeWithCustomMethod()
64+
public function testGetProxyFactoryCode()
6565
{
6666
$definition = new Definition(__CLASS__);
6767

@@ -70,19 +70,15 @@ public function testGetProxyFactoryCodeWithCustomMethod()
7070
$code = $this->dumper->getProxyFactoryCode($definition, 'foo', '$this->getFoo2Service(false)');
7171

7272
$this->assertStringMatchesFormat(
73-
'%wif ($lazyLoad) {%wreturn $this->services[\'foo\'] =%s'
74-
.'SymfonyBridgeProxyManagerTestsLazyProxyPhpDumperProxyDumperTest_%s(%wfunction '
75-
.'(&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) {'
76-
.'%w$wrappedInstance = $this->getFoo2Service(false);%w$proxy->setProxyInitializer(null);'
77-
.'%wreturn true;%w}%w);%w}%w',
78-
$code
73+
'%A$wrappedInstance = $this->getFoo2Service(false);%w$proxy->setProxyInitializer(null);%A',
74+
$code
7975
);
8076
}
8177

8278
/**
8379
* @group legacy
8480
*/
85-
public function testGetProxyFactoryCode()
81+
public function testLegacyGetProxyFactoryCode()
8682
{
8783
$definition = new Definition(__CLASS__);
8884

@@ -91,11 +87,7 @@ public function testGetProxyFactoryCode()
9187
$code = $this->dumper->getProxyFactoryCode($definition, 'foo');
9288

9389
$this->assertStringMatchesFormat(
94-
'%wif ($lazyLoad) {%wreturn $this->services[\'foo\'] =%s'
95-
.'SymfonyBridgeProxyManagerTestsLazyProxyPhpDumperProxyDumperTest_%s(%wfunction '
96-
.'(&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) {'
97-
.'%w$wrappedInstance = $this->getFooService(false);%w$proxy->setProxyInitializer(null);'
98-
.'%wreturn true;%w}%w);%w}%w',
90+
'%A$wrappedInstance = $this->getFooService(false);%w$proxy->setProxyInitializer(null);%A',
9991
$code
10092
);
10193
}

src/Symfony/Bridge/ProxyManager/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
],
1818
"require": {
1919
"php": "^5.5.9|>=7.0.8",
20-
"symfony/dependency-injection": "~2.8|~3.0|~4.0",
20+
"symfony/dependency-injection": "~3.4|~4.0",
2121
"ocramius/proxy-manager": "~0.4|~1.0|~2.0"
2222
},
2323
"require-dev": {

src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\Console\Input\InputOption;
1616
use Symfony\Component\Console\Output\OutputInterface;
1717
use Symfony\Component\Console\Style\SymfonyStyle;
18+
use Symfony\Component\EventDispatcher\EventDispatcher;
1819
use Symfony\Component\HttpKernel\KernelInterface;
1920
use Symfony\Component\Finder\Finder;
2021

@@ -92,6 +93,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
9293

9394
$filesystem->remove($oldCacheDir);
9495

96+
// The current event dispatcher is stale, let's not use it anymore
97+
$this->getApplication()->setDispatcher(new EventDispatcher());
98+
9599
if ($output->isVerbose()) {
96100
$io->comment('Finished');
97101
}
@@ -181,13 +185,19 @@ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = tr
181185
}
182186

183187
// fix references to container's class
184-
$tempContainerClass = get_class($tempKernel->getContainer());
185-
$realContainerClass = get_class($realKernel->getContainer());
188+
$tempContainerClass = $tempKernel->getContainerClass();
189+
$realContainerClass = $tempKernel->getRealContainerClass();
186190
foreach (Finder::create()->files()->depth('<2')->name($tempContainerClass.'*')->in($warmupDir) as $file) {
187191
$content = str_replace($tempContainerClass, $realContainerClass, file_get_contents($file));
188192
file_put_contents($file, $content);
189193
rename($file, str_replace(DIRECTORY_SEPARATOR.$tempContainerClass, DIRECTORY_SEPARATOR.$realContainerClass, $file));
190194
}
195+
if (is_dir($tempContainerDir = $warmupDir.'/'.get_class($tempKernel->getContainer()))) {
196+
foreach (Finder::create()->files()->in($tempContainerDir) as $file) {
197+
$content = str_replace($tempContainerClass, $realContainerClass, file_get_contents($file));
198+
file_put_contents($file, $content);
199+
}
200+
}
191201

192202
// remove temp kernel file after cache warmed up
193203
@unlink($tempKernelFile);
@@ -213,7 +223,9 @@ protected function getTempKernel(KernelInterface $parent, $namespace, $parentCla
213223
// to avoid the many problems in serialized resources files
214224
$class = substr($parentClass, 0, -1).'_';
215225
// the temp container class must be changed too
216-
$containerClass = var_export(substr(get_class($parent->getContainer()), 0, -1).'_', true);
226+
$container = $parent->getContainer();
227+
$realContainerClass = var_export($container->hasParameter('kernel.container_class') ? $container->getParameter('kernel.container_class') : get_class($parent->getContainer()), true);
228+
$containerClass = substr_replace($realContainerClass, '_', -2, 1);
217229

218230
if (method_exists($parent, 'getProjectDir')) {
219231
$projectDir = var_export(realpath($parent->getProjectDir()), true);
@@ -249,7 +261,12 @@ public function getLogDir()
249261
return $logDir;
250262
}
251263
252-
protected function getContainerClass()
264+
public function getRealContainerClass()
265+
{
266+
return $realContainerClass;
267+
}
268+
269+
public function getContainerClass()
253270
{
254271
return $containerClass;
255272
}

src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,9 @@ public function testCacheIsFreshAfterCacheClearedWithWarmup()
6868
}
6969

7070
// check that app kernel file present in meta file of container's cache
71-
$containerRef = new \ReflectionObject($this->kernel->getContainer());
72-
$containerFile = $containerRef->getFileName();
71+
$containerClass = $this->kernel->getContainer()->getParameter('kernel.container_class');
72+
$containerRef = new \ReflectionClass($containerClass);
73+
$containerFile = dirname(dirname($containerRef->getFileName())).'/'.$containerClass.'.php';
7374
$containerMetaFile = $containerFile.'.meta';
7475
$kernelRef = new \ReflectionObject($this->kernel);
7576
$kernelFile = $kernelRef->getFileName();
@@ -83,6 +84,12 @@ public function testCacheIsFreshAfterCacheClearedWithWarmup()
8384
}
8485
}
8586
$this->assertTrue($found, 'Kernel file should present as resource');
86-
$this->assertRegExp(sprintf('/\'kernel.container_class\'\s*=>\s*\'%s\'/', get_class($this->kernel->getContainer())), file_get_contents($containerFile), 'kernel.container_class is properly set on the dumped container');
87+
88+
if (defined('HHVM_VERSION')) {
89+
return;
90+
}
91+
$containerRef = new \ReflectionClass(require $containerFile);
92+
$containerFile = str_replace('tes_'.DIRECTORY_SEPARATOR, 'test'.DIRECTORY_SEPARATOR, $containerRef->getFileName());
93+
$this->assertRegExp(sprintf('/\'kernel.container_class\'\s*=>\s*\'%s\'/', $containerClass), file_get_contents($containerFile), 'kernel.container_class is properly set on the dumped container');
8794
}
8895
}

src/Symfony/Component/DependencyInjection/Container.php

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class Container implements ResettableContainerInterface
5555
protected $parameterBag;
5656

5757
protected $services = array();
58+
protected $fileMap = array();
5859
protected $methodMap = array();
5960
protected $aliases = array();
6061
protected $loading = array();
@@ -203,7 +204,7 @@ public function set($id, $service)
203204
} else {
204205
@trigger_error(sprintf('Setting the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED);
205206
}
206-
} elseif (isset($this->methodMap[$id])) {
207+
} elseif (isset($this->fileMap[$id]) || isset($this->methodMap[$id])) {
207208
if (null === $service) {
208209
@trigger_error(sprintf('Unsetting the "%s" pre-defined service is deprecated since Symfony 3.3 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED);
209210
} else {
@@ -235,7 +236,7 @@ public function has($id)
235236
return true;
236237
}
237238

238-
if (isset($this->methodMap[$id])) {
239+
if (isset($this->fileMap[$id]) || isset($this->methodMap[$id])) {
239240
return true;
240241
}
241242

@@ -299,49 +300,48 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE
299300
throw new ServiceCircularReferenceException($id, array_keys($this->loading));
300301
}
301302

302-
if (isset($this->methodMap[$id])) {
303-
$method = $this->methodMap[$id];
304-
} elseif (--$i && $id !== $normalizedId = $this->normalizeId($id)) {
305-
$id = $normalizedId;
306-
continue;
307-
} elseif (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, $method = 'get'.strtr($id, $this->underscoreMap).'Service')) {
308-
// We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder,
309-
// and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper)
310-
@trigger_error('Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED);
311-
// $method is set to the right value, proceed
312-
} else {
313-
if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) {
314-
if (!$id) {
315-
throw new ServiceNotFoundException($id);
316-
}
317-
318-
$alternatives = array();
319-
foreach ($this->getServiceIds() as $knownId) {
320-
$lev = levenshtein($id, $knownId);
321-
if ($lev <= strlen($id) / 3 || false !== strpos($knownId, $id)) {
322-
$alternatives[] = $knownId;
323-
}
324-
}
325-
326-
throw new ServiceNotFoundException($id, null, null, $alternatives);
327-
}
328-
329-
return;
330-
}
331-
332303
$this->loading[$id] = true;
333304

334305
try {
335-
$service = $this->$method();
306+
if (isset($this->fileMap[$id])) {
307+
return $this->load($this->fileMap[$id]);
308+
} elseif (isset($this->methodMap[$id])) {
309+
return $this->{$this->methodMap[$id]}();
310+
} elseif (--$i && $id !== $normalizedId = $this->normalizeId($id)) {
311+
$id = $normalizedId;
312+
continue;
313+
} elseif (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, $method = 'get'.strtr($id, $this->underscoreMap).'Service')) {
314+
// We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder,
315+
// and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper)
316+
@trigger_error('Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED);
317+
318+
return $this->{$method}();
319+
}
320+
321+
break;
336322
} catch (\Exception $e) {
337323
unset($this->services[$id]);
338324

339325
throw $e;
340326
} finally {
341327
unset($this->loading[$id]);
342328
}
329+
}
330+
331+
if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) {
332+
if (!$id) {
333+
throw new ServiceNotFoundException($id);
334+
}
335+
336+
$alternatives = array();
337+
foreach ($this->getServiceIds() as $knownId) {
338+
$lev = levenshtein($id, $knownId);
339+
if ($lev <= strlen($id) / 3 || false !== strpos($knownId, $id)) {
340+
$alternatives[] = $knownId;
341+
}
342+
}
343343

344-
return $service;
344+
throw new ServiceNotFoundException($id, null, null, $alternatives);
345345
}
346346
}
347347

@@ -401,7 +401,7 @@ public function getServiceIds()
401401
}
402402
$ids[] = 'service_container';
403403

404-
return array_unique(array_merge($ids, array_keys($this->methodMap), array_keys($this->services)));
404+
return array_unique(array_merge($ids, array_keys($this->methodMap), array_keys($this->fileMap), array_keys($this->services)));
405405
}
406406

407407
/**
@@ -428,6 +428,16 @@ public static function underscore($id)
428428
return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), str_replace('_', '.', $id)));
429429
}
430430

431+
/**
432+
* Creates a service by requiring its factory file.
433+
*
434+
* @return object The service created by the file
435+
*/
436+
protected function load($file)
437+
{
438+
return require $file;
439+
}
440+
431441
/**
432442
* Fetches a variable from the environment.
433443
*

0 commit comments

Comments
 (0)
0