|
|
|
@ -55,7 +55,9 @@ class PhpDumper extends Dumper
|
|
|
|
|
private $definitionVariables;
|
|
|
|
|
private $referenceVariables;
|
|
|
|
|
private $variableCount;
|
|
|
|
|
private $reservedVariables = array('instance', 'class');
|
|
|
|
|
private $inlinedDefinitions;
|
|
|
|
|
private $serviceCalls;
|
|
|
|
|
private $reservedVariables = array('instance', 'class', 'this');
|
|
|
|
|
private $expressionLanguage;
|
|
|
|
|
private $targetDirRegex;
|
|
|
|
|
private $targetDirMaxMatches;
|
|
|
|
@ -295,63 +297,6 @@ EOF;
|
|
|
|
|
return $this->proxyDumper;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Generates Service local temp variables.
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
private function addServiceLocalTempVariables($cId, Definition $definition, \SplObjectStorage $inlinedDefinitions, array $serviceCalls, $preInstance = false)
|
|
|
|
|
{
|
|
|
|
|
$calls = array();
|
|
|
|
|
|
|
|
|
|
foreach ($inlinedDefinitions as $def) {
|
|
|
|
|
if ($preInstance && !$inlinedDefinitions[$def][1]) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
$this->getServiceCallsFromArguments(array($def->getArguments(), $def->getFactory()), $calls, $preInstance, $cId);
|
|
|
|
|
if ($def !== $definition) {
|
|
|
|
|
$arguments = array($def->getProperties(), $def->getMethodCalls(), $def->getConfigurator());
|
|
|
|
|
$this->getServiceCallsFromArguments($arguments, $calls, $preInstance && !$this->hasReference($cId, $arguments, true), $cId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!isset($inlinedDefinitions[$definition])) {
|
|
|
|
|
$arguments = array($definition->getProperties(), $definition->getMethodCalls(), $definition->getConfigurator());
|
|
|
|
|
$this->getServiceCallsFromArguments($arguments, $calls, false, $cId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$code = '';
|
|
|
|
|
foreach ($calls as $id => list($callCount)) {
|
|
|
|
|
if ('service_container' === $id || $id === $cId || isset($this->referenceVariables[$id])) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if ($callCount <= 1 && $serviceCalls[$id][0] <= 1) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$name = $this->getNextVariableName();
|
|
|
|
|
$this->referenceVariables[$id] = new Variable($name);
|
|
|
|
|
|
|
|
|
|
$reference = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $serviceCalls[$id][1] ? new Reference($id, $serviceCalls[$id][1]) : null;
|
|
|
|
|
$code .= sprintf(" \$%s = %s;\n", $name, $this->getServiceCall($id, $reference));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ('' !== $code) {
|
|
|
|
|
if ($preInstance) {
|
|
|
|
|
$code .= <<<EOTXT
|
|
|
|
|
|
|
|
|
|
if (isset(\$this->services['$cId'])) {
|
|
|
|
|
return \$this->services['$cId'];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EOTXT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$code .= "\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $code;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function analyzeCircularReferences(array $edges, &$checkedNodes, &$currentPath)
|
|
|
|
|
{
|
|
|
|
|
foreach ($edges as $edge) {
|
|
|
|
@ -436,19 +381,19 @@ EOTXT;
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
private function addServiceInclude($cId, Definition $definition, \SplObjectStorage $inlinedDefinitions, array $serviceCalls)
|
|
|
|
|
private function addServiceInclude($cId, Definition $definition)
|
|
|
|
|
{
|
|
|
|
|
$code = '';
|
|
|
|
|
|
|
|
|
|
if ($this->inlineRequires && !$this->isHotPath($definition)) {
|
|
|
|
|
$lineage = array();
|
|
|
|
|
foreach ($inlinedDefinitions as $def) {
|
|
|
|
|
foreach ($this->inlinedDefinitions as $def) {
|
|
|
|
|
if (!$def->isDeprecated() && \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) {
|
|
|
|
|
$this->collectLineage($class, $lineage);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ($serviceCalls as $id => list($callCount, $behavior)) {
|
|
|
|
|
foreach ($this->serviceCalls as $id => list($callCount, $behavior)) {
|
|
|
|
|
if ('service_container' !== $id && $id !== $cId
|
|
|
|
|
&& ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE !== $behavior
|
|
|
|
|
&& $this->container->has($id)
|
|
|
|
@ -464,7 +409,7 @@ EOTXT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ($inlinedDefinitions as $def) {
|
|
|
|
|
foreach ($this->inlinedDefinitions as $def) {
|
|
|
|
|
if ($file = $def->getFile()) {
|
|
|
|
|
$code .= sprintf(" include_once %s;\n", $this->dumpValue($file));
|
|
|
|
|
}
|
|
|
|
@ -477,59 +422,6 @@ EOTXT;
|
|
|
|
|
return $code;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Generates the inline definition of a service.
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*
|
|
|
|
|
* @throws RuntimeException When the factory definition is incomplete
|
|
|
|
|
* @throws ServiceCircularReferenceException When a circular reference is detected
|
|
|
|
|
*/
|
|
|
|
|
private function addServiceInlinedDefinitions($id, Definition $definition, \SplObjectStorage $inlinedDefinitions, &$isSimpleInstance, $preInstance = false)
|
|
|
|
|
{
|
|
|
|
|
$code = '';
|
|
|
|
|
|
|
|
|
|
foreach ($inlinedDefinitions as $def) {
|
|
|
|
|
if ($definition === $def || isset($this->definitionVariables[$def])) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if ($inlinedDefinitions[$def][0] <= 1 && !$def->getMethodCalls() && !$def->getProperties() && !$def->getConfigurator() && false === strpos($this->dumpValue($def->getClass()), '$')) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if ($preInstance && !$inlinedDefinitions[$def][1]) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$name = $this->getNextVariableName();
|
|
|
|
|
$this->definitionVariables[$def] = new Variable($name);
|
|
|
|
|
|
|
|
|
|
// a construct like:
|
|
|
|
|
// $a = new ServiceA(ServiceB $b); $b = new ServiceB(ServiceA $a);
|
|
|
|
|
// this is an indication for a wrong implementation, you can circumvent this problem
|
|
|
|
|
// by setting up your service structure like this:
|
|
|
|
|
// $b = new ServiceB();
|
|
|
|
|
// $a = new ServiceA(ServiceB $b);
|
|
|
|
|
// $b->setServiceA(ServiceA $a);
|
|
|
|
|
if (isset($inlinedDefinitions[$definition]) && $this->hasReference($id, array($def->getArguments(), $def->getFactory()))) {
|
|
|
|
|
throw new ServiceCircularReferenceException($id, array($id, '...', $id));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$code .= $this->addNewInstance($def, '$'.$name, ' = ', $id);
|
|
|
|
|
|
|
|
|
|
if (!$this->hasReference($id, array($def->getProperties(), $def->getMethodCalls(), $def->getConfigurator()), true, $inlinedDefinitions)) {
|
|
|
|
|
$code .= $this->addServiceProperties($def, $name);
|
|
|
|
|
$code .= $this->addServiceMethodCalls($def, $name);
|
|
|
|
|
$code .= $this->addServiceConfigurator($def, $name);
|
|
|
|
|
} else {
|
|
|
|
|
$isSimpleInstance = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$code .= "\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $code;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Generates the service instance.
|
|
|
|
|
*
|
|
|
|
@ -566,14 +458,7 @@ EOTXT;
|
|
|
|
|
$instantiation .= ' = ';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$code = $this->addNewInstance($definition, $return, $instantiation, $id);
|
|
|
|
|
$this->referenceVariables[$id] = new Variable('instance');
|
|
|
|
|
|
|
|
|
|
if (!$isSimpleInstance) {
|
|
|
|
|
$code .= "\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $code;
|
|
|
|
|
return $this->addNewInstance($definition, $return, $instantiation, $id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -658,40 +543,6 @@ EOTXT;
|
|
|
|
|
return $code;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Generates the inline definition setup.
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*
|
|
|
|
|
* @throws ServiceCircularReferenceException when the container contains a circular reference
|
|
|
|
|
*/
|
|
|
|
|
private function addServiceInlinedDefinitionsSetup($id, Definition $definition, \SplObjectStorage $inlinedDefinitions, $isSimpleInstance)
|
|
|
|
|
{
|
|
|
|
|
$code = '';
|
|
|
|
|
foreach ($inlinedDefinitions as $def) {
|
|
|
|
|
if ($definition === $def || !$this->hasReference($id, array($def->getProperties(), $def->getMethodCalls(), $def->getConfigurator()), true, $inlinedDefinitions)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if the instance is simple, the return statement has already been generated
|
|
|
|
|
// so, the only possible way to get there is because of a circular reference
|
|
|
|
|
if ($isSimpleInstance) {
|
|
|
|
|
throw new ServiceCircularReferenceException($id, array($id, '...', $id));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$name = (string) $this->definitionVariables[$def];
|
|
|
|
|
$code .= $this->addServiceProperties($def, $name);
|
|
|
|
|
$code .= $this->addServiceMethodCalls($def, $name);
|
|
|
|
|
$code .= $this->addServiceConfigurator($def, $name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ('' !== $code && ($definition->getProperties() || $definition->getMethodCalls() || $definition->getConfigurator())) {
|
|
|
|
|
$code .= "\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $code;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds configurator definition.
|
|
|
|
|
*
|
|
|
|
@ -742,6 +593,7 @@ EOTXT;
|
|
|
|
|
$this->definitionVariables = new \SplObjectStorage();
|
|
|
|
|
$this->referenceVariables = array();
|
|
|
|
|
$this->variableCount = 0;
|
|
|
|
|
$this->definitionVariables[$definition] = $this->referenceVariables[$id] = new Variable('instance');
|
|
|
|
|
|
|
|
|
|
$return = array();
|
|
|
|
|
|
|
|
|
@ -801,6 +653,11 @@ EOTXT;
|
|
|
|
|
EOF;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->serviceCalls = array();
|
|
|
|
|
$this->inlinedDefinitions = $this->getDefinitionsFromArguments(array($definition), null, $this->serviceCalls);
|
|
|
|
|
|
|
|
|
|
$code .= $this->addServiceInclude($id, $definition);
|
|
|
|
|
|
|
|
|
|
if ($this->getProxyDumper()->isProxyCandidate($definition)) {
|
|
|
|
|
$factoryCode = $asFile ? "\$this->load('%s.php', false)" : '$this->%s(false)';
|
|
|
|
|
$code .= $this->getProxyDumper()->getProxyFactoryCode($definition, $id, sprintf($factoryCode, $methodName));
|
|
|
|
@ -810,40 +667,22 @@ EOF;
|
|
|
|
|
$code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$inlinedDefinitions = $this->getDefinitionsFromArguments(array($definition));
|
|
|
|
|
$constructorDefinitions = $this->getDefinitionsFromArguments(array($definition->getArguments(), $definition->getFactory()));
|
|
|
|
|
unset($constructorDefinitions[$definition]); // ensures $definition will be last
|
|
|
|
|
$otherDefinitions = new \SplObjectStorage();
|
|
|
|
|
$serviceCalls = array();
|
|
|
|
|
$head = $tail = '';
|
|
|
|
|
$arguments = array($definition->getArguments(), $definition->getFactory());
|
|
|
|
|
$this->addInlineVariables($head, $tail, $id, $arguments, true);
|
|
|
|
|
$code .= '' !== $head ? $head."\n" : '';
|
|
|
|
|
|
|
|
|
|
foreach ($inlinedDefinitions as $def) {
|
|
|
|
|
if ($def === $definition || isset($constructorDefinitions[$def])) {
|
|
|
|
|
$constructorDefinitions[$def] = $inlinedDefinitions[$def];
|
|
|
|
|
} else {
|
|
|
|
|
$otherDefinitions[$def] = $inlinedDefinitions[$def];
|
|
|
|
|
}
|
|
|
|
|
$arguments = array($def->getArguments(), $def->getFactory(), $def->getProperties(), $def->getMethodCalls(), $def->getConfigurator());
|
|
|
|
|
$this->getServiceCallsFromArguments($arguments, $serviceCalls, false, $id);
|
|
|
|
|
if ($arguments = array_filter(array($definition->getProperties(), $definition->getMethodCalls(), $definition->getConfigurator()))) {
|
|
|
|
|
$this->addInlineVariables($tail, $tail, $id, $arguments, false);
|
|
|
|
|
|
|
|
|
|
$tail .= '' !== $tail ? "\n" : '';
|
|
|
|
|
$tail .= $this->addServiceProperties($definition);
|
|
|
|
|
$tail .= $this->addServiceMethodCalls($definition);
|
|
|
|
|
$tail .= $this->addServiceConfigurator($definition);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$isSimpleInstance = !$definition->getProperties() && !$definition->getMethodCalls() && !$definition->getConfigurator();
|
|
|
|
|
$preInstance = isset($this->circularReferences[$id]) && !$this->getProxyDumper()->isProxyCandidate($definition) && $definition->isShared();
|
|
|
|
|
|
|
|
|
|
$code .=
|
|
|
|
|
$this->addServiceInclude($id, $definition, $inlinedDefinitions, $serviceCalls).
|
|
|
|
|
$this->addServiceLocalTempVariables($id, $definition, $constructorDefinitions, $serviceCalls, $preInstance).
|
|
|
|
|
$this->addServiceInlinedDefinitions($id, $definition, $constructorDefinitions, $isSimpleInstance, $preInstance).
|
|
|
|
|
$this->addServiceInstance($id, $definition, $isSimpleInstance).
|
|
|
|
|
$this->addServiceLocalTempVariables($id, $definition, $constructorDefinitions->offsetUnset($definition) ?: $constructorDefinitions, $serviceCalls).
|
|
|
|
|
$this->addServiceLocalTempVariables($id, $definition, $otherDefinitions, $serviceCalls).
|
|
|
|
|
$this->addServiceInlinedDefinitions($id, $definition, $constructorDefinitions, $isSimpleInstance).
|
|
|
|
|
$this->addServiceInlinedDefinitions($id, $definition, $otherDefinitions, $isSimpleInstance).
|
|
|
|
|
$this->addServiceInlinedDefinitionsSetup($id, $definition, $inlinedDefinitions, $isSimpleInstance).
|
|
|
|
|
$this->addServiceProperties($definition).
|
|
|
|
|
$this->addServiceMethodCalls($definition).
|
|
|
|
|
$this->addServiceConfigurator($definition).
|
|
|
|
|
(!$isSimpleInstance ? "\n return \$instance;\n" : '')
|
|
|
|
|
;
|
|
|
|
|
$code .= $this->addServiceInstance($id, $definition, '' === $tail)
|
|
|
|
|
.('' !== $tail ? "\n".$tail."\n return \$instance;\n" : '');
|
|
|
|
|
|
|
|
|
|
if ($asFile) {
|
|
|
|
|
$code = implode("\n", array_map(function ($line) { return $line ? substr($line, 8) : $line; }, explode("\n", $code)));
|
|
|
|
@ -851,12 +690,108 @@ EOF;
|
|
|
|
|
$code .= " }\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->definitionVariables = null;
|
|
|
|
|
$this->referenceVariables = null;
|
|
|
|
|
$this->definitionVariables = $this->inlinedDefinitions = null;
|
|
|
|
|
$this->referenceVariables = $this->serviceCalls = null;
|
|
|
|
|
|
|
|
|
|
return $code;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function addInlineVariables(&$head, &$tail, $id, array $arguments, $forConstructor)
|
|
|
|
|
{
|
|
|
|
|
$hasSelfRef = false;
|
|
|
|
|
|
|
|
|
|
foreach ($arguments as $argument) {
|
|
|
|
|
if (\is_array($argument)) {
|
|
|
|
|
$hasSelfRef = $this->addInlineVariables($head, $tail, $id, $argument, $forConstructor) || $hasSelfRef;
|
|
|
|
|
} elseif ($argument instanceof Reference) {
|
|
|
|
|
$hasSelfRef = $this->addInlineReference($head, $tail, $id, $this->container->normalizeId($argument), $forConstructor) || $hasSelfRef;
|
|
|
|
|
} elseif ($argument instanceof Definition) {
|
|
|
|
|
$hasSelfRef = $this->addInlineService($head, $tail, $id, $argument, $forConstructor) || $hasSelfRef;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $hasSelfRef;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function addInlineReference(&$head, &$tail, $id, $targetId, $forConstructor)
|
|
|
|
|
{
|
|
|
|
|
if ('service_container' === $targetId || isset($this->referenceVariables[$targetId])) {
|
|
|
|
|
return isset($this->circularReferences[$id][$targetId]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
list($callCount, $behavior) = $this->serviceCalls[$targetId];
|
|
|
|
|
|
|
|
|
|
if (2 > $callCount && (!$forConstructor || !isset($this->circularReferences[$id][$targetId]))) {
|
|
|
|
|
return isset($this->circularReferences[$id][$targetId]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$name = $this->getNextVariableName();
|
|
|
|
|
$this->referenceVariables[$targetId] = new Variable($name);
|
|
|
|
|
|
|
|
|
|
$reference = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $behavior ? new Reference($targetId, $behavior) : null;
|
|
|
|
|
$code = sprintf(" \$%s = %s;\n", $name, $this->getServiceCall($targetId, $reference));
|
|
|
|
|
|
|
|
|
|
if (!isset($this->circularReferences[$id][$targetId])) {
|
|
|
|
|
$head .= $code;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!$forConstructor) {
|
|
|
|
|
$tail .= $code;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$head .= $code.sprintf(<<<'EOTXT'
|
|
|
|
|
|
|
|
|
|
if (isset($this->%s['%s'])) {
|
|
|
|
|
return $this->%1$s['%2$s'];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EOTXT
|
|
|
|
|
,
|
|
|
|
|
$this->container->getDefinition($id)->isPublic() ? 'services' : 'privates',
|
|
|
|
|
$id
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function addInlineService(&$head, &$tail, $id, Definition $definition, $forConstructor)
|
|
|
|
|
{
|
|
|
|
|
if (isset($this->definitionVariables[$definition])) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$arguments = array($definition->getArguments(), $definition->getFactory());
|
|
|
|
|
|
|
|
|
|
if (2 > $this->inlinedDefinitions[$definition] && !$definition->getMethodCalls() && !$definition->getProperties() && !$definition->getConfigurator() && false === strpos($this->dumpValue($definition->getClass()), '$')) {
|
|
|
|
|
return $this->addInlineVariables($head, $tail, $id, $arguments, $forConstructor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$name = $this->getNextVariableName();
|
|
|
|
|
$this->definitionVariables[$definition] = new Variable($name);
|
|
|
|
|
|
|
|
|
|
$code = '';
|
|
|
|
|
$hasSelfRef = $this->addInlineVariables($code, $tail, $id, $arguments, $forConstructor);
|
|
|
|
|
$code .= $this->addNewInstance($definition, '$'.$name, ' = ', $id);
|
|
|
|
|
$hasSelfRef ? $tail .= ('' !== $tail ? "\n" : '').$code : $head .= ('' !== $head ? "\n" : '').$code;
|
|
|
|
|
|
|
|
|
|
$code = '';
|
|
|
|
|
$arguments = array($definition->getProperties(), $definition->getMethodCalls(), $definition->getConfigurator());
|
|
|
|
|
$hasSelfRef = $this->addInlineVariables($code, $tail, $id, $arguments, false) || $hasSelfRef;
|
|
|
|
|
|
|
|
|
|
$code .= $this->addServiceProperties($definition, $name);
|
|
|
|
|
$code .= $this->addServiceMethodCalls($definition, $name);
|
|
|
|
|
$code .= $this->addServiceConfigurator($definition, $name);
|
|
|
|
|
if ('' !== $code) {
|
|
|
|
|
$hasSelfRef ? $tail .= ('' !== $tail ? "\n" : '').$code : $head .= $code;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $hasSelfRef;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds multiple services.
|
|
|
|
|
*
|
|
|
|
@ -1574,31 +1509,7 @@ EOF;
|
|
|
|
|
return implode(' && ', $conditions);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Builds service calls from arguments.
|
|
|
|
|
*
|
|
|
|
|
* Populates $calls with "referenced id" => ["reference count", "invalid behavior"] pairs.
|
|
|
|
|
*/
|
|
|
|
|
private function getServiceCallsFromArguments(array $arguments, array &$calls, $preInstance, $callerId)
|
|
|
|
|
{
|
|
|
|
|
foreach ($arguments as $argument) {
|
|
|
|
|
if (\is_array($argument)) {
|
|
|
|
|
$this->getServiceCallsFromArguments($argument, $calls, $preInstance, $callerId);
|
|
|
|
|
} elseif ($argument instanceof Reference) {
|
|
|
|
|
$id = $this->container->normalizeId($argument);
|
|
|
|
|
|
|
|
|
|
if (!isset($calls[$id])) {
|
|
|
|
|
$calls[$id] = array((int) ($preInstance && isset($this->circularReferences[$callerId][$id])), $argument->getInvalidBehavior());
|
|
|
|
|
} else {
|
|
|
|
|
$calls[$id][1] = min($calls[$id][1], $argument->getInvalidBehavior());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
++$calls[$id][0];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function getDefinitionsFromArguments(array $arguments, $isConstructorArgument = true, \SplObjectStorage $definitions = null)
|
|
|
|
|
private function getDefinitionsFromArguments(array $arguments, \SplObjectStorage $definitions = null, array &$calls = array())
|
|
|
|
|
{
|
|
|
|
|
if (null === $definitions) {
|
|
|
|
|
$definitions = new \SplObjectStorage();
|
|
|
|
@ -1606,88 +1517,31 @@ EOF;
|
|
|
|
|
|
|
|
|
|
foreach ($arguments as $argument) {
|
|
|
|
|
if (\is_array($argument)) {
|
|
|
|
|
$this->getDefinitionsFromArguments($argument, $isConstructorArgument, $definitions);
|
|
|
|
|
$this->getDefinitionsFromArguments($argument, $definitions, $calls);
|
|
|
|
|
} elseif ($argument instanceof Reference) {
|
|
|
|
|
$id = $this->container->normalizeId($argument);
|
|
|
|
|
|
|
|
|
|
if (!isset($calls[$id])) {
|
|
|
|
|
$calls[$id] = array(0, $argument->getInvalidBehavior());
|
|
|
|
|
} else {
|
|
|
|
|
$calls[$id][1] = min($calls[$id][1], $argument->getInvalidBehavior());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
++$calls[$id][0];
|
|
|
|
|
} elseif (!$argument instanceof Definition) {
|
|
|
|
|
// no-op
|
|
|
|
|
} elseif (isset($definitions[$argument])) {
|
|
|
|
|
$def = $definitions[$argument];
|
|
|
|
|
$definitions[$argument] = array(1 + $def[0], $isConstructorArgument || $def[1]);
|
|
|
|
|
$definitions[$argument] = 1 + $definitions[$argument];
|
|
|
|
|
} else {
|
|
|
|
|
$definitions[$argument] = array(1, $isConstructorArgument);
|
|
|
|
|
$this->getDefinitionsFromArguments($argument->getArguments(), $isConstructorArgument, $definitions);
|
|
|
|
|
$this->getDefinitionsFromArguments(array($argument->getFactory()), $isConstructorArgument, $definitions);
|
|
|
|
|
$this->getDefinitionsFromArguments($argument->getProperties(), false, $definitions);
|
|
|
|
|
$this->getDefinitionsFromArguments($argument->getMethodCalls(), false, $definitions);
|
|
|
|
|
$this->getDefinitionsFromArguments(array($argument->getConfigurator()), false, $definitions);
|
|
|
|
|
// move current definition last in the list
|
|
|
|
|
$def = $definitions[$argument];
|
|
|
|
|
unset($definitions[$argument]);
|
|
|
|
|
$definitions[$argument] = $def;
|
|
|
|
|
$definitions[$argument] = 1;
|
|
|
|
|
$arguments = array($argument->getArguments(), $argument->getFactory(), $argument->getProperties(), $argument->getMethodCalls(), $argument->getConfigurator());
|
|
|
|
|
$this->getDefinitionsFromArguments($arguments, $definitions, $calls);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $definitions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Checks if a service id has a reference.
|
|
|
|
|
*
|
|
|
|
|
* @param string $id
|
|
|
|
|
* @param array $arguments
|
|
|
|
|
* @param bool $deep
|
|
|
|
|
* @param array $visited
|
|
|
|
|
*
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
private function hasReference($id, array $arguments, $deep = false, \SplObjectStorage $inlinedDefinitions = null, array &$visited = array())
|
|
|
|
|
{
|
|
|
|
|
if (!isset($this->circularReferences[$id])) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ($arguments as $argument) {
|
|
|
|
|
if (\is_array($argument)) {
|
|
|
|
|
if ($this->hasReference($id, $argument, $deep, $inlinedDefinitions, $visited)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
} elseif ($argument instanceof Reference) {
|
|
|
|
|
$argumentId = $this->container->normalizeId($argument);
|
|
|
|
|
if ($id === $argumentId) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!$deep || isset($visited[$argumentId]) || !isset($this->circularReferences[$argumentId])) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$visited[$argumentId] = true;
|
|
|
|
|
|
|
|
|
|
$service = $this->container->getDefinition($argumentId);
|
|
|
|
|
} elseif ($argument instanceof Definition) {
|
|
|
|
|
if (isset($inlinedDefinitions[$argument])) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
$service = $argument;
|
|
|
|
|
} else {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if the proxy manager is enabled, disable searching for references in lazy services,
|
|
|
|
|
// as these services will be instantiated lazily and don't have direct related references.
|
|
|
|
|
if ($service->isLazy() && !$this->getProxyDumper() instanceof NullDumper) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($this->hasReference($id, array($service->getArguments(), $service->getFactory(), $service->getProperties(), $service->getMethodCalls(), $service->getConfigurator()), $deep, $inlinedDefinitions, $visited)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Dumps values.
|
|
|
|
|
*
|
|
|
|
@ -1711,7 +1565,7 @@ EOF;
|
|
|
|
|
|
|
|
|
|
return sprintf('array(%s)', implode(', ', $code));
|
|
|
|
|
} elseif ($value instanceof ArgumentInterface) {
|
|
|
|
|
$scope = array($this->definitionVariables, $this->referenceVariables, $this->variableCount);
|
|
|
|
|
$scope = array($this->definitionVariables, $this->referenceVariables);
|
|
|
|
|
$this->definitionVariables = $this->referenceVariables = null;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
@ -1758,7 +1612,7 @@ EOF;
|
|
|
|
|
return implode("\n", $code);
|
|
|
|
|
}
|
|
|
|
|
} finally {
|
|
|
|
|
list($this->definitionVariables, $this->referenceVariables, $this->variableCount) = $scope;
|
|
|
|
|
list($this->definitionVariables, $this->referenceVariables) = $scope;
|
|
|
|
|
}
|
|
|
|
|
} elseif ($value instanceof Definition) {
|
|
|
|
|
if (null !== $this->definitionVariables && $this->definitionVariables->contains($value)) {
|
|
|
|
|