Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a840809

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

File tree

10 files changed

+230
-9
lines changed

10 files changed

+230
-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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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->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" on-invalid="null" />
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: 9 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
*
@@ -60,6 +66,9 @@ protected static function bootKernel(array $options = array())
6066
static::$kernel = static::createKernel($options);
6167
static::$kernel->boot();
6268

69+
$container = static::$kernel->getContainer();
70+
static::$container = $container->has('test.service_container') ? $container->get('test.service_container') : $container;
71+
6372
return static::$kernel;
6473
}
6574

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 <[email protected]>
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 <[email protected]>
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 ?? $publicContainer->getParameterBag();
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)