Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * TPageService class file.
4
 *
5
 * @author Qiang Xue <qiang.xue@gmail.com>
6
 * @link http://www.pradosoft.com/
7
 * @copyright Copyright &copy; 2005-2008 PradoSoft
8
 * @license http://www.pradosoft.com/license/
9
 * @version $Id: TPageService.php 2597 2009-01-06 14:38:07Z christophe.boulain $
10
 * @package System.Web.Services
11
 */
12
 
13
/**
14
 * Include classes to be used by page service
15
 */
16
Prado::using('System.Web.UI.TPage');
17
Prado::using('System.Web.UI.TTemplateManager');
18
Prado::using('System.Web.UI.TThemeManager');
19
 
20
/**
21
 * TPageService class.
22
 *
23
 * TPageService implements the service for serving user page requests.
24
 *
25
 * Pages that are available to client users are stored under a directory specified by
26
 * {@link setBasePath BasePath}. The directory may contain subdirectories.
27
 * Pages serving for a similar goal are usually placed under the same directory.
28
 * A directory may contain a configuration file <b>config.xml</b> whose content
29
 * is similar to that of application configuration file.
30
 *
31
 * A page is requested via page path, which is a dot-connected directory names
32
 * appended by the page name. Assume '<BasePath>/Users/Admin' is the directory
33
 * containing the page 'Update'. Then the page can be requested via 'Users.Admin.Update'.
34
 * By default, the {@link setBasePath BasePath} of the page service is the "pages"
35
 * directory under the application base path. You may change this default
36
 * by setting {@link setBasePath BasePath} with a different path you prefer.
37
 *
38
 * Page name refers to the file name (without extension) of the page template.
39
 * In order to differentiate from the common control template files, the extension
40
 * name of the page template files must be '.page'. If there is a PHP file with
41
 * the same page name under the same directory as the template file, that file
42
 * will be considered as the page class file and the file name is the page class name.
43
 * If such a file is not found, the page class is assumed as {@link TPage}.
44
 *
45
 * Modules can be configured and loaded in page directory configurations.
46
 * Configuration of a module in a subdirectory will overwrite its parent
47
 * directory's configuration, if both configurations refer to the same module.
48
 *
49
 * By default, TPageService will automatically load two modules:
50
 * - {@link TTemplateManager} : manages page and control templates
51
 * - {@link TThemeManager} : manages themes used in a Prado application
52
 *
53
 * In page directory configurations, static authorization rules can also be specified,
54
 * which governs who and which roles can access particular pages.
55
 * Refer to {@link TAuthorizationRule} for more details about authorization rules.
56
 * Page authorization rules can be configured within an <authorization> tag in
57
 * each page directory configuration as follows,
58
 * <authorization>
59
 *   <deny pages="Update" users="?" />
60
 *   <allow pages="Admin" roles="administrator" />
61
 *   <deny pages="Admin" users="*" />
62
 * </authorization>
63
 * where the 'pages' attribute may be filled with a sequence of comma-separated
64
 * page IDs. If 'pages' attribute does not appear in a rule, the rule will be
65
 * applied to all pages in this directory and all subdirectories (recursively).
66
 * Application of authorization rules are in a bottom-up fashion, starting from
67
 * the directory containing the requested page up to all parent directories.
68
 * The first matching rule will be used. The last rule always allows all users
69
 * accessing to any resources.
70
 *
71
 * @author Qiang Xue <qiang.xue@gmail.com>
72
 * @version $Id: TPageService.php 2597 2009-01-06 14:38:07Z christophe.boulain $
73
 * @package System.Web.Services
74
 * @since 3.0
75
 */
