ServiceContainerTrait   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 205
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 0
loc 205
rs 10
c 0
b 0
f 0
wmc 15
lcom 1
cbo 2

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A buildClassMap() 0 7 1
A createService() 0 29 4
A get() 0 15 3
A getRegistered() 0 6 1
A register() 0 10 2
A registerClass() 0 8 1
A registerInstance() 0 8 1
A unifyNameStyle() 0 4 1
1
<?php
2
namespace Fwlib\Base;
3
4
use Fwlib\Base\Exception\ServiceInstanceCreationFailException;
5
6
/**
7
 * Trait for service container
8
 *
9
 * Usually only one container instance is need, so use Singleton pattern.
10
 *
11
 * Service name better use camelCase or StudyCaps style.
12
 *
13
 * @copyright   Copyright 2013-2015 Fwolf
14
 * @license     http://www.gnu.org/licenses/lgpl.html LGPL-3.0+
15
 * @see         ServiceContainerInterface
16
 */
17
trait ServiceContainerTrait
18
{
19
    use SingletonTrait;
20
21
22
    /**
23
     * Service class map
24
     *
25
     * These class can have static getInstance() method for reuse, see
26
     * {@see SingleInstanceTrait}.
27
     *
28
     * For easy inherit and not conflict with user registered class, do not
29
     * set value here, set them in {@see buildClassMap()}.
30
     *
31
     * @var string[]
32
     */
33
    protected $classMap = [];
34
35
    /**
36
     * Service instances
37
     *
38
     * @var object[]
39
     */
40
    protected $instances = [];
41
42
43
    /**
44
     * Constructor
45
     */
46
    protected function __construct()
47
    {
48
        $this->classMap = $this->buildClassMap();
49
    }
50
51
52
    /**
53
     * Build service class map
54
     *
55
     * @return  string[]
56
     */
57
    protected function buildClassMap()
58
    {
59
        // Dummy for inherit and extend by child class.
60
        $classMap = [];
61
62
        return $classMap;
63
    }
64
65
66
    /**
67
     * Create service instance by name
68
     *
69
     * Will try below sequence to create instance:
70
     *
71
     *  - createName() in this container
72
     *  - Name::getInstance()
73
     *  - new Name
74
     *
75
     * @param   string $name
76
     * @return  object
77
     * @throws  ServiceInstanceCreationFailException
78
     */
79
    protected function createService($name)
80
    {
81
        $service = null;
0 ignored issues
show
Unused Code introduced by
$service is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
82
        $name = $this->unifyNameStyle($name);
83
84
        $method = 'create' . $name;
85
        if (method_exists($this, $method)) {
86
            $service = $this->$method();
87
88
89
        } elseif (isset($this->classMap[$name])) {
90
            $className = $this->classMap[$name];
91
92
            // Singleton or single instance class instantiate diffs
93
            if (method_exists($className, 'getInstance')) {
94
                $service = $className::getInstance();
95
            } else {
96
                $service = new $className;
97
            }
98
99
100
        } else {
101
            throw (new ServiceInstanceCreationFailException)
102
                ->setServiceName($name);
103
        }
104
105
106
        return $service;
107
    }
108
109
110
    /**
111
     * Get service instance by name
112
     *
113
     * The return type maybe variable, so this method is inner use only. Make
114
     * getFoo() methods in client class to identify return type.
115
     *
116
     * When $forcenew is true, it will ignore exists service instance and
117
     * create a new one-time use instance, which will not be stored in instance
118
     * array.
119
     *
120
     * $forcenew does not affect instances create according to class map,
121
     * because they use singleton or single instance pattern.
122
     *
123
     * @param   string  $name
124
     * @param   boolean $forcenew
125
     * @return  object
126
     */
127
    protected function get($name, $forcenew = false)
128
    {
129
        $name = $this->unifyNameStyle($name);
130
131
        if ($forcenew) {
132
            return $this->createService($name);
133
134
        } else {
135
            if (!isset($this->instances[$name])) {
136
                $this->instances[$name] = $this->createService($name);
137
            }
138
139
            return $this->instances[$name];
140
        }
141
    }
142
143
144
    /**
145
     * @see ServiceContainerInterface::getRegistered()
146
     *
147
     * @param   string $name
148
     * @return  object
149
     */
150
    public function getRegistered($name)
151
    {
152
        $name = $this->unifyNameStyle($name);
153
154
        return $this->get($name, false);
155
    }
156
157
158
    /**
159
     * @see ServiceContainerInterface::register()
160
     *
161
     * @param   string        $name
162
     * @param   string|object $service
163
     * @return  static
164
     */
165
    public function register($name, $service)
166
    {
167
        $name = $this->unifyNameStyle($name);
168
169
        if (is_string($service)) {
170
            return $this->registerClass($name, $service);
171
        } else {
172
            return $this->registerInstance($name, $service);
173
        }
174
    }
175
176
177
    /**
178
     * @see ServiceContainerInterface::registerClass()
179
     *
180
     * @param   string $name
181
     * @param   string $className Full qualified name without leading '\'
182
     * @return  static
183
     */
184
    public function registerClass($name, $className)
185
    {
186
        $name = $this->unifyNameStyle($name);
187
188
        $this->classMap[$name] = $className;
189
190
        return $this;
191
    }
192
193
194
    /**
195
     * @see ServiceContainerInterface::registerInstance()
196
     *
197
     * @param   string $name
198
     * @param   object $instance
199
     * @return  static
200
     */
201
    public function registerInstance($name, $instance)
202
    {
203
        $name = $this->unifyNameStyle($name);
204
205
        $this->instances[$name] = $instance;
206
207
        return $this;
208
    }
209
210
211
    /**
212
     * Unify service name case style
213
     *
214
     * @param   string $name
215
     * @return  string
216
     */
217
    protected function unifyNameStyle($name)
218
    {
219
        return ucfirst($name);
220
    }
221
}
222