[DependencyInjection] Add "instanceof" section for local interface-defined configs
This commit is contained in:
parent
0a3cd973ae
commit
2fb601983f
@ -4,6 +4,7 @@ CHANGELOG
|
|||||||
3.3.0
|
3.3.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
* [EXPERIMENTAL] added "instanceof" section for local interface-defined configs
|
||||||
* [EXPERIMENTAL] added "service-locator" argument for lazy loading a set of identified values and services
|
* [EXPERIMENTAL] added "service-locator" argument for lazy loading a set of identified values and services
|
||||||
* [EXPERIMENTAL] added prototype services for PSR4-based discovery and registration
|
* [EXPERIMENTAL] added prototype services for PSR4-based discovery and registration
|
||||||
* added `ContainerBuilder::getReflectionClass()` for retrieving and tracking reflection class info
|
* added `ContainerBuilder::getReflectionClass()` for retrieving and tracking reflection class info
|
||||||
|
@ -119,6 +119,16 @@ class ChildDefinition extends Definition
|
|||||||
return parent::setFile($file);
|
return parent::setFile($file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function setShared($boolean)
|
||||||
|
{
|
||||||
|
$this->changes['shared'] = true;
|
||||||
|
|
||||||
|
return parent::setShared($boolean);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
@ -139,6 +149,16 @@ class ChildDefinition extends Definition
|
|||||||
return parent::setLazy($boolean);
|
return parent::setLazy($boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function setAbstract($boolean)
|
||||||
|
{
|
||||||
|
$this->changes['abstract'] = true;
|
||||||
|
|
||||||
|
return parent::setAbstract($boolean);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
@ -42,6 +42,7 @@ class PassConfig
|
|||||||
$this->beforeOptimizationPasses = array(
|
$this->beforeOptimizationPasses = array(
|
||||||
100 => array(
|
100 => array(
|
||||||
$resolveClassPass = new ResolveClassPass(),
|
$resolveClassPass = new ResolveClassPass(),
|
||||||
|
new ResolveDefinitionInheritancePass(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -0,0 +1,106 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\DependencyInjection\Compiler;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\ChildDefinition;
|
||||||
|
use Symfony\Component\DependencyInjection\Definition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies tags and instanceof inheritance to definitions.
|
||||||
|
*
|
||||||
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
|
*/
|
||||||
|
class ResolveDefinitionInheritancePass extends AbstractRecursivePass
|
||||||
|
{
|
||||||
|
protected function processValue($value, $isRoot = false)
|
||||||
|
{
|
||||||
|
if (!$value instanceof Definition) {
|
||||||
|
return parent::processValue($value, $isRoot);
|
||||||
|
}
|
||||||
|
if ($value instanceof ChildDefinition) {
|
||||||
|
$this->resolveDefinition($value);
|
||||||
|
}
|
||||||
|
$class = $value->getClass();
|
||||||
|
if (!$class || false !== strpos($class, '%') || !$instanceof = $value->getInstanceofConditionals()) {
|
||||||
|
return parent::processValue($value, $isRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($instanceof as $interface => $definition) {
|
||||||
|
if ($interface !== $class && (!$this->container->getReflectionClass($interface) || !$this->container->getReflectionClass($class))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($interface === $class || is_subclass_of($class, $interface)) {
|
||||||
|
$this->mergeDefinition($value, $definition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::processValue($value, $isRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates the class and tags from parent definitions.
|
||||||
|
*/
|
||||||
|
private function resolveDefinition(ChildDefinition $definition)
|
||||||
|
{
|
||||||
|
if (!$this->container->has($parent = $definition->getParent())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$parentDef = $this->container->findDefinition($parent);
|
||||||
|
if ($parentDef instanceof ChildDefinition) {
|
||||||
|
$this->resolveDefinition($parentDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($definition->getChanges()['class'])) {
|
||||||
|
$definition->setClass($parentDef->getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
// append parent tags when inheriting is enabled
|
||||||
|
if ($definition->getInheritTags()) {
|
||||||
|
foreach ($parentDef->getTags() as $k => $v) {
|
||||||
|
foreach ($v as $v) {
|
||||||
|
$definition->addTag($k, $v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$definition->setInheritTags(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function mergeDefinition(Definition $def, ChildDefinition $definition)
|
||||||
|
{
|
||||||
|
$changes = $definition->getChanges();
|
||||||
|
if (isset($changes['shared'])) {
|
||||||
|
$def->setShared($definition->isShared());
|
||||||
|
}
|
||||||
|
if (isset($changes['abstract'])) {
|
||||||
|
$def->setAbstract($definition->isAbstract());
|
||||||
|
}
|
||||||
|
if (isset($changes['autowired_calls'])) {
|
||||||
|
$autowiredCalls = $def->getAutowiredCalls();
|
||||||
|
}
|
||||||
|
|
||||||
|
ResolveDefinitionTemplatesPass::mergeDefinition($def, $definition);
|
||||||
|
|
||||||
|
// merge autowired calls
|
||||||
|
if (isset($changes['autowired_calls'])) {
|
||||||
|
$def->setAutowiredCalls(array_merge($autowiredCalls, $def->getAutowiredCalls()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge tags
|
||||||
|
foreach ($definition->getTags() as $k => $v) {
|
||||||
|
foreach ($v as $v) {
|
||||||
|
$def->addTag($k, $v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -103,6 +103,26 @@ class ResolveDefinitionTemplatesPass extends AbstractRecursivePass
|
|||||||
$def->setLazy($parentDef->isLazy());
|
$def->setLazy($parentDef->isLazy());
|
||||||
$def->setAutowiredCalls($parentDef->getAutowiredCalls());
|
$def->setAutowiredCalls($parentDef->getAutowiredCalls());
|
||||||
|
|
||||||
|
self::mergeDefinition($def, $definition);
|
||||||
|
|
||||||
|
// merge autowiring types
|
||||||
|
foreach ($definition->getAutowiringTypes(false) as $autowiringType) {
|
||||||
|
$def->addAutowiringType($autowiringType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// these attributes are always taken from the child
|
||||||
|
$def->setAbstract($definition->isAbstract());
|
||||||
|
$def->setShared($definition->isShared());
|
||||||
|
$def->setTags($definition->getTags());
|
||||||
|
|
||||||
|
return $def;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
public static function mergeDefinition(Definition $def, ChildDefinition $definition)
|
||||||
|
{
|
||||||
// overwrite with values specified in the decorator
|
// overwrite with values specified in the decorator
|
||||||
$changes = $definition->getChanges();
|
$changes = $definition->getChanges();
|
||||||
if (isset($changes['class'])) {
|
if (isset($changes['class'])) {
|
||||||
@ -168,26 +188,5 @@ class ResolveDefinitionTemplatesPass extends AbstractRecursivePass
|
|||||||
foreach ($definition->getOverriddenGetters() as $k => $v) {
|
foreach ($definition->getOverriddenGetters() as $k => $v) {
|
||||||
$def->setOverriddenGetter($k, $v);
|
$def->setOverriddenGetter($k, $v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// merge autowiring types
|
|
||||||
foreach ($definition->getAutowiringTypes(false) as $autowiringType) {
|
|
||||||
$def->addAutowiringType($autowiringType);
|
|
||||||
}
|
|
||||||
|
|
||||||
// these attributes are always taken from the child
|
|
||||||
$def->setAbstract($definition->isAbstract());
|
|
||||||
$def->setShared($definition->isShared());
|
|
||||||
$def->setTags($definition->getTags());
|
|
||||||
|
|
||||||
// append parent tags when inheriting is enabled
|
|
||||||
if ($definition->getInheritTags()) {
|
|
||||||
foreach ($parentDef->getTags() as $k => $v) {
|
|
||||||
foreach ($v as $v) {
|
|
||||||
$def->addTag($k, $v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $def;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ class Definition
|
|||||||
private $properties = array();
|
private $properties = array();
|
||||||
private $calls = array();
|
private $calls = array();
|
||||||
private $getters = array();
|
private $getters = array();
|
||||||
|
private $instanceof = array();
|
||||||
private $configurator;
|
private $configurator;
|
||||||
private $tags = array();
|
private $tags = array();
|
||||||
private $public = true;
|
private $public = true;
|
||||||
@ -363,6 +364,32 @@ class Definition
|
|||||||
return $this->getters;
|
return $this->getters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the definition templates to conditionally apply on the current definition, keyed by parent interface/class.
|
||||||
|
*
|
||||||
|
* @param $instanceof ChildDefinition[]
|
||||||
|
*
|
||||||
|
* @experimental in version 3.3
|
||||||
|
*/
|
||||||
|
public function setInstanceofConditionals(array $instanceof)
|
||||||
|
{
|
||||||
|
$this->instanceof = $instanceof;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the definition templates to conditionally apply on the current definition, keyed by parent interface/class.
|
||||||
|
*
|
||||||
|
* @return ChildDefinition[]
|
||||||
|
*
|
||||||
|
* @experimental in version 3.3
|
||||||
|
*/
|
||||||
|
public function getInstanceofConditionals()
|
||||||
|
{
|
||||||
|
return $this->instanceof;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets tags for this definition.
|
* Sets tags for this definition.
|
||||||
*
|
*
|
||||||
@ -736,9 +763,7 @@ class Definition
|
|||||||
*/
|
*/
|
||||||
public function setAutowired($autowired)
|
public function setAutowired($autowired)
|
||||||
{
|
{
|
||||||
$this->autowiredCalls = $autowired ? array('__construct') : array();
|
return $this->setAutowiredCalls($autowired ? array('__construct') : array());
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Component\DependencyInjection\Loader;
|
namespace Symfony\Component\DependencyInjection\Loader;
|
||||||
|
|
||||||
use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
|
use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
|
||||||
|
use Symfony\Component\DependencyInjection\ChildDefinition;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Component\DependencyInjection\Definition;
|
use Symfony\Component\DependencyInjection\Definition;
|
||||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||||
@ -29,6 +30,8 @@ use Symfony\Component\Finder\Glob;
|
|||||||
abstract class FileLoader extends BaseFileLoader
|
abstract class FileLoader extends BaseFileLoader
|
||||||
{
|
{
|
||||||
protected $container;
|
protected $container;
|
||||||
|
protected $isLoadingInstanceof = false;
|
||||||
|
protected $instanceof = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||||
@ -80,7 +83,22 @@ abstract class FileLoader extends BaseFileLoader
|
|||||||
$prototype = serialize($prototype);
|
$prototype = serialize($prototype);
|
||||||
|
|
||||||
foreach ($classes as $class) {
|
foreach ($classes as $class) {
|
||||||
$this->container->setDefinition($class, unserialize($prototype));
|
$this->setDefinition($class, unserialize($prototype));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @experimental in version 3.3
|
||||||
|
*/
|
||||||
|
protected function setDefinition($id, Definition $definition)
|
||||||
|
{
|
||||||
|
if ($this->isLoadingInstanceof) {
|
||||||
|
if (!$definition instanceof ChildDefinition) {
|
||||||
|
throw new InvalidArgumentException(sprintf('Invalid type definition "%s": ChildDefinition expected, "%s" given.', $id, get_class($definition)));
|
||||||
|
}
|
||||||
|
$this->instanceof[$id] = $definition;
|
||||||
|
} else {
|
||||||
|
$this->container->setDefinition($id, $definition->setInstanceofConditionals($this->instanceof));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,11 @@ class XmlFileLoader extends FileLoader
|
|||||||
$this->loadFromExtensions($xml);
|
$this->loadFromExtensions($xml);
|
||||||
|
|
||||||
// services
|
// services
|
||||||
$this->parseDefinitions($xml, $path);
|
try {
|
||||||
|
$this->parseDefinitions($xml, $path);
|
||||||
|
} finally {
|
||||||
|
$this->instanceof = array();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -126,13 +130,21 @@ class XmlFileLoader extends FileLoader
|
|||||||
}
|
}
|
||||||
$this->setCurrentDir(dirname($file));
|
$this->setCurrentDir(dirname($file));
|
||||||
|
|
||||||
|
$this->instanceof = array();
|
||||||
|
$this->isLoadingInstanceof = true;
|
||||||
|
$instanceof = $xpath->query('//container:services/container:instanceof');
|
||||||
|
foreach ($instanceof as $service) {
|
||||||
|
$this->setDefinition((string) $service->getAttribute('id'), $this->parseDefinition($service, $file, array()));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->isLoadingInstanceof = false;
|
||||||
$defaults = $this->getServiceDefaults($xml, $file);
|
$defaults = $this->getServiceDefaults($xml, $file);
|
||||||
foreach ($services as $service) {
|
foreach ($services as $service) {
|
||||||
if (null !== $definition = $this->parseDefinition($service, $file, $defaults)) {
|
if (null !== $definition = $this->parseDefinition($service, $file, $defaults)) {
|
||||||
if ('prototype' === $service->tagName) {
|
if ('prototype' === $service->tagName) {
|
||||||
$this->registerClasses($definition, (string) $service->getAttribute('namespace'), (string) $service->getAttribute('resource'));
|
$this->registerClasses($definition, (string) $service->getAttribute('namespace'), (string) $service->getAttribute('resource'));
|
||||||
} else {
|
} else {
|
||||||
$this->container->setDefinition((string) $service->getAttribute('id'), $definition);
|
$this->setDefinition((string) $service->getAttribute('id'), $definition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,7 +221,9 @@ class XmlFileLoader extends FileLoader
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($parent = $service->getAttribute('parent')) {
|
if ($this->isLoadingInstanceof) {
|
||||||
|
$definition = new ChildDefinition('');
|
||||||
|
} elseif ($parent = $service->getAttribute('parent')) {
|
||||||
$definition = new ChildDefinition($parent);
|
$definition = new ChildDefinition($parent);
|
||||||
|
|
||||||
if ($value = $service->getAttribute('inherit-tags')) {
|
if ($value = $service->getAttribute('inherit-tags')) {
|
||||||
@ -247,7 +261,7 @@ class XmlFileLoader extends FileLoader
|
|||||||
$definition->setDeprecated(true, $deprecated[0]->nodeValue ?: null);
|
$definition->setDeprecated(true, $deprecated[0]->nodeValue ?: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
$definition->setArguments($this->getArgumentsAsPhp($service, 'argument', false, (bool) $parent));
|
$definition->setArguments($this->getArgumentsAsPhp($service, 'argument', false, $definition instanceof ChildDefinition));
|
||||||
$definition->setProperties($this->getArgumentsAsPhp($service, 'property'));
|
$definition->setProperties($this->getArgumentsAsPhp($service, 'property'));
|
||||||
$definition->setOverriddenGetters($this->getArgumentsAsPhp($service, 'getter'));
|
$definition->setOverriddenGetters($this->getArgumentsAsPhp($service, 'getter'));
|
||||||
|
|
||||||
@ -422,7 +436,7 @@ class XmlFileLoader extends FileLoader
|
|||||||
uksort($definitions, 'strnatcmp');
|
uksort($definitions, 'strnatcmp');
|
||||||
foreach (array_reverse($definitions) as $id => list($domElement, $file, $wild)) {
|
foreach (array_reverse($definitions) as $id => list($domElement, $file, $wild)) {
|
||||||
if (null !== $definition = $this->parseDefinition($domElement, $file)) {
|
if (null !== $definition = $this->parseDefinition($domElement, $file)) {
|
||||||
$this->container->setDefinition($id, $definition);
|
$this->setDefinition($id, $definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (true === $wild) {
|
if (true === $wild) {
|
||||||
|
@ -81,6 +81,22 @@ class YamlFileLoader extends FileLoader
|
|||||||
'autowire' => 'autowire',
|
'autowire' => 'autowire',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
private static $instanceofKeywords = array(
|
||||||
|
'shared' => 'shared',
|
||||||
|
'lazy' => 'lazy',
|
||||||
|
'public' => 'public',
|
||||||
|
'abstract' => 'abstract',
|
||||||
|
'deprecated' => 'deprecated',
|
||||||
|
'factory' => 'factory',
|
||||||
|
'arguments' => 'arguments',
|
||||||
|
'properties' => 'properties',
|
||||||
|
'getters' => 'getters',
|
||||||
|
'configurator' => 'configurator',
|
||||||
|
'calls' => 'calls',
|
||||||
|
'tags' => 'tags',
|
||||||
|
'autowire' => 'autowire',
|
||||||
|
);
|
||||||
|
|
||||||
private static $defaultsKeywords = array(
|
private static $defaultsKeywords = array(
|
||||||
'public' => 'public',
|
'public' => 'public',
|
||||||
'tags' => 'tags',
|
'tags' => 'tags',
|
||||||
@ -125,7 +141,11 @@ class YamlFileLoader extends FileLoader
|
|||||||
|
|
||||||
// services
|
// services
|
||||||
$this->setCurrentDir(dirname($path));
|
$this->setCurrentDir(dirname($path));
|
||||||
$this->parseDefinitions($content, $resource);
|
try {
|
||||||
|
$this->parseDefinitions($content, $resource);
|
||||||
|
} finally {
|
||||||
|
$this->instanceof = array();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -187,6 +207,22 @@ class YamlFileLoader extends FileLoader
|
|||||||
throw new InvalidArgumentException(sprintf('The "services" key should contain an array in %s. Check your YAML syntax.', $file));
|
throw new InvalidArgumentException(sprintf('The "services" key should contain an array in %s. Check your YAML syntax.', $file));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->isUnderscoredParamValid($content, '_instanceof', $file)) {
|
||||||
|
$this->instanceof = array();
|
||||||
|
$this->isLoadingInstanceof = true;
|
||||||
|
foreach ($content['services']['_instanceof'] as $id => $service) {
|
||||||
|
if (!$service || !is_array($service)) {
|
||||||
|
throw new InvalidArgumentException(sprintf('Type definition "%s" must be a non-empty array within "_instanceof" in %s. Check your YAML syntax.', $id, $file));
|
||||||
|
}
|
||||||
|
if (is_string($service) && 0 === strpos($service, '@')) {
|
||||||
|
throw new InvalidArgumentException(sprintf('Type definition "%s" cannot be an alias within "_instanceof" in %s. Check your YAML syntax.', $id, $file));
|
||||||
|
}
|
||||||
|
$this->parseDefinition($id, $service, $file, array());
|
||||||
|
}
|
||||||
|
unset($content['services']['_instanceof']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->isLoadingInstanceof = false;
|
||||||
$defaults = $this->parseDefaults($content, $file);
|
$defaults = $this->parseDefaults($content, $file);
|
||||||
foreach ($content['services'] as $id => $service) {
|
foreach ($content['services'] as $id => $service) {
|
||||||
$this->parseDefinition($id, $service, $file, $defaults);
|
$this->parseDefinition($id, $service, $file, $defaults);
|
||||||
@ -203,18 +239,11 @@ class YamlFileLoader extends FileLoader
|
|||||||
*/
|
*/
|
||||||
private function parseDefaults(array &$content, $file)
|
private function parseDefaults(array &$content, $file)
|
||||||
{
|
{
|
||||||
if (!isset($content['services']['_defaults'])) {
|
if (!$this->isUnderscoredParamValid($content, '_defaults', $file)) {
|
||||||
return array();
|
|
||||||
}
|
|
||||||
if (!is_array($defaults = $content['services']['_defaults'])) {
|
|
||||||
throw new InvalidArgumentException(sprintf('Service defaults must be an array, "%s" given in "%s".', gettype($defaults), $file));
|
|
||||||
}
|
|
||||||
if (isset($defaults['alias']) || isset($defaults['class']) || isset($defaults['factory'])) {
|
|
||||||
// @deprecated code path, to be removed in 4.0
|
|
||||||
|
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$defaults = $content['services']['_defaults'];
|
||||||
unset($content['services']['_defaults']);
|
unset($content['services']['_defaults']);
|
||||||
|
|
||||||
foreach ($defaults as $key => $default) {
|
foreach ($defaults as $key => $default) {
|
||||||
@ -304,7 +333,7 @@ class YamlFileLoader extends FileLoader
|
|||||||
throw new InvalidArgumentException(sprintf('A service definition must be an array or a string starting with "@" but %s found for service "%s" in %s. Check your YAML syntax.', gettype($service), $id, $file));
|
throw new InvalidArgumentException(sprintf('A service definition must be an array or a string starting with "@" but %s found for service "%s" in %s. Check your YAML syntax.', gettype($service), $id, $file));
|
||||||
}
|
}
|
||||||
|
|
||||||
static::checkDefinition($id, $service, $file);
|
$this->checkDefinition($id, $service, $file);
|
||||||
|
|
||||||
if (isset($service['alias'])) {
|
if (isset($service['alias'])) {
|
||||||
$public = array_key_exists('public', $service) ? (bool) $service['public'] : (isset($defaults['public']) ? $defaults['public'] : true);
|
$public = array_key_exists('public', $service) ? (bool) $service['public'] : (isset($defaults['public']) ? $defaults['public'] : true);
|
||||||
@ -319,7 +348,9 @@ class YamlFileLoader extends FileLoader
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($service['parent'])) {
|
if ($this->isLoadingInstanceof) {
|
||||||
|
$definition = new ChildDefinition('');
|
||||||
|
} elseif (isset($service['parent'])) {
|
||||||
$definition = new ChildDefinition($service['parent']);
|
$definition = new ChildDefinition($service['parent']);
|
||||||
|
|
||||||
$inheritTag = isset($service['inherit_tags']) ? $service['inherit_tags'] : (isset($defaults['inherit_tags']) ? $defaults['inherit_tags'] : null);
|
$inheritTag = isset($service['inherit_tags']) ? $service['inherit_tags'] : (isset($defaults['inherit_tags']) ? $defaults['inherit_tags'] : null);
|
||||||
@ -494,7 +525,7 @@ class YamlFileLoader extends FileLoader
|
|||||||
}
|
}
|
||||||
$this->registerClasses($definition, $id, $service['resource']);
|
$this->registerClasses($definition, $id, $service['resource']);
|
||||||
} else {
|
} else {
|
||||||
$this->container->setDefinition($id, $definition);
|
$this->setDefinition($id, $definition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -723,12 +754,14 @@ class YamlFileLoader extends FileLoader
|
|||||||
* @param array $definition The service definition to check
|
* @param array $definition The service definition to check
|
||||||
* @param string $file The loaded YAML file
|
* @param string $file The loaded YAML file
|
||||||
*/
|
*/
|
||||||
private static function checkDefinition($id, array $definition, $file)
|
private function checkDefinition($id, array $definition, $file)
|
||||||
{
|
{
|
||||||
if ($throw = isset($definition['resource'])) {
|
if ($throw = $this->isLoadingInstanceof) {
|
||||||
$keywords = static::$prototypeKeywords;
|
$keywords = self::$instanceofKeywords;
|
||||||
|
} elseif ($throw = isset($definition['resource'])) {
|
||||||
|
$keywords = self::$prototypeKeywords;
|
||||||
} else {
|
} else {
|
||||||
$keywords = static::$serviceKeywords;
|
$keywords = self::$serviceKeywords;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($definition as $key => $value) {
|
foreach ($definition as $key => $value) {
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
<xsd:element name="service" type="service" minOccurs="1" />
|
<xsd:element name="service" type="service" minOccurs="1" />
|
||||||
<xsd:element name="prototype" type="prototype" minOccurs="0" />
|
<xsd:element name="prototype" type="prototype" minOccurs="0" />
|
||||||
<xsd:element name="defaults" type="defaults" minOccurs="0" maxOccurs="1" />
|
<xsd:element name="defaults" type="defaults" minOccurs="0" maxOccurs="1" />
|
||||||
|
<xsd:element name="instanceof" type="instanceof" minOccurs="0" />
|
||||||
</xsd:choice>
|
</xsd:choice>
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
|
|
||||||
@ -137,6 +138,26 @@
|
|||||||
<xsd:attribute name="inherit-tags" type="boolean" />
|
<xsd:attribute name="inherit-tags" type="boolean" />
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
|
|
||||||
|
<xsd:complexType name="instanceof">
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
|
||||||
|
<xsd:element name="configurator" type="callable" minOccurs="0" maxOccurs="1" />
|
||||||
|
<xsd:element name="factory" type="callable" minOccurs="0" maxOccurs="1" />
|
||||||
|
<xsd:element name="deprecated" type="xsd:string" minOccurs="0" maxOccurs="1" />
|
||||||
|
<xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" />
|
||||||
|
<xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
|
||||||
|
<xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
|
||||||
|
<xsd:element name="getter" type="getter" minOccurs="0" maxOccurs="unbounded" />
|
||||||
|
<xsd:element name="autowire" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
|
||||||
|
</xsd:choice>
|
||||||
|
<xsd:attribute name="id" type="xsd:string" use="required" />
|
||||||
|
<xsd:attribute name="shared" type="boolean" />
|
||||||
|
<xsd:attribute name="public" type="boolean" />
|
||||||
|
<xsd:attribute name="lazy" type="boolean" />
|
||||||
|
<xsd:attribute name="abstract" type="boolean" />
|
||||||
|
<xsd:attribute name="autowire" type="boolean" />
|
||||||
|
</xsd:complexType>
|
||||||
|
|
||||||
<xsd:complexType name="prototype">
|
<xsd:complexType name="prototype">
|
||||||
<xsd:choice maxOccurs="unbounded">
|
<xsd:choice maxOccurs="unbounded">
|
||||||
<xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
|
<xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
|
||||||
|
Reference in New Issue
Block a user