Test Failed
Pull Request — master (#171)
by Zaahid
04:55
created

Container   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 103
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 38
c 0
b 0
f 0
dl 0
loc 103
ccs 10
cts 10
cp 1
rs 10
wmc 19

5 Methods

Rating   Name   Duplication   Size   Complexity  
A offsetExists() 0 8 3
A offsetGet() 0 10 3
A extend() 0 4 1
A getParameterClass() 0 11 6
A autoRegister() 0 21 6
1
<?php
2
/**
3
 * This file is part of the ZBateson\MailMimeParser project.
4
 *
5
 * @license http://opensource.org/licenses/bsd-license.php BSD
6
 */
7
namespace ZBateson\MailMimeParser;
8
9
use Pimple\Container as PimpleContainer;
10
use Pimple\Exception\UnknownIdentifierException;
11
use ReflectionClass;
12
use ReflectionParameter;
13
14
/**
15
 * Automatically configures classes and dependencies.
16
 *
17
 * Sets up an automatic registration for classes when requested through
18
 * Pimple by looking up the class's constructor and arguments.
19
 *
20
 * @author Zaahid Bateson
21
 */
22
class Container extends PimpleContainer
23
{
24
    /**
25
     * Looks up the type of the passed ReflectionParameter and returns it as a
26
     * fully qualified class name as expected by the class's auto registration.
27
     *
28
     * @param ReflectionParameter $param
29
     * @return string
30
     */
31
    private function getParameterClass(ReflectionParameter $param)
32
    {
33
        if (method_exists($param, 'getType')) {
34
            $type = $param->getType();
35
            if ($type && !$type->isBuiltin()) {
36
                return '\\' . (method_exists($type, 'getName') ? $type->getName() : (string) $type);
37
            }
38
        } elseif ($param->getClass() !== null) {
39
            return '\\' . $param->getClass();
40
        }
41
        return null;
42
    }
43
44
    /**
45
     * Returns a factory function for the passed class.
46
     *
47
     * The returned factory method looks up arguments and uses pimple to get an
48
     * instance of those types to pass them during construction.
49
     *
50
     * @param string $class
51
     */
52
    public function autoRegister($class)
53
    {
54
        $fn = function($c) use ($class) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
55
            $ref = new ReflectionClass($class);
56
            $cargs = ($ref->getConstructor() !== null) ? $ref->getConstructor()->getParameters() : [];
57
            $ap = [];
58
            foreach ($cargs as $arg) {
59
                $name = $arg->getName();
60
                $argClass = $this->getParameterClass($arg);
61
                if (!empty($c[$name])) {
62
                    $ap[] = $c[$name];
63
                } else if ($argClass !== null && !empty($c[$argClass])) {
64
                    $ap[] = $c[$argClass];
65
                } else {
66
                    $ap[] = null;
67
                }
68
            }
69
            $ret = $ref->newInstanceArgs($ap);
70
            return $ret;
71
        };
72
        $this[$class] = $fn;
73
    }
74
75
    /**
76
     * Overridden to see if the class can be auto-registered and return true if
77
     * it can.
78
     * 
79
     * @param string $id
80
     * @return boolean
81
     */
82
    public function offsetExists($id)
83
    {
84
        $exists = parent::offsetExists($id);
85
        if (!$exists && class_exists($id)) {
86
            $this->autoRegister($id);
87
            return true;
88 110
        }
89
        return $exists;
90 110
    }
91
92
    /**
93
     * Overridden to see if the class can be auto-registered and return an
94
     * instance if it can.
95
     *
96
     * @param string $id
97
     * @return object
98
     * @throws UnknownIdentifierException
99
     */
100 105
    public function offsetGet($id)
101
    {
102 105
        try {
103 105
            return parent::offsetGet($id);
104
        } catch (UnknownIdentifierException $e) {
105 105
            if (class_exists($id)) {
106
                $this->autoRegister($id);
107
                return parent::offsetGet($id);
108
            }
109
            throw $e;
110
        }
111
    }
112
113 105
    /**
114
     * Overridden to see if the class can be auto-registered first before
115 105
     * calling Pimple\Container::extend
116 105
     *
117 105
     * @param string $id
118
     * @param callable $callable
119
     * @return callable the wrapped $callable
120
     */
121
    public function extend($id, $callable)
122
    {
123
        $this->offsetExists($id);
124
        return parent::extend($id, $callable);
125
    }
126
}
127