Skip to content

Commit c005bde

Browse files
committed
added dynamic parameters [Closes #61]
1 parent 929bf71 commit c005bde

File tree

6 files changed

+103
-11
lines changed

6 files changed

+103
-11
lines changed

src/DI/Compiler.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ class Compiler
3333
/** @var string */
3434
private $className = 'Container';
3535

36+
/** @var string[] */
37+
private $dynamicParams = [];
38+
3639
/** @var array reserved section names */
3740
private static $reserved = ['services' => 1, 'parameters' => 1];
3841

@@ -125,6 +128,17 @@ public function getConfig()
125128
}
126129

127130

131+
/**
132+
* Sets the names of dynamic parameters.
133+
* @return static
134+
*/
135+
public function selectDynamicParameters(array $names)
136+
{
137+
$this->dynamicParams = $names;
138+
return $this;
139+
}
140+
141+
128142
/**
129143
* Adds dependencies to the list.
130144
* @param array of ReflectionClass|\ReflectionFunctionAbstract|string
@@ -168,9 +182,13 @@ public function compile()
168182
/** @internal */
169183
public function processParameters()
170184
{
171-
if (isset($this->config['parameters'])) {
172-
$this->builder->parameters = Helpers::expand($this->config['parameters'], $this->config['parameters'], TRUE);
185+
$params = isset($this->config['parameters']) ? $this->config['parameters'] : [];
186+
foreach ($this->dynamicParams as $key) {
187+
$params[$key] = array_key_exists($key, $params)
188+
? ContainerBuilder::literal('isset($this->parameters[?]) ? $this->parameters[?] : ?', [$key, ContainerBuilder::literal('?'), $key, $params[$key]])
189+
: ContainerBuilder::literal('$this->parameters[?]', [$key]);
173190
}
191+
$this->builder->parameters = Helpers::expand($params, $params, TRUE);
174192
}
175193

176194

src/DI/Helpers.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
namespace Nette\DI;
99

1010
use Nette;
11+
use Nette\PhpGenerator\PhpLiteral;
1112
use Nette\Utils\Reflection;
1213

1314

@@ -68,7 +69,7 @@ public static function expand($var, array $params, $recursive = FALSE)
6869
if (strlen($part) + 2 === strlen($var)) {
6970
return $val;
7071
}
71-
if ($val instanceof Nette\PhpGenerator\PhpLiteral) {
72+
if ($val instanceof PhpLiteral) {
7273
$php = TRUE;
7374
} elseif (!is_scalar($val)) {
7475
throw new Nette\InvalidArgumentException("Unable to concatenate non-scalar parameter '$part' into '$var'.");
@@ -78,8 +79,8 @@ public static function expand($var, array $params, $recursive = FALSE)
7879
}
7980
if ($php) {
8081
$res = array_filter($res, function ($val) { return $val !== ''; });
81-
$res = array_map(function ($val) { return is_string($val) ? var_export($val, TRUE) : $val; }, $res);
82-
return new Nette\PhpGenerator\PhpLiteral(implode(' . ', $res));
82+
$res = array_map(function ($val) { return $val instanceof PhpLiteral ? "($val)" : var_export((string) $val, TRUE); }, $res);
83+
return new PhpLiteral(implode(' . ', $res));
8384
}
8485
return implode('', $res);
8586
}

src/DI/PhpGenerator.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ public function generate($className)
5252
$containerClass = $this->generatedClasses[] = new Nette\PhpGenerator\ClassType($this->className);
5353
$containerClass->setExtends(Container::class);
5454
$containerClass->addMethod('__construct')
55-
->addBody('parent::__construct(?);', [$this->builder->parameters]);
55+
->addBody('$this->parameters = $params;')
56+
->addBody('$this->parameters += ?;', [$this->builder->parameters])
57+
->addParameter('params', [])
58+
->setTypeHint('array');
5659

5760
$definitions = $this->builder->getDefinitions();
5861
ksort($definitions);
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Nette\DI;
6+
use Nette\DI\Statement;
7+
use Tester\Assert;
8+
9+
10+
require __DIR__ . '/../bootstrap.php';
11+
12+
13+
class Service
14+
{
15+
public $arg;
16+
17+
function __construct($arg)
18+
{
19+
$this->arg = $arg;
20+
}
21+
}
22+
23+
test(function () {
24+
$compiler = new DI\Compiler;
25+
$compiler->selectDynamicParameters(['dynamic']);
26+
$container = createContainer($compiler, '
27+
services:
28+
one: Service(%dynamic%)
29+
', ['dynamic' => 123]);
30+
Assert::same(123, $container->getService('one')->arg);
31+
});
32+
33+
34+
test(function () {
35+
$compiler = new DI\Compiler;
36+
$compiler->selectDynamicParameters(['dynamic']);
37+
$container = createContainer($compiler, '
38+
parameters:
39+
dynamic: default
40+
41+
services:
42+
one: Service(%dynamic%)
43+
');
44+
Assert::same('default', $container->getService('one')->arg);
45+
});
46+
47+
48+
test(function () {
49+
$compiler = new DI\Compiler;
50+
$compiler->selectDynamicParameters(['dynamic']);
51+
$container = createContainer($compiler, '
52+
parameters:
53+
dynamic: default
54+
55+
services:
56+
one: Service(%dynamic%)
57+
', ['dynamic' => 'overwritten']);
58+
Assert::same('overwritten', $container->getService('one')->arg);
59+
});
60+
61+
62+
test(function () {
63+
$compiler = new DI\Compiler;
64+
$compiler->selectDynamicParameters(['dynamic']);
65+
$container = createContainer($compiler, '
66+
parameters:
67+
expand: hello%dynamic%
68+
', ['dynamic' => 123]);
69+
Assert::same(['dynamic' => 123, 'expand' => 'hello123'], $container->parameters);
70+
});

tests/DI/Helpers.expand().phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ Assert::same(
3030
);
3131

3232
Assert::equal(new PhpLiteral('func()'), Helpers::expand('%key%', ['key' => new PhpLiteral('func()')]));
33-
Assert::equal(new PhpLiteral("'text' . func()"), Helpers::expand('text%key%', ['key' => new PhpLiteral('func()')]));
34-
Assert::equal(new PhpLiteral("func() . 'text'"), Helpers::expand('%key%text', ['key' => new PhpLiteral('func()')]));
35-
Assert::equal(new PhpLiteral("'a' . func() . 'b' . 123 . func() . 'c'"), Helpers::expand('a%key1%b%key2%%key1%c', ['key1' => new PhpLiteral('func()'), 'key2' => 123]));
33+
Assert::equal(new PhpLiteral("'text' . (func())"), Helpers::expand('text%key%', ['key' => new PhpLiteral('func()')]));
34+
Assert::equal(new PhpLiteral("(func()) . 'text'"), Helpers::expand('%key%text', ['key' => new PhpLiteral('func()')]));
35+
Assert::equal(new PhpLiteral("'a' . (func()) . 'b' . '123' . (func()) . 'c'"), Helpers::expand('a%key1%b%key2%%key1%c', ['key1' => new PhpLiteral('func()'), 'key2' => 123]));
3636

3737

3838
Assert::exception(function () {

tests/bootstrap.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public static function fetch()
4646

4747

4848
/** @return Nette\DI\Container */
49-
function createContainer($source, $config = NULL)
49+
function createContainer($source, $config = NULL, $params = [])
5050
{
5151
$class = 'Container' . md5((string) lcg_value());
5252
if ($source instanceof Nette\DI\ContainerBuilder) {
@@ -66,5 +66,5 @@ function createContainer($source, $config = NULL)
6666

6767
file_put_contents(TEMP_DIR . '/code.php', "<?php\n\n$code");
6868
require TEMP_DIR . '/code.php';
69-
return new $class;
69+
return new $class($params);
7070
}

0 commit comments

Comments
 (0)