ContainerBuilderTest   F
last analyzed

Complexity

Total Complexity 57

Size/Duplication

Total Lines 821
Duplicated Lines 7.67 %

Coupling/Cohesion

Components 0
Dependencies 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 57
c 1
b 0
f 0
lcom 0
cbo 6
dl 63
loc 821
rs 1.0434

45 Methods

Rating   Name   Duplication   Size   Complexity  
A testCreateServiceConfigurator() 0 22 2
A testAddObjectResource() 22 22 1
A testAddClassResource() 22 22 1
B testDefinitions() 0 26 2
A testRegister() 0 7 1
A testHas() 0 9 1
B testGet() 0 30 3
A testGetUnsetLoadingServiceWhenCreateServiceThrowsAnException() 0 14 2
A testGetReturnsNullOnInactiveScope() 0 7 1
A testGetReturnsNullOnInactiveScopeWhenServiceIsCreatedByAMethod() 0 6 1
A testGetServiceIds() 0 8 1
B testAliases() 0 25 3
A testGetAliases() 0 21 1
A testSetAliases() 9 9 1
A testAddAliases() 10 10 1
A testAddGetCompilerPass() 0 9 1
A testCreateService() 0 9 1
A testCreateProxyWithRealServiceInstantiator() 0 12 1
A testCreateServiceClass() 0 7 1
A testCreateServiceArguments() 0 8 1
A testCreateServiceFactory() 0 13 1
A testLegacyCreateServiceFactory() 0 17 1
A testLegacyCreateServiceFactoryService() 0 14 1
A testCreateServiceMethodCalls() 0 8 1
A testCreateSyntheticService() 0 6 1
A testCreateServiceWithExpression() 0 8 1
A testResolveServices() 0 8 1
B testMerge() 0 43 1
A testMergeLogicException() 0 7 1
A testfindTaggedServiceIds() 0 17 1
A testFindDefinition() 0 8 1
A testCompilesClassDefinitionsOfLazyServices() 0 21 2
A testResources() 0 15 3
A testExtension() 0 11 1
A testRegisteredButNotLoadedExtension() 0 11 1
A testRegisteredAndLoadedExtension() 0 12 1
A testPrivateServiceUser() 0 17 1
A testThrowsExceptionWhenSetServiceOnAFrozenContainer() 0 8 1
A testThrowsExceptionWhenAddServiceOnAFrozenContainer() 0 6 1
A testNoExceptionWhenSetSyntheticServiceOnAFrozenContainer() 0 10 1
A testLegacySetOnSynchronizedService() 0 18 1
B testLegacySynchronizedServiceWithScopes() 0 30 1
A testThrowsExceptionWhenSetDefinitionOnAFrozenContainer() 0 7 1
A testExtensionConfig() 0 17 1
B testLazyLoadedService() 0 32 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like ContainerBuilderTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ContainerBuilderTest, and based on these observations, apply Extract Interface, too.

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\Component\DependencyInjection\Tests;
13
14
require_once __DIR__.'/Fixtures/includes/classes.php';
15
require_once __DIR__.'/Fixtures/includes/ProjectExtension.php';
16
17
use Symfony\Component\Config\Resource\ResourceInterface;
18
use Symfony\Component\DependencyInjection\Alias;
19
use Symfony\Component\DependencyInjection\ContainerBuilder;
20
use Symfony\Component\DependencyInjection\ContainerInterface;
21
use Symfony\Component\DependencyInjection\Definition;
22
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
23
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
24
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
25
use Symfony\Component\DependencyInjection\Reference;
26
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
27
use Symfony\Component\DependencyInjection\Scope;
28
use Symfony\Component\Config\Resource\FileResource;
29
use Symfony\Component\ExpressionLanguage\Expression;
30
31
class ContainerBuilderTest extends \PHPUnit_Framework_TestCase
32
{
33
    /**
34
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setDefinitions
35
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getDefinitions
36
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setDefinition
37
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getDefinition
38
     */
39
    public function testDefinitions()
40
    {
41
        $builder = new ContainerBuilder();
42
        $definitions = array(
43
            'foo' => new Definition('Bar\FooClass'),
44
            'bar' => new Definition('BarClass'),
45
        );
46
        $builder->setDefinitions($definitions);
47
        $this->assertEquals($definitions, $builder->getDefinitions(), '->setDefinitions() sets the service definitions');
48
        $this->assertTrue($builder->hasDefinition('foo'), '->hasDefinition() returns true if a service definition exists');
49
        $this->assertFalse($builder->hasDefinition('foobar'), '->hasDefinition() returns false if a service definition does not exist');
50
51
        $builder->setDefinition('foobar', $foo = new Definition('FooBarClass'));
52
        $this->assertEquals($foo, $builder->getDefinition('foobar'), '->getDefinition() returns a service definition if defined');
53
        $this->assertTrue($builder->setDefinition('foobar', $foo = new Definition('FooBarClass')) === $foo, '->setDefinition() implements a fluid interface by returning the service reference');
54
55
        $builder->addDefinitions($defs = array('foobar' => new Definition('FooBarClass')));
56
        $this->assertEquals(array_merge($definitions, $defs), $builder->getDefinitions(), '->addDefinitions() adds the service definitions');
57
58
        try {
59
            $builder->getDefinition('baz');
60
            $this->fail('->getDefinition() throws an InvalidArgumentException if the service definition does not exist');
61
        } catch (\InvalidArgumentException $e) {
62
            $this->assertEquals('The service definition "baz" does not exist.', $e->getMessage(), '->getDefinition() throws an InvalidArgumentException if the service definition does not exist');
63
        }
64
    }
65
66
    /**
67
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::register
68
     */
69
    public function testRegister()
70
    {
71
        $builder = new ContainerBuilder();
72
        $builder->register('foo', 'Bar\FooClass');
73
        $this->assertTrue($builder->hasDefinition('foo'), '->register() registers a new service definition');
74
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $builder->getDefinition('foo'), '->register() returns the newly created Definition instance');
75
    }
