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