Skip to content

Commit c115c71

Browse files
Merge branch '2.8' into 3.0
* 2.8: [travis] Disable hirak/prestissimo for deps=low/high tests Fixed the "hover" state of the profiler sidebar menu [HttpFoundation] fix phpdoc of UploadedFile Lower complexity of Form:isValid() skipped dns-sensitive tests when DnsMock is not found [FrameworkBundle] Return the invokable service if its name is the class name [ci] Skip dns-sensitive tests when DnsMock is not found Exclude Bridge\PhpUnit from composer.json by default fixed CS Optimize ReplaceAliasByActualDefinitionPass [Process] use __METHOD__ where applicable [Routing] Don't needlessly execute strtr's as they are fairly expensive Conflicts: .travis.yml src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php
2 parents 7b56d7b + 5fc28ce commit c115c71

File tree

1 file changed

+53
-71
lines changed

1 file changed

+53
-71
lines changed

Compiler/ReplaceAliasByActualDefinitionPass.php

Lines changed: 53 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
2525
{
2626
private $compiler;
2727
private $formatter;
28-
private $sourceId;
2928

3029
/**
3130
* Process the Container to replace aliases with service definitions.
@@ -36,107 +35,90 @@ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
3635
*/
3736
public function process(ContainerBuilder $container)
3837
{
38+
// Setup
3939
$this->compiler = $container->getCompiler();
4040
$this->formatter = $this->compiler->getLoggingFormatter();
41-
42-
foreach ($container->getAliases() as $id => $alias) {
43-
$aliasId = (string) $alias;
44-
45-
if ('service_container' === $aliasId) {
41+
// First collect all alias targets that need to be replaced
42+
$seenAliasTargets = array();
43+
$replacements = array();
44+
foreach ($container->getAliases() as $definitionId => $target) {
45+
$targetId = (string) $target;
46+
// Special case: leave this target alone
47+
if ('service_container' === $targetId) {
4648
continue;
4749
}
48-
50+
// Check if target needs to be replaces
51+
if (isset($replacements[$targetId])) {
52+
$container->setAlias($definitionId, $replacements[$targetId]);
53+
}
54+
// No neeed to process the same target twice
55+
if (isset($seenAliasTargets[$targetId])) {
56+
continue;
57+
}
58+
// Process new target
59+
$seenAliasTargets[$targetId] = true;
4960
try {
50-
$definition = $container->getDefinition($aliasId);
61+
$definition = $container->getDefinition($targetId);
5162
} catch (InvalidArgumentException $e) {
52-
throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with actual definition "%s".', $id, $alias), null, $e);
63+
throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with actual definition "%s".', $definitionId, $targetId), null, $e);
5364
}
54-
5565
if ($definition->isPublic()) {
5666
continue;
5767
}
58-
68+
// Remove private definition and schedule for replacement
5969
$definition->setPublic(true);
60-
$container->setDefinition($id, $definition);
61-
$container->removeDefinition($aliasId);
62-
63-
$this->updateReferences($container, $aliasId, $id);
64-
65-
// we have to restart the process due to concurrent modification of
66-
// the container
67-
$this->process($container);
68-
69-
break;
70-
}
71-
}
72-
73-
/**
74-
* Updates references to remove aliases.
75-
*
76-
* @param ContainerBuilder $container The container
77-
* @param string $currentId The alias identifier being replaced
78-
* @param string $newId The id of the service the alias points to
79-
*/
80-
private function updateReferences($container, $currentId, $newId)
81-
{
82-
foreach ($container->getAliases() as $id => $alias) {
83-
if ($currentId === (string) $alias) {
84-
$container->setAlias($id, $newId);
85-
}
70+
$container->setDefinition($definitionId, $definition);
71+
$container->removeDefinition($targetId);
72+
$replacements[$targetId] = $definitionId;
8673
}
8774

88-
foreach ($container->getDefinitions() as $id => $definition) {
89-
$this->sourceId = $id;
90-
91-
$definition->setArguments(
92-
$this->updateArgumentReferences($definition->getArguments(), $currentId, $newId)
93-
);
94-
95-
$definition->setMethodCalls(
96-
$this->updateArgumentReferences($definition->getMethodCalls(), $currentId, $newId)
97-
);
98-
99-
$definition->setProperties(
100-
$this->updateArgumentReferences($definition->getProperties(), $currentId, $newId)
101-
);
102-
103-
$definition->setFactory($this->updateFactoryReference($definition->getFactory(), $currentId, $newId));
75+
// Now replace target instances in all definitions
76+
foreach ($container->getDefinitions() as $definitionId => $definition) {
77+
$definition->setArguments($this->updateArgumentReferences($replacements, $definitionId, $definition->getArguments()));
78+
$definition->setMethodCalls($this->updateArgumentReferences($replacements, $definitionId, $definition->getMethodCalls()));
79+
$definition->setProperties($this->updateArgumentReferences($replacements, $definitionId, $definition->getProperties()));
80+
$definition->setFactory($this->updateFactoryReference($replacements, $definition->getFactory()));
10481
}
10582
}
10683

10784
/**
108-
* Updates argument references.
85+
* Recursively updates references in an array.
10986
*
110-
* @param array $arguments An array of Arguments
111-
* @param string $currentId The alias identifier
112-
* @param string $newId The identifier the alias points to
87+
* @param array $replacements Table of aliases to replace
88+
* @param string $definitionId Identifier of this definition
89+
* @param array $arguments Where to replace the aliases
11390
*
11491
* @return array
11592
*/
116-
private function updateArgumentReferences(array $arguments, $currentId, $newId)
93+
private function updateArgumentReferences(array $replacements, $definitionId, array $arguments)
11794
{
11895
foreach ($arguments as $k => $argument) {
96+
// Handle recursion step
11997
if (is_array($argument)) {
120-
$arguments[$k] = $this->updateArgumentReferences($argument, $currentId, $newId);
121-
} elseif ($argument instanceof Reference) {
122-
if ($currentId === (string) $argument) {
123-
$arguments[$k] = new Reference($newId, $argument->getInvalidBehavior());
124-
$this->compiler->addLogMessage($this->formatter->formatUpdateReference($this, $this->sourceId, $currentId, $newId));
125-
}
98+
$arguments[$k] = $this->updateArgumentReferences($replacements, $definitionId, $argument);
99+
continue;
100+
}
101+
// Skip arguments that don't need replacement
102+
if (!$argument instanceof Reference) {
103+
continue;
126104
}
105+
$referenceId = (string) $argument;
106+
if (!isset($replacements[$referenceId])) {
107+
continue;
108+
}
109+
// Perform the replacement
110+
$newId = $replacements[$referenceId];
111+
$arguments[$k] = new Reference($newId, $argument->getInvalidBehavior());
112+
$this->compiler->addLogMessage($this->formatter->formatUpdateReference($this, $definitionId, $referenceId, $newId));
127113
}
128114

129115
return $arguments;
130116
}
131117

132-
private function updateFactoryReference($factory, $currentId, $newId)
118+
private function updateFactoryReference(array $replacements, $factory)
133119
{
134-
if (null === $factory || !is_array($factory) || !$factory[0] instanceof Reference) {
135-
return $factory;
136-
}
137-
138-
if ($currentId === (string) $factory[0]) {
139-
$factory[0] = new Reference($newId, $factory[0]->getInvalidBehavior());
120+
if (is_array($factory) && $factory[0] instanceof Reference && isset($replacements[$referenceId = (string) $factory[0]])) {
121+
$factory[0] = new Reference($replacements[$referenceId], $factory[0]->getInvalidBehavior());
140122
}
141123

142124
return $factory;

0 commit comments

Comments
 (0)