Completed
Push — master ( 3c559e...05a21e )
by Nikola
02:55
created

Cascader::marshalArguments()   C

Complexity

Conditions 8
Paths 15

Size

Total Lines 39
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 8

Importance

Changes 0
Metric Value
dl 0
loc 39
ccs 20
cts 20
cp 1
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 21
nc 15
nop 2
crap 8
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cascader;
6
7
use BetterReflection\Reflection\ReflectionClass;
8
use Cascader\Exception\InvalidClassException;
9
use Cascader\Exception\InvalidOptionsException;
10
use Cascader\Exception\OptionNotSetException;
11
use phpDocumentor\Reflection\Types\Object_;
12
13
class Cascader
14
{
15
    /**
16
     * @param string $className
17
     * @param array $options
18
     *
19
     * @throws InvalidClassException
20
     * @throws InvalidOptionsException
21
     *
22
     * @return object
23
     */
24 7
    public static function create(string $className, array $options)
25
    {
26 7
        if (!class_exists($className)) {
27
            throw InvalidClassException::forNonExistingClass($className);
28
        }
29
30 7
        $reflectionClass = ReflectionClass::createFromName($className);
31
32 7
        if (!$reflectionClass->isInstantiable()) {
33
            throw InvalidClassException::forNonInstantiableClass($className);
34
        }
35
36 7
        $options = Options::fromArray($options);
37
38 6
        $arguments = self::marshalArguments($options, $reflectionClass);
39
40 5
        return new $className(...$arguments);
41
    }
42
43 6
    protected static function marshalArguments(Options $options, ReflectionClass $reflectionClass) : array
44
    {
45 6
        if (!$reflectionClass->hasMethod('__construct')) {
46 1
            return [];
47
        }
48
49 5
        $arguments = [];
50
51 5
        $className = $reflectionClass->getName();
52 5
        $constructorParameters = $reflectionClass->getConstructor()->getParameters();
53
54 5
        foreach ($constructorParameters as $parameter) {
55
            /* @var $parameter \BetterReflection\Reflection\ReflectionParameter */
56 5
            $parameterName = $parameter->getName();
57
58 5
            $argument = null;
59
            try {
60 5
                $argument = $options->get($parameterName);
61
62 4
                if (null !== ($parameterType = $parameter->getType())) {
63 4
                    $parameterTypeObject = $parameterType->getTypeObject();
64
65 4
                    if (is_array($argument) && $parameterTypeObject instanceof Object_) {
66 4
                        $argument = static::create((string) $parameterTypeObject->getFqsen(), $argument);
67
                    }
68
                }
69 4
            } catch (OptionNotSetException $ex) {
70 4
                if (!$parameter->isOptional()) {
71 1
                    throw InvalidOptionsException::forMissingMandatoryParameter($className, $parameterName);
72
                }
73
74 3
                $argument = $parameter->getDefaultValue();
75
            }
76
77 4
            $arguments[] = $argument;
78
        }
79
80 4
        return $arguments;
81
    }
82
}
83