[DI] Add "container.hot_path" tag to flag the hot path and inline related services
This commit is contained in:
parent
8cd2193a82
commit
f7cb559a06
@ -24,6 +24,7 @@ class UnusedTagsPass implements CompilerPassInterface
|
|||||||
private $whitelist = array(
|
private $whitelist = array(
|
||||||
'cache.pool.clearer',
|
'cache.pool.clearer',
|
||||||
'console.command',
|
'console.command',
|
||||||
|
'container.hot_path',
|
||||||
'container.service_locator',
|
'container.service_locator',
|
||||||
'container.service_subscriber',
|
'container.service_subscriber',
|
||||||
'controller.service_arguments',
|
'controller.service_arguments',
|
||||||
|
@ -43,6 +43,7 @@ use Symfony\Component\HttpKernel\DependencyInjection\FragmentRendererPass;
|
|||||||
use Symfony\Component\Form\DependencyInjection\FormPass;
|
use Symfony\Component\Form\DependencyInjection\FormPass;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||||
|
use Symfony\Component\HttpKernel\KernelEvents;
|
||||||
use Symfony\Component\Config\Resource\ClassExistenceResource;
|
use Symfony\Component\Config\Resource\ClassExistenceResource;
|
||||||
use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass;
|
use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass;
|
||||||
use Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass;
|
use Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass;
|
||||||
@ -83,6 +84,14 @@ class FrameworkBundle extends Bundle
|
|||||||
{
|
{
|
||||||
parent::build($container);
|
parent::build($container);
|
||||||
|
|
||||||
|
$hotPathEvents = array(
|
||||||
|
KernelEvents::REQUEST,
|
||||||
|
KernelEvents::CONTROLLER,
|
||||||
|
KernelEvents::CONTROLLER_ARGUMENTS,
|
||||||
|
KernelEvents::RESPONSE,
|
||||||
|
KernelEvents::FINISH_REQUEST,
|
||||||
|
);
|
||||||
|
|
||||||
$container->addCompilerPass(new LoggerPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32);
|
$container->addCompilerPass(new LoggerPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32);
|
||||||
$container->addCompilerPass(new RegisterControllerArgumentLocatorsPass());
|
$container->addCompilerPass(new RegisterControllerArgumentLocatorsPass());
|
||||||
$container->addCompilerPass(new RemoveEmptyControllerArgumentLocatorsPass(), PassConfig::TYPE_BEFORE_REMOVING);
|
$container->addCompilerPass(new RemoveEmptyControllerArgumentLocatorsPass(), PassConfig::TYPE_BEFORE_REMOVING);
|
||||||
@ -90,7 +99,7 @@ class FrameworkBundle extends Bundle
|
|||||||
$container->addCompilerPass(new ProfilerPass());
|
$container->addCompilerPass(new ProfilerPass());
|
||||||
// must be registered before removing private services as some might be listeners/subscribers
|
// must be registered before removing private services as some might be listeners/subscribers
|
||||||
// but as late as possible to get resolved parameters
|
// but as late as possible to get resolved parameters
|
||||||
$container->addCompilerPass(new RegisterListenersPass(), PassConfig::TYPE_BEFORE_REMOVING);
|
$container->addCompilerPass((new RegisterListenersPass())->setHotPathEvents($hotPathEvents), PassConfig::TYPE_BEFORE_REMOVING);
|
||||||
$container->addCompilerPass(new TemplatingPass());
|
$container->addCompilerPass(new TemplatingPass());
|
||||||
$this->addCompilerPassIfExists($container, AddConstraintValidatorsPass::class, PassConfig::TYPE_BEFORE_REMOVING);
|
$this->addCompilerPassIfExists($container, AddConstraintValidatorsPass::class, PassConfig::TYPE_BEFORE_REMOVING);
|
||||||
$container->addCompilerPass(new AddAnnotationsCachedReaderPass(), PassConfig::TYPE_BEFORE_REMOVING);
|
$container->addCompilerPass(new AddAnnotationsCachedReaderPass(), PassConfig::TYPE_BEFORE_REMOVING);
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
<service id="event_dispatcher" class="Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher" public="true">
|
<service id="event_dispatcher" class="Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher" public="true">
|
||||||
<argument type="service" id="service_container" />
|
<argument type="service" id="service_container" />
|
||||||
|
<tag name="container.hot_path" />
|
||||||
</service>
|
</service>
|
||||||
<service id="Symfony\Component\EventDispatcher\EventDispatcherInterface" alias="event_dispatcher" />
|
<service id="Symfony\Component\EventDispatcher\EventDispatcherInterface" alias="event_dispatcher" />
|
||||||
|
|
||||||
@ -17,6 +18,7 @@
|
|||||||
<argument type="service" id="controller_resolver" />
|
<argument type="service" id="controller_resolver" />
|
||||||
<argument type="service" id="request_stack" />
|
<argument type="service" id="request_stack" />
|
||||||
<argument type="service" id="argument_resolver" />
|
<argument type="service" id="argument_resolver" />
|
||||||
|
<tag name="container.hot_path" />
|
||||||
</service>
|
</service>
|
||||||
<service id="Symfony\Component\HttpKernel\HttpKernelInterface" alias="http_kernel" />
|
<service id="Symfony\Component\HttpKernel\HttpKernelInterface" alias="http_kernel" />
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
"symfony/class-loader": "~3.2",
|
"symfony/class-loader": "~3.2",
|
||||||
"symfony/dependency-injection": "~3.4|~4.0",
|
"symfony/dependency-injection": "~3.4|~4.0",
|
||||||
"symfony/config": "~3.4|~4.0",
|
"symfony/config": "~3.4|~4.0",
|
||||||
"symfony/event-dispatcher": "^3.3.1|~4.0",
|
"symfony/event-dispatcher": "^3.4-beta4|~4.0-beta4",
|
||||||
"symfony/http-foundation": "^3.3.11|~4.0",
|
"symfony/http-foundation": "^3.3.11|~4.0",
|
||||||
"symfony/http-kernel": "~3.4|~4.0",
|
"symfony/http-kernel": "~3.4|~4.0",
|
||||||
"symfony/polyfill-mbstring": "~1.0",
|
"symfony/polyfill-mbstring": "~1.0",
|
||||||
|
@ -89,6 +89,7 @@ class PassConfig
|
|||||||
)),
|
)),
|
||||||
new DefinitionErrorExceptionPass(),
|
new DefinitionErrorExceptionPass(),
|
||||||
new CheckExceptionOnInvalidReferenceBehaviorPass(),
|
new CheckExceptionOnInvalidReferenceBehaviorPass(),
|
||||||
|
new ResolveHotPathPass(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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))) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
if ($value instanceof Reference && ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior() && $this->container->has($id = (string) $value)) {
|
||||||
|
$definition = $this->container->findDefinition($id);
|
||||||
|
if (!$definition->hasTag($this->tagName)) {
|
||||||
|
$this->resolvedIds[$id] = true;
|
||||||
|
$definition->addTag($this->tagName);
|
||||||
|
parent::processValue($definition, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::processValue($value, $isRoot);
|
||||||
|
}
|
||||||
|
}
|
@ -63,6 +63,9 @@ class PhpDumper extends Dumper
|
|||||||
private $usedMethodNames;
|
private $usedMethodNames;
|
||||||
private $namespace;
|
private $namespace;
|
||||||
private $asFiles;
|
private $asFiles;
|
||||||
|
private $hotPathTag;
|
||||||
|
private $inlineRequires;
|
||||||
|
private $inlinedRequires = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ProxyDumper
|
* @var ProxyDumper
|
||||||
@ -108,16 +111,21 @@ class PhpDumper extends Dumper
|
|||||||
public function dump(array $options = array())
|
public function dump(array $options = array())
|
||||||
{
|
{
|
||||||
$this->targetDirRegex = null;
|
$this->targetDirRegex = null;
|
||||||
|
$this->inlinedRequires = array();
|
||||||
$options = array_merge(array(
|
$options = array_merge(array(
|
||||||
'class' => 'ProjectServiceContainer',
|
'class' => 'ProjectServiceContainer',
|
||||||
'base_class' => 'Container',
|
'base_class' => 'Container',
|
||||||
'namespace' => '',
|
'namespace' => '',
|
||||||
'as_files' => false,
|
'as_files' => false,
|
||||||
'debug' => true,
|
'debug' => true,
|
||||||
|
'hot_path_tag' => null,
|
||||||
|
'inline_class_loader_parameter' => 'container.dumper.inline_class_loader',
|
||||||
), $options);
|
), $options);
|
||||||
|
|
||||||
$this->namespace = $options['namespace'];
|
$this->namespace = $options['namespace'];
|
||||||
$this->asFiles = $options['as_files'];
|
$this->asFiles = $options['as_files'];
|
||||||
|
$this->hotPathTag = $options['hot_path_tag'];
|
||||||
|
$this->inlineRequires = $this->container->hasParameter($options['inline_class_loader_parameter']) && $this->container->getParameter($options['inline_class_loader_parameter']);
|
||||||
$this->initializeMethodNamesMap($options['base_class']);
|
$this->initializeMethodNamesMap($options['base_class']);
|
||||||
|
|
||||||
$this->docStar = $options['debug'] ? '*' : '';
|
$this->docStar = $options['debug'] ? '*' : '';
|
||||||
@ -214,6 +222,7 @@ EOF;
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->targetDirRegex = null;
|
$this->targetDirRegex = null;
|
||||||
|
$this->inlinedRequires = array();
|
||||||
|
|
||||||
$unusedEnvs = array();
|
$unusedEnvs = array();
|
||||||
foreach ($this->container->getEnvCounters() as $env => $use) {
|
foreach ($this->container->getEnvCounters() as $env => $use) {
|
||||||
@ -257,9 +266,13 @@ EOF;
|
|||||||
|
|
||||||
array_unshift($inlinedDefinitions, $definition);
|
array_unshift($inlinedDefinitions, $definition);
|
||||||
|
|
||||||
|
$collectLineage = $this->inlineRequires && !($this->hotPathTag && $definition->hasTag($this->hotPathTag));
|
||||||
$isNonLazyShared = !$this->getProxyDumper()->isProxyCandidate($definition) && $definition->isShared();
|
$isNonLazyShared = !$this->getProxyDumper()->isProxyCandidate($definition) && $definition->isShared();
|
||||||
$calls = $behavior = array();
|
$lineage = $calls = $behavior = array();
|
||||||
foreach ($inlinedDefinitions as $iDefinition) {
|
foreach ($inlinedDefinitions as $iDefinition) {
|
||||||
|
if ($collectLineage && $class = is_array($factory = $iDefinition->getFactory()) && is_string($factory[0]) ? $factory[0] : $iDefinition->getClass()) {
|
||||||
|
$this->collectLineage($class, $lineage);
|
||||||
|
}
|
||||||
$this->getServiceCallsFromArguments($iDefinition->getArguments(), $calls, $behavior, $isNonLazyShared);
|
$this->getServiceCallsFromArguments($iDefinition->getArguments(), $calls, $behavior, $isNonLazyShared);
|
||||||
$isPreInstantiation = $isNonLazyShared && $iDefinition !== $definition && !$this->hasReference($cId, $iDefinition->getMethodCalls(), true) && !$this->hasReference($cId, $iDefinition->getProperties(), true);
|
$isPreInstantiation = $isNonLazyShared && $iDefinition !== $definition && !$this->hasReference($cId, $iDefinition->getMethodCalls(), true) && !$this->hasReference($cId, $iDefinition->getProperties(), true);
|
||||||
$this->getServiceCallsFromArguments($iDefinition->getMethodCalls(), $calls, $behavior, $isPreInstantiation);
|
$this->getServiceCallsFromArguments($iDefinition->getMethodCalls(), $calls, $behavior, $isPreInstantiation);
|
||||||
@ -274,6 +287,13 @@ EOF;
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($collectLineage && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE !== $behavior[$id] && $this->container->has($id)
|
||||||
|
&& $this->isTrivialInstance($iDefinition = $this->container->findDefinition($id))
|
||||||
|
&& $class = is_array($factory = $iDefinition->getFactory()) && is_string($factory[0]) ? $factory[0] : $iDefinition->getClass()
|
||||||
|
) {
|
||||||
|
$this->collectLineage($class, $lineage);
|
||||||
|
}
|
||||||
|
|
||||||
if ($callCount > 1) {
|
if ($callCount > 1) {
|
||||||
$name = $this->getNextVariableName();
|
$name = $this->getNextVariableName();
|
||||||
$this->referenceVariables[$id] = new Variable($name);
|
$this->referenceVariables[$id] = new Variable($name);
|
||||||
@ -300,9 +320,48 @@ EOTXT;
|
|||||||
$code .= "\n";
|
$code .= "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($lineage && $lineage = array_diff_key(array_flip($lineage), $this->inlinedRequires)) {
|
||||||
|
$code = "\n".$code;
|
||||||
|
|
||||||
|
foreach (array_reverse($lineage) as $file => $class) {
|
||||||
|
$code = sprintf(" require_once %s;\n", $file).$code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $code;
|
return $code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function collectLineage($class, array &$lineage)
|
||||||
|
{
|
||||||
|
if (isset($lineage[$class])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!$r = $this->container->getReflectionClass($class)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($this->container instanceof $class) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$file = $r->getFileName();
|
||||||
|
if (!$file || $this->doExport($file) === $exportedFile = $this->export($file)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($parent = $r->getParentClass()) {
|
||||||
|
$this->collectLineage($parent->name, $lineage);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($r->getInterfaces() as $parent) {
|
||||||
|
$this->collectLineage($parent->name, $lineage);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($r->getTraits() as $parent) {
|
||||||
|
$this->collectLineage($parent->name, $lineage);
|
||||||
|
}
|
||||||
|
|
||||||
|
$lineage[$class] = substr($exportedFile, 1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
private function generateProxyClasses()
|
private function generateProxyClasses()
|
||||||
{
|
{
|
||||||
$definitions = $this->container->getDefinitions();
|
$definitions = $this->container->getDefinitions();
|
||||||
@ -509,10 +568,15 @@ EOTXT;
|
|||||||
if (!$v || ($v instanceof Reference && 'service_container' === (string) $v)) {
|
if (!$v || ($v instanceof Reference && 'service_container' === (string) $v)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if ($v instanceof Reference && $this->container->has($id = (string) $v) && $this->container->findDefinition($id)->isSynthetic()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!is_scalar($v) || $this->dumpValue($v) !== $this->dumpValue($v, false)) {
|
if (!is_scalar($v) || $this->dumpValue($v) !== $this->dumpValue($v, false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} elseif ($arg instanceof Reference && $this->container->has($id = (string) $arg) && $this->container->findDefinition($id)->isSynthetic()) {
|
||||||
|
continue;
|
||||||
} elseif (!is_scalar($arg) || $this->dumpValue($arg) !== $this->dumpValue($arg, false)) {
|
} elseif (!is_scalar($arg) || $this->dumpValue($arg) !== $this->dumpValue($arg, false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -694,7 +758,7 @@ EOTXT;
|
|||||||
$lazyInitialization = '';
|
$lazyInitialization = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$asFile = $this->asFiles && $definition->isShared();
|
$asFile = $this->asFiles && $definition->isShared() && !($this->hotPathTag && $definition->hasTag($this->hotPathTag));
|
||||||
$methodName = $this->generateMethodName($id);
|
$methodName = $this->generateMethodName($id);
|
||||||
if ($asFile) {
|
if ($asFile) {
|
||||||
$file = $methodName.'.php';
|
$file = $methodName.'.php';
|
||||||
@ -760,7 +824,7 @@ EOF;
|
|||||||
$definitions = $this->container->getDefinitions();
|
$definitions = $this->container->getDefinitions();
|
||||||
ksort($definitions);
|
ksort($definitions);
|
||||||
foreach ($definitions as $id => $definition) {
|
foreach ($definitions as $id => $definition) {
|
||||||
if ($definition->isSynthetic() || ($this->asFiles && $definition->isShared())) {
|
if ($definition->isSynthetic() || ($this->asFiles && $definition->isShared() && !($this->hotPathTag && $definition->hasTag($this->hotPathTag)))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($definition->isPublic()) {
|
if ($definition->isPublic()) {
|
||||||
@ -778,7 +842,7 @@ EOF;
|
|||||||
$definitions = $this->container->getDefinitions();
|
$definitions = $this->container->getDefinitions();
|
||||||
ksort($definitions);
|
ksort($definitions);
|
||||||
foreach ($definitions as $id => $definition) {
|
foreach ($definitions as $id => $definition) {
|
||||||
if (!$definition->isSynthetic() && $definition->isShared()) {
|
if (!$definition->isSynthetic() && $definition->isShared() && !($this->hotPathTag && $definition->hasTag($this->hotPathTag))) {
|
||||||
$code = $this->addService($id, $definition, $file);
|
$code = $this->addService($id, $definition, $file);
|
||||||
yield $file => $code;
|
yield $file => $code;
|
||||||
}
|
}
|
||||||
@ -899,6 +963,7 @@ EOF;
|
|||||||
$code .= $this->asFiles ? $this->addFileMap() : '';
|
$code .= $this->asFiles ? $this->addFileMap() : '';
|
||||||
$code .= $this->addPrivateServices();
|
$code .= $this->addPrivateServices();
|
||||||
$code .= $this->addAliases();
|
$code .= $this->addAliases();
|
||||||
|
$code .= $this->addInlineRequires();
|
||||||
$code .= <<<'EOF'
|
$code .= <<<'EOF'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1050,7 +1115,7 @@ EOF;
|
|||||||
$definitions = $this->container->getDefinitions();
|
$definitions = $this->container->getDefinitions();
|
||||||
ksort($definitions);
|
ksort($definitions);
|
||||||
foreach ($definitions as $id => $definition) {
|
foreach ($definitions as $id => $definition) {
|
||||||
if (!$definition->isSynthetic() && (!$this->asFiles || !$definition->isShared())) {
|
if (!$definition->isSynthetic() && (!$this->asFiles || !$definition->isShared() || ($this->hotPathTag && $definition->hasTag($this->hotPathTag)))) {
|
||||||
$code .= ' '.$this->export($id).' => '.$this->export($this->generateMethodName($id)).",\n";
|
$code .= ' '.$this->export($id).' => '.$this->export($this->generateMethodName($id)).",\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1069,7 +1134,7 @@ EOF;
|
|||||||
$definitions = $this->container->getDefinitions();
|
$definitions = $this->container->getDefinitions();
|
||||||
ksort($definitions);
|
ksort($definitions);
|
||||||
foreach ($definitions as $id => $definition) {
|
foreach ($definitions as $id => $definition) {
|
||||||
if (!$definition->isSynthetic() && $definition->isShared()) {
|
if (!$definition->isSynthetic() && $definition->isShared() && !($this->hotPathTag && $definition->hasTag($this->hotPathTag))) {
|
||||||
$code .= sprintf(" %s => __DIR__.'/%s.php',\n", $this->export($id), $this->generateMethodName($id));
|
$code .= sprintf(" %s => __DIR__.'/%s.php',\n", $this->export($id), $this->generateMethodName($id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1137,6 +1202,38 @@ EOF;
|
|||||||
return $code." );\n";
|
return $code." );\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function addInlineRequires()
|
||||||
|
{
|
||||||
|
if (!$this->hotPathTag || !$this->inlineRequires) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$lineage = array();
|
||||||
|
|
||||||
|
foreach ($this->container->findTaggedServiceIds($this->hotPathTag) as $id => $tags) {
|
||||||
|
$definition = $this->container->getDefinition($id);
|
||||||
|
$inlinedDefinitions = $this->getInlinedDefinitions($definition);
|
||||||
|
array_unshift($inlinedDefinitions, $definition);
|
||||||
|
|
||||||
|
foreach ($inlinedDefinitions as $iDefinition) {
|
||||||
|
if ($class = is_array($factory = $iDefinition->getFactory()) && is_string($factory[0]) ? $factory[0] : $iDefinition->getClass()) {
|
||||||
|
$this->collectLineage($class, $lineage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$code = "\n";
|
||||||
|
|
||||||
|
foreach ($lineage as $file) {
|
||||||
|
if (!isset($this->inlinedRequires[$file])) {
|
||||||
|
$this->inlinedRequires[$file] = true;
|
||||||
|
$code .= sprintf(" require_once %s;\n", $file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "\n" === $code ? '' : $code;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds default parameters method.
|
* Adds default parameters method.
|
||||||
*
|
*
|
||||||
@ -1408,7 +1505,7 @@ EOF;
|
|||||||
$id = (string) $argument;
|
$id = (string) $argument;
|
||||||
|
|
||||||
if (!isset($calls[$id])) {
|
if (!isset($calls[$id])) {
|
||||||
$calls[$id] = (int) $isPreInstantiation;
|
$calls[$id] = (int) ($isPreInstantiation && $this->container->has($id) && !$this->container->findDefinition($id)->isSynthetic());
|
||||||
}
|
}
|
||||||
if (!isset($behavior[$id])) {
|
if (!isset($behavior[$id])) {
|
||||||
$behavior[$id] = $argument->getInvalidBehavior();
|
$behavior[$id] = $argument->getInvalidBehavior();
|
||||||
@ -1746,9 +1843,7 @@ EOF;
|
|||||||
return '$this';
|
return '$this';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->container->hasDefinition($id)) {
|
if ($this->container->hasDefinition($id) && ($definition = $this->container->getDefinition($id)) && !$definition->isSynthetic()) {
|
||||||
$definition = $this->container->getDefinition($id);
|
|
||||||
|
|
||||||
if (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) {
|
if (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) {
|
||||||
$code = 'null';
|
$code = 'null';
|
||||||
} elseif ($this->isTrivialInstance($definition)) {
|
} elseif ($this->isTrivialInstance($definition)) {
|
||||||
@ -1756,7 +1851,7 @@ EOF;
|
|||||||
if ($definition->isShared()) {
|
if ($definition->isShared()) {
|
||||||
$code = sprintf('$this->services[\'%s\'] = %s', $id, $code);
|
$code = sprintf('$this->services[\'%s\'] = %s', $id, $code);
|
||||||
}
|
}
|
||||||
} elseif ($this->asFiles && $definition->isShared()) {
|
} elseif ($this->asFiles && $definition->isShared() && !($this->hotPathTag && $definition->hasTag($this->hotPathTag))) {
|
||||||
$code = sprintf("\$this->load(__DIR__.'/%s.php')", $this->generateMethodName($id));
|
$code = sprintf("\$this->load(__DIR__.'/%s.php')", $this->generateMethodName($id));
|
||||||
} else {
|
} else {
|
||||||
$code = sprintf('$this->%s()', $this->generateMethodName($id));
|
$code = sprintf('$this->%s()', $this->generateMethodName($id));
|
||||||
|
@ -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\Tests\Compiler;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||||
|
use Symfony\Component\DependencyInjection\Compiler\ResolveHotPathPass;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\DependencyInjection\Definition;
|
||||||
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
|
|
||||||
|
class ResolveHotPathPassTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testProcess()
|
||||||
|
{
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
|
$container->register('foo')
|
||||||
|
->addTag('container.hot_path')
|
||||||
|
->addArgument(new IteratorArgument(array(new Reference('lazy'))))
|
||||||
|
->addArgument(new Reference('service_container'))
|
||||||
|
->addArgument(new Definition('', array(new Reference('bar'))))
|
||||||
|
->addArgument(new Reference('baz', ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE))
|
||||||
|
->addArgument(new Reference('missing'))
|
||||||
|
;
|
||||||
|
|
||||||
|
$container->register('lazy');
|
||||||
|
$container->register('bar');
|
||||||
|
$container->register('bar')->addArgument(new Reference('buz'));
|
||||||
|
$container->register('baz')->addArgument(new Reference('lazy'));
|
||||||
|
$container->register('baz')->addArgument(new Reference('lazy'));
|
||||||
|
$container->register('buz');
|
||||||
|
|
||||||
|
(new ResolveHotPathPass())->process($container);
|
||||||
|
|
||||||
|
$this->assertFalse($container->getDefinition('lazy')->hasTag('container.hot_path'));
|
||||||
|
$this->assertTrue($container->getDefinition('bar')->hasTag('container.hot_path'));
|
||||||
|
$this->assertTrue($container->getDefinition('buz')->hasTag('container.hot_path'));
|
||||||
|
$this->assertFalse($container->getDefinition('baz')->hasTag('container.hot_path'));
|
||||||
|
$this->assertFalse($container->getDefinition('service_container')->hasTag('container.hot_path'));
|
||||||
|
}
|
||||||
|
}
|
@ -170,9 +170,10 @@ class PhpDumperTest extends TestCase
|
|||||||
public function testDumpAsFiles()
|
public function testDumpAsFiles()
|
||||||
{
|
{
|
||||||
$container = include self::$fixturesPath.'/containers/container9.php';
|
$container = include self::$fixturesPath.'/containers/container9.php';
|
||||||
|
$container->getDefinition('bar')->addTag('hot');
|
||||||
$container->compile();
|
$container->compile();
|
||||||
$dumper = new PhpDumper($container);
|
$dumper = new PhpDumper($container);
|
||||||
$dump = print_r($dumper->dump(array('as_files' => true, 'file' => __DIR__)), true);
|
$dump = print_r($dumper->dump(array('as_files' => true, 'file' => __DIR__, 'hot_path_tag' => 'hot')), true);
|
||||||
if ('\\' === DIRECTORY_SEPARATOR) {
|
if ('\\' === DIRECTORY_SEPARATOR) {
|
||||||
$dump = str_replace('\\\\Fixtures\\\\includes\\\\foo.php', '/Fixtures/includes/foo.php', $dump);
|
$dump = str_replace('\\\\Fixtures\\\\includes\\\\foo.php', '/Fixtures/includes/foo.php', $dump);
|
||||||
}
|
}
|
||||||
@ -798,6 +799,21 @@ class PhpDumperTest extends TestCase
|
|||||||
$this->assertSame($foo, $foo->bar->foobar->foo);
|
$this->assertSame($foo, $foo->bar->foobar->foo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testHotPathOptimizations()
|
||||||
|
{
|
||||||
|
$container = include self::$fixturesPath.'/containers/container_inline_requires.php';
|
||||||
|
$container->setParameter('inline_requires', true);
|
||||||
|
$container->compile();
|
||||||
|
$dumper = new PhpDumper($container);
|
||||||
|
|
||||||
|
$dump = $dumper->dump(array('hot_path_tag' => 'container.hot_path', 'inline_class_loader_parameter' => 'inline_requires', 'file' => self::$fixturesPath.'/php/container_inline_requires.php'));
|
||||||
|
if ('\\' === DIRECTORY_SEPARATOR) {
|
||||||
|
$dump = str_replace("'\\\\includes\\\\HotPath\\\\", "'/includes/HotPath/", $dump);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/container_inline_requires.php', $dump);
|
||||||
|
}
|
||||||
|
|
||||||
public function testDumpHandlesLiteralClassWithRootNamespace()
|
public function testDumpHandlesLiteralClassWithRootNamespace()
|
||||||
{
|
{
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Tests\InlineRequires;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\DependencyInjection\Definition;
|
||||||
|
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
|
||||||
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath;
|
||||||
|
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
|
$container->register(HotPath\C1::class)->addTag('container.hot_path')->setPublic(true);
|
||||||
|
$container->register(HotPath\C2::class)->addArgument(new Reference(HotPath\C3::class))->setPublic(true);
|
||||||
|
$container->register(HotPath\C3::class);
|
||||||
|
|
||||||
|
return $container;
|
@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath;
|
||||||
|
|
||||||
|
class C1 extends P1
|
||||||
|
{
|
||||||
|
use T1;
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath;
|
||||||
|
|
||||||
|
class C2
|
||||||
|
{
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath;
|
||||||
|
|
||||||
|
class C3
|
||||||
|
{
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath;
|
||||||
|
|
||||||
|
interface I1
|
||||||
|
{
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath;
|
||||||
|
|
||||||
|
class P1 implements I1
|
||||||
|
{
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath;
|
||||||
|
|
||||||
|
trait T1
|
||||||
|
{
|
||||||
|
}
|
@ -0,0 +1,204 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\Container;
|
||||||
|
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||||
|
use Symfony\Component\DependencyInjection\Exception\LogicException;
|
||||||
|
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||||
|
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class has been auto-generated
|
||||||
|
* by the Symfony Dependency Injection Component.
|
||||||
|
*
|
||||||
|
* @final since Symfony 3.3
|
||||||
|
*/
|
||||||
|
class ProjectServiceContainer extends Container
|
||||||
|
{
|
||||||
|
private $parameters;
|
||||||
|
private $targetDirs = array();
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$dir = __DIR__;
|
||||||
|
for ($i = 1; $i <= 5; ++$i) {
|
||||||
|
$this->targetDirs[$i] = $dir = dirname($dir);
|
||||||
|
}
|
||||||
|
$this->parameters = $this->getDefaultParameters();
|
||||||
|
|
||||||
|
$this->services = array();
|
||||||
|
$this->normalizedIds = array(
|
||||||
|
'symfony\\component\\dependencyinjection\\tests\\fixtures\\includes\\hotpath\\c1' => 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\includes\\HotPath\\C1',
|
||||||
|
'symfony\\component\\dependencyinjection\\tests\\fixtures\\includes\\hotpath\\c2' => 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\includes\\HotPath\\C2',
|
||||||
|
'symfony\\component\\dependencyinjection\\tests\\fixtures\\includes\\hotpath\\c3' => 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\includes\\HotPath\\C3',
|
||||||
|
);
|
||||||
|
$this->methodMap = array(
|
||||||
|
'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\includes\\HotPath\\C1' => 'getC1Service',
|
||||||
|
'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\includes\\HotPath\\C2' => 'getC2Service',
|
||||||
|
'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\includes\\HotPath\\C3' => 'getC3Service',
|
||||||
|
);
|
||||||
|
$this->privates = array(
|
||||||
|
'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\includes\\HotPath\\C3' => true,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->aliases = array();
|
||||||
|
|
||||||
|
require_once $this->targetDirs[1].'/includes/HotPath/I1.php';
|
||||||
|
require_once $this->targetDirs[1].'/includes/HotPath/P1.php';
|
||||||
|
require_once $this->targetDirs[1].'/includes/HotPath/T1.php';
|
||||||
|
require_once $this->targetDirs[1].'/includes/HotPath/C1.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRemovedIds()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'Psr\\Container\\ContainerInterface' => true,
|
||||||
|
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compile()
|
||||||
|
{
|
||||||
|
throw new LogicException('You cannot compile a dumped container that was already compiled.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isCompiled()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isFrozen()
|
||||||
|
{
|
||||||
|
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the public 'Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C1' shared service.
|
||||||
|
*
|
||||||
|
* @return \Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C1
|
||||||
|
*/
|
||||||
|
protected function getC1Service()
|
||||||
|
{
|
||||||
|
return $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C1'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C1();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the public 'Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C2' shared service.
|
||||||
|
*
|
||||||
|
* @return \Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C2
|
||||||
|
*/
|
||||||
|
protected function getC2Service()
|
||||||
|
{
|
||||||
|
require_once $this->targetDirs[1].'/includes/HotPath/C2.php';
|
||||||
|
require_once $this->targetDirs[1].'/includes/HotPath/C3.php';
|
||||||
|
|
||||||
|
$a = ${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C3']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C3'] : $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C3'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C3()) && false ?: '_'};
|
||||||
|
|
||||||
|
if (isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C2'])) {
|
||||||
|
return $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C2'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C2'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C2($a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the private 'Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C3' shared service.
|
||||||
|
*
|
||||||
|
* @return \Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C3
|
||||||
|
*/
|
||||||
|
protected function getC3Service()
|
||||||
|
{
|
||||||
|
require_once $this->targetDirs[1].'/includes/HotPath/C3.php';
|
||||||
|
|
||||||
|
return $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C3'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\includes\HotPath\C3();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParameter($name)
|
||||||
|
{
|
||||||
|
if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
|
||||||
|
$name = $this->normalizeParameterName($name);
|
||||||
|
|
||||||
|
if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) {
|
||||||
|
throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($this->loadedDynamicParameters[$name])) {
|
||||||
|
return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->parameters[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasParameter($name)
|
||||||
|
{
|
||||||
|
$name = $this->normalizeParameterName($name);
|
||||||
|
|
||||||
|
return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setParameter($name, $value)
|
||||||
|
{
|
||||||
|
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getParameterBag()
|
||||||
|
{
|
||||||
|
if (null === $this->parameterBag) {
|
||||||
|
$parameters = $this->parameters;
|
||||||
|
foreach ($this->loadedDynamicParameters as $name => $loaded) {
|
||||||
|
$parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
|
||||||
|
}
|
||||||
|
$this->parameterBag = new FrozenParameterBag($parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->parameterBag;
|
||||||
|
}
|
||||||
|
|
||||||
|
private $loadedDynamicParameters = array();
|
||||||
|
private $dynamicParameters = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes a dynamic parameter.
|
||||||
|
*
|
||||||
|
* @param string The name of the dynamic parameter to load
|
||||||
|
*
|
||||||
|
* @return mixed The value of the dynamic parameter
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException When the dynamic parameter does not exist
|
||||||
|
*/
|
||||||
|
private function getDynamicParameter($name)
|
||||||
|
{
|
||||||
|
throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name));
|
||||||
|
}
|
||||||
|
|
||||||
|
private $normalizedParameterNames = array();
|
||||||
|
|
||||||
|
private function normalizeParameterName($name)
|
||||||
|
{
|
||||||
|
if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) {
|
||||||
|
$normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName;
|
||||||
|
if ((string) $name !== $normalizedName) {
|
||||||
|
@trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $normalizedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the default parameters.
|
||||||
|
*
|
||||||
|
* @return array An array of the default parameters
|
||||||
|
*/
|
||||||
|
protected function getDefaultParameters()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'inline_requires' => true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -13,25 +13,6 @@ return array(
|
|||||||
'new_factory' => true,
|
'new_factory' => true,
|
||||||
);
|
);
|
||||||
|
|
||||||
[Container%s/getBarService.php] => <?php
|
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
|
|
||||||
|
|
||||||
// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
|
|
||||||
// Returns the public 'bar' shared service.
|
|
||||||
|
|
||||||
$a = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->load(__DIR__.'/getFoo_BazService.php')) && false ?: '_'};
|
|
||||||
|
|
||||||
if (isset($this->services['bar'])) {
|
|
||||||
return $this->services['bar'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->services['bar'] = $instance = new \Bar\FooClass('foo', $a, $this->getParameter('foo_bar'));
|
|
||||||
|
|
||||||
$a->configure($instance);
|
|
||||||
|
|
||||||
return $instance;
|
|
||||||
|
|
||||||
[Container%s/getBazService.php] => <?php
|
[Container%s/getBazService.php] => <?php
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
|
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
|
||||||
@ -168,7 +149,7 @@ $this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, array
|
|||||||
$instance->foo = 'bar';
|
$instance->foo = 'bar';
|
||||||
$instance->moo = $a;
|
$instance->moo = $a;
|
||||||
$instance->qux = array('bar' => 'foo is bar', 'foobar' => 'bar');
|
$instance->qux = array('bar' => 'foo is bar', 'foobar' => 'bar');
|
||||||
$instance->setBar(${($_ = isset($this->services['bar']) ? $this->services['bar'] : $this->load(__DIR__.'/getBarService.php')) && false ?: '_'});
|
$instance->setBar(${($_ = isset($this->services['bar']) ? $this->services['bar'] : $this->getBarService()) && false ?: '_'});
|
||||||
$instance->initialize();
|
$instance->initialize();
|
||||||
sc_configure($instance);
|
sc_configure($instance);
|
||||||
|
|
||||||
@ -329,10 +310,10 @@ class Container%s extends Container
|
|||||||
'request' => true,
|
'request' => true,
|
||||||
);
|
);
|
||||||
$this->methodMap = array(
|
$this->methodMap = array(
|
||||||
|
'bar' => 'getBarService',
|
||||||
'foo_bar' => 'getFooBarService',
|
'foo_bar' => 'getFooBarService',
|
||||||
);
|
);
|
||||||
$this->fileMap = array(
|
$this->fileMap = array(
|
||||||
'bar' => __DIR__.'/getBarService.php',
|
|
||||||
'baz' => __DIR__.'/getBazService.php',
|
'baz' => __DIR__.'/getBazService.php',
|
||||||
'configured_service' => __DIR__.'/getConfiguredServiceService.php',
|
'configured_service' => __DIR__.'/getConfiguredServiceService.php',
|
||||||
'configured_service_simple' => __DIR__.'/getConfiguredServiceSimpleService.php',
|
'configured_service_simple' => __DIR__.'/getConfiguredServiceSimpleService.php',
|
||||||
@ -391,6 +372,26 @@ class Container%s extends Container
|
|||||||
return require $file;
|
return require $file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the public 'bar' shared service.
|
||||||
|
*
|
||||||
|
* @return \Bar\FooClass
|
||||||
|
*/
|
||||||
|
protected function getBarService()
|
||||||
|
{
|
||||||
|
$a = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->load(__DIR__.'/getFoo_BazService.php')) && false ?: '_'};
|
||||||
|
|
||||||
|
if (isset($this->services['bar'])) {
|
||||||
|
return $this->services['bar'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->services['bar'] = $instance = new \Bar\FooClass('foo', $a, $this->getParameter('foo_bar'));
|
||||||
|
|
||||||
|
$a->configure($instance);
|
||||||
|
|
||||||
|
return $instance;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the public 'foo_bar' service.
|
* Gets the public 'foo_bar' service.
|
||||||
*
|
*
|
||||||
|
@ -28,6 +28,9 @@ class RegisterListenersPass implements CompilerPassInterface
|
|||||||
protected $listenerTag;
|
protected $listenerTag;
|
||||||
protected $subscriberTag;
|
protected $subscriberTag;
|
||||||
|
|
||||||
|
private $hotPathEvents = array();
|
||||||
|
private $hotPathTagName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $dispatcherService Service name of the event dispatcher in processed container
|
* @param string $dispatcherService Service name of the event dispatcher in processed container
|
||||||
* @param string $listenerTag Tag name used for listener
|
* @param string $listenerTag Tag name used for listener
|
||||||
@ -40,6 +43,14 @@ class RegisterListenersPass implements CompilerPassInterface
|
|||||||
$this->subscriberTag = $subscriberTag;
|
$this->subscriberTag = $subscriberTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setHotPathEvents(array $hotPathEvents, $tagName = 'container.hot_path')
|
||||||
|
{
|
||||||
|
$this->hotPathEvents = array_flip($hotPathEvents);
|
||||||
|
$this->hotPathTagName = $tagName;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function process(ContainerBuilder $container)
|
public function process(ContainerBuilder $container)
|
||||||
{
|
{
|
||||||
if (!$container->hasDefinition($this->dispatcherService) && !$container->hasAlias($this->dispatcherService)) {
|
if (!$container->hasDefinition($this->dispatcherService) && !$container->hasAlias($this->dispatcherService)) {
|
||||||
@ -65,6 +76,10 @@ class RegisterListenersPass implements CompilerPassInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
$definition->addMethodCall('addListener', array($event['event'], array(new ServiceClosureArgument(new Reference($id)), $event['method']), $priority));
|
$definition->addMethodCall('addListener', array($event['event'], array(new ServiceClosureArgument(new Reference($id)), $event['method']), $priority));
|
||||||
|
|
||||||
|
if (isset($this->hotPathEvents[$event['event']])) {
|
||||||
|
$container->getDefinition($id)->addTag($this->hotPathTagName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,6 +106,10 @@ class RegisterListenersPass implements CompilerPassInterface
|
|||||||
foreach ($extractingDispatcher->listeners as $args) {
|
foreach ($extractingDispatcher->listeners as $args) {
|
||||||
$args[1] = array(new ServiceClosureArgument(new Reference($id)), $args[1]);
|
$args[1] = array(new ServiceClosureArgument(new Reference($id)), $args[1]);
|
||||||
$definition->addMethodCall('addListener', $args);
|
$definition->addMethodCall('addListener', $args);
|
||||||
|
|
||||||
|
if (isset($this->hotPathEvents[$args[0]])) {
|
||||||
|
$container->getDefinition($id)->addTag('container.hot_path');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$extractingDispatcher->listeners = array();
|
$extractingDispatcher->listeners = array();
|
||||||
}
|
}
|
||||||
|
@ -141,6 +141,18 @@ class RegisterListenersPassTest extends TestCase
|
|||||||
$this->assertEquals($expectedCalls, $definition->getMethodCalls());
|
$this->assertEquals($expectedCalls, $definition->getMethodCalls());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testHotPathEvents()
|
||||||
|
{
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
|
$container->register('foo', SubscriberService::class)->addTag('kernel.event_subscriber', array());
|
||||||
|
$container->register('event_dispatcher', 'stdClass');
|
||||||
|
|
||||||
|
(new RegisterListenersPass())->setHotPathEvents(array('event'))->process($container);
|
||||||
|
|
||||||
|
$this->assertTrue($container->getDefinition('foo')->hasTag('container.hot_path'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \InvalidArgumentException
|
* @expectedException \InvalidArgumentException
|
||||||
* @expectedExceptionMessage You have requested a non-existent parameter "subscriber.class"
|
* @expectedExceptionMessage You have requested a non-existent parameter "subscriber.class"
|
||||||
|
@ -818,6 +818,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
|
|||||||
'file' => $cache->getPath(),
|
'file' => $cache->getPath(),
|
||||||
'as_files' => true,
|
'as_files' => true,
|
||||||
'debug' => $this->debug,
|
'debug' => $this->debug,
|
||||||
|
'hot_path_tag' => !$this->loadClassCache ? 'container.hot_path' : null,
|
||||||
));
|
));
|
||||||
|
|
||||||
$rootCode = array_pop($content);
|
$rootCode = array_pop($content);
|
||||||
|
Reference in New Issue
Block a user