Completed
Pull Request — master (#17)
by
unknown
02:55
created

CDI::__get()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
ccs 0
cts 2
cp 0
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Anax\DI;
4
5
/**
6
 * Anax base class implementing Dependency Injection / Service Locator of the services used by the
7
 * framework, using lazy loading.
8
 *
9
 */
10
class CDI implements IDI
11
{
12
13
    /**
14
     * Properties
15
     *
16
     */
17
    public $loaded = [];  // Store all lazy loaded services, ready to be instantiated
18
    public $active = [];  // A service is instantiated into this array, once its accessed
19
20
21
22
    /**
23
     * Construct.
24
     *
25
     */
26 4
    public function __construct()
27
    {
28 4
        ;
29 4
    }
30
31
32
33
    /**
34
     * Return an arry with all loaded services names.
35
     *
36
     * @return void
37
     */
38 2
    public function getServices()
39
    {
40 2
        return array_keys($this->loaded);
41
    }
42
43
44
45
    /**
46
     * Return an array with all loaded services that are controllers.
47
     *
48
     * @return void
49
     */
50
    public function getControllers()
51
    {
52
        return array_filter(
53
            array_keys($this->loaded),
54
            function ($val) {
55
                return strpos($val, "Controller") !== false;
56
            }
57
        );
58
    }
59
60
61
62
    /**
63
     * Return an arry with all active services names.
64
     *
65
     * @return void
66
     */
67
    public function getActiveServices()
68
    {
69
        return array_keys($this->active);
70
    }
71
72
73
74
    /**
75
     * Set a service and connect it to a task which creates the object (lazy loading).
76
     *
77
     * @param string  $service   as a service label, naming this service.
78
     * @param mixed   $loader    contains a pre-defined object, a string with classname or an
79
     *      callable which returns an instance of the service object. Its the way to
80
     *      actually load, insantiate, the serviceobject.
81
     * @param boolean $singleton set if service is to act as singleton or not, default is false.
82
     *
83
     * @return nothing.
0 ignored issues
show
Documentation introduced by
The doc-type nothing. could not be parsed: Unknown type name "nothing." at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
84
     */
85 2
    public function set($service, $loader, $singleton = false)
86
    {
87 2
        $this->loaded[$service]['loader'] = $loader;
88 2
        $this->loaded[$service]['singleton'] = $singleton;
89 2
    }
90
91
92
93
    /**
94
     * Set a singleton service and connect it to a task which creates the object (lazy loading).
95
     *
96
     * @param string $service as a service label, naming this service.
97
     * @param mixed  $loader  contains a pre-defined object, a string with
98
     *                        classname or an callable which returns an
99
     *                        instance of the service object. Its the way
100
     *                        to actually load, insantiate, the serviceobject.
101
     *
102
     * @return nothing.
0 ignored issues
show
Documentation introduced by
The doc-type nothing. could not be parsed: Unknown type name "nothing." at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
103
     */
104 1
    public function setShared($service, $loader)
105
    {
106 1
        $this->set($service, $loader, true);
107 1
    }
108
109
110
111
    /**
112
     * Get an instance of the service object, managing singletons.
113
     *
114
     * @param string $service as a service label, naming this service.
115
     *
116
     * @return object as instance of the service object.
117
     * @throws Exception when service accessed is not loaded.
118
     */
119 2
    public function get($service)
120
    {
121
        // Is the service active?
122 2
        if (isset($this->active[$service])) {
123
            if ($this->loaded[$service]['singleton']) {
124
                return $this->active[$service];
125
            } else {
126
                return $this->load($service);
127
            }
128 2
        } elseif (isset($this->loaded[$service])) {
129
            // Is the service loaded?
130 2
            return $this->load($service);
131
        }
132
133
        $message  = "CDI the service accessed '$service' is not loaded in the DI-container.";
134
        $services = $this->getServices();
135
        natcasesort($services);
136
        $services = implode("\n", $services);
137
        $message .= " Loaded services are: <pre>$services</pre>";
138
        
139
        throw new \Exception($message);
140
    }
141
142
143
144
    /**
145
     * Magic method to get and create services.
146
     * When created it is also stored as a parameter of this object.
147
     *
148
     * @param string $service name of class property not existing.
149
     *
150
     * @return class as the service requested.
151
     */
152
    public function __get($service)
153
    {
154
        return $this->get($service);
155
    }
156
157
158
159
    /**
160
     * Check if service exists by name.
161
     *
162
     * @param string $service as a service label, naming this service.
163
     *
164
     * @return boolean true if the service exists, otherwise false.
165
     */
166 1
    public function has($service)
167
    {
168 1
        return isset($this->loaded[$service])
169 1
            ? true
170 1
            : false;
171
    }
172
173
174
175
    /**
176
     * Magic method to get and create services.
177
     * When created it is also stored as a parameter of this object.
178
     *
179
     * @param string $service   name of class property not existing.
180
     * @param array  $arguments currently NOT USED.
181
     *
182
     * @return class as the service requested.
183
     */
184
    public function __call($service, $arguments = [])
185
    {
186
        return $this->get($service);
187
    }
188
189
190
191
    /**
192
     * Lazy load a service object and create an instance of it.
193
     *
194
     * @param string $service as a service label, naming this service.
195
     *
196
     * @return object as instance of the service object.
197
     * @throws Exception when service could not be loaded.
198
     */
199 2
    protected function load($service)
200
    {
201 2
        $sol = isset($this->loaded[$service]['loader'])
202 2
            ? $this->loaded[$service]['loader']
203 2
            : null;
204
205
        // Load by calling a function
206 2
        if (is_callable($sol)) {
207
208
            try {
209 2
                $this->active[$service] = $sol();
210 2
            } catch (\Exception $e) {
211 1
                $msg = "CDI could not load service '$service'. Failed in the callback that instantiates the service. "
212 1
                    . $e->getMessage();
213 1
                throw new \Exception($msg);
214
            }
215
216 1
        } elseif (is_object($sol)) {
217
            // Load by pre-instantiated object
218
            $this->active[$service] = $sol;
219
220
        } elseif (is_string($sol)) {
221
            // Load by creating a new object from class-string
222
            $this->active[$service] = new $sol();
223
224
        } else {
225
            throw new Exception("CDI could not load service '$service'. It is unknown how to load it.");
226
        }
227
228 1
        $this->$service = $this->active[$service];
229 1
        return $this->active[$service];
230
    }
231
}
232