DI   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 164
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 37
dl 0
loc 164
ccs 41
cts 41
cp 1
rs 10
c 0
b 0
f 0
wmc 15

7 Methods

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