pradosoft /
prado
| 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. Loading history...
|
|||||||
| 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
Loading history...
|
|||||||
| 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
Loading history...
|
|||||||
| 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: