8000 [DI] Generate one factory class per private service · symfony/symfony@c6062d6 · GitHub
[go: up one dir, main page]

Skip to content

Commit c6062d6

Browse files
[DI] Generate one factory class per private service
1 parent f96fc19 commit c6062d6

20 files changed

+312
-181
lines changed

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,14 @@ public function getProxyFactoryCode(Definition $definition, $id, $methodName = n
7070
$instantiation = 'return';
7171

7272
if ($definition->isShared()) {
73-
$instantiation .= sprintf(' $this->%s[\'%s\'] =', $definition->isPublic() || !method_exists(ContainerBuilder::class, 'addClassResource') ? 'services' : 'privates', $id);
73+
$instantiation .= sprintf(' $container->%s[\'%s\'] =', $definition->isPublic() || !method_exists(ContainerBuilder::class, 'addClassResource') ? 'services' : 'privates', $id);
7474
}
7575

7676
if (null === $methodName) {
7777
throw new \InvalidArgumentException(sprintf('Missing name of method to call to construct the service "%s".', $id));
7878
}
7979

80+
$factoryCall = sprintf($definition->isPublic() || !method_exists(ContainerBuilder::class, 'addClassResource') ? '$container->%s(false)' : '%s::create($container, false)', $methodName);
8081
$proxyClass = $this->getProxyClassName($definition);
8182

8283
$generatedClass = $this->generateProxyClass($definition);
@@ -89,8 +90,8 @@ public function getProxyFactoryCode(Definition $definition, $id, $methodName = n
8990
if (\$lazyLoad) {
9091
9192
$instantiati F438 on $constructorCall(
92-
function (&\$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface \$proxy) {
93-
\$wrappedInstance = \$this->$methodName(false);
93+
function (&\$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface \$proxy) use (\$container) {
94+
\$wrappedInstance = $factoryCall;
9495
9596
\$proxy->setProxyInitializer(null);
9697

src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ protected function processValue($value, $isRoot = false)
8383
return $value;
8484
}
8585
if ($value instanceof Expression) {
86-
$this->getExpressionLanguage()->compile((string) $value, array('this' => 'container'));
86+
$this->getExpressionLanguage()->compile((string) $value, array('container' => 'container'));
8787

8888
return $value;
8989
}
@@ -168,7 +168,7 @@ private function getExpressionLanguage()
168168
);
169169
}
170170

171-
return sprintf('$this->get(%s)', $arg);
171+
return sprintf('$container->get(%s)', $arg);
172172
});
173173
}
174174

src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Lines changed: 75 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class PhpDumper extends Dumper
6666
private $docStar;
6767
private $serviceIdToMethodNameMap;
6868
private $usedMethodNames;
69+
private $class;
6970

