| 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 © 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 |
|