/** * @covers Symfony\Component\DependencyInjection\Definition::__construct */ public function testConstructor() { $def = new Definition('stdClass'); $this->assertEquals('stdClass', $def->getClass(), '__construct() takes the class name as its first argument'); $def = new Definition('stdClass', array('foo')); $this->assertEquals(array('foo'), $def->getArguments(), '__construct() takes an optional array of arguments as its second argument'); }
/** * @param string $class * @param Definition $definition * @param string[] $classes * @param string $id * @param ContainerBuilder $container */ private function autowireConstructor($class, Definition $definition, array $classes, $id, ContainerBuilder $container) { $reflection = new ReflectionClass($class); $constructor = $reflection->getConstructor(); // service not created by factory with public constructor with not fully configured arguments if ($constructor !== NULL && $constructor->isPublic() && $definition->getFactoryMethod() === NULL) { $autowiredArgs = $this->autowireMethod($constructor, $definition->getArguments(), $classes, $id, $container); if ($definition instanceof DefinitionDecorator && $definition->getParent() !== NULL) { $parentDef = $container->getDefinition($definition->getParent()); $parentDefArgsCount = count($parentDef->getArguments()); $argsToReplace = array(); foreach ($autowiredArgs as $i => $arg) { if ($i < $parentDefArgsCount) { $argsToReplace[$i] = $arg; unset($autowiredArgs[$i]); } } $definition->setArguments($autowiredArgs); foreach ($argsToReplace as $i => $arg) { $definition->replaceArgument($i, $arg); } } else { $definition->setArguments($autowiredArgs); } } }
/** * @param Definition $definition * @param stdClass $dependables */ private function addDefinitionArguments(Definition $definition, stdClass $dependables) { $class = $definition->getClass(); $dependables->references[$class] = array(); for ($arg = 0; $arg < count($definition->getArguments()); $arg++) { $dependables->references[$class][$arg] = $definition->getArgument($arg); } }
function it_sets_services_to_array_of_controller_services_definitions(ContainerBuilder $container, Definition $definition1, Definition $definition2) { $container->findTaggedServiceIds(InjectableCompilerPass::TAG_NAME)->willReturn(['my.first.controller' => [InjectableCompilerPass::TAG_NAME], 'my.second.controller' => [InjectableCompilerPass::TAG_NAME]]); $controllersObject = (object) array('references' => array('My_First_Controller' => [0 => 'arg1', 1 => 'arg2'], 'My_Second_Controller' => [0 => 'arg1'])); $definition1->getClass()->willReturn('My_First_Controller'); $definition1->getArguments()->willReturn(['arg1', 'arg2']); $definition1->getArgument(0)->willReturn('arg1'); $definition1->getArgument(1)->willReturn('arg2'); $container->findDefinition('my.first.controller')->willReturn($definition1); $definition2->getClass()->willReturn('My_Second_Controller'); $definition2->getArguments()->willReturn(['arg1']); $definition2->getArgument(0)->willReturn('arg1'); $container->findDefinition('my.second.controller')->willReturn($definition2); $this->process($container); $container->set(InjectableCompilerPass::INJECTABLES_SERVICE_ID, $controllersObject)->shouldHaveBeenCalled(); }
public function testProcess() { $container = new ContainerBuilder(); $container->setDefinition('security.access.after_invocation_manager', $manager = new Definition()); $provider1 = new Definition(); $provider1->addTag('security.after_invocation.provider'); $container->setDefinition('provider1', $provider1); $provider2 = new Definition(); $provider2->addTag('security.after_invocation.provider'); $container->setDefinition('provider2', $provider2); $this->process($container); $arguments = $manager->getArguments(); $this->assertEquals(2, count($providers = $arguments[0])); $this->assertEquals('provider1', (string) $providers[0]); $this->assertEquals('provider2', (string) $providers[1]); }
public function autowireParams(ReflectionMethod $constructor, $serviceId, Definition $definition, array $classes) { $explicitlyDefinedArguments = $definition->getArguments(); $allArguments = array(); foreach ($constructor->getParameters() as $index => $parameter) { if (array_key_exists($index, $explicitlyDefinedArguments)) { $allArguments[] = $explicitlyDefinedArguments[$index]; } else { if ($parameter->isDefaultValueAvailable()) { $allArguments[] = $parameter->getDefaultValue(); } else { $allArguments[] = $this->parameterProcessor->getParameterValue($parameter, $classes, $serviceId); } } } $definition->setArguments($allArguments); }
private function replaceArguments(ContainerBuilder $container, Definition $definition, $id) { $arguments = $definition->getArguments(); foreach ($arguments as $index => $argument) { if (!$argument instanceof Reference) { continue; } $argumentDefinition = $container->getDefinition((string) $argument); $lazyArgument = new Definition($argumentDefinition->getClass()); $lazyKey = '__lazy__' . (string) $argument; $container->setDefinition($lazyKey, $lazyArgument); $lazyArgument->setFactory(array(new Reference('console.command.argument_proxy_factory'), 'getService')); $lazyArgument->setArguments(array($argumentDefinition->getClass(), (string) $argument)); $arguments[$index] = new Reference($lazyKey); } $definition->setArguments($arguments); }
/** * Creates a service for a service definition. * * @param Definition $definition A service definition instance * @param string $id The service identifier * * @return object The service described by the service definition * * @throws \InvalidArgumentException When configure callable is not callable */ protected function createService(Definition $definition, $id) { if (null !== $definition->getFile()) { require_once $this->getParameterBag()->resolveValue($definition->getFile()); } $arguments = $this->resolveServices($this->getParameterBag()->resolveValue($definition->getArguments())); if (null !== $definition->getFactoryMethod()) { if (null !== $definition->getFactoryService()) { $factory = $this->get($this->getParameterBag()->resolveValue($definition->getFactoryService())); } else { $factory = $this->getParameterBag()->resolveValue($definition->getClass()); } $service = call_user_func_array(array($factory, $definition->getFactoryMethod()), $arguments); } else { $r = new \ReflectionClass($this->getParameterBag()->resolveValue($definition->getClass())); $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments); } if ($definition->isShared()) { $this->services[$id] = $service; } foreach ($definition->getMethodCalls() as $call) { $services = self::getServiceConditionals($call[1]); $ok = true; foreach ($services as $s) { if (!$this->has($s)) { $ok = false; break; } } if ($ok) { call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->resolveValue($call[1]))); } } if ($callable = $definition->getConfigurator()) { if (is_array($callable) && is_object($callable[0]) && $callable[0] instanceof Reference) { $callable[0] = $this->get((string) $callable[0]); } elseif (is_array($callable)) { $callable[0] = $this->getParameterBag()->resolveValue($callable[0]); } if (!is_callable($callable)) { throw new \InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', get_class($service))); } call_user_func($callable, $service); } return $service; }
private function processDefinition(Definition $definition) { $this->processReferences($definition->getArguments()); $this->processReferences($definition->getMethodCalls()); $this->processReferences($definition->getProperties()); }
/** * Adds a service. * * @param Definition $definition * @param string $id * @param \DOMElement $parent */ private function addService($definition, $id, \DOMElement $parent) { $service = $this->document->createElement('service'); if (null !== $id) { $service->setAttribute('id', $id); } if ($class = $definition->getClass()) { if ('\\' === substr($class, 0, 1)) { $class = substr($class, 1); } $service->setAttribute('class', $class); } if (!$definition->isShared()) { $service->setAttribute('shared', 'false'); } if (!$definition->isPublic()) { $service->setAttribute('public', 'false'); } if ($definition->isSynthetic()) { $service->setAttribute('synthetic', 'true'); } if ($definition->isLazy()) { $service->setAttribute('lazy', 'true'); } if (null !== ($decorated = $definition->getDecoratedService())) { list($decorated, $renamedId, $priority) = $decorated; $service->setAttribute('decorates', $decorated); if (null !== $renamedId) { $service->setAttribute('decoration-inner-name', $renamedId); } if (0 !== $priority) { $service->setAttribute('decoration-priority', $priority); } } foreach ($definition->getTags() as $name => $tags) { foreach ($tags as $attributes) { $tag = $this->document->createElement('tag'); $tag->setAttribute('name', $name); foreach ($attributes as $key => $value) { $tag->setAttribute($key, $value); } $service->appendChild($tag); } } if ($definition->getFile()) { $file = $this->document->createElement('file'); $file->appendChild($this->document->createTextNode($definition->getFile())); $service->appendChild($file); } if ($parameters = $definition->getArguments()) { $this->convertParameters($parameters, 'argument', $service); } if ($parameters = $definition->getProperties()) { $this->convertParameters($parameters, 'property', $service, 'name'); } $this->addMethodCalls($definition->getMethodCalls(), $service); if ($callable = $definition->getFactory()) { $factory = $this->document->createElement('factory'); if (is_array($callable) && $callable[0] instanceof Definition) { $this->addService($callable[0], null, $factory); $factory->setAttribute('method', $callable[1]); } elseif (is_array($callable)) { $factory->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]); $factory->setAttribute('method', $callable[1]); } else { $factory->setAttribute('function', $callable); } $service->appendChild($factory); } if ($definition->isDeprecated()) { $deprecated = $this->document->createElement('deprecated'); $deprecated->appendChild($this->document->createTextNode($definition->getDeprecationMessage('%service_id%'))); $service->appendChild($deprecated); } if ($definition->isAutowired()) { $service->setAttribute('autowire', 'true'); } foreach ($definition->getAutowiringTypes() as $autowiringTypeValue) { $autowiringType = $this->document->createElement('autowiring-type'); $autowiringType->appendChild($this->document->createTextNode($autowiringTypeValue)); $service->appendChild($autowiringType); } if ($callable = $definition->getConfigurator()) { $configurator = $this->document->createElement('configurator'); if (is_array($callable) && $callable[0] instanceof Definition) { $this->addService($callable[0], null, $configurator); $configurator->setAttribute('method', $callable[1]); } elseif (is_array($callable)) { $configurator->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]); $configurator->setAttribute('method', $callable[1]); } else { $configurator->setAttribute('function', $callable); } $service->appendChild($configurator); } $parent->appendChild($service); }
/** * Adds a service. * * @param string $id * @param Definition $definition * * @return string */ private function addService($id, $definition) { $code = " {$id}:\n"; if ($class = $definition->getClass()) { if ('\\' === substr($class, 0, 1)) { $class = substr($class, 1); } $code .= sprintf(" class: %s\n", $this->dumper->dump($class)); } if (!$definition->isPublic()) { $code .= " public: false\n"; } $tagsCode = ''; foreach ($definition->getTags() as $name => $tags) { foreach ($tags as $attributes) { $att = array(); foreach ($attributes as $key => $value) { $att[] = sprintf('%s: %s', $this->dumper->dump($key), $this->dumper->dump($value)); } $att = $att ? ', ' . implode(', ', $att) : ''; $tagsCode .= sprintf(" - { name: %s%s }\n", $this->dumper->dump($name), $att); } } if ($tagsCode) { $code .= " tags:\n" . $tagsCode; } if ($definition->getFile()) { $code .= sprintf(" file: %s\n", $this->dumper->dump($definition->getFile())); } if ($definition->isSynthetic()) { $code .= sprintf(" synthetic: true\n"); } if ($definition->isSynchronized(false)) { $code .= sprintf(" synchronized: true\n"); } if ($definition->isDeprecated()) { $code .= sprintf(" deprecated: %s\n", $definition->getDeprecationMessage('%service_id%')); } if ($definition->isAutowired()) { $code .= " autowire: true\n"; } $autowiringTypesCode = ''; foreach ($definition->getAutowiringTypes() as $autowiringType) { $autowiringTypesCode .= sprintf(" - %s\n", $this->dumper->dump($autowiringType)); } if ($autowiringTypesCode) { $code .= sprintf(" autowiring_types:\n%s", $autowiringTypesCode); } if ($definition->getFactoryClass(false)) { $code .= sprintf(" factory_class: %s\n", $this->dumper->dump($definition->getFactoryClass(false))); } if ($definition->isLazy()) { $code .= sprintf(" lazy: true\n"); } if ($definition->getFactoryMethod(false)) { $code .= sprintf(" factory_method: %s\n", $this->dumper->dump($definition->getFactoryMethod(false))); } if ($definition->getFactoryService(false)) { $code .= sprintf(" factory_service: %s\n", $this->dumper->dump($definition->getFactoryService(false))); } if ($definition->getArguments()) { $code .= sprintf(" arguments: %s\n", $this->dumper->dump($this->dumpValue($definition->getArguments()), 0)); } if ($definition->getProperties()) { $code .= sprintf(" properties: %s\n", $this->dumper->dump($this->dumpValue($definition->getProperties()), 0)); } if ($definition->getMethodCalls()) { $code .= sprintf(" calls:\n%s\n", $this->dumper->dump($this->dumpValue($definition->getMethodCalls()), 1, 12)); } if (!$definition->isShared()) { $code .= " shared: false\n"; } if (ContainerInterface::SCOPE_CONTAINER !== ($scope = $definition->getScope(false))) { $code .= sprintf(" scope: %s\n", $this->dumper->dump($scope)); } if (null !== ($decorated = $definition->getDecoratedService())) { list($decorated, $renamedId, $priority) = $decorated; $code .= sprintf(" decorates: %s\n", $decorated); if (null !== $renamedId) { $code .= sprintf(" decoration_inner_name: %s\n", $renamedId); } if (0 !== $priority) { $code .= sprintf(" decoration_priority: %s\n", $priority); } } if ($callable = $definition->getFactory()) { $code .= sprintf(" factory: %s\n", $this->dumper->dump($this->dumpCallable($callable), 0)); } if ($callable = $definition->getConfigurator()) { $code .= sprintf(" configurator: %s\n", $this->dumper->dump($this->dumpCallable($callable), 0)); } return $code; }
private function addNewInstance($id, Definition $definition, $return, $instantiation) { $class = $this->dumpValue($definition->getClass()); $arguments = array(); foreach ($definition->getArguments() as $value) { $arguments[] = $this->dumpValue($value); } if (null !== $definition->getFactoryMethod()) { if (null !== $definition->getFactoryClass()) { return sprintf(" {$return}{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($definition->getFactoryClass()), $definition->getFactoryMethod(), $arguments ? ', ' . implode(', ', $arguments) : ''); } if (null !== $definition->getFactoryService()) { return sprintf(" {$return}{$instantiation}%s->%s(%s);\n", $this->getServiceCall($definition->getFactoryService()), $definition->getFactoryMethod(), implode(', ', $arguments)); } throw new RuntimeException(sprintf('Factory method requires a factory service or factory class in service definition for %s', $id)); } if (false !== strpos($class, '$')) { return sprintf(" \$class = %s;\n\n {$return}{$instantiation}new \$class(%s);\n", $class, implode(', ', $arguments)); } return sprintf(" {$return}{$instantiation}new \\%s(%s);\n", substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments)); }
/** * Assert that loader definition described properly. * * @param Definition $loader loader definition * @param bool $includeFormat whether or not the requested view format must be included in the route path * @param string[] $formats supported view formats * @param string $defaultFormat default view format */ private function assertValidRestFileLoader(Definition $loader, $includeFormat, array $formats, $defaultFormat) { $locatorRef = new Reference('file_locator'); $processorRef = new Reference('fos_rest.routing.loader.processor'); $arguments = $loader->getArguments(); $this->assertEquals(5, count($arguments)); $this->assertEquals($locatorRef, $arguments[0]); $this->assertEquals($processorRef, $arguments[1]); $this->assertEquals($includeFormat, $this->container->getParameter(strtr($arguments[2], ['%' => '']))); $this->assertEquals($formats, $this->container->getParameter(strtr($arguments[3], ['%' => '']))); $this->assertEquals($defaultFormat, $this->container->getParameter(strtr($arguments[4], ['%' => '']))); $this->assertArrayHasKey('routing.loader', $loader->getTags()); }
/** * Gets a service definition as PHP array. * * @param \Symfony\Component\DependencyInjection\Definition $definition * The definition to process. * * @return array * The service definition as PHP array. */ protected function getServiceDefinition($definition) { $service = array(); if ($definition->getClass()) { $service['class'] = $definition->getClass(); } if (!$definition->isPublic()) { $service['public'] = FALSE; } /* $tagsCode = ''; foreach ($definition->getTags() as $name => $tags) { foreach ($tags as $attributes) { $att = array(); foreach ($attributes as $key => $value) { $att[] = sprintf('%s: %s', $this->dumper->dump($key), $this->dumper->dump($value)); } $att = $att ? ', '.implode(', ', $att) : ''; $tagsCode .= sprintf(" - { name: %s%s }\n", $this->dumper->dump($name), $att); } } if ($tagsCode) { $code .= " tags:\n".$tagsCode; } */ if ($definition->getFile()) { $service['file'] = $definition->getFile(); } if ($definition->isSynthetic()) { $service['synthetic'] = TRUE; } if ($definition->isLazy()) { $service['lazy'] = TRUE; } if ($definition->getArguments()) { $service['arguments'] = $this->dumpValue($definition->getArguments()); } if ($definition->getProperties()) { $service['properties'] = $this->dumpValue($definition->getProperties()); } if ($definition->getMethodCalls()) { $service['calls'] = $this->dumpValue($definition->getMethodCalls()); } if (($scope = $definition->getScope()) !== ContainerInterface::SCOPE_CONTAINER) { $service['scope'] = $scope; } if (($decorated = $definition->getDecoratedService()) !== NULL) { $service['decorates'] = $decorated; } if ($callable = $definition->getFactory()) { $service['factory'] = $this->dumpCallable($callable); } if ($callable = $definition->getConfigurator()) { $service['configurator'] = $this->dumpCallable($callable); } return $service; }
/** * Autowires the constructor or a setter. * * @param string $id * @param Definition $definition * @param \ReflectionMethod $reflectionMethod * * @throws RuntimeException */ private function autowireMethod($id, Definition $definition, \ReflectionMethod $reflectionMethod) { if ($isConstructor = $reflectionMethod->isConstructor()) { $arguments = $definition->getArguments(); } else { $arguments = array(); } $addMethodCall = false; // Whether the method should be added to the definition as a call or as arguments foreach ($reflectionMethod->getParameters() as $index => $parameter) { if (array_key_exists($index, $arguments) && '' !== $arguments[$index]) { continue; } try { if (!$typeHint = $parameter->getClass()) { // no default value? Then fail if (!$parameter->isOptional()) { if ($isConstructor) { throw new RuntimeException(sprintf('Unable to autowire argument index %d ($%s) for the service "%s". If this is an object, give it a type-hint. Otherwise, specify this argument\'s value explicitly.', $index, $parameter->name, $id)); } return; } // specifically pass the default value $arguments[$index] = $parameter->getDefaultValue(); continue; } if (null === $this->types) { $this->populateAvailableTypes(); } if (isset($this->types[$typeHint->name])) { $value = new Reference($this->types[$typeHint->name]); $addMethodCall = true; } else { try { $value = $this->createAutowiredDefinition($typeHint, $id); $addMethodCall = true; } catch (RuntimeException $e) { if ($parameter->allowsNull()) { $value = null; } elseif ($parameter->isDefaultValueAvailable()) { $value = $parameter->getDefaultValue(); } else { // The exception code is set to 1 if the exception must be thrown even if it's a setter if (1 === $e->getCode() || $isConstructor) { throw $e; } return; } } } } catch (\ReflectionException $e) { // Typehint against a non-existing class if (!$parameter->isDefaultValueAvailable()) { if ($isConstructor) { throw new RuntimeException(sprintf('Cannot autowire argument %s for %s because the type-hinted class does not exist (%s).', $index + 1, $definition->getClass(), $e->getMessage()), 0, $e); } return; } $value = $parameter->getDefaultValue(); } $arguments[$index] = $value; } // it's possible index 1 was set, then index 0, then 2, etc // make sure that we re-order so they're injected as expected ksort($arguments); if ($isConstructor) { $definition->setArguments($arguments); } elseif ($addMethodCall) { $definition->addMethodCall($reflectionMethod->name, $arguments); } }
/** * Adds a service. * * @param Definition $definition * @param string $id * @param \DOMElement $parent */ private function addService($definition, $id, \DOMElement $parent) { $service = $this->document->createElement('service'); if (null !== $id) { $service->setAttribute('id', $id); } if ($class = $definition->getClass()) { if ('\\' === substr($class, 0, 1)) { $class = substr($class, 1); } $service->setAttribute('class', $class); } if ($definition->getFactoryMethod(false)) { $service->setAttribute('factory-method', $definition->getFactoryMethod(false)); } if ($definition->getFactoryClass(false)) { $service->setAttribute('factory-class', $definition->getFactoryClass(false)); } if ($definition->getFactoryService(false)) { $service->setAttribute('factory-service', $definition->getFactoryService(false)); } if (ContainerInterface::SCOPE_CONTAINER !== ($scope = $definition->getScope())) { $service->setAttribute('scope', $scope); } if (!$definition->isPublic()) { $service->setAttribute('public', 'false'); } if ($definition->isSynthetic()) { $service->setAttribute('synthetic', 'true'); } if ($definition->isSynchronized(false)) { $service->setAttribute('synchronized', 'true'); } if ($definition->isLazy()) { $service->setAttribute('lazy', 'true'); } if (null !== ($decorated = $definition->getDecoratedService())) { list($decorated, $renamedId) = $decorated; $service->setAttribute('decorates', $decorated); if (null !== $renamedId) { $service->setAttribute('decoration-inner-name', $renamedId); } } foreach ($definition->getTags() as $name => $tags) { foreach ($tags as $attributes) { $tag = $this->document->createElement('tag'); $tag->setAttribute('name', $name); foreach ($attributes as $key => $value) { $tag->setAttribute($key, $value); } $service->appendChild($tag); } } if ($definition->getFile()) { $file = $this->document->createElement('file'); $file->appendChild($this->document->createTextNode($definition->getFile())); $service->appendChild($file); } if ($parameters = $definition->getArguments()) { $this->convertParameters($parameters, 'argument', $service); } if ($parameters = $definition->getProperties()) { $this->convertParameters($parameters, 'property', $service, 'name'); } $this->addMethodCalls($definition->getMethodCalls(), $service); if ($callable = $definition->getFactory()) { $factory = $this->document->createElement('factory'); if (is_array($callable) && $callable[0] instanceof Definition) { $this->addService($callable[0], null, $factory); $factory->setAttribute('method', $callable[1]); } elseif (is_array($callable)) { $factory->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]); $factory->setAttribute('method', $callable[1]); } else { $factory->setAttribute('function', $callable); } $service->appendChild($factory); } if ($callable = $definition->getConfigurator()) { $configurator = $this->document->createElement('configurator'); if (is_array($callable) && $callable[0] instanceof Definition) { $this->addService($callable[0], null, $configurator); $configurator->setAttribute('method', $callable[1]); } elseif (is_array($callable)) { $configurator->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]); $configurator->setAttribute('method', $callable[1]); } else { $configurator->setAttribute('function', $callable); } $service->appendChild($configurator); } $parent->appendChild($service); }
/** * Get the arguments to pass to the service constructor/factory method. * * @return array The array of arguments * * @api * @since 4.0.0 */ public function getArguments() { $symfonyArguments = $this->_underlyingSymfonyDefinition->getArguments(); return $this->convertToTubePressReferenceIfNecessary($symfonyArguments); }
/** * Creates a service for a service definition. * * @param Definition $definition A service definition instance * @param string $id The service identifier * * @return object The service described by the service definition * * @throws \InvalidArgumentException When configure callable is not callable */ private function createService(Definition $definition, $id) { if (null !== $definition->getFile()) { require_once $this->getParameterBag()->resolveValue($definition->getFile()); } $arguments = $this->resolveServices($this->getParameterBag()->resolveValue($definition->getArguments())); if (null !== $definition->getFactoryMethod()) { if (null !== $definition->getFactoryClass()) { $factory = $this->getParameterBag()->resolveValue($definition->getFactoryClass()); } elseif (null !== $definition->getFactoryService()) { $factory = $this->get($this->getParameterBag()->resolveValue($definition->getFactoryService())); } else { throw new \RuntimeException('Cannot create service from factory method without a factory service or factory class.'); } $service = call_user_func_array(array($factory, $definition->getFactoryMethod()), $arguments); } else { $r = new \ReflectionClass($this->getParameterBag()->resolveValue($definition->getClass())); $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments); } if (self::SCOPE_PROTOTYPE !== ($scope = $definition->getScope())) { if (self::SCOPE_CONTAINER !== $scope && !isset($this->scopedServices[$scope])) { throw new \RuntimeException('You tried to create a service of an inactive scope.'); } $this->services[$lowerId = strtolower($id)] = $service; if (self::SCOPE_CONTAINER !== $scope) { $this->scopedServices[$scope][$lowerId] = $service; } } foreach ($definition->getMethodCalls() as $call) { $services = self::getServiceConditionals($call[1]); $ok = true; foreach ($services as $s) { if (!$this->has($s)) { $ok = false; break; } } if ($ok) { call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->resolveValue($call[1]))); } } $properties = $this->resolveServices($this->getParameterBag()->resolveValue($definition->getProperties())); foreach ($properties as $name => $value) { $service->{$name} = $value; } if ($callable = $definition->getConfigurator()) { if (is_array($callable) && is_object($callable[0]) && $callable[0] instanceof Reference) { $callable[0] = $this->get((string) $callable[0]); } elseif (is_array($callable)) { $callable[0] = $this->getParameterBag()->resolveValue($callable[0]); } if (!is_callable($callable)) { throw new \InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', get_class($service))); } call_user_func($callable, $service); } return $service; }
private function getInlineDefinitions(Definition $def) { $defs = new \SplObjectStorage(); $this->getDefinitionsFromArray($def->getArguments(), $defs); $this->getDefinitionsFromArray($def->getMethodCalls(), $defs); $this->getDefinitionsFromArray($def->getProperties(), $defs); return $defs; }
/** * Assert that loader definition described properly. * * @param Definition $loader loader definition * @param string $loaderClassParameter loader class parameter name */ private function assertValidRestFileLoader(Definition $loader, $loaderClassParameter) { $locatorRef = new Reference('file_locator'); $processorRef = new Reference('fos_rest.routing.loader.processor'); $arguments = $loader->getArguments(); $this->assertEquals('%' . $loaderClassParameter . '%', $loader->getClass()); $this->assertEquals(2, count($arguments)); $this->assertEquals($locatorRef, $arguments[0]); $this->assertEquals($processorRef, $arguments[1]); $this->assertArrayHasKey('routing.loader', $loader->getTags()); }
/** * @covers Symfony\Component\DependencyInjection\Definition::replaceArgument */ public function testSetArgument() { $def = new Definition('stdClass'); $def->addArgument('foo'); $this->assertSame(array('foo'), $def->getArguments()); $this->assertSame($def, $def->replaceArgument(0, 'moo')); $this->assertSame(array('moo'), $def->getArguments()); $def->addArgument('moo'); $def->replaceArgument(0, 'foo')->replaceArgument(1, 'bar'); $this->assertSame(array('foo', 'bar'), $def->getArguments()); }
private function addNewInstance($id, Definition $definition, $return, $instantiation) { $class = $this->dumpValue($definition->getClass()); $arguments = array(); foreach ($definition->getArguments() as $value) { $arguments[] = $this->dumpValue($value); } if (null !== $definition->getFactory()) { $callable = $definition->getFactory(); if (is_array($callable)) { if ($callable[0] instanceof Reference || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))) { return sprintf(" $return{$instantiation}%s->%s(%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : ''); } $class = $this->dumpValue($callable[0]); // If the class is a string we can optimize call_user_func away if (strpos($class, "'") === 0) { return sprintf(" $return{$instantiation}%s::%s(%s);\n", $this->dumpLiteralClass($class), $callable[1], $arguments ? implode(', ', $arguments) : ''); } return sprintf(" $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? ', '.implode(', ', $arguments) : ''); } return sprintf(" $return{$instantiation}\\%s(%s);\n", $callable, $arguments ? implode(', ', $arguments) : ''); } if (false !== strpos($class, '$')) { return sprintf(" \$class = %s;\n\n $return{$instantiation}new \$class(%s);\n", $class, implode(', ', $arguments)); } return sprintf(" $return{$instantiation}new %s(%s);\n", $this->dumpLiteralClass($class), implode(', ', $arguments)); }
private function addNewInstance(Definition $definition, $return, $instantiation) { $class = $this->dumpValue($definition->getClass()); $arguments = array(); foreach ($definition->getArguments() as $value) { $arguments[] = $this->dumpValue($value); } if (null !== $definition->getFactory()) { $callable = $definition->getFactory(); if (is_array($callable)) { if (!preg_match('/^[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*$/', $callable[1])) { throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s)', $callable[1] ?: 'n/a')); } if ($callable[0] instanceof Reference || $callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0])) { return sprintf(" {$return}{$instantiation}%s->%s(%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : ''); } $class = $this->dumpValue($callable[0]); // If the class is a string we can optimize call_user_func away if (strpos($class, "'") === 0) { return sprintf(" {$return}{$instantiation}%s::%s(%s);\n", $this->dumpLiteralClass($class), $callable[1], $arguments ? implode(', ', $arguments) : ''); } return sprintf(" {$return}{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? ', ' . implode(', ', $arguments) : ''); } return sprintf(" {$return}{$instantiation}\\%s(%s);\n", $callable, $arguments ? implode(', ', $arguments) : ''); } if (false !== strpos($class, '$')) { return sprintf(" \$class = %s;\n\n {$return}{$instantiation}new \$class(%s);\n", $class, implode(', ', $arguments)); } return sprintf(" {$return}{$instantiation}new %s(%s);\n", $this->dumpLiteralClass($class), implode(', ', $arguments)); }
/** * @param Definition $serviceDefinition * @param TestData $data */ private function setupConstructor(Definition $serviceDefinition, TestData $data) { foreach ($serviceDefinition->getArguments() as $reference) { if ($reference instanceof Definition) { $definition = $reference; $mockName = $this->getShortClassName($definition->getClass()); } elseif ($reference instanceof Reference) { // add setter for model mock $definition = $this->getServiceDefinition((string) $reference); $mockName = $this->getShortClassName($definition->getClass()); } else { $data->constructorArguments[] = var_export($reference, true); continue; } $data->constructorArguments[] = sprintf('$this->%s', lcfirst($mockName)); $this->addMock($definition, $data, $mockName); } }
/** * Adds a service * * @param string $id * @param Definition $definition * * @return string */ private function addService($id, $definition) { $code = " {$id}:\n"; if ($definition->getClass()) { $code .= sprintf(" class: %s\n", $definition->getClass()); } if (!$definition->isPublic()) { $code .= " public: false\n"; } $tagsCode = ''; foreach ($definition->getTags() as $name => $tags) { foreach ($tags as $attributes) { $att = array(); foreach ($attributes as $key => $value) { $att[] = sprintf('%s: %s', $this->dumper->dump($key), $this->dumper->dump($value)); } $att = $att ? ', ' . implode(' ', $att) : ''; $tagsCode .= sprintf(" - { name: %s%s }\n", $this->dumper->dump($name), $att); } } if ($tagsCode) { $code .= " tags:\n" . $tagsCode; } if ($definition->getFile()) { $code .= sprintf(" file: %s\n", $definition->getFile()); } if ($definition->isSynthetic()) { $code .= sprintf(" synthetic: true\n"); } if ($definition->isSynchronized()) { $code .= sprintf(" synchronized: true\n"); } if ($definition->getFactoryClass()) { $code .= sprintf(" factory_class: %s\n", $definition->getFactoryClass()); } if ($definition->isLazy()) { $code .= sprintf(" lazy: true\n"); } if ($definition->getFactoryMethod()) { $code .= sprintf(" factory_method: %s\n", $definition->getFactoryMethod()); } if ($definition->getFactoryService()) { $code .= sprintf(" factory_service: %s\n", $definition->getFactoryService()); } if ($definition->getArguments()) { $code .= sprintf(" arguments: %s\n", $this->dumper->dump($this->dumpValue($definition->getArguments()), 0)); } if ($definition->getProperties()) { $code .= sprintf(" properties: %s\n", $this->dumper->dump($this->dumpValue($definition->getProperties()), 0)); } if ($definition->getMethodCalls()) { $code .= sprintf(" calls:\n%s\n", $this->dumper->dump($this->dumpValue($definition->getMethodCalls()), 1, 12)); } if (ContainerInterface::SCOPE_CONTAINER !== ($scope = $definition->getScope())) { $code .= sprintf(" scope: %s\n", $scope); } if ($callable = $definition->getConfigurator()) { if (is_array($callable)) { if ($callable[0] instanceof Reference) { $callable = array($this->getServiceCall((string) $callable[0], $callable[0]), $callable[1]); } else { $callable = array($callable[0], $callable[1]); } } $code .= sprintf(" configurator: %s\n", $this->dumper->dump($callable, 0)); } return $code; }
private function addNewInstance($id, Definition $definition, $return, $instantiation) { $class = $this->dumpValue($definition->getClass()); $arguments = array(); foreach ($definition->getArguments() as $value) { $arguments[] = $this->dumpValue($value); } if (null !== $definition->getFactory()) { $callable = $definition->getFactory(); if (is_array($callable)) { if ($callable[0] instanceof Reference || $callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0])) { return sprintf(" {$return}{$instantiation}%s->%s(%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : ''); } $class = $this->dumpValue($callable[0]); // If the class is a string we can optimize call_user_func away if (strpos($class, "'") === 0) { return sprintf(" {$return}{$instantiation}%s::%s(%s);\n", $this->dumpLiteralClass($class), $callable[1], $arguments ? implode(', ', $arguments) : ''); } return sprintf(" {$return}{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? ', ' . implode(', ', $arguments) : ''); } return sprintf(" {$return}{$instantiation}\\%s(%s);\n", $callable, $arguments ? implode(', ', $arguments) : ''); } elseif (null !== $definition->getFactoryMethod(false)) { if (null !== $definition->getFactoryClass(false)) { $class = $this->dumpValue($definition->getFactoryClass(false)); // If the class is a string we can optimize call_user_func away if (strpos($class, "'") === 0) { return sprintf(" {$return}{$instantiation}%s::%s(%s);\n", $this->dumpLiteralClass($class), $definition->getFactoryMethod(false), $arguments ? implode(', ', $arguments) : ''); } return sprintf(" {$return}{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($definition->getFactoryClass(false)), $definition->getFactoryMethod(false), $arguments ? ', ' . implode(', ', $arguments) : ''); } if (null !== $definition->getFactoryService(false)) { return sprintf(" {$return}{$instantiation}%s->%s(%s);\n", $this->getServiceCall($definition->getFactoryService(false)), $definition->getFactoryMethod(false), implode(', ', $arguments)); } throw new RuntimeException(sprintf('Factory method requires a factory service or factory class in service definition for %s', $id)); } if (false !== strpos($class, '$')) { return sprintf(" \$class = %s;\n\n {$return}{$instantiation}new \$class(%s);\n", $class, implode(', ', $arguments)); } return sprintf(" {$return}{$instantiation}new %s(%s);\n", $this->dumpLiteralClass($class), implode(', ', $arguments)); }
private function assertDICConstructorArguments(Definition $definition, $args) { $this->assertEquals($args, $definition->getArguments(), "Expected and actual DIC Service constructor arguments of definition '" . $definition->getClass() . "' don't match."); }
/** * Generates the service instance. * * @param string $id * @param Definition $definition * * @return string * * @throws InvalidArgumentException * @throws RuntimeException */ private function addServiceInstance($id, $definition) { $class = $this->dumpValue($definition->getClass()); if (0 === strpos($class, "'") && !preg_match('/^\'[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*(\\\\{2}[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*)*\'$/', $class)) { throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id)); } $arguments = array(); foreach ($definition->getArguments() as $value) { $arguments[] = $this->dumpValue($value); } $simple = $this->isSimpleInstance($id, $definition); $instantiation = ''; if (ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) { $instantiation = "\$this->services['{$id}'] = " . ($simple ? '' : '$instance'); } elseif (ContainerInterface::SCOPE_PROTOTYPE !== ($scope = $definition->getScope())) { $instantiation = "\$this->services['{$id}'] = \$this->scopedServices['{$scope}']['{$id}'] = " . ($simple ? '' : '$instance'); } elseif (!$simple) { $instantiation = '$instance'; } $return = ''; if ($simple) { $return = 'return '; } else { $instantiation .= ' = '; } if (null !== $definition->getFactoryMethod()) { if (null !== $definition->getFactoryClass()) { $code = sprintf(" {$return}{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($definition->getFactoryClass()), $definition->getFactoryMethod(), $arguments ? ', ' . implode(', ', $arguments) : ''); } elseif (null !== $definition->getFactoryService()) { $code = sprintf(" {$return}{$instantiation}%s->%s(%s);\n", $this->getServiceCall($definition->getFactoryService()), $definition->getFactoryMethod(), implode(', ', $arguments)); } else { throw new RuntimeException('Factory method requires a factory service or factory class in service definition for ' . $id); } } elseif (false !== strpos($class, '$')) { $code = sprintf(" \$class = %s;\n\n {$return}{$instantiation}new \$class(%s);\n", $class, implode(', ', $arguments)); } else { $code = sprintf(" {$return}{$instantiation}new \\%s(%s);\n", substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments)); } if (!$simple) { $code .= "\n"; } return $code; }
/** * Adds a service. * * @param Definition $definition * @param string $id * @param \DOMElement $parent */ private function addService($definition, $id, \DOMElement $parent) { $service = $this->document->createElement('service'); if (null !== $id) { $service->setAttribute('id', $id); } if ($definition->getClass()) { $service->setAttribute('class', $definition->getClass()); } if ($definition->getFactoryMethod()) { $service->setAttribute('factory-method', $definition->getFactoryMethod()); } if ($definition->getFactoryService()) { $service->setAttribute('factory-service', $definition->getFactoryService()); } if (ContainerInterface::SCOPE_CONTAINER !== ($scope = $definition->getScope())) { $service->setAttribute('scope', $scope); } if (!$definition->isPublic()) { $service->setAttribute('public', 'false'); } foreach ($definition->getTags() as $name => $tags) { foreach ($tags as $attributes) { $tag = $this->document->createElement('tag'); $tag->setAttribute('name', $name); foreach ($attributes as $key => $value) { $tag->setAttribute($key, $value); } $service->appendChild($tag); } } if ($definition->getFile()) { $file = $this->document->createElement('file'); $file->appendChild($this->document->createTextNode($definition->getFile())); $service->appendChild($file); } if ($parameters = $definition->getArguments()) { $this->convertParameters($parameters, 'argument', $service); } if ($parameters = $definition->getProperties()) { $this->convertParameters($parameters, 'property', $service, 'name'); } $this->addMethodCalls($definition->getMethodCalls(), $service); if ($callable = $definition->getConfigurator()) { $configurator = $this->document->createElement('configurator'); if (is_array($callable)) { $configurator->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]); $configurator->setAttribute('method', $callable[1]); } else { $configurator->setAttribute('function', $callable); } $service->appendChild($configurator); } $parent->appendChild($service); }
/** * Gets a service definition as PHP array. * * @param \Symfony\Component\DependencyInjection\Definition $definition * The definition to process. * * @return array * The service definition as PHP array. * * @throws \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException * Thrown when the definition is marked as decorated, or with an explicit * scope different from SCOPE_CONTAINER and SCOPE_PROTOTYPE. */ protected function getServiceDefinition(Definition $definition) { $service = array(); if ($definition->getClass()) { $service['class'] = $definition->getClass(); } if (!$definition->isPublic()) { $service['public'] = FALSE; } if ($definition->getFile()) { $service['file'] = $definition->getFile(); } if ($definition->isSynthetic()) { $service['synthetic'] = TRUE; } if ($definition->isLazy()) { $service['lazy'] = TRUE; } if ($definition->getArguments()) { $arguments = $definition->getArguments(); $service['arguments'] = $this->dumpCollection($arguments); $service['arguments_count'] = count($arguments); } else { $service['arguments_count'] = 0; } if ($definition->getProperties()) { $service['properties'] = $this->dumpCollection($definition->getProperties()); } if ($definition->getMethodCalls()) { $service['calls'] = $this->dumpMethodCalls($definition->getMethodCalls()); } if (($scope = $definition->getScope()) !== ContainerInterface::SCOPE_CONTAINER) { if ($scope === ContainerInterface::SCOPE_PROTOTYPE) { // Scope prototype has been replaced with 'shared' => FALSE. // This is a Symfony 2.8 forward compatibility fix. // Reference: https://github.com/symfony/symfony/blob/2.8/UPGRADE-2.8.md#dependencyinjection $service['shared'] = FALSE; } else { throw new InvalidArgumentException("The 'scope' definition is deprecated in Symfony 3.0 and not supported by Drupal 8."); } } // By default services are shared, so just provide the flag, when needed. if ($definition->isShared() === FALSE) { $service['shared'] = $definition->isShared(); } if (($decorated = $definition->getDecoratedService()) !== NULL) { throw new InvalidArgumentException("The 'decorated' definition is not supported by the Drupal 8 run-time container. The Container Builder should have resolved that during the DecoratorServicePass compiler pass."); } if ($callable = $definition->getFactory()) { $service['factory'] = $this->dumpCallable($callable); } if ($callable = $definition->getConfigurator()) { $service['configurator'] = $this->dumpCallable($callable); } return $service; }