76
class TPageService extends TService
77
{
78
	/**
79
	 * Configuration file name
80
	 */
81
	const CONFIG_FILE='config.xml';
82
	/**
83
	 * Default base path
84
	 */
85
	const DEFAULT_BASEPATH='pages';
86
	/**
87
	 * Prefix of ID used for storing parsed configuration in cache
88
	 */
89
	const CONFIG_CACHE_PREFIX='prado:pageservice:';
90
	/**
91
	 * Page template file extension
92
	 */
93
	const PAGE_FILE_EXT='.page';
94
	/**
95
	 * @var string root path of pages
96
	 */
97
	private $_basePath=null;
98
	/**
99
	 * @var string base path class in namespace format
100
	 */
101
	private $_basePageClass='TPage';
102
	/**
103
	 * @var string default page
104
	 */
105
	private $_defaultPage='Home';
106
	/**
107
	 * @var string requested page (path)
108
	 */
109
	private $_pagePath=null;
110
	/**
111
	 * @var TPage the requested page
112
	 */
113
	private $_page=null;
114
	/**
115
	 * @var array list of initial page property values
116
	 */
117
	private $_properties=array();
118
	/**
119
	 * @var boolean whether service is initialized
120
	 */
121
	private $_initialized=false;
122
	/**
123
	 * @var TThemeManager theme manager
124
	 */
125
	private $_themeManager=null;
126
	/**
127
	 * @var TTemplateManager template manager
128
	 */
129
	private $_templateManager=null;
130
 
131
	/**
132
	 * Initializes the service.
133
	 * This method is required by IService interface and is invoked by application.
134
	 * @param TXmlElement service configuration
135
	 */
136
	public function init($config)
137
	{
138
		Prado::trace("Initializing TPageService",'System.Web.Services.TPageService');
139
 
140
		$pageConfig=$this->loadPageConfig($config);
141
 
142
		$this->initPageContext($pageConfig);
143
 
144
		$this->_initialized=true;
145
	}
146
 
147
	/**
148
	 * Initializes page context.
149
	 * Page context includes path alias settings, namespace usages,
150
	 * parameter initialization, module loadings, page initial properties
151
	 * and authorization rules.
152
	 * @param TPageConfiguration
153
	 */
154
	protected function initPageContext($pageConfig)
155
	{
156
		$application=$this->getApplication();
157
		foreach($pageConfig->getApplicationConfigurations() as $appConfig)
158
			$application->applyConfiguration($appConfig);
159
 
160
		$this->applyConfiguration($pageConfig);
161
	}
162
 
163
	/**
164
	 * Applies a page configuration.
165
	 * @param TPageConfiguration the configuration
166
	 */
167
	protected function applyConfiguration($config)
168
	{
169
		// initial page properties (to be set when page runs)
170
		$this->_properties=array_merge($this->_properties, $config->getProperties());
171
		$this->getApplication()->getAuthorizationRules()->mergeWith($config->getRules());
172
		$pagePath=$this->getRequestedPagePath();
173
		// external configurations
174
		foreach($config->getExternalConfigurations() as $filePath=>$params)
175
		{
176
			list($configPagePath,$condition)=$params;
177
			if($condition!==true)
178
				$condition=$this->evaluateExpression($condition);
179
			if($condition)
180
			{
181
				if(($path=Prado::getPathOfNamespace($filePath,TApplication::CONFIG_FILE_EXT))===null || !is_file($path))
182
					throw new TConfigurationException('pageservice_includefile_invalid',$filePath);
183
				$c=new TPageConfiguration($pagePath);
184
				$c->loadFromFile($path,$configPagePath);
185
				$this->applyConfiguration($c);
186
			}
187
		}
188
 
189
	}
190
 
191
	/**
192
	 * Determines the requested page path.
193
	 * @return string page path requested
194
	 */
195
	protected function determineRequestedPagePath()
196
	{
197
		$pagePath=$this->getRequest()->getServiceParameter();
198
		if(empty($pagePath))
199
			$pagePath=$this->getDefaultPage();
200
		return $pagePath;
201
	}
202
 
203
	/**
204
	 * Collects configuration for a page.
205
	 * @param TXmlElement additional configuration specified in the application configuration
206
	 * @return TPageConfiguration
207
	 */
208
	protected function loadPageConfig($config)
209
	{
210
		$application=$this->getApplication();
211
		$pagePath=$this->getRequestedPagePath();
212
		if(($cache=$application->getCache())===null)
213
		{
214
			$pageConfig=new TPageConfiguration($pagePath);
215
			if($config!==null)
216
				$pageConfig->loadPageConfigurationFromXml($config,$application->getBasePath(),'');
217
			$pageConfig->loadFromFiles($this->getBasePath());
218
		}
219
		else
220
		{
221
			$configCached=true;
222
			$currentTimestamp=array();
223
			$arr=$cache->get(self::CONFIG_CACHE_PREFIX.$this->getID().$pagePath);
224
			if(is_array($arr))
225
			{
226
				list($pageConfig,$timestamps)=$arr;
227
				if($application->getMode()!==TApplicationMode::Performance)
228
				{
229
					foreach($timestamps as $fileName=>$timestamp)
230
					{
231
						if($fileName===0) // application config file
232
						{
233
							$appConfigFile=$application->getConfigurationFile();
234
							$currentTimestamp[0]=$appConfigFile===null?0:@filemtime($appConfigFile);
235
							if($currentTimestamp[0]>$timestamp || ($timestamp>0 && !$currentTimestamp[0]))
236
								$configCached=false;
237
						}
238
						else
239
						{
240
							$currentTimestamp[$fileName]=@filemtime($fileName);
241
							if($currentTimestamp[$fileName]>$timestamp || ($timestamp>0 && !$currentTimestamp[$fileName]))
242
								$configCached=false;
243
						}
244
					}
245
				}
246
			}
247
			else
248
			{
249
				$configCached=false;
250
				$paths=explode('.',$pagePath);
251
				$configPath=$this->getBasePath();
252
				foreach($paths as $path)
253
				{
254
					$configFile=$configPath.DIRECTORY_SEPARATOR.self::CONFIG_FILE;
255
					$currentTimestamp[$configFile]=@filemtime($configFile);
256
					$configPath.=DIRECTORY_SEPARATOR.$path;
257
				}
258
				$appConfigFile=$application->getConfigurationFile();
259
				$currentTimestamp[0]=$appConfigFile===null?0:@filemtime($appConfigFile);
260
			}
261
			if(!$configCached)
262
			{
263
				$pageConfig=new TPageConfiguration($pagePath);
264
				if($config!==null)
265
					$pageConfig->loadPageConfigurationFromXml($config,$application->getBasePath(),'');
266
				$pageConfig->loadFromFiles($this->getBasePath());
267
				$cache->set(self::CONFIG_CACHE_PREFIX.$this->getID().$pagePath,array($pageConfig,$currentTimestamp));
268
			}
269
		}
270
		return $pageConfig;
271
	}
272
 
273
	/**
274
	 * @return TTemplateManager template manager
275
	 */
276
	public function getTemplateManager()
277
	{
278
		if(!$this->_templateManager)
279
		{
280
			$this->_templateManager=new TTemplateManager;
281
			$this->_templateManager->init(null);
282
		}
283
		return $this->_templateManager;
284
	}
285
 
286
	/**
287
	 * @param TTemplateManager template manager
288
	 */
289
	public function setTemplateManager(TTemplateManager $value)
290
	{
291
		$this->_templateManager=$value;
292
	}
293
 
294
	/**
295
	 * @return TThemeManager theme manager
296
	 */
297
	public function getThemeManager()
298
	{
299
		if(!$this->_themeManager)
300
		{
301
			$this->_themeManager=new TThemeManager;
302
			$this->_themeManager->init(null);
303
		}
304
		return $this->_themeManager;
305
	}
306
 
307
	/**
308
	 * @param TThemeManager theme manager
309
	 */
310
	public function setThemeManager(TThemeManager $value)
311
	{
312
		$this->_themeManager=$value;
313
	}
314
 
315
	/**
316
	 * @return string the requested page path
317
	 */
318
	public function getRequestedPagePath()
319
	{
320
		if($this->_pagePath===null)
321
		{
322
			$this->_pagePath=strtr($this->determineRequestedPagePath(),'/\\','..');
323
			if(empty($this->_pagePath))
324
				throw new THttpException(404,'pageservice_page_required');
325
		}
326
		return $this->_pagePath;
327
	}
328
 
329
	/**
330
	 * @return TPage the requested page
331
	 */
332
	public function getRequestedPage()
333
	{
334
		return $this->_page;
335
	}
336
 
337
	/**
338
	 * @return string default page path to be served if no explicit page is request. Defaults to 'Home'.
339
	 */
340
	public function getDefaultPage()
341
	{
342
		return $this->_defaultPage;
343
	}
344
 
345
	/**
346
	 * @param string default page path to be served if no explicit page is request
347
	 * @throws TInvalidOperationException if the page service is initialized
348
	 */
349
	public function setDefaultPage($value)
350
	{
351
		if($this->_initialized)
352
			throw new TInvalidOperationException('pageservice_defaultpage_unchangeable');
353
		else
354
			$this->_defaultPage=$value;
355
	}
356
 
357
	/**
358
	 * @return string the URL for the default page
359
	 */
360
	public function getDefaultPageUrl()
361
	{
362
		return $this->constructUrl($this->getDefaultPage());
363
	}
364
 
365
	/**
366
	 * @return string the root directory for storing pages. Defaults to the 'pages' directory under the application base path.
367
	 */
368
	public function getBasePath()
369
	{
370
		if($this->_basePath===null)
371
		{
372
			$basePath=$this->getApplication()->getBasePath().DIRECTORY_SEPARATOR.self::DEFAULT_BASEPATH;
373
			if(($this->_basePath=realpath($basePath))===false || !is_dir($this->_basePath))
374
				throw new TConfigurationException('pageservice_basepath_invalid',$basePath);
375
		}
376
		return $this->_basePath;
377
	}
378
 
379
	/**
380
	 * @param string root directory (in namespace form) storing pages
381
	 * @throws TInvalidOperationException if the service is initialized already or basepath is invalid
382
	 */
383
	public function setBasePath($value)
384
	{
385
		if($this->_initialized)
386
			throw new TInvalidOperationException('pageservice_basepath_unchangeable');
387
		else if(($path=Prado::getPathOfNamespace($value))===null || !is_dir($path))
388
			throw new TConfigurationException('pageservice_basepath_invalid',$value);
389
		$this->_basePath=realpath($path);
390
	}
391
 
392
	/**
393
	 * Sets the base page class name (in namespace format).
394
	 * If a page only has a template file without page class file,
395
	 * this base page class will be instantiated.
396
	 * @param string class name
397
	 */
398
	public function setBasePageClass($value)
399
	{
400
		$this->_basePageClass=$value;
401
	}
402
 
403
	/**
404
	 * @return string base page class name in namespace format. Defaults to 'TPage'.
405
	 */
406
	public function getBasePageClass()
407
	{
408
		return $this->_basePageClass;
409
	}
410
 
411
	/**
412
	 * Runs the service.
413
	 * This will create the requested page, initializes it with the property values
414
	 * specified in the configuration, and executes the page.
415
	 */
416
	public function run()
417
	{
418
		Prado::trace("Running page service",'System.Web.Services.TPageService');
419
		$this->_page=$this->createPage($this->getRequestedPagePath());
420
		$this->runPage($this->_page,$this->_properties);
421
	}
422
 
423
	/**
424
	 * Creates a page instance based on requested page path.
425
	 * @param string requested page path
426
	 * @return TPage the requested page instance
427
	 * @throws THttpException if requested page path is invalid
428
	 * @throws TConfigurationException if the page class cannot be found
429
	 */
430
	protected function createPage($pagePath)
431
	{
432
		$path=$this->getBasePath().DIRECTORY_SEPARATOR.strtr($pagePath,'.',DIRECTORY_SEPARATOR);
433
		$hasTemplateFile=is_file($path.self::PAGE_FILE_EXT);
434
		$hasClassFile=is_file($path.Prado::CLASS_FILE_EXT);
435
 
436
		if(!$hasTemplateFile && !$hasClassFile)
437
			throw new THttpException(404,'pageservice_page_unknown',$pagePath);
438
 
439
		if($hasClassFile)
440
		{
441
			$className=basename($path);
442
			if(!class_exists($className,false))
443
				include_once($path.Prado::CLASS_FILE_EXT);
444
		}
445
		else
446
		{
447
			$className=$this->getBasePageClass();
448
			Prado::using($className);
449
			if(($pos=strrpos($className,'.'))!==false)
450
				$className=substr($className,$pos+1);
451
		}
452
 
453
 		if(!class_exists($className,false) || ($className!=='TPage' && !is_subclass_of($className,'TPage')))
454
			throw new THttpException(404,'pageservice_page_unknown',$pagePath);
455
 
456
		$page=new $className;
457
		$page->setPagePath($pagePath);
458
 
459
		if($hasTemplateFile)
460
			$page->setTemplate($this->getTemplateManager()->getTemplateByFileName($path.self::PAGE_FILE_EXT));
461
 
462
		return $page;
463
	}
464
 
465
	/**
466
	 * Executes a page.
467
	 * @param TPage the page instance to be run
468
	 * @param array list of initial page properties
469
	 */
470
	protected function runPage($page,$properties)
471
	{
472
		foreach($properties as $name=>$value)
473
			$page->setSubProperty($name,$value);
474
		$page->run($this->getResponse()->createHtmlWriter());
475
	}
476
 
477
	/**
478
	 * Constructs a URL with specified page path and GET parameters.
479
	 * @param string page path
480
	 * @param array list of GET parameters, null if no GET parameters required
481
	 * @param boolean whether to encode the ampersand in URL, defaults to true.
482
	 * @param boolean whether to encode the GET parameters (their names and values), defaults to true.
483
	 * @return string URL for the page and GET parameters
484
	 */
485
	public function constructUrl($pagePath,$getParams=null,$encodeAmpersand=true,$encodeGetItems=true)
486
	{
487
		return $this->getRequest()->constructUrl($this->getID(),$pagePath,$getParams,$encodeAmpersand,$encodeGetItems);
488
	}
489
}
490
 
