Completed
Push — class-param ( e73fc7...0f473f )
by Akihito
03:12
created

ClassParam::__invoke()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.6666
c 0
b 0
f 0
cc 4
nc 4
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Resource;
6
7
use BEAR\Resource\Exception\ParameterException;
8
use Ray\Di\InjectorInterface;
9
use ReflectionClass;
10
11
final class ClassParam implements ParamInterface
12
{
13
    /**
14
     * @var ReflectionClass
15
     */
16
    private $class;
17
18
    /**
19
     * @var \ReflectionParameter
20
     */
21
    private $parameter;
22
23
    public function __construct(ReflectionClass $class, \ReflectionParameter $parameter)
24
    {
25
        $this->class = $class;
26
        $this->parameter = $parameter;
27
    }
28
29
    /**
30
     * {@inheritdoc}
31
     */
32
    public function __invoke(string $varName, array $query, InjectorInterface $injector)
33
    {
34
        try {
35
            $props = $this->getProps($varName, $query, $injector);
36
        } catch (ParameterException $e) {
37
            if ($this->parameter->isDefaultValueAvailable()) {
38
                return $this->parameter->getDefaultValue();
39
            }
40
41
            throw $e;
42
        }
43
        $obj = $this->class->newInstanceWithoutConstructor();
44
        foreach ($props as $propName => $propValue) {
45
            $obj->{$propName} = $propValue;
46
        }
47
48
        return $obj;
49
    }
50
51
    private function getProps(string $varName, array $query, InjectorInterface $injector) : array
52
    {
53
        if (isset($query[$varName])) {
54
            return $query[$varName];
55
        }
56
        // try camelCase variable name
57
        $snakeName = ltrim(strtolower(preg_replace('/[A-Z]/', '_\0', $varName)), '_');
58
        if (isset($query[$snakeName])) {
59
            return $query[$snakeName];
60
        }
61
62
        unset($injector);
63
64
        throw new ParameterException($varName);
65
    }
66
}
67