76
77
    /**
78
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::has
79
     */
80
    public function testHas()
81
    {
82
        $builder = new ContainerBuilder();
83
        $this->assertFalse($builder->has('foo'), '->has() returns false if the service does not exist');
84
        $builder->register('foo', 'Bar\FooClass');
85
        $this->assertTrue($builder->has('foo'), '->has() returns true if a service definition exists');
86
        $builder->set('bar', new \stdClass());
87
        $this->assertTrue($builder->has('bar'), '->has() returns true if a service exists');
88
    }
89
90
    /**
91
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::get
92
     */
93
    public function testGet()
94
    {
95
        $builder = new ContainerBuilder();
96
        try {
97
            $builder->get('foo');
98
            $this->fail('->get() throws an InvalidArgumentException if the service does not exist');
99
        } catch (\InvalidArgumentException $e) {
100
            $this->assertEquals('The service definition "foo" does not exist.', $e->getMessage(), '->get() throws an InvalidArgumentException if the service does not exist');
101
        }
102
103
        $this->assertNull($builder->get('foo', ContainerInterface::NULL_ON_INVALID_REFERENCE), '->get() returns null if the service does not exist and NULL_ON_INVALID_REFERENCE is passed as a second argument');
104
105
        $builder->register('foo', 'stdClass');
106
        $this->assertInternalType('object', $builder->get('foo'), '->get() returns the service definition associated with the id');
107
        $builder->set('bar', $bar = new \stdClass());
108
        $this->assertEquals($bar, $builder->get('bar'), '->get() returns the service associated with the id');
109
        $builder->register('bar', 'stdClass');
110
        $this->assertEquals($bar, $builder->get('bar'), '->get() returns the service associated with the id even if a definition has been defined');
111
112
        $builder->register('baz', 'stdClass')->setArguments(array(new Reference('baz')));
113
        try {
114
            @$builder->get('baz');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
115
            $this->fail('->get() throws a ServiceCircularReferenceException if the service has a circular reference to itself');
116
        } catch (\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException $e) {
117
            $this->assertEquals('Circular reference detected for service "baz", path: "baz".', $e->getMessage(), '->get() throws a LogicException if the service has a circular reference to itself');
118
        }
119
120
        $builder->register('foobar', 'stdClass')->setScope('container');
121
        $this->assertTrue($builder->get('bar') === $builder->get('bar'), '->get() always returns the same instance if the service is shared');
122
    }
123
124
    /**
125
     * @covers                   \Symfony\Component\DependencyInjection\ContainerBuilder::get
126
     * @expectedException        \Symfony\Component\DependencyInjection\Exception\RuntimeException
127
     * @expectedExceptionMessage You have requested a synthetic service ("foo"). The DIC does not know how to construct this service.
128
     */
129
    public function testGetUnsetLoadingServiceWhenCreateServiceThrowsAnException()
130
    {
131
        $builder = new ContainerBuilder();
132
        $builder->register('foo', 'stdClass')->setSynthetic(true);
133
134
        // we expect a RuntimeException here as foo is synthetic
135
        try {
136
            $builder->get('foo');
137
        } catch (RuntimeException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
138
        }
139
140
        // we must also have the same RuntimeException here
141
        $builder->get('foo');
142
    }
143
144
    /**
145
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::get
146
     */
147
    public function testGetReturnsNullOnInactiveScope()
148
    {
149
        $builder = new ContainerBuilder();
150
        $builder->register('foo', 'stdClass')->setScope('request');
151
152
        $this->assertNull($builder->get('foo', ContainerInterface::NULL_ON_INVALID_REFERENCE));
153
    }
154
155
    /**
156
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::get
157
     */
158
    public function testGetReturnsNullOnInactiveScopeWhenServiceIsCreatedByAMethod()
159
    {
160
        $builder = new ProjectContainer();
161
162
        $this->assertNull($builder->get('foobaz', ContainerInterface::NULL_ON_INVALID_REFERENCE));
163
    }
