From ab1100426053c2df3fc0f1b9b60eeb800591ebb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mat=C4=9Bjka?= Date: Tue, 12 Jul 2016 13:50:00 +0200 Subject: [PATCH 1/6] ContainerBuilder::resolveImplement: use isDefaultValueAvailable instead of isOptional (#121) --- src/DI/ContainerBuilder.php | 2 +- tests/DI/Compiler.generatedFactory.phpt | 31 +++++++++++++++++++ tests/DI/files/compiler.generatedFactory.neon | 1 + 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/DI/ContainerBuilder.php b/src/DI/ContainerBuilder.php index 703eead2c..588a02f17 100644 --- a/src/DI/ContainerBuilder.php +++ b/src/DI/ContainerBuilder.php @@ -440,7 +440,7 @@ private function resolveImplement(ServiceDefinition $def, $name) throw new ServiceCreationException("Unused parameter \${$param->getName()} when implementing method $interface::$methodName()" . ($hint ? ", did you mean \${$hint}?" : '.')); } $paramDef = $hint . ' ' . $param->getName(); - if ($param->isOptional()) { + if ($param->isDefaultValueAvailable()) { $def->parameters[$paramDef] = $param->getDefaultValue(); } else { $def->parameters[] = $paramDef; diff --git a/tests/DI/Compiler.generatedFactory.phpt b/tests/DI/Compiler.generatedFactory.phpt index 839ab7d6f..e6e2c5c61 100644 --- a/tests/DI/Compiler.generatedFactory.phpt +++ b/tests/DI/Compiler.generatedFactory.phpt @@ -97,6 +97,28 @@ interface IFooFactory public function create(Baz $baz = NULL); } +class Dolor +{ + public $bar; + + public $foo; + + public function __construct(Bar $bar = NULL, $foo) + { + $this->bar = $bar; + $this->foo = $foo; + } +} + +interface DolorFactory +{ + + /** @return Dolor */ + public function create(Bar $bar = NULL, $foo); + +} + + class TestClass { public $foo; @@ -220,6 +242,15 @@ $obj = $container->getService('factory5')->create('bar'); Assert::same('foo', $obj->foo); Assert::same('bar', $obj->bar); +Assert::type(DolorFactory::class, $factory = $container->getService('dolorFactory')); +Assert::type(Dolor::class, $obj = $factory->create($bar = new Bar(), 'abc')); +Assert::same($bar, $obj->bar); +Assert::same('abc', $obj->foo); + +Assert::type(Dolor::class, $obj = $factory->create(NULL, 'abc')); +Assert::null($obj->bar); +Assert::same('abc', $obj->foo); + class Bad1 { diff --git a/tests/DI/files/compiler.generatedFactory.neon b/tests/DI/files/compiler.generatedFactory.neon index d4583e97f..b89ef067c 100644 --- a/tests/DI/files/compiler.generatedFactory.neon +++ b/tests/DI/files/compiler.generatedFactory.neon @@ -31,3 +31,4 @@ services: factory5: implement: ITestClassFactory arguments: ['foo'] + dolorFactory: DolorFactory From a4149834614604761e0552a33f7a2de4dafabbea Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 13 Jul 2016 13:04:41 +0200 Subject: [PATCH 2/6] DIExtension: added option 'parentClass' [Closes nette/bootstrap#52] --- src/DI/Extensions/DIExtension.php | 5 +++++ tests/DI/DIExtension.parentClass.phpt | 26 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 tests/DI/DIExtension.parentClass.phpt diff --git a/src/DI/Extensions/DIExtension.php b/src/DI/Extensions/DIExtension.php index 4d314360c..35023d1e6 100644 --- a/src/DI/Extensions/DIExtension.php +++ b/src/DI/Extensions/DIExtension.php @@ -19,6 +19,7 @@ class DIExtension extends Nette\DI\CompilerExtension 'debugger' => TRUE, 'accessors' => FALSE, 'excluded' => [], + 'parentClass' => NULL, ]; /** @var bool */ @@ -45,6 +46,10 @@ public function loadConfiguration() public function afterCompile(Nette\PhpGenerator\ClassType $class) { + if ($this->config['parentClass']) { + $class->setExtends($this->config['parentClass']); + } + $initialize = $class->getMethod('initialize'); $builder = $this->getContainerBuilder(); diff --git a/tests/DI/DIExtension.parentClass.phpt b/tests/DI/DIExtension.parentClass.phpt new file mode 100644 index 000000000..083038c55 --- /dev/null +++ b/tests/DI/DIExtension.parentClass.phpt @@ -0,0 +1,26 @@ +addExtension('di', new DIExtension); +$container = createContainer($compiler, ' +di: + parentClass: MyContainer +', 'neon'); + +Assert::type(MyContainer::class, $container); From 3a0fc37c841c5cf6430f285a042110b67acc8685 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 14 Jul 2016 16:21:25 +0200 Subject: [PATCH 3/6] travis: added PHP 7.1 --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index a7eec88c7..ca9be8193 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,12 +2,16 @@ language: php php: - 5.6 - 7.0 + - 7.1 matrix: include: - php: 5.6 env: dependencies="--prefer-lowest --prefer-stable" + allow_failures: + - php: 7.1 + script: - vendor/bin/tester tests -s -c tests/php-unix.ini $coverage - php temp/code-checker/src/code-checker.php --short-arrays From 6f645e613683f141cab2cd48bbd6484cd2d233a9 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 20 Jul 2016 23:56:51 +0200 Subject: [PATCH 4/6] DependencyChecker: prevents fatal error when undefined constant is used as default value of method parameter --- src/DI/DependencyChecker.php | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/DI/DependencyChecker.php b/src/DI/DependencyChecker.php index 21d245576..d52726e9f 100644 --- a/src/DI/DependencyChecker.php +++ b/src/DI/DependencyChecker.php @@ -108,7 +108,7 @@ private static function calculateHash($classes, $functions) $name, $method->getName(), $method->getDocComment(), - implode('', $method->getParameters()), + self::hashParameters($method), PHP_VERSION >= 70000 ? $method->getReturnType() : NULL ]; } @@ -130,7 +130,7 @@ private static function calculateHash($classes, $functions) $name, $class ? PhpReflection::getUseStatements($method->getDeclaringClass()) : NULL, $method->getDocComment(), - implode('', $method->getParameters()), + self::hashParameters($method), PHP_VERSION >= 70000 ? $method->getReturnType() : NULL ]; } @@ -138,4 +138,20 @@ private static function calculateHash($classes, $functions) return md5(serialize($hash)); } + + private static function hashParameters(\ReflectionFunctionAbstract $method) + { + $res = []; + foreach ($method->getParameters() as $param) { + $res[] = [ + $param->getName(), + PhpReflection::getParameterType($param), + $param->isDefaultValueAvailable() + ? ($param->isDefaultValueConstant() ? $param->getDefaultValueConstantName() : [$param->getDefaultValue()]) + : NULL + ]; + } + return $res; + } + } From 4f05d0c17e62e5cbee61cb38046fc0f39e50ff1a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 21 Jul 2016 15:46:46 +0200 Subject: [PATCH 5/6] PhpReflection::parseAnnotation() regexp fix --- src/DI/PhpReflection.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/DI/PhpReflection.php b/src/DI/PhpReflection.php index e0a6f3c50..832076b98 100644 --- a/src/DI/PhpReflection.php +++ b/src/DI/PhpReflection.php @@ -31,6 +31,7 @@ public static function parseAnnotation(\Reflector $ref, $name) } $ok = TRUE; } + $name = preg_quote($name, '#'); if ($ref->getDocComment() && preg_match("#[\\s*]@$name(?:\\s++([^@]\\S*)?|$)#", trim($ref->getDocComment(), '/*'), $m)) { return isset($m[1]) ? $m[1] : ''; } From e3ae78a0f6cf921968e3298f57a7628d27feef72 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sat, 30 Jul 2016 17:30:12 +0200 Subject: [PATCH 6/6] composer: requires PHP extension tokenizer --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index e6f076fc0..ef4a5da58 100644 --- a/composer.json +++ b/composer.json @@ -15,6 +15,7 @@ ], "require": { "php": ">=5.6.0", + "ext-tokenizer": "*", "nette/neon": "^2.3.3", "nette/php-generator": "^2.4", "nette/utils": "^2.4"