Update Composer, update everything
This commit is contained in:
parent
ea3e94409f
commit
dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions
172
vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php
vendored
Normal file
172
vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php
vendored
Normal file
|
@ -0,0 +1,172 @@
|
|||
<?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\Argument\ArgumentInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
abstract class AbstractRecursivePass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* @var ContainerBuilder
|
||||
*/
|
||||
protected $container;
|
||||
protected $currentId;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
|
||||
try {
|
||||
$this->processValue($container->getDefinitions(), true);
|
||||
} finally {
|
||||
$this->container = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a value found in a definition tree.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param bool $isRoot
|
||||
*
|
||||
* @return mixed The processed value
|
||||
*/
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if (\is_array($value)) {
|
||||
foreach ($value as $k => $v) {
|
||||
if ($isRoot) {
|
||||
$this->currentId = $k;
|
||||
}
|
||||
if ($v !== $processedValue = $this->processValue($v, $isRoot)) {
|
||||
$value[$k] = $processedValue;
|
||||
}
|
||||
}
|
||||
} elseif ($value instanceof ArgumentInterface) {
|
||||
$value->setValues($this->processValue($value->getValues()));
|
||||
} elseif ($value instanceof Definition) {
|
||||
$value->setArguments($this->processValue($value->getArguments()));
|
||||
$value->setProperties($this->processValue($value->getProperties()));
|
||||
$value->setMethodCalls($this->processValue($value->getMethodCalls()));
|
||||
|
||||
$changes = $value->getChanges();
|
||||
if (isset($changes['factory'])) {
|
||||
$value->setFactory($this->processValue($value->getFactory()));
|
||||
}
|
||||
if (isset($changes['configurator'])) {
|
||||
$value->setConfigurator($this->processValue($value->getConfigurator()));
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Definition $definition
|
||||
* @param bool $required
|
||||
*
|
||||
* @return \ReflectionFunctionAbstract|null
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
protected function getConstructor(Definition $definition, $required)
|
||||
{
|
||||
if (\is_string($factory = $definition->getFactory())) {
|
||||
if (!\function_exists($factory)) {
|
||||
throw new RuntimeException(sprintf('Invalid service "%s": function "%s" does not exist.', $this->currentId, $factory));
|
||||
}
|
||||
$r = new \ReflectionFunction($factory);
|
||||
if (false !== $r->getFileName() && file_exists($r->getFileName())) {
|
||||
$this->container->fileExists($r->getFileName());
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
if ($factory) {
|
||||
list($class, $method) = $factory;
|
||||
if ($class instanceof Reference) {
|
||||
$class = $this->container->findDefinition((string) $class)->getClass();
|
||||
} elseif (null === $class) {
|
||||
$class = $definition->getClass();
|
||||
}
|
||||
if ('__construct' === $method) {
|
||||
throw new RuntimeException(sprintf('Invalid service "%s": "__construct()" cannot be used as a factory method.', $this->currentId));
|
||||
}
|
||||
|
||||
return $this->getReflectionMethod(new Definition($class), $method);
|
||||
}
|
||||
|
||||
$class = $definition->getClass();
|
||||
|
||||
try {
|
||||
if (!$r = $this->container->getReflectionClass($class)) {
|
||||
throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class));
|
||||
}
|
||||
} catch (\ReflectionException $e) {
|
||||
throw new RuntimeException(sprintf('Invalid service "%s": %s.', $this->currentId, lcfirst(rtrim($e->getMessage(), '.'))));
|
||||
}
|
||||
if (!$r = $r->getConstructor()) {
|
||||
if ($required) {
|
||||
throw new RuntimeException(sprintf('Invalid service "%s": class%s has no constructor.', $this->currentId, sprintf($class !== $this->currentId ? ' "%s"' : '', $class)));
|
||||
}
|
||||
} elseif (!$r->isPublic()) {
|
||||
throw new RuntimeException(sprintf('Invalid service "%s": %s must be public.', $this->currentId, sprintf($class !== $this->currentId ? 'constructor of class "%s"' : 'its constructor', $class)));
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Definition $definition
|
||||
* @param string $method
|
||||
*
|
||||
* @throws RuntimeException
|
||||
*
|
||||
* @return \ReflectionFunctionAbstract
|
||||
*/
|
||||
protected function getReflectionMethod(Definition $definition, $method)
|
||||
{
|
||||
if ('__construct' === $method) {
|
||||
return $this->getConstructor($definition, true);
|
||||
}
|
||||
|
||||
if (!$class = $definition->getClass()) {
|
||||
throw new RuntimeException(sprintf('Invalid service "%s": the class is not set.', $this->currentId));
|
||||
}
|
||||
|
||||
if (!$r = $this->container->getReflectionClass($class)) {
|
||||
throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class));
|
||||
}
|
||||
|
||||
if (!$r->hasMethod($method)) {
|
||||
throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" does not exist.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method));
|
||||
}
|
||||
|
||||
$r = $r->getMethod($method);
|
||||
if (!$r->isPublic()) {
|
||||
throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" must be public.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method));
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
}
|
186
vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php
vendored
Normal file
186
vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php
vendored
Normal file
|
@ -0,0 +1,186 @@
|
|||
<?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\Argument\ArgumentInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
use Symfony\Component\DependencyInjection\ExpressionLanguage;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\ExpressionLanguage\Expression;
|
||||
|
||||
/**
|
||||
* Run this pass before passes that need to know more about the relation of
|
||||
* your services.
|
||||
*
|
||||
* This class will populate the ServiceReferenceGraph with information. You can
|
||||
* retrieve the graph in other passes from the compiler.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements RepeatablePassInterface
|
||||
{
|
||||
private $graph;
|
||||
private $currentDefinition;
|
||||
private $onlyConstructorArguments;
|
||||
private $hasProxyDumper;
|
||||
private $lazy;
|
||||
private $expressionLanguage;
|
||||
|
||||
/**
|
||||
* @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
|
||||
*/
|
||||
public function __construct($onlyConstructorArguments = false, $hasProxyDumper = true)
|
||||
{
|
||||
$this->onlyConstructorArguments = (bool) $onlyConstructorArguments;
|
||||
$this->hasProxyDumper = (bool) $hasProxyDumper;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRepeatedPass(RepeatedPass $repeatedPass)
|
||||
{
|
||||
// no-op for BC
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a ContainerBuilder object to populate the service reference graph.
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->graph = $container->getCompiler()->getServiceReferenceGraph();
|
||||
$this->graph->clear();
|
||||
$this->lazy = false;
|
||||
|
||||
foreach ($container->getAliases() as $id => $alias) {
|
||||
$targetId = $this->getDefinitionId((string) $alias);
|
||||
$this->graph->connect($id, $alias, $targetId, $this->getDefinition($targetId), null);
|
||||
}
|
||||
|
||||
parent::process($container);
|
||||
}
|
||||
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
$lazy = $this->lazy;
|
||||
|
||||
if ($value instanceof ArgumentInterface) {
|
||||
$this->lazy = true;
|
||||
parent::processValue($value->getValues());
|
||||
$this->lazy = $lazy;
|
||||
|
||||
return $value;
|
||||
}
|
||||
if ($value instanceof Expression) {
|
||||
$this->getExpressionLanguage()->compile((string) $value, array('this' => 'container'));
|
||||
|
||||
return $value;
|
||||
}
|
||||
if ($value instanceof Reference) {
|
||||
$targetId = $this->getDefinitionId((string) $value);
|
||||
$targetDefinition = $this->getDefinition($targetId);
|
||||
|
||||
$this->graph->connect(
|
||||
$this->currentId,
|
||||
$this->currentDefinition,
|
||||
$targetId,
|
||||
$targetDefinition,
|
||||
$value,
|
||||
$this->lazy || ($this->hasProxyDumper && $targetDefinition && $targetDefinition->isLazy()),
|
||||
ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior()
|
||||
);
|
||||
|
||||
return $value;
|
||||
}
|
||||
if (!$value instanceof Definition) {
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
if ($isRoot) {
|
||||
if ($value->isSynthetic() || $value->isAbstract()) {
|
||||
return $value;
|
||||
}
|
||||
$this->currentDefinition = $value;
|
||||
} elseif ($this->currentDefinition === $value) {
|
||||
return $value;
|
||||
}
|
||||
$this->lazy = false;
|
||||
|
||||
$this->processValue($value->getFactory());
|
||||
$this->processValue($value->getArguments());
|
||||
|
||||
if (!$this->onlyConstructorArguments) {
|
||||
$this->processValue($value->getProperties());
|
||||
$this->processValue($value->getMethodCalls());
|
||||
$this->processValue($value->getConfigurator());
|
||||
}
|
||||
$this->lazy = $lazy;
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a service definition given the full name or an alias.
|
||||
*
|
||||
* @param string $id A full id or alias for a service definition
|
||||
*
|
||||
* @return Definition|null The definition related to the supplied id
|
||||
*/
|
||||
private function getDefinition($id)
|
||||
{
|
||||
return null === $id ? null : $this->container->getDefinition($id);
|
||||
}
|
||||
|
||||
private function getDefinitionId($id)
|
||||
{
|
||||
while ($this->container->hasAlias($id)) {
|
||||
$id = (string) $this->container->getAlias($id);
|
||||
}
|
||||
|
||||
if (!$this->container->hasDefinition($id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return $this->container->normalizeId($id);
|
||||
}
|
||||
|
||||
private function getExpressionLanguage()
|
||||
{
|
||||
if (null === $this->expressionLanguage) {
|
||||
if (!class_exists(ExpressionLanguage::class)) {
|
||||
throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
|
||||
}
|
||||
|
||||
$providers = $this->container->getExpressionLanguageProviders();
|
||||
$this->expressionLanguage = new ExpressionLanguage(null, $providers, function ($arg) {
|
||||
if ('""' === substr_replace($arg, '', 1, -1)) {
|
||||
$id = stripcslashes(substr($arg, 1, -1));
|
||||
$id = $this->getDefinitionId($id);
|
||||
|
||||
$this->graph->connect(
|
||||
$this->currentId,
|
||||
$this->currentDefinition,
|
||||
$id,
|
||||
$this->getDefinition($id)
|
||||
);
|
||||
}
|
||||
|
||||
return sprintf('$this->get(%s)', $arg);
|
||||
});
|
||||
}
|
||||
|
||||
return $this->expressionLanguage;
|
||||
}
|
||||
}
|
41
vendor/symfony/dependency-injection/Compiler/AutoAliasServicePass.php
vendored
Normal file
41
vendor/symfony/dependency-injection/Compiler/AutoAliasServicePass.php
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?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\Alias;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Sets a service to be an alias of another one, given a format pattern.
|
||||
*/
|
||||
class AutoAliasServicePass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
foreach ($container->findTaggedServiceIds('auto_alias') as $serviceId => $tags) {
|
||||
foreach ($tags as $tag) {
|
||||
if (!isset($tag['format'])) {
|
||||
throw new InvalidArgumentException(sprintf('Missing tag information "format" on auto_alias service "%s".', $serviceId));
|
||||
}
|
||||
|
||||
$aliasId = $container->getParameterBag()->resolveValue($tag['format']);
|
||||
if ($container->hasDefinition($aliasId) || $container->hasAlias($aliasId)) {
|
||||
$container->setAlias($serviceId, new Alias($aliasId, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
74
vendor/symfony/dependency-injection/Compiler/AutowireExceptionPass.php
vendored
Normal file
74
vendor/symfony/dependency-injection/Compiler/AutowireExceptionPass.php
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?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;
|
||||
|
||||
@trigger_error('The '.__NAMESPACE__.'\AutowireExceptionPass class is deprecated since Symfony 3.4 and will be removed in 4.0. Use the DefinitionErrorExceptionPass class instead.', E_USER_DEPRECATED);
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* Throws autowire exceptions from AutowirePass for definitions that still exist.
|
||||
*
|
||||
* @deprecated since version 3.4, will be removed in 4.0.
|
||||
*
|
||||
* @author Ryan Weaver <ryan@knpuniversity.com>
|
||||
*/
|
||||
class AutowireExceptionPass implements CompilerPassInterface
|
||||
{
|
||||
private $autowirePass;
|
||||
private $inlineServicePass;
|
||||
|
||||
public function __construct(AutowirePass $autowirePass, InlineServiceDefinitionsPass $inlineServicePass)
|
||||
{
|
||||
$this->autowirePass = $autowirePass;
|
||||
$this->inlineServicePass = $inlineServicePass;
|
||||
}
|
||||
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
// the pass should only be run once
|
||||
if (null === $this->autowirePass || null === $this->inlineServicePass) {
|
||||
return;
|
||||
}
|
||||
|
||||
$inlinedIds = $this->inlineServicePass->getInlinedServiceIds();
|
||||
$exceptions = $this->autowirePass->getAutowiringExceptions();
|
||||
|
||||
// free up references
|
||||
$this->autowirePass = null;
|
||||
$this->inlineServicePass = null;
|
||||
|
||||
foreach ($exceptions as $exception) {
|
||||
if ($this->doesServiceExistInTheContainer($exception->getServiceId(), $container, $inlinedIds)) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function doesServiceExistInTheContainer($serviceId, ContainerBuilder $container, array $inlinedIds)
|
||||
{
|
||||
if ($container->hasDefinition($serviceId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// was the service inlined? Of so, does its parent service exist?
|
||||
if (isset($inlinedIds[$serviceId])) {
|
||||
foreach ($inlinedIds[$serviceId] as $parentId) {
|
||||
if ($this->doesServiceExistInTheContainer($parentId, $container, $inlinedIds)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
559
vendor/symfony/dependency-injection/Compiler/AutowirePass.php
vendored
Normal file
559
vendor/symfony/dependency-injection/Compiler/AutowirePass.php
vendored
Normal file
|
@ -0,0 +1,559 @@
|
|||
<?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\Config\Resource\ClassExistenceResource;
|
||||
use Symfony\Component\DependencyInjection\Config\AutowireServiceResource;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper;
|
||||
use Symfony\Component\DependencyInjection\TypedReference;
|
||||
|
||||
/**
|
||||
* Inspects existing service definitions and wires the autowired ones using the type hints of their classes.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class AutowirePass extends AbstractRecursivePass
|
||||
{
|
||||
private $definedTypes = array();
|
||||
private $types;
|
||||
private $ambiguousServiceTypes;
|
||||
private $autowired = array();
|
||||
private $lastFailure;
|
||||
private $throwOnAutowiringException;
|
||||
private $autowiringExceptions = array();
|
||||
private $strictMode;
|
||||
|
||||
/**
|
||||
* @param bool $throwOnAutowireException Errors can be retrieved via Definition::getErrors()
|
||||
*/
|
||||
public function __construct($throwOnAutowireException = true)
|
||||
{
|
||||
$this->throwOnAutowiringException = $throwOnAutowireException;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since version 3.4, to be removed in 4.0.
|
||||
*
|
||||
* @return AutowiringFailedException[]
|
||||
*/
|
||||
public function getAutowiringExceptions()
|
||||
{
|
||||
@trigger_error('Calling AutowirePass::getAutowiringExceptions() is deprecated since Symfony 3.4 and will be removed in 4.0. Use Definition::getErrors() instead.', E_USER_DEPRECATED);
|
||||
|
||||
return $this->autowiringExceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
// clear out any possibly stored exceptions from before
|
||||
$this->autowiringExceptions = array();
|
||||
$this->strictMode = $container->hasParameter('container.autowiring.strict_mode') && $container->getParameter('container.autowiring.strict_mode');
|
||||
|
||||
try {
|
||||
parent::process($container);
|
||||
} finally {
|
||||
$this->definedTypes = array();
|
||||
$this->types = null;
|
||||
$this->ambiguousServiceTypes = null;
|
||||
$this->autowired = array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a resource to help know if this service has changed.
|
||||
*
|
||||
* @param \ReflectionClass $reflectionClass
|
||||
*
|
||||
* @return AutowireServiceResource
|
||||
*
|
||||
* @deprecated since version 3.3, to be removed in 4.0. Use ContainerBuilder::getReflectionClass() instead.
|
||||
*/
|
||||
public static function createResourceForClass(\ReflectionClass $reflectionClass)
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.'() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use ContainerBuilder::getReflectionClass() instead.', E_USER_DEPRECATED);
|
||||
|
||||
$metadata = array();
|
||||
|
||||
foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflectionMethod) {
|
||||
if (!$reflectionMethod->isStatic()) {
|
||||
$metadata[$reflectionMethod->name] = self::getResourceMetadataForMethod($reflectionMethod);
|
||||
}
|
||||
}
|
||||
|
||||
return new AutowireServiceResource($reflectionClass->name, $reflectionClass->getFileName(), $metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
try {
|
||||
return $this->doProcessValue($value, $isRoot);
|
||||
} catch (AutowiringFailedException $e) {
|
||||
if ($this->throwOnAutowiringException) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$this->autowiringExceptions[] = $e;
|
||||
$this->container->getDefinition($this->currentId)->addError($e->getMessage());
|
||||
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
}
|
||||
|
||||
private function doProcessValue($value, $isRoot = false)
|
||||
{
|
||||
if ($value instanceof TypedReference) {
|
||||
if ($ref = $this->getAutowiredReference($value, $value->getRequiringClass() ? sprintf('for "%s" in "%s"', $value->getType(), $value->getRequiringClass()) : '')) {
|
||||
return $ref;
|
||||
}
|
||||
$this->container->log($this, $this->createTypeNotFoundMessage($value, 'it'));
|
||||
}
|
||||
$value = parent::processValue($value, $isRoot);
|
||||
|
||||
if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) {
|
||||
return $value;
|
||||
}
|
||||
if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), false)) {
|
||||
$this->container->log($this, sprintf('Skipping service "%s": Class or interface "%s" cannot be loaded.', $this->currentId, $value->getClass()));
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
$methodCalls = $value->getMethodCalls();
|
||||
|
||||
try {
|
||||
$constructor = $this->getConstructor($value, false);
|
||||
} catch (RuntimeException $e) {
|
||||
throw new AutowiringFailedException($this->currentId, $e->getMessage(), 0, $e);
|
||||
}
|
||||
|
||||
if ($constructor) {
|
||||
array_unshift($methodCalls, array($constructor, $value->getArguments()));
|
||||
}
|
||||
|
||||
$methodCalls = $this->autowireCalls($reflectionClass, $methodCalls);
|
||||
|
||||
if ($constructor) {
|
||||
list(, $arguments) = array_shift($methodCalls);
|
||||
|
||||
if ($arguments !== $value->getArguments()) {
|
||||
$value->setArguments($arguments);
|
||||
}
|
||||
}
|
||||
|
||||
if ($methodCalls !== $value->getMethodCalls()) {
|
||||
$value->setMethodCalls($methodCalls);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \ReflectionClass $reflectionClass
|
||||
* @param array $methodCalls
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function autowireCalls(\ReflectionClass $reflectionClass, array $methodCalls)
|
||||
{
|
||||
foreach ($methodCalls as $i => $call) {
|
||||
list($method, $arguments) = $call;
|
||||
|
||||
if ($method instanceof \ReflectionFunctionAbstract) {
|
||||
$reflectionMethod = $method;
|
||||
} else {
|
||||
$reflectionMethod = $this->getReflectionMethod(new Definition($reflectionClass->name), $method);
|
||||
}
|
||||
|
||||
$arguments = $this->autowireMethod($reflectionMethod, $arguments);
|
||||
|
||||
if ($arguments !== $call[1]) {
|
||||
$methodCalls[$i][1] = $arguments;
|
||||
}
|
||||
}
|
||||
|
||||
return $methodCalls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Autowires the constructor or a method.
|
||||
*
|
||||
* @param \ReflectionFunctionAbstract $reflectionMethod
|
||||
* @param array $arguments
|
||||
*
|
||||
* @return array The autowired arguments
|
||||
*
|
||||
* @throws AutowiringFailedException
|
||||
*/
|
||||
private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, array $arguments)
|
||||
{
|
||||
$class = $reflectionMethod instanceof \ReflectionMethod ? $reflectionMethod->class : $this->currentId;
|
||||
$method = $reflectionMethod->name;
|
||||
$parameters = $reflectionMethod->getParameters();
|
||||
if (method_exists('ReflectionMethod', 'isVariadic') && $reflectionMethod->isVariadic()) {
|
||||
array_pop($parameters);
|
||||
}
|
||||
|
||||
foreach ($parameters as $index => $parameter) {
|
||||
if (array_key_exists($index, $arguments) && '' !== $arguments[$index]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, true);
|
||||
|
||||
if (!$type) {
|
||||
if (isset($arguments[$index])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// no default value? Then fail
|
||||
if (!$parameter->isDefaultValueAvailable()) {
|
||||
// For core classes, isDefaultValueAvailable() can
|
||||
// be false when isOptional() returns true. If the
|
||||
// argument *is* optional, allow it to be missing
|
||||
if ($parameter->isOptional()) {
|
||||
continue;
|
||||
}
|
||||
$type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, false);
|
||||
$type = $type ? sprintf('is type-hinted "%s"', $type) : 'has no type-hint';
|
||||
|
||||
throw new AutowiringFailedException($this->currentId, sprintf('Cannot autowire service "%s": argument "$%s" of method "%s()" %s, you should configure its value explicitly.', $this->currentId, $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method, $type));
|
||||
}
|
||||
|
||||
// specifically pass the default value
|
||||
$arguments[$index] = $parameter->getDefaultValue();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$value = $this->getAutowiredReference($ref = new TypedReference($type, $type, !$parameter->isOptional() ? $class : ''), 'for '.sprintf('argument "$%s" of method "%s()"', $parameter->name, $class.'::'.$method))) {
|
||||
$failureMessage = $this->createTypeNotFoundMessage($ref, sprintf('argument "$%s" of method "%s()"', $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method));
|
||||
|
||||
if ($parameter->isDefaultValueAvailable()) {
|
||||
$value = $parameter->getDefaultValue();
|
||||
} elseif (!$parameter->allowsNull()) {
|
||||
throw new AutowiringFailedException($this->currentId, $failureMessage);
|
||||
}
|
||||
$this->container->log($this, $failureMessage);
|
||||
}
|
||||
|
||||
$arguments[$index] = $value;
|
||||
}
|
||||
|
||||
if ($parameters && !isset($arguments[++$index])) {
|
||||
while (0 <= --$index) {
|
||||
$parameter = $parameters[$index];
|
||||
if (!$parameter->isDefaultValueAvailable() || $parameter->getDefaultValue() !== $arguments[$index]) {
|
||||
break;
|
||||
}
|
||||
unset($arguments[$index]);
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TypedReference|null A reference to the service matching the given type, if any
|
||||
*/
|
||||
private function getAutowiredReference(TypedReference $reference, $deprecationMessage)
|
||||
{
|
||||
$this->lastFailure = null;
|
||||
$type = $reference->getType();
|
||||
|
||||
if ($type !== $this->container->normalizeId($reference) || ($this->container->has($type) && !$this->container->findDefinition($type)->isAbstract())) {
|
||||
return $reference;
|
||||
}
|
||||
|
||||
if (null === $this->types) {
|
||||
$this->populateAvailableTypes($this->strictMode);
|
||||
}
|
||||
|
||||
if (isset($this->definedTypes[$type])) {
|
||||
return new TypedReference($this->types[$type], $type);
|
||||
}
|
||||
|
||||
if (!$this->strictMode && isset($this->types[$type])) {
|
||||
$message = 'Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won\'t be supported in version 4.0.';
|
||||
if ($aliasSuggestion = $this->getAliasesSuggestionForType($type = $reference->getType(), $deprecationMessage)) {
|
||||
$message .= ' '.$aliasSuggestion;
|
||||
} else {
|
||||
$message .= sprintf(' You should %s the "%s" service to "%s" instead.', isset($this->types[$this->types[$type]]) ? 'alias' : 'rename (or alias)', $this->types[$type], $type);
|
||||
}
|
||||
|
||||
@trigger_error($message, E_USER_DEPRECATED);
|
||||
|
||||
return new TypedReference($this->types[$type], $type);
|
||||
}
|
||||
|
||||
if (!$reference->canBeAutoregistered() || isset($this->types[$type]) || isset($this->ambiguousServiceTypes[$type])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($this->autowired[$type])) {
|
||||
return $this->autowired[$type] ? new TypedReference($this->autowired[$type], $type) : null;
|
||||
}
|
||||
|
||||
if (!$this->strictMode) {
|
||||
return $this->createAutowiredDefinition($type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the list of available types.
|
||||
*/
|
||||
private function populateAvailableTypes($onlyAutowiringTypes = false)
|
||||
{
|
||||
$this->types = array();
|
||||
if (!$onlyAutowiringTypes) {
|
||||
$this->ambiguousServiceTypes = array();
|
||||
}
|
||||
|
||||
foreach ($this->container->getDefinitions() as $id => $definition) {
|
||||
$this->populateAvailableType($id, $definition, $onlyAutowiringTypes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the list of available types for a given definition.
|
||||
*
|
||||
* @param string $id
|
||||
* @param Definition $definition
|
||||
*/
|
||||
private function populateAvailableType($id, Definition $definition, $onlyAutowiringTypes)
|
||||
{
|
||||
// Never use abstract services
|
||||
if ($definition->isAbstract()) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($definition->getAutowiringTypes(false) as $type) {
|
||||
$this->definedTypes[$type] = true;
|
||||
$this->types[$type] = $id;
|
||||
unset($this->ambiguousServiceTypes[$type]);
|
||||
}
|
||||
|
||||
if ($onlyAutowiringTypes) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (preg_match('/^\d+_[^~]++~[._a-zA-Z\d]{7}$/', $id) || $definition->isDeprecated() || !$reflectionClass = $this->container->getReflectionClass($definition->getClass(), false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($reflectionClass->getInterfaces() as $reflectionInterface) {
|
||||
$this->set($reflectionInterface->name, $id);
|
||||
}
|
||||
|
||||
do {
|
||||
$this->set($reflectionClass->name, $id);
|
||||
} while ($reflectionClass = $reflectionClass->getParentClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates a type and a service id if applicable.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $id
|
||||
*/
|
||||
private function set($type, $id)
|
||||
{
|
||||
if (isset($this->definedTypes[$type])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// is this already a type/class that is known to match multiple services?
|
||||
if (isset($this->ambiguousServiceTypes[$type])) {
|
||||
$this->ambiguousServiceTypes[$type][] = $id;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// check to make sure the type doesn't match multiple services
|
||||
if (!isset($this->types[$type]) || $this->types[$type] === $id) {
|
||||
$this->types[$type] = $id;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// keep an array of all services matching this type
|
||||
if (!isset($this->ambiguousServiceTypes[$type])) {
|
||||
$this->ambiguousServiceTypes[$type] = array($this->types[$type]);
|
||||
unset($this->types[$type]);
|
||||
}
|
||||
$this->ambiguousServiceTypes[$type][] = $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a definition for the type if possible or throws an exception.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return TypedReference|null A reference to the registered definition
|
||||
*/
|
||||
private function createAutowiredDefinition($type)
|
||||
{
|
||||
if (!($typeHint = $this->container->getReflectionClass($type, false)) || !$typeHint->isInstantiable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$currentId = $this->currentId;
|
||||
$this->currentId = $type;
|
||||
$this->autowired[$type] = $argumentId = sprintf('autowired.%s', $type);
|
||||
$argumentDefinition = new Definition($type);
|
||||
$argumentDefinition->setPublic(false);
|
||||
$argumentDefinition->setAutowired(true);
|
||||
|
||||
try {
|
||||
$originalThrowSetting = $this->throwOnAutowiringException;
|
||||
$this->throwOnAutowiringException = true;
|
||||
$this->processValue($argumentDefinition, true);
|
||||
$this->container->setDefinition($argumentId, $argumentDefinition);
|
||||
} catch (AutowiringFailedException $e) {
|
||||
$this->autowired[$type] = false;
|
||||
$this->lastFailure = $e->getMessage();
|
||||
$this->container->log($this, $this->lastFailure);
|
||||
|
||||
return;
|
||||
} finally {
|
||||
$this->throwOnAutowiringException = $originalThrowSetting;
|
||||
$this->currentId = $currentId;
|
||||
}
|
||||
|
||||
@trigger_error(sprintf('Relying on service auto-registration for type "%s" is deprecated since Symfony 3.4 and won\'t be supported in 4.0. Create a service named "%s" instead.', $type, $type), E_USER_DEPRECATED);
|
||||
|
||||
$this->container->log($this, sprintf('Type "%s" has been auto-registered for service "%s".', $type, $this->currentId));
|
||||
|
||||
return new TypedReference($argumentId, $type);
|
||||
}
|
||||
|
||||
private function createTypeNotFoundMessage(TypedReference $reference, $label)
|
||||
{
|
||||
if (!$r = $this->container->getReflectionClass($type = $reference->getType(), false)) {
|
||||
// either $type does not exist or a parent class does not exist
|
||||
try {
|
||||
$resource = new ClassExistenceResource($type, false);
|
||||
// isFresh() will explode ONLY if a parent class/trait does not exist
|
||||
$resource->isFresh(0);
|
||||
$parentMsg = false;
|
||||
} catch (\ReflectionException $e) {
|
||||
$parentMsg = $e->getMessage();
|
||||
}
|
||||
|
||||
$message = sprintf('has type "%s" but this class %s.', $type, $parentMsg ? sprintf('is missing a parent class (%s)', $parentMsg) : 'was not found');
|
||||
} else {
|
||||
$alternatives = $this->createTypeAlternatives($reference);
|
||||
$message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists';
|
||||
$message = sprintf('references %s "%s" but %s.%s', $r->isInterface() ? 'interface' : 'class', $type, $message, $alternatives);
|
||||
|
||||
if ($r->isInterface() && !$alternatives) {
|
||||
$message .= ' Did you create a class that implements this interface?';
|
||||
}
|
||||
}
|
||||
|
||||
$message = sprintf('Cannot autowire service "%s": %s %s', $this->currentId, $label, $message);
|
||||
|
||||
if (null !== $this->lastFailure) {
|
||||
$message = $this->lastFailure."\n".$message;
|
||||
$this->lastFailure = null;
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
private function createTypeAlternatives(TypedReference $reference)
|
||||
{
|
||||
// try suggesting available aliases first
|
||||
if ($message = $this->getAliasesSuggestionForType($type = $reference->getType())) {
|
||||
return ' '.$message;
|
||||
}
|
||||
if (null === $this->ambiguousServiceTypes) {
|
||||
$this->populateAvailableTypes();
|
||||
}
|
||||
|
||||
if (isset($this->ambiguousServiceTypes[$type])) {
|
||||
$message = sprintf('one of these existing services: "%s"', implode('", "', $this->ambiguousServiceTypes[$type]));
|
||||
} elseif (isset($this->types[$type])) {
|
||||
$message = sprintf('the existing "%s" service', $this->types[$type]);
|
||||
} elseif ($reference->getRequiringClass() && !$reference->canBeAutoregistered() && !$this->strictMode) {
|
||||
return ' It cannot be auto-registered because it is from a different root namespace.';
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
return sprintf(' You should maybe alias this %s to %s.', class_exists($type, false) ? 'class' : 'interface', $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since version 3.3, to be removed in 4.0.
|
||||
*/
|
||||
private static function getResourceMetadataForMethod(\ReflectionMethod $method)
|
||||
{
|
||||
$methodArgumentsMetadata = array();
|
||||
foreach ($method->getParameters() as $parameter) {
|
||||
try {
|
||||
$class = $parameter->getClass();
|
||||
} catch (\ReflectionException $e) {
|
||||
// type-hint is against a non-existent class
|
||||
$class = false;
|
||||
}
|
||||
|
||||
$isVariadic = method_exists($parameter, 'isVariadic') && $parameter->isVariadic();
|
||||
$methodArgumentsMetadata[] = array(
|
||||
'class' => $class,
|
||||
'isOptional' => $parameter->isOptional(),
|
||||
'defaultValue' => ($parameter->isOptional() && !$isVariadic) ? $parameter->getDefaultValue() : null,
|
||||
);
|
||||
}
|
||||
|
||||
return $methodArgumentsMetadata;
|
||||
}
|
||||
|
||||
private function getAliasesSuggestionForType($type, $extraContext = null)
|
||||
{
|
||||
$aliases = array();
|
||||
foreach (class_parents($type) + class_implements($type) as $parent) {
|
||||
if ($this->container->has($parent) && !$this->container->findDefinition($parent)->isAbstract()) {
|
||||
$aliases[] = $parent;
|
||||
}
|
||||
}
|
||||
|
||||
$extraContext = $extraContext ? ' '.$extraContext : '';
|
||||
if (1 < $len = \count($aliases)) {
|
||||
$message = sprintf('Try changing the type-hint%s to one of its parents: ', $extraContext);
|
||||
for ($i = 0, --$len; $i < $len; ++$i) {
|
||||
$message .= sprintf('%s "%s", ', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]);
|
||||
}
|
||||
$message .= sprintf('or %s "%s".', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]);
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
if ($aliases) {
|
||||
return sprintf('Try changing the type-hint%s to "%s" instead.', $extraContext, $aliases[0]);
|
||||
}
|
||||
}
|
||||
}
|
70
vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php
vendored
Normal file
70
vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?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\Definition;
|
||||
|
||||
/**
|
||||
* Looks for definitions with autowiring enabled and registers their corresponding "@required" methods as setters.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class AutowireRequiredMethodsPass extends AbstractRecursivePass
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
$value = parent::processValue($value, $isRoot);
|
||||
|
||||
if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) {
|
||||
return $value;
|
||||
}
|
||||
if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), false)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$alreadyCalledMethods = array();
|
||||
|
||||
foreach ($value->getMethodCalls() as list($method)) {
|
||||
$alreadyCalledMethods[strtolower($method)] = true;
|
||||
}
|
||||
|
||||
foreach ($reflectionClass->getMethods() as $reflectionMethod) {
|
||||
$r = $reflectionMethod;
|
||||
|
||||
if ($r->isConstructor() || isset($alreadyCalledMethods[strtolower($r->name)])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (false !== $doc = $r->getDocComment()) {
|
||||
if (false !== stripos($doc, '@required') && preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@required(?:\s|\*/$)#i', $doc)) {
|
||||
$value->addMethodCall($reflectionMethod->name);
|
||||
break;
|
||||
}
|
||||
if (false === stripos($doc, '@inheritdoc') || !preg_match('#(?:^/\*\*|\n\s*+\*)\s*+(?:\{@inheritdoc\}|@inheritdoc)(?:\s|\*/$)#i', $doc)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
try {
|
||||
$r = $r->getPrototype();
|
||||
} catch (\ReflectionException $e) {
|
||||
break; // method has no prototype
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
85
vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php
vendored
Normal file
85
vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?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\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* Checks if arguments of methods are properly configured.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class CheckArgumentsValidityPass extends AbstractRecursivePass
|
||||
{
|
||||
private $throwExceptions;
|
||||
|
||||
public function __construct($throwExceptions = true)
|
||||
{
|
||||
$this->throwExceptions = $throwExceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if (!$value instanceof Definition) {
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
foreach ($value->getArguments() as $k => $v) {
|
||||
if ($k !== $i++) {
|
||||
if (!\is_int($k)) {
|
||||
$msg = sprintf('Invalid constructor argument for service "%s": integer expected but found string "%s". Check your service definition.', $this->currentId, $k);
|
||||
$value->addError($msg);
|
||||
if ($this->throwExceptions) {
|
||||
throw new RuntimeException($msg);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$msg = sprintf('Invalid constructor argument %d for service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $this->currentId, $i);
|
||||
$value->addError($msg);
|
||||
if ($this->throwExceptions) {
|
||||
throw new RuntimeException($msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($value->getMethodCalls() as $methodCall) {
|
||||
$i = 0;
|
||||
foreach ($methodCall[1] as $k => $v) {
|
||||
if ($k !== $i++) {
|
||||
if (!\is_int($k)) {
|
||||
$msg = sprintf('Invalid argument for method call "%s" of service "%s": integer expected but found string "%s". Check your service definition.', $methodCall[0], $this->currentId, $k);
|
||||
$value->addError($msg);
|
||||
if ($this->throwExceptions) {
|
||||
throw new RuntimeException($msg);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$msg = sprintf('Invalid argument %d for method call "%s" of service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $methodCall[0], $this->currentId, $i);
|
||||
$value->addError($msg);
|
||||
if ($this->throwExceptions) {
|
||||
throw new RuntimeException($msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
78
vendor/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php
vendored
Normal file
78
vendor/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?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\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
|
||||
|
||||
/**
|
||||
* Checks your services for circular references.
|
||||
*
|
||||
* References from method calls are ignored since we might be able to resolve
|
||||
* these references depending on the order in which services are called.
|
||||
*
|
||||
* Circular reference from method calls will only be detected at run-time.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class CheckCircularReferencesPass implements CompilerPassInterface
|
||||
{
|
||||
private $currentPath;
|
||||
private $checkedNodes;
|
||||
|
||||
/**
|
||||
* Checks the ContainerBuilder object for circular references.
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$graph = $container->getCompiler()->getServiceReferenceGraph();
|
||||
|
||||
$this->checkedNodes = array();
|
||||
foreach ($graph->getNodes() as $id => $node) {
|
||||
$this->currentPath = array($id);
|
||||
|
||||
$this->checkOutEdges($node->getOutEdges());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for circular references.
|
||||
*
|
||||
* @param ServiceReferenceGraphEdge[] $edges An array of Edges
|
||||
*
|
||||
* @throws ServiceCircularReferenceException when a circular reference is found
|
||||
*/
|
||||
private function checkOutEdges(array $edges)
|
||||
{
|
||||
foreach ($edges as $edge) {
|
||||
$node = $edge->getDestNode();
|
||||
$id = $node->getId();
|
||||
|
||||
if (empty($this->checkedNodes[$id])) {
|
||||
// Don't check circular references for lazy edges
|
||||
if (!$node->getValue() || (!$edge->isLazy() && !$edge->isWeak())) {
|
||||
$searchKey = array_search($id, $this->currentPath);
|
||||
$this->currentPath[] = $id;
|
||||
|
||||
if (false !== $searchKey) {
|
||||
throw new ServiceCircularReferenceException($id, \array_slice($this->currentPath, $searchKey));
|
||||
}
|
||||
|
||||
$this->checkOutEdges($node->getOutEdges());
|
||||
}
|
||||
|
||||
$this->checkedNodes[$id] = true;
|
||||
array_pop($this->currentPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
100
vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php
vendored
Normal file
100
vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php
vendored
Normal file
|
@ -0,0 +1,100 @@
|
|||
<?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\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\EnvParameterException;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* This pass validates each definition individually only taking the information
|
||||
* into account which is contained in the definition itself.
|
||||
*
|
||||
* Later passes can rely on the following, and specifically do not need to
|
||||
* perform these checks themselves:
|
||||
*
|
||||
* - non synthetic, non abstract services always have a class set
|
||||
* - synthetic services are always public
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class CheckDefinitionValidityPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* Processes the ContainerBuilder to validate the Definition.
|
||||
*
|
||||
* @throws RuntimeException When the Definition is invalid
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
foreach ($container->getDefinitions() as $id => $definition) {
|
||||
// synthetic service is public
|
||||
if ($definition->isSynthetic() && !($definition->isPublic() || $definition->isPrivate())) {
|
||||
throw new RuntimeException(sprintf('A synthetic service ("%s") must be public.', $id));
|
||||
}
|
||||
|
||||
// non-synthetic, non-abstract service has class
|
||||
if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass()) {
|
||||
if ($definition->getFactory()) {
|
||||
throw new RuntimeException(sprintf('Please add the class to service "%s" even if it is constructed by a factory since we might need to add method calls based on compile-time checks.', $id));
|
||||
}
|
||||
if (class_exists($id) || interface_exists($id, false)) {
|
||||
if (0 === strpos($id, '\\') && 1 < substr_count($id, '\\')) {
|
||||
throw new RuntimeException(sprintf(
|
||||
'The definition for "%s" has no class attribute, and appears to reference a class or interface. '
|
||||
.'Please specify the class attribute explicitly or remove the leading backslash by renaming '
|
||||
.'the service to "%s" to get rid of this error.',
|
||||
$id, substr($id, 1)
|
||||
));
|
||||
}
|
||||
|
||||
throw new RuntimeException(sprintf(
|
||||
'The definition for "%s" has no class attribute, and appears to reference a '
|
||||
.'class or interface in the global namespace. Leaving out the "class" attribute '
|
||||
.'is only allowed for namespaced classes. Please specify the class attribute '
|
||||
.'explicitly to get rid of this error.',
|
||||
$id
|
||||
));
|
||||
}
|
||||
|
||||
throw new RuntimeException(sprintf('The definition for "%s" has no class. If you intend to inject this service dynamically at runtime, please mark it as synthetic=true. If this is an abstract definition solely used by child definitions, please add abstract=true, otherwise specify a class to get rid of this error.', $id));
|
||||
}
|
||||
|
||||
// tag attribute values must be scalars
|
||||
foreach ($definition->getTags() as $name => $tags) {
|
||||
foreach ($tags as $attributes) {
|
||||
foreach ($attributes as $attribute => $value) {
|
||||
if (!is_scalar($value) && null !== $value) {
|
||||
throw new RuntimeException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s".', $id, $name, $attribute));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($definition->isPublic() && !$definition->isPrivate()) {
|
||||
$resolvedId = $container->resolveEnvPlaceholders($id, null, $usedEnvs);
|
||||
if (null !== $usedEnvs) {
|
||||
throw new EnvParameterException(array($resolvedId), null, 'A service name ("%s") cannot contain dynamic values.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($container->getAliases() as $id => $alias) {
|
||||
if ($alias->isPublic() && !$alias->isPrivate()) {
|
||||
$resolvedId = $container->resolveEnvPlaceholders($id, null, $usedEnvs);
|
||||
if (null !== $usedEnvs) {
|
||||
throw new EnvParameterException(array($resolvedId), null, 'An alias name ("%s") cannot contain dynamic values.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
36
vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php
vendored
Normal file
36
vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?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\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Checks that all references are pointing to a valid service.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class CheckExceptionOnInvalidReferenceBehaviorPass extends AbstractRecursivePass
|
||||
{
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if (!$value instanceof Reference) {
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior() && !$this->container->has($id = (string) $value)) {
|
||||
throw new ServiceNotFoundException($id, $this->currentId);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
43
vendor/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php
vendored
Normal file
43
vendor/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?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\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Checks the validity of references.
|
||||
*
|
||||
* The following checks are performed by this pass:
|
||||
* - target definitions are not abstract
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class CheckReferenceValidityPass extends AbstractRecursivePass
|
||||
{
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if ($isRoot && $value instanceof Definition && ($value->isSynthetic() || $value->isAbstract())) {
|
||||
return $value;
|
||||
}
|
||||
if ($value instanceof Reference && $this->container->hasDefinition((string) $value)) {
|
||||
$targetDefinition = $this->container->getDefinition((string) $value);
|
||||
|
||||
if ($targetDefinition->isAbstract()) {
|
||||
throw new RuntimeException(sprintf('The definition "%s" has a reference to an abstract definition "%s". Abstract definitions cannot be the target of references.', $this->currentId, $value));
|
||||
}
|
||||
}
|
||||
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
}
|
166
vendor/symfony/dependency-injection/Compiler/Compiler.php
vendored
Normal file
166
vendor/symfony/dependency-injection/Compiler/Compiler.php
vendored
Normal file
|
@ -0,0 +1,166 @@
|
|||
<?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\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\EnvParameterException;
|
||||
|
||||
/**
|
||||
* This class is used to remove circular dependencies between individual passes.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class Compiler
|
||||
{
|
||||
private $passConfig;
|
||||
private $log = array();
|
||||
private $loggingFormatter;
|
||||
private $serviceReferenceGraph;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->passConfig = new PassConfig();
|
||||
$this->serviceReferenceGraph = new ServiceReferenceGraph();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the PassConfig.
|
||||
*
|
||||
* @return PassConfig The PassConfig instance
|
||||
*/
|
||||
public function getPassConfig()
|
||||
{
|
||||
return $this->passConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ServiceReferenceGraph.
|
||||
*
|
||||
* @return ServiceReferenceGraph The ServiceReferenceGraph instance
|
||||
*/
|
||||
public function getServiceReferenceGraph()
|
||||
{
|
||||
return $this->serviceReferenceGraph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the logging formatter which can be used by compilation passes.
|
||||
*
|
||||
* @return LoggingFormatter
|
||||
*
|
||||
* @deprecated since version 3.3, to be removed in 4.0. Use the ContainerBuilder::log() method instead.
|
||||
*/
|
||||
public function getLoggingFormatter()
|
||||
{
|
||||
if (null === $this->loggingFormatter) {
|
||||
@trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the ContainerBuilder::log() method instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->loggingFormatter = new LoggingFormatter();
|
||||
}
|
||||
|
||||
return $this->loggingFormatter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a pass to the PassConfig.
|
||||
*
|
||||
* @param CompilerPassInterface $pass A compiler pass
|
||||
* @param string $type The type of the pass
|
||||
* @param int $priority Used to sort the passes
|
||||
*/
|
||||
public function addPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/)
|
||||
{
|
||||
if (\func_num_args() >= 3) {
|
||||
$priority = func_get_arg(2);
|
||||
} else {
|
||||
if (__CLASS__ !== \get_class($this)) {
|
||||
$r = new \ReflectionMethod($this, __FUNCTION__);
|
||||
if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
|
||||
@trigger_error(sprintf('Method %s() will have a third `int $priority = 0` argument in version 4.0. Not defining it is deprecated since Symfony 3.2.', __METHOD__), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
|
||||
$priority = 0;
|
||||
}
|
||||
|
||||
$this->passConfig->addPass($pass, $type, $priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a log message.
|
||||
*
|
||||
* @param string $string The log message
|
||||
*
|
||||
* @deprecated since version 3.3, to be removed in 4.0. Use the ContainerBuilder::log() method instead.
|
||||
*/
|
||||
public function addLogMessage($string)
|
||||
{
|
||||
@trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the ContainerBuilder::log() method instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->log[] = $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @final
|
||||
*/
|
||||
public function log(CompilerPassInterface $pass, $message)
|
||||
{
|
||||
if (false !== strpos($message, "\n")) {
|
||||
$message = str_replace("\n", "\n".\get_class($pass).': ', trim($message));
|
||||
}
|
||||
|
||||
$this->log[] = \get_class($pass).': '.$message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the log.
|
||||
*
|
||||
* @return array Log array
|
||||
*/
|
||||
public function getLog()
|
||||
{
|
||||
return $this->log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the Compiler and process all Passes.
|
||||
*/
|
||||
public function compile(ContainerBuilder $container)
|
||||
{
|
||||
try {
|
||||
foreach ($this->passConfig->getPasses() as $pass) {
|
||||
$pass->process($container);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$usedEnvs = array();
|
||||
$prev = $e;
|
||||
|
||||
do {
|
||||
$msg = $prev->getMessage();
|
||||
|
||||
if ($msg !== $resolvedMsg = $container->resolveEnvPlaceholders($msg, null, $usedEnvs)) {
|
||||
$r = new \ReflectionProperty($prev, 'message');
|
||||
$r->setAccessible(true);
|
||||
$r->setValue($prev, $resolvedMsg);
|
||||
}
|
||||
} while ($prev = $prev->getPrevious());
|
||||
|
||||
if ($usedEnvs) {
|
||||
$e = new EnvParameterException($usedEnvs, $e);
|
||||
}
|
||||
|
||||
throw $e;
|
||||
} finally {
|
||||
$this->getServiceReferenceGraph()->clear();
|
||||
}
|
||||
}
|
||||
}
|
27
vendor/symfony/dependency-injection/Compiler/CompilerPassInterface.php
vendored
Normal file
27
vendor/symfony/dependency-injection/Compiler/CompilerPassInterface.php
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?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\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* Interface that must be implemented by compilation passes.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
interface CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* You can modify the container here before it is dumped to PHP code.
|
||||
*/
|
||||
public function process(ContainerBuilder $container);
|
||||
}
|
81
vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php
vendored
Normal file
81
vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
<?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\Alias;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* Overwrites a service but keeps the overridden one.
|
||||
*
|
||||
* @author Christophe Coevoet <stof@notk.org>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Diego Saint Esteben <diego@saintesteben.me>
|
||||
*/
|
||||
class DecoratorServicePass implements CompilerPassInterface
|
||||
{
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$definitions = new \SplPriorityQueue();
|
||||
$order = PHP_INT_MAX;
|
||||
|
||||
foreach ($container->getDefinitions() as $id => $definition) {
|
||||
if (!$decorated = $definition->getDecoratedService()) {
|
||||
continue;
|
||||
}
|
||||
$definitions->insert(array($id, $definition), array($decorated[2], --$order));
|
||||
}
|
||||
$decoratingDefinitions = array();
|
||||
|
||||
foreach ($definitions as list($id, $definition)) {
|
||||
list($inner, $renamedId) = $definition->getDecoratedService();
|
||||
|
||||
$definition->setDecoratedService(null);
|
||||
|
||||
if (!$renamedId) {
|
||||
$renamedId = $id.'.inner';
|
||||
}
|
||||
|
||||
// we create a new alias/service for the service we are replacing
|
||||
// to be able to reference it in the new one
|
||||
if ($container->hasAlias($inner)) {
|
||||
$alias = $container->getAlias($inner);
|
||||
$public = $alias->isPublic();
|
||||
$private = $alias->isPrivate();
|
||||
$container->setAlias($renamedId, new Alias($container->normalizeId($alias), false));
|
||||
} else {
|
||||
$decoratedDefinition = $container->getDefinition($inner);
|
||||
$public = $decoratedDefinition->isPublic();
|
||||
$private = $decoratedDefinition->isPrivate();
|
||||
$decoratedDefinition->setPublic(false);
|
||||
$container->setDefinition($renamedId, $decoratedDefinition);
|
||||
$decoratingDefinitions[$inner] = $decoratedDefinition;
|
||||
}
|
||||
|
||||
if (isset($decoratingDefinitions[$inner])) {
|
||||
$decoratingDefinition = $decoratingDefinitions[$inner];
|
||||
$definition->setTags(array_merge($decoratingDefinition->getTags(), $definition->getTags()));
|
||||
$autowiringTypes = $decoratingDefinition->getAutowiringTypes(false);
|
||||
if ($types = array_merge($autowiringTypes, $definition->getAutowiringTypes(false))) {
|
||||
$definition->setAutowiringTypes($types);
|
||||
}
|
||||
$decoratingDefinition->setTags(array());
|
||||
if ($autowiringTypes) {
|
||||
$decoratingDefinition->setAutowiringTypes(array());
|
||||
}
|
||||
$decoratingDefinitions[$inner] = $definition;
|
||||
}
|
||||
|
||||
$container->setAlias($inner, $id)->setPublic($public)->setPrivate($private);
|
||||
}
|
||||
}
|
||||
}
|
39
vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php
vendored
Normal file
39
vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?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\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* Throws an exception for any Definitions that have errors and still exist.
|
||||
*
|
||||
* @author Ryan Weaver <ryan@knpuniversity.com>
|
||||
*/
|
||||
class DefinitionErrorExceptionPass extends AbstractRecursivePass
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if (!$value instanceof Definition || empty($value->getErrors())) {
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
|
||||
// only show the first error so the user can focus on it
|
||||
$errors = $value->getErrors();
|
||||
$message = reset($errors);
|
||||
|
||||
throw new RuntimeException($message);
|
||||
}
|
||||
}
|
37
vendor/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php
vendored
Normal file
37
vendor/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?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\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* A pass to automatically process extensions if they implement
|
||||
* CompilerPassInterface.
|
||||
*
|
||||
* @author Wouter J <wouter@wouterj.nl>
|
||||
*/
|
||||
class ExtensionCompilerPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
foreach ($container->getExtensions() as $extension) {
|
||||
if (!$extension instanceof CompilerPassInterface) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$extension->process($container);
|
||||
}
|
||||
}
|
||||
}
|
112
vendor/symfony/dependency-injection/Compiler/FactoryReturnTypePass.php
vendored
Normal file
112
vendor/symfony/dependency-injection/Compiler/FactoryReturnTypePass.php
vendored
Normal file
|
@ -0,0 +1,112 @@
|
|||
<?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\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* @author Guilhem N. <egetick@gmail.com>
|
||||
*
|
||||
* @deprecated since version 3.3, to be removed in 4.0.
|
||||
*/
|
||||
class FactoryReturnTypePass implements CompilerPassInterface
|
||||
{
|
||||
private $resolveClassPass;
|
||||
|
||||
public function __construct(ResolveClassPass $resolveClassPass = null)
|
||||
{
|
||||
if (null === $resolveClassPass) {
|
||||
@trigger_error('The '.__CLASS__.' class is deprecated since Symfony 3.3 and will be removed in 4.0.', E_USER_DEPRECATED);
|
||||
}
|
||||
$this->resolveClassPass = $resolveClassPass;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
// works only since php 7.0 and hhvm 3.11
|
||||
if (!method_exists(\ReflectionMethod::class, 'getReturnType')) {
|
||||
return;
|
||||
}
|
||||
$resolveClassPassChanges = null !== $this->resolveClassPass ? $this->resolveClassPass->getChanges() : array();
|
||||
|
||||
foreach ($container->getDefinitions() as $id => $definition) {
|
||||
$this->updateDefinition($container, $id, $definition, $resolveClassPassChanges);
|
||||
}
|
||||
}
|
||||
|
||||
private function updateDefinition(ContainerBuilder $container, $id, Definition $definition, array $resolveClassPassChanges, array $previous = array())
|
||||
{
|
||||
// circular reference
|
||||
if (isset($previous[$id])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$factory = $definition->getFactory();
|
||||
if (null === $factory || (!isset($resolveClassPassChanges[$id]) && null !== $definition->getClass())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$class = null;
|
||||
if (\is_string($factory)) {
|
||||
try {
|
||||
$m = new \ReflectionFunction($factory);
|
||||
if (false !== $m->getFileName() && file_exists($m->getFileName())) {
|
||||
$container->fileExists($m->getFileName());
|
||||
}
|
||||
} catch (\ReflectionException $e) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if ($factory[0] instanceof Reference) {
|
||||
$previous[$id] = true;
|
||||
$factoryId = $container->normalizeId($factory[0]);
|
||||
$factoryDefinition = $container->findDefinition($factoryId);
|
||||
$this->updateDefinition($container, $factoryId, $factoryDefinition, $resolveClassPassChanges, $previous);
|
||||
$class = $factoryDefinition->getClass();
|
||||
} else {
|
||||
$class = $factory[0];
|
||||
}
|
||||
|
||||
if (!$m = $container->getReflectionClass($class, false)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
$m = $m->getMethod($factory[1]);
|
||||
} catch (\ReflectionException $e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$returnType = $m->getReturnType();
|
||||
if (null !== $returnType && !$returnType->isBuiltin()) {
|
||||
$returnType = $returnType instanceof \ReflectionNamedType ? $returnType->getName() : $returnType->__toString();
|
||||
if (null !== $class) {
|
||||
$declaringClass = $m->getDeclaringClass()->getName();
|
||||
if ('self' === strtolower($returnType)) {
|
||||
$returnType = $declaringClass;
|
||||
} elseif ('parent' === strtolower($returnType)) {
|
||||
$returnType = get_parent_class($declaringClass) ?: null;
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $returnType && (!isset($resolveClassPassChanges[$id]) || $returnType !== $resolveClassPassChanges[$id])) {
|
||||
@trigger_error(sprintf('Relying on its factory\'s return-type to define the class of service "%s" is deprecated since Symfony 3.3 and won\'t work in 4.0. Set the "class" attribute to "%s" on the service definition instead.', $id, $returnType), E_USER_DEPRECATED);
|
||||
}
|
||||
$definition->setClass($returnType);
|
||||
}
|
||||
}
|
||||
}
|
147
vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php
vendored
Normal file
147
vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php
vendored
Normal file
|
@ -0,0 +1,147 @@
|
|||
<?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\Argument\ArgumentInterface;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Inline service definitions where this is possible.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class InlineServiceDefinitionsPass extends AbstractRecursivePass implements RepeatablePassInterface
|
||||
{
|
||||
private $cloningIds = array();
|
||||
private $inlinedServiceIds = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRepeatedPass(RepeatedPass $repeatedPass)
|
||||
{
|
||||
// no-op for BC
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all services inlined by this pass.
|
||||
*
|
||||
* The key is the inlined service id and its value is the list of services it was inlined into.
|
||||
*
|
||||
* @deprecated since version 3.4, to be removed in 4.0.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getInlinedServiceIds()
|
||||
{
|
||||
@trigger_error('Calling InlineServiceDefinitionsPass::getInlinedServiceIds() is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED);
|
||||
|
||||
return $this->inlinedServiceIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if ($value instanceof ArgumentInterface) {
|
||||
// Reference found in ArgumentInterface::getValues() are not inlineable
|
||||
return $value;
|
||||
}
|
||||
|
||||
if ($value instanceof Definition && $this->cloningIds) {
|
||||
if ($value->isShared()) {
|
||||
return $value;
|
||||
}
|
||||
$value = clone $value;
|
||||
}
|
||||
|
||||
if (!$value instanceof Reference || !$this->container->hasDefinition($id = $this->container->normalizeId($value))) {
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
|
||||
$definition = $this->container->getDefinition($id);
|
||||
|
||||
if (!$this->isInlineableDefinition($id, $definition, $this->container->getCompiler()->getServiceReferenceGraph())) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$this->container->log($this, sprintf('Inlined service "%s" to "%s".', $id, $this->currentId));
|
||||
$this->inlinedServiceIds[$id][] = $this->currentId;
|
||||
|
||||
if ($definition->isShared()) {
|
||||
return $definition;
|
||||
}
|
||||
|
||||
if (isset($this->cloningIds[$id])) {
|
||||
$ids = array_keys($this->cloningIds);
|
||||
$ids[] = $id;
|
||||
|
||||
throw new ServiceCircularReferenceException($id, \array_slice($ids, array_search($id, $ids)));
|
||||
}
|
||||
|
||||
$this->cloningIds[$id] = true;
|
||||
try {
|
||||
return $this->processValue($definition);
|
||||
} finally {
|
||||
unset($this->cloningIds[$id]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the definition is inlineable.
|
||||
*
|
||||
* @return bool If the definition is inlineable
|
||||
*/
|
||||
private function isInlineableDefinition($id, Definition $definition, ServiceReferenceGraph $graph)
|
||||
{
|
||||
if ($definition->getErrors() || $definition->isDeprecated() || $definition->isLazy() || $definition->isSynthetic()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$definition->isShared()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($definition->isPublic() || $definition->isPrivate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$graph->hasNode($id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->currentId == $id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ids = array();
|
||||
foreach ($graph->getNode($id)->getInEdges() as $edge) {
|
||||
if ($edge->isWeak()) {
|
||||
return false;
|
||||
}
|
||||
$ids[] = $edge->getSourceNode()->getId();
|
||||
}
|
||||
|
||||
if (\count(array_unique($ids)) > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (\count($ids) > 1 && \is_array($factory = $definition->getFactory()) && ($factory[0] instanceof Reference || $factory[0] instanceof Definition)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !$ids || $this->container->getDefinition($ids[0])->isShared();
|
||||
}
|
||||
}
|
54
vendor/symfony/dependency-injection/Compiler/LoggingFormatter.php
vendored
Normal file
54
vendor/symfony/dependency-injection/Compiler/LoggingFormatter.php
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?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;
|
||||
|
||||
@trigger_error('The '.__NAMESPACE__.'\LoggingFormatter class is deprecated since Symfony 3.3 and will be removed in 4.0. Use the ContainerBuilder::log() method instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Used to format logging messages during the compilation.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*
|
||||
* @deprecated since version 3.3, to be removed in 4.0. Use the ContainerBuilder::log() method instead.
|
||||
*/
|
||||
class LoggingFormatter
|
||||
{
|
||||
public function formatRemoveService(CompilerPassInterface $pass, $id, $reason)
|
||||
{
|
||||
return $this->format($pass, sprintf('Removed service "%s"; reason: %s.', $id, $reason));
|
||||
}
|
||||
|
||||
public function formatInlineService(CompilerPassInterface $pass, $id, $target)
|
||||
{
|
||||
return $this->format($pass, sprintf('Inlined service "%s" to "%s".', $id, $target));
|
||||
}
|
||||
|
||||
public function formatUpdateReference(CompilerPassInterface $pass, $serviceId, $oldDestId, $newDestId)
|
||||
{
|
||||
return $this->format($pass, sprintf('Changed reference of service "%s" previously pointing to "%s" to "%s".', $serviceId, $oldDestId, $newDestId));
|
||||
}
|
||||
|
||||
public function formatResolveInheritance(CompilerPassInterface $pass, $childId, $parentId)
|
||||
{
|
||||
return $this->format($pass, sprintf('Resolving inheritance for "%s" (parent: %s).', $childId, $parentId));
|
||||
}
|
||||
|
||||
public function formatUnusedAutowiringPatterns(CompilerPassInterface $pass, $id, array $patterns)
|
||||
{
|
||||
return $this->format($pass, sprintf('Autowiring\'s patterns "%s" for service "%s" don\'t match any method.', implode('", "', $patterns), $id));
|
||||
}
|
||||
|
||||
public function format(CompilerPassInterface $pass, $message)
|
||||
{
|
||||
return sprintf('%s: %s', \get_class($pass), $message);
|
||||
}
|
||||
}
|
202
vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php
vendored
Normal file
202
vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php
vendored
Normal file
|
@ -0,0 +1,202 @@
|
|||
<?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\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\LogicException;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface;
|
||||
use Symfony\Component\DependencyInjection\Extension\Extension;
|
||||
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
|
||||
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
|
||||
/**
|
||||
* Merges extension configs into the container builder.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class MergeExtensionConfigurationPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$parameters = $container->getParameterBag()->all();
|
||||
$definitions = $container->getDefinitions();
|
||||
$aliases = $container->getAliases();
|
||||
$exprLangProviders = $container->getExpressionLanguageProviders();
|
||||
|
||||
foreach ($container->getExtensions() as $extension) {
|
||||
if ($extension instanceof PrependExtensionInterface) {
|
||||
$extension->prepend($container);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($container->getExtensions() as $name => $extension) {
|
||||
if (!$config = $container->getExtensionConfig($name)) {
|
||||
// this extension was not called
|
||||
continue;
|
||||
}
|
||||
$resolvingBag = $container->getParameterBag();
|
||||
if ($resolvingBag instanceof EnvPlaceholderParameterBag && $extension instanceof Extension) {
|
||||
// create a dedicated bag so that we can track env vars per-extension
|
||||
$resolvingBag = new MergeExtensionConfigurationParameterBag($resolvingBag);
|
||||
}
|
||||
$config = $resolvingBag->resolveValue($config);
|
||||
|
||||
try {
|
||||
$tmpContainer = new MergeExtensionConfigurationContainerBuilder($extension, $resolvingBag);
|
||||
$tmpContainer->setResourceTracking($container->isTrackingResources());
|
||||
$tmpContainer->addObjectResource($extension);
|
||||
if ($extension instanceof ConfigurationExtensionInterface && null !== $configuration = $extension->getConfiguration($config, $tmpContainer)) {
|
||||
$tmpContainer->addObjectResource($configuration);
|
||||
}
|
||||
|
||||
foreach ($exprLangProviders as $provider) {
|
||||
$tmpContainer->addExpressionLanguageProvider($provider);
|
||||
}
|
||||
|
||||
$extension->load($config, $tmpContainer);
|
||||
} catch (\Exception $e) {
|
||||
if ($resolvingBag instanceof MergeExtensionConfigurationParameterBag) {
|
||||
$container->getParameterBag()->mergeEnvPlaceholders($resolvingBag);
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if ($resolvingBag instanceof MergeExtensionConfigurationParameterBag) {
|
||||
// don't keep track of env vars that are *overridden* when configs are merged
|
||||
$resolvingBag->freezeAfterProcessing($extension, $tmpContainer);
|
||||
}
|
||||
|
||||
$container->merge($tmpContainer);
|
||||
$container->getParameterBag()->add($parameters);
|
||||
}
|
||||
|
||||
$container->addDefinitions($definitions);
|
||||
$container->addAliases($aliases);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class MergeExtensionConfigurationParameterBag extends EnvPlaceholderParameterBag
|
||||
{
|
||||
private $processedEnvPlaceholders;
|
||||
|
||||
public function __construct(parent $parameterBag)
|
||||
{
|
||||
parent::__construct($parameterBag->all());
|
||||
$this->mergeEnvPlaceholders($parameterBag);
|
||||
}
|
||||
|
||||
public function freezeAfterProcessing(Extension $extension, ContainerBuilder $container)
|
||||
{
|
||||
if (!$config = $extension->getProcessedConfigs()) {
|
||||
// Extension::processConfiguration() wasn't called, we cannot know how configs were merged
|
||||
return;
|
||||
}
|
||||
$this->processedEnvPlaceholders = array();
|
||||
|
||||
// serialize config and container to catch env vars nested in object graphs
|
||||
$config = serialize($config).serialize($container->getDefinitions()).serialize($container->getAliases()).serialize($container->getParameterBag()->all());
|
||||
|
||||
foreach (parent::getEnvPlaceholders() as $env => $placeholders) {
|
||||
foreach ($placeholders as $placeholder) {
|
||||
if (false !== stripos($config, $placeholder)) {
|
||||
$this->processedEnvPlaceholders[$env] = $placeholders;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getEnvPlaceholders()
|
||||
{
|
||||
return null !== $this->processedEnvPlaceholders ? $this->processedEnvPlaceholders : parent::getEnvPlaceholders();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A container builder preventing using methods that wouldn't have any effect from extensions.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class MergeExtensionConfigurationContainerBuilder extends ContainerBuilder
|
||||
{
|
||||
private $extensionClass;
|
||||
|
||||
public function __construct(ExtensionInterface $extension, ParameterBagInterface $parameterBag = null)
|
||||
{
|
||||
parent::__construct($parameterBag);
|
||||
|
||||
$this->extensionClass = \get_class($extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/)
|
||||
{
|
||||
throw new LogicException(sprintf('You cannot add compiler pass "%s" from extension "%s". Compiler passes must be registered before the container is compiled.', \get_class($pass), $this->extensionClass));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function registerExtension(ExtensionInterface $extension)
|
||||
{
|
||||
throw new LogicException(sprintf('You cannot register extension "%s" from "%s". Extensions must be registered before the container is compiled.', \get_class($extension), $this->extensionClass));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function compile($resolveEnvPlaceholders = false)
|
||||
{
|
||||
throw new LogicException(sprintf('Cannot compile the container in extension "%s".', $this->extensionClass));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolveEnvPlaceholders($value, $format = null, array &$usedEnvs = null)
|
||||
{
|
||||
if (true !== $format || !\is_string($value)) {
|
||||
return parent::resolveEnvPlaceholders($value, $format, $usedEnvs);
|
||||
}
|
||||
|
||||
$bag = $this->getParameterBag();
|
||||
$value = $bag->resolveValue($value);
|
||||
|
||||
foreach ($bag->getEnvPlaceholders() as $env => $placeholders) {
|
||||
if (false === strpos($env, ':')) {
|
||||
continue;
|
||||
}
|
||||
foreach ($placeholders as $placeholder) {
|
||||
if (false !== stripos($value, $placeholder)) {
|
||||
throw new RuntimeException(sprintf('Using a cast in "env(%s)" is incompatible with resolution at compile time in "%s". The logic in the extension should be moved to a compiler pass, or an env parameter with no cast should be used instead.', $env, $this->extensionClass));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return parent::resolveEnvPlaceholders($value, $format, $usedEnvs);
|
||||
}
|
||||
}
|
283
vendor/symfony/dependency-injection/Compiler/PassConfig.php
vendored
Normal file
283
vendor/symfony/dependency-injection/Compiler/PassConfig.php
vendored
Normal file
|
@ -0,0 +1,283 @@
|
|||
<?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\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Compiler Pass Configuration.
|
||||
*
|
||||
* This class has a default configuration embedded.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class PassConfig
|
||||
{
|
||||
const TYPE_AFTER_REMOVING = 'afterRemoving';
|
||||
const TYPE_BEFORE_OPTIMIZATION = 'beforeOptimization';
|
||||
const TYPE_BEFORE_REMOVING = 'beforeRemoving';
|
||||
const TYPE_OPTIMIZE = 'optimization';
|
||||
const TYPE_REMOVE = 'removing';
|
||||
|
||||
private $mergePass;
|
||||
private $afterRemovingPasses = array();
|
||||
private $beforeOptimizationPasses = array();
|
||||
private $beforeRemovingPasses = array();
|
||||
private $optimizationPasses;
|
||||
private $removingPasses;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->mergePass = new MergeExtensionConfigurationPass();
|
||||
|
||||
$this->beforeOptimizationPasses = array(
|
||||
100 => array(
|
||||
$resolveClassPass = new ResolveClassPass(),
|
||||
new ResolveInstanceofConditionalsPass(),
|
||||
new RegisterEnvVarProcessorsPass(),
|
||||
),
|
||||
-1000 => array(new ExtensionCompilerPass()),
|
||||
);
|
||||
|
||||
$this->optimizationPasses = array(array(
|
||||
new ResolveChildDefinitionsPass(),
|
||||
new ServiceLocatorTagPass(),
|
||||
new DecoratorServicePass(),
|
||||
new ResolveParameterPlaceHoldersPass(false),
|
||||
new ResolveFactoryClassPass(),
|
||||
new FactoryReturnTypePass($resolveClassPass),
|
||||
new CheckDefinitionValidityPass(),
|
||||
new RegisterServiceSubscribersPass(),
|
||||
new ResolveNamedArgumentsPass(),
|
||||
new AutowireRequiredMethodsPass(),
|
||||
new ResolveBindingsPass(),
|
||||
new AutowirePass(false),
|
||||
new ResolveTaggedIteratorArgumentPass(),
|
||||
new ResolveServiceSubscribersPass(),
|
||||
new ResolveReferencesToAliasesPass(),
|
||||
new ResolveInvalidReferencesPass(),
|
||||
new AnalyzeServiceReferencesPass(true),
|
||||
new CheckCircularReferencesPass(),
|
||||
new CheckReferenceValidityPass(),
|
||||
new CheckArgumentsValidityPass(false),
|
||||
));
|
||||
|
||||
$this->beforeRemovingPasses = array(
|
||||
-100 => array(
|
||||
new ResolvePrivatesPass(),
|
||||
),
|
||||
);
|
||||
|
||||
$this->removingPasses = array(array(
|
||||
new RemovePrivateAliasesPass(),
|
||||
new ReplaceAliasByActualDefinitionPass(),
|
||||
new RemoveAbstractDefinitionsPass(),
|
||||
new RepeatedPass(array(
|
||||
new AnalyzeServiceReferencesPass(),
|
||||
new InlineServiceDefinitionsPass(),
|
||||
new AnalyzeServiceReferencesPass(),
|
||||
new RemoveUnusedDefinitionsPass(),
|
||||
)),
|
||||
new DefinitionErrorExceptionPass(),
|
||||
new CheckExceptionOnInvalidReferenceBehaviorPass(),
|
||||
new ResolveHotPathPass(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all passes in order to be processed.
|
||||
*
|
||||
* @return CompilerPassInterface[]
|
||||
*/
|
||||
public function getPasses()
|
||||
{
|
||||
return array_merge(
|
||||
array($this->mergePass),
|
||||
$this->getBeforeOptimizationPasses(),
|
||||
$this->getOptimizationPasses(),
|
||||
$this->getBeforeRemovingPasses(),
|
||||
$this->getRemovingPasses(),
|
||||
$this->getAfterRemovingPasses()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a pass.
|
||||
*
|
||||
* @param CompilerPassInterface $pass A Compiler pass
|
||||
* @param string $type The pass type
|
||||
* @param int $priority Used to sort the passes
|
||||
*
|
||||
* @throws InvalidArgumentException when a pass type doesn't exist
|
||||
*/
|
||||
public function addPass(CompilerPassInterface $pass, $type = self::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/)
|
||||
{
|
||||
if (\func_num_args() >= 3) {
|
||||
$priority = func_get_arg(2);
|
||||
} else {
|
||||
if (__CLASS__ !== \get_class($this)) {
|
||||
$r = new \ReflectionMethod($this, __FUNCTION__);
|
||||
if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
|
||||
@trigger_error(sprintf('Method %s() will have a third `int $priority = 0` argument in version 4.0. Not defining it is deprecated since Symfony 3.2.', __METHOD__), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
|
||||
$priority = 0;
|
||||
}
|
||||
|
||||
$property = $type.'Passes';
|
||||
if (!isset($this->$property)) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid type "%s".', $type));
|
||||
}
|
||||
|
||||
$passes = &$this->$property;
|
||||
|
||||
if (!isset($passes[$priority])) {
|
||||
$passes[$priority] = array();
|
||||
}
|
||||
$passes[$priority][] = $pass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all passes for the AfterRemoving pass.
|
||||
*
|
||||
* @return CompilerPassInterface[]
|
||||
*/
|
||||
public function getAfterRemovingPasses()
|
||||
{
|
||||
return $this->sortPasses($this->afterRemovingPasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all passes for the BeforeOptimization pass.
|
||||
*
|
||||
* @return CompilerPassInterface[]
|
||||
*/
|
||||
public function getBeforeOptimizationPasses()
|
||||
{
|
||||
return $this->sortPasses($this->beforeOptimizationPasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all passes for the BeforeRemoving pass.
|
||||
*
|
||||
* @return CompilerPassInterface[]
|
||||
*/
|
||||
public function getBeforeRemovingPasses()
|
||||
{
|
||||
return $this->sortPasses($this->beforeRemovingPasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all passes for the Optimization pass.
|
||||
*
|
||||
* @return CompilerPassInterface[]
|
||||
*/
|
||||
public function getOptimizationPasses()
|
||||
{
|
||||
return $this->sortPasses($this->optimizationPasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all passes for the Removing pass.
|
||||
*
|
||||
* @return CompilerPassInterface[]
|
||||
*/
|
||||
public function getRemovingPasses()
|
||||
{
|
||||
return $this->sortPasses($this->removingPasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Merge pass.
|
||||
*
|
||||
* @return CompilerPassInterface
|
||||
*/
|
||||
public function getMergePass()
|
||||
{
|
||||
return $this->mergePass;
|
||||
}
|
||||
|
||||
public function setMergePass(CompilerPassInterface $pass)
|
||||
{
|
||||
$this->mergePass = $pass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the AfterRemoving passes.
|
||||
*
|
||||
* @param CompilerPassInterface[] $passes
|
||||
*/
|
||||
public function setAfterRemovingPasses(array $passes)
|
||||
{
|
||||
$this->afterRemovingPasses = array($passes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the BeforeOptimization passes.
|
||||
*
|
||||
* @param CompilerPassInterface[] $passes
|
||||
*/
|
||||
public function setBeforeOptimizationPasses(array $passes)
|
||||
{
|
||||
$this->beforeOptimizationPasses = array($passes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the BeforeRemoving passes.
|
||||
*
|
||||
* @param CompilerPassInterface[] $passes
|
||||
*/
|
||||
public function setBeforeRemovingPasses(array $passes)
|
||||
{
|
||||
$this->beforeRemovingPasses = array($passes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Optimization passes.
|
||||
*
|
||||
* @param CompilerPassInterface[] $passes
|
||||
*/
|
||||
public function setOptimizationPasses(array $passes)
|
||||
{
|
||||
$this->optimizationPasses = array($passes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Removing passes.
|
||||
*
|
||||
* @param CompilerPassInterface[] $passes
|
||||
*/
|
||||
public function setRemovingPasses(array $passes)
|
||||
{
|
||||
$this->removingPasses = array($passes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort passes by priority.
|
||||
*
|
||||
* @param array $passes CompilerPassInterface instances with their priority as key
|
||||
*
|
||||
* @return CompilerPassInterface[]
|
||||
*/
|
||||
private function sortPasses(array $passes)
|
||||
{
|
||||
if (0 === \count($passes)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
krsort($passes);
|
||||
|
||||
// Flatten the array
|
||||
return \call_user_func_array('array_merge', $passes);
|
||||
}
|
||||
}
|
55
vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php
vendored
Normal file
55
vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?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\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Trait that allows a generic method to find and sort service by priority option in the tag.
|
||||
*
|
||||
* @author Iltar van der Berg <kjarli@gmail.com>
|
||||
*/
|
||||
trait PriorityTaggedServiceTrait
|
||||
{
|
||||
/**
|
||||
* Finds all services with the given tag name and order them by their priority.
|
||||
*
|
||||
* The order of additions must be respected for services having the same priority,
|
||||
* and knowing that the \SplPriorityQueue class does not respect the FIFO method,
|
||||
* we should not use that class.
|
||||
*
|
||||
* @see https://bugs.php.net/bug.php?id=53710
|
||||
* @see https://bugs.php.net/bug.php?id=60926
|
||||
*
|
||||
* @param string $tagName
|
||||
* @param ContainerBuilder $container
|
||||
*
|
||||
* @return Reference[]
|
||||
*/
|
||||
private function findAndSortTaggedServices($tagName, ContainerBuilder $container)
|
||||
{
|
||||
$services = array();
|
||||
|
||||
foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $attributes) {
|
||||
$priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
|
||||
$services[$priority][] = new Reference($serviceId);
|
||||
}
|
||||
|
||||
if ($services) {
|
||||
krsort($services);
|
||||
$services = \call_user_func_array('array_merge', $services);
|
||||
}
|
||||
|
||||
return $services;
|
||||
}
|
||||
}
|
78
vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php
vendored
Normal file
78
vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?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\Argument\ServiceClosureArgument;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\EnvVarProcessor;
|
||||
use Symfony\Component\DependencyInjection\EnvVarProcessorInterface;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\ServiceLocator;
|
||||
|
||||
/**
|
||||
* Creates the container.env_var_processors_locator service.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class RegisterEnvVarProcessorsPass implements CompilerPassInterface
|
||||
{
|
||||
private static $allowedTypes = array('array', 'bool', 'float', 'int', 'string');
|
||||
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$bag = $container->getParameterBag();
|
||||
$types = array();
|
||||
$processors = array();
|
||||
foreach ($container->findTaggedServiceIds('container.env_var_processor') as $id => $tags) {
|
||||
if (!$r = $container->getReflectionClass($class = $container->getDefinition($id)->getClass())) {
|
||||
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
|
||||
} elseif (!$r->isSubclassOf(EnvVarProcessorInterface::class)) {
|
||||
throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EnvVarProcessorInterface::class));
|
||||
}
|
||||
foreach ($class::getProvidedTypes() as $prefix => $type) {
|
||||
$processors[$prefix] = new ServiceClosureArgument(new Reference($id));
|
||||
$types[$prefix] = self::validateProvidedTypes($type, $class);
|
||||
}
|
||||
}
|
||||
|
||||
if ($bag instanceof EnvPlaceholderParameterBag) {
|
||||
foreach (EnvVarProcessor::getProvidedTypes() as $prefix => $type) {
|
||||
if (!isset($types[$prefix])) {
|
||||
$types[$prefix] = self::validateProvidedTypes($type, EnvVarProcessor::class);
|
||||
}
|
||||
}
|
||||
$bag->setProvidedTypes($types);
|
||||
}
|
||||
|
||||
if ($processors) {
|
||||
$container->register('container.env_var_processors_locator', ServiceLocator::class)
|
||||
->setPublic(true)
|
||||
->setArguments(array($processors))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
private static function validateProvidedTypes($types, $class)
|
||||
{
|
||||
$types = explode('|', $types);
|
||||
|
||||
foreach ($types as $type) {
|
||||
if (!\in_array($type, self::$allowedTypes)) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid type "%s" returned by "%s::getProvidedTypes()", expected one of "%s".', $type, $class, implode('", "', self::$allowedTypes)));
|
||||
}
|
||||
}
|
||||
|
||||
return $types;
|
||||
}
|
||||
}
|
101
vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php
vendored
Normal file
101
vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
<?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\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
|
||||
use Symfony\Component\DependencyInjection\TypedReference;
|
||||
|
||||
/**
|
||||
* Compiler pass to register tagged services that require a service locator.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class RegisterServiceSubscribersPass extends AbstractRecursivePass
|
||||
{
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if (!$value instanceof Definition || $value->isAbstract() || $value->isSynthetic() || !$value->hasTag('container.service_subscriber')) {
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
|
||||
$serviceMap = array();
|
||||
$autowire = $value->isAutowired();
|
||||
|
||||
foreach ($value->getTag('container.service_subscriber') as $attributes) {
|
||||
if (!$attributes) {
|
||||
$autowire = true;
|
||||
continue;
|
||||
}
|
||||
ksort($attributes);
|
||||
if (array() !== array_diff(array_keys($attributes), array('id', 'key'))) {
|
||||
throw new InvalidArgumentException(sprintf('The "container.service_subscriber" tag accepts only the "key" and "id" attributes, "%s" given for service "%s".', implode('", "', array_keys($attributes)), $this->currentId));
|
||||
}
|
||||
if (!array_key_exists('id', $attributes)) {
|
||||
throw new InvalidArgumentException(sprintf('Missing "id" attribute on "container.service_subscriber" tag with key="%s" for service "%s".', $attributes['key'], $this->currentId));
|
||||
}
|
||||
if (!array_key_exists('key', $attributes)) {
|
||||
$attributes['key'] = $attributes['id'];
|
||||
}
|
||||
if (isset($serviceMap[$attributes['key']])) {
|
||||
continue;
|
||||
}
|
||||
$serviceMap[$attributes['key']] = new Reference($attributes['id']);
|
||||
}
|
||||
$class = $value->getClass();
|
||||
|
||||
if (!$r = $this->container->getReflectionClass($class)) {
|
||||
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $this->currentId));
|
||||
}
|
||||
if (!$r->isSubclassOf(ServiceSubscriberInterface::class)) {
|
||||
throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $this->currentId, ServiceSubscriberInterface::class));
|
||||
}
|
||||
$class = $r->name;
|
||||
|
||||
$subscriberMap = array();
|
||||
$declaringClass = (new \ReflectionMethod($class, 'getSubscribedServices'))->class;
|
||||
|
||||
foreach ($class::getSubscribedServices() as $key => $type) {
|
||||
if (!\is_string($type) || !preg_match('/^\??[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $type)) {
|
||||
throw new InvalidArgumentException(sprintf('"%s::getSubscribedServices()" must return valid PHP types for service "%s" key "%s", "%s" returned.', $class, $this->currentId, $key, \is_string($type) ? $type : \gettype($type)));
|
||||
}
|
||||
if ($optionalBehavior = '?' === $type[0]) {
|
||||
$type = substr($type, 1);
|
||||
$optionalBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
|
||||
}
|
||||
if (\is_int($key)) {
|
||||
$key = $type;
|
||||
}
|
||||
if (!isset($serviceMap[$key])) {
|
||||
if (!$autowire) {
|
||||
throw new InvalidArgumentException(sprintf('Service "%s" misses a "container.service_subscriber" tag with "key"/"id" attributes corresponding to entry "%s" as returned by "%s::getSubscribedServices()".', $this->currentId, $key, $class));
|
||||
}
|
||||
$serviceMap[$key] = new Reference($type);
|
||||
}
|
||||
|
||||
$subscriberMap[$key] = new TypedReference($this->container->normalizeId($serviceMap[$key]), $type, $declaringClass, $optionalBehavior ?: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
|
||||
unset($serviceMap[$key]);
|
||||
}
|
||||
|
||||
if ($serviceMap = array_keys($serviceMap)) {
|
||||
$message = sprintf(1 < \count($serviceMap) ? 'keys "%s" do' : 'key "%s" does', str_replace('%', '%%', implode('", "', $serviceMap)));
|
||||
throw new InvalidArgumentException(sprintf('Service %s not exist in the map returned by "%s::getSubscribedServices()" for service "%s".', $message, $class, $this->currentId));
|
||||
}
|
||||
|
||||
$value->addTag('container.service_subscriber.locator', array('id' => (string) ServiceLocatorTagPass::register($this->container, $subscriberMap, $this->currentId)));
|
||||
|
||||
return parent::processValue($value);
|
||||
}
|
||||
}
|
33
vendor/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php
vendored
Normal file
33
vendor/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?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\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* Removes abstract Definitions.
|
||||
*/
|
||||
class RemoveAbstractDefinitionsPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* Removes abstract definitions from the ContainerBuilder.
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
foreach ($container->getDefinitions() as $id => $definition) {
|
||||
if ($definition->isAbstract()) {
|
||||
$container->removeDefinition($id);
|
||||
$container->log($this, sprintf('Removed service "%s"; reason: abstract.', $id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
39
vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php
vendored
Normal file
39
vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?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\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* Remove private aliases from the container. They were only used to establish
|
||||
* dependencies between services, and these dependencies have been resolved in
|
||||
* one of the previous passes.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class RemovePrivateAliasesPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* Removes private aliases from the ContainerBuilder.
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
foreach ($container->getAliases() as $id => $alias) {
|
||||
if ($alias->isPublic() || $alias->isPrivate()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$container->removeAlias($id);
|
||||
$container->log($this, sprintf('Removed service "%s"; reason: private alias.', $id));
|
||||
}
|
||||
}
|
||||
}
|
85
vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php
vendored
Normal file
85
vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?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\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* Removes unused service definitions from the container.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class RemoveUnusedDefinitionsPass implements RepeatablePassInterface
|
||||
{
|
||||
private $repeatedPass;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRepeatedPass(RepeatedPass $repeatedPass)
|
||||
{
|
||||
$this->repeatedPass = $repeatedPass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the ContainerBuilder to remove unused definitions.
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$graph = $container->getCompiler()->getServiceReferenceGraph();
|
||||
|
||||
$hasChanged = false;
|
||||
foreach ($container->getDefinitions() as $id => $definition) {
|
||||
if ($definition->isPublic() || $definition->isPrivate()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($graph->hasNode($id)) {
|
||||
$edges = $graph->getNode($id)->getInEdges();
|
||||
$referencingAliases = array();
|
||||
$sourceIds = array();
|
||||
foreach ($edges as $edge) {
|
||||
if ($edge->isWeak()) {
|
||||
continue;
|
||||
}
|
||||
$node = $edge->getSourceNode();
|
||||
$sourceIds[] = $node->getId();
|
||||
|
||||
if ($node->isAlias()) {
|
||||
$referencingAliases[] = $node->getValue();
|
||||
}
|
||||
}
|
||||
$isReferenced = (\count(array_unique($sourceIds)) - \count($referencingAliases)) > 0;
|
||||
} else {
|
||||
$referencingAliases = array();
|
||||
$isReferenced = false;
|
||||
}
|
||||
|
||||
if (1 === \count($referencingAliases) && false === $isReferenced) {
|
||||
$container->setDefinition((string) reset($referencingAliases), $definition);
|
||||
$definition->setPublic(!$definition->isPrivate());
|
||||
$definition->setPrivate(reset($referencingAliases)->isPrivate());
|
||||
$container->removeDefinition($id);
|
||||
$container->log($this, sprintf('Removed service "%s"; reason: replaces alias %s.', $id, reset($referencingAliases)));
|
||||
} elseif (0 === \count($referencingAliases) && false === $isReferenced) {
|
||||
$container->removeDefinition($id);
|
||||
$container->resolveEnvPlaceholders(serialize($definition));
|
||||
$container->log($this, sprintf('Removed service "%s"; reason: unused.', $id));
|
||||
$hasChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($hasChanged) {
|
||||
$this->repeatedPass->setRepeat();
|
||||
}
|
||||
}
|
||||
}
|
23
vendor/symfony/dependency-injection/Compiler/RepeatablePassInterface.php
vendored
Normal file
23
vendor/symfony/dependency-injection/Compiler/RepeatablePassInterface.php
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?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;
|
||||
|
||||
/**
|
||||
* Interface that must be implemented by passes that are run as part of an
|
||||
* RepeatedPass.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
interface RepeatablePassInterface extends CompilerPassInterface
|
||||
{
|
||||
public function setRepeatedPass(RepeatedPass $repeatedPass);
|
||||
}
|
79
vendor/symfony/dependency-injection/Compiler/RepeatedPass.php
vendored
Normal file
79
vendor/symfony/dependency-injection/Compiler/RepeatedPass.php
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?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\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* A pass that might be run repeatedly.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class RepeatedPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $repeat = false;
|
||||
|
||||
private $passes;
|
||||
|
||||
/**
|
||||
* @param RepeatablePassInterface[] $passes An array of RepeatablePassInterface objects
|
||||
*
|
||||
* @throws InvalidArgumentException when the passes don't implement RepeatablePassInterface
|
||||
*/
|
||||
public function __construct(array $passes)
|
||||
{
|
||||
foreach ($passes as $pass) {
|
||||
if (!$pass instanceof RepeatablePassInterface) {
|
||||
throw new InvalidArgumentException('$passes must be an array of RepeatablePassInterface.');
|
||||
}
|
||||
|
||||
$pass->setRepeatedPass($this);
|
||||
}
|
||||
|
||||
$this->passes = $passes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the repeatable passes that run more than once.
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
do {
|
||||
$this->repeat = false;
|
||||
foreach ($this->passes as $pass) {
|
||||
$pass->process($container);
|
||||
}
|
||||
} while ($this->repeat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if the pass should repeat.
|
||||
*/
|
||||
public function setRepeat()
|
||||
{
|
||||
$this->repeat = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the passes.
|
||||
*
|
||||
* @return RepeatablePassInterface[] An array of RepeatablePassInterface objects
|
||||
*/
|
||||
public function getPasses()
|
||||
{
|
||||
return $this->passes;
|
||||
}
|
||||
}
|
89
vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php
vendored
Normal file
89
vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
<?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\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Replaces aliases with actual service definitions, effectively removing these
|
||||
* aliases.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class ReplaceAliasByActualDefinitionPass extends AbstractRecursivePass
|
||||
{
|
||||
private $replacements;
|
||||
|
||||
/**
|
||||
* Process the Container to replace aliases with service definitions.
|
||||
*
|
||||
* @throws InvalidArgumentException if the service definition does not exist
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
// First collect all alias targets that need to be replaced
|
||||
$seenAliasTargets = array();
|
||||
$replacements = array();
|
||||
foreach ($container->getAliases() as $definitionId => $target) {
|
||||
$targetId = $container->normalizeId($target);
|
||||
// Special case: leave this target alone
|
||||
if ('service_container' === $targetId) {
|
||||
continue;
|
||||
}
|
||||
// Check if target needs to be replaces
|
||||
if (isset($replacements[$targetId])) {
|
||||
$container->setAlias($definitionId, $replacements[$targetId])->setPublic($target->isPublic())->setPrivate($target->isPrivate());
|
||||
}
|
||||
// No need to process the same target twice
|
||||
if (isset($seenAliasTargets[$targetId])) {
|
||||
continue;
|
||||
}
|
||||
// Process new target
|
||||
$seenAliasTargets[$targetId] = true;
|
||||
try {
|
||||
$definition = $container->getDefinition($targetId);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with actual definition "%s".', $definitionId, $targetId), null, $e);
|
||||
}
|
||||
if ($definition->isPublic() || $definition->isPrivate()) {
|
||||
continue;
|
||||
}
|
||||
// Remove private definition and schedule for replacement
|
||||
$definition->setPublic(!$target->isPrivate());
|
||||
$definition->setPrivate($target->isPrivate());
|
||||
$container->setDefinition($definitionId, $definition);
|
||||
$container->removeDefinition($targetId);
|
||||
$replacements[$targetId] = $definitionId;
|
||||
}
|
||||
$this->replacements = $replacements;
|
||||
|
||||
parent::process($container);
|
||||
$this->replacements = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if ($value instanceof Reference && isset($this->replacements[$referenceId = $this->container->normalizeId($value)])) {
|
||||
// Perform the replacement
|
||||
$newId = $this->replacements[$referenceId];
|
||||
$value = new Reference($newId, $value->getInvalidBehavior());
|
||||
$this->container->log($this, sprintf('Changed reference of service "%s" previously pointing to "%s" to "%s".', $this->currentId, $referenceId, $newId));
|
||||
}
|
||||
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
}
|
171
vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php
vendored
Normal file
171
vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php
vendored
Normal file
|
@ -0,0 +1,171 @@
|
|||
<?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\Argument\BoundArgument;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\TypedReference;
|
||||
|
||||
/**
|
||||
* @author Guilhem Niot <guilhem.niot@gmail.com>
|
||||
*/
|
||||
class ResolveBindingsPass extends AbstractRecursivePass
|
||||
{
|
||||
private $usedBindings = array();
|
||||
private $unusedBindings = array();
|
||||
private $errorMessages = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
try {
|
||||
parent::process($container);
|
||||
|
||||
foreach ($this->unusedBindings as list($key, $serviceId)) {
|
||||
$message = sprintf('Unused binding "%s" in service "%s".', $key, $serviceId);
|
||||
if ($this->errorMessages) {
|
||||
$message .= sprintf("\nCould be related to%s:", 1 < \count($this->errorMessages) ? ' one of' : '');
|
||||
}
|
||||
foreach ($this->errorMessages as $m) {
|
||||
$message .= "\n - ".$m;
|
||||
}
|
||||
throw new InvalidArgumentException($message);
|
||||
}
|
||||
} finally {
|
||||
$this->usedBindings = array();
|
||||
$this->unusedBindings = array();
|
||||
$this->errorMessages = array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if ($value instanceof TypedReference && $value->getType() === $this->container->normalizeId($value)) {
|
||||
// Already checked
|
||||
$bindings = $this->container->getDefinition($this->currentId)->getBindings();
|
||||
|
||||
if (isset($bindings[$value->getType()])) {
|
||||
return $this->getBindingValue($bindings[$value->getType()]);
|
||||
}
|
||||
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
|
||||
if (!$value instanceof Definition || !$bindings = $value->getBindings()) {
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
|
||||
foreach ($bindings as $key => $binding) {
|
||||
list($bindingValue, $bindingId, $used) = $binding->getValues();
|
||||
if ($used) {
|
||||
$this->usedBindings[$bindingId] = true;
|
||||
unset($this->unusedBindings[$bindingId]);
|
||||
} elseif (!isset($this->usedBindings[$bindingId])) {
|
||||
$this->unusedBindings[$bindingId] = array($key, $this->currentId);
|
||||
}
|
||||
|
||||
if (isset($key[0]) && '$' === $key[0]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (null !== $bindingValue && !$bindingValue instanceof Reference && !$bindingValue instanceof Definition) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid value for binding key "%s" for service "%s": expected null, an instance of %s or an instance of %s, %s given.', $key, $this->currentId, Reference::class, Definition::class, \gettype($bindingValue)));
|
||||
}
|
||||
}
|
||||
|
||||
if ($value->isAbstract()) {
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
|
||||
$calls = $value->getMethodCalls();
|
||||
|
||||
try {
|
||||
if ($constructor = $this->getConstructor($value, false)) {
|
||||
$calls[] = array($constructor, $value->getArguments());
|
||||
}
|
||||
} catch (RuntimeException $e) {
|
||||
$this->errorMessages[] = $e->getMessage();
|
||||
$this->container->getDefinition($this->currentId)->addError($e->getMessage());
|
||||
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
|
||||
foreach ($calls as $i => $call) {
|
||||
list($method, $arguments) = $call;
|
||||
|
||||
if ($method instanceof \ReflectionFunctionAbstract) {
|
||||
$reflectionMethod = $method;
|
||||
} else {
|
||||
$reflectionMethod = $this->getReflectionMethod($value, $method);
|
||||
}
|
||||
|
||||
foreach ($reflectionMethod->getParameters() as $key => $parameter) {
|
||||
if (array_key_exists($key, $arguments) && '' !== $arguments[$key]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (array_key_exists('$'.$parameter->name, $bindings)) {
|
||||
$arguments[$key] = $this->getBindingValue($bindings['$'.$parameter->name]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$typeHint = ProxyHelper::getTypeHint($reflectionMethod, $parameter, true);
|
||||
|
||||
if (!isset($bindings[$typeHint])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$arguments[$key] = $this->getBindingValue($bindings[$typeHint]);
|
||||
}
|
||||
|
||||
if ($arguments !== $call[1]) {
|
||||
ksort($arguments);
|
||||
$calls[$i][1] = $arguments;
|
||||
}
|
||||
}
|
||||
|
||||
if ($constructor) {
|
||||
list(, $arguments) = array_pop($calls);
|
||||
|
||||
if ($arguments !== $value->getArguments()) {
|
||||
$value->setArguments($arguments);
|
||||
}
|
||||
}
|
||||
|
||||
if ($calls !== $value->getMethodCalls()) {
|
||||
$value->setMethodCalls($calls);
|
||||
}
|
||||
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
|
||||
private function getBindingValue(BoundArgument $binding)
|
||||
{
|
||||
list($bindingValue, $bindingId) = $binding->getValues();
|
||||
|
||||
$this->usedBindings[$bindingId] = true;
|
||||
unset($this->unusedBindings[$bindingId]);
|
||||
|
||||
return $bindingValue;
|
||||
}
|
||||
}
|
198
vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php
vendored
Normal file
198
vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php
vendored
Normal file
|
@ -0,0 +1,198 @@
|
|||
<?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;
|
||||
use Symfony\Component\DependencyInjection\Exception\ExceptionInterface;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
|
||||
|
||||
/**
|
||||
* This replaces all ChildDefinition instances with their equivalent fully
|
||||
* merged Definition instance.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class ResolveChildDefinitionsPass extends AbstractRecursivePass
|
||||
{
|
||||
private $currentPath;
|
||||
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if (!$value instanceof Definition) {
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
if ($isRoot) {
|
||||
// yes, we are specifically fetching the definition from the
|
||||
// container to ensure we are not operating on stale data
|
||||
$value = $this->container->getDefinition($this->currentId);
|
||||
}
|
||||
if ($value instanceof ChildDefinition) {
|
||||
$this->currentPath = array();
|
||||
$value = $this->resolveDefinition($value);
|
||||
if ($isRoot) {
|
||||
$this->container->setDefinition($this->currentId, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the definition.
|
||||
*
|
||||
* @return Definition
|
||||
*
|
||||
* @throws RuntimeException When the definition is invalid
|
||||
*/
|
||||
private function resolveDefinition(ChildDefinition $definition)
|
||||
{
|
||||
try {
|
||||
return $this->doResolveDefinition($definition);
|
||||
} catch (ServiceCircularReferenceException $e) {
|
||||
throw $e;
|
||||
} catch (ExceptionInterface $e) {
|
||||
$r = new \ReflectionProperty($e, 'message');
|
||||
$r->setAccessible(true);
|
||||
$r->setValue($e, sprintf('Service "%s": %s', $this->currentId, $e->getMessage()));
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
private function doResolveDefinition(ChildDefinition $definition)
|
||||
{
|
||||
if (!$this->container->has($parent = $definition->getParent())) {
|
||||
throw new RuntimeException(sprintf('Parent definition "%s" does not exist.', $parent));
|
||||
}
|
||||
|
||||
$searchKey = array_search($parent, $this->currentPath);
|
||||
$this->currentPath[] = $parent;
|
||||
|
||||
if (false !== $searchKey) {
|
||||
throw new ServiceCircularReferenceException($parent, \array_slice($this->currentPath, $searchKey));
|
||||
}
|
||||
|
||||
$parentDef = $this->container->findDefinition($parent);
|
||||
if ($parentDef instanceof ChildDefinition) {
|
||||
$id = $this->currentId;
|
||||
$this->currentId = $parent;
|
||||
$parentDef = $this->resolveDefinition($parentDef);
|
||||
$this->container->setDefinition($parent, $parentDef);
|
||||
$this->currentId = $id;
|
||||
}
|
||||
|
||||
$this->container->log($this, sprintf('Resolving inheritance for "%s" (parent: %s).', $this->currentId, $parent));
|
||||
$def = new Definition();
|
||||
|
||||
// merge in parent definition
|
||||
// purposely ignored attributes: abstract, shared, tags, autoconfigured
|
||||
$def->setClass($parentDef->getClass());
|
||||
$def->setArguments($parentDef->getArguments());
|
||||
$def->setMethodCalls($parentDef->getMethodCalls());
|
||||
$def->setProperties($parentDef->getProperties());
|
||||
if ($parentDef->getAutowiringTypes(false)) {
|
||||
$def->setAutowiringTypes($parentDef->getAutowiringTypes(false));
|
||||
}
|
||||
if ($parentDef->isDeprecated()) {
|
||||
$def->setDeprecated(true, $parentDef->getDeprecationMessage('%service_id%'));
|
||||
}
|
||||
$def->setFactory($parentDef->getFactory());
|
||||
$def->setConfigurator($parentDef->getConfigurator());
|
||||
$def->setFile($parentDef->getFile());
|
||||
$def->setPublic($parentDef->isPublic());
|
||||
$def->setLazy($parentDef->isLazy());
|
||||
$def->setAutowired($parentDef->isAutowired());
|
||||
$def->setChanges($parentDef->getChanges());
|
||||
|
||||
$def->setBindings($definition->getBindings() + $parentDef->getBindings());
|
||||
|
||||
// overwrite with values specified in the decorator
|
||||
$changes = $definition->getChanges();
|
||||
if (isset($changes['class'])) {
|
||||
$def->setClass($definition->getClass());
|
||||
}
|
||||
if (isset($changes['factory'])) {
|
||||
$def->setFactory($definition->getFactory());
|
||||
}
|
||||
if (isset($changes['configurator'])) {
|
||||
$def->setConfigurator($definition->getConfigurator());
|
||||
}
|
||||
if (isset($changes['file'])) {
|
||||
$def->setFile($definition->getFile());
|
||||
}
|
||||
if (isset($changes['public'])) {
|
||||
$def->setPublic($definition->isPublic());
|
||||
} else {
|
||||
$def->setPrivate($definition->isPrivate() || $parentDef->isPrivate());
|
||||
}
|
||||
if (isset($changes['lazy'])) {
|
||||
$def->setLazy($definition->isLazy());
|
||||
}
|
||||
if (isset($changes['deprecated'])) {
|
||||
$def->setDeprecated($definition->isDeprecated(), $definition->getDeprecationMessage('%service_id%'));
|
||||
}
|
||||
if (isset($changes['autowired'])) {
|
||||
$def->setAutowired($definition->isAutowired());
|
||||
}
|
||||
if (isset($changes['shared'])) {
|
||||
$def->setShared($definition->isShared());
|
||||
}
|
||||
if (isset($changes['decorated_service'])) {
|
||||
$decoratedService = $definition->getDecoratedService();
|
||||
if (null === $decoratedService) {
|
||||
$def->setDecoratedService($decoratedService);
|
||||
} else {
|
||||
$def->setDecoratedService($decoratedService[0], $decoratedService[1], $decoratedService[2]);
|
||||
}
|
||||
}
|
||||
|
||||
// merge arguments
|
||||
foreach ($definition->getArguments() as $k => $v) {
|
||||
if (is_numeric($k)) {
|
||||
$def->addArgument($v);
|
||||
} elseif (0 === strpos($k, 'index_')) {
|
||||
$def->replaceArgument((int) substr($k, \strlen('index_')), $v);
|
||||
} else {
|
||||
$def->setArgument($k, $v);
|
||||
}
|
||||
}
|
||||
|
||||
// merge properties
|
||||
foreach ($definition->getProperties() as $k => $v) {
|
||||
$def->setProperty($k, $v);
|
||||
}
|
||||
|
||||
// append method calls
|
||||
if ($calls = $definition->getMethodCalls()) {
|
||||
$def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
|
||||
}
|
||||
|
||||
// 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->setTags($definition->getTags());
|
||||
// autoconfigure is never taken from parent (on purpose)
|
||||
// and it's not legal on an instanceof
|
||||
$def->setAutoconfigured($definition->isAutoconfigured());
|
||||
|
||||
return $def;
|
||||
}
|
||||
}
|
||||
|
||||
class_alias(ResolveChildDefinitionsPass::class, ResolveDefinitionTemplatesPass::class);
|
56
vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php
vendored
Normal file
56
vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?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\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class ResolveClassPass implements CompilerPassInterface
|
||||
{
|
||||
private $changes = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
foreach ($container->getDefinitions() as $id => $definition) {
|
||||
if ($definition->isSynthetic() || null !== $definition->getClass()) {
|
||||
continue;
|
||||
}
|
||||
if (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $id)) {
|
||||
if ($definition instanceof ChildDefinition && !class_exists($id)) {
|
||||
throw new InvalidArgumentException(sprintf('Service definition "%s" has a parent but no class, and its name looks like a FQCN. Either the class is missing or you want to inherit it from the parent service. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.', $id));
|
||||
}
|
||||
$this->changes[strtolower($id)] = $id;
|
||||
$definition->setClass($id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @deprecated since 3.3, to be removed in 4.0.
|
||||
*/
|
||||
public function getChanges()
|
||||
{
|
||||
$changes = $this->changes;
|
||||
$this->changes = array();
|
||||
|
||||
return $changes;
|
||||
}
|
||||
}
|
29
vendor/symfony/dependency-injection/Compiler/ResolveDefinitionTemplatesPass.php
vendored
Normal file
29
vendor/symfony/dependency-injection/Compiler/ResolveDefinitionTemplatesPass.php
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?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;
|
||||
|
||||
@trigger_error('The '.__NAMESPACE__.'\ResolveDefinitionTemplatesPass class is deprecated since Symfony 3.4 and will be removed in 4.0. Use the ResolveChildDefinitionsPass class instead.', E_USER_DEPRECATED);
|
||||
|
||||
class_exists(ResolveChildDefinitionsPass::class);
|
||||
|
||||
if (false) {
|
||||
/**
|
||||
* This definition decorates another definition.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*
|
||||
* @deprecated The ResolveDefinitionTemplatesPass class is deprecated since version 3.4 and will be removed in 4.0. Use the ResolveChildDefinitionsPass class instead.
|
||||
*/
|
||||
class ResolveDefinitionTemplatesPass extends AbstractRecursivePass
|
||||
{
|
||||
}
|
||||
}
|
44
vendor/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php
vendored
Normal file
44
vendor/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?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\Definition;
|
||||
|
||||
/**
|
||||
* Replaces env var placeholders by their current values.
|
||||
*/
|
||||
class ResolveEnvPlaceholdersPass extends AbstractRecursivePass
|
||||
{
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if (\is_string($value)) {
|
||||
return $this->container->resolveEnvPlaceholders($value, true);
|
||||
}
|
||||
if ($value instanceof Definition) {
|
||||
$changes = $value->getChanges();
|
||||
if (isset($changes['class'])) {
|
||||
$value->setClass($this->container->resolveEnvPlaceholders($value->getClass(), true));
|
||||
}
|
||||
if (isset($changes['file'])) {
|
||||
$value->setFile($this->container->resolveEnvPlaceholders($value->getFile(), true));
|
||||
}
|
||||
}
|
||||
|
||||
$value = parent::processValue($value, $isRoot);
|
||||
|
||||
if ($value && \is_array($value) && !$isRoot) {
|
||||
$value = array_combine($this->container->resolveEnvPlaceholders(array_keys($value), true), $value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
38
vendor/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php
vendored
Normal file
38
vendor/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?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\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
|
||||
*/
|
||||
class ResolveFactoryClassPass extends AbstractRecursivePass
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if ($value instanceof Definition && \is_array($factory = $value->getFactory()) && null === $factory[0]) {
|
||||
if (null === $class = $value->getClass()) {
|
||||
throw new RuntimeException(sprintf('The "%s" service is defined to be created by a factory, but is missing the factory class. Did you forget to define the factory or service class?', $this->currentId));
|
||||
}
|
||||
|
||||
$factory[0] = $class;
|
||||
$value->setFactory($factory);
|
||||
}
|
||||
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
}
|
71
vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php
vendored
Normal file
71
vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
<?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\Argument\ArgumentInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Propagate "container.hot_path" tags to referenced services.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class ResolveHotPathPass extends AbstractRecursivePass
|
||||
{
|
||||
private $tagName;
|
||||
private $resolvedIds = array();
|
||||
|
||||
public function __construct($tagName = 'container.hot_path')
|
||||
{
|
||||
$this->tagName = $tagName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
try {
|
||||
parent::process($container);
|
||||
$container->getDefinition('service_container')->clearTag($this->tagName);
|
||||
} finally {
|
||||
$this->resolvedIds = array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if ($value instanceof ArgumentInterface) {
|
||||
return $value;
|
||||
}
|
||||
if ($value instanceof Definition && $isRoot && (isset($this->resolvedIds[$this->currentId]) || !$value->hasTag($this->tagName) || $value->isDeprecated())) {
|
||||
return $value->isDeprecated() ? $value->clearTag($this->tagName) : $value;
|
||||
}
|
||||
if ($value instanceof Reference && ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior() && $this->container->has($id = $this->container->normalizeId($value))) {
|
||||
$definition = $this->container->findDefinition($id);
|
||||
if (!$definition->hasTag($this->tagName) && !$definition->isDeprecated()) {
|
||||
$this->resolvedIds[$id] = true;
|
||||
$definition->addTag($this->tagName);
|
||||
parent::processValue($definition, false);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
}
|
155
vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php
vendored
Normal file
155
vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php
vendored
Normal file
|
@ -0,0 +1,155 @@
|
|||
<?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\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* Applies instanceof conditionals to definitions.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class ResolveInstanceofConditionalsPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
foreach ($container->getAutoconfiguredInstanceof() as $interface => $definition) {
|
||||
if ($definition->getArguments()) {
|
||||
throw new InvalidArgumentException(sprintf('Autoconfigured instanceof for type "%s" defines arguments but these are not supported and should be removed.', $interface));
|
||||
}
|
||||
if ($definition->getMethodCalls()) {
|
||||
throw new InvalidArgumentException(sprintf('Autoconfigured instanceof for type "%s" defines method calls but these are not supported and should be removed.', $interface));
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($container->getDefinitions() as $id => $definition) {
|
||||
if ($definition instanceof ChildDefinition) {
|
||||
// don't apply "instanceof" to children: it will be applied to their parent
|
||||
continue;
|
||||
}
|
||||
$container->setDefinition($id, $this->processDefinition($container, $id, $definition));
|
||||
}
|
||||
}
|
||||
|
||||
private function processDefinition(ContainerBuilder $container, $id, Definition $definition)
|
||||
{
|
||||
$instanceofConditionals = $definition->getInstanceofConditionals();
|
||||
$autoconfiguredInstanceof = $definition->isAutoconfigured() ? $container->getAutoconfiguredInstanceof() : array();
|
||||
if (!$instanceofConditionals && !$autoconfiguredInstanceof) {
|
||||
return $definition;
|
||||
}
|
||||
|
||||
if (!$class = $container->getParameterBag()->resolveValue($definition->getClass())) {
|
||||
return $definition;
|
||||
}
|
||||
|
||||
$conditionals = $this->mergeConditionals($autoconfiguredInstanceof, $instanceofConditionals, $container);
|
||||
|
||||
$definition->setInstanceofConditionals(array());
|
||||
$parent = $shared = null;
|
||||
$instanceofTags = array();
|
||||
|
||||
foreach ($conditionals as $interface => $instanceofDefs) {
|
||||
if ($interface !== $class && (!$container->getReflectionClass($class, false))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($interface !== $class && !is_subclass_of($class, $interface)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($instanceofDefs as $key => $instanceofDef) {
|
||||
/** @var ChildDefinition $instanceofDef */
|
||||
$instanceofDef = clone $instanceofDef;
|
||||
$instanceofDef->setAbstract(true)->setParent($parent ?: 'abstract.instanceof.'.$id);
|
||||
$parent = 'instanceof.'.$interface.'.'.$key.'.'.$id;
|
||||
$container->setDefinition($parent, $instanceofDef);
|
||||
$instanceofTags[] = $instanceofDef->getTags();
|
||||
$instanceofDef->setTags(array());
|
||||
|
||||
if (isset($instanceofDef->getChanges()['shared'])) {
|
||||
$shared = $instanceofDef->isShared();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($parent) {
|
||||
$bindings = $definition->getBindings();
|
||||
$abstract = $container->setDefinition('abstract.instanceof.'.$id, $definition);
|
||||
|
||||
// cast Definition to ChildDefinition
|
||||
$definition->setBindings(array());
|
||||
$definition = serialize($definition);
|
||||
$definition = substr_replace($definition, '53', 2, 2);
|
||||
$definition = substr_replace($definition, 'Child', 44, 0);
|
||||
$definition = unserialize($definition);
|
||||
$definition->setParent($parent);
|
||||
|
||||
if (null !== $shared && !isset($definition->getChanges()['shared'])) {
|
||||
$definition->setShared($shared);
|
||||
}
|
||||
|
||||
$i = \count($instanceofTags);
|
||||
while (0 <= --$i) {
|
||||
foreach ($instanceofTags[$i] as $k => $v) {
|
||||
foreach ($v as $v) {
|
||||
if ($definition->hasTag($k) && \in_array($v, $definition->getTag($k))) {
|
||||
continue;
|
||||
}
|
||||
$definition->addTag($k, $v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$definition->setBindings($bindings);
|
||||
|
||||
// reset fields with "merge" behavior
|
||||
$abstract
|
||||
->setBindings(array())
|
||||
->setArguments(array())
|
||||
->setMethodCalls(array())
|
||||
->setDecoratedService(null)
|
||||
->setTags(array())
|
||||
->setAbstract(true);
|
||||
}
|
||||
|
||||
return $definition;
|
||||
}
|
||||
|
||||
private function mergeConditionals(array $autoconfiguredInstanceof, array $instanceofConditionals, ContainerBuilder $container)
|
||||
{
|
||||
// make each value an array of ChildDefinition
|
||||
$conditionals = array_map(function ($childDef) { return array($childDef); }, $autoconfiguredInstanceof);
|
||||
|
||||
foreach ($instanceofConditionals as $interface => $instanceofDef) {
|
||||
// make sure the interface/class exists (but don't validate automaticInstanceofConditionals)
|
||||
if (!$container->getReflectionClass($interface)) {
|
||||
throw new RuntimeException(sprintf('"%s" is set as an "instanceof" conditional, but it does not exist.', $interface));
|
||||
}
|
||||
|
||||
if (!isset($autoconfiguredInstanceof[$interface])) {
|
||||
$conditionals[$interface] = array();
|
||||
}
|
||||
|
||||
$conditionals[$interface][] = $instanceofDef;
|
||||
}
|
||||
|
||||
return $conditionals;
|
||||
}
|
||||
}
|
111
vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php
vendored
Normal file
111
vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php
vendored
Normal file
|
@ -0,0 +1,111 @@
|
|||
<?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\Argument\ArgumentInterface;
|
||||
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Emulates the invalid behavior if the reference is not found within the
|
||||
* container.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class ResolveInvalidReferencesPass implements CompilerPassInterface
|
||||
{
|
||||
private $container;
|
||||
private $signalingException;
|
||||
|
||||
/**
|
||||
* Process the ContainerBuilder to resolve invalid references.
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->signalingException = new RuntimeException('Invalid reference.');
|
||||
|
||||
try {
|
||||
$this->processValue($container->getDefinitions(), 1);
|
||||
} finally {
|
||||
$this->container = $this->signalingException = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes arguments to determine invalid references.
|
||||
*
|
||||
* @throws RuntimeException When an invalid reference is found
|
||||
*/
|
||||
private function processValue($value, $rootLevel = 0, $level = 0)
|
||||
{
|
||||
if ($value instanceof ServiceClosureArgument) {
|
||||
$value->setValues($this->processValue($value->getValues(), 1, 1));
|
||||
} elseif ($value instanceof ArgumentInterface) {
|
||||
$value->setValues($this->processValue($value->getValues(), $rootLevel, 1 + $level));
|
||||
} elseif ($value instanceof Definition) {
|
||||
if ($value->isSynthetic() || $value->isAbstract()) {
|
||||
return $value;
|
||||
}
|
||||
$value->setArguments($this->processValue($value->getArguments(), 0));
|
||||
$value->setProperties($this->processValue($value->getProperties(), 1));
|
||||
$value->setMethodCalls($this->processValue($value->getMethodCalls(), 2));
|
||||
} elseif (\is_array($value)) {
|
||||
$i = 0;
|
||||
|
||||
foreach ($value as $k => $v) {
|
||||
try {
|
||||
if (false !== $i && $k !== $i++) {
|
||||
$i = false;
|
||||
}
|
||||
if ($v !== $processedValue = $this->processValue($v, $rootLevel, 1 + $level)) {
|
||||
$value[$k] = $processedValue;
|
||||
}
|
||||
} catch (RuntimeException $e) {
|
||||
if ($rootLevel < $level || ($rootLevel && !$level)) {
|
||||
unset($value[$k]);
|
||||
} elseif ($rootLevel) {
|
||||
throw $e;
|
||||
} else {
|
||||
$value[$k] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure numerically indexed arguments have sequential numeric keys.
|
||||
if (false !== $i) {
|
||||
$value = array_values($value);
|
||||
}
|
||||
} elseif ($value instanceof Reference) {
|
||||
if ($this->container->has($value)) {
|
||||
return $value;
|
||||
}
|
||||
$invalidBehavior = $value->getInvalidBehavior();
|
||||
|
||||
// resolve invalid behavior
|
||||
if (ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
|
||||
$value = null;
|
||||
} elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) {
|
||||
if (0 < $level || $rootLevel) {
|
||||
throw $this->signalingException;
|
||||
}
|
||||
$value = null;
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
101
vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php
vendored
Normal file
101
vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
<?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\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Resolves named arguments to their corresponding numeric index.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class ResolveNamedArgumentsPass extends AbstractRecursivePass
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if (!$value instanceof Definition) {
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
|
||||
$calls = $value->getMethodCalls();
|
||||
$calls[] = array('__construct', $value->getArguments());
|
||||
|
||||
foreach ($calls as $i => $call) {
|
||||
list($method, $arguments) = $call;
|
||||
$parameters = null;
|
||||
$resolvedArguments = array();
|
||||
|
||||
foreach ($arguments as $key => $argument) {
|
||||
if (\is_int($key)) {
|
||||
$resolvedArguments[$key] = $argument;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (null === $parameters) {
|
||||
$r = $this->getReflectionMethod($value, $method);
|
||||
$class = $r instanceof \ReflectionMethod ? $r->class : $this->currentId;
|
||||
$parameters = $r->getParameters();
|
||||
}
|
||||
|
||||
if (isset($key[0]) && '$' === $key[0]) {
|
||||
foreach ($parameters as $j => $p) {
|
||||
if ($key === '$'.$p->name) {
|
||||
$resolvedArguments[$j] = $argument;
|
||||
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException(sprintf('Invalid service "%s": method "%s()" has no argument named "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key));
|
||||
}
|
||||
|
||||
if (null !== $argument && !$argument instanceof Reference && !$argument instanceof Definition) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid service "%s": the value of argument "%s" of method "%s()" must be null, an instance of %s or an instance of %s, %s given.', $this->currentId, $key, $class !== $this->currentId ? $class.'::'.$method : $method, Reference::class, Definition::class, \gettype($argument)));
|
||||
}
|
||||
|
||||
$typeFound = false;
|
||||
foreach ($parameters as $j => $p) {
|
||||
if (!array_key_exists($j, $resolvedArguments) && ProxyHelper::getTypeHint($r, $p, true) === $key) {
|
||||
$resolvedArguments[$j] = $argument;
|
||||
$typeFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$typeFound) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid service "%s": method "%s()" has no argument type-hinted as "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key));
|
||||
}
|
||||
}
|
||||
|
||||
if ($resolvedArguments !== $call[1]) {
|
||||
ksort($resolvedArguments);
|
||||
$calls[$i][1] = $resolvedArguments;
|
||||
}
|
||||
}
|
||||
|
||||
list(, $arguments) = array_pop($calls);
|
||||
|
||||
if ($arguments !== $value->getArguments()) {
|
||||
$value->setArguments($arguments);
|
||||
}
|
||||
if ($calls !== $value->getMethodCalls()) {
|
||||
$value->setMethodCalls($calls);
|
||||
}
|
||||
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
}
|
87
vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php
vendored
Normal file
87
vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
<?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\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
|
||||
|
||||
/**
|
||||
* Resolves all parameter placeholders "%somevalue%" to their real values.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class ResolveParameterPlaceHoldersPass extends AbstractRecursivePass
|
||||
{
|
||||
private $bag;
|
||||
private $resolveArrays;
|
||||
|
||||
public function __construct($resolveArrays = true)
|
||||
{
|
||||
$this->resolveArrays = $resolveArrays;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @throws ParameterNotFoundException
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$this->bag = $container->getParameterBag();
|
||||
|
||||
try {
|
||||
parent::process($container);
|
||||
|
||||
$aliases = array();
|
||||
foreach ($container->getAliases() as $name => $target) {
|
||||
$this->currentId = $name;
|
||||
$aliases[$this->bag->resolveValue($name)] = $target;
|
||||
}
|
||||
$container->setAliases($aliases);
|
||||
} catch (ParameterNotFoundException $e) {
|
||||
$e->setSourceId($this->currentId);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$this->bag->resolve();
|
||||
$this->bag = null;
|
||||
}
|
||||
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if (\is_string($value)) {
|
||||
$v = $this->bag->resolveValue($value);
|
||||
|
||||
return $this->resolveArrays || !$v || !\is_array($v) ? $v : $value;
|
||||
}
|
||||
if ($value instanceof Definition) {
|
||||
$value->setBindings($this->processValue($value->getBindings()));
|
||||
$changes = $value->getChanges();
|
||||
if (isset($changes['class'])) {
|
||||
$value->setClass($this->bag->resolveValue($value->getClass()));
|
||||
}
|
||||
if (isset($changes['file'])) {
|
||||
$value->setFile($this->bag->resolveValue($value->getFile()));
|
||||
}
|
||||
}
|
||||
|
||||
$value = parent::processValue($value, $isRoot);
|
||||
|
||||
if ($value && \is_array($value)) {
|
||||
$value = array_combine($this->bag->resolveValue(array_keys($value)), $value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
40
vendor/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php
vendored
Normal file
40
vendor/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?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\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class ResolvePrivatesPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
foreach ($container->getDefinitions() as $id => $definition) {
|
||||
if ($definition->isPrivate()) {
|
||||
$definition->setPublic(false);
|
||||
$definition->setPrivate(true);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($container->getAliases() as $id => $alias) {
|
||||
if ($alias->isPrivate()) {
|
||||
$alias->setPublic(false);
|
||||
$alias->setPrivate(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
77
vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php
vendored
Normal file
77
vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?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\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Replaces all references to aliases with references to the actual service.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class ResolveReferencesToAliasesPass extends AbstractRecursivePass
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
parent::process($container);
|
||||
|
||||
foreach ($container->getAliases() as $id => $alias) {
|
||||
$aliasId = $container->normalizeId($alias);
|
||||
if ($aliasId !== $defId = $this->getDefinitionId($aliasId, $container)) {
|
||||
$container->setAlias($id, $defId)->setPublic($alias->isPublic())->setPrivate($alias->isPrivate());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if ($value instanceof Reference) {
|
||||
$defId = $this->getDefinitionId($id = $this->container->normalizeId($value), $this->container);
|
||||
|
||||
if ($defId !== $id) {
|
||||
return new Reference($defId, $value->getInvalidBehavior());
|
||||
}
|
||||
}
|
||||
|
||||
return parent::processValue($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves an alias into a definition id.
|
||||
*
|
||||
* @param string $id The definition or alias id to resolve
|
||||
* @param ContainerBuilder $container
|
||||
*
|
||||
* @return string The definition id with aliases resolved
|
||||
*/
|
||||
private function getDefinitionId($id, ContainerBuilder $container)
|
||||
{
|
||||
$seen = array();
|
||||
while ($container->hasAlias($id)) {
|
||||
if (isset($seen[$id])) {
|
||||
throw new ServiceCircularReferenceException($id, array_merge(array_keys($seen), array($id)));
|
||||
}
|
||||
$seen[$id] = true;
|
||||
$id = $container->normalizeId($container->getAlias($id));
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
}
|
51
vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php
vendored
Normal file
51
vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?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 Psr\Container\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* Compiler pass to inject their service locator to service subscribers.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class ResolveServiceSubscribersPass extends AbstractRecursivePass
|
||||
{
|
||||
private $serviceLocator;
|
||||
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if ($value instanceof Reference && $this->serviceLocator && ContainerInterface::class === $this->container->normalizeId($value)) {
|
||||
return new Reference($this->serviceLocator);
|
||||
}
|
||||
|
||||
if (!$value instanceof Definition) {
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
|
||||
$serviceLocator = $this->serviceLocator;
|
||||
$this->serviceLocator = null;
|
||||
|
||||
if ($value->hasTag('container.service_subscriber.locator')) {
|
||||
$this->serviceLocator = $value->getTag('container.service_subscriber.locator')[0]['id'];
|
||||
$value->clearTag('container.service_subscriber.locator');
|
||||
}
|
||||
|
||||
try {
|
||||
return parent::processValue($value);
|
||||
} finally {
|
||||
$this->serviceLocator = $serviceLocator;
|
||||
}
|
||||
}
|
||||
}
|
38
vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php
vendored
Normal file
38
vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?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\Argument\TaggedIteratorArgument;
|
||||
|
||||
/**
|
||||
* Resolves all TaggedIteratorArgument arguments.
|
||||
*
|
||||
* @author Roland Franssen <franssen.roland@gmail.com>
|
||||
*/
|
||||
class ResolveTaggedIteratorArgumentPass extends AbstractRecursivePass
|
||||
{
|
||||
use PriorityTaggedServiceTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if (!$value instanceof TaggedIteratorArgument) {
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
|
||||
$value->setValues($this->findAndSortTaggedServices($value->getTag(), $this->container));
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
112
vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php
vendored
Normal file
112
vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php
vendored
Normal file
|
@ -0,0 +1,112 @@
|
|||
<?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\Alias;
|
||||
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\ServiceLocator;
|
||||
|
||||
/**
|
||||
* Applies the "container.service_locator" tag by wrapping references into ServiceClosureArgument instances.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
final class ServiceLocatorTagPass extends AbstractRecursivePass
|
||||
{
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if (!$value instanceof Definition || !$value->hasTag('container.service_locator')) {
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
|
||||
if (!$value->getClass()) {
|
||||
$value->setClass(ServiceLocator::class);
|
||||
}
|
||||
|
||||
$arguments = $value->getArguments();
|
||||
if (!isset($arguments[0]) || !\is_array($arguments[0])) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": an array of references is expected as first argument when the "container.service_locator" tag is set.', $this->currentId));
|
||||
}
|
||||
|
||||
foreach ($arguments[0] as $k => $v) {
|
||||
if ($v instanceof ServiceClosureArgument) {
|
||||
continue;
|
||||
}
|
||||
if (!$v instanceof Reference) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": an array of references is expected as first argument when the "container.service_locator" tag is set, "%s" found for key "%s".', $this->currentId, \is_object($v) ? \get_class($v) : \gettype($v), $k));
|
||||
}
|
||||
$arguments[0][$k] = new ServiceClosureArgument($v);
|
||||
}
|
||||
ksort($arguments[0]);
|
||||
|
||||
$value->setArguments($arguments);
|
||||
|
||||
$id = 'service_locator.'.ContainerBuilder::hash($value);
|
||||
|
||||
if ($isRoot) {
|
||||
if ($id !== $this->currentId) {
|
||||
$this->container->setAlias($id, new Alias($this->currentId, false));
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
$this->container->setDefinition($id, $value->setPublic(false));
|
||||
|
||||
return new Reference($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerBuilder $container
|
||||
* @param Reference[] $refMap
|
||||
* @param string|null $callerId
|
||||
*
|
||||
* @return Reference
|
||||
*/
|
||||
public static function register(ContainerBuilder $container, array $refMap, $callerId = null)
|
||||
{
|
||||
foreach ($refMap as $id => $ref) {
|
||||
if (!$ref instanceof Reference) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid service locator definition: only services can be referenced, "%s" found for key "%s". Inject parameter values using constructors instead.', \is_object($ref) ? \get_class($ref) : \gettype($ref), $id));
|
||||
}
|
||||
$refMap[$id] = new ServiceClosureArgument($ref);
|
||||
}
|
||||
ksort($refMap);
|
||||
|
||||
$locator = (new Definition(ServiceLocator::class))
|
||||
->addArgument($refMap)
|
||||
->setPublic(false)
|
||||
->addTag('container.service_locator');
|
||||
|
||||
if (!$container->has($id = 'service_locator.'.ContainerBuilder::hash($locator))) {
|
||||
$container->setDefinition($id, $locator);
|
||||
}
|
||||
|
||||
if (null !== $callerId) {
|
||||
$locatorId = $id;
|
||||
// Locators are shared when they hold the exact same list of factories;
|
||||
// to have them specialized per consumer service, we use a cloning factory
|
||||
// to derivate customized instances from the prototype one.
|
||||
$container->register($id .= '.'.$callerId, ServiceLocator::class)
|
||||
->setPublic(false)
|
||||
->setFactory(array(new Reference($locatorId), 'withContext'))
|
||||
->addArgument($callerId)
|
||||
->addArgument(new Reference('service_container'));
|
||||
}
|
||||
|
||||
return new Reference($id);
|
||||
}
|
||||
}
|
128
vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php
vendored
Normal file
128
vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php
vendored
Normal file
|
@ -0,0 +1,128 @@
|
|||
<?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\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* This is a directed graph of your services.
|
||||
*
|
||||
* This information can be used by your compiler passes instead of collecting
|
||||
* it themselves which improves performance quite a lot.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*
|
||||
* @final since version 3.4
|
||||
*/
|
||||
class ServiceReferenceGraph
|
||||
{
|
||||
/**
|
||||
* @var ServiceReferenceGraphNode[]
|
||||
*/
|
||||
private $nodes = array();
|
||||
|
||||
/**
|
||||
* Checks if the graph has a specific node.
|
||||
*
|
||||
* @param string $id Id to check
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasNode($id)
|
||||
{
|
||||
return isset($this->nodes[$id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node by identifier.
|
||||
*
|
||||
* @param string $id The id to retrieve
|
||||
*
|
||||
* @return ServiceReferenceGraphNode
|
||||
*
|
||||
* @throws InvalidArgumentException if no node matches the supplied identifier
|
||||
*/
|
||||
public function getNode($id)
|
||||
{
|
||||
if (!isset($this->nodes[$id])) {
|
||||
throw new InvalidArgumentException(sprintf('There is no node with id "%s".', $id));
|
||||
}
|
||||
|
||||
return $this->nodes[$id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all nodes.
|
||||
*
|
||||
* @return ServiceReferenceGraphNode[]
|
||||
*/
|
||||
public function getNodes()
|
||||
{
|
||||
return $this->nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all nodes.
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
foreach ($this->nodes as $node) {
|
||||
$node->clear();
|
||||
}
|
||||
$this->nodes = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects 2 nodes together in the Graph.
|
||||
*
|
||||
* @param string $sourceId
|
||||
* @param mixed $sourceValue
|
||||
* @param string $destId
|
||||
* @param mixed $destValue
|
||||
* @param string $reference
|
||||
* @param bool $lazy
|
||||
* @param bool $weak
|
||||
*/
|
||||
public function connect($sourceId, $sourceValue, $destId, $destValue = null, $reference = null/*, bool $lazy = false, bool $weak = false*/)
|
||||
{
|
||||
$lazy = \func_num_args() >= 6 ? func_get_arg(5) : false;
|
||||
$weak = \func_num_args() >= 7 ? func_get_arg(6) : false;
|
||||
|
||||
if (null === $sourceId || null === $destId) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sourceNode = $this->createNode($sourceId, $sourceValue);
|
||||
$destNode = $this->createNode($destId, $destValue);
|
||||
$edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference, $lazy, $weak);
|
||||
|
||||
$sourceNode->addOutEdge($edge);
|
||||
$destNode->addInEdge($edge);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a graph node.
|
||||
*
|
||||
* @param string $id
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return ServiceReferenceGraphNode
|
||||
*/
|
||||
private function createNode($id, $value)
|
||||
{
|
||||
if (isset($this->nodes[$id]) && $this->nodes[$id]->getValue() === $value) {
|
||||
return $this->nodes[$id];
|
||||
}
|
||||
|
||||
return $this->nodes[$id] = new ServiceReferenceGraphNode($id, $value);
|
||||
}
|
||||
}
|
94
vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php
vendored
Normal file
94
vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
<?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;
|
||||
|
||||
/**
|
||||
* Represents an edge in your service graph.
|
||||
*
|
||||
* Value is typically a reference.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class ServiceReferenceGraphEdge
|
||||
{
|
||||
private $sourceNode;
|
||||
private $destNode;
|
||||
private $value;
|
||||
private $lazy;
|
||||
private $weak;
|
||||
|
||||
/**
|
||||
* @param ServiceReferenceGraphNode $sourceNode
|
||||
* @param ServiceReferenceGraphNode $destNode
|
||||
* @param mixed $value
|
||||
* @param bool $lazy
|
||||
* @param bool $weak
|
||||
*/
|
||||
public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null, $lazy = false, $weak = false)
|
||||
{
|
||||
$this->sourceNode = $sourceNode;
|
||||
$this->destNode = $destNode;
|
||||
$this->value = $value;
|
||||
$this->lazy = $lazy;
|
||||
$this->weak = $weak;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the edge.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the source node.
|
||||
*
|
||||
* @return ServiceReferenceGraphNode
|
||||
*/
|
||||
public function getSourceNode()
|
||||
{
|
||||
return $this->sourceNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the destination node.
|
||||
*
|
||||
* @return ServiceReferenceGraphNode
|
||||
*/
|
||||
public function getDestNode()
|
||||
{
|
||||
return $this->destNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the edge is lazy, meaning it's a dependency not requiring direct instantiation.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isLazy()
|
||||
{
|
||||
return $this->lazy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the edge is weak, meaning it shouldn't prevent removing the target service.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isWeak()
|
||||
{
|
||||
return $this->weak;
|
||||
}
|
||||
}
|
118
vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php
vendored
Normal file
118
vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php
vendored
Normal file
|
@ -0,0 +1,118 @@
|
|||
<?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\Alias;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
|
||||
/**
|
||||
* Represents a node in your service graph.
|
||||
*
|
||||
* Value is typically a definition, or an alias.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*/
|
||||
class ServiceReferenceGraphNode
|
||||
{
|
||||
private $id;
|
||||
private $inEdges = array();
|
||||
private $outEdges = array();
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* @param string $id The node identifier
|
||||
* @param mixed $value The node value
|
||||
*/
|
||||
public function __construct($id, $value)
|
||||
{
|
||||
$this->id = $id;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function addInEdge(ServiceReferenceGraphEdge $edge)
|
||||
{
|
||||
$this->inEdges[] = $edge;
|
||||
}
|
||||
|
||||
public function addOutEdge(ServiceReferenceGraphEdge $edge)
|
||||
{
|
||||
$this->outEdges[] = $edge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value of this node is an Alias.
|
||||
*
|
||||
* @return bool True if the value is an Alias instance
|
||||
*/
|
||||
public function isAlias()
|
||||
{
|
||||
return $this->value instanceof Alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value of this node is a Definition.
|
||||
*
|
||||
* @return bool True if the value is a Definition instance
|
||||
*/
|
||||
public function isDefinition()
|
||||
{
|
||||
return $this->value instanceof Definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identifier.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the in edges.
|
||||
*
|
||||
* @return array The in ServiceReferenceGraphEdge array
|
||||
*/
|
||||
public function getInEdges()
|
||||
{
|
||||
return $this->inEdges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the out edges.
|
||||
*
|
||||
* @return array The out ServiceReferenceGraphEdge array
|
||||
*/
|
||||
public function getOutEdges()
|
||||
{
|
||||
return $this->outEdges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of this Node.
|
||||
*
|
||||
* @return mixed The value
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all edges.
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->inEdges = $this->outEdges = array();
|
||||
}
|
||||
}
|
Reference in a new issue