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

Cascader   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 70
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 8

Test Coverage

Coverage 93.1%

Importance

Changes 0
Metric Value
wmc 11
lcom 0
cbo 8
dl 0
loc 70
ccs 27
cts 29
cp 0.931
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A create() 0 18 3
C marshalArguments() 0 39 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