Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit f23e460

Browse filesBrowse files
committed
[DI] Allow to count on lazy collection arguments
1 parent 2183f98 commit f23e460
Copy full SHA for f23e460

File tree

7 files changed

+125
-16
lines changed
Filter options

7 files changed

+125
-16
lines changed

‎src/Symfony/Component/DependencyInjection/Argument/RewindableGenerator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Argument/RewindableGenerator.php
+17-2Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,19 @@
1414
/**
1515
* @internal
1616
*/
17-
class RewindableGenerator implements \IteratorAggregate
17+
class RewindableGenerator implements \IteratorAggregate, \Countable
1818
{
1919
private $generator;
20+
private $count;
2021

21-
public function __construct(callable $generator)
22+
/**
23+
* @param callable $generator
24+
* @param int|callable $count
25+
*/
26+
public function __construct(callable $generator, $count)
2227
{
2328
$this->generator = $generator;
29+
$this->count = $count;
2430
}
2531

2632
public function getIterator()
@@ -29,4 +35,13 @@ public function getIterator()
2935

3036
return $g();
3137
}
38+
39+
public function count()
40+
{
41+
if (is_callable($count = $this->count)) {
42+
$this->count = $count();
43+
}
44+
45+
return $this->count;
46+
}
3247
}

‎src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/ContainerBuilder.php
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,19 @@ public function resolveServices($value)
10001000