164
165
    /**
166
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getServiceIds
167
     */
168
    public function testGetServiceIds()
169
    {
170
        $builder = new ContainerBuilder();
171
        $builder->register('foo', 'stdClass');
172
        $builder->bar = $bar = new \stdClass();
0 ignored issues
show
Bug introduced by
The property bar does not seem to exist in Symfony\Component\Depend...ection\ContainerBuilder.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
Unused Code introduced by
$bar is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
173
        $builder->register('bar', 'stdClass');
174
        $this->assertEquals(array('foo', 'bar', 'service_container'), $builder->getServiceIds(), '->getServiceIds() returns all defined service ids');
175
    }
176
177
    /**
178
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setAlias
179
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::hasAlias
180
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getAlias
181
     */
182
    public function testAliases()
183
    {
184
        $builder = new ContainerBuilder();
185
        $builder->register('foo', 'stdClass');
186
        $builder->setAlias('bar', 'foo');
187
        $this->assertTrue($builder->hasAlias('bar'), '->hasAlias() returns true if the alias exists');
188
        $this->assertFalse($builder->hasAlias('foobar'), '->hasAlias() returns false if the alias does not exist');
189
        $this->assertEquals('foo', (string) $builder->getAlias('bar'), '->getAlias() returns the aliased service');
190
        $this->assertTrue($builder->has('bar'), '->setAlias() defines a new service');
191
        $this->assertTrue($builder->get('bar') === $builder->get('foo'), '->setAlias() creates a service that is an alias to another one');
192
193
        try {
194
            $builder->setAlias('foobar', 'foobar');
195
            $this->fail('->setAlias() throws an InvalidArgumentException if the alias references itself');
196
        } catch (\InvalidArgumentException $e) {
197
            $this->assertEquals('An alias can not reference itself, got a circular reference on "foobar".', $e->getMessage(), '->setAlias() throws an InvalidArgumentException if the alias references itself');
198
        }
199
200
        try {
201
            $builder->getAlias('foobar');
202
            $this->fail('->getAlias() throws an InvalidArgumentException if the alias does not exist');
203
        } catch (\InvalidArgumentException $e) {
204
            $this->assertEquals('The service alias "foobar" does not exist.', $e->getMessage(), '->getAlias() throws an InvalidArgumentException if the alias does not exist');
205
        }
206
    }
207
208
    /**
209
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getAliases
210
     */
211
    public function testGetAliases()
212
    {
213
        $builder = new ContainerBuilder();
214
        $builder->setAlias('bar', 'foo');
215
        $builder->setAlias('foobar', 'foo');
216
        $builder->setAlias('moo', new Alias('foo', false));
217
218
        $aliases = $builder->getAliases();
219
        $this->assertEquals('foo', (string) $aliases['bar']);
220
        $this->assertTrue($aliases['bar']->isPublic());
221
        $this->assertEquals('foo', (string) $aliases['foobar']);
222
        $this->assertEquals('foo', (string) $aliases['moo']);
223
        $this->assertFalse($aliases['moo']->isPublic());
224
225
        $builder->register('bar', 'stdClass');
226
        $this->assertFalse($builder->hasAlias('bar'));
227
228
        $builder->set('foobar', 'stdClass');
0 ignored issues
show
Documentation introduced by
'stdClass' is of type string, but the function expects a object.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
229
        $builder->set('moo', 'stdClass');
0 ignored issues
show
Documentation introduced by
'stdClass' is of type string, but the function expects a object.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
230
        $this->assertCount(0, $builder->getAliases(), '->getAliases() does not return aliased services that have been overridden');
231
    }
232
233
    /**
234
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setAliases
235
     */
236 View Code Duplication
    public function testSetAliases()
237
    {
238
        $builder = new ContainerBuilder();
239
        $builder->setAliases(array('bar' => 'foo', 'foobar' => 'foo'));
240
241
        $aliases = $builder->getAliases();
242
        $this->assertTrue(isset($aliases['bar']));
243
        $this->assertTrue(isset($aliases['foobar']));
244
    }
245
246
    /**
247
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addAliases
248
     */
249 View Code Duplication
    public function testAddAliases()
250
    {
251
        $builder = new ContainerBuilder();
252
        $builder->setAliases(array('bar' => 'foo'));
253
        $builder->addAliases(array('foobar' => 'foo'));
254
255
        $aliases = $builder->getAliases();
256
        $this->assertTrue(isset($aliases['bar']));
257
        $this->assertTrue(isset($aliases['foobar']));
258
    }
259
260
    /**
261
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addCompilerPass
262
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getCompilerPassConfig
263
     */
264
    public function testAddGetCompilerPass()
265
    {
266
        $builder = new ContainerBuilder();
267
        $builder->setResourceTracking(false);
268
        $builderCompilerPasses = $builder->getCompiler()->getPassConfig()->getPasses();
269
        $builder->addCompilerPass($this->getMock('Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface'));
270
271
        $this->assertCount(count($builder->getCompiler()->getPassConfig()->getPasses()) - 1, $builderCompilerPasses);
272
    }
