Passed
Pull Request — master (#62)
by Wilmer
40:49 queued 27:24
created

ArgumentException::getClosureSignature()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 32
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 23
nc 7
nop 1
dl 0
loc 32
ccs 22
cts 22
cp 1
crap 6
rs 8.9297
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Injector;
6
7
use ReflectionNamedType;
8
use ReflectionUnionType;
9
10
abstract class ArgumentException extends \InvalidArgumentException
11
{
12
    protected const EXCEPTION_MESSAGE = 'Something is wrong with argument "%s" when calling "%s"%s.';
13
14 35
    public function __construct(\ReflectionFunctionAbstract $reflection, string $parameter)
15
    {
16 35
        $function = $reflection->getName();
17
        /** @psalm-var class-string|null $class */
18 35
        $class = $reflection->class ?? null;
19
20 35
        if ($class === null) {
21 29
            $method = $function;
22 29
            if (substr($method, -9) === '{closure}') {
23 29
                $method = $this->getClosureSignature($reflection);
24
            }
25
        } else {
26 6
            $method = "{$class}::{$function}";
27
        }
28
29 35
        $fileName = $reflection->getFileName();
30 35
        $line = $reflection->getStartLine();
31
32 35
        $fileAndLine = '';
33 35
        if (!empty($fileName)) {
34 26
            $fileAndLine = " in \"$fileName\" at line $line";
35
        }
36
37 35
        parent::__construct(sprintf((string)static::EXCEPTION_MESSAGE, $parameter, $method, $fileAndLine));
38
    }
39
40 17
    private function getClosureSignature(\ReflectionFunctionAbstract $reflection): string
41
    {
42 17
        $closureParameters = [];
43 17
        $append = static function (string &$parameterString, bool $condition, string $postfix): void {
44 16
            if ($condition) {
45 4
                $parameterString .= $postfix;
46
            }
47
        };
48 17
        foreach ($reflection->getParameters() as $parameter) {
49 16
            $parameterString = '';
50
            /** @var ReflectionNamedType|ReflectionUnionType|null $type */
51 16
            $type = $parameter->getType();
52 16
            if ($type instanceof ReflectionNamedType) {
53 13
                $append($parameterString, $parameter->allowsNull(), '?');
54 13
                $parameterString .= $type->getName() . ' ';
55 7
            } elseif ($type instanceof ReflectionUnionType) {
56
                /** @var ReflectionNamedType[] $types */
57 3
                $types = $type->getTypes();
58 3
                $parameterString .= implode('|', array_map(
59 3
                    static fn (ReflectionNamedType $r) => $r->getName(),
60
                    $types
61
                )) . ' ';
62
            }
63 16
            $append($parameterString, $parameter->isPassedByReference(), '&');
64 16
            $append($parameterString, $parameter->isVariadic(), '...');
65 16
            $parameterString .= '$' . $parameter->name;
66 16
            if ($parameter->isDefaultValueAvailable()) {
67 3
                $parameterString .= ' = ' . var_export($parameter->getDefaultValue(), true);
68
            }
69 16
            $closureParameters[] = $parameterString;
70
        }
71 17
        return 'function (' . implode(', ', $closureParameters) . ')';
72
    }
73
}
74