Builder   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 96
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 0

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 96
ccs 28
cts 28
cp 1
rs 10
c 0
b 0
f 0
wmc 11
lcom 0
cbo 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A retrieveArguments() 0 17 4
A create() 0 14 4
A createIgnoreCase() 0 17 3
1
<?php
2
namespace ConstructNamedParameters;
3
4
abstract class Builder
5
{
6
    /**
7
     * Retrive by reflection the constructor arguments from a class.
8
     * The information is statically stored in the function so call two times
9
     * the same class will only run one Reflection
10
     *
11
     * The array is a map of keys as the name of the parameter and value as the
12
     * default value (if any) of the parameter.
13
     *
14
     * The constructor (int $value, array $data = [], $type = 5) returns:
15
     * [
16
     *     'value' => null,
17
     *     'data' => [],
18
     *     'type' => 5
19
     * ]
20
     *
21
     * @param string $className
22
     *
23
     * @return array
24
     */
25 15
    public static function retrieveArguments($className)
26
    {
27 15
        static $cache = [];
28
29 15
        if (! array_key_exists($className, $cache)) {
30 5
            $reflection = new \ReflectionClass($className);
31 4
            $constructor = $reflection->getConstructor();
32 4
            $parameters = $constructor->getParameters();
33 4
            $buildArgs = [];
34 4
            foreach ($parameters as $parameter) {
35 4
                $buildArgs[$parameter->getName()] = ($parameter->isOptional()) ? $parameter->getDefaultValue() : null;
36
            }
37 4
            $cache[$className] = $buildArgs;
38
        }
39
40 14
        return $cache[$className];
41
    }
42
43
    /**
44
     * Create an instance of a class using the given named parameters
45
     *
46
     * @param string $classname
47
     * @param array $values
48
     * @param array $parameters
49
     *
50
     * @return object
51
     */
52 11
    public static function create($classname, array $values = [], array $parameters = null)
53
    {
54
        // get parameters if they were not set
55 11
        if (null === $parameters) {
56 8
            $parameters = static::retrieveArguments($classname);
57
        }
58
        // build the arguments based on the parameters list and the values
59 11
        $mixed = [];
60 11
        foreach ($parameters as $parameter => $defaultValue) {
61 11
            $mixed[] = array_key_exists($parameter, $values) ? $values[$parameter] : $defaultValue;
62
        }
63
64 11
        return new $classname(...$mixed);
65
    }
66
67
    /**
68
     * This function is the same as construct_named_parameters but it convert the case of values and parameters
69
     * Be aware that a constructor can have two parameters with the same name and different case.
70
     * In this situation this function will thow an \InvalidArgumentException
71
     *
72
     * @see create()
73
     *
74
     * @param string $classname
75
     * @param array $values
76
     * @param array|null $parameters
77
     *
78
     * @return object
79
     *
80
     * @throws \InvalidArgumentException if the class has two parameters with the same name but different case
81
     */
82 4
    public static function createIgnoreCase($classname, array $values = [], array $parameters = null)
83
    {
84
        // get parameters if they were not set
85 4
        if (null === $parameters) {
86 4
            $parameters = static::retrieveArguments($classname);
87
        }
88 4
        $originalCount = count($parameters);
89 4
        $parameters = array_change_key_case($parameters, CASE_LOWER);
90 4
        if (count($parameters) !== $originalCount) {
91 1
            throw new \InvalidArgumentException(
92 1
                "The class $classname has parameters with the same name but different case"
93
            );
94
        }
95 3
        $values = array_change_key_case($values, CASE_LOWER);
96
97 3
        return static::create($classname, $values, $parameters);
98
    }
99
}
100