7071
/**
7172
* @var \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface
@@ -121,6 +122,7 @@ public function dump(array $options = array())
121122
'debug' => true,
122123
), $options);
123124

125+
$this->class = $options['class'];
124126
$this->initializeMethodNamesMap($options['base_class']);
125127

126128
$this->docStar = $options['debug'] ? '*' : '';
@@ -156,9 +158,10 @@ public function dump(array $options = array())
156158
$this->addReset().
157159
$this->addCompile().
158160
$this->addIsCompiled().
159-
$this->addServices().
161+
$this->addPublicServices().
160162
$this->addDefaultParametersMethod().
161163
$this->endClass().
164+
$this->addPrivateServices().
162165
$this->addProxyClasses()
163166
;
164167
$this->targetDirRegex = null;
@@ -402,7 +405,7 @@ private function addServiceInstance($id, Definition $definition, $isSimpleInstan
402405
$instantiation = '';
403406

404407
if (!$isProxyCandidate && $definition->isShared()) {
405-
$instantiation = sprintf('$this->%s[\'%s\'] = %s', $this->container->getDefinition($id)->isPublic() ? 'services' : 'privates', $id, $isSimpleInstance ? '' : '$instance');
408+
$instantiation = sprintf('$container->%s[\'%s\'] = %s', $this->container->getDefinition($id)->isPublic() ? 'services' : 'privates', $id, $isSimpleInstance ? '' : '$instance');
406409
} elseif (!$isSimpleInstance) {
407410
$instantiation = '$instance';
408411
}
@@ -658,15 +661,21 @@ private function addService($id, Definition $definition)
658661
$autowired = $definition->isAutowired() ? ' autowired' : '';
659662

660663
if ($definition->isLazy()) {
661-
$lazyInitialization = '$lazyLoad = true';
662-
} else {
664+
$lazyInitialization = 'bool $lazyLoad = true';
665+
if (!$definition->isPublic()) {
666+
$lazyInitialization = 'parent $container, '.$lazyInitialization;
667+
}
668+
} elseif ($definition->isPublic()) {
663669
$lazyInitialization = '';
670+
} else {
671+
$lazyInitialization = 'parent $container';
664672
}
665673

666674
// with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer
667675
$isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition);
668-
$visibility = $isProxyCandidate ? 'public' : ($definition->isPublic() ? 'protected' : 'private');
669-
$methodName = $this->generateMethodName($id);
676+
$visibility = $isProxyCandidate ? 'public' : ($definition->isPublic() ? 'protected' : 'protected static');
677+
$generatedMethodName = $this->generateMethodName($id);
678+
$methodName = $definition->isPublic() ? $generatedMethodName : 'create';
670679
$code = <<<EOF
671680
672681
/*{$this->docStar}
@@ -679,7 +688,11 @@ private function addService($id, Definition $definition)
679688
680689
EOF;
681690

682-
$code .= $isProxyCandidate ? $this->getProxyDumper()->getProxyFactoryCode($definition, $id, $methodName) : '';
691+
if ($definition->isPublic()) {
692+
$code .= " \$container = \$this;\n\n";
693+
}
694+
695+
$code .= $isProxyCandidate ? $this->getProxyDumper()->getProxyFactoryCode($definition, $id, $definition->isPublic() ? $methodName : $this->class.'_'.substr($generatedMethodName, 3)) : '';
683696

684697
if ($definition->isDeprecated()) {
685698
$code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id)));
@@ -700,31 +713,52 @@ private function addService($id, Definition $definition)
700713
$this->addServiceReturn($id, $isSimpleInstance)
701714
;
702715

716+
if (!$definition->isPublic()) {
717+
$code = sprintf("\nclass %s_%s extends %1\$s\n{%s}\n", $this->class, substr($generatedMethodName, 3), $code);
718+
}
719+
703720
$this->definitionVariables = null;
704721
$this->referenceVariables = null;
705722

706723
return $code;
707724
}
708725

709726
/**
710-
* Adds multiple services.
727+
* Adds multiple public services.
711728
*
712729
* @return string
713730
*/
714-
private function addServices()
731+
private function addPublicServices()
715732
{
716-
$publicServices = $privateServices = '';
733+
$publicServices = '';
717734
$definitions = $this->container->getDefinitions();
718735
ksort($definitions);
719736
foreach ($definitions as $id => $definition) {
720737
if ($definition->isPublic()) {
721738
$publicServices .= $this->addService($id, $definition);
722-
} elseif (!$this->isTrivialInstance($definition)) {
739+
}
740+
}
741+
742+
return $publicServices;
743+
}
744+
745+
/**
746+
* Adds multiple private services.
747+
*
748+
* @return string
749+
*/
750+
private function addPrivateServices()
751+
{
752+
$privateServices = '';
753+
$definitions = $this->container->getDefinitions();
754+
ksort($definitions);
755+
foreach ($definitions as $id => $definition) {
756+
if (!$definition->isPublic() && !$this->isTrivialInstance($definition)) {
723757
$privateServices .= $this->addService($id, $definition);
724758
}
725759
}
726760

727-
return $publicServices.$privateServices;
761+
return $privateServices;
728762
}
729763

730764
private function addNewInstance(Definition $definition, $return, $instantiation, $id)
@@ -809,9 +843,9 @@ private function startClass($class, $baseClass, $namespace)
809843
*/
810844
class $class extends $baseClass
811845
{
812-
private \$parameters;
813-
private \$targetDirs = array();
814-
private \$privates = array();
846+
protected \$parameters;
847+
protected \$targetDirs = array();
848+
protected \$privates = array();
815849
816850
EOF;
817851
}
@@ -979,7 +1013,7 @@ private function addDefaultParametersMethod()
9791013
$export = $this->exportParameters(array($value));
9801014
$export = explode('0 => ', substr(rtrim($export, " )\n"), 7, -1), 2);
9811015

