1 | <?php |
||||||
2 | |||||||
3 | /** |
||||||
4 | * TApplication class file |
||||||
5 | * |
||||||
6 | * @author Qiang Xue <[email protected]> |
||||||
7 | * @link https://github.com/pradosoft/prado |
||||||
8 | * @license https://github.com/pradosoft/prado/blob/master/LICENSE |
||||||
9 | */ |
||||||
10 | |||||||
11 | namespace Prado; |
||||||
12 | |||||||
13 | use Prado\Exceptions\TErrorHandler; |
||||||
14 | use Prado\Exceptions\TExitException; |
||||||
15 | use Prado\Exceptions\THttpException; |
||||||
16 | use Prado\Exceptions\TConfigurationException; |
||||||
17 | use Prado\I18N\TGlobalization; |
||||||
18 | use Prado\Security\TSecurityManager; |
||||||
19 | use Prado\Web\TAssetManager; |
||||||
20 | use Prado\Web\THttpRequest; |
||||||
21 | use Prado\Web\THttpResponse; |
||||||
22 | use Prado\Web\THttpSession; |
||||||
23 | use Prado\Util\TLogger; |
||||||
24 | use Prado\Web\UI\TTemplateManager; |
||||||
25 | use Prado\Web\UI\TThemeManager; |
||||||
26 | |||||||
27 | /** |
||||||
28 | * TApplication class. |
||||||
29 | * |
||||||
30 | * TApplication coordinates modules and services, and serves as a configuration |
||||||
31 | * context for all Prado components. |
||||||
32 | * |
||||||
33 | * TApplication uses a configuration file to specify the settings of |
||||||
34 | * the application, the modules, the services, the parameters, and so on. |
||||||
35 | * |
||||||
36 | * TApplication adopts a modular structure. A TApplication instance is a composition |
||||||
37 | * of multiple modules. A module is an instance of class implementing |
||||||
38 | * {@see \Prado\IModule} interface. Each module accomplishes certain functionalities |
||||||
39 | * that are shared by all Prado components in an application. |
||||||
40 | * There are default modules, composer modules, and user-defined modules. The latter |
||||||
41 | * offers extreme flexibility of extending TApplication in a plug-and-play fashion. |
||||||
42 | * Modules cooperate with each other to serve a user request by following |
||||||
43 | * a sequence of lifecycles predefined in TApplication. |
||||||
44 | * |
||||||
45 | * TApplicationConfiguration loads the composer.json for each installed composer extension |
||||||
46 | * and checks the extra field for a "bootstrap" class for the package. |
||||||
47 | * Packages can be specified as a configuration module (without a class) to load the |
||||||
48 | * composer extension module. The ID of the module is the name of the package. |
||||||
49 | * |
||||||
50 | * TApplication has four modes that can be changed by setting {@see setMode Mode} |
||||||
51 | * property (in the application configuration file). |
||||||
52 | * - <b>Off</b> mode will prevent the application from serving user requests. |
||||||
53 | * - <b>Debug</b> mode is mainly used during application development. It ensures |
||||||
54 | * the cache is always up-to-date if caching is enabled. It also allows |
||||||
55 | * exceptions are displayed with rich context information if they occur. |
||||||
56 | * - <b>Normal</b> mode is mainly used during production stage. Exception information |
||||||
57 | * will only be recorded in system error logs. The cache is ensured to be |
||||||
58 | * up-to-date if it is enabled. |
||||||
59 | * - <b>Performance</b> mode is similar to <b>Normal</b> mode except that it |
||||||
60 | * does not ensure the cache is up-to-date. |
||||||
61 | * |
||||||
62 | * TApplication dispatches each user request to a particular service which |
||||||
63 | * finishes the actual work for the request with the aid from the application |
||||||
64 | * modules. |
||||||
65 | * |
||||||
66 | * TApplication maintains a lifecycle with the following stages: |
||||||
67 | * - [construct] : construction of the application instance |
||||||
68 | * - [initApplication] : load application configuration and instantiate modules and the requested service |
||||||
69 | * - onInitComplete : this event happens right after after module and service initialization. This event is particularly useful for CLI/Shell applications |
||||||
70 | * - onBeginRequest : this event happens right after application initialization |
||||||
71 | * - onAuthentication : this event happens when authentication is needed for the current request |
||||||
72 | * - onAuthenticationComplete : this event happens right after the authentication is done for the current request |
||||||
73 | * - onAuthorization : this event happens when authorization is needed for the current request |
||||||
74 | * - onAuthorizationComplete : this event happens right after the authorization is done for the current request |
||||||
75 | * - onLoadState : this event happens when application state needs to be loaded |
||||||
76 | * - onLoadStateComplete : this event happens right after the application state is loaded |
||||||
77 | * - onPreRunService : this event happens right before the requested service is to run |
||||||
78 | * - runService : the requested service runs |
||||||
79 | * - onSaveState : this event happens when application needs to save its state |
||||||
80 | * - onSaveStateComplete : this event happens right after the application saves its state |
||||||
81 | * - onPreFlushOutput : this event happens right before the application flushes output to client side. |
||||||
82 | * - flushOutput : the application flushes output to client side. |
||||||
83 | * - onEndRequest : this is the last stage a request is being completed |
||||||
84 | * - [destruct] : destruction of the application instance |
||||||
85 | * Modules and services can attach their methods to one or several of the above |
||||||
86 | * events and do appropriate processing when the events are raised. By this way, |
||||||
87 | * the application is able to coordinate the activities of modules and services |
||||||
88 | * in the above order. To terminate an application before the whole lifecycle |
||||||
89 | * completes, call {@see completeRequest}. |
||||||
90 | * |
||||||
91 | * Examples: |
||||||
92 | * - Create and run a Prado application: |
||||||
93 | * ```php |
||||||
94 | * $application=new TApplication($configFile); |
||||||
95 | * $application->run(); |
||||||
96 | * ``` |
||||||
97 | * |
||||||
98 | * @author Qiang Xue <[email protected]> |
||||||
99 | * @since 3.0 |
||||||
100 | */ |
||||||
101 | class TApplication extends \Prado\TComponent implements ISingleton |
||||||
102 | { |
||||||
103 | /** |
||||||
104 | * Page service ID |
||||||
105 | */ |
||||||
106 | public const PAGE_SERVICE_ID = 'page'; |
||||||
107 | /** |
||||||
108 | * Application configuration file name |
||||||
109 | */ |
||||||
110 | public const CONFIG_FILE_XML = 'application.xml'; |
||||||
111 | /** |
||||||
112 | * File extension for external config files |
||||||
113 | */ |
||||||
114 | public const CONFIG_FILE_EXT_XML = '.xml'; |
||||||
115 | /** |
||||||
116 | * Configuration file type, application.xml and config.xml |
||||||
117 | */ |
||||||
118 | public const CONFIG_TYPE_XML = 'xml'; |
||||||
119 | /** |
||||||
120 | * Application configuration file name |
||||||
121 | */ |
||||||
122 | public const CONFIG_FILE_PHP = 'application.php'; |
||||||
123 | /** |
||||||
124 | * File extension for external config files |
||||||
125 | */ |
||||||
126 | public const CONFIG_FILE_EXT_PHP = '.php'; |
||||||
127 | /** |
||||||
128 | * Configuration file type, application.php and config.php |
||||||
129 | */ |
||||||
130 | public const CONFIG_TYPE_PHP = 'php'; |
||||||
131 | /** |
||||||
132 | * Runtime directory name |
||||||
133 | */ |
||||||
134 | public const RUNTIME_PATH = 'runtime'; |
||||||
135 | /** |
||||||
136 | * Config cache file |
||||||
137 | */ |
||||||
138 | public const CONFIGCACHE_FILE = 'config.cache'; |
||||||
139 | /** |
||||||
140 | * Global data file |
||||||
141 | */ |
||||||
142 | public const GLOBAL_FILE = 'global.cache'; |
||||||
143 | |||||||
144 | /** |
||||||
145 | * @var array list of events that define application lifecycles |
||||||
146 | */ |
||||||
147 | private static $_steps = [ |
||||||
148 | 'onBeginRequest', |
||||||
149 | 'onLoadState', |
||||||
150 | 'onLoadStateComplete', |
||||||
151 | 'onAuthentication', |
||||||
152 | 'onAuthenticationComplete', |
||||||
153 | 'onAuthorization', |
||||||
154 | 'onAuthorizationComplete', |
||||||
155 | 'onPreRunService', |
||||||
156 | 'runService', |
||||||
157 | 'onSaveState', |
||||||
158 | 'onSaveStateComplete', |
||||||
159 | 'onPreFlushOutput', |
||||||
160 | 'flushOutput', |
||||||
161 | ]; |
||||||
162 | |||||||
163 | /** |
||||||
164 | * @var string application ID |
||||||
165 | */ |
||||||
166 | private $_id; |
||||||
167 | /** |
||||||
168 | * @var string unique application ID |
||||||
169 | */ |
||||||
170 | private $_uniqueID; |
||||||
171 | /** |
||||||
172 | * @var bool whether the request is completed |
||||||
173 | */ |
||||||
174 | private $_requestCompleted = false; |
||||||
175 | /** |
||||||
176 | * @var int application state |
||||||
177 | */ |
||||||
178 | private $_step; |
||||||
179 | /** |
||||||
180 | * @var array available services and their configurations indexed by service IDs |
||||||
181 | */ |
||||||
182 | private $_services; |
||||||
183 | /** |
||||||
184 | * @var IService current service instance |
||||||
185 | */ |
||||||
186 | private $_service; |
||||||
187 | /** |
||||||
188 | * @var array list of loaded application modules |
||||||
189 | */ |
||||||
190 | private $_modules = []; |
||||||
191 | /** |
||||||
192 | * @var array list of application modules yet to be loaded |
||||||
193 | */ |
||||||
194 | private $_lazyModules = []; |
||||||
195 | /** |
||||||
196 | * @var \Prado\Collections\TMap list of application parameters |
||||||
197 | */ |
||||||
198 | private $_parameters; |
||||||
199 | /** |
||||||
200 | * @var string configuration file |
||||||
201 | */ |
||||||
202 | private $_configFile; |
||||||
203 | /** |
||||||
204 | * @var string configuration file extension |
||||||
205 | */ |
||||||
206 | private $_configFileExt; |
||||||
207 | /** |
||||||
208 | * @var string configuration type |
||||||
209 | */ |
||||||
210 | private $_configType; |
||||||
211 | /** |
||||||
212 | * @var string application base path |
||||||
213 | */ |
||||||
214 | private $_basePath; |
||||||
215 | /** |
||||||
216 | * @var string directory storing application state |
||||||
217 | */ |
||||||
218 | private $_runtimePath; |
||||||
219 | /** |
||||||
220 | * @var bool if any global state is changed during the current request |
||||||
221 | */ |
||||||
222 | private $_stateChanged = false; |
||||||
223 | /** |
||||||
224 | * @var array global variables (persistent across sessions, requests) |
||||||
225 | */ |
||||||
226 | private $_globals = []; |
||||||
227 | /** |
||||||
228 | * @var string cache file |
||||||
229 | */ |
||||||
230 | private $_cacheFile; |
||||||
231 | /** |
||||||
232 | * @var TErrorHandler error handler module |
||||||
233 | */ |
||||||
234 | private $_errorHandler; |
||||||
235 | /** |
||||||
236 | * @var THttpRequest request module |
||||||
237 | */ |
||||||
238 | private $_request; |
||||||
239 | /** |
||||||
240 | * @var THttpResponse response module |
||||||
241 | */ |
||||||
242 | private $_response; |
||||||
243 | /** |
||||||
244 | * @var THttpSession session module, could be null |
||||||
245 | */ |
||||||
246 | private $_session; |
||||||
247 | /** |
||||||
248 | * @var \Prado\Caching\ICache cache module, could be null |
||||||
249 | */ |
||||||
250 | private $_cache; |
||||||
251 | /** |
||||||
252 | * @var IStatePersister application state persister |
||||||
253 | */ |
||||||
254 | private $_statePersister; |
||||||
255 | /** |
||||||
256 | * @var \Prado\Security\IUser user instance, could be null |
||||||
257 | */ |
||||||
258 | private $_user; |
||||||
259 | /** |
||||||
260 | * @var TGlobalization module, could be null |
||||||
261 | */ |
||||||
262 | private $_globalization; |
||||||
263 | /** |
||||||
264 | * @var TSecurityManager security manager module |
||||||
265 | */ |
||||||
266 | private $_security; |
||||||
267 | /** |
||||||
268 | * @var TAssetManager asset manager module |
||||||
269 | */ |
||||||
270 | private $_assetManager; |
||||||
271 | /** |
||||||
272 | * @var \Prado\Web\UI\TTemplateManager template manager module |
||||||
273 | */ |
||||||
274 | private $_templateManager; |
||||||
275 | /** |
||||||
276 | * @var \Prado\Web\UI\TThemeManager theme manager module |
||||||
277 | */ |
||||||
278 | private $_themeManager; |
||||||
279 | /** |
||||||
280 | * @var \Prado\Security\TAuthorizationRuleCollection collection of authorization rules |
||||||
281 | */ |
||||||
282 | private $_authRules; |
||||||
283 | /** |
||||||
284 | * @var string|TApplicationMode application mode |
||||||
285 | */ |
||||||
286 | private $_mode = TApplicationMode::Debug; |
||||||
287 | |||||||
288 | /** |
||||||
289 | * @var string Customizable page service ID |
||||||
290 | */ |
||||||
291 | private $_pageServiceID = self::PAGE_SERVICE_ID; |
||||||
292 | |||||||
293 | /** |
||||||
294 | * Constructor. |
||||||
295 | * Sets application base path and initializes the application singleton. |
||||||
296 | 55 | * Application base path refers to the root directory storing application |
|||||
297 | * data and code not directly accessible by Web users. |
||||||
298 | * By default, the base path is assumed to be the <b>protected</b> |
||||||
299 | 55 | * directory under the directory containing the current running script. |
|||||
300 | 55 | * @param string $basePath application base path or configuration file path. |
|||||
301 | 55 | * If the parameter is a file, it is assumed to be the application |
|||||
302 | * configuration file, and the directory containing the file is treated |
||||||
303 | 55 | * as the application base path. |
|||||
304 | 26 | * If it is a directory, it is assumed to be the application base path, |
|||||
305 | * and within that directory, a file named <b>application.xml</b> |
||||||
306 | * will be looked for. If found, the file is considered as the application |
||||||
307 | * configuration file. |
||||||
308 | 55 | * @param bool $cacheConfig whether to cache application configuration. Defaults to true. |
|||||
309 | 55 | * @param string $configType configuration type. Defaults to CONFIG_TYPE_XML. |
|||||
310 | 55 | * @throws TConfigurationException if configuration file cannot be read or the runtime path is invalid. |
|||||
311 | */ |
||||||
312 | 55 | public function __construct($basePath = 'protected', $cacheConfig = true, $configType = self::CONFIG_TYPE_XML) |
|||||
313 | 55 | { |
|||||
314 | // register application as a singleton |
||||||
315 | Prado::setApplication($this); |
||||||
316 | $this->setConfigurationType($configType); |
||||||
317 | $this->resolvePaths($basePath); |
||||||
318 | |||||||
319 | if ($cacheConfig) { |
||||||
320 | $this->_cacheFile = $this->_runtimePath . DIRECTORY_SEPARATOR . self::CONFIGCACHE_FILE; |
||||||
321 | } |
||||||
322 | |||||||
323 | // generates unique ID by hashing the runtime path |
||||||
324 | $this->_uniqueID = md5($this->_runtimePath); |
||||||
325 | 55 | $this->_parameters = new \Prado\Collections\TMap(); |
|||||
326 | $this->_services = [$this->getPageServiceID() => ['TPageService', [], null]]; |
||||||
327 | |||||||
328 | 55 | Prado::setPathOfAlias('Application', $this->_basePath); |
|||||
329 | parent::__construct(); |
||||||
330 | } |
||||||
331 | 55 | ||||||
332 | /** |
||||||
333 | 55 | * Returns the current Prado application. This enables application behaviors to |
|||||
334 | * be used for undefined static function calls via {@see \Prado\TComponent::__callStatic}. |
||||||
335 | * @param bool $create This is ignored and returns Prado::getApplication(). |
||||||
336 | * @return ?object The singleton instance of the class. |
||||||
337 | 55 | * @since 4.3.0 |
|||||
338 | */ |
||||||
339 | public static function singleton(bool $create = true): ?object |
||||||
340 | { |
||||||
341 | 55 | return Prado::getApplication(); |
|||||
342 | 55 | } |
|||||
343 | 55 | ||||||
344 | /** |
||||||
345 | * Resolves application-relevant paths. |
||||||
346 | * This method is invoked by the application constructor |
||||||
347 | * to determine the application configuration file, |
||||||
348 | * application root path and the runtime path. |
||||||
349 | * @param string $basePath the application root path or the application configuration file |
||||||
350 | * @see setBasePath |
||||||
351 | * @see setRuntimePath |
||||||
352 | * @see setConfigurationFile |
||||||
353 | 55 | */ |
|||||
354 | 55 | protected function resolvePaths($basePath) |
|||||
355 | { |
||||||
356 | // determine configuration path and file |
||||||
357 | if (empty($errValue = $basePath) || ($basePath = realpath($basePath)) === false) { |
||||||
358 | 55 | throw new TConfigurationException('application_basepath_invalid', $errValue); |
|||||
359 | } |
||||||
360 | if (is_dir($basePath) && is_file($basePath . DIRECTORY_SEPARATOR . $this->getConfigurationFileName())) { |
||||||
361 | $configFile = $basePath . DIRECTORY_SEPARATOR . $this->getConfigurationFileName(); |
||||||
362 | } elseif (is_file($basePath)) { |
||||||
363 | $configFile = $basePath; |
||||||
364 | $basePath = dirname($configFile); |
||||||
365 | } else { |
||||||
366 | $configFile = null; |
||||||
367 | } |
||||||
368 | |||||||
369 | // determine runtime path |
||||||
370 | $runtimePath = $basePath . DIRECTORY_SEPARATOR . self::RUNTIME_PATH; |
||||||
371 | if (is_writable($runtimePath)) { |
||||||
372 | if ($configFile !== null) { |
||||||
373 | $runtimePath .= DIRECTORY_SEPARATOR . basename($configFile) . '-' . Prado::getVersion(); |
||||||
374 | if (!is_dir($runtimePath)) { |
||||||
375 | if (@mkdir($runtimePath) === false) { |
||||||
376 | throw new TConfigurationException('application_runtimepath_failed', $runtimePath); |
||||||
377 | } |
||||||
378 | @chmod($runtimePath, Prado::getDefaultDirPermissions()); //make it deletable |
||||||
0 ignored issues
–
show
|
|||||||
379 | } |
||||||
380 | $this->setConfigurationFile($configFile); |
||||||
381 | } |
||||||
382 | $this->setBasePath($basePath); |
||||||
383 | $this->setRuntimePath($runtimePath); |
||||||
384 | } else { |
||||||
385 | throw new TConfigurationException('application_runtimepath_invalid', $runtimePath); |
||||||
386 | } |
||||||
387 | } |
||||||
388 | |||||||
389 | /** |
||||||
390 | * Executes the lifecycles of the application. |
||||||
391 | * This is the main entry function that leads to the running of the whole |
||||||
392 | * Prado application. |
||||||
393 | */ |
||||||
394 | public function run() |
||||||
395 | { |
||||||
396 | try { |
||||||
397 | $this->initApplication(); |
||||||
398 | $n = count(self::$_steps); |
||||||
399 | $this->_step = 0; |
||||||
400 | $this->_requestCompleted = false; |
||||||
401 | while ($this->_step < $n) { |
||||||
402 | if ($this->_mode === TApplicationMode::Off) { |
||||||
403 | throw new THttpException(503, 'application_unavailable'); |
||||||
404 | } |
||||||
405 | if ($this->_requestCompleted) { |
||||||
406 | break; |
||||||
407 | } |
||||||
408 | $method = self::$_steps[$this->_step]; |
||||||
409 | Prado::trace("Executing $method()", TApplication::class); |
||||||
410 | $this->$method(); |
||||||
411 | $this->_step++; |
||||||
412 | } |
||||||
413 | } catch (TExitException $e) { |
||||||
414 | $this->onEndRequest(); |
||||||
415 | exit($e->getExitCode()); |
||||||
0 ignored issues
–
show
|
|||||||
416 | 3 | } catch (\Exception $e) { |
|||||
417 | $this->onError($e); |
||||||
418 | 3 | } |
|||||
419 | $this->onEndRequest(); |
||||||
420 | } |
||||||
421 | |||||||
422 | /** |
||||||
423 | * Completes current request processing. |
||||||
424 | * This method can be used to exit the application lifecycles after finishing |
||||||
425 | * the current cycle. |
||||||
426 | */ |
||||||
427 | public function completeRequest() |
||||||
428 | { |
||||||
429 | $this->_requestCompleted = true; |
||||||
430 | } |
||||||
431 | 3 | ||||||
432 | /** |
||||||
433 | 3 | * @return bool whether the current request is processed. |
|||||
434 | 3 | */ |
|||||
435 | public function getRequestCompleted() |
||||||
436 | { |
||||||
437 | 3 | return $this->_requestCompleted; |
|||||
438 | } |
||||||
439 | 3 | ||||||
440 | 3 | /** |
|||||
441 | * Returns a global value. |
||||||
442 | 3 | * |
|||||
443 | * A global value is one that is persistent across users sessions and requests. |
||||||
444 | * @param string $key the name of the value to be returned |
||||||
445 | * @param mixed $defaultValue the default value. If $key is not found, $defaultValue will be returned |
||||||
446 | * @return mixed the global value corresponding to $key |
||||||
447 | */ |
||||||
448 | public function getGlobalState($key, $defaultValue = null) |
||||||
449 | { |
||||||
450 | return $this->_globals[$key] ?? $defaultValue; |
||||||
451 | } |
||||||
452 | |||||||
453 | /** |
||||||
454 | * Sets a global value. |
||||||
455 | * |
||||||
456 | * A global value is one that is persistent across users sessions and requests. |
||||||
457 | * Make sure that the value is serializable and unserializable. |
||||||
458 | * @param string $key the name of the value to be set |
||||||
459 | * @param mixed $value the global value to be set |
||||||
460 | * @param null|mixed $defaultValue the default value. If $key is not found, $defaultValue will be returned |
||||||
461 | * @param bool $forceSave wheter to force an immediate GlobalState save. defaults to false |
||||||
462 | */ |
||||||
463 | public function setGlobalState($key, $value, $defaultValue = null, $forceSave = false) |
||||||
464 | { |
||||||
465 | $this->_stateChanged = true; |
||||||
466 | if ($value === $defaultValue) { |
||||||
467 | unset($this->_globals[$key]); |
||||||
468 | } else { |
||||||
469 | $this->_globals[$key] = $value; |
||||||
470 | } |
||||||
471 | 3 | if ($forceSave) { |
|||||
472 | $this->saveGlobals(); |
||||||
473 | 3 | } |
|||||
474 | 3 | } |
|||||
475 | 3 | ||||||
476 | /** |
||||||
477 | 3 | * Clears a global value. |
|||||
478 | * |
||||||
479 | * The value cleared will no longer be available in this request and the following requests. |
||||||
480 | * @param string $key the name of the value to be cleared |
||||||
481 | */ |
||||||
482 | 3 | public function clearGlobalState($key) |
|||||
483 | { |
||||||
484 | 3 | $this->_stateChanged = true; |
|||||
485 | unset($this->_globals[$key]); |
||||||
486 | } |
||||||
487 | |||||||
488 | /** |
||||||
489 | * Loads global values from persistent storage. |
||||||
490 | * This method is invoked when {@see onLoadState OnLoadState} event is raised. |
||||||
491 | * After this method, values that are stored in previous requests become |
||||||
492 | * available to the current request via {@see getGlobalState}. |
||||||
493 | */ |
||||||
494 | protected function loadGlobals() |
||||||
495 | { |
||||||
496 | $this->_globals = $this->getApplicationStatePersister()->load(); |
||||||
497 | } |
||||||
498 | 55 | ||||||
499 | /** |
||||||
500 | 55 | * Saves global values into persistent storage. |
|||||
501 | * This method is invoked when {@see onSaveState OnSaveState} event is raised. |
||||||
502 | */ |
||||||
503 | protected function saveGlobals() |
||||||
504 | { |
||||||
505 | if ($this->_stateChanged) { |
||||||
506 | $this->_stateChanged = false; |
||||||
507 | $this->getApplicationStatePersister()->save($this->_globals); |
||||||
508 | } |
||||||
509 | } |
||||||
510 | |||||||
511 | /** |
||||||
512 | * @return string application ID |
||||||
513 | */ |
||||||
514 | 7 | public function getID() |
|||||
515 | { |
||||||
516 | 7 | return $this->_id; |
|||||
517 | } |
||||||
518 | |||||||
519 | /** |
||||||
520 | * @param string $value application ID |
||||||
521 | */ |
||||||
522 | 32 | public function setID($value) |
|||||
523 | { |
||||||
524 | 32 | $this->_id = $value; |
|||||
525 | } |
||||||
526 | |||||||
527 | /** |
||||||
528 | * @return string page service ID |
||||||
529 | */ |
||||||
530 | public function getPageServiceID() |
||||||
531 | { |
||||||
532 | return $this->_pageServiceID; |
||||||
533 | } |
||||||
534 | |||||||
535 | /** |
||||||
536 | * @param string $value page service ID |
||||||
537 | */ |
||||||
538 | public function setPageServiceID($value) |
||||||
539 | { |
||||||
540 | $this->_pageServiceID = $value; |
||||||
541 | } |
||||||
542 | |||||||
543 | /** |
||||||
544 | * @return string an ID that uniquely identifies this Prado application from the others |
||||||
545 | */ |
||||||
546 | 55 | public function getUniqueID() |
|||||
547 | { |
||||||
548 | 55 | return $this->_uniqueID; |
|||||
549 | 55 | } |
|||||
550 | |||||||
551 | /** |
||||||
552 | * @return string|TApplicationMode application mode. Defaults to TApplicationMode::Debug. |
||||||
553 | */ |
||||||
554 | public function getMode() |
||||||
555 | { |
||||||
556 | return $this->_mode; |
||||||
557 | } |
||||||
558 | |||||||
559 | /** |
||||||
560 | * @param TApplicationMode $value application mode |
||||||
561 | */ |
||||||
562 | public function setMode($value) |
||||||
563 | { |
||||||
564 | $this->_mode = TPropertyValue::ensureEnum($value, TApplicationMode::class); |
||||||
565 | } |
||||||
566 | |||||||
567 | /** |
||||||
568 | * @return string the directory containing the application configuration file (absolute path) |
||||||
569 | */ |
||||||
570 | 9 | public function getBasePath() |
|||||
571 | { |
||||||
572 | 9 | return $this->_basePath; |
|||||
573 | } |
||||||
574 | |||||||
575 | /** |
||||||
576 | * @param string $value the directory containing the application configuration file |
||||||
577 | */ |
||||||
578 | 55 | public function setBasePath($value) |
|||||
579 | { |
||||||
580 | 55 | $this->_basePath = $value; |
|||||
581 | 55 | } |
|||||
582 | |||||||
583 | /** |
||||||
584 | * @return string the application configuration file (absolute path) |
||||||
585 | */ |
||||||
586 | public function getConfigurationFile() |
||||||
587 | { |
||||||
588 | return $this->_configFile; |
||||||
589 | } |
||||||
590 | |||||||
591 | /** |
||||||
592 | * @param string $value the application configuration file (absolute path) |
||||||
593 | */ |
||||||
594 | public function setConfigurationFile($value) |
||||||
595 | { |
||||||
596 | $this->_configFile = $value; |
||||||
597 | } |
||||||
598 | |||||||
599 | /** |
||||||
600 | * @return string the application configuration file (absolute path) |
||||||
601 | */ |
||||||
602 | public function getConfigurationType() |
||||||
603 | 55 | { |
|||||
604 | return $this->_configType; |
||||||
605 | 55 | } |
|||||
606 | 55 | ||||||
607 | 2 | /** |
|||||
608 | 2 | * @param string $value the application configuration type. 'xml' and 'php' are valid values |
|||||
609 | */ |
||||||
610 | public function setConfigurationType($value) |
||||||
611 | { |
||||||
612 | 2 | $this->_configType = $value; |
|||||
613 | } |
||||||
614 | |||||||
615 | 55 | /** |
|||||
616 | * @return string the application configuration type. default is 'xml' |
||||||
617 | */ |
||||||
618 | public function getConfigurationFileExt() |
||||||
619 | { |
||||||
620 | if ($this->_configFileExt === null) { |
||||||
621 | 3 | switch ($this->_configType) { |
|||||
622 | case TApplication::CONFIG_TYPE_PHP: |
||||||
623 | 3 | $this->_configFileExt = TApplication::CONFIG_FILE_EXT_PHP; |
|||||
624 | break; |
||||||
625 | default: |
||||||
626 | $this->_configFileExt = TApplication::CONFIG_FILE_EXT_XML; |
||||||
627 | } |
||||||
628 | } |
||||||
629 | 55 | return $this->_configFileExt; |
|||||
630 | } |
||||||
631 | 55 | ||||||
632 | 55 | /** |
|||||
633 | * @return string the default configuration file name |
||||||
634 | */ |
||||||
635 | public function getConfigurationFileName() |
||||||
636 | 55 | { |
|||||
637 | 55 | static $fileName; |
|||||
638 | if ($fileName == null) { |
||||||
639 | switch ($this->_configType) { |
||||||
640 | case TApplication::CONFIG_TYPE_PHP: |
||||||
641 | $fileName = TApplication::CONFIG_FILE_PHP; |
||||||
642 | break; |
||||||
643 | default: |
||||||
644 | $fileName = TApplication::CONFIG_FILE_XML; |
||||||
645 | } |
||||||
646 | } |
||||||
647 | return $fileName; |
||||||
648 | } |
||||||
649 | |||||||
650 | /** |
||||||
651 | * @return string the directory storing cache data and application-level persistent data. (absolute path) |
||||||
652 | */ |
||||||
653 | public function getRuntimePath() |
||||||
654 | { |
||||||
655 | return $this->_runtimePath; |
||||||
656 | } |
||||||
657 | |||||||
658 | /** |
||||||
659 | * @param string $value the directory storing cache data and application-level persistent data. (absolute path) |
||||||
660 | */ |
||||||
661 | 14 | public function setRuntimePath($value) |
|||||
662 | { |
||||||
663 | 14 | $this->_runtimePath = $value; |
|||||
664 | if ($this->_cacheFile) { |
||||||
665 | $this->_cacheFile = $this->_runtimePath . DIRECTORY_SEPARATOR . self::CONFIGCACHE_FILE; |
||||||
666 | 14 | } |
|||||
667 | // generates unique ID by hashing the runtime path |
||||||
668 | 14 | $this->_uniqueID = md5($this->_runtimePath); |
|||||
669 | } |
||||||
670 | |||||||
671 | /** |
||||||
672 | * @return TService the currently requested service |
||||||
673 | */ |
||||||
674 | 15 | public function getService() |
|||||
675 | { |
||||||
676 | 15 | return $this->_service; |
|||||
677 | 2 | } |
|||||
678 | |||||||
679 | /** |
||||||
680 | * @param IService $value the currently requested service |
||||||
681 | 15 | */ |
|||||
682 | public function setService($value) |
||||||
683 | { |
||||||
684 | $this->_service = $value; |
||||||
685 | } |
||||||
686 | 15 | ||||||
687 | /** |
||||||
688 | * Adds a module to application. |
||||||
689 | * Note, this method does not do module initialization. |
||||||
690 | * @param string $id ID of the module |
||||||
691 | * @param null|IModule $module module object or null if the module has not been loaded yet |
||||||
692 | */ |
||||||
693 | public function setModule($id, ?IModule $module = null) |
||||||
694 | { |
||||||
695 | if (isset($this->_modules[$id])) { |
||||||
696 | throw new TConfigurationException('application_moduleid_duplicated', $id); |
||||||
697 | } else { |
||||||
698 | $this->_modules[$id] = $module; |
||||||
699 | } |
||||||
700 | } |
||||||
701 | |||||||
702 | /** |
||||||
703 | * @param mixed $id |
||||||
704 | * @return null|TModule the module with the specified ID, null if not found |
||||||
705 | */ |
||||||
706 | public function getModule($id) |
||||||
707 | { |
||||||
708 | if (!array_key_exists($id, $this->_modules)) { |
||||||
709 | return null; |
||||||
710 | } |
||||||
711 | |||||||
712 | // force loading of a lazy module |
||||||
713 | 18 | if ($this->_modules[$id] === null) { |
|||||
714 | $module = $this->internalLoadModule($id, true); |
||||||
715 | 18 | $module[0]->init($module[1]); |
|||||
0 ignored issues
–
show
The method
init() does not exist on null .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||||||
716 | 1 | } |
|||||
717 | 1 | ||||||
718 | return $this->_modules[$id]; |
||||||
719 | 18 | } |
|||||
720 | |||||||
721 | /** |
||||||
722 | * Returns a list of application modules indexed by module IDs. |
||||||
723 | * Modules that have not been loaded yet are returned as null objects. |
||||||
724 | * @return array<TModule> list of loaded application modules, indexed by module IDs |
||||||
725 | 42 | */ |
|||||
726 | public function getModules() |
||||||
727 | 42 | { |
|||||
728 | 42 | return $this->_modules; |
|||||
729 | } |
||||||
730 | |||||||
731 | /** |
||||||
732 | * Returns a list of application modules of a specific class. |
||||||
733 | 1 | * Lazy Loading Modules are not loaded, and are null but have an ID Key. |
|||||
734 | * When null modules are found, load them with {@see getModule}. eg. |
||||||
735 | 1 | * ```php |
|||||
736 | * foreach (Prado::getApplication()->getModulesByType(\Prado\Caching\ICache::class) as $id => $module) { |
||||||
737 | * $module = (!$module) ? $app->getModule($id) : $module; |
||||||
738 | * ... |
||||||
739 | 1 | * } |
|||||
740 | * ``` |
||||||
741 | * @param string $type class name of the modules to look for. |
||||||
742 | * @param bool $strict should the module be the class or can the module be a subclass |
||||||
743 | * @return array keys are the ids of the module and values are module of a specific class |
||||||
744 | * @since 4.2.0 |
||||||
745 | 8 | */ |
|||||
746 | public function getModulesByType($type, $strict = false) |
||||||
747 | 8 | { |
|||||
748 | 8 | $m = []; |
|||||
749 | foreach ($this->_modules as $id => $module) { |
||||||
750 | if ($module === null && isset($this->_lazyModules[$id])) { |
||||||
751 | [$moduleClass, $initProperties, $configElement] = $this->_lazyModules[$id]; |
||||||
752 | if ($strict ? ($moduleClass === $type) : ($moduleClass instanceof $type)) { |
||||||
753 | $m[$id] = null; |
||||||
754 | } |
||||||
755 | } elseif ($module !== null && ($strict ? ($module::class === $type) : $module->isa($type))) { |
||||||
756 | $m[$id] = $module; |
||||||
757 | } |
||||||
758 | } |
||||||
759 | return $m; |
||||||
760 | } |
||||||
761 | |||||||
762 | /** |
||||||
763 | * Returns the list of application parameters. |
||||||
764 | * Since the parameters are returned as a {@see \Prado\Collections\TMap} object, you may use |
||||||
765 | 10 | * the returned result to access, add or remove individual parameters. |
|||||
766 | * @return \Prado\Collections\TMap the list of application parameters |
||||||
767 | 10 | */ |
|||||
768 | 10 | public function getParameters() |
|||||
769 | { |
||||||
770 | return $this->_parameters; |
||||||
771 | } |
||||||
772 | |||||||
773 | /** |
||||||
774 | * @return THttpRequest the request module |
||||||
775 | */ |
||||||
776 | public function getRequest() |
||||||
777 | { |
||||||
778 | if (!$this->_request) { |
||||||
779 | $this->_request = new \Prado\Web\THttpRequest(); |
||||||
780 | $this->_request->init(null); |
||||||
781 | } |
||||||
782 | return $this->_request; |
||||||
783 | } |
||||||
784 | |||||||
785 | /** |
||||||
786 | * @param THttpRequest $request the request module |
||||||
787 | */ |
||||||
788 | public function setRequest(THttpRequest $request) |
||||||
789 | { |
||||||
790 | $this->_request = $request; |
||||||
791 | } |
||||||
792 | |||||||
793 | 2 | /** |
|||||
794 | * @return THttpResponse the response module |
||||||
795 | 2 | */ |
|||||
796 | 1 | public function getResponse() |
|||||
797 | 1 | { |
|||||
798 | if (!$this->_response) { |
||||||
799 | 2 | $this->_response = new THttpResponse(); |
|||||
800 | $this->_response->init(null); |
||||||
801 | } |
||||||
802 | return $this->_response; |
||||||
803 | } |
||||||
804 | |||||||
805 | 9 | /** |
|||||
806 | * @param THttpResponse $response the request module |
||||||
807 | 9 | */ |
|||||
808 | 9 | public function setResponse(THttpResponse $response) |
|||||
809 | { |
||||||
810 | $this->_response = $response; |
||||||
811 | } |
||||||
812 | |||||||
813 | 1 | /** |
|||||
814 | * @return THttpSession the session module, null if session module is not installed |
||||||
815 | 1 | */ |
|||||
816 | public function getSession() |
||||||
817 | { |
||||||
818 | if (!$this->_session) { |
||||||
819 | 1 | $this->_session = new THttpSession(); |
|||||
820 | $this->_session->init(null); |
||||||
821 | } |
||||||
822 | return $this->_session; |
||||||
823 | } |
||||||
824 | |||||||
825 | 6 | /** |
|||||
826 | * @param THttpSession $session the session module |
||||||
827 | 6 | */ |
|||||
828 | 6 | public function setSession(THttpSession $session) |
|||||
829 | { |
||||||
830 | $this->_session = $session; |
||||||
831 | } |
||||||
832 | |||||||
833 | 3 | /** |
|||||
834 | * @return TErrorHandler the error handler module |
||||||
835 | 3 | */ |
|||||
836 | 2 | public function getErrorHandler() |
|||||
837 | 2 | { |
|||||
838 | if (!$this->_errorHandler) { |
||||||
839 | 3 | $this->_errorHandler = new TErrorHandler(); |
|||||
840 | $this->_errorHandler->init(null); |
||||||
841 | } |
||||||
842 | return $this->_errorHandler; |
||||||
843 | } |
||||||
844 | |||||||
845 | 2 | /** |
|||||
846 | * @param TErrorHandler $handler the error handler module |
||||||
847 | 2 | */ |
|||||
848 | 2 | public function setErrorHandler(TErrorHandler $handler) |
|||||
849 | { |
||||||
850 | $this->_errorHandler = $handler; |
||||||
851 | } |
||||||
852 | |||||||
853 | 20 | /** |
|||||
854 | * @return TSecurityManager the security manager module |
||||||
855 | 20 | */ |
|||||
856 | public function getSecurityManager() |
||||||
857 | { |
||||||
858 | if (!$this->_security) { |
||||||
859 | $this->_security = new TSecurityManager(); |
||||||
860 | $this->_security->init(null); |
||||||
861 | 17 | } |
|||||
862 | return $this->_security; |
||||||
863 | 17 | } |
|||||
864 | 17 | ||||||
865 | /** |
||||||
866 | * @param TSecurityManager $sm the security manager module |
||||||
867 | */ |
||||||
868 | public function setSecurityManager(TSecurityManager $sm) |
||||||
869 | { |
||||||
870 | $this->_security = $sm; |
||||||
871 | } |
||||||
872 | |||||||
873 | /** |
||||||
874 | * @return TAssetManager asset manager |
||||||
875 | */ |
||||||
876 | public function getAssetManager() |
||||||
877 | { |
||||||
878 | if (!$this->_assetManager) { |
||||||
879 | $this->_assetManager = new TAssetManager(); |
||||||
880 | $this->_assetManager->init(null); |
||||||
881 | } |
||||||
882 | return $this->_assetManager; |
||||||
883 | } |
||||||
884 | |||||||
885 | /** |
||||||
886 | * @param TAssetManager $value asset manager |
||||||
887 | */ |
||||||
888 | public function setAssetManager(TAssetManager $value) |
||||||
889 | { |
||||||
890 | $this->_assetManager = $value; |
||||||
891 | } |
||||||
892 | |||||||
893 | /** |
||||||
894 | * @return TTemplateManager template manager |
||||||
895 | */ |
||||||
896 | public function getTemplateManager() |
||||||
897 | { |
||||||
898 | if (!$this->_templateManager) { |
||||||
899 | $this->_templateManager = new TTemplateManager(); |
||||||
900 | $this->_templateManager->init(null); |
||||||
901 | } |
||||||
902 | return $this->_templateManager; |
||||||
903 | } |
||||||
904 | |||||||
905 | /** |
||||||
906 | * @param TTemplateManager $value template manager |
||||||
907 | */ |
||||||
908 | public function setTemplateManager(TTemplateManager $value) |
||||||
909 | { |
||||||
910 | $this->_templateManager = $value; |
||||||
911 | } |
||||||
912 | |||||||
913 | /** |
||||||
914 | * @return TThemeManager theme manager |
||||||
915 | */ |
||||||
916 | public function getThemeManager() |
||||||
917 | { |
||||||
918 | if (!$this->_themeManager) { |
||||||
919 | $this->_themeManager = new TThemeManager(); |
||||||
920 | $this->_themeManager->init(null); |
||||||
921 | } |
||||||
922 | return $this->_themeManager; |
||||||
923 | } |
||||||
924 | |||||||
925 | /** |
||||||
926 | * @param TThemeManager $value theme manager |
||||||
927 | */ |
||||||
928 | public function setThemeManager(TThemeManager $value) |
||||||
929 | { |
||||||
930 | $this->_themeManager = $value; |
||||||
931 | } |
||||||
932 | |||||||
933 | /** |
||||||
934 | * @return IStatePersister application state persister |
||||||
935 | */ |
||||||
936 | public function getApplicationStatePersister() |
||||||
937 | { |
||||||
938 | if (!$this->_statePersister) { |
||||||
939 | $this->_statePersister = new TApplicationStatePersister(); |
||||||
940 | $this->_statePersister->init(null); |
||||||
941 | } |
||||||
942 | return $this->_statePersister; |
||||||
943 | } |
||||||
944 | |||||||
945 | /** |
||||||
946 | * @param IStatePersister $persister application state persister |
||||||
947 | */ |
||||||
948 | public function setApplicationStatePersister(IStatePersister $persister) |
||||||
949 | { |
||||||
950 | $this->_statePersister = $persister; |
||||||
951 | } |
||||||
952 | |||||||
953 | /** |
||||||
954 | * @return null|\Prado\Caching\ICache the cache module, null if cache module is not installed |
||||||
955 | */ |
||||||
956 | public function getCache() |
||||||
957 | { |
||||||
958 | return $this->_cache; |
||||||
959 | } |
||||||
960 | |||||||
961 | /** |
||||||
962 | * @param \Prado\Caching\ICache $cache the cache module |
||||||
963 | */ |
||||||
964 | public function setCache(\Prado\Caching\ICache $cache) |
||||||
965 | { |
||||||
966 | $this->_cache = $cache; |
||||||
967 | } |
||||||
968 | |||||||
969 | /** |
||||||
970 | * @return \Prado\Security\IUser the application user |
||||||
971 | */ |
||||||
972 | public function getUser() |
||||||
973 | { |
||||||
974 | return $this->_user; |
||||||
975 | } |
||||||
976 | |||||||
977 | /** |
||||||
978 | * This sets the application user and raises the onSetUser event. |
||||||
979 | * @param \Prado\Security\IUser $user the application user |
||||||
980 | */ |
||||||
981 | public function setUser(\Prado\Security\IUser $user) |
||||||
982 | { |
||||||
983 | $this->_user = $user; |
||||||
984 | $this->onSetUser($user); |
||||||
985 | } |
||||||
986 | |||||||
987 | /** |
||||||
988 | * Raises onSetUser event. |
||||||
989 | * Allows modules/components to run handlers when the Application User is set. |
||||||
990 | * e.g. A user module could set the $_SERVER['HTTP_ACCEPT_LANGUAGE'] and |
||||||
991 | * $_SERVER['HTTP_ACCEPT_CHARSET'] in a cli environment to the user's last |
||||||
992 | * web Language and Charset so Emails (and other templates) get language |
||||||
993 | * customized. |
||||||
994 | * @param \Prado\Security\IUser $user |
||||||
995 | * @since 4.2.2 |
||||||
996 | */ |
||||||
997 | public function onSetUser(\Prado\Security\IUser $user) |
||||||
998 | { |
||||||
999 | $this->raiseEvent('onSetUser', $this, $user); |
||||||
0 ignored issues
–
show
$user of type Prado\Security\IUser is incompatible with the type Prado\TEventParameter expected by parameter $param of Prado\TComponent::raiseEvent() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
1000 | } |
||||||
1001 | |||||||
1002 | /** |
||||||
1003 | * @param bool $createIfNotExists whether to create globalization if it does not exist |
||||||
1004 | * @return null|TGlobalization globalization module |
||||||
1005 | */ |
||||||
1006 | public function getGlobalization($createIfNotExists = true) |
||||||
1007 | { |
||||||
1008 | if ($this->_globalization === null && $createIfNotExists) { |
||||||
1009 | $this->_globalization = new TGlobalization(); |
||||||
1010 | $this->_globalization->init(null); |
||||||
1011 | } |
||||||
1012 | return $this->_globalization; |
||||||
1013 | } |
||||||
1014 | |||||||
1015 | /** |
||||||
1016 | * @param \Prado\I18N\TGlobalization $glob globalization module |
||||||
1017 | */ |
||||||
1018 | public function setGlobalization(\Prado\I18N\TGlobalization $glob) |
||||||
1019 | { |
||||||
1020 | $this->_globalization = $glob; |
||||||
1021 | } |
||||||
1022 | |||||||
1023 | /** |
||||||
1024 | * @return \Prado\Security\TAuthorizationRuleCollection list of authorization rules for the current request |
||||||
1025 | */ |
||||||
1026 | public function getAuthorizationRules() |
||||||
1027 | { |
||||||
1028 | if ($this->_authRules === null) { |
||||||
1029 | $this->_authRules = new \Prado\Security\TAuthorizationRuleCollection(); |
||||||
1030 | } |
||||||
1031 | return $this->_authRules; |
||||||
1032 | } |
||||||
1033 | |||||||
1034 | protected function getApplicationConfigurationClass() |
||||||
1035 | { |
||||||
1036 | return TApplicationConfiguration::class; |
||||||
1037 | } |
||||||
1038 | |||||||
1039 | protected function internalLoadModule($id, $force = false) |
||||||
1040 | { |
||||||
1041 | [$moduleClass, $initProperties, $configElement] = $this->_lazyModules[$id]; |
||||||
1042 | if (isset($initProperties['lazy']) && $initProperties['lazy'] && !$force) { |
||||||
1043 | Prado::trace("Postponed loading of lazy module $id ({$moduleClass})", TApplication::class); |
||||||
1044 | $this->setModule($id, null); |
||||||
1045 | return null; |
||||||
1046 | } |
||||||
1047 | |||||||
1048 | Prado::trace("Loading module $id ({$moduleClass})", TApplication::class); |
||||||
1049 | $module = Prado::createComponent($moduleClass); |
||||||
1050 | foreach ($initProperties as $name => $value) { |
||||||
1051 | if ($name === 'lazy') { |
||||||
1052 | continue; |
||||||
1053 | } |
||||||
1054 | $module->setSubProperty($name, $value); |
||||||
1055 | } |
||||||
1056 | $this->setModule($id, $module); |
||||||
1057 | // keep the key to avoid reuse of the old module id |
||||||
1058 | $this->_lazyModules[$id] = null; |
||||||
1059 | $module->dyPreInit($configElement); |
||||||
0 ignored issues
–
show
The method
dyPreInit() does not exist on Prado\IModule . It seems like you code against a sub-type of said class. However, the method does not exist in Prado\Util\IDbModule or Prado\Util\IPluginModule . Are you sure you never get one of those?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
1060 | |||||||
1061 | return [$module, $configElement]; |
||||||
1062 | } |
||||||
1063 | /** |
||||||
1064 | * Applies an application configuration. |
||||||
1065 | * @param TApplicationConfiguration $config the configuration |
||||||
1066 | * @param bool $withinService whether the configuration is specified within a service. |
||||||
1067 | */ |
||||||
1068 | public function applyConfiguration($config, $withinService = false) |
||||||
1069 | { |
||||||
1070 | if ($config->getIsEmpty()) { |
||||||
1071 | return; |
||||||
1072 | } |
||||||
1073 | |||||||
1074 | // set path aliases and using namespaces |
||||||
1075 | foreach ($config->getAliases() as $alias => $path) { |
||||||
1076 | Prado::setPathOfAlias($alias, $path); |
||||||
1077 | } |
||||||
1078 | foreach ($config->getUsings() as $using) { |
||||||
1079 | Prado::using($using); |
||||||
1080 | } |
||||||
1081 | |||||||
1082 | // set application properties |
||||||
1083 | if (!$withinService) { |
||||||
1084 | foreach ($config->getProperties() as $name => $value) { |
||||||
1085 | $this->setSubProperty($name, $value); |
||||||
1086 | } |
||||||
1087 | } |
||||||
1088 | |||||||
1089 | if (empty($this->_services)) { |
||||||
1090 | $this->_services = [$this->getPageServiceID() => [\Prado\Web\Services\TPageService::class, [], null]]; |
||||||
1091 | } |
||||||
1092 | |||||||
1093 | // load parameters |
||||||
1094 | foreach ($config->getParameters() as $id => $parameter) { |
||||||
1095 | if (is_array($parameter)) { |
||||||
1096 | $component = Prado::createComponent($parameter[0]); |
||||||
1097 | foreach ($parameter[1] as $name => $value) { |
||||||
1098 | $component->setSubProperty($name, $value); |
||||||
1099 | } |
||||||
1100 | $component->dyInit($parameter[2]); |
||||||
1101 | $this->_parameters->add($id, $component); |
||||||
1102 | } else { |
||||||
1103 | $this->_parameters->add($id, $parameter); |
||||||
1104 | } |
||||||
1105 | } |
||||||
1106 | |||||||
1107 | // load and init modules specified in app config |
||||||
1108 | $modules = []; |
||||||
1109 | foreach ($config->getModules() as $id => $moduleConfig) { |
||||||
1110 | if (!is_string($id)) { |
||||||
1111 | $id = '_module' . count($this->_lazyModules); |
||||||
1112 | } |
||||||
1113 | $this->_lazyModules[$id] = $moduleConfig; |
||||||
1114 | if ($module = $this->internalLoadModule($id)) { |
||||||
1115 | $modules[] = $module; |
||||||
1116 | } |
||||||
1117 | } |
||||||
1118 | foreach ($modules as $module) { |
||||||
1119 | $module[0]->init($module[1]); |
||||||
1120 | } |
||||||
1121 | |||||||
1122 | // load service |
||||||
1123 | foreach ($config->getServices() as $serviceID => $serviceConfig) { |
||||||
1124 | $this->_services[$serviceID] = $serviceConfig; |
||||||
1125 | } |
||||||
1126 | |||||||
1127 | // external configurations |
||||||
1128 | foreach ($config->getExternalConfigurations() as $filePath => $condition) { |
||||||
1129 | if ($condition !== true) { |
||||||
1130 | $condition = $this->evaluateExpression($condition); |
||||||
1131 | } |
||||||
1132 | if ($condition) { |
||||||
1133 | if (($path = Prado::getPathOfNamespace($filePath, $this->getConfigurationFileExt())) === null || !is_file($path)) { |
||||||
1134 | throw new TConfigurationException('application_includefile_invalid', $filePath); |
||||||
1135 | } |
||||||
1136 | $cn = $this->getApplicationConfigurationClass(); |
||||||
1137 | $c = new $cn(); |
||||||
1138 | $c->loadFromFile($path); |
||||||
1139 | $this->applyConfiguration($c, $withinService); |
||||||
1140 | } |
||||||
1141 | } |
||||||
1142 | } |
||||||
1143 | |||||||
1144 | /** |
||||||
1145 | * Loads configuration and initializes application. |
||||||
1146 | * Configuration file will be read and parsed (if a valid cached version exists, |
||||||
1147 | * it will be used instead). Then, modules are created and initialized; |
||||||
1148 | * Afterwards, the requested service is created and initialized. |
||||||
1149 | * Lastly, the onInitComplete event is raised. |
||||||
1150 | * @throws TConfigurationException if module is redefined of invalid type, or service not defined or of invalid type |
||||||
1151 | */ |
||||||
1152 | protected function initApplication() |
||||||
1153 | { |
||||||
1154 | Prado::trace('Initializing application', TApplication::class); |
||||||
1155 | |||||||
1156 | if ($this->_configFile !== null) { |
||||||
1157 | if ($this->_cacheFile === null || @filemtime($this->_cacheFile) < filemtime($this->_configFile)) { |
||||||
1158 | $config = new TApplicationConfiguration(); |
||||||
1159 | $config->loadFromFile($this->_configFile); |
||||||
1160 | if ($this->_cacheFile !== null) { |
||||||
1161 | file_put_contents($this->_cacheFile, serialize($config), LOCK_EX); |
||||||
1162 | } |
||||||
1163 | } else { |
||||||
1164 | $config = unserialize(file_get_contents($this->_cacheFile)); |
||||||
1165 | } |
||||||
1166 | |||||||
1167 | $this->applyConfiguration($config, false); |
||||||
1168 | } |
||||||
1169 | |||||||
1170 | if (($serviceID = $this->getRequest()->resolveRequest(array_keys($this->_services))) === null) { |
||||||
0 ignored issues
–
show
|
|||||||
1171 | $serviceID = $this->getPageServiceID(); |
||||||
1172 | } |
||||||
1173 | |||||||
1174 | $this->startService($serviceID); |
||||||
1175 | |||||||
1176 | $this->onInitComplete(); |
||||||
1177 | } |
||||||
1178 | |||||||
1179 | /** |
||||||
1180 | * Starts the specified service. |
||||||
1181 | * The service instance will be created. Its properties will be initialized |
||||||
1182 | * and the configurations will be applied, if any. |
||||||
1183 | * @param string $serviceID service ID |
||||||
1184 | */ |
||||||
1185 | public function startService($serviceID) |
||||||
1186 | { |
||||||
1187 | if (isset($this->_services[$serviceID])) { |
||||||
1188 | [$serviceClass, $initProperties, $configElement] = $this->_services[$serviceID]; |
||||||
1189 | $service = Prado::createComponent($serviceClass); |
||||||
1190 | if (!($service instanceof TService)) { |
||||||
1191 | throw new THttpException(500, 'application_service_invalid', $serviceClass); |
||||||
1192 | } |
||||||
1193 | if (!$service->getEnabled()) { |
||||||
1194 | throw new THttpException(500, 'application_service_unavailable', $serviceClass); |
||||||
1195 | } |
||||||
1196 | $service->setID($serviceID); |
||||||
1197 | $this->setService($service); |
||||||
1198 | |||||||
1199 | foreach ($initProperties as $name => $value) { |
||||||
1200 | $service->setSubProperty($name, $value); |
||||||
1201 | } |
||||||
1202 | |||||||
1203 | if ($configElement !== null) { |
||||||
1204 | $config = new TApplicationConfiguration(); |
||||||
1205 | if ($this->getConfigurationType() == self::CONFIG_TYPE_PHP) { |
||||||
1206 | $config->loadFromPhp($configElement, $this->getBasePath()); |
||||||
1207 | } else { |
||||||
1208 | $config->loadFromXml($configElement, $this->getBasePath()); |
||||||
1209 | } |
||||||
1210 | $this->applyConfiguration($config, true); |
||||||
1211 | } |
||||||
1212 | |||||||
1213 | $service->init($configElement); |
||||||
1214 | } else { |
||||||
1215 | throw new THttpException(500, 'application_service_unknown', $serviceID); |
||||||
1216 | } |
||||||
1217 | } |
||||||
1218 | |||||||
1219 | /** |
||||||
1220 | * Raises OnError event. |
||||||
1221 | * This method is invoked when an exception is raised during the lifecycles |
||||||
1222 | * of the application. |
||||||
1223 | * @param mixed $param event parameter |
||||||
1224 | */ |
||||||
1225 | public function onError($param) |
||||||
1226 | { |
||||||
1227 | Prado::log($param->getMessage(), TLogger::ERROR, TApplication::class); |
||||||
1228 | $this->raiseEvent('OnError', $this, $param); |
||||||
1229 | $this->getErrorHandler()->handleError($this, $param); |
||||||
1230 | } |
||||||
1231 | |||||||
1232 | /** |
||||||
1233 | * Raises onInitComplete event. |
||||||
1234 | * At the time when this method is invoked, application modules are loaded, |
||||||
1235 | * user request is resolved and the corresponding service is loaded and |
||||||
1236 | * initialized. The application is about to start processing the user |
||||||
1237 | * request. This call is important for CLI/Shell applications that do not have |
||||||
1238 | * a web service lifecycle stack. This is the first and last event for finalization |
||||||
1239 | * of any loaded modules in CLI/Shell mode. |
||||||
1240 | * @since 4.2.0 |
||||||
1241 | */ |
||||||
1242 | public function onInitComplete() |
||||||
1243 | { |
||||||
1244 | $this->raiseEvent('onInitComplete', $this, null); |
||||||
1245 | } |
||||||
1246 | |||||||
1247 | /** |
||||||
1248 | * Raises OnBeginRequest event. |
||||||
1249 | * At the time when this method is invoked, application modules are loaded |
||||||
1250 | * and initialized, user request is resolved and the corresponding service |
||||||
1251 | * is loaded and initialized. The application is about to start processing |
||||||
1252 | * the user request. |
||||||
1253 | */ |
||||||
1254 | public function onBeginRequest() |
||||||
1255 | { |
||||||
1256 | $this->raiseEvent('OnBeginRequest', $this, null); |
||||||
1257 | } |
||||||
1258 | |||||||
1259 | /** |
||||||
1260 | * Raises OnAuthentication event. |
||||||
1261 | * This method is invoked when the user request needs to be authenticated. |
||||||
1262 | */ |
||||||
1263 | public function onAuthentication() |
||||||
1264 | { |
||||||
1265 | $this->raiseEvent('OnAuthentication', $this, null); |
||||||
1266 | } |
||||||
1267 | |||||||
1268 | /** |
||||||
1269 | * Raises OnAuthenticationComplete event. |
||||||
1270 | * This method is invoked right after the user request is authenticated. |
||||||
1271 | */ |
||||||
1272 | public function onAuthenticationComplete() |
||||||
1273 | { |
||||||
1274 | $this->raiseEvent('OnAuthenticationComplete', $this, null); |
||||||
1275 | } |
||||||
1276 | |||||||
1277 | /** |
||||||
1278 | * Raises OnAuthorization event. |
||||||
1279 | * This method is invoked when the user request needs to be authorized. |
||||||
1280 | */ |
||||||
1281 | public function onAuthorization() |
||||||
1282 | { |
||||||
1283 | $this->raiseEvent('OnAuthorization', $this, null); |
||||||
1284 | } |
||||||
1285 | |||||||
1286 | /** |
||||||
1287 | * Raises OnAuthorizationComplete event. |
||||||
1288 | * This method is invoked right after the user request is authorized. |
||||||
1289 | */ |
||||||
1290 | public function onAuthorizationComplete() |
||||||
1291 | { |
||||||
1292 | $this->raiseEvent('OnAuthorizationComplete', $this, null); |
||||||
1293 | } |
||||||
1294 | |||||||
1295 | /** |
||||||
1296 | * Raises OnLoadState event. |
||||||
1297 | * This method is invoked when the application needs to load state (probably stored in session). |
||||||
1298 | */ |
||||||
1299 | public function onLoadState() |
||||||
1300 | { |
||||||
1301 | $this->loadGlobals(); |
||||||
1302 | $this->raiseEvent('OnLoadState', $this, null); |
||||||
1303 | } |
||||||
1304 | |||||||
1305 | /** |
||||||
1306 | * Raises OnLoadStateComplete event. |
||||||
1307 | * This method is invoked right after the application state has been loaded. |
||||||
1308 | */ |
||||||
1309 | public function onLoadStateComplete() |
||||||
1310 | { |
||||||
1311 | $this->raiseEvent('OnLoadStateComplete', $this, null); |
||||||
1312 | } |
||||||
1313 | |||||||
1314 | /** |
||||||
1315 | * Raises OnPreRunService event. |
||||||
1316 | * This method is invoked right before the service is to be run. |
||||||
1317 | */ |
||||||
1318 | public function onPreRunService() |
||||||
1319 | { |
||||||
1320 | $this->raiseEvent('OnPreRunService', $this, null); |
||||||
1321 | } |
||||||
1322 | |||||||
1323 | /** |
||||||
1324 | * Runs the requested service. |
||||||
1325 | */ |
||||||
1326 | public function runService() |
||||||
1327 | { |
||||||
1328 | if ($this->_service) { |
||||||
1329 | $this->_service->run(); |
||||||
1330 | } |
||||||
1331 | } |
||||||
1332 | |||||||
1333 | /** |
||||||
1334 | * Raises OnSaveState event. |
||||||
1335 | * This method is invoked when the application needs to save state (probably stored in session). |
||||||
1336 | */ |
||||||
1337 | public function onSaveState() |
||||||
1338 | { |
||||||
1339 | $this->raiseEvent('OnSaveState', $this, null); |
||||||
1340 | $this->saveGlobals(); |
||||||
1341 | } |
||||||
1342 | |||||||
1343 | /** |
||||||
1344 | * Raises OnSaveStateComplete event. |
||||||
1345 | * This method is invoked right after the application state has been saved. |
||||||
1346 | */ |
||||||
1347 | public function onSaveStateComplete() |
||||||
1348 | { |
||||||
1349 | $this->raiseEvent('OnSaveStateComplete', $this, null); |
||||||
1350 | } |
||||||
1351 | |||||||
1352 | /** |
||||||
1353 | * Raises OnPreFlushOutput event. |
||||||
1354 | * This method is invoked right before the application flushes output to client. |
||||||
1355 | */ |
||||||
1356 | public function onPreFlushOutput() |
||||||
1357 | { |
||||||
1358 | $this->raiseEvent('OnPreFlushOutput', $this, null); |
||||||
1359 | } |
||||||
1360 | |||||||
1361 | /** |
||||||
1362 | * Flushes output to client side. |
||||||
1363 | * @param bool $continueBuffering whether to continue buffering after flush if buffering was active |
||||||
1364 | */ |
||||||
1365 | public function flushOutput($continueBuffering = true) |
||||||
1366 | { |
||||||
1367 | $this->getResponse()->flush($continueBuffering); |
||||||
1368 | } |
||||||
1369 | |||||||
1370 | /** |
||||||
1371 | * Raises OnEndRequest event. |
||||||
1372 | * This method is invoked when the application completes the processing of the request. |
||||||
1373 | */ |
||||||
1374 | public function onEndRequest() |
||||||
1375 | { |
||||||
1376 | $this->flushOutput(false); // flush all remaining content in the buffer |
||||||
1377 | $this->raiseEvent('OnEndRequest', $this, null); |
||||||
1378 | $this->saveGlobals(); // save global state |
||||||
1379 | } |
||||||
1380 | } |
||||||
1381 |
If you suppress an error, we recommend checking for the error condition explicitly: