diff options
| -rw-r--r-- | HISTORY | 1 | ||||
| -rw-r--r-- | framework/Exceptions/messages.txt | 5 | ||||
| -rw-r--r-- | framework/TApplication.php | 292 | ||||
| -rw-r--r-- | framework/TService.php | 20 | ||||
| -rw-r--r-- | framework/Web/Services/TPageService.php | 217 | ||||
| -rw-r--r-- | framework/Web/THttpRequest.php | 33 | ||||
| -rw-r--r-- | framework/interfaces.php | 8 | 
7 files changed, 265 insertions, 311 deletions
@@ -10,6 +10,7 @@ ENH: Added PRADO_CHMOD constant so that users can specify the permission of PRAD  ENH: Added Display property to TWebControl (Wei)  ENH: Added TUser.getState() and setState() for storing user session data (Qiang)  ENH: Added renderer feature to TRepeater, TDataList and TDataGrid (Qiang) +ENH: Added support to include external application configuration files (Qiang)  NEW: TShellApplication (Qiang)  NEW: Active Record driver for IBM DB2 (Cesar Ramos) diff --git a/framework/Exceptions/messages.txt b/framework/Exceptions/messages.txt index 1b9ab749..b35ba7bf 100644 --- a/framework/Exceptions/messages.txt +++ b/framework/Exceptions/messages.txt @@ -24,11 +24,13 @@ map_item_unremovable					= The item cannot be removed from the map.  map_data_not_iterable					= Data must be either an array or an object implementing Traversable interface.
  map_readonly							= {0} is read-only.
 +application_includefile_invalid			= Unable to find application configuration {0}. Make sure it is in namespace format and the file ends with ".xml".
  application_basepath_invalid			= Application base path '{0}' does not exist or is not a directory.
  application_runtimepath_invalid			= Application runtime path '{0}' does not exist or is not writable by Web server process.
  application_service_invalid				= Service '{0}' must implement IService interface.
  application_service_unknown				= Requested service '{0}' is not defined.
 -application_service_unavailable			= Service Unavailable.
 +application_unavailable					= Application is unavailable at this time.
 +application_service_unavailable			= Service '{0}' is unavailable at this time.
  application_moduleid_duplicated			= Application module ID '{0}' is not unique.
  application_runtimepath_failed			= Unable to create runtime path '{0}'. Make sure the parent directory exists and is writable by the Web process.
 @@ -41,6 +43,7 @@ appconfig_moduletype_required			= Application configuration <module id="{0}"> mu  appconfig_serviceid_required			= Application configuration <service> element must have an "id" attribute.
  appconfig_servicetype_required			= Application configuration <service id="{0}"> must have a "class" attribute.
  appconfig_parameterid_required			= Application configuration <parameter> element must have an "id" attribute.
 +appconfig_includefile_required			= Application configuration <include> element must have a "file" attribute.
  securitymanager_validationkey_invalid	= TSecurityManager.ValidationKey must not be empty.
  securitymanager_encryptionkey_invalid	= TSecurityManager.EncryptionKey must not be empty.
 diff --git a/framework/TApplication.php b/framework/TApplication.php index b12dc64a..411b5241 100644 --- a/framework/TApplication.php +++ b/framework/TApplication.php @@ -130,6 +130,10 @@ class TApplication extends TComponent  	 */  	const CONFIG_FILE='application.xml';  	/** +	 * File extension for external config files +	 */ +	const CONFIG_FILE_EXT='.xml'; +	/**  	 * Runtime directory name  	 */  	const RUNTIME_PATH='runtime'; @@ -178,6 +182,10 @@ class TApplication extends TComponent  	 */  	private $_step;  	/** +	 * @var array available services and their configurations indexed by service IDs +	 */ +	private $_services; +	/**  	 * @var IService current service instance  	 */  	private $_service; @@ -188,7 +196,7 @@ class TApplication extends TComponent  	/**  	 * @var array list of application modules  	 */ -	private $_modules; +	private $_modules=array();  	/**  	 * @var TMap list of application parameters  	 */ @@ -296,6 +304,9 @@ class TApplication extends TComponent  		// generates unique ID by hashing the runtime path  		$this->_uniqueID=md5($this->_runtimePath); +		$this->_parameters=new TMap; +		$this->_services=array(self::PAGE_SERVICE_ID=>array('TPageService',array(),null)); +		Prado::setPathOfAlias('Application',$this->_basePath);  	}  	/** @@ -329,7 +340,7 @@ class TApplication extends TComponent  		{  			if($configFile!==null)  			{ -				$runtimePath.=DIRECTORY_SEPARATOR.basename($configFile); +				$runtimePath.=DIRECTORY_SEPARATOR.basename($configFile).'-'.Prado::getVersion();  				if(!is_dir($runtimePath))  				{  					if(@mkdir($runtimePath)===false) @@ -362,7 +373,7 @@ class TApplication extends TComponent  			while($this->_step<$n)  			{  				if($this->_mode===self::STATE_OFF) -					throw new THttpException(503,'application_service_unavailable'); +					throw new THttpException(503,'application_unavailable');  				if($this->_requestCompleted)  					break;  				$method=self::$_steps[$this->_step]; @@ -560,6 +571,14 @@ class TApplication extends TComponent  	}  	/** +	 * @param IService the currently requested service +	 */ +	public function setService($value) +	{ +		$this->_service=$value; +	} + +	/**  	 * Adds a module to application.  	 * Note, this method does not do module initialization.  	 * @param string ID of the module @@ -601,29 +620,6 @@ class TApplication extends TComponent  	}  	/** -	 * @return TPageService page service -	 */ -	public function getPageService() -	{ -		if(!$this->_pageService) -		{ -			$this->_pageService=new TPageService; -			$this->_pageService->init(null); -		} -		return $this->_pageService; -	} - -	/** -	 * Registers the page service instance. -	 * This method should only be used by framework developers. -	 * @param TPageService page service -	 */ -	public function setPageService(TPageService $service) -	{ -		$this->_pageService=$service; -	} - -	/**  	 * @return THttpRequest the request module  	 */  	public function getRequest() @@ -831,49 +827,10 @@ class TApplication extends TComponent  		return $this->_authRules;  	} -	/** -	 * Loads configuration and initializes application. -	 * Configuration file will be read and parsed (if a valid cached version exists, -	 * it will be used instead). Then, modules are created and initialized; -	 * Afterwards, the requested service is created and initialized. -	 * @param string configuration file path (absolute or relative to current executing script) -	 * @param string cache file path, empty if no present or needed -	 * @throws TConfigurationException if module is redefined of invalid type, or service not defined or of invalid type -	 */ -	protected function initApplication() +	public function applyConfiguration($config,$withinService=false)  	{ -		Prado::trace('Initializing application','System.TApplication'); - -		Prado::setPathOfAlias('Application',$this->_basePath); - -		if($this->_configFile===null) -		{ -			$request=$this->getRequest(); -			$request->setAvailableServices(array(self::PAGE_SERVICE_ID)); -			$request->resolveRequest(); -			$this->_service=$this->getPageService(); +		if($config->getIsEmpty())  			return; -		} - -		if($this->_cacheFile===null || @filemtime($this->_cacheFile)<filemtime($this->_configFile)) -		{ -			$config=new TApplicationConfiguration; -			$config->loadFromFile($this->_configFile); -			if($this->_cacheFile!==null) -			{ -				if(($fp=fopen($this->_cacheFile,'wb'))!==false) -				{ -					fputs($fp,Prado::serialize($config)); -					fclose($fp); -				} -				else -					syslog(LOG_WARNING, 'Prado application config cache file "'.$this->_cacheFile.'" cannot be created.'); -			} -		} -		else -		{ -			$config=Prado::unserialize(file_get_contents($this->_cacheFile)); -		}  		// set path aliases and using namespaces  		foreach($config->getAliases() as $alias=>$path) @@ -882,11 +839,13 @@ class TApplication extends TComponent  			Prado::using($using);  		// set application properties -		foreach($config->getProperties() as $name=>$value) -			$this->setSubProperty($name,$value); +		if(!$withinService) +		{ +			foreach($config->getProperties() as $name=>$value) +				$this->setSubProperty($name,$value); +		}  		// load parameters -		$this->_parameters=new TMap;  		foreach($config->getParameters() as $id=>$parameter)  		{  			if(is_array($parameter)) @@ -901,46 +860,108 @@ class TApplication extends TComponent  		}  		// load and init modules specified in app config -		$this->_modules=array();  		$modules=array();  		foreach($config->getModules() as $id=>$moduleConfig)  		{  			Prado::trace("Loading module $id ({$moduleConfig[0]})",'System.TApplication'); - -			$module=Prado::createComponent($moduleConfig[0]); +			list($moduleClass, $initProperties, $configElement)=$moduleConfig; +			$module=Prado::createComponent($moduleClass);  			if(is_string($id))  				$this->setModule($id,$module); -			foreach($moduleConfig[1] as $name=>$value) +			foreach($initProperties as $name=>$value)  				$module->setSubProperty($name,$value); -			$modules[]=array($module,$moduleConfig[2]); +			$modules[]=array($module,$configElement);  		}  		foreach($modules as $module)  			$module[0]->init($module[1]);  		// load service -		$services=$config->getServices(); -		$serviceIDs=array_keys($services); -		array_unshift($serviceIDs,self::PAGE_SERVICE_ID); -		$request=$this->getRequest(); -		$request->setAvailableServices($serviceIDs); +		foreach($config->getServices() as $serviceID=>$serviceConfig) +			$this->_services[$serviceID]=$serviceConfig; + +		// external configurations +		foreach($config->getExternalConfigurations() as $filePath=>$condition) +		{ +			if($condition!==true) +				$condition=$this->evaluateExpression($condition); +			if($condition) +			{ +				if(($path=Prado::getPathOfNamespace($filePath,self::CONFIG_FILE_EXT))===null || !is_file($path)) +					throw new TConfigurationException('application_includefile_invalid',$filePath); +				$c=new TApplicationConfiguration; +				$c->loadFromFile($path); +				$this->applyConfiguration($c,$withinService); +			} +		} +	} -		$request->resolveRequest(); +	/** +	 * Loads configuration and initializes application. +	 * Configuration file will be read and parsed (if a valid cached version exists, +	 * it will be used instead). Then, modules are created and initialized; +	 * Afterwards, the requested service is created and initialized. +	 * @param string configuration file path (absolute or relative to current executing script) +	 * @param string cache file path, empty if no present or needed +	 * @throws TConfigurationException if module is redefined of invalid type, or service not defined or of invalid type +	 */ +	protected function initApplication() +	{ +		Prado::trace('Initializing application','System.TApplication'); + +		if($this->_configFile!==null) +		{ +			if($this->_cacheFile===null || @filemtime($this->_cacheFile)<filemtime($this->_configFile)) +			{ +				$config=new TApplicationConfiguration; +				$config->loadFromFile($this->_configFile); +				if($this->_cacheFile!==null) +					file_put_contents($this->_cacheFile,Prado::serialize($config),LOCK_EX); +			} +			else +				$config=Prado::unserialize(file_get_contents($this->_cacheFile)); + +			$this->applyConfiguration($config,false); +		} -		if(($serviceID=$request->getServiceID())===null) +		if(($serviceID=$this->getRequest()->resolveRequest(array_keys($this->_services)))===null)  			$serviceID=self::PAGE_SERVICE_ID; -		if(isset($services[$serviceID])) + +		$this->startService($serviceID); +	} + +	/** +	 * Starts the specified service. +	 * The service instance will be created. Its properties will be initialized +	 * and the configurations will be applied, if any. +	 * @param string service ID +	 */ +	public function startService($serviceID) +	{ +		if(isset($this->_services[$serviceID]))  		{ -			$serviceConfig=$services[$serviceID]; -			$service=Prado::createComponent($serviceConfig[0]); +			list($serviceClass,$initProperties,$configElement)=$this->_services[$serviceID]; +			$service=Prado::createComponent($serviceClass);  			if(!($service instanceof IService)) -				throw new THttpException(500,'application_service_unknown',$serviceID); -			$this->_service=$service; -			foreach($serviceConfig[1] as $name=>$value) +				throw new THttpException(500,'application_service_invalid',$serviceClass); +			if(!$service->getEnabled()) +				throw new THttpException(500,'application_service_unavailable',$serviceClass); +			$service->setID($serviceID); +			$this->setService($service); + +			foreach($initProperties as $name=>$value)  				$service->setSubProperty($name,$value); -			$service->init($serviceConfig[2]); + +			if($configElement!==null) +			{ +				$config=new TApplicationConfiguration; +				$config->loadFromXml($configElement,$this->getBasePath()); +				$this->applyConfiguration($config,true); +			} + +			$service->init($configElement);  		}  		else -			$this->_service=$this->getPageService(); +			throw new THttpException(500,'application_service_unknown',$serviceID);  	}  	/** @@ -1147,6 +1168,14 @@ class TApplicationConfiguration extends TComponent  	 * @var array list of parameters  	 */  	private $_parameters=array(); +	/** +	 * @var array list of included configurations +	 */ +	private $_includes=array(); +	/** +	 * @var boolean whether this configuration contains actual stuff +	 */ +	private $_empty=true;  	/**  	 * Parses the application configuration file. @@ -1155,13 +1184,32 @@ class TApplicationConfiguration extends TComponent  	 */  	public function loadFromFile($fname)  	{ -		$configPath=dirname($fname);  		$dom=new TXmlDocument;  		$dom->loadFromFile($fname); +		$this->loadFromXml($dom,dirname($fname)); +	} + +	/** +	 * @return boolean whether this configuration contains actual stuff +	 */ +	public function getIsEmpty() +	{ +		return $this->_empty; +	} +	/** +	 * Parses the application configuration given in terms of a TXmlElement. +	 * @param TXmlElement the XML element +	 * @param string the context path (for specifying relative paths) +	 */ +	public function loadFromXml($dom,$configPath) +	{  		// application properties  		foreach($dom->getAttributes() as $name=>$value) +		{  			$this->_properties[$name]=$value; +			$this->_empty=false; +		}  		// paths  		if(($pathsNode=$dom->getElementByTagName('paths'))!==null) @@ -1183,6 +1231,7 @@ class TApplicationConfiguration extends TComponent  				}  				else  					throw new TConfigurationException('appconfig_alias_invalid'); +				$this->_empty=false;  			}  			foreach($pathsNode->getElementsByTagName('using') as $usingNode)  			{ @@ -1190,6 +1239,7 @@ class TApplicationConfiguration extends TComponent  					$this->_usings[]=$namespace;  				else  					throw new TConfigurationException('appconfig_using_invalid'); +				$this->_empty=false;  			}  		} @@ -1208,6 +1258,7 @@ class TApplicationConfiguration extends TComponent  					$this->_modules[]=array($type,$properties->toArray(),$node);  				else  					$this->_modules[$id]=array($type,$properties->toArray(),$node); +				$this->_empty=false;  			}  		} @@ -1223,6 +1274,7 @@ class TApplicationConfiguration extends TComponent  					throw new TConfigurationException('appconfig_servicetype_required',$id);  				$node->setParent(null);  				$this->_services[$id]=array($type,$properties->toArray(),$node); +				$this->_empty=false;  			}  		} @@ -1243,12 +1295,26 @@ class TApplicationConfiguration extends TComponent  				}  				else  					$this->_parameters[$id]=array($type,$properties->toArray()); +				$this->_empty=false;  			}  		} + +		// external configurations +		foreach($dom->getElementsByTagName('include') as $node) +		{ +			if(($when=$node->getAttribute('when'))===null) +				$when=true; +			if(($filePath=$node->getAttribute('file'))===null) +				throw new TConfigurationException('appconfig_includefile_required'); +			$this->_includes[$filePath]=$when; +		}  	}  	/** -	 * @return array list of application initial property values, indexed by property names +	 * Returns list of page initial property values. +	 * Each array element represents a single property with the key +	 * being the property name and the value the initial property value. +	 * @return array list of page initial property values  	 */  	public function getProperties()  	{ @@ -1256,7 +1322,11 @@ class TApplicationConfiguration extends TComponent  	}  	/** -	 * @return array list of path aliases, indexed by alias names +	 * Returns list of path alias definitions. +	 * The definitions are aggregated (top-down) from configuration files along the path +	 * to the specified page. Each array element represents a single alias definition, +	 * with the key being the alias name and the value the absolute path. +	 * @return array list of path alias definitions  	 */  	public function getAliases()  	{ @@ -1264,6 +1334,10 @@ class TApplicationConfiguration extends TComponent  	}  	/** +	 * Returns list of namespaces to be used. +	 * The namespaces are aggregated (top-down) from configuration files along the path +	 * to the specified page. Each array element represents a single namespace usage, +	 * with the value being the namespace to be used.  	 * @return array list of namespaces to be used  	 */  	public function getUsings() @@ -1272,7 +1346,18 @@ class TApplicationConfiguration extends TComponent  	}  	/** -	 * @return array list of module configurations +	 * Returns list of module configurations. +	 * The module configurations are aggregated (top-down) from configuration files +	 * along the path to the specified page. Each array element represents +	 * a single module configuration, with the key being the module ID and +	 * the value the module configuration. Each module configuration is +	 * stored in terms of an array with the following content +	 * ([0]=>module type, [1]=>module properties, [2]=>complete module configuration) +	 * The module properties are an array of property values indexed by property names. +	 * The complete module configuration is a TXmlElement object representing +	 * the raw module configuration which may contain contents enclosed within +	 * module tags. +	 * @return array list of module configurations to be used  	 */  	public function getModules()  	{ @@ -1288,12 +1373,29 @@ class TApplicationConfiguration extends TComponent  	}  	/** -	 * @return array list of parameters +	 * Returns list of parameter definitions. +	 * The parameter definitions are aggregated (top-down) from configuration files +	 * along the path to the specified page. Each array element represents +	 * a single parameter definition, with the key being the parameter ID and +	 * the value the parameter definition. A parameter definition can be either +	 * a string representing a string-typed parameter, or an array. +	 * The latter defines a component-typed parameter whose format is as follows, +	 * ([0]=>component type, [1]=>component properties) +	 * The component properties are an array of property values indexed by property names. +	 * @return array list of parameter definitions to be used  	 */  	public function getParameters()  	{  		return $this->_parameters;  	} + +	/** +	 * @return array list of external configuration files. Each element is like $filePath=>$condition +	 */ +	public function getExternalConfigurations() +	{ +		return $this->_includes; +	}  }  /** diff --git a/framework/TService.php b/framework/TService.php index 5df31534..ec91c43a 100644 --- a/framework/TService.php +++ b/framework/TService.php @@ -27,6 +27,10 @@ abstract class TService extends TApplicationComponent implements IService  	 * @var string service id
  	 */
  	private $_id;
 +	/**
 +	 * @var boolean whether the service is enabled
 +	 */
 +	private $_enabled=true;
  	/**
  	 * Initializes the service and attaches {@link run} to the RunService event of application.
 @@ -54,6 +58,22 @@ abstract class TService extends TApplicationComponent implements IService  	}
  	/**
 +	 * @return boolean whether the service is enabled
 +	 */
 +	public function getEnabled()
 +	{
 +		return $this->_enabled;
 +	}
 +
 +	/**
 +	 * @param boolean whether the service is enabled
 +	 */
 +	public function setEnabled($value)
 +	{
 +		$this->_enabled=TPropertyValue::ensureBoolean($value);
 +	}
 +
 +	/**
  	 * Runs the service.
  	 */
  	public function run()
 diff --git a/framework/Web/Services/TPageService.php b/framework/Web/Services/TPageService.php index 8d1eb3f4..a0c4b8fb 100644 --- a/framework/Web/Services/TPageService.php +++ b/framework/Web/Services/TPageService.php @@ -129,15 +129,6 @@ class TPageService extends TService  	private $_templateManager=null;
  	/**
 -	 * Constructor.
 -	 * Sets default service ID to 'page'.
 -	 */
 -	public function __construct()
 -	{
 -		$this->setID('page');
 -	}
 -
 -	/**
  	 * Initializes the service.
  	 * This method is required by IService interface and is invoked by application.
  	 * @param TXmlElement service configuration
 @@ -146,8 +137,6 @@ class TPageService extends TService  	{
  		Prado::trace("Initializing TPageService",'System.Web.Services.TPageService');
 -		$this->getApplication()->setPageService($this);
 -
  		$pageConfig=$this->loadPageConfig($this->getRequestedPagePath(),$config);
  		$this->initPageContext($pageConfig);
 @@ -166,45 +155,12 @@ class TPageService extends TService  	{
  		$application=$this->getApplication();
 -		// set path aliases and using namespaces
 -		foreach($pageConfig->getAliases() as $alias=>$path)
 -			Prado::setPathOfAlias($alias,$path);
 -		foreach($pageConfig->getUsings() as $using)
 -			Prado::using($using);
 +		foreach($pageConfig->getApplicationConfigurations() as $appConfig)
 +			$application->applyConfiguration($appConfig);
  		// initial page properties (to be set when page runs)
  		$this->_properties=$pageConfig->getProperties();
 -		// load parameters
 -		$parameters=$application->getParameters();
 -		foreach($pageConfig->getParameters() as $id=>$parameter)
 -		{
 -			if(is_array($parameter))
 -			{
 -				$component=Prado::createComponent($parameter[0]);
 -				foreach($parameter[1] as $name=>$value)
 -					$component->setSubProperty($name,$value);
 -				$parameters->add($id,$component);
 -			}
 -			else
 -				$parameters->add($id,$parameter);
 -		}
 -
 -		// load modules specified in page directory config
 -		$modules=array();
 -		foreach($pageConfig->getModules() as $id=>$moduleConfig)
 -		{
 -			Prado::trace("Loading module $id ({$moduleConfig[0]})",'System.Web.Services.TPageService');
 -			$module=Prado::createComponent($moduleConfig[0]);
 -			if(is_string($id))
 -				$application->setModule($id,$module);
 -			foreach($moduleConfig[1] as $name=>$value)
 -				$module->setSubProperty($name,$value);
 -			$modules[]=array($module,$moduleConfig[2]);
 -		}
 -		foreach($modules as $module)
 -			$module[0]->init($module[1]);
 -
  		$application->getAuthorizationRules()->mergeWith($pageConfig->getRules());
  	}
 @@ -233,8 +189,8 @@ class TPageService extends TService  		{
  			$pageConfig=new TPageConfiguration;
  			if($config!==null)
 -				$pageConfig->loadXmlElement($config,$application->getBasePath(),null);
 -			$pageConfig->loadConfigurationFiles($pagePath,$this->getBasePath());
 +				$pageConfig->loadFromXml($config,$application->getBasePath());
 +			$pageConfig->loadFromFiles($pagePath,$this->getBasePath());
  		}
  		else
  		{
 @@ -282,8 +238,8 @@ class TPageService extends TService  			{
  				$pageConfig=new TPageConfiguration;
  				if($config!==null)
 -					$pageConfig->loadXmlElement($config,$application->getBasePath(),null);
 -				$pageConfig->loadConfigurationFiles($pagePath,$this->getBasePath());
 +					$pageConfig->loadFromXml($config,$application->getBasePath());
 +				$pageConfig->loadFromFiles($pagePath,$this->getBasePath());
  				$cache->set(self::CONFIG_CACHE_PREFIX.$this->getID().$pagePath,array($pageConfig,$currentTimestamp));
  			}
  		}
 @@ -510,25 +466,13 @@ class TPageService extends TService  class TPageConfiguration extends TComponent
  {
  	/**
 -	 * @var array list of page initial property values
 +	 * @var array list of application configurations
  	 */
 -	private $_properties=array();
 +	private $_appConfigs=array();
  	/**
 -	 * @var array list of namespaces to be used
 -	 */
 -	private $_usings=array();
 -	/**
 -	 * @var array list of path aliases
 -	 */
 -	private $_aliases=array();
 -	/**
 -	 * @var array list of module configurations
 -	 */
 -	private $_modules=array();
 -	/**
 -	 * @var array list of parameters
 +	 * @var array list of page initial property values
  	 */
 -	private $_parameters=array();
 +	private $_properties=array();
  	/**
  	 * @var TAuthorizationRuleCollection list of authorization rules
  	 */
 @@ -546,66 +490,6 @@ class TPageConfiguration extends TComponent  	}
  	/**
 -	 * Returns list of path alias definitions.
 -	 * The definitions are aggregated (top-down) from configuration files along the path
 -	 * to the specified page. Each array element represents a single alias definition,
 -	 * with the key being the alias name and the value the absolute path.
 -	 * @return array list of path alias definitions
 -	 */
 -	public function getAliases()
 -	{
 -		return $this->_aliases;
 -	}
 -
 -	/**
 -	 * Returns list of namespaces to be used.
 -	 * The namespaces are aggregated (top-down) from configuration files along the path
 -	 * to the specified page. Each array element represents a single namespace usage,
 -	 * with the value being the namespace to be used.
 -	 * @return array list of namespaces to be used
 -	 */
 -	public function getUsings()
 -	{
 -		return $this->_usings;
 -	}
 -
 -	/**
 -	 * Returns list of module configurations.
 -	 * The module configurations are aggregated (top-down) from configuration files
 -	 * along the path to the specified page. Each array element represents
 -	 * a single module configuration, with the key being the module ID and
 -	 * the value the module configuration. Each module configuration is
 -	 * stored in terms of an array with the following content
 -	 * ([0]=>module type, [1]=>module properties, [2]=>complete module configuration)
 -	 * The module properties are an array of property values indexed by property names.
 -	 * The complete module configuration is a TXmlElement object representing
 -	 * the raw module configuration which may contain contents enclosed within
 -	 * module tags.
 -	 * @return array list of module configurations to be used
 -	 */
 -	public function getModules()
 -	{
 -		return $this->_modules;
 -	}
 -
 -	/**
 -	 * Returns list of parameter definitions.
 -	 * The parameter definitions are aggregated (top-down) from configuration files
 -	 * along the path to the specified page. Each array element represents
 -	 * a single parameter definition, with the key being the parameter ID and
 -	 * the value the parameter definition. A parameter definition can be either
 -	 * a string representing a string-typed parameter, or an array.
 -	 * The latter defines a component-typed parameter whose format is as follows,
 -	 * ([0]=>component type, [1]=>component properties)
 -	 * The component properties are an array of property values indexed by property names.
 -	 * @return array list of parameter definitions to be used
 -	 */
 -	public function getParameters()
 -	{
 -		return $this->_parameters;
 -	}
 -
 -	/**
  	 * Returns list of authorization rules.
  	 * The authorization rules are aggregated (bottom-up) from configuration files
  	 * along the path to the specified page.
 @@ -617,11 +501,19 @@ class TPageConfiguration extends TComponent  	}
  	/**
 +	 * @return array list of application configurations specified along page path
 +	 */
 +	public function getApplicationConfigurations()
 +	{
 +		return $this->_appConfigs;
 +	}
 +
 +	/**
  	 * Loads configuration for a page specified in a path format.
  	 * @param string path to the page (dot-connected format)
  	 * @param string root path for pages
  	 */
 -	public function loadConfigurationFiles($pagePath,$basePath)
 +	public function loadFromFiles($pagePath,$basePath)
  	{
  		$paths=explode('.',$pagePath);
  		$page=array_pop($paths);
 @@ -647,7 +539,7 @@ class TPageConfiguration extends TComponent  			return;
  		$dom=new TXmlDocument;
  		if($dom->loadFromFile($fname))
 -			$this->loadXmlElement($dom,dirname($fname),$page);
 +			$this->loadFromXml($dom,dirname($fname),$page);
  		else
  			throw new TConfigurationException('pageserviceconf_file_invalid',$fname);
  	}
 @@ -658,73 +550,14 @@ class TPageConfiguration extends TComponent  	 * @param string base path corresponding to this xml element
  	 * @param string page name, null if page is not required
  	 */
 -	public function loadXmlElement($dom,$configPath,$page)
 +	public function loadFromXml($dom,$configPath,$page=null)
  	{
 -		// paths
 -		if(($pathsNode=$dom->getElementByTagName('paths'))!==null)
 -		{
 -			foreach($pathsNode->getElementsByTagName('alias') as $aliasNode)
 -			{
 -				if(($id=$aliasNode->getAttribute('id'))!==null && ($p=$aliasNode->getAttribute('path'))!==null)
 -				{
 -					$p=str_replace('\\','/',$p);
 -					$path=realpath(preg_match('/^\\/|.:\\//',$p)?$p:$configPath.'/'.$p);
 -					if($path===false || !is_dir($path))
 -						throw new TConfigurationException('pageserviceconf_aliaspath_invalid',$id,$p,$configPath);
 -					if(isset($this->_aliases[$id]))
 -						throw new TConfigurationException('pageserviceconf_alias_redefined',$id,$configPath);
 -					$this->_aliases[$id]=$path;
 -				}
 -				else
 -					throw new TConfigurationException('pageserviceconf_alias_invalid',$configPath);
 -			}
 -			foreach($pathsNode->getElementsByTagName('using') as $usingNode)
 -			{
 -				if(($namespace=$usingNode->getAttribute('namespace'))!==null)
 -					$this->_usings[]=$namespace;
 -				else
 -					throw new TConfigurationException('pageserviceconf_using_invalid',$configPath);
 -			}
 -		}
 -
 -		// modules
 -		if(($modulesNode=$dom->getElementByTagName('modules'))!==null)
 +		if($page!==null) // config.xml
  		{
 -			foreach($modulesNode->getElementsByTagName('module') as $node)
 -			{
 -				$properties=$node->getAttributes();
 -				$type=$properties->remove('class');
 -				$id=$properties->itemAt('id');
 -				if($type===null)
 -					throw new TConfigurationException('pageserviceconf_moduletype_required',$id,$configPath);
 -				$node->setParent(null);
 -				if($id===null)
 -					$this->_modules[]=array($type,$properties->toArray(),$node);
 -				else
 -					$this->_modules[$id]=array($type,$properties->toArray(),$node);
 -			}
 +			$appConfig=new TApplicationConfiguration;
 +			$appConfig->loadFromXml($dom,$configPath);
 +			$this->_appConfigs[]=$appConfig;
  		}
 -
 -		// parameters
 -		if(($parametersNode=$dom->getElementByTagName('parameters'))!==null)
 -		{
 -			foreach($parametersNode->getElementsByTagName('parameter') as $node)
 -			{
 -				$properties=$node->getAttributes();
 -				if(($id=$properties->remove('id'))===null)
 -					throw new TConfigurationException('pageserviceconf_parameter_invalid',$configPath);
 -				if(($type=$properties->remove('class'))===null)
 -				{
 -					if(($value=$properties->remove('value'))===null)
 -						$this->_parameters[$id]=$node;
 -					else
 -						$this->_parameters[$id]=$value;
 -				}
 -				else
 -					$this->_parameters[$id]=array($type,$properties->toArray());
 -			}
 -		}
 -
  		// authorization
  		if(($authorizationNode=$dom->getElementByTagName('authorization'))!==null)
  		{
 diff --git a/framework/Web/THttpRequest.php b/framework/Web/THttpRequest.php index 47fe1230..9c3ce98d 100644 --- a/framework/Web/THttpRequest.php +++ b/framework/Web/THttpRequest.php @@ -568,22 +568,25 @@ class THttpRequest extends TApplicationComponent implements IteratorAggregate,Ar  	 * A URL in the format of /index.php?sp=serviceID.serviceParameter
  	 * will be resolved with the serviceID and the serviceParameter.
  	 * You may override this method to provide your own way of service resolution.
 +	 * @param array list of valid service IDs
 +	 * @return string the currently requested service ID, null if no service ID is found
  	 * @see constructUrl
  	 */
 -	public function resolveRequest()
 +	public function resolveRequest($serviceIDs)
  	{
  		Prado::trace("Resolving request from ".$_SERVER['REMOTE_ADDR'],'System.Web.THttpRequest');
 -		$this->_requestResolved=true;
  		$this->_items=array_merge($_GET,$this->parseUrl(),$_POST);
 -		foreach($this->_services as $id)
 +		$this->_requestResolved=true;
 +		foreach($serviceIDs as $serviceID)
  		{
 -			if($this->contains($id))
 +			if($this->contains($serviceID))
  			{
 -				$this->setServiceID($id);
 -				$this->setServiceParameter($this->itemAt($id));
 -				break;
 +				$this->setServiceID($serviceID);
 +				$this->setServiceParameter($this->itemAt($serviceID));
 +				return $serviceID;
  			}
  		}
 +		return null;
  	}
  	/**
 @@ -595,22 +598,6 @@ class THttpRequest extends TApplicationComponent implements IteratorAggregate,Ar  	}
  	/**
 -	 * @return array IDs of the available services
 -	 */
 -	public function getAvailableServices()
 -	{
 -		return $this->_services;
 -	}
 -
 -	/**
 -	 * @param array IDs of the available services
 -	 */
 -	public function setAvailableServices($services)
 -	{
 -		$this->_services=$services;
 -	}
 -
 -	/**
  	 * @return string requested service ID
  	 */
  	public function getServiceID()
 diff --git a/framework/interfaces.php b/framework/interfaces.php index 31bbefd7..747d5b02 100644 --- a/framework/interfaces.php +++ b/framework/interfaces.php @@ -63,6 +63,14 @@ interface IService  	 */
  	public function setID($id);
  	/**
 +	 * @return boolean whether the service is enabled
 +	 */
 +	public function getEnabled();
 +	/**
 +	 * @param boolean whether the service is enabled
 +	 */
 +	public function setEnabled($value);
 +	/**
  	 * Runs the service.
  	 */
  	public function run();
  | 
