Skip to content

Commit

Permalink
Resolver::autowireArgument() uses named arguments to skip optional pa…
Browse files Browse the repository at this point in the history
…rameters in PHP 8
  • Loading branch information
dg committed Dec 14, 2021
1 parent 850177e commit 687b8af
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 17 deletions.
10 changes: 5 additions & 5 deletions src/DI/PhpGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public function formatStatement(Statement $statement): string

case is_string($entity): // create class
return $arguments
? $this->formatPhp("new $entity(...?)", [$arguments])
? $this->formatPhp("new $entity(...?:)", [$arguments])
: $this->formatPhp("new $entity", []);

case is_array($entity):
Expand All @@ -147,16 +147,16 @@ public function formatStatement(Statement $statement): string
$inner = "($inner)";
}

return $this->formatPhp('?->?(...?)', [new Php\Literal($inner), $entity[1], $arguments]);
return $this->formatPhp('?->?(...?:)', [new Php\Literal($inner), $entity[1], $arguments]);

case $entity[0] instanceof Reference:
return $this->formatPhp('?->?(...?)', [$entity[0], $entity[1], $arguments]);
return $this->formatPhp('?->?(...?:)', [$entity[0], $entity[1], $arguments]);

case $entity[0] === '': // function call
return $this->formatPhp('?(...?)', [new Php\Literal($entity[1]), $arguments]);
return $this->formatPhp('?(...?:)', [new Php\Literal($entity[1]), $arguments]);

case is_string($entity[0]): // static method call
return $this->formatPhp('?::?(...?)', [new Php\Literal($entity[0]), $entity[1], $arguments]);
return $this->formatPhp('?::?(...?:)', [new Php\Literal($entity[0]), $entity[1], $arguments]);
}
}

Expand Down
34 changes: 25 additions & 9 deletions src/DI/Resolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,7 @@ public static function autowireArguments(
callable $getter
): array {
$optCount = 0;
$useName = false;
$num = -1;
$res = [];

Expand All @@ -549,40 +550,55 @@ public static function autowireArguments(
));
}

$res = array_merge($res, $arguments[$paramName]);
$variadics = $arguments[$paramName];
unset($arguments[$paramName]);
} else {
$res = array_merge($res, $arguments);
$variadics = array_merge($arguments);
$arguments = [];
}

if ($useName) {
$res[$paramName] = $variadics;
} else {
$res = array_merge($res, $variadics);
}

$optCount = 0;
break;

} elseif (array_key_exists($paramName, $arguments)) {
$res[$num] = $arguments[$paramName];
$res[$useName ? $paramName : $num] = $arguments[$paramName];
unset($arguments[$paramName], $arguments[$num]);

} elseif (array_key_exists($num, $arguments)) {
$res[$num] = $arguments[$num];
$res[$useName ? $paramName : $num] = $arguments[$num];
unset($arguments[$num]);

} elseif (($aw = self::autowireArgument($param, $getter)) !== null) {
$res[$num] = $aw;
$res[$useName ? $paramName : $num] = $aw;

} elseif (PHP_VERSION_ID >= 80000) {
if ($param->isOptional()) {
$useName = true;
} else {
$res[$num] = null;
}

} else {
$res[$num] = $param->isDefaultValueAvailable()
? Reflection::getParameterDefaultValue($param)
: null;
}

$optCount = $param->isOptional() && $res[$num] === ($param->isDefaultValueAvailable() ? Reflection::getParameterDefaultValue($param) : null)
? $optCount + 1
: 0;
if (PHP_VERSION_ID < 80000) {
$optCount = $param->isOptional() && $res[$num] === ($param->isDefaultValueAvailable() ? Reflection::getParameterDefaultValue($param) : null)
? $optCount + 1
: 0;
}
}

// extra parameters
while (!$optCount && array_key_exists(++$num, $arguments)) {
while (!$useName && !$optCount && array_key_exists(++$num, $arguments)) {
$res[$num] = $arguments[$num];
unset($arguments[$num]);
}
Expand Down
1 change: 1 addition & 0 deletions tests/DI/Compiler.referenceBug.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

/**
* Test: Nette\DI\Compiler and service referencing.
* @phpVersion < 8.0
*/

declare(strict_types=1);
Expand Down
10 changes: 10 additions & 0 deletions tests/DI/Resolver.autowireArguments.81.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,13 @@ Assert::exception(function () {
function () {}
);
}, Nette\InvalidStateException::class, 'Parameter $x in {closure}%a?% has intersection type, so its value must be specified.');

// object as default
Assert::same(
['b' => 10],
Resolver::autowireArguments(
new ReflectionFunction(function ($a = new stdClass, $b = null) {}),
[1 => 10],
function () {}
),
);
6 changes: 3 additions & 3 deletions tests/DI/Resolver.autowireArguments.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Assert::equal(

// optional arguments + positional
Assert::equal(
[1, 'new'],
PHP_VERSION_ID < 80000 ? [1, 'new'] : ['b' => 'new'],
Resolver::autowireArguments(
new ReflectionFunction(function ($a = 1, $b = 2) {}),
[1 => 'new'],
Expand All @@ -90,7 +90,7 @@ Assert::equal(

// optional arguments + named
Assert::equal(
[1, 'new'],
PHP_VERSION_ID < 80000 ? [1, 'new'] : ['b' => 'new'],
Resolver::autowireArguments(
new ReflectionFunction(function ($a = 1, $b = 2) {}),
['b' => 'new'],
Expand All @@ -100,7 +100,7 @@ Assert::equal(

// optional arguments + variadics
Assert::equal(
[1, 'new1', 'new2'],
PHP_VERSION_ID < 80000 ? [1, 'new1', 'new2'] : ['args' => ['new1', 'new2']],
Resolver::autowireArguments(
new ReflectionFunction(function ($a = 1, ...$args) {}),
[1 => 'new1', 2 => 'new2'],
Expand Down

0 comments on commit 687b8af

Please sign in to comment.