1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* This file is part of the PPI Framework. |
4
|
|
|
* |
5
|
|
|
* @copyright Copyright (c) 2011-2016 Paul Dragoonis <[email protected]> |
6
|
|
|
* @license http://opensource.org/licenses/mit-license.php MIT |
7
|
|
|
* |
8
|
|
|
* @link http://www.ppi.io |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
namespace PPI\Framework; |
12
|
|
|
|
13
|
|
|
use PPI\Framework\Config\ConfigManager; |
14
|
|
|
use PPI\Framework\Http\Request as HttpRequest; |
15
|
|
|
use PPI\Framework\Http\Response as HttpResponse; |
16
|
|
|
use PPI\Framework\Router\ChainRouter; |
17
|
|
|
use PPI\Framework\ServiceManager\ServiceManager; |
18
|
|
|
use PPI\Framework\ServiceManager\ServiceManagerBuilder; |
19
|
|
|
use PPI\Framework\Debug\ExceptionHandler; |
20
|
|
|
use Symfony\Component\Debug\Debug; |
21
|
|
|
use Symfony\Component\HttpFoundation\Response as SymfonyResponse; |
22
|
|
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; |
23
|
|
|
use Symfony\Component\HttpKernel\KernelInterface; |
24
|
|
|
use Symfony\Component\Routing\Exception\ResourceNotFoundException; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* The PPI App bootstrap class. |
28
|
|
|
* |
29
|
|
|
* This class sets various app settings, and allows you to override classes used in the bootup process. |
30
|
|
|
* |
31
|
|
|
* @author Paul Dragoonis <[email protected]> |
32
|
|
|
* @author Vítor Brandão <[email protected]> |
33
|
|
|
*/ |
34
|
|
|
class App implements AppInterface |
35
|
|
|
{ |
36
|
|
|
/** |
37
|
|
|
* Version string. |
38
|
|
|
* |
39
|
|
|
* @var string |
40
|
|
|
*/ |
41
|
|
|
const VERSION = '2.2.0-DEV'; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* @var bool |
45
|
|
|
*/ |
46
|
|
|
protected $booted = false; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @var bool |
50
|
|
|
*/ |
51
|
|
|
protected $debug; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Application environment: "dev|development" vs "prod|production". |
55
|
|
|
* |
56
|
|
|
* @var string |
57
|
|
|
*/ |
58
|
|
|
protected $environment; |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* @var \Psr\Log\LoggerInterface |
62
|
|
|
*/ |
63
|
|
|
protected $logger; |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Unix timestamp with microseconds. |
67
|
|
|
* |
68
|
|
|
* @var float |
69
|
|
|
*/ |
70
|
|
|
protected $startTime; |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Configuration loader. |
74
|
|
|
* |
75
|
|
|
* @var \PPI\Framework\Config\ConfigManager |
76
|
|
|
*/ |
77
|
|
|
protected $configManager; |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* The Module Manager. |
81
|
|
|
* |
82
|
|
|
* @var \Zend\ModuleManager\ModuleManager |
83
|
|
|
*/ |
84
|
|
|
protected $moduleManager; |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* @param int $errorReportingLevel The level of error reporting you want |
88
|
|
|
*/ |
89
|
|
|
protected $errorReportingLevel; |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* @var null|array |
93
|
|
|
*/ |
94
|
|
|
protected $matchedRoute; |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* @var \PPI\Framework\Module\Controller\ControllerResolver |
98
|
|
|
*/ |
99
|
|
|
protected $resolver; |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* @var string |
103
|
|
|
*/ |
104
|
|
|
protected $name; |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Path to the application root dir aka the "app" directory. |
108
|
|
|
* |
109
|
|
|
* @var null|string |
110
|
|
|
*/ |
111
|
|
|
protected $rootDir; |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* Service Manager. |
115
|
|
|
* |
116
|
|
|
* @var \PPI\Framework\ServiceManager\ServiceManager |
117
|
|
|
*/ |
118
|
|
|
protected $serviceManager; |
119
|
|
|
|
120
|
|
|
/** |
121
|
|
|
* @var ChainRouter |
122
|
|
|
*/ |
123
|
|
|
private $router; |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* @var KernelInterface |
127
|
|
|
*/ |
128
|
|
|
private $symfonyKernel; |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* App constructor. |
132
|
|
|
* |
133
|
|
|
* @param array $options |
134
|
|
|
*/ |
135
|
|
|
public function __construct(array $options = array()) |
136
|
|
|
{ |
137
|
|
|
// Default options |
138
|
|
|
$this->environment = isset($options['environment']) && $options['environment'] ? (string) $options['environment'] : 'prod'; |
139
|
|
|
$this->debug = isset($options['debug']) && null !== $options['debug'] ? (boolean) $options['debug'] : false; |
140
|
|
|
$this->rootDir = isset($options['rootDir']) && $options['rootDir'] ? (string) $options['rootDir'] : $this->getRootDir(); |
141
|
|
|
$this->name = isset($options['name']) && $options['name'] ? (string) $options['name'] : $this->getName(); |
142
|
|
|
|
143
|
|
|
if ($this->debug) { |
144
|
|
|
$this->startTime = microtime(true); |
145
|
|
|
Debug::enable(); |
146
|
|
|
} else { |
147
|
|
|
ini_set('display_errors', 0); |
148
|
|
|
} |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
public function __clone() |
152
|
|
|
{ |
153
|
|
|
if ($this->debug) { |
154
|
|
|
$this->startTime = microtime(true); |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
$this->booted = false; |
158
|
|
|
$this->serviceManager = null; |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* Run the boot process, load our modules and their dependencies. |
163
|
|
|
* |
164
|
|
|
* This method is automatically called by dispatch(), but you can use it |
165
|
|
|
* to build all services when not handling a request. |
166
|
|
|
* |
167
|
|
|
* @return $this |
168
|
|
|
*/ |
169
|
|
|
public function boot() |
170
|
|
|
{ |
171
|
|
|
if (true === $this->booted) { |
172
|
|
|
return $this; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
if($this->isDebug()) { |
176
|
|
|
ExceptionHandler::register(true, 'UTF-8', 'PPI Framework', self::VERSION, true); |
|
|
|
|
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
$this->serviceManager = $this->buildServiceManager(); |
180
|
|
|
$this->log('debug', sprintf('Booting %s ...', $this->name)); |
181
|
|
|
|
182
|
|
|
// Loading our Modules |
183
|
|
|
$this->getModuleManager()->loadModules(); |
184
|
|
|
if ($this->debug) { |
185
|
|
|
$modules = $this->getModuleManager()->getModules(); |
186
|
|
|
$this->log('debug', sprintf('All modules online (%d): "%s"', count($modules), implode('", "', $modules))); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
// Lets get all the services our of our modules and start setting them in the ServiceManager |
190
|
|
|
$moduleServices = $this->serviceManager->get('ModuleDefaultListener')->getServices(); |
191
|
|
|
foreach ($moduleServices as $key => $service) { |
192
|
|
|
$this->serviceManager->setFactory($key, $service); |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
$this->booted = true; |
196
|
|
|
if ($this->debug) { |
197
|
|
|
$this->log('debug', sprintf('%s has booted (in %.3f secs)', $this->name, microtime(true) - $this->startTime)); |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
return $this; |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
/** |
204
|
|
|
* Run the application and send the response. |
205
|
|
|
* |
206
|
|
|
* @param HttpRequest|null $request |
207
|
|
|
* @param HttpResponse|null $response |
208
|
|
|
* |
209
|
|
|
* @throws \Exception |
210
|
|
|
* |
211
|
|
|
* @return HttpResponse |
212
|
|
|
*/ |
213
|
|
|
public function run(HttpRequest $request = null, HttpResponse $response = null) |
214
|
|
|
{ |
215
|
|
|
if (false === $this->booted) { |
216
|
|
|
$this->boot(); |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
if (null === $request) { |
220
|
|
|
$request = HttpRequest::createFromGlobals(); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
if (null === $response) { |
224
|
|
|
$response = new HttpResponse(); |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
// Create a copy of request, as it's by-ref passed into $this->dispatch() and gets modified. |
228
|
|
|
$cleanRequest = clone $request; |
229
|
|
|
try { |
230
|
|
|
$response = $this->dispatch($request, $response); |
|
|
|
|
231
|
|
|
} catch (ResourceNotFoundException $e) { |
232
|
|
|
|
233
|
|
|
if($this->symfonyKernel === null) { |
234
|
|
|
throw $e; |
235
|
|
|
} |
236
|
|
|
$response = $this->symfonyKernel->handle($cleanRequest); |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
|
240
|
|
|
$response->send(); |
241
|
|
|
|
242
|
|
|
return $response; |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* Decide on a route to use and dispatch our module's controller action. |
247
|
|
|
* |
248
|
|
|
* @param HttpRequest $request |
249
|
|
|
* @param HttpResponse $response |
250
|
|
|
* |
251
|
|
|
* @throws \Exception |
252
|
|
|
* |
253
|
|
|
* @return HttpResponse |
254
|
|
|
*/ |
255
|
|
|
public function dispatch(HttpRequest $request, HttpResponse $response) |
256
|
|
|
{ |
257
|
|
|
if (false === $this->booted) { |
258
|
|
|
$this->boot(); |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
|
262
|
|
|
// cache like a mother fucker |
|
|
|
|
263
|
|
|
// if(!$this->hasRouteInCache($request)) { |
264
|
|
|
$routeParams = $this->handleRouting($request); |
265
|
|
|
// $this->setRouteInCache($request, $routeParams); |
|
|
|
|
266
|
|
|
// @todo - move these 2 lines to setRouteInCache() |
|
|
|
|
267
|
|
|
// $routingCache = $this->serviceManager->get('RoutingCache'); |
268
|
|
|
// $routingCache->set($request->getPathInfo(), $routeParams); |
269
|
|
|
// } else { |
270
|
|
|
// $routeParams = $this->getRouteFromCache($request); |
271
|
|
|
// } |
272
|
|
|
|
273
|
|
|
$request->attributes->add($routeParams); |
274
|
|
|
|
275
|
|
|
// Resolve our Controller |
276
|
|
|
$resolver = $this->serviceManager->get('ControllerResolver'); |
277
|
|
|
if (false === $controller = $resolver->getController($request)) { |
278
|
|
|
throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s".', $request->getPathInfo())); |
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
$controllerArguments = $resolver->getArguments($request, $controller); |
282
|
|
|
|
283
|
|
|
$result = call_user_func_array( |
284
|
|
|
$controller, |
285
|
|
|
$controllerArguments |
286
|
|
|
); |
287
|
|
|
|
288
|
|
|
if ($result === null) { |
289
|
|
|
throw new \Exception('Your action returned null. It must always return something'); |
290
|
|
|
} elseif (is_string($result)) { |
291
|
|
|
$response->setContent($result); |
292
|
|
|
} elseif ($result instanceof SymfonyResponse || $response instanceof HttpResponse) { |
293
|
|
|
$response = $result; |
294
|
|
|
} else { |
295
|
|
|
throw new \Exception('Invalid response type returned from controller'); |
296
|
|
|
} |
297
|
|
|
|
298
|
|
|
return $response; |
|
|
|
|
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
/** |
302
|
|
|
* Gets the name of the application. |
303
|
|
|
* |
304
|
|
|
* @return string The application name |
305
|
|
|
* |
306
|
|
|
* @api |
307
|
|
|
*/ |
308
|
|
|
public function getName() |
309
|
|
|
{ |
310
|
|
|
if (null === $this->name) { |
311
|
|
|
$this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir)); |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
return $this->name; |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
/** |
318
|
|
|
* Gets the version of the application. |
319
|
|
|
* |
320
|
|
|
* @return string The application version |
321
|
|
|
* |
322
|
|
|
* @api |
323
|
|
|
*/ |
324
|
|
|
public function getVersion() |
325
|
|
|
{ |
326
|
|
|
return self::VERSION; |
327
|
|
|
} |
328
|
|
|
|
329
|
|
|
/** |
330
|
|
|
* Get the environment mode the application is in. |
331
|
|
|
* |
332
|
|
|
* @return string The current environment |
333
|
|
|
* |
334
|
|
|
* @api |
335
|
|
|
*/ |
336
|
|
|
public function getEnvironment() |
337
|
|
|
{ |
338
|
|
|
return $this->environment; |
339
|
|
|
} |
340
|
|
|
|
341
|
|
|
/** |
342
|
|
|
* @param $env |
343
|
|
|
* |
344
|
|
|
* @return bool |
345
|
|
|
*/ |
346
|
|
|
public function isEnvironment($env) |
347
|
|
|
{ |
348
|
|
|
if ('development' == $env) { |
349
|
|
|
$env = 'dev'; |
350
|
|
|
} elseif ('production' == $env) { |
351
|
|
|
$env = 'prod'; |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
return $this->getEnvironment() == $env; |
355
|
|
|
} |
356
|
|
|
|
357
|
|
|
/** |
358
|
|
|
* Checks if debug mode is enabled. |
359
|
|
|
* |
360
|
|
|
* @return bool true if debug mode is enabled, false otherwise |
361
|
|
|
* |
362
|
|
|
* @api |
363
|
|
|
*/ |
364
|
|
|
public function isDebug() |
365
|
|
|
{ |
366
|
|
|
return $this->debug; |
367
|
|
|
} |
368
|
|
|
|
369
|
|
|
/** |
370
|
|
|
* Gets the application root dir. |
371
|
|
|
* |
372
|
|
|
* @return string The application root dir |
373
|
|
|
* |
374
|
|
|
* @api |
375
|
|
|
*/ |
376
|
|
|
public function getRootDir() |
377
|
|
|
{ |
378
|
|
|
if (null === $this->rootDir) { |
379
|
|
|
$this->rootDir = realpath(getcwd() . '/app'); |
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
return $this->rootDir; |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* Get the service manager. |
387
|
|
|
* |
388
|
|
|
* @return ServiceManager |
389
|
|
|
*/ |
390
|
|
|
public function getServiceManager() |
391
|
|
|
{ |
392
|
|
|
return $this->serviceManager; |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
/** |
396
|
|
|
* @note Added for compatibility with Symfony's HttpKernel\Kernel. |
397
|
|
|
* |
398
|
|
|
* @return null|ServiceManager |
399
|
|
|
*/ |
400
|
|
|
public function getContainer() |
401
|
|
|
{ |
402
|
|
|
return $this->serviceManager; |
403
|
|
|
} |
404
|
|
|
|
405
|
|
|
/** |
406
|
|
|
* Returns the Module Manager. |
407
|
|
|
* |
408
|
|
|
* @return \Zend\ModuleManager\ModuleManager |
409
|
|
|
*/ |
410
|
|
|
public function getModuleManager() |
411
|
|
|
{ |
412
|
|
|
if (null === $this->moduleManager) { |
413
|
|
|
$this->moduleManager = $this->serviceManager->get('ModuleManager'); |
|
|
|
|
414
|
|
|
} |
415
|
|
|
|
416
|
|
|
return $this->moduleManager; |
|
|
|
|
417
|
|
|
} |
418
|
|
|
|
419
|
|
|
/** |
420
|
|
|
* Get an array of the loaded modules. |
421
|
|
|
* |
422
|
|
|
* @return array An array of Module objects, keyed by module name |
423
|
|
|
*/ |
424
|
|
|
public function getModules() |
425
|
|
|
{ |
426
|
|
|
return $this->getModuleManager()->getLoadedModules(true); |
427
|
|
|
} |
428
|
|
|
|
429
|
|
|
/** |
430
|
|
|
* @see PPI\Framework\Module\ModuleManager::locateResource() |
431
|
|
|
* |
432
|
|
|
* @param string $name A resource name to locate |
433
|
|
|
* @param string $dir A directory where to look for the resource first |
434
|
|
|
* @param bool $first Whether to return the first path or paths for all matching bundles |
435
|
|
|
* |
436
|
|
|
* @throws \InvalidArgumentException if the file cannot be found or the name is not valid |
437
|
|
|
* @throws \RuntimeException if the name contains invalid/unsafe |
438
|
|
|
* @throws \RuntimeException if a custom resource is hidden by a resource in a derived bundle |
439
|
|
|
* |
440
|
|
|
* @return string|array The absolute path of the resource or an array if $first is false |
441
|
|
|
*/ |
442
|
|
|
public function locateResource($name, $dir = null, $first = true) |
443
|
|
|
{ |
444
|
|
|
return $this->getModuleManager()->locateResource($name, $dir, $first); |
|
|
|
|
445
|
|
|
} |
446
|
|
|
|
447
|
|
|
/** |
448
|
|
|
* Gets the request start time (not available if debug is disabled). |
449
|
|
|
* |
450
|
|
|
* @return int The request start timestamp |
451
|
|
|
* |
452
|
|
|
* @api |
453
|
|
|
*/ |
454
|
|
|
public function getStartTime() |
455
|
|
|
{ |
456
|
|
|
return $this->debug ? $this->startTime : -INF; |
457
|
|
|
} |
458
|
|
|
|
459
|
|
|
/** |
460
|
|
|
* Gets the cache directory. |
461
|
|
|
* |
462
|
|
|
* @return string The cache directory |
463
|
|
|
* |
464
|
|
|
* @api |
465
|
|
|
*/ |
466
|
|
|
public function getCacheDir() |
467
|
|
|
{ |
468
|
|
|
return $this->rootDir . '/cache/' . $this->environment; |
469
|
|
|
} |
470
|
|
|
|
471
|
|
|
/** |
472
|
|
|
* Gets the log directory. |
473
|
|
|
* |
474
|
|
|
* @return string The log directory |
475
|
|
|
* |
476
|
|
|
* @api |
477
|
|
|
*/ |
478
|
|
|
public function getLogDir() |
479
|
|
|
{ |
480
|
|
|
return $this->rootDir . '/logs'; |
481
|
|
|
} |
482
|
|
|
|
483
|
|
|
/** |
484
|
|
|
* Gets the charset of the application. |
485
|
|
|
* |
486
|
|
|
* @return string The charset |
487
|
|
|
* |
488
|
|
|
* @api |
489
|
|
|
*/ |
490
|
|
|
public function getCharset() |
491
|
|
|
{ |
492
|
|
|
return 'UTF-8'; |
493
|
|
|
} |
494
|
|
|
|
495
|
|
|
/** |
496
|
|
|
* Returns a ConfigManager instance. |
497
|
|
|
* |
498
|
|
|
* @return \PPI\Framework\Config\ConfigManager |
499
|
|
|
*/ |
500
|
|
|
public function getConfigManager() |
501
|
|
|
{ |
502
|
|
|
if (null === $this->configManager) { |
503
|
|
|
$cachePath = $this->getCacheDir() . '/application-config-cache.' . $this->getName() . '.php'; |
504
|
|
|
$this->configManager = new ConfigManager($cachePath, !$this->debug, $this->rootDir . '/config'); |
505
|
|
|
} |
506
|
|
|
|
507
|
|
|
return $this->configManager; |
508
|
|
|
} |
509
|
|
|
|
510
|
|
|
/** |
511
|
|
|
* Loads a configuration file or PHP array. |
512
|
|
|
* |
513
|
|
|
* @param $resource |
514
|
|
|
* @param null $type |
515
|
|
|
* |
516
|
|
|
* @return App The current instance |
517
|
|
|
*/ |
518
|
|
|
public function loadConfig($resource, $type = null) |
519
|
|
|
{ |
520
|
|
|
$this->getConfigManager()->addConfig($resource, $type); |
521
|
|
|
|
522
|
|
|
return $this; |
523
|
|
|
} |
524
|
|
|
|
525
|
|
|
/** |
526
|
|
|
* Returns the application configuration. |
527
|
|
|
* |
528
|
|
|
* @throws \RuntimeException |
529
|
|
|
* |
530
|
|
|
* @return array|object |
531
|
|
|
*/ |
532
|
|
|
public function getConfig() |
533
|
|
|
{ |
534
|
|
|
if (!$this->booted) { |
535
|
|
|
throw new \RuntimeException('The "Config" service is only available after the App boot()'); |
536
|
|
|
} |
537
|
|
|
|
538
|
|
|
return $this->serviceManager->get('Config'); |
539
|
|
|
} |
540
|
|
|
|
541
|
|
|
/** |
542
|
|
|
* @return string |
543
|
|
|
*/ |
544
|
|
|
public function serialize() |
545
|
|
|
{ |
546
|
|
|
return serialize(array($this->environment, $this->debug)); |
547
|
|
|
} |
548
|
|
|
|
549
|
|
|
/** |
550
|
|
|
* @param KernelInterface $kernel |
551
|
|
|
*/ |
552
|
|
|
public function setSymfonyKernel(KernelInterface $kernel) |
553
|
|
|
{ |
554
|
|
|
$this->symfonyKernel = $kernel; |
555
|
|
|
} |
556
|
|
|
|
557
|
|
|
public function unserialize($data) |
558
|
|
|
{ |
559
|
|
|
list($environment, $debug) = unserialize($data); |
560
|
|
|
|
561
|
|
|
$this->__construct($environment, $debug); |
|
|
|
|
562
|
|
|
} |
563
|
|
|
|
564
|
|
|
/** |
565
|
|
|
* Returns the application parameters. |
566
|
|
|
* |
567
|
|
|
* @return array An array of application parameters |
568
|
|
|
*/ |
569
|
|
|
protected function getAppParameters() |
570
|
|
|
{ |
571
|
|
|
return array_merge( |
572
|
|
|
array( |
573
|
|
|
'app.root_dir' => $this->rootDir, |
574
|
|
|
'app.environment' => $this->environment, |
575
|
|
|
'app.debug' => $this->debug, |
576
|
|
|
'app.name' => $this->name, |
577
|
|
|
'app.cache_dir' => $this->getCacheDir(), |
578
|
|
|
'app.logs_dir' => $this->getLogDir(), |
579
|
|
|
'app.charset' => $this->getCharset(), |
580
|
|
|
), |
581
|
|
|
$this->getEnvParameters() |
582
|
|
|
); |
583
|
|
|
} |
584
|
|
|
|
585
|
|
|
/** |
586
|
|
|
* Gets the environment parameters. |
587
|
|
|
* |
588
|
|
|
* Only the parameters starting with "PPI__" are considered. |
589
|
|
|
* |
590
|
|
|
* @return array An array of parameters |
591
|
|
|
*/ |
592
|
|
|
protected function getEnvParameters() |
|
|
|
|
593
|
|
|
{ |
594
|
|
|
$parameters = array(); |
595
|
|
|
foreach ($_SERVER as $key => $value) { |
596
|
|
|
if (0 === strpos($key, 'PPI__')) { |
597
|
|
|
$parameters[strtolower(str_replace('__', '.', substr($key, 5)))] = $value; |
598
|
|
|
} |
599
|
|
|
} |
600
|
|
|
|
601
|
|
|
return $parameters; |
602
|
|
|
} |
603
|
|
|
|
604
|
|
|
/** |
605
|
|
|
* Creates and initializes a ServiceManager instance. |
606
|
|
|
* |
607
|
|
|
* @return ServiceManager The compiled service manager |
608
|
|
|
*/ |
609
|
|
|
protected function buildServiceManager() |
610
|
|
|
{ |
611
|
|
|
// ServiceManager creation |
612
|
|
|
$serviceManager = new ServiceManagerBuilder($this->getConfigManager()->getMergedConfig()); |
613
|
|
|
$serviceManager->build($this->getAppParameters()); |
614
|
|
|
$serviceManager->set('app', $this); |
615
|
|
|
|
616
|
|
|
return $serviceManager; |
617
|
|
|
} |
618
|
|
|
|
619
|
|
|
/** |
620
|
|
|
* Perform the matching of a route and return a set of routing parameters if a valid one is found. |
621
|
|
|
* Otherwise exceptions get thrown. |
622
|
|
|
* |
623
|
|
|
* @param HttpRequest $request |
624
|
|
|
* |
625
|
|
|
* @throws \Exception |
626
|
|
|
* |
627
|
|
|
* @return array |
628
|
|
|
*/ |
629
|
|
|
protected function handleRouting(HttpRequest $request) |
630
|
|
|
{ |
631
|
|
|
$this->router = $this->serviceManager->get('Router'); |
|
|
|
|
632
|
|
|
$this->router->warmUp($this->getCacheDir()); |
633
|
|
|
|
634
|
|
|
try { |
635
|
|
|
// Lets load up our router and match the appropriate route |
636
|
|
|
$parameters = $this->router->matchRequest($request); |
637
|
|
View Code Duplication |
if (!empty($parameters)) { |
|
|
|
|
638
|
|
|
if (null !== $this->logger) { |
639
|
|
|
$this->logger->info(sprintf('Matched route "%s" (parameters: %s)', $parameters['_route'], $this->router->parametersToString($parameters))); |
640
|
|
|
} |
641
|
|
|
} |
642
|
|
|
} catch (ResourceNotFoundException $e) { |
643
|
|
|
$routeUri = $this->router->generate('Framework_404'); |
644
|
|
|
$parameters = $this->router->matchRequest($request::create($routeUri)); |
645
|
|
|
} catch (\Exception $e) { |
646
|
|
|
throw $e; |
647
|
|
|
} |
648
|
|
|
|
649
|
|
|
$parameters['_route_params'] = $parameters; |
650
|
|
|
|
651
|
|
|
return $parameters; |
652
|
|
|
} |
653
|
|
|
|
654
|
|
|
/** |
655
|
|
|
* Logs with an arbitrary level. |
656
|
|
|
* |
657
|
|
|
* @param mixed $level |
658
|
|
|
* @param string $message |
659
|
|
|
* @param array $context |
660
|
|
|
*/ |
661
|
|
|
protected function log($level, $message, array $context = array()) |
662
|
|
|
{ |
663
|
|
|
if (null === $this->logger && $this->getServiceManager()->has('logger')) { |
664
|
|
|
$this->logger = $this->getServiceManager()->get('logger'); |
|
|
|
|
665
|
|
|
} |
666
|
|
|
|
667
|
|
|
if ($this->logger) { |
668
|
|
|
$this->logger->log($level, $message, $context); |
669
|
|
|
} |
670
|
|
|
} |
671
|
|
|
} |
672
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.