Passed
Push — master ( af3b98...6fd3d5 )
by Mikael
01:57
created

DI::load()   B

Complexity

Conditions 7
Paths 12

Size

Total Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 9.3554

Importance

Changes 0
Metric Value
dl 0
loc 36
ccs 14
cts 22
cp 0.6364
rs 8.4106
c 0
b 0
f 0
cc 7
nc 12
nop 1
crap 9.3554
1
<?php
2
3
namespace Anax\DI;
4
5
use Anax\DI\Exception\NotFoundException;
6
use Anax\DI\Exception\Exception;
7
8
/**
9
 * Anax base class implementing Dependency Injection / Service Locator of
10
 * the services used by the framework, using lazy loading.
11
 */
12
class DI implements DIInterface
13
{
14
    /**
15
     * @var array $loaded  Store all lazy loaded services, ready to be
16
     *                     instantiated.
17
     * @var array $active  A service is instantiated into this array,
18
     *                     once its accessed.
19
     */
20
    protected $loaded = [];
21
    protected $active = [];
22
23
24
25
    /**
26
     * Finds an entry in the container by its identifier and returns it.
27
     * If the service is active/singelton then that instance is returned,
28
     * else the service is loaded and a new instance is returned.
29
     *
30
     * @param string $service     Identifier of the entry to look for.
31
     *
32
     * @throws NotFoundException  No entry was found for this identifier.
33
     * @throws Exception          Error while retrieving the entry.
34
     *
35
     * @return mixed Entry.
36
     */
37 8
    public function get($service)
38
    {
39 8
        if (!$this->has($service)) {
40
            throw new NotFoundException("The service '$service' is not loaded in the DI-container.");
41
        }
42
43 8
        if (isset($this->active[$service])
44 8
            && $this->loaded[$service]['singleton']) {
45
            return $this->active[$service];
46
        }
47
48 8
        return $this->load($service);
49
    }
50
51
52
53
    /**
54
     * Load a prepared service object and create an instance of it.
55
     *
56
     * @param string $service as a service label, naming this service.
57
     *
58
     * @throws Exception when service could not be loaded.
59
     *
60
     * @return object as instance of the service object.
61
     */
62 8
    protected function load($service)
63
    {
64 8
        $sol = isset($this->loaded[$service]['loader'])
65 8
            ? $this->loaded[$service]['loader']
66 8
            : null;
67
68 8
        if (is_callable($sol)) {
69
            // Load by calling a function
70
            try {
71 6
                $this->active[$service] = $sol();
72
            } catch (\Exception $e) {
73
                throw new Exception(
74
                    "Could not load service '$service'."
75
                    . "Failed in the callback that instantiates the service. "
76 6
                    . $e->getMessage()
77
                );
78
            }
79 2
        } elseif (is_object($sol)) {
80
            // Load by pre-instantiated object
81 1
            $this->active[$service] = $sol;
82 1
        } elseif (is_string($sol)) {
83
            // Load by creating a new object from class-string
84 1
            if (!class_exists($sol)) {
85
                throw new Exception(
86
                    "Could not load service '$service'."
87
                    . "Class '$sol' does not exists."
88
                );
89
            }
90 1
            $this->active[$service] = new $sol();
91
        } else {
92
            throw new Exception("The service '$service' has no init mechanism.");
93
        }
94
95 8
        $this->$service = $this->active[$service];
96 8
        return $this->active[$service];
97
    }
98
99
100
101
    /**
102
     * Returns true if the container can return an entry for the given
103
     * identifier, otherwise false
104
     *
105
     * @param string $service Identifier of the entry to look for.
106
     *
107
     * @return boolean
108
     */
109 8
    public function has($service)
110
    {
111 8
        return isset($this->loaded[$service]);
112
    }
113
114
115
116
    /**
117
     * Set a service and connect it to a task which creates the object
118
     * (lazy loading).
119
     *
120
     * @param string  $service   as a service label, naming this service.
121
     * @param mixed   $loader    contains a pre-defined object, a string with
122
     *                           class name or an callable which returns an
123
     *                           instance of the service object. Its the way
124
     *                           to actually load, insantiate, the service
125
     *                           object.
126
     *
127
     * @return void
128
     */
129 8
    public function set($service, $loader)
130
    {
131 8
        $this->loaded[$service]['loader'] = $loader;
132 8
        $this->loaded[$service]['singleton'] = false;
133 8
    }
134
135
136
137
    /**
138
     * Set a singleton service and connect it to a task which creates the
139
     * object (lazy loading).
140
     *
141
     * @param string $service as a service label, naming this service.
142
     * @param mixed   $loader    contains a pre-defined object, a string with
143
     *                           class name or an callable which returns an
144
     *                           instance of the service object. Its the way
145
     *                           to actually load, insantiate, the service
146
     *                           object.
147
     *
148
     * @return void
149
     */
150 8
    public function setShared($service, $loader)
151
    {
152 8
        $this->loaded[$service]['loader'] = $loader;
153 8
        $this->loaded[$service]['singleton'] = true;
154 8
    }
155
156
157
158
    /**
159
     * Return an arry with all loaded services names.
160
     *
161
     * @return void
162
     */
163 3
    public function getServices()
164
    {
165 3
        return array_keys($this->loaded);
166
    }
167
168
169
170
    /**
171
     * Return an arry with all active services names.
172
     *
173
     * @return void
174
     */
175
    public function getActiveServices()
176
    {
177
        return array_keys($this->active);
178
    }
179
}
180