273
274
    /**
275
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
276
     */
277
    public function testCreateService()
278
    {
279
        $builder = new ContainerBuilder();
280
        $builder->register('foo1', 'Bar\FooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php');
281
        $this->assertInstanceOf('\Bar\FooClass', $builder->get('foo1'), '->createService() requires the file defined by the service definition');
282
        $builder->register('foo2', 'Bar\FooClass')->setFile(__DIR__.'/Fixtures/includes/%file%.php');
283
        $builder->setParameter('file', 'foo');
284
        $this->assertInstanceOf('\Bar\FooClass', $builder->get('foo2'), '->createService() replaces parameters in the file provided by the service definition');
285
    }
286
287
    /**
288
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
289
     */
290
    public function testCreateProxyWithRealServiceInstantiator()
291
    {
292
        $builder = new ContainerBuilder();
293
294
        $builder->register('foo1', 'Bar\FooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php');
295
        $builder->getDefinition('foo1')->setLazy(true);
296
297
        $foo1 = $builder->get('foo1');
298
299
        $this->assertSame($foo1, $builder->get('foo1'), 'The same proxy is retrieved on multiple subsequent calls');
300
        $this->assertSame('Bar\FooClass', get_class($foo1));
301
    }
302
303
    /**
304
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
305
     */
306
    public function testCreateServiceClass()
307
    {
308
        $builder = new ContainerBuilder();
309
        $builder->register('foo1', '%class%');
310
        $builder->setParameter('class', 'stdClass');
311
        $this->assertInstanceOf('\stdClass', $builder->get('foo1'), '->createService() replaces parameters in the class provided by the service definition');
312
    }
313
314
    /**
315
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
316
     */
317
    public function testCreateServiceArguments()
318
    {
319
        $builder = new ContainerBuilder();
320
        $builder->register('bar', 'stdClass');
321
        $builder->register('foo1', 'Bar\FooClass')->addArgument(array('foo' => '%value%', '%value%' => 'foo', new Reference('bar'), '%%unescape_it%%'));
322
        $builder->setParameter('value', 'bar');
323
        $this->assertEquals(array('foo' => 'bar', 'bar' => 'foo', $builder->get('bar'), '%unescape_it%'), $builder->get('foo1')->arguments, '->createService() replaces parameters and service references in the arguments provided by the service definition');
324
    }
325
326
    /**
327
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
328
     */
329
    public function testCreateServiceFactory()
330
    {
331
        $builder = new ContainerBuilder();
332
        $builder->register('foo', 'Bar\FooClass')->setFactory('Bar\FooClass::getInstance');
333
        $builder->register('qux', 'Bar\FooClass')->setFactory(array('Bar\FooClass', 'getInstance'));
334
        $builder->register('bar', 'Bar\FooClass')->setFactory(array(new Definition('Bar\FooClass'), 'getInstance'));
335
        $builder->register('baz', 'Bar\FooClass')->setFactory(array(new Reference('bar'), 'getInstance'));
336
337
        $this->assertTrue($builder->get('foo')->called, '->createService() calls the factory method to create the service instance');
338
        $this->assertTrue($builder->get('qux')->called, '->createService() calls the factory method to create the service instance');
339
        $this->assertTrue($builder->get('bar')->called, '->createService() uses anonymous service as factory');
340
        $this->assertTrue($builder->get('baz')->called, '->createService() uses another service as factory');
341
    }
342
343
    public function testLegacyCreateServiceFactory()
344
    {
345
        $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
346
347
        $builder = new ContainerBuilder();
348
        $builder->register('bar', 'Bar\FooClass');
349
        $builder
0 ignored issues
show
Deprecated Code introduced by
The method Symfony\Component\Depend...tion::setFactoryClass() has been deprecated with message: since version 2.6, to be removed in 3.0.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
Deprecated Code introduced by
The method Symfony\Component\Depend...ion::setFactoryMethod() has been deprecated with message: since version 2.6, to be removed in 3.0.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
350
            ->register('foo1', 'Bar\FooClass')
351
            ->setFactoryClass('%foo_class%')
352
            ->setFactoryMethod('getInstance')
353
            ->addArgument(array('foo' => '%value%', '%value%' => 'foo', new Reference('bar')))
354
        ;
355
        $builder->setParameter('value', 'bar');
356
        $builder->setParameter('foo_class', 'Bar\FooClass');
357
        $this->assertTrue($builder->get('foo1')->called, '->createService() calls the factory method to create the service instance');
358
        $this->assertEquals(array('foo' => 'bar', 'bar' => 'foo', $builder->get('bar')), $builder->get('foo1')->arguments, '->createService() passes the arguments to the factory method');
359
    }
360
361
    /**
362
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
363
     */
364
    public function testLegacyCreateServiceFactoryService()
365
    {
366
        $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
367
368
        $builder = new ContainerBuilder();
369
        $builder->register('foo_service', 'Bar\FooClass');
370
        $builder
0 ignored issues
show
Deprecated Code introduced by
The method Symfony\Component\Depend...on::setFactoryService() has been deprecated with message: since version 2.6, to be removed in 3.0.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
Deprecated Code introduced by
The method Symfony\Component\Depend...ion::setFactoryMethod() has been deprecated with message: since version 2.6, to be removed in 3.0.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
371
            ->register('foo', 'Bar\FooClass')
372
            ->setFactoryService('%foo_service%')
373
            ->setFactoryMethod('getInstance')
374
        ;
375
        $builder->setParameter('foo_service', 'foo_service');
376
        $this->assertTrue($builder->get('foo')->called, '->createService() calls the factory method to create the service instance');
377
    }
378
379
    /**
380
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
381
     */
382
    public function testCreateServiceMethodCalls()
383
    {
384
        $builder = new ContainerBuilder();
385
        $builder->register('bar', 'stdClass');
386
        $builder->register('foo1', 'Bar\FooClass')->addMethodCall('setBar', array(array('%value%', new Reference('bar'))));
387
        $builder->setParameter('value', 'bar');
388
        $this->assertEquals(array('bar', $builder->get('bar')), $builder->get('foo1')->bar, '->createService() replaces the values in the method calls arguments');
389
    }
390
391
    /**
392
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
393
     */
394
    public function testCreateServiceConfigurator()
395
    {
396
        $builder = new ContainerBuilder();
397
        $builder->register('foo1', 'Bar\FooClass')->setConfigurator('sc_configure');
398
        $this->assertTrue($builder->get('foo1')->configured, '->createService() calls the configurator');
399
400
        $builder->register('foo2', 'Bar\FooClass')->setConfigurator(array('%class%', 'configureStatic'));
401
        $builder->setParameter('class', 'BazClass');
402
        $this->assertTrue($builder->get('foo2')->configured, '->createService() calls the configurator');
403
404
        $builder->register('baz', 'BazClass');
405
        $builder->register('foo3', 'Bar\FooClass')->setConfigurator(array(new Reference('baz'), 'configure'));
406
        $this->assertTrue($builder->get('foo3')->configured, '->createService() calls the configurator');
407
408
        $builder->register('foo4', 'Bar\FooClass')->setConfigurator('foo');
409
        try {
410
            $builder->get('foo4');
411
            $this->fail('->createService() throws an InvalidArgumentException if the configure callable is not a valid callable');
412
        } catch (\InvalidArgumentException $e) {
413
            $this->assertEquals('The configure callable for class "Bar\FooClass" is not a callable.', $e->getMessage(), '->createService() throws an InvalidArgumentException if the configure callable is not a valid callable');
414
        }
415
    }
416
417
    /**
418
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
419
     * @expectedException \RuntimeException
420
     */
421
    public function testCreateSyntheticService()
422
    {
423
        $builder = new ContainerBuilder();
424
        $builder->register('foo', 'Bar\FooClass')->setSynthetic(true);
425
        $builder->get('foo');
426
    }
427
428
    public function testCreateServiceWithExpression()
429
    {
430
        $builder = new ContainerBuilder();
431
        $builder->setParameter('bar', 'bar');
432
        $builder->register('bar', 'BarClass');
433
        $builder->register('foo', 'Bar\FooClass')->addArgument(array('foo' => new Expression('service("bar").foo ~ parameter("bar")')));
434
        $this->assertEquals('foobar', $builder->get('foo')->arguments['foo']);
435
    }
436
437
    /**
438
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::resolveServices
439
     */
440
    public function testResolveServices()
441
    {
442
        $builder = new ContainerBuilder();
443
        $builder->register('foo', 'Bar\FooClass');
444
        $this->assertEquals($builder->get('foo'), $builder->resolveServices(new Reference('foo')), '->resolveServices() resolves service references to service instances');
445
        $this->assertEquals(array('foo' => array('foo', $builder->get('foo'))), $builder->resolveServices(array('foo' => array('foo', new Reference('foo')))), '->resolveServices() resolves service references to service instances in nested arrays');
446
        $this->assertEquals($builder->get('foo'), $builder->resolveServices(new Expression('service("foo")')), '->resolveServices() resolves expressions');
447
    }
448
449
    /**
450
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::merge
451
     */
452
    public function testMerge()
453
    {
454
        $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo')));
455
        $container->setResourceTracking(false);
456
        $config = new ContainerBuilder(new ParameterBag(array('foo' => 'bar')));
457
        $container->merge($config);
458
        $this->assertEquals(array('bar' => 'foo', 'foo' => 'bar'), $container->getParameterBag()->all(), '->merge() merges current parameters with the loaded ones');
459
460
        $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo')));
461
        $container->setResourceTracking(false);
462
        $config = new ContainerBuilder(new ParameterBag(array('foo' => '%bar%')));
463
        $container->merge($config);
464
        $container->compile();
465
        $this->assertEquals(array('bar' => 'foo', 'foo' => 'foo'), $container->getParameterBag()->all(), '->merge() evaluates the values of the parameters towards already defined ones');
466
467
        $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo')));
468
        $container->setResourceTracking(false);
469
        $config = new ContainerBuilder(new ParameterBag(array('foo' => '%bar%', 'baz' => '%foo%')));
470
        $container->merge($config);
471
        $container->compile();
472
        $this->assertEquals(array('bar' => 'foo', 'foo' => 'foo', 'baz' => 'foo'), $container->getParameterBag()->all(), '->merge() evaluates the values of the parameters towards already defined ones');
473
474
        $container = new ContainerBuilder();
475
        $container->setResourceTracking(false);
476
        $container->register('foo', 'Bar\FooClass');
477
        $container->register('bar', 'BarClass');
478
        $config = new ContainerBuilder();
479
        $config->setDefinition('baz', new Definition('BazClass'));
480
        $config->setAlias('alias_for_foo', 'foo');
481
        $container->merge($config);
482
        $this->assertEquals(array('foo', 'bar', 'baz'), array_keys($container->getDefinitions()), '->merge() merges definitions already defined ones');
483
484
        $aliases = $container->getAliases();
485
        $this->assertTrue(isset($aliases['alias_for_foo']));
486
        $this->assertEquals('foo', (string) $aliases['alias_for_foo']);
487
488
        $container = new ContainerBuilder();
489
        $container->setResourceTracking(false);
490
        $container->register('foo', 'Bar\FooClass');
491
        $config->setDefinition('foo', new Definition('BazClass'));
492
        $container->merge($config);
493
        $this->assertEquals('BazClass', $container->getDefinition('foo')->getClass(), '->merge() overrides already defined services');
494
    }
495
496
    /**
497
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::merge
498
     * @expectedException \LogicException
499
     */
500
    public function testMergeLogicException()
501
    {
502
        $container = new ContainerBuilder();
503
        $container->setResourceTracking(false);
504
        $container->compile();
505
        $container->merge(new ContainerBuilder());
506
    }
507
508
    /**
509
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::findTaggedServiceIds
510
     */
511
    public function testfindTaggedServiceIds()
512
    {
513
        $builder = new ContainerBuilder();
514
        $builder
515
            ->register('foo', 'Bar\FooClass')
516
            ->addTag('foo', array('foo' => 'foo'))
517
            ->addTag('bar', array('bar' => 'bar'))
518
            ->addTag('foo', array('foofoo' => 'foofoo'))
519
        ;
520
        $this->assertEquals($builder->findTaggedServiceIds('foo'), array(
521
            'foo' => array(
522
                array('foo' => 'foo'),
523
                array('foofoo' => 'foofoo'),
524
            ),
525
        ), '->findTaggedServiceIds() returns an array of service ids and its tag attributes');
526
        $this->assertEquals(array(), $builder->findTaggedServiceIds('foobar'), '->findTaggedServiceIds() returns an empty array if there is annotated services');
527
    }
528
529
    /**
530
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::findDefinition
531
     */
532
    public function testFindDefinition()
533
    {
534
        $container = new ContainerBuilder();
535
        $container->setDefinition('foo', $definition = new Definition('Bar\FooClass'));
536
        $container->setAlias('bar', 'foo');
537
        $container->setAlias('foobar', 'bar');
538
        $this->assertEquals($definition, $container->findDefinition('foobar'), '->findDefinition() returns a Definition');
539
    }
540
541
    /**
542
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addObjectResource
543
     */
544 View Code Duplication
    public function testAddObjectResource()
545
    {
546
        $container = new ContainerBuilder();
547
548
        $container->setResourceTracking(false);
549
        $container->addObjectResource(new \BarClass());
550
551
        $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking');
552
553
        $container->setResourceTracking(true);
554
        $container->addObjectResource(new \BarClass());
555
556
        $resources = $container->getResources();
557
558
        $this->assertCount(1, $resources, '1 resource was registered');
559
560
        /* @var $resource \Symfony\Component\Config\Resource\FileResource */
561
        $resource = end($resources);
562
563
        $this->assertInstanceOf('Symfony\Component\Config\Resource\FileResource', $resource);
564
        $this->assertSame(realpath(__DIR__.'/Fixtures/includes/classes.php'), realpath($resource->getResource()));
565
    }
566
567
    /**
568
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addClassResource
569
     */
570 View Code Duplication
    public function testAddClassResource()
571
    {
572
        $container = new ContainerBuilder();
573
574
        $container->setResourceTracking(false);
575
        $container->addClassResource(new \ReflectionClass('BarClass'));
576
577
        $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking');
578
579
        $container->setResourceTracking(true);
580
        $container->addClassResource(new \ReflectionClass('BarClass'));
581
582
        $resources = $container->getResources();
583
584
        $this->assertCount(1, $resources, '1 resource was registered');
585
586
        /* @var $resource \Symfony\Component\Config\Resource\FileResource */
587
        $resource = end($resources);
588
589
        $this->assertInstanceOf('Symfony\Component\Config\Resource\FileResource', $resource);
590
        $this->assertSame(realpath(__DIR__.'/Fixtures/includes/classes.php'), realpath($resource->getResource()));
591
    }
592
593
    /**
594
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::compile
595
     */
596
    public function testCompilesClassDefinitionsOfLazyServices()
597
    {
598
        $container = new ContainerBuilder();
599
600
        $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking');
601
602
        $container->register('foo', 'BarClass');
603
        $container->getDefinition('foo')->setLazy(true);
604
605
        $container->compile();
606
607
        $classesPath = realpath(__DIR__.'/Fixtures/includes/classes.php');
608
        $matchingResources = array_filter(
609
            $container->getResources(),
610
            function (ResourceInterface $resource) use ($classesPath) {
611
                return $resource instanceof FileResource && $classesPath === realpath($resource->getResource());
0 ignored issues
show
Bug introduced by
The class Symfony\Component\Config\Resource\FileResource does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
612
            }
613
        );
614
615
        $this->assertNotEmpty($matchingResources);
616
    }
617
618
    /**
619
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getResources
620
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addResource
621
     */
622
    public function testResources()
623
    {
624
        $container = new ContainerBuilder();
625
        $container->addResource($a = new FileResource(__DIR__.'/Fixtures/xml/services1.xml'));
626
        $container->addResource($b = new FileResource(__DIR__.'/Fixtures/xml/services2.xml'));
627
        $resources = array();
628
        foreach ($container->getResources() as $resource) {
629
            if (false === strpos($resource, '.php')) {
630
                $resources[] = $resource;
631
            }
632
        }
633
        $this->assertEquals(array($a, $b), $resources, '->getResources() returns an array of resources read for the current configuration');
634
        $this->assertSame($container, $container->setResources(array()));
635
        $this->assertEquals(array(), $container->getResources());
636
    }
637
638
    /**
639
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::registerExtension
640
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getExtension
641
     */
642
    public function testExtension()
643
    {
644
        $container = new ContainerBuilder();
645
        $container->setResourceTracking(false);
646
647
        $container->registerExtension($extension = new \ProjectExtension());
648
        $this->assertTrue($container->getExtension('project') === $extension, '->registerExtension() registers an extension');
649
650
        $this->setExpectedException('LogicException');
651
        $container->getExtension('no_registered');
652
    }
653
654
    public function testRegisteredButNotLoadedExtension()
655
    {
656
        $extension = $this->getMock('Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface');
657
        $extension->expects($this->once())->method('getAlias')->will($this->returnValue('project'));
658
        $extension->expects($this->never())->method('load');
659
660
        $container = new ContainerBuilder();
661
        $container->setResourceTracking(false);
662
        $container->registerExtension($extension);
663
        $container->compile();
664
    }
665
666
    public function testRegisteredAndLoadedExtension()
667
    {
668
        $extension = $this->getMock('Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface');
669
        $extension->expects($this->exactly(2))->method('getAlias')->will($this->returnValue('project'));
670
        $extension->expects($this->once())->method('load')->with(array(array('foo' => 'bar')));
671
672
        $container = new ContainerBuilder();
673
        $container->setResourceTracking(false);
674
        $container->registerExtension($extension);
675
        $container->loadFromExtension('project', array('foo' => 'bar'));
676
        $container->compile();
677
    }
678
679
    public function testPrivateServiceUser()
680
    {
681
        $fooDefinition = new Definition('BarClass');
682
        $fooUserDefinition = new Definition('BarUserClass', array(new Reference('bar')));
683
        $container = new ContainerBuilder();
684
        $container->setResourceTracking(false);
685
686
        $fooDefinition->setPublic(false);
687
688
        $container->addDefinitions(array(
689
            'bar' => $fooDefinition,
690
            'bar_user' => $fooUserDefinition,
691
        ));
692
693
        $container->compile();
694
        $this->assertInstanceOf('BarClass', $container->get('bar_user')->bar);
695
    }
696
697
    /**
698
     * @expectedException \BadMethodCallException
699
     */
700
    public function testThrowsExceptionWhenSetServiceOnAFrozenContainer()
701
    {
702
        $container = new ContainerBuilder();
703
        $container->setResourceTracking(false);
704
        $container->setDefinition('a', new Definition('stdClass'));
705
        $container->compile();
706
        $container->set('a', new \stdClass());
707
    }
708
709
    /**
710
     * @expectedException \BadMethodCallException
711
     */
712
    public function testThrowsExceptionWhenAddServiceOnAFrozenContainer()
713
    {
714
        $container = new ContainerBuilder();
715
        $container->compile();
716
        $container->set('a', new \stdClass());
717
    }
718
719
    public function testNoExceptionWhenSetSyntheticServiceOnAFrozenContainer()
720
    {
721
        $container = new ContainerBuilder();
722
        $def = new Definition('stdClass');
723
        $def->setSynthetic(true);
724
        $container->setDefinition('a', $def);
725
        $container->compile();
726
        $container->set('a', $a = new \stdClass());
727
        $this->assertEquals($a, $container->get('a'));
728
    }
729
730
    /**
731
     * @group legacy
732
     */
733
    public function testLegacySetOnSynchronizedService()
734
    {
735
        $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
736
737
        $container = new ContainerBuilder();
738
        $container->register('baz', 'BazClass')
0 ignored issues
show
Deprecated Code introduced by
The method Symfony\Component\Depend...tion::setSynchronized() has been deprecated with message: since version 2.7, will be removed in 3.0.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
739
            ->setSynchronized(true)
740
        ;
741
        $container->register('bar', 'BarClass')
742
            ->addMethodCall('setBaz', array(new Reference('baz')))
743
        ;
744
745
        $container->set('baz', $baz = new \BazClass());
746
        $this->assertSame($baz, $container->get('bar')->getBaz());
747
748
        $container->set('baz', $baz = new \BazClass());
749
        $this->assertSame($baz, $container->get('bar')->getBaz());
750
    }
751
752
    /**
753
     * @group legacy
754
     */
755
    public function testLegacySynchronizedServiceWithScopes()
756
    {
757
        $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
758
759
        $container = new ContainerBuilder();
760
        $container->addScope(new Scope('foo'));
761
        $container->register('baz', 'BazClass')
0 ignored issues
show
Deprecated Code introduced by
The method Symfony\Component\Depend...tion::setSynchronized() has been deprecated with message: since version 2.7, will be removed in 3.0.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
762
            ->setSynthetic(true)
763
            ->setSynchronized(true)
764
            ->setScope('foo')
765
        ;
766
        $container->register('bar', 'BarClass')
767
            ->addMethodCall('setBaz', array(new Reference('baz', ContainerInterface::NULL_ON_INVALID_REFERENCE, false)))
768
        ;
769
        $container->compile();
770
771
        $container->enterScope('foo');
772
        $container->set('baz', $outerBaz = new \BazClass(), 'foo');
773
        $this->assertSame($outerBaz, $container->get('bar')->getBaz());
774
775
        $container->enterScope('foo');
776
        $container->set('baz', $innerBaz = new \BazClass(), 'foo');
777
        $this->assertSame($innerBaz, $container->get('bar')->getBaz());
778
        $container->leaveScope('foo');
779
780
        $this->assertNotSame($innerBaz, $container->get('bar')->getBaz());
781
        $this->assertSame($outerBaz, $container->get('bar')->getBaz());
782
783
        $container->leaveScope('foo');
784
    }
785
786
    /**
787
     * @expectedException \BadMethodCallException
788
     */
789
    public function testThrowsExceptionWhenSetDefinitionOnAFrozenContainer()
790
    {
791
        $container = new ContainerBuilder();
792
        $container->setResourceTracking(false);
793
        $container->compile();
794
        $container->setDefinition('a', new Definition());
795
    }
796
797
    /**
798
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getExtensionConfig
799
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::prependExtensionConfig
800
     */
801
    public function testExtensionConfig()
802
    {
803
        $container = new ContainerBuilder();
804
805
        $configs = $container->getExtensionConfig('foo');
806
        $this->assertEmpty($configs);
807
808
        $first = array('foo' => 'bar');
809
        $container->prependExtensionConfig('foo', $first);
810
        $configs = $container->getExtensionConfig('foo');
811
        $this->assertEquals(array($first), $configs);
812
813
        $second = array('ding' => 'dong');
814
        $container->prependExtensionConfig('foo', $second);
815
        $configs = $container->getExtensionConfig('foo');
816
        $this->assertEquals(array($second, $first), $configs);
817
    }
818
819
    public function testLazyLoadedService()
820
    {
821
        $loader = new ClosureLoader($container = new ContainerBuilder());
822
        $loader->load(function (ContainerBuilder $container) {
823
                $container->set('a', new \BazClass());
824
                $definition = new Definition('BazClass');
825
                $definition->setLazy(true);
826
                $container->setDefinition('a', $definition);
827
            }
828
        );
829
830
        $container->setResourceTracking(true);
831
832
        $container->compile();
833
834
        $class = new \BazClass();
835
        $reflectionClass = new \ReflectionClass($class);
836
837
        $r = new \ReflectionProperty($container, 'resources');
838
        $r->setAccessible(true);
839
        $resources = $r->getValue($container);
840
841
        $classInList = false;
842
        foreach ($resources as $resource) {
843
            if ($resource->getResource() === $reflectionClass->getFileName()) {
844
                $classInList = true;
845
                break;
846
            }
847
        }
848
849
        $this->assertTrue($classInList);
850
    }
851
}
852
853
class FooClass
854
{
855
}
856
857
class ProjectContainer extends ContainerBuilder
858
{
859
    public function getFoobazService()
860
    {
861
        throw new InactiveScopeException('foo', 'request');
862
    }
863
}
864