491
 
492
/**
493
 * TPageConfiguration class
494
 *
495
 * TPageConfiguration represents the configuration for a page.
496
 * The page is specified by a dot-connected path.
497
 * Configurations along this path are merged together to be provided for the page.
498
 *
499
 * @author Qiang Xue <qiang.xue@gmail.com>
500
 * @version $Id: TPageService.php 2597 2009-01-06 14:38:07Z christophe.boulain $
501
 * @package System.Web.Services
502
 * @since 3.0
503
 */
504
class TPageConfiguration extends TComponent
505
{
506
	/**
507
	 * @var array list of application configurations
508
	 */
509
	private $_appConfigs=array();
510
	/**
511
	 * @var array list of page initial property values
512
	 */
513
	private $_properties=array();
514
	/**
515
	 * @var TAuthorizationRuleCollection list of authorization rules
516
	 */
517
	private $_rules=array();
518
	/**
519
	 * @var array list of included configurations
520
	 */
521
	private $_includes=array();
522
	/**
523
	 * @var string the currently request page in the format of Path.To.PageName
524
	 */
525
	private $_pagePath='';
526
 
527
	/**
528
	 * Constructor.
529
	 * @param string the currently request page in the format of Path.To.PageName
530
	 */
531
	public function __construct($pagePath)
532
	{
533
		$this->_pagePath=$pagePath;
534
	}
535
 
536
	/**
537
	 * @return array list of external configuration files. Each element is like $filePath=>$condition
538
	 */
539
	public function getExternalConfigurations()
540
	{
541
		return $this->_includes;
542
	}
543
 
544
	/**
545
	 * Returns list of page initial property values.
546
	 * Each array element represents a single property with the key
547
	 * being the property name and the value the initial property value.
548
	 * @return array list of page initial property values
549
	 */
550
	public function getProperties()
551
	{
552
		return $this->_properties;
553
	}
554
 
555
	/**
556
	 * Returns list of authorization rules.
557
	 * The authorization rules are aggregated (bottom-up) from configuration files
558
	 * along the path to the specified page.
559
	 * @return TAuthorizationRuleCollection collection of authorization rules
560
	 */
561
	public function getRules()
562
	{
563
		return $this->_rules;
564
	}
565
 
566
	/**
567
	 * @return array list of application configurations specified along page path
568
	 */
569
	public function getApplicationConfigurations()
570
	{
571
		return $this->_appConfigs;
572
	}
573
 
574
	/**
575
	 * Loads configuration for a page specified in a path format.
576
	 * @param string root path for pages
577
	 */
578
	public function loadFromFiles($basePath)
579
	{
580
		$paths=explode('.',$this->_pagePath);
581
		$page=array_pop($paths);
582
		$path=$basePath;
583
		$configPagePath='';
584
		foreach($paths as $p)
585
		{
586
			$this->loadFromFile($path.DIRECTORY_SEPARATOR.TPageService::CONFIG_FILE,$configPagePath);
587
			$path.=DIRECTORY_SEPARATOR.$p;
588
			if($configPagePath==='')
589
				$configPagePath=$p;
590
			else
591
				$configPagePath.='.'.$p;
592
		}
593
		$this->loadFromFile($path.DIRECTORY_SEPARATOR.TPageService::CONFIG_FILE,$configPagePath);
594
		$this->_rules=new TAuthorizationRuleCollection($this->_rules);
595
	}
596
 
597
	/**
598
	 * Loads a specific config file.
599
	 * @param string config file name
600
	 * @param string the page path that the config file is associated with. The page path doesn't include the page name.
601
	 */
602
	public function loadFromFile($fname,$configPagePath)
603
	{
604
		Prado::trace("Loading page configuration file $fname",'System.Web.Services.TPageService');
605
		if(empty($fname) || !is_file($fname))
606
			return;
607
		$dom=new TXmlDocument;
608
		if($dom->loadFromFile($fname))
609
			$this->loadFromXml($dom,dirname($fname),$configPagePath);
610
		else
611
			throw new TConfigurationException('pageserviceconf_file_invalid',$fname);
612
	}
613
 
614
	/**
615
	 * Loads a page configuration.
616
	 * The configuration includes information for both application
617
	 * and page service.
618
	 * @param TXmlElement config xml element
619
	 * @param string the directory containing this configuration
620
	 * @param string the page path that the config XML is associated with. The page path doesn't include the page name.
621
	 */
622
	public function loadFromXml($dom,$configPath,$configPagePath)
623
	{
624
		$this->loadApplicationConfigurationFromXml($dom,$configPath);
625
		$this->loadPageConfigurationFromXml($dom,$configPath,$configPagePath);
626
	}
627
 
628
	/**
629
	 * Loads the configuration specific for application part
630
	 * @param TXmlElement config xml element
631
	 * @param string base path corresponding to this xml element
632
	 */
633
	public function loadApplicationConfigurationFromXml($dom,$configPath)
634
	{
635
		$appConfig=new TApplicationConfiguration;
636
		$appConfig->loadFromXml($dom,$configPath);
637
		$this->_appConfigs[]=$appConfig;
638
	}
639
 
640
	/**
641
	 * Loads the configuration specific for page service.
642
	 * @param TXmlElement config xml element
643
	 * @param string base path corresponding to this xml element
644
	 * @param string the page path that the config XML is associated with. The page path doesn't include the page name.
645
	 */
646
	public function loadPageConfigurationFromXml($dom,$configPath,$configPagePath)
647
	{
648
		// authorization
649
		if(($authorizationNode=$dom->getElementByTagName('authorization'))!==null)
650
		{
651
			$rules=array();
652
			foreach($authorizationNode->getElements() as $node)
653
			{
654
				$patterns=$node->getAttribute('pages');
655
				$ruleApplies=false;
656
				if(empty($patterns) || trim($patterns)==='*') // null or empty string
657
					$ruleApplies=true;
658
				else
659
				{
660
					foreach(explode(',',$patterns) as $pattern)
661
					{
662
						if(($pattern=trim($pattern))!=='')
663
						{
664
							// we know $configPagePath and $this->_pagePath
665
							if($configPagePath!=='')  // prepend the pattern with ConfigPagePath
666
								$pattern=$configPagePath.'.'.$pattern;
667
							if(strcasecmp($pattern,$this->_pagePath)===0)
668
							{
669
								$ruleApplies=true;
670
								break;
671
							}
672
							if($pattern[strlen($pattern)-1]==='*') // try wildcard matching
673
							{
674
								if(strncasecmp($this->_pagePath,$pattern,strlen($pattern)-1)===0)
675
								{
676
									$ruleApplies=true;
677
									break;
678
								}
679
							}
680
						}
681
					}
682
				}
683
				if($ruleApplies)
684
					$rules[]=new TAuthorizationRule($node->getTagName(),$node->getAttribute('users'),$node->getAttribute('roles'),$node->getAttribute('verb'),$node->getAttribute('ips'));
685
			}
686
			$this->_rules=array_merge($rules,$this->_rules);
687
		}
688
 
689
		// pages
690
		if(($pagesNode=$dom->getElementByTagName('pages'))!==null)
691
		{
692
			$this->_properties=array_merge($this->_properties,$pagesNode->getAttributes()->toArray());
693
			// at the page folder
694
			foreach($pagesNode->getElementsByTagName('page') as $node)
695
			{
696
				$properties=$node->getAttributes();
697
				$id=$properties->remove('id');
698
				if(empty($id))
699
					throw new TConfigurationException('pageserviceconf_page_invalid',$configPath);
700
				$matching=false;
701
				$id=($configPagePath==='')?$id:$configPagePath.'.'.$id;
702
				if(strcasecmp($id,$this->_pagePath)===0)
703
					$matching=true;
704
				else if($id[strlen($id)-1]==='*') // try wildcard matching
705
					$matching=strncasecmp($this->_pagePath,$id,strlen($id)-1)===0;
706
				if($matching)
707
					$this->_properties=array_merge($this->_properties,$properties->toArray());
708
			}
709
		}
710
 
711
		// external configurations
712
		foreach($dom->getElementsByTagName('include') as $node)
713
		{
714
			if(($when=$node->getAttribute('when'))===null)
715
				$when=true;
716
			if(($filePath=$node->getAttribute('file'))===null)
717
				throw new TConfigurationException('pageserviceconf_includefile_required');
718
			if(isset($this->_includes[$filePath]))
719
				$this->_includes[$filePath]=array($configPagePath,'('.$this->_includes[$filePath][1].') || ('.$when.')');
720
			else
721
				$this->_includes[$filePath]=array($configPagePath,$when);
722
		}
723
	}
724
}
725