10011001
yield $k => $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($v)));
10021002
}
1003+
}, function () use ($value) {
1004+
$count = 0;
1005+
foreach ($value->getValues() as $v) {
1006+
foreach (self::getServiceConditionals($v) as $s) {
1007+
if (!$this->has($s)) {
1008+
continue 2;
1009+
}
1010+
}
1011+
1012+
++$count;
1013+
}
1014+
1015+
return $count;
10031016
});
10041017
} elseif ($value instanceof ClosureProxyArgument) {
10051018
$parameterBag = $this->getParameterBag();

‎src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+33-7Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,19 +1362,36 @@ private function instantiateProxy($class, $args, $useConstructor)
13621362
*/
13631363
private function wrapServiceConditionals($value, $code, &$isUnconditional = null, $containerRef = '$this')
13641364
{
1365-
if ($isUnconditional = !$services = ContainerBuilder::getServiceConditionals($value)) {
1365+
if ($isUnconditional = !$condition = $this->getServiceConditionals($value, $containerRef)) {
13661366
return $code;
13671367
}
13681368

1369+
// re-indent the wrapped code
1370+
$code = implode("\n", array_map(function ($line) { return $line ? ' '.$line : $line; }, explode("\n", $code)));
1371+
1372+
return sprintf(" if (%s) {\n%s }\n", $condition, $code);
1373+
}
1374+
1375+
/**
1376+
* Get the conditions to execute for conditional services.
1377+
*
1378+
* @param string $value
1379+
* @param string $containerRef
1380+
*
1381+
* @return null|string
1382+
*/
1383+
private function getServiceConditionals($value, $containerRef = '$this')
1384+
{
1385+
if (!$services = ContainerBuilder::getServiceConditionals($value)) {
1386+
return null;
1387+
}
1388+
13691389
$conditions = array();
13701390
foreach ($services as $service) {
13711391
$conditions[] = sprintf("%s->has('%s')", $containerRef, $service);
13721392
}
13731393

1374-
// re-indent the wrapped code
1375-
$code = implode("\n", array_map(function ($line) { return $line ? ' '.$line : $line; }, explode("\n", $code)));
1376-
1377-
return sprintf(" if (%s) {\n%s }\n", implode(' && ', $conditions), $code);
1394+
return implode(' && ', $conditions);
13781395
}
13791396

13801397
/**
@@ -1524,17 +1541,26 @@ private function dumpValue($value, $interpolate = true)
15241541

15251542
return sprintf('array(%s)', implode(', ', $code));
15261543
} elseif ($value instanceof IteratorArgument) {
1544+
$countCode = array();
1545+
$countCode[] = 'function () {';
1546+
$operands = array(0);
1547+
15271548
$code = array();
1528-
$code[] = 'new RewindableGenerator(function() {';
1549+
$code[] = 'new RewindableGenerator(function () {';
15291550
foreach ($value->getValues() as $k => $v) {
1551+
($c = $this->getServiceConditionals($v)) ? $operands[] = "(int) ($c)" : ++$operands[0];
15301552
$v = $this->wrapServiceConditionals($v, sprintf(" yield %s => %s;\n", $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate)));
15311553
foreach (explode("\n", $v) as $v) {
15321554
if ($v) {
15331555
$code[] = ' '.$v;
15341556
}
15351557
}
15361558
}
1537-
$code[] = ' })';
1559+
1560+
$countCode[] = sprintf(' return %s;', implode(' + ', $operands));
1561+
$countCode[] = ' }';
1562+
1563+
$code[] = sprintf(' }, %s)', count($operands) > 1 ? implode("\n", $countCode) : $operands[0]);
15381564

15391565
return implode("\n", $code);
15401566
} elseif ($value instanceof Definition) {
+52Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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\Component\DependencyInjection\Tests\Argument;
13+
14+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
15+
16+
class RewindableGeneratorTest extends \PHPUnit_Framework_TestCase
17+
{
18+
public function testImplementsCountable()
19+
{
20+
$this->assertInstanceOf(\Countable::class, new RewindableGenerator(function () {
21+
yield 1;
22+
}, 1));
23+
}
24+
25+
public function testCountUsesProvidedValue()
26+
{
27+
$generator = new RewindableGenerator(function () {
28+
yield 1;
29+
}, 3);
30+
31+
$this->assertCount(3, $generator);
32+
}
33+
34+
public function testCountUsesProvidedValueAsCallback()
35+
{
36+
$called = 0;
37+
$generator = new RewindableGenerator(function () {
38+
yield 1;
39+
}, function () use (&$called) {
40+
++$called;
41+
42+
return 3;
43+
});
44+
45+
$this->assertSame(0, $called, 'Count callback is called lazily');
46+
$this->assertCount(3, $generator);
47+
48+
count($generator);
49+
50+
$this->assertSame(1, $called, 'Count callback is called only once');
51+
}
52+
}

‎src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ public function testCreateServiceWithIteratorArgument()
422422

423423
$lazyContext = $builder->get('lazy_context');
424424
$this->assertInstanceOf(RewindableGenerator::class, $lazyContext->lazyValues);
425+
$this->assertCount(1, $lazyContext->lazyValues);
425426

426427
$i = 0;
427428
foreach ($lazyContext->lazyValues as $k => $v) {

‎src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php
+5-3Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,13 +314,13 @@ protected function getFooWithInlineService()
314314
*/
315315
protected function getLazyContextService()
316316
{
317-
return $this->services['lazy_context'] = new \LazyContext(new RewindableGenerator(function() {
317+
return $this->services['lazy_context'] = new \LazyContext(new RewindableGenerator(function () {
318318
yield 0 => 'foo';
319319
yield 1 => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'};
320320
yield 2 => array($this->getParameter('foo') => 'foo is '.$this->getParameter('foo').'', 'foobar' => $this->getParameter('foo'));
321321
yield 3 => true;
322322
yield 4 => $this;
323-
}));
323+
}, 5));
324324
}
325325

326326
/**
@@ -333,11 +333,13 @@ protected function getLazyContextService()
333333
*/
334334
protected function getLazyContextIgnoreInvalidRefService()
335335
{
336-
return $this->services['lazy_context_ignore_invalid_ref'] = new \LazyContext(new RewindableGenerator(function() {
336+
return $this->services['lazy_context_ignore_invalid_ref'] = new \LazyContext(new RewindableGenerator(function () {
337337
yield 0 => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'};
338338
if ($this->has('invalid')) {
339339
yield 1 => $this->get('invalid', ContainerInterface::NULL_ON_INVALID_REFERENCE);
340340
}
341+
}, function () {
342+
return 1 + (int) ($this->has('invalid'));
341343
}));
342344
}
343345

‎src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php
+4-4Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -313,13 +313,13 @@ protected function getFooWithInlineService()
313313
*/
314314
protected function getLazyContextService()
315315
{
316-
return $this->services['lazy_context'] = new \LazyContext(new RewindableGenerator(function() {
316+
return $this->services['lazy_context'] = new \LazyContext(new RewindableGenerator(function () {
317317
yield 0 => 'foo';
318318
yield 1 => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'};
319319
yield 2 => array('bar' => 'foo is bar', 'foobar' => 'bar');
320320
yield 3 => true;
321321
yield 4 => $this;
322-
}));
322+
}, 5));
323323
}
324324

325325
/**
@@ -332,9 +332,9 @@ protected function getLazyContextService()
332332
*/
333333
protected function getLazyContextIgnoreInvalidRefService()
334334
{
335-
return $this->services['lazy_context_ignore_invalid_ref'] = new \LazyContext(new RewindableGenerator(function() {
335+
return $this->services['lazy_context_ignore_invalid_ref'] = new \LazyContext(new RewindableGenerator(function () {
336336
yield 0 => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'};
337-
}));
337+
}, 1));
338338
}
339339

340340
/**

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.