982-
if (preg_match("/\\\$this->(?:getEnv\('\w++'\)|targetDirs\[\d++\])/", $export[1])) {
1016+
if (preg_match("/\\\$container->(?:getEnv\('\w++'\)|targetDirs\[\d++\])/", $export[1])) {
9831017
$dynamicPhp[$key] = sprintf('%scase %s: $value = %s; break;', $export[0], $this->export($key), $export[1]);
9841018
} else {
9851019
$php[] = sprintf('%s%s => %s,', $export[0], $this->export($key), $export[1]);
@@ -1358,19 +1392,19 @@ private function dumpValue($value, $interpolate = true)
13581392

13591393
$code = sprintf('return %s;', $code);
13601394

1361-
return sprintf("function ()%s {\n %s\n }", $returnedType, $code);
1395+
return sprintf("function () use (\$container)%s {\n %s\n }", $returnedType, $code);
13621396
}
13631397

13641398
if ($value instanceof IteratorArgument) {
13651399
$operands = array(0);
13661400
$code = array();
1367-
$code[] = 'new RewindableGenerator(function () {';
1401+
$code[] = 'new RewindableGenerator(function () use ($container) {';
13681402

13691403
if (!$values = $value->getValues()) {
13701404
$code[] = ' return new \EmptyIterator();';
13711405
} else {
13721406
$countCode = array();
1373-
$countCode[] = 'function () {';
1407+
$countCode[] = 'function () use ($container) {';
13741408

13751409
foreach ($values as $k => $v) {
13761410
($c = $this->getServiceConditionals($v)) ? $operands[] = "(int) ($c)" : ++$operands[0];
@@ -1455,7 +1489,7 @@ private function dumpValue($value, $interpolate = true)
14551489

14561490
return $this->getServiceCall((string) $value, $value);
14571491
} elseif ($value instanceof Expression) {
1458-
return $this->getExpressionLanguage()->compile((string) $value, array('this' => 'container'));
1492+
return $this->getExpressionLanguage()->compile((string) $value, array('container' => 'container'));
14591493
} elseif ($value instanceof Parameter) {
14601494
return $this->dumpParameter($value);
14611495
} elseif (true === $interpolate && is_string($value)) {
@@ -1521,12 +1555,12 @@ private function dumpParameter($name)
15211555
return $dumpedValue;
15221556
}
15231557

1524-
if (!preg_match("/\\\$this->(?:getEnv\('\w++'\)|targetDirs\[\d++\])/", $dumpedValue)) {
1525-
return sprintf("\$this->parameters['%s']", $name);
1558+
if (!preg_match("/\\\$container->(?:getEnv\('\w++'\)|targetDirs\[\d++\])/", $dumpedValue)) {
1559+
return sprintf("\$container->parameters['%s']", $name);
15261560
}
15271561
}
15281562

1529-
return sprintf("\$this->getParameter('%s')", $name);
1563+
return sprintf("\$container->getParameter('%s')", $name);
15301564
}
15311565

15321566
/**
@@ -1544,27 +1578,30 @@ private function getServiceCall($id, Reference $reference = null)
15441578
}
15451579

15461580
if ('service_container' === $id) {
1547-
return '$this';
1581+
return '$container';
15481582
}
15491583

15501584
if ($this->container->hasDefinition($id)) {
15511585
$definition = $this->container->getDefinition($id);
15521586

1553-
if ($definition->isPublic() || !$this->isTrivialInstance($definition)) {
1554-
$code = sprintf('$this->%s()', $this->generateMethodName($id));
1555-
} else {
1587+
if ($definition->isPublic()) {
1588+
$code = sprintf('$container->%s()', $this->generateMethodName($id));
1589+
} elseif ($this->isTrivialInstance($definition)) {
15561590
$code = substr($this->addNewInstance($definition, '', '', $id), 8, -2);
15571591
if ($definition->isShared()) {
1558-
$code = sprintf('($this->privates[\'%s\'] = %s)', $id, $code);
1592+
$code = sprintf('($container->%s[\'%s\'] = %s)', $definition->isPublic() ? 'services' : 'privates', $id, $code);
15591593
}
1594+
} else {
1595+
$code = sprintf('%s_%s::create($container)', $this->class, substr($this->generateMethodName($id), 3));
15601596
}
1597+
15611598
if ($definition->isShared()) {
1562-
$code = sprintf('($this->%s[\'%s\'] ?? %s)', $definition->isPublic() ? 'services' : 'privates', $id, $code);
1599+
$code = sprintf('($container->%s[\'%s\'] ?? %s)', $definition->isPublic() ? 'services' : 'privates', $id, $code);
15631600
}
15641601
} elseif (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) {
1565-
$code = sprintf('$this->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)', $id);
1602+
$code = sprintf('$container->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)', $id);
15661603
} else {
1567-
$code = sprintf('$this->get(\'%s\')', $id);
1604+
$code = sprintf('$container->get(\'%s\')', $id);
15681605
}
15691606

15701607
return $code;
@@ -1670,7 +1707,7 @@ private function getExpressionLanguage()
16701707
return $this->getServiceCall($id);
16711708
}
16721709

1673-
return sprintf('$this->get(%s)', $arg);
1710+
return sprintf('$container->get(%s)', $arg);
16741711
});
16751712

16761713
if ($this->container->isTrackingResources()) {
@@ -1703,7 +1740,7 @@ private function export($value)
17031740
$dirname = '__DIR__';
17041741

17051742
if (0 < $offset = 1 + $this->targetDirMaxMatches - count($matches)) {
1706-
$dirname = sprintf('$this->targetDirs[%d]', $offset);
1743+
$dirname = sprintf('$container->targetDirs[%d]', $offset);
17071744
}
17081745

17091746
if ($prefix || $suffix) {
@@ -1720,7 +1757,11 @@ private function doExport($value)
17201757
{
17211758
$export = var_export($value, true);
17221759

1723-
if ("'" === $export[0] && $export !== $resolvedExport = $this->container->resolveEnvPlaceholders($export, "'.\$this->getEnv('%s').'")) {
1760+
if (false !== strpos($export, "\n\nclass ")) {
1761+
$export = str_replace("\n\nclass ", "\n'.'\nclass ", $export);
1762+
}
1763+
1764+
if ("'" === $export[0] && $export !== $resolvedExport = $this->container->resolveEnvPlaceholders($export, "'.\$container->getEnv('%s').'")) {
17241765
$export = $resolvedExport;
17251766
if ("'" === $export[1]) {
17261767
$export = substr($export, 3);

src/Symfony/Component/DependencyInjection/ExpressionLanguageProvider.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ public function getFunctions()
3535
{
3636
return array(
3737
new ExpressionFunction('service', $this->serviceCompiler ?: function ($arg) {
38-
return sprintf('$this->get(%s)', $arg);
38+
return sprintf('$container->get(%s)', $arg);
3939
}, function (array $variables, $value) {
4040
return $variables['container']->get($value);
4141
}),
4242

4343
new ExpressionFunction('parameter', function ($arg) {
44-
return sprintf('$this->getParameter(%s)', $arg);
44+
return sprintf('$container->getParameter(%s)', $arg);
4545
}, function (array $variables, $value) {
4646
return $variables['container']->getParameter($value);
4747
}),

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
*/
2121
class Container extends AbstractContainer
2222
{
23-
private $parameters;
24-
private $targetDirs = array();
25-
private $privates = array();
23+
protected $parameters;
24+
protected $targetDirs = array();
25+
protected $privates = array();
2626

2727
/**
2828
* Constructor.

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
*/
1919
class ProjectServiceContainer extends Container
2020
{
21-
private $parameters;
22-
private $targetDirs = array();
23-
private $privates = array();
21+
protected $parameters;
22+
protected $targetDirs = array();
23+
protected $privates = array();
2424

2525
/**
2626
* Constructor.

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
*/
1919
class ProjectServiceContainer extends Container
2020
{
21-
private $parameters;
22-
private $targetDirs = array();
23-
private $privates = array();
21+
protected $parameters;
22+
protected $targetDirs = array();
23+
protected $privates = array();
2424

2525
/**
2626
* Constructor.
@@ -69,7 +69,9 @@ public function isCompiled()
6969
*/
7070
protected function getTestService()
7171
{
72-
return $this->services['test'] = new \stdClass(array('only dot' => '.', 'concatenation as value' => '.\'\'.', 'concatenation from the start value' => '\'\'.', '.' => 'dot as a key', '.\'\'.' => 'concatenation as a key', '\'\'.' => 'concatenation from the start key', 'optimize concatenation' => 'string1-string2', 'optimize concatenation with empty string' => 'string1string2', 'optimize concatenation from the start' => 'start', 'optimize concatenation at the end' => 'end'));
72+
$container = $this;
73+
74+
return $container->services['test'] = new \stdClass(array('only dot' => '.', 'concatenation as value' => '.\'\'.', 'concatenation from the start value' => '\'\'.', '.' => 'dot as a key', '.\'\'.' => 'concatenation as a key', '\'\'.' => 'concatenation from the start key', 'optimize concatenation' => 'string1-string2', 'optimize concatenation with empty string' => 'string1string2', 'optimize concatenation from the start' => 'start', 'optimize concatenation at the end' => 'end'));
7375
}
7476

7577
/**

0 commit comments

Comments
 (0)
0