8000 [FrameworkBundle] Allow fetching private services from test clients · symfony/symfony@d5c7c60 · GitHub
[go: up one dir, main page]

Skip to content

Commit d5c7c60

Browse files
[FrameworkBundle] Allow fetching private services from test clients
1 parent 9e82562 commit d5c7c60

File tree

10 files changed

+228
-9
lines changed
  • app
  • 10 files changed

    +228
    -9
    lines changed

    src/Symfony/Bundle/FrameworkBundle/Client.php

    Lines changed: 4 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -30,13 +30,15 @@ class Client extends BaseClient
    3030
    private $hasPerformedRequest = false;
    3131
    private $profiler = false;
    3232
    private $reboot = true;
    33+
    private $container;
    3334

    3435
    /**
    3536
    * {@inheritdoc}
    3637
    */
    37-
    public function __construct(KernelInterface $kernel, array $server = array(), History $history = null, CookieJar $cookieJar = null)
    38+
    public function __construct(KernelInterface $kernel, array $server = array(), History $history = null, CookieJar $cookieJar = null, ContainerInterface $container = null)
    3839
    {
    3940
    parent::__construct($kernel, $server, $history, $cookieJar);
    41+
    $this->container = $container;
    4042
    }
    4143

    4244
    /**
    @@ -46,7 +48,7 @@ public function __construct(KernelInterface $kernel, array $server = array(), Hi
    4648
    */
    4749
    public function getContainer()
    4850
    {
    49-
    return $this->kernel->getContainer();
    51+
    return $this->container ?? $this->kernel->getContainer();
    5052
    }
    5153

    5254
    /**
    Lines changed: 39 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -0,0 +1,39 @@
    1+
    <?php
    2+
    3+
    /*
    4+
    * This file is part of the Symfony package.
    5+
    *
    6+
    * (c) Fabien Potencier <fabien@symfony.com>
    7+
    *
    8+
    * For the full copyright and license information, please view the LICENSE
    9+
    * file that was distributed with this source code.
    10+
    */
    11+
    12+
    namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
    13+
    14+
    use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
    15+
    use Symfony\Component\DependencyInjection\ContainerBuilder;
    16+
    use Symfony\Component\DependencyInjection\Reference;
    17+
    18+
    /**
    19+
    * @author Nicolas Grekas <p@tchwork.com>
    20+
    */
    21+
    class TestServiceContainerRealRefPass implements CompilerPassInterface
    22+
    {
    23+
    public function process(ContainerBuilder $container)
    24+
    {
    25+
    if (!$container->hasDefinition('test.service_container')) {
    26+
    return;
    27+
    }
    28+
    29+
    $testContainer = $container->getDefinition('test.service_container');
    30+
    $privateContainer = $container->getDefinition((string) $testContainer->getArgument(2));
    31+
    $definitions = $container->getDefinitions();
    32+
    33+
    foreach ($privateContainer->getArgument(0) as $id => $argument) {
    34+
    if (isset($definitions[$target = (string) $argument->getValues()[0]])) {
    35+
    $argument->setValues(array(new Reference($target)));
    36+
    }
    37+
    }
    38+
    }
    39+
    }
    Lines changed: 56 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -0,0 +1,56 @@
    1+
    <?php
    2+
    3+
    /*
    4+
    * This file is part of the Symfony package.
    5+
    *
    6+
    * (c) Fabien Potencier <fabien@symfony.com>
    7+
    *
    8+
    * For the full copyright and license information, please view the LICENSE
    9+
    * file that was distributed with this source code.
    10+
    */
    11+
    12+
    namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
    13+
    14+
    use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
    15+
    use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
    16+
    use Symfony\Component\DependencyInjection\ContainerBuilder;
    17+
    use Symfony\Component\DependencyInjection\Reference;
    18+
    19+
    /**
    20+
    * @author Nicolas Grekas <p@tchwork.com>
    21+
    */
    22+
    class TestServiceContainerWeakRefPass implements CompilerPassInterface
    23+
    {
    24+
    public function process(ContainerBuilder $container)
    25+
    {
    26+
    if (!$container->hasDefinition('test.service_container')) {
    27+
    return;
    28+
    }
    29+
    30+
    $privateServices = array();
    31+
    $definitions = $container->getDefinitions();
    32+
    33+
    foreach ($definitions as $id => $definition) {
    34+
    if (!$definition->isPublic() && !$definition->getErrors() && !$definition->isAbstract()) {
    35+
    $privateServices[$id] = new ServiceClosureArgument(new Reference($id, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE));
    36+
    }
    37+
    }
    38+
    39+
    $aliases = $container->getAliases();
    40+
    41+
    foreach ($aliases as $id => $alias) {
    42+
    if (!$alias-> 10000 isPublic()) {
    43+
    while (isset($aliases[$target = (string) $alias])) {
    44+
    $alias = $aliases[$target];
    45+
    }
    46+
    if (isset($definitions[$target]) && !$definitions[$target]->getErrors() && !$definitions[$target]->isAbstract()) {
    47+
    $privateServices[$id] = new ServiceClosureArgument(new Reference($target, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE));
    48+
    }
    49+
    }
    50+
    }
    51+
    52+
    if ($privateServices) {
    53+
    $definitions[(string) $definitions['test.service_container']->getArgument(2)]->replaceArgument(0, $privateServices);
    54+
    }
    55+
    }
    56+
    }

    src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

    Lines changed: 4 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -23,6 +23,8 @@
    2323
    use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass;
    2424
    use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass;
    2525
    use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass;
    26+
    use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerWeakRefPass;
    27+
    use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerRealRefPass;
    2628
    use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass;
    2729
    use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\WorkflowGuardListenerPass;
    2830
    use Symfony\Component\Console\Application;
    @@ -114,6 +116,8 @@ public function build(ContainerBuilder $container)
    114116
    $this->addCompilerPassIfExists($container, FormPass::class);
    115117
    $container->addCompilerPass(new WorkflowGuardListenerPass());
    116118
    $container->addCompilerPass(new ResettableServicePass());
    119+
    $container->addCompilerPass(new TestServiceContainerWeakRefPass(), PassConfig::TYPE_BEFORE_REMOVING, -32);
    120+
    $container->addCompilerPass(new TestServiceContainerRealRefPass(), PassConfig::TYPE_AFTER_REMOVING);
    117121

    118122
    if ($container->getParameter('kernel.debug')) {
    119123
    $container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32);

    src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml

    Lines changed: 11 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -16,6 +16,7 @@
    1616
    <argument>%test.client.parameters%</argument>
    1717
    <argument type="service" id="test.client.history" />
    1818
    <argument type="service" id="test.client.cookiejar" />
    19+
    <argument type="service" id="test.service_container" />
    1920
    </service>
    2021

    2122
    <service id="test.client.history" class="Symfony\Component\BrowserKit\History" shared="false" />
    @@ -33,5 +34,15 @@
    3334
    </service>
    3435
    </argument>
    3536
    </service>
    37+
    38+
    <service id="test.service_container" class="Symfony\Bundle\FrameworkBundle\Test\TestContainer" public="true">
    39+
    <argument type="service" id="parameter_bag" />
    40+
    <argument type="service" id="service_container" />
    41+
    <argument type="service">
    42+
    <service class="Symfony\Component\DependencyInjection\ServiceLocator">
    43+
    <argument type="collection" />
    44+
    </service>
    45+
    </argument>
    46+
    </service>
    3647
    </services>
    3748
    </container>

    src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php

    Lines changed: 7 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -12,6 +12,7 @@
    1212
    namespace Symfony\Bundle\FrameworkBundle\Test;
    1313

    1414
    use PHPUnit\Framework\TestCase;
    15+
    use Symfony\Component\DependencyInjection\ContainerInterface;
    1516
    use Symfony\Component\DependencyInjection\ResettableContainerInterface;
    1617
    use Symfony\Component\HttpKernel\KernelInterface;
    1718

    @@ -29,6 +30,11 @@ abstract class KernelTestCase extends TestCase
    2930
    */
    3031
    protected static $kernel;
    3132

    33+
    /**
    34+
    * @var ContainerInterface
    35+
    */
    36+
    protected static $container;
    37+
    3238
    /**
    3339
    * @return string The Kernel class name
    3440
    *
    @@ -59,6 +65,7 @@ protected static function bootKernel(array $options = array())
    5965

    6066
    static::$kernel = static::createKernel($options);
    6167
    static::$kernel->boot();
    68+
    static::$container = static::$kernel->getContainer()->get('test.service_container');
    6269

    6370
    return static::$kernel;
    6471
    }
    Lines changed: 105 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -0,0 +1,105 @@
    1+
    <?php
    2+
    3+
    /*
    4+
    * This file is part of the Symfony package.
    5+
    *
    6+
    * (c) Fabien Potencier <fabien@symfony.com>
    7+
    *
    8+
    * For the full copyright and license information, please view the LICENSE
    9+
    * file that was distributed with this source code.
    10+
    */
    11+
    12+
    namespace Symfony\Bundle\FrameworkBundle\Test;
    13+
    14+
    use Psr\Container\ContainerInterface as PsrContainerInterface;
    15+
    use Symfony\Component\DependencyInjection\Container;
    16+
    use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface;
    17+
    use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
    18+
    19+
    /**
    20+
    * @author Nicolas Grekas <p@tchwork.com>
    21+
    */
    22+
    class TestContainer extends Container
    23+
    {
    24+
    private $publicContainer;
    25+
    private $privateContainer;
    26+
    27+
    public function __construct(ParameterBagInterface $parameterBag, SymfonyContainerInterface $publicContainer, PsrContainerInterface $privateContainer)
    28+
    {
    29+
    $this->parameterBag = $parameterBag;
    30+
    $this->publicContainer = $publicContainer;
    31+
    $this->privateContainer = $privateContainer;
    32+
    }
    33+
    34+
    /**
    35+
    * {@inheritdoc}
    36+
    */
    37+
    public function compile()
    38+
    {
    39+
    $this->publicContainer->compile();
    40+
    }
    41+
    42+
    /**
    43+
    * {@inheritdoc}
    44+
    */
    45+
    public function isCompiled()
    46+
    {
    47+
    return $this->publicContainer->isCompiled();
    48+
    }
    49+
    50+
    /**
    51+
    * {@inheritdoc}
    52+
    */
    53+
    public function set($id, $service)
    54+
    {
    55+
    $this->publicContainer->set($id, $service);
    56+
    }
    57+
    58+
    /**
    59+
    * {@inheritdoc}
    60+
    */
    61+
    public function has($id)
    62+
    {
    63+
    return $this->publicContainer->has($id) || $this->privateContainer->has($id);
    64+
    }
    65+
    66+
    /**
    67+
    * {@inheritdoc}
    68+
    */
    69+
    public function get($id, $invalidBehavior = /* self::EXCEPTION_ON_INVALID_REFERENCE */ 1)
    70+
    {
    71+
    return $this->privateContainer->has($id) ? $this->privateContainer->get($id) : $this->publicContainer->get($id, $invalidBehavior);
    72+
    }
    73+
    74+
    /**
    75+
    * {@inheritdoc}
    76+
    */
    77+
    public function initialized($id)
    78+
    {
    79+
    return $this->publicContainer->initialized($id);
    80+
    }
    81+
    82+
    /**
    83+
    * {@inheritdoc}
    84+
    */
    85+
    public function reset()
    86+
    {
    87+
    $this->publicContainer->reset();
    88+
    }
    89+
    90+
    /**
    91+
    * {@inheritdoc}
    92+
    */
    93+
    public function getServiceIds()
    94+
    {
    95+
    return $this->publicContainer->getServiceIds();
    96+
    }
    97+
    98+
    /**
    99+
    * {@inheritdoc}
    100+
    */
    101+
    public function getRemovedIds()
    102+
    {
    103+
    return $this->publicContainer->getRemovedIds();
    104+
    }
    105+
    }

    src/Symfony/Bundle/FrameworkBundle/Tests/Functional/PropertyInfoTest.php

    Lines changed: 1 addition & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -18,9 +18,8 @@ class PropertyInfoTest extends WebTestCase
    1818
    public function testPhpDocPriority()
    1919
    {
    2020
    static::bootKernel(array('test_case' => 'Serializer'));
    21-
    $container = static::$kernel->getContainer();
    2221

    23-
    $this->assertEquals(array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_INT))), $container->get('test.property_info')->getTypes('Symfony\Bundle\FrameworkBundle\Tests\Functional\Dummy', 'codes'));
    22+
    $this->assertEquals(array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_INT))), static::$container->get('property_info')->getTypes('Symfony\Bundle\FrameworkBundle\Tests\Functional\Dummy', 'codes'));
    2423
    }
    2524
    }
    2625

    Lines changed: 0 additions & 4 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,10 +1,6 @@
    11
    imports:
    22
    - { resource: ../config/default.yml }
    33

    4-
    services:
    5-
    _defaults: { public: true }
    6-
    test.property_info: '@property_info'
    7-
    84
    framework:
    95
    serializer: { enabled: true }
    106
    property_info: { enabled: true }

    src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/config/framework.yml

    Lines changed: 1 addition & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -4,7 +4,7 @@ framework:
    44
    validation: { enabled: true, enable_annotations: true }
    55
    csrf_protection: true
    66
    form: true
    7-
    test: ~
    7+
    test: true
    88
    default_locale: en
    99
    session:
    1010
    storage_id: session.storage.mock_file

    0 commit comments

    Comments
     (0)
    0