1
|
|
|
<?php |
2
|
|
|
/* |
3
|
|
|
* This file is part of the PommProject/Foundation package. |
4
|
|
|
* |
5
|
|
|
* (c) 2014 - 2017 Grégoire HUBERT <[email protected]> |
6
|
|
|
* |
7
|
|
|
* For the full copyright and license information, please view the LICENSE |
8
|
|
|
* file that was distributed with this source code. |
9
|
|
|
*/ |
10
|
|
|
namespace PommProject\Foundation; |
11
|
|
|
|
12
|
|
|
use PommProject\Foundation\Exception\FoundationException; |
13
|
|
|
use PommProject\Foundation\Session\SessionBuilder as VanillaSessionBuilder; |
14
|
|
|
use PommProject\Foundation\Session\Session as BaseSession; |
15
|
|
|
use Psr\Log\LoggerAwareInterface; |
16
|
|
|
use Psr\Log\LoggerAwareTrait; |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* Pomm |
20
|
|
|
* |
21
|
|
|
* The Pomm service manager. |
22
|
|
|
* |
23
|
|
|
* @package Foundation |
24
|
|
|
* @copyright 2014 - 2017 Grégoire HUBERT |
25
|
|
|
* @author Grégoire HUBERT |
26
|
|
|
* @license X11 {@link http://opensource.org/licenses/mit-license.php} |
27
|
|
|
*/ |
28
|
|
|
class Pomm implements \ArrayAccess, LoggerAwareInterface |
29
|
|
|
{ |
30
|
|
|
protected $builders = []; |
31
|
|
|
protected $post_configurations = []; |
32
|
|
|
protected $sessions = []; |
33
|
|
|
protected $default; |
34
|
|
|
|
35
|
|
|
use LoggerAwareTrait; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* __construct |
39
|
|
|
* |
40
|
|
|
* Instantiate a new Pomm Service class. It takes an array of |
41
|
|
|
* configurations as parameter. Following configuration settings are |
42
|
|
|
* supported by this service for each configuration: |
43
|
|
|
* |
44
|
|
|
* class_name name of the DatabaseConfiguration class to instantiate. |
45
|
|
|
* |
46
|
|
|
* @param array $configurations |
47
|
|
|
*/ |
48
|
|
|
public function __construct(array $configurations = []) |
49
|
|
|
{ |
50
|
|
|
foreach ($configurations as $name => $configuration) { |
51
|
|
|
$builder_class = '\PommProject\Foundation\SessionBuilder'; |
52
|
|
|
if (isset($configuration['class:session_builder'])) { |
53
|
|
|
$builder_class = $this->checkSessionBuilderClass($configuration['class:session_builder']); |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
$this->addBuilder($name, new $builder_class($configuration)); |
57
|
|
|
|
58
|
|
|
if (isset($configuration['pomm:default']) && $configuration['pomm:default'] === true) { |
59
|
|
|
$this->setDefaultBuilder($name); |
60
|
|
|
} |
61
|
|
|
} |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* checkSessionBuilderClass |
66
|
|
|
* |
67
|
|
|
* Check if the given builder class is valid. |
68
|
|
|
* |
69
|
|
|
* @param string $builder_class |
70
|
|
|
* @throws FoundationException if not valid |
71
|
|
|
* @return string $builder_class |
72
|
|
|
*/ |
73
|
|
|
private function checkSessionBuilderClass($builder_class) |
|
|
|
|
74
|
|
|
{ |
75
|
|
|
try { |
76
|
|
|
$reflection = new \ReflectionClass($builder_class); |
77
|
|
|
|
78
|
|
|
if (!$reflection->isSubclassOf('\PommProject\Foundation\Session\SessionBuilder')) { |
79
|
|
|
throw new FoundationException( |
80
|
|
|
sprintf( |
81
|
|
|
"Class '%s' is not a subclass of \PommProject\Foundation\Session\SessionBuilder.", |
82
|
|
|
$builder_class |
83
|
|
|
) |
84
|
|
|
); |
85
|
|
|
} |
86
|
|
|
} catch (\ReflectionException $e) { |
87
|
|
|
throw new FoundationException( |
88
|
|
|
sprintf( |
89
|
|
|
"Could not instantiate class '%s'.", |
90
|
|
|
$builder_class |
91
|
|
|
), |
92
|
|
|
null, |
93
|
|
|
$e |
94
|
|
|
); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
return $builder_class; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* setDefaultBuilder |
102
|
|
|
* |
103
|
|
|
* Set the name for the default session builder. |
104
|
|
|
* |
105
|
|
|
* @param string $name |
106
|
|
|
* @return Pomm $this |
107
|
|
|
* @throws FoundationException |
108
|
|
|
*/ |
109
|
|
|
public function setDefaultBuilder($name) |
110
|
|
|
{ |
111
|
|
|
if (!$this->hasBuilder($name)) { |
112
|
|
|
throw new FoundationException( |
113
|
|
|
sprintf( |
114
|
|
|
"No such builder '%s'.", |
115
|
|
|
$name |
116
|
|
|
) |
117
|
|
|
); |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
$this->default = $name; |
121
|
|
|
|
122
|
|
|
return $this; |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* getDefaultSession |
127
|
|
|
* |
128
|
|
|
* Return a session built by the default session builder. |
129
|
|
|
* |
130
|
|
|
* @return BaseSession |
131
|
|
|
* @throws FoundationException |
132
|
|
|
*/ |
133
|
|
|
public function getDefaultSession() |
134
|
|
|
{ |
135
|
|
|
if ($this->default === null) { |
136
|
|
|
throw new FoundationException( |
137
|
|
|
"No default session builder set." |
138
|
|
|
) |
139
|
|
|
; |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
return $this->getSession($this->default); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* isDefaultSession |
147
|
|
|
* |
148
|
|
|
* Check if $name is a default session builder |
149
|
|
|
* |
150
|
|
|
* @param string $name |
151
|
|
|
* @return bool |
152
|
|
|
*/ |
153
|
|
|
public function isDefaultSession($name) |
154
|
|
|
{ |
155
|
|
|
return (bool) ($this->default == $name); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* addBuilder |
160
|
|
|
* |
161
|
|
|
* Add a new session builder. Override any previously existing builder with |
162
|
|
|
* the same name. |
163
|
|
|
* |
164
|
|
|
* @param string $builder_name |
165
|
|
|
* @param VanillaSessionBuilder $builder |
166
|
|
|
* @return Pomm $this |
167
|
|
|
*/ |
168
|
|
|
public function addBuilder($builder_name, VanillaSessionBuilder $builder) |
169
|
|
|
{ |
170
|
|
|
$this->builders[$builder_name] = $builder; |
171
|
|
|
$this->post_configurations[$builder_name] = []; |
172
|
|
|
|
173
|
|
|
if ($this->default === null) { |
174
|
|
|
$this->setDefaultBuilder($builder_name); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
return $this; |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* addPostConfiguration |
182
|
|
|
* |
183
|
|
|
* Add a environment dependent post configuration callable that will be run |
184
|
|
|
* once after the session creation. |
185
|
|
|
* |
186
|
|
|
* @param string $name |
187
|
|
|
* @param callable $callable |
188
|
|
|
* @return Pomm $this |
189
|
|
|
*/ |
190
|
|
|
public function addPostConfiguration($name, callable $callable) |
191
|
|
|
{ |
192
|
|
|
$this |
193
|
|
|
->builderMustExist($name) |
194
|
|
|
->post_configurations[$name][] = $callable |
195
|
|
|
; |
196
|
|
|
|
197
|
|
|
return $this; |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
/** |
201
|
|
|
* hasBuilder |
202
|
|
|
* |
203
|
|
|
* Return if true or false the given builder exists. |
204
|
|
|
* |
205
|
|
|
* @param string $name |
206
|
|
|
* @return bool |
207
|
|
|
*/ |
208
|
|
|
public function hasBuilder($name) |
209
|
|
|
{ |
210
|
|
|
return (bool) (isset($this->builders[$name])); |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
/** |
214
|
|
|
* removeBuilder |
215
|
|
|
* |
216
|
|
|
* Remove the builder with the given name. |
217
|
|
|
* |
218
|
|
|
* @param string $name |
219
|
|
|
* @throws FoundationException if name does not exist. |
220
|
|
|
* @return Pomm $this |
221
|
|
|
*/ |
222
|
|
|
public function removeBuilder($name) |
223
|
|
|
{ |
224
|
|
|
unset( |
225
|
|
|
$this->builderMustExist($name)->builders[$name], |
226
|
|
|
$this->post_configurations[$name] |
227
|
|
|
); |
228
|
|
|
|
229
|
|
|
return $this; |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* getBuilder |
234
|
|
|
* |
235
|
|
|
* Return the given builder. |
236
|
|
|
* |
237
|
|
|
* @param string $name |
238
|
|
|
* @return VanillaSessionBuilder |
239
|
|
|
*/ |
240
|
|
|
public function getBuilder($name) |
241
|
|
|
{ |
242
|
|
|
return $this->builderMustExist($name)->builders[$name]; |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* getSession |
247
|
|
|
* |
248
|
|
|
* Return a session from the pool. If no session exists, an attempt is made |
249
|
|
|
* to create one. |
250
|
|
|
* |
251
|
|
|
* @param string $name |
252
|
|
|
* @return BaseSession |
253
|
|
|
*/ |
254
|
|
|
public function getSession($name) |
255
|
|
|
{ |
256
|
|
|
if (!$this->hasSession($name)) { |
257
|
|
|
$this->createSession($name); |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
return $this->sessions[$name]; |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
/** |
264
|
|
|
* createSession |
265
|
|
|
* |
266
|
|
|
* Create a new session using a session_builder and set it to the pool. Any |
267
|
|
|
* previous session for this name is overrided. |
268
|
|
|
* |
269
|
|
|
* @param string $name |
270
|
|
|
* @throws FoundationException if builder does not exist. |
271
|
|
|
* @return BaseSession |
272
|
|
|
*/ |
273
|
|
|
public function createSession($name) |
274
|
|
|
{ |
275
|
|
|
$this->sessions[$name] = $this |
276
|
|
|
->builderMustExist($name) |
277
|
|
|
->builders[$name] |
278
|
|
|
->buildSession($name) |
279
|
|
|
; |
280
|
|
|
|
281
|
|
|
$session = $this->sessions[$name]; |
282
|
|
|
|
283
|
|
|
foreach ($this->post_configurations[$name] as $callable) { |
284
|
|
|
call_user_func($callable, $session); |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
if ($this->logger !== null) { |
288
|
|
|
$session->setLogger($this->logger); |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
return $session; |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
/** |
295
|
|
|
* hasSession |
296
|
|
|
* |
297
|
|
|
* Does a given session exist in the pool ? |
298
|
|
|
* |
299
|
|
|
* @param string $name |
300
|
|
|
* @return bool |
301
|
|
|
*/ |
302
|
|
|
public function hasSession($name) |
303
|
|
|
{ |
304
|
|
|
return (bool) isset($this->sessions[$name]); |
305
|
|
|
} |
306
|
|
|
|
307
|
|
|
/** |
308
|
|
|
* removeSession |
309
|
|
|
* |
310
|
|
|
* Remove a session from the pool if it exists. |
311
|
|
|
* |
312
|
|
|
* @param string $name |
313
|
|
|
* @throws FoundationException if no builders with that name exist |
314
|
|
|
* @return Pomm $this |
315
|
|
|
*/ |
316
|
|
|
public function removeSession($name) |
317
|
|
|
{ |
318
|
|
|
if ($this->builderMustExist($name)->hasSession($name)) { |
319
|
|
|
unset($this->sessions[$name]); |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
return $this; |
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
/** |
326
|
|
|
* getSessionBuilders |
327
|
|
|
* |
328
|
|
|
* Return the builders. This is mainly done for testing |
329
|
|
|
* purposes. |
330
|
|
|
* |
331
|
|
|
* @return array |
332
|
|
|
*/ |
333
|
|
|
public function getSessionBuilders() |
334
|
|
|
{ |
335
|
|
|
return $this->builders; |
336
|
|
|
} |
337
|
|
|
|
338
|
|
|
/** |
339
|
|
|
* @see ArrayAccess |
340
|
|
|
*/ |
341
|
|
|
public function offsetGet($offset) |
342
|
|
|
{ |
343
|
|
|
return $this->getSession($offset); |
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
/** |
347
|
|
|
* @see ArrayAccess |
348
|
|
|
*/ |
349
|
|
|
public function offsetSet($offset, $value) |
350
|
|
|
{ |
351
|
|
|
$this->addBuilder($offset, $value); |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
/** |
355
|
|
|
* @see ArrayAccess |
356
|
|
|
*/ |
357
|
|
|
public function offsetUnset($offset) |
358
|
|
|
{ |
359
|
|
|
$this->removeBuilder($offset); |
360
|
|
|
} |
361
|
|
|
|
362
|
|
|
/** |
363
|
|
|
* @see ArrayAccess |
364
|
|
|
*/ |
365
|
|
|
public function offsetExists($offset) |
366
|
|
|
{ |
367
|
|
|
return $this->hasBuilder($offset); |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
/** |
371
|
|
|
* shutdown |
372
|
|
|
* |
373
|
|
|
* Shutdown and remove sessions from the service. If no arguments are |
374
|
|
|
* given, all the instantiated sessions are shutdown. Otherwise, only given |
375
|
|
|
* sessions are shutdown. |
376
|
|
|
* |
377
|
|
|
* @param array $session_names |
378
|
|
|
* @return Pomm $this |
379
|
|
|
*/ |
380
|
|
|
public function shutdown(array $session_names = []) |
381
|
|
|
{ |
382
|
|
|
if (empty($session_names)) { |
383
|
|
|
$sessions = array_keys($this->sessions); |
384
|
|
|
} else { |
385
|
|
|
array_map([ $this, 'builderMustExist' ], $session_names); |
386
|
|
|
$sessions = array_intersect( |
387
|
|
|
array_keys($this->sessions), |
388
|
|
|
$session_names |
389
|
|
|
); |
390
|
|
|
} |
391
|
|
|
|
392
|
|
|
foreach ($sessions as $session_name) { |
393
|
|
|
$this->getSession($session_name)->shutdown(); |
394
|
|
|
$this->removeSession($session_name); |
395
|
|
|
} |
396
|
|
|
|
397
|
|
|
return $this; |
398
|
|
|
} |
399
|
|
|
|
400
|
|
|
/** |
401
|
|
|
* builderMustExist |
402
|
|
|
* |
403
|
|
|
* Throw a FoundationException if the given builder does not exist. |
404
|
|
|
* |
405
|
|
|
* @param string $name |
406
|
|
|
* @throws FoundationException |
407
|
|
|
* @return Pomm $this |
408
|
|
|
*/ |
409
|
|
|
private function builderMustExist($name) |
410
|
|
|
{ |
411
|
|
|
if (!$this->hasBuilder($name)) { |
412
|
|
|
throw new FoundationException( |
413
|
|
|
sprintf( |
414
|
|
|
"No such builder '%s'. Available builders are {%s}.", |
415
|
|
|
$name, |
416
|
|
|
join( |
417
|
|
|
', ', |
418
|
|
|
array_map( |
419
|
|
|
function ($val) { |
420
|
|
|
return sprintf("'%s'", $val); |
421
|
|
|
}, |
422
|
|
|
array_keys($this->getSessionBuilders()) |
423
|
|
|
) |
424
|
|
|
) |
425
|
|
|
) |
426
|
|
|
); |
427
|
|
|
} |
428
|
|
|
|
429
|
|
|
return $this; |
430
|
|
|
} |
431
|
|
|
} |
432
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.