1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* File Name: pradolite.php |
4
|
|
|
* Last Update: 2017/01/23 17:32:51 |
5
|
|
|
* Generated By: buildscripts/phpbuilder/build.php |
6
|
|
|
* |
7
|
|
|
* This file is used in lieu of prado.php to boost PRADO application performance. |
8
|
|
|
* It is generated by expanding prado.php with included files. |
9
|
|
|
* Comments and trace statements are stripped off. |
10
|
|
|
* |
11
|
|
|
* Do not modify this file manually. |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
if(!defined('PRADO_DIR')) |
15
|
|
|
define('PRADO_DIR',dirname(__FILE__)); |
16
|
|
|
if(!defined('PRADO_CHMOD')) |
17
|
|
|
define('PRADO_CHMOD',0777); |
18
|
|
|
class PradoBase |
19
|
|
|
{ |
20
|
|
|
const CLASS_FILE_EXT='.php'; |
21
|
|
|
private static $_aliases=array('System'=>PRADO_DIR); |
22
|
|
|
private static $_usings=array(); |
23
|
|
|
private static $_application=null; |
24
|
|
|
private static $_logger=null; |
25
|
|
|
protected static $classExists = array(); |
26
|
|
|
public static function getVersion() |
27
|
|
|
{ |
28
|
|
|
return '3.3.2'; |
29
|
|
|
} |
30
|
|
|
public static function initErrorHandlers() |
31
|
|
|
{ |
32
|
|
|
set_error_handler(array('PradoBase','phpErrorHandler')); |
33
|
|
|
register_shutdown_function(array('PradoBase','phpFatalErrorHandler')); |
34
|
|
|
set_exception_handler(array('PradoBase','exceptionHandler')); |
35
|
|
|
ini_set('display_errors', 0); |
36
|
|
|
} |
37
|
|
|
public static function autoload($className) |
38
|
|
|
{ |
39
|
|
|
@include_once($className.self::CLASS_FILE_EXT); |
40
|
|
|
} |
41
|
|
|
public static function poweredByPrado($logoType=0) |
42
|
|
|
{ |
43
|
|
|
$logoName=$logoType==1?'powered2':'powered'; |
44
|
|
|
if(self::$_application!==null) |
45
|
|
|
{ |
46
|
|
|
$am=self::$_application->getAssetManager(); |
47
|
|
|
$url=$am->publishFilePath(self::getPathOfNamespace('System.'.$logoName,'.gif')); |
48
|
|
|
} |
49
|
|
|
else |
50
|
|
|
$url='http://pradosoft.github.io/docs/'.$logoName.'.gif'; |
51
|
|
|
return '<a title="Powered by PRADO" href="https://github.com/pradosoft/prado" target="_blank"><img src="'.$url.'" style="border-width:0px;" alt="Powered by PRADO" /></a>'; |
52
|
|
|
} |
53
|
|
|
public static function phpErrorHandler($errno,$errstr,$errfile,$errline) |
54
|
|
|
{ |
55
|
|
|
if(error_reporting() & $errno) |
56
|
|
|
throw new TPhpErrorException($errno,$errstr,$errfile,$errline); |
57
|
|
|
} |
58
|
|
|
public static function phpFatalErrorHandler() |
59
|
|
|
{ |
60
|
|
|
$error = error_get_last(); |
61
|
|
|
if($error && |
|
|
|
|
62
|
|
|
TPhpErrorException::isFatalError($error) && |
63
|
|
|
error_reporting() & $error['type']) |
64
|
|
|
{ |
65
|
|
|
self::exceptionHandler(new TPhpErrorException($error['type'],$error['message'],$error['file'],$error['line'])); |
66
|
|
|
} |
67
|
|
|
} |
68
|
|
|
public static function exceptionHandler($exception) |
69
|
|
|
{ |
70
|
|
|
if(self::$_application!==null && ($errorHandler=self::$_application->getErrorHandler())!==null) |
71
|
|
|
{ |
72
|
|
|
$errorHandler->handleError(null,$exception); |
73
|
|
|
} |
74
|
|
|
else |
75
|
|
|
{ |
76
|
|
|
echo $exception; |
77
|
|
|
} |
78
|
|
|
exit(1); |
|
|
|
|
79
|
|
|
} |
80
|
|
|
public static function setApplication($application) |
81
|
|
|
{ |
82
|
|
|
if(self::$_application!==null && !defined('PRADO_TEST_RUN')) |
83
|
|
|
throw new TInvalidOperationException('prado_application_singleton_required'); |
84
|
|
|
self::$_application=$application; |
85
|
|
|
} |
86
|
|
|
public static function getApplication() |
87
|
|
|
{ |
88
|
|
|
return self::$_application; |
89
|
|
|
} |
90
|
|
|
public static function getFrameworkPath() |
91
|
|
|
{ |
92
|
|
|
return PRADO_DIR; |
93
|
|
|
} |
94
|
|
|
public static function createComponent($type) |
95
|
|
|
{ |
96
|
|
|
if(!isset(self::$classExists[$type])) |
97
|
|
|
self::$classExists[$type] = class_exists($type, false); |
98
|
|
|
if( !isset(self::$_usings[$type]) && !self::$classExists[$type]) { |
99
|
|
|
self::using($type); |
100
|
|
|
self::$classExists[$type] = class_exists($type, false); |
101
|
|
|
} |
102
|
|
|
if( ($pos = strrpos($type, '.')) !== false) |
103
|
|
|
$type = substr($type,$pos+1); |
104
|
|
|
if(($n=func_num_args())>1) |
105
|
|
|
{ |
106
|
|
|
$args = func_get_args(); |
107
|
|
|
switch($n) { |
108
|
|
|
case 2: |
109
|
|
|
return new $type($args[1]); |
110
|
|
|
break; |
|
|
|
|
111
|
|
|
case 3: |
112
|
|
|
return new $type($args[1], $args[2]); |
113
|
|
|
break; |
|
|
|
|
114
|
|
|
case 4: |
115
|
|
|
return new $type($args[1], $args[2], $args[3]); |
116
|
|
|
break; |
|
|
|
|
117
|
|
|
case 5: |
118
|
|
|
return new $type($args[1], $args[2], $args[3], $args[4]); |
119
|
|
|
break; |
|
|
|
|
120
|
|
|
default: |
121
|
|
|
$s='$args[1]'; |
122
|
|
|
for($i=2;$i<$n;++$i) |
123
|
|
|
$s.=",\$args[$i]"; |
124
|
|
|
eval("\$component=new $type($s);"); |
|
|
|
|
125
|
|
|
return $component; |
|
|
|
|
126
|
|
|
break; |
|
|
|
|
127
|
|
|
} |
128
|
|
|
} |
129
|
|
|
else |
130
|
|
|
return new $type; |
131
|
|
|
} |
132
|
|
|
public static function using($namespace,$checkClassExistence=true) |
133
|
|
|
{ |
134
|
|
|
if(isset(self::$_usings[$namespace]) || class_exists($namespace,false)) |
135
|
|
|
return; |
136
|
|
|
if(($pos=strrpos($namespace,'.'))===false) { |
137
|
|
|
try |
138
|
|
|
{ |
139
|
|
|
include_once($namespace.self::CLASS_FILE_EXT); |
140
|
|
|
} |
141
|
|
|
catch(Exception $e) |
142
|
|
|
{ |
143
|
|
|
if($checkClassExistence && !class_exists($namespace,false)) |
144
|
|
|
throw new TInvalidOperationException('prado_component_unknown',$namespace,$e->getMessage()); |
145
|
|
|
else |
146
|
|
|
throw $e; |
147
|
|
|
} |
148
|
|
|
} |
149
|
|
|
else if(($path=self::getPathOfNamespace($namespace,self::CLASS_FILE_EXT))!==null) |
150
|
|
|
{ |
151
|
|
|
$className=substr($namespace,$pos+1); |
152
|
|
|
if($className==='*') { |
153
|
|
|
self::$_usings[$namespace]=$path; |
154
|
|
|
set_include_path(get_include_path().PATH_SEPARATOR.$path); |
155
|
|
|
} |
156
|
|
|
else { |
157
|
|
|
self::$_usings[$namespace]=$path; |
158
|
|
|
if(!$checkClassExistence || !class_exists($className,false)) |
159
|
|
|
{ |
160
|
|
|
try |
161
|
|
|
{ |
162
|
|
|
include_once($path); |
163
|
|
|
} |
164
|
|
|
catch(Exception $e) |
165
|
|
|
{ |
166
|
|
|
if($checkClassExistence && !class_exists($className,false)) |
167
|
|
|
throw new TInvalidOperationException('prado_component_unknown',$className,$e->getMessage()); |
168
|
|
|
else |
169
|
|
|
throw $e; |
170
|
|
|
} |
171
|
|
|
} |
172
|
|
|
} |
173
|
|
|
} |
174
|
|
|
else |
175
|
|
|
throw new TInvalidDataValueException('prado_using_invalid',$namespace); |
176
|
|
|
} |
177
|
|
|
public static function getPathOfNamespace($namespace, $ext='') |
178
|
|
|
{ |
179
|
|
|
if(self::CLASS_FILE_EXT === $ext || empty($ext)) |
180
|
|
|
{ |
181
|
|
|
if(isset(self::$_usings[$namespace])) |
182
|
|
|
return self::$_usings[$namespace]; |
183
|
|
|
if(isset(self::$_aliases[$namespace])) |
184
|
|
|
return self::$_aliases[$namespace]; |
185
|
|
|
} |
186
|
|
|
$segs = explode('.',$namespace); |
187
|
|
|
$alias = array_shift($segs); |
188
|
|
|
if(null !== ($file = array_pop($segs)) && null !== ($root = self::getPathOfAlias($alias))) |
189
|
|
|
return rtrim($root.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR ,$segs),'/\\').(($file === '*') ? '' : DIRECTORY_SEPARATOR.$file.$ext); |
190
|
|
|
return null; |
191
|
|
|
} |
192
|
|
|
public static function getPathOfAlias($alias) |
193
|
|
|
{ |
194
|
|
|
return isset(self::$_aliases[$alias])?self::$_aliases[$alias]:null; |
195
|
|
|
} |
196
|
|
|
protected static function getPathAliases() |
197
|
|
|
{ |
198
|
|
|
return self::$_aliases; |
199
|
|
|
} |
200
|
|
|
public static function setPathOfAlias($alias,$path) |
201
|
|
|
{ |
202
|
|
|
if(isset(self::$_aliases[$alias]) && !defined('PRADO_TEST_RUN')) |
203
|
|
|
throw new TInvalidOperationException('prado_alias_redefined',$alias); |
204
|
|
|
else if(($rp=realpath($path))!==false && is_dir($rp)) |
205
|
|
|
{ |
206
|
|
|
if(strpos($alias,'.')===false) |
207
|
|
|
self::$_aliases[$alias]=$rp; |
208
|
|
|
else |
209
|
|
|
throw new TInvalidDataValueException('prado_aliasname_invalid',$alias); |
210
|
|
|
} |
211
|
|
|
else |
212
|
|
|
throw new TInvalidDataValueException('prado_alias_invalid',$alias,$path); |
213
|
|
|
} |
214
|
|
|
public static function fatalError($msg) |
215
|
|
|
{ |
216
|
|
|
echo '<h1>Fatal Error</h1>'; |
217
|
|
|
echo '<p>'.$msg.'</p>'; |
218
|
|
|
if(!function_exists('debug_backtrace')) |
219
|
|
|
return; |
220
|
|
|
echo '<h2>Debug Backtrace</h2>'; |
221
|
|
|
echo '<pre>'; |
222
|
|
|
$index=-1; |
223
|
|
|
foreach(debug_backtrace() as $t) |
224
|
|
|
{ |
225
|
|
|
$index++; |
226
|
|
|
if($index==0) continue; |
227
|
|
|
echo '#'.$index.' '; |
228
|
|
|
if(isset($t['file'])) |
229
|
|
|
echo basename($t['file']) . ':' . $t['line']; |
230
|
|
|
else |
231
|
|
|
echo '<PHP inner-code>'; |
232
|
|
|
echo ' -- '; |
233
|
|
|
if(isset($t['class'])) |
234
|
|
|
echo $t['class'] . $t['type']; |
235
|
|
|
echo $t['function'] . '('; |
236
|
|
|
if(isset($t['args']) && sizeof($t['args']) > 0) |
237
|
|
|
{ |
238
|
|
|
$count=0; |
239
|
|
|
foreach($t['args'] as $item) |
240
|
|
|
{ |
241
|
|
|
if(is_string($item)) |
242
|
|
|
{ |
243
|
|
|
$str=htmlentities(str_replace("\r\n", "", $item), ENT_QUOTES); |
244
|
|
|
if (strlen($item) > 70) |
245
|
|
|
echo "'". substr($str, 0, 70) . "...'"; |
246
|
|
|
else |
247
|
|
|
echo "'" . $str . "'"; |
248
|
|
|
} |
249
|
|
|
else if (is_int($item) || is_float($item)) |
250
|
|
|
echo $item; |
251
|
|
|
else if (is_object($item)) |
252
|
|
|
echo get_class($item); |
253
|
|
|
else if (is_array($item)) |
254
|
|
|
echo 'array(' . count($item) . ')'; |
255
|
|
|
else if (is_bool($item)) |
256
|
|
|
echo $item ? 'true' : 'false'; |
257
|
|
|
else if ($item === null) |
258
|
|
|
echo 'NULL'; |
259
|
|
|
else if (is_resource($item)) |
260
|
|
|
echo get_resource_type($item); |
261
|
|
|
$count++; |
262
|
|
|
if (count($t['args']) > $count) |
263
|
|
|
echo ', '; |
264
|
|
|
} |
265
|
|
|
} |
266
|
|
|
echo ")\n"; |
267
|
|
|
} |
268
|
|
|
echo '</pre>'; |
269
|
|
|
exit(1); |
|
|
|
|
270
|
|
|
} |
271
|
|
|
public static function getUserLanguages() |
|
|
|
|
272
|
|
|
{ |
273
|
|
|
static $languages=null; |
274
|
|
|
if($languages===null) |
275
|
|
|
{ |
276
|
|
|
if(!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) |
277
|
|
|
$languages[0]='en'; |
278
|
|
|
else |
279
|
|
|
{ |
280
|
|
|
$languages=array(); |
281
|
|
|
foreach(explode(',',$_SERVER['HTTP_ACCEPT_LANGUAGE']) as $language) |
282
|
|
|
{ |
283
|
|
|
$array=explode(';q=',trim($language)); |
284
|
|
|
$languages[trim($array[0])]=isset($array[1])?(float)$array[1]:1.0; |
285
|
|
|
} |
286
|
|
|
arsort($languages); |
287
|
|
|
$languages=array_keys($languages); |
288
|
|
|
if(empty($languages)) |
289
|
|
|
$languages[0]='en'; |
290
|
|
|
} |
291
|
|
|
} |
292
|
|
|
return $languages; |
293
|
|
|
} |
294
|
|
|
public static function getPreferredLanguage() |
295
|
|
|
{ |
296
|
|
|
static $language=null; |
297
|
|
|
if($language===null) |
298
|
|
|
{ |
299
|
|
|
$langs=Prado::getUserLanguages(); |
300
|
|
|
$lang=explode('-',$langs[0]); |
301
|
|
|
if(empty($lang[0]) || !ctype_alpha($lang[0])) |
302
|
|
|
$language='en'; |
303
|
|
|
else |
304
|
|
|
$language=$lang[0]; |
305
|
|
|
} |
306
|
|
|
return $language; |
307
|
|
|
} |
308
|
|
|
public static function trace($msg,$category='Uncategorized',$ctl=null) |
309
|
|
|
{ |
310
|
|
|
if(self::$_application && self::$_application->getMode()===TApplicationMode::Performance) |
311
|
|
|
return; |
312
|
|
|
if(!self::$_application || self::$_application->getMode()===TApplicationMode::Debug) |
313
|
|
|
{ |
314
|
|
|
$trace=debug_backtrace(); |
315
|
|
|
if(isset($trace[0]['file']) && isset($trace[0]['line'])) |
316
|
|
|
$msg.=" (line {$trace[0]['line']}, {$trace[0]['file']})"; |
317
|
|
|
$level=TLogger::DEBUG; |
318
|
|
|
} |
319
|
|
|
else |
320
|
|
|
$level=TLogger::INFO; |
321
|
|
|
self::log($msg,$level,$category,$ctl); |
322
|
|
|
} |
323
|
|
|
public static function log($msg,$level=TLogger::INFO,$category='Uncategorized',$ctl=null) |
324
|
|
|
{ |
325
|
|
|
if(self::$_logger===null) |
326
|
|
|
self::$_logger=new TLogger; |
327
|
|
|
self::$_logger->log($msg,$level,$category,$ctl); |
328
|
|
|
} |
329
|
|
|
public static function getLogger() |
330
|
|
|
{ |
331
|
|
|
if(self::$_logger===null) |
332
|
|
|
self::$_logger=new TLogger; |
333
|
|
|
return self::$_logger; |
334
|
|
|
} |
335
|
|
|
public static function varDump($var,$depth=10,$highlight=false) |
336
|
|
|
{ |
337
|
|
|
Prado::using('System.Util.TVarDumper'); |
338
|
|
|
return TVarDumper::dump($var,$depth,$highlight); |
339
|
|
|
} |
340
|
|
|
public static function localize($text, $parameters=array(), $catalogue=null, $charset=null) |
341
|
|
|
{ |
342
|
|
|
Prado::using('System.I18N.Translation'); |
343
|
|
|
$app = Prado::getApplication()->getGlobalization(false); |
344
|
|
|
$params = array(); |
345
|
|
|
foreach($parameters as $key => $value) |
346
|
|
|
$params['{'.$key.'}'] = $value; |
347
|
|
|
if($app===null || ($config = $app->getTranslationConfiguration())===null) |
348
|
|
|
return strtr($text, $params); |
349
|
|
|
if ($catalogue===null) |
350
|
|
|
$catalogue=isset($config['catalogue'])?$config['catalogue']:'messages'; |
351
|
|
|
Translation::init($catalogue); |
352
|
|
|
$appCharset = $app===null ? '' : $app->getCharset(); |
353
|
|
|
$defaultCharset = ($app===null) ? 'UTF-8' : $app->getDefaultCharset(); |
354
|
|
|
if(empty($charset)) $charset = $appCharset; |
355
|
|
|
if(empty($charset)) $charset = $defaultCharset; |
356
|
|
|
return Translation::formatter($catalogue)->format($text,$params,$catalogue,$charset); |
357
|
|
|
} |
358
|
|
|
} |
359
|
|
|
PradoBase::using('System.TComponent'); |
360
|
|
|
PradoBase::using('System.Exceptions.TException'); |
361
|
|
|
PradoBase::using('System.Util.TLogger'); |
362
|
|
|
if(!class_exists('Prado',false)) |
363
|
|
|
{ |
364
|
|
|
class Prado extends PradoBase |
365
|
|
|
{ |
366
|
|
|
} |
367
|
|
|
} |
368
|
|
|
spl_autoload_register(array('Prado','autoload')); |
369
|
|
|
Prado::initErrorHandlers(); |
370
|
|
|
interface IModule |
371
|
|
|
{ |
372
|
|
|
public function init($config); |
|
|
|
|
373
|
|
|
public function getID(); |
|
|
|
|
374
|
|
|
public function setID($id); |
|
|
|
|
375
|
|
|
} |
376
|
|
|
interface IService |
377
|
|
|
{ |
378
|
|
|
public function init($config); |
|
|
|
|
379
|
|
|
public function getID(); |
|
|
|
|
380
|
|
|
public function setID($id); |
|
|
|
|
381
|
|
|
public function getEnabled(); |
|
|
|
|
382
|
|
|
public function setEnabled($value); |
|
|
|
|
383
|
|
|
public function run(); |
|
|
|
|
384
|
|
|
} |
385
|
|
|
interface ITextWriter |
386
|
|
|
{ |
387
|
|
|
public function write($str); |
|
|
|
|
388
|
|
|
public function flush(); |
|
|
|
|
389
|
|
|
} |
390
|
|
|
interface IUser |
391
|
|
|
{ |
392
|
|
|
public function getName(); |
|
|
|
|
393
|
|
|
public function setName($value); |
|
|
|
|
394
|
|
|
public function getIsGuest(); |
|
|
|
|
395
|
|
|
public function setIsGuest($value); |
|
|
|
|
396
|
|
|
public function getRoles(); |
|
|
|
|
397
|
|
|
public function setRoles($value); |
|
|
|
|
398
|
|
|
public function isInRole($role); |
|
|
|
|
399
|
|
|
public function saveToString(); |
|
|
|
|
400
|
|
|
public function loadFromString($string); |
|
|
|
|
401
|
|
|
} |
402
|
|
|
interface IStatePersister |
403
|
|
|
{ |
404
|
|
|
public function load(); |
|
|
|
|
405
|
|
|
public function save($state); |
|
|
|
|
406
|
|
|
} |
407
|
|
|
interface ICache |
408
|
|
|
{ |
409
|
|
|
public function get($id); |
|
|
|
|
410
|
|
|
public function set($id,$value,$expire=0,$dependency=null); |
|
|
|
|
411
|
|
|
public function add($id,$value,$expire=0,$dependency=null); |
|
|
|
|
412
|
|
|
public function delete($id); |
|
|
|
|
413
|
|
|
public function flush(); |
|
|
|
|
414
|
|
|
} |
415
|
|
|
interface ICacheDependency |
416
|
|
|
{ |
417
|
|
|
public function getHasChanged(); |
|
|
|
|
418
|
|
|
} |
419
|
|
|
interface IRenderable |
420
|
|
|
{ |
421
|
|
|
public function render($writer); |
|
|
|
|
422
|
|
|
} |
423
|
|
|
interface IBindable |
424
|
|
|
{ |
425
|
|
|
public function dataBind(); |
|
|
|
|
426
|
|
|
} |
427
|
|
|
interface IStyleable |
428
|
|
|
{ |
429
|
|
|
public function getHasStyle(); |
|
|
|
|
430
|
|
|
public function getStyle(); |
|
|
|
|
431
|
|
|
public function clearStyle(); |
|
|
|
|
432
|
|
|
} |
433
|
|
|
interface IActiveControl |
434
|
|
|
{ |
435
|
|
|
public function getActiveControl(); |
|
|
|
|
436
|
|
|
} |
437
|
|
|
interface ICallbackEventHandler |
438
|
|
|
{ |
439
|
|
|
public function raiseCallbackEvent($eventArgument); |
|
|
|
|
440
|
|
|
} |
441
|
|
|
interface IDataRenderer |
442
|
|
|
{ |
443
|
|
|
public function getData(); |
|
|
|
|
444
|
|
|
public function setData($value); |
|
|
|
|
445
|
|
|
} |
446
|
|
|
class TApplicationComponent extends TComponent |
447
|
|
|
{ |
448
|
|
|
public function getApplication() |
449
|
|
|
{ |
450
|
|
|
return Prado::getApplication(); |
451
|
|
|
} |
452
|
|
|
public function getService() |
453
|
|
|
{ |
454
|
|
|
return Prado::getApplication()->getService(); |
455
|
|
|
} |
456
|
|
|
public function getRequest() |
457
|
|
|
{ |
458
|
|
|
return Prado::getApplication()->getRequest(); |
459
|
|
|
} |
460
|
|
|
public function getResponse() |
461
|
|
|
{ |
462
|
|
|
return Prado::getApplication()->getResponse(); |
463
|
|
|
} |
464
|
|
|
public function getSession() |
465
|
|
|
{ |
466
|
|
|
return Prado::getApplication()->getSession(); |
467
|
|
|
} |
468
|
|
|
public function getUser() |
469
|
|
|
{ |
470
|
|
|
return Prado::getApplication()->getUser(); |
471
|
|
|
} |
472
|
|
|
public function publishAsset($assetPath,$className=null) |
473
|
|
|
{ |
474
|
|
|
if($className===null) |
475
|
|
|
$className=get_class($this); |
476
|
|
|
$class=new ReflectionClass($className); |
477
|
|
|
$fullPath=dirname($class->getFileName()).DIRECTORY_SEPARATOR.$assetPath; |
478
|
|
|
return $this->publishFilePath($fullPath); |
479
|
|
|
} |
480
|
|
|
public function publishFilePath($fullPath, $checkTimestamp=false) |
481
|
|
|
{ |
482
|
|
|
return Prado::getApplication()->getAssetManager()->publishFilePath($fullPath, $checkTimestamp); |
483
|
|
|
} |
484
|
|
|
} |
485
|
|
|
abstract class TModule extends TApplicationComponent implements IModule |
486
|
|
|
{ |
487
|
|
|
private $_id; |
488
|
|
|
public function init($config) |
489
|
|
|
{ |
490
|
|
|
} |
491
|
|
|
public function getID() |
492
|
|
|
{ |
493
|
|
|
return $this->_id; |
494
|
|
|
} |
495
|
|
|
public function setID($value) |
496
|
|
|
{ |
497
|
|
|
$this->_id=$value; |
498
|
|
|
} |
499
|
|
|
} |
500
|
|
|
abstract class TService extends TApplicationComponent implements IService |
501
|
|
|
{ |
502
|
|
|
private $_id; |
503
|
|
|
private $_enabled=true; |
504
|
|
|
public function init($config) |
505
|
|
|
{ |
506
|
|
|
} |
507
|
|
|
public function getID() |
508
|
|
|
{ |
509
|
|
|
return $this->_id; |
510
|
|
|
} |
511
|
|
|
public function setID($value) |
512
|
|
|
{ |
513
|
|
|
$this->_id=$value; |
514
|
|
|
} |
515
|
|
|
public function getEnabled() |
516
|
|
|
{ |
517
|
|
|
return $this->_enabled; |
518
|
|
|
} |
519
|
|
|
public function setEnabled($value) |
520
|
|
|
{ |
521
|
|
|
$this->_enabled=TPropertyValue::ensureBoolean($value); |
522
|
|
|
} |
523
|
|
|
public function run() |
524
|
|
|
{ |
525
|
|
|
} |
526
|
|
|
} |
527
|
|
|
class TErrorHandler extends TModule |
528
|
|
|
{ |
529
|
|
|
const ERROR_FILE_NAME='error'; |
530
|
|
|
const EXCEPTION_FILE_NAME='exception'; |
531
|
|
|
const SOURCE_LINES=12; |
532
|
|
|
private $_templatePath=null; |
533
|
|
|
public function init($config) |
534
|
|
|
{ |
535
|
|
|
$this->getApplication()->setErrorHandler($this); |
536
|
|
|
} |
537
|
|
|
public function getErrorTemplatePath() |
538
|
|
|
{ |
539
|
|
|
if($this->_templatePath===null) |
540
|
|
|
$this->_templatePath=Prado::getFrameworkPath().'/Exceptions/templates'; |
541
|
|
|
return $this->_templatePath; |
542
|
|
|
} |
543
|
|
|
public function setErrorTemplatePath($value) |
544
|
|
|
{ |
545
|
|
|
if(($templatePath=Prado::getPathOfNamespace($value))!==null && is_dir($templatePath)) |
546
|
|
|
$this->_templatePath=$templatePath; |
547
|
|
|
else |
548
|
|
|
throw new TConfigurationException('errorhandler_errortemplatepath_invalid',$value); |
549
|
|
|
} |
550
|
|
|
public function handleError($sender,$param) |
551
|
|
|
{ |
552
|
|
|
static $handling=false; |
553
|
|
|
restore_error_handler(); |
554
|
|
|
restore_exception_handler(); |
555
|
|
|
if($handling) |
556
|
|
|
$this->handleRecursiveError($param); |
557
|
|
|
else |
558
|
|
|
{ |
559
|
|
|
$handling=true; |
560
|
|
|
if(($response=$this->getResponse())!==null) |
561
|
|
|
$response->clear(); |
562
|
|
|
if(!headers_sent()) |
563
|
|
|
header('Content-Type: text/html; charset=UTF-8'); |
564
|
|
|
if($param instanceof THttpException) |
565
|
|
|
$this->handleExternalError($param->getStatusCode(),$param); |
566
|
|
|
else if($this->getApplication()->getMode()===TApplicationMode::Debug) |
567
|
|
|
$this->displayException($param); |
568
|
|
|
else |
569
|
|
|
$this->handleExternalError(500,$param); |
570
|
|
|
} |
571
|
|
|
} |
572
|
|
|
protected static function hideSecurityRelated($value, $exception=null) |
|
|
|
|
573
|
|
|
{ |
574
|
|
|
$aRpl = array(); |
575
|
|
|
if($exception !== null && $exception instanceof Exception) |
576
|
|
|
{ |
577
|
|
|
$aTrace = $exception->getTrace(); |
578
|
|
|
foreach($aTrace as $item) |
579
|
|
|
{ |
580
|
|
|
if(isset($item['file'])) |
581
|
|
|
$aRpl[dirname($item['file']) . DIRECTORY_SEPARATOR] = '<hidden>' . DIRECTORY_SEPARATOR; |
582
|
|
|
} |
583
|
|
|
} |
584
|
|
|
$aRpl[$_SERVER['DOCUMENT_ROOT']] = '${DocumentRoot}'; |
585
|
|
|
$aRpl[str_replace('/', DIRECTORY_SEPARATOR, $_SERVER['DOCUMENT_ROOT'])] = '${DocumentRoot}'; |
586
|
|
|
$aRpl[PRADO_DIR . DIRECTORY_SEPARATOR] = '${PradoFramework}' . DIRECTORY_SEPARATOR; |
587
|
|
|
if(isset($aRpl[DIRECTORY_SEPARATOR])) unset($aRpl[DIRECTORY_SEPARATOR]); |
588
|
|
|
$aRpl = array_reverse($aRpl, true); |
589
|
|
|
return str_replace(array_keys($aRpl), $aRpl, $value); |
590
|
|
|
} |
591
|
|
|
protected function handleExternalError($statusCode,$exception) |
|
|
|
|
592
|
|
|
{ |
593
|
|
|
if(!($exception instanceof THttpException)) |
594
|
|
|
error_log($exception->__toString()); |
595
|
|
|
$content=$this->getErrorTemplate($statusCode,$exception); |
596
|
|
|
$serverAdmin=isset($_SERVER['SERVER_ADMIN'])?$_SERVER['SERVER_ADMIN']:''; |
597
|
|
|
$isDebug = $this->getApplication()->getMode()===TApplicationMode::Debug; |
598
|
|
|
$errorMessage = $exception->getMessage(); |
599
|
|
|
if($isDebug) |
600
|
|
|
$version=$_SERVER['SERVER_SOFTWARE'].' <a href="https://github.com/pradosoft/prado">PRADO</a>/'.Prado::getVersion(); |
601
|
|
|
else |
602
|
|
|
{ |
603
|
|
|
$version=''; |
604
|
|
|
$errorMessage = self::hideSecurityRelated($errorMessage, $exception); |
605
|
|
|
} |
606
|
|
|
$tokens=array( |
607
|
|
|
'%%StatusCode%%' => "$statusCode", |
608
|
|
|
'%%ErrorMessage%%' => htmlspecialchars($errorMessage), |
609
|
|
|
'%%ServerAdmin%%' => $serverAdmin, |
610
|
|
|
'%%Version%%' => $version, |
611
|
|
|
'%%Time%%' => @strftime('%Y-%m-%d %H:%M',time()) |
612
|
|
|
); |
613
|
|
|
$this->getApplication()->getResponse()->setStatusCode($statusCode, $isDebug ? $exception->getMessage() : null); |
614
|
|
|
echo strtr($content,$tokens); |
615
|
|
|
} |
616
|
|
|
protected function handleRecursiveError($exception) |
617
|
|
|
{ |
618
|
|
|
if($this->getApplication()->getMode()===TApplicationMode::Debug) |
619
|
|
|
{ |
620
|
|
|
echo "<html><head><title>Recursive Error</title></head>\n"; |
621
|
|
|
echo "<body><h1>Recursive Error</h1>\n"; |
622
|
|
|
echo "<pre>".$exception->__toString()."</pre>\n"; |
623
|
|
|
echo "</body></html>"; |
624
|
|
|
} |
625
|
|
|
else |
626
|
|
|
{ |
627
|
|
|
error_log("Error happened while processing an existing error:\n".$exception->__toString()); |
628
|
|
|
header('HTTP/1.0 500 Internal Error'); |
629
|
|
|
} |
630
|
|
|
} |
631
|
|
|
protected function displayException($exception) |
|
|
|
|
632
|
|
|
{ |
633
|
|
|
if(php_sapi_name()==='cli') |
634
|
|
|
{ |
635
|
|
|
echo $exception->getMessage()."\n"; |
636
|
|
|
echo $exception->getTraceAsString(); |
637
|
|
|
return; |
638
|
|
|
} |
639
|
|
|
if($exception instanceof TTemplateException) |
640
|
|
|
{ |
641
|
|
|
$fileName=$exception->getTemplateFile(); |
642
|
|
|
$lines=empty($fileName)?explode("\n",$exception->getTemplateSource()):@file($fileName); |
643
|
|
|
$source=$this->getSourceCode($lines,$exception->getLineNumber()); |
644
|
|
|
if($fileName==='') |
645
|
|
|
$fileName='---embedded template---'; |
646
|
|
|
$errorLine=$exception->getLineNumber(); |
647
|
|
|
} |
648
|
|
|
else |
649
|
|
|
{ |
650
|
|
|
if(($trace=$this->getExactTrace($exception))!==null) |
651
|
|
|
{ |
652
|
|
|
$fileName=$trace['file']; |
653
|
|
|
$errorLine=$trace['line']; |
654
|
|
|
} |
655
|
|
|
else |
656
|
|
|
{ |
657
|
|
|
$fileName=$exception->getFile(); |
658
|
|
|
$errorLine=$exception->getLine(); |
659
|
|
|
} |
660
|
|
|
$source=$this->getSourceCode(@file($fileName),$errorLine); |
661
|
|
|
} |
662
|
|
|
if($this->getApplication()->getMode()===TApplicationMode::Debug) |
663
|
|
|
$version=$_SERVER['SERVER_SOFTWARE'].' <a href="https://github.com/pradosoft/prado">PRADO</a>/'.Prado::getVersion(); |
664
|
|
|
else |
665
|
|
|
$version=''; |
666
|
|
|
$tokens=array( |
667
|
|
|
'%%ErrorType%%' => get_class($exception), |
668
|
|
|
'%%ErrorMessage%%' => $this->addLink(htmlspecialchars($exception->getMessage())), |
669
|
|
|
'%%SourceFile%%' => htmlspecialchars($fileName).' ('.$errorLine.')', |
670
|
|
|
'%%SourceCode%%' => $source, |
671
|
|
|
'%%StackTrace%%' => htmlspecialchars($exception->getTraceAsString()), |
672
|
|
|
'%%Version%%' => $version, |
673
|
|
|
'%%Time%%' => @strftime('%Y-%m-%d %H:%M',time()) |
674
|
|
|
); |
675
|
|
|
$content=$this->getExceptionTemplate($exception); |
676
|
|
|
echo strtr($content,$tokens); |
677
|
|
|
} |
678
|
|
|
protected function getExceptionTemplate($exception) |
679
|
|
|
{ |
680
|
|
|
$lang=Prado::getPreferredLanguage(); |
681
|
|
|
$exceptionFile=Prado::getFrameworkPath().'/Exceptions/templates/'.self::EXCEPTION_FILE_NAME.'-'.$lang.'.html'; |
682
|
|
|
if(!is_file($exceptionFile)) |
683
|
|
|
$exceptionFile=Prado::getFrameworkPath().'/Exceptions/templates/'.self::EXCEPTION_FILE_NAME.'.html'; |
684
|
|
|
if(($content=@file_get_contents($exceptionFile))===false) |
685
|
|
|
die("Unable to open exception template file '$exceptionFile'."); |
|
|
|
|
686
|
|
|
return $content; |
687
|
|
|
} |
688
|
|
|
protected function getErrorTemplate($statusCode,$exception) |
689
|
|
|
{ |
690
|
|
|
$base=$this->getErrorTemplatePath().DIRECTORY_SEPARATOR.self::ERROR_FILE_NAME; |
691
|
|
|
$lang=Prado::getPreferredLanguage(); |
692
|
|
|
if(is_file("$base$statusCode-$lang.html")) |
693
|
|
|
$errorFile="$base$statusCode-$lang.html"; |
694
|
|
|
else if(is_file("$base$statusCode.html")) |
695
|
|
|
$errorFile="$base$statusCode.html"; |
696
|
|
|
else if(is_file("$base-$lang.html")) |
697
|
|
|
$errorFile="$base-$lang.html"; |
698
|
|
|
else |
699
|
|
|
$errorFile="$base.html"; |
700
|
|
|
if(($content=@file_get_contents($errorFile))===false) |
701
|
|
|
die("Unable to open error template file '$errorFile'."); |
|
|
|
|
702
|
|
|
return $content; |
703
|
|
|
} |
704
|
|
|
private function getExactTrace($exception) |
705
|
|
|
{ |
706
|
|
|
$trace=$exception->getTrace(); |
707
|
|
|
$result=null; |
708
|
|
|
if($exception instanceof TPhpErrorException) |
709
|
|
|
{ |
710
|
|
|
if(isset($trace[0]['file'])) |
711
|
|
|
$result=$trace[0]; |
712
|
|
|
elseif(isset($trace[1])) |
713
|
|
|
$result=$trace[1]; |
714
|
|
|
} |
715
|
|
|
else if($exception instanceof TInvalidOperationException) |
716
|
|
|
{ |
717
|
|
|
if(($result=$this->getPropertyAccessTrace($trace,'__get'))===null) |
718
|
|
|
$result=$this->getPropertyAccessTrace($trace,'__set'); |
719
|
|
|
} |
720
|
|
|
if($result!==null && strpos($result['file'],': eval()\'d code')!==false) |
721
|
|
|
return null; |
722
|
|
|
return $result; |
723
|
|
|
} |
724
|
|
|
private function getPropertyAccessTrace($trace,$pattern) |
725
|
|
|
{ |
726
|
|
|
$result=null; |
727
|
|
|
foreach($trace as $t) |
728
|
|
|
{ |
729
|
|
|
if(isset($t['function']) && $t['function']===$pattern) |
730
|
|
|
$result=$t; |
731
|
|
|
else |
732
|
|
|
break; |
733
|
|
|
} |
734
|
|
|
return $result; |
735
|
|
|
} |
736
|
|
|
private function getSourceCode($lines,$errorLine) |
737
|
|
|
{ |
738
|
|
|
$beginLine=$errorLine-self::SOURCE_LINES>=0?$errorLine-self::SOURCE_LINES:0; |
739
|
|
|
$endLine=$errorLine+self::SOURCE_LINES<=count($lines)?$errorLine+self::SOURCE_LINES:count($lines); |
740
|
|
|
$source=''; |
741
|
|
|
for($i=$beginLine;$i<$endLine;++$i) |
742
|
|
|
{ |
743
|
|
|
if($i===$errorLine-1) |
744
|
|
|
{ |
745
|
|
|
$line=htmlspecialchars(sprintf("%04d: %s",$i+1,str_replace("\t",' ',$lines[$i]))); |
746
|
|
|
$source.="<div class=\"error\">".$line."</div>"; |
747
|
|
|
} |
748
|
|
|
else |
749
|
|
|
$source.=htmlspecialchars(sprintf("%04d: %s",$i+1,str_replace("\t",' ',$lines[$i]))); |
750
|
|
|
} |
751
|
|
|
return $source; |
752
|
|
|
} |
753
|
|
|
private function addLink($message) |
754
|
|
|
{ |
755
|
|
|
$baseUrl='http://pradosoft.github.io/docs/manual/class-'; |
756
|
|
|
return preg_replace('/\b(T[A-Z]\w+)\b/',"<a href=\"$baseUrl\${1}\" target=\"_blank\">\${1}</a>",$message); |
757
|
|
|
} |
758
|
|
|
} |
759
|
|
|
class TList extends TComponent implements IteratorAggregate,ArrayAccess,Countable |
|
|
|
|
760
|
|
|
{ |
761
|
|
|
private $_d=array(); |
762
|
|
|
private $_c=0; |
763
|
|
|
private $_r=false; |
764
|
|
|
public function __construct($data=null,$readOnly=false) |
765
|
|
|
{ |
766
|
|
|
if($data!==null) |
767
|
|
|
$this->copyFrom($data); |
768
|
|
|
$this->setReadOnly($readOnly); |
769
|
|
|
} |
770
|
|
|
public function getReadOnly() |
771
|
|
|
{ |
772
|
|
|
return $this->_r; |
773
|
|
|
} |
774
|
|
|
protected function setReadOnly($value) |
775
|
|
|
{ |
776
|
|
|
$this->_r=TPropertyValue::ensureBoolean($value); |
777
|
|
|
} |
778
|
|
|
public function getIterator() |
779
|
|
|
{ |
780
|
|
|
return new ArrayIterator( $this->_d ); |
781
|
|
|
} |
782
|
|
|
public function count() |
783
|
|
|
{ |
784
|
|
|
return $this->getCount(); |
785
|
|
|
} |
786
|
|
|
public function getCount() |
787
|
|
|
{ |
788
|
|
|
return $this->_c; |
789
|
|
|
} |
790
|
|
|
public function itemAt($index) |
791
|
|
|
{ |
792
|
|
|
if($index>=0 && $index<$this->_c) |
793
|
|
|
return $this->_d[$index]; |
794
|
|
|
else |
795
|
|
|
throw new TInvalidDataValueException('list_index_invalid',$index); |
796
|
|
|
} |
797
|
|
|
public function add($item) |
798
|
|
|
{ |
799
|
|
|
$this->insertAt($this->_c,$item); |
800
|
|
|
return $this->_c-1; |
801
|
|
|
} |
802
|
|
|
public function insertAt($index,$item) |
803
|
|
|
{ |
804
|
|
|
if(!$this->_r) |
805
|
|
|
{ |
806
|
|
|
if($index===$this->_c) |
807
|
|
|
$this->_d[$this->_c++]=$item; |
808
|
|
|
else if($index>=0 && $index<$this->_c) |
809
|
|
|
{ |
810
|
|
|
array_splice($this->_d,$index,0,array($item)); |
811
|
|
|
$this->_c++; |
812
|
|
|
} |
813
|
|
|
else |
814
|
|
|
throw new TInvalidDataValueException('list_index_invalid',$index); |
815
|
|
|
} |
816
|
|
|
else |
817
|
|
|
throw new TInvalidOperationException('list_readonly',get_class($this)); |
818
|
|
|
} |
819
|
|
|
public function remove($item) |
820
|
|
|
{ |
821
|
|
|
if(!$this->_r) |
822
|
|
|
{ |
823
|
|
|
if(($index=$this->indexOf($item))>=0) |
824
|
|
|
{ |
825
|
|
|
$this->removeAt($index); |
826
|
|
|
return $index; |
827
|
|
|
} |
828
|
|
|
else |
829
|
|
|
throw new TInvalidDataValueException('list_item_inexistent'); |
830
|
|
|
} |
831
|
|
|
else |
832
|
|
|
throw new TInvalidOperationException('list_readonly',get_class($this)); |
833
|
|
|
} |
834
|
|
|
public function removeAt($index) |
835
|
|
|
{ |
836
|
|
|
if(!$this->_r) |
837
|
|
|
{ |
838
|
|
|
if($index>=0 && $index<$this->_c) |
839
|
|
|
{ |
840
|
|
|
$this->_c--; |
841
|
|
|
if($index===$this->_c) |
842
|
|
|
return array_pop($this->_d); |
843
|
|
|
else |
844
|
|
|
{ |
845
|
|
|
$item=$this->_d[$index]; |
846
|
|
|
array_splice($this->_d,$index,1); |
847
|
|
|
return $item; |
848
|
|
|
} |
849
|
|
|
} |
850
|
|
|
else |
851
|
|
|
throw new TInvalidDataValueException('list_index_invalid',$index); |
852
|
|
|
} |
853
|
|
|
else |
854
|
|
|
throw new TInvalidOperationException('list_readonly',get_class($this)); |
855
|
|
|
} |
856
|
|
|
public function clear() |
857
|
|
|
{ |
858
|
|
|
for($i=$this->_c-1;$i>=0;--$i) |
859
|
|
|
$this->removeAt($i); |
860
|
|
|
} |
861
|
|
|
public function contains($item) |
862
|
|
|
{ |
863
|
|
|
return $this->indexOf($item)>=0; |
864
|
|
|
} |
865
|
|
|
public function indexOf($item) |
866
|
|
|
{ |
867
|
|
|
if(($index=array_search($item,$this->_d,true))===false) |
868
|
|
|
return -1; |
869
|
|
|
else |
870
|
|
|
return $index; |
871
|
|
|
} |
872
|
|
|
public function insertBefore($baseitem, $item) |
873
|
|
|
{ |
874
|
|
|
if(!$this->_r) |
875
|
|
|
{ |
876
|
|
|
if(($index = $this->indexOf($baseitem)) == -1) |
877
|
|
|
throw new TInvalidDataValueException('list_item_inexistent'); |
878
|
|
|
$this->insertAt($index, $item); |
879
|
|
|
return $index; |
880
|
|
|
} |
881
|
|
|
else |
882
|
|
|
throw new TInvalidOperationException('list_readonly',get_class($this)); |
883
|
|
|
} |
884
|
|
|
public function insertAfter($baseitem, $item) |
885
|
|
|
{ |
886
|
|
|
if(!$this->_r) |
887
|
|
|
{ |
888
|
|
|
if(($index = $this->indexOf($baseitem)) == -1) |
889
|
|
|
throw new TInvalidDataValueException('list_item_inexistent'); |
890
|
|
|
$this->insertAt($index + 1, $item); |
891
|
|
|
return $index + 1; |
892
|
|
|
} |
893
|
|
|
else |
894
|
|
|
throw new TInvalidOperationException('list_readonly',get_class($this)); |
895
|
|
|
} |
896
|
|
|
public function toArray() |
897
|
|
|
{ |
898
|
|
|
return $this->_d; |
899
|
|
|
} |
900
|
|
|
public function copyFrom($data) |
901
|
|
|
{ |
902
|
|
|
if(is_array($data) || ($data instanceof Traversable)) |
903
|
|
|
{ |
904
|
|
|
if($this->_c>0) |
905
|
|
|
$this->clear(); |
906
|
|
|
foreach($data as $item) |
907
|
|
|
$this->add($item); |
908
|
|
|
} |
909
|
|
|
else if($data!==null) |
910
|
|
|
throw new TInvalidDataTypeException('list_data_not_iterable'); |
911
|
|
|
} |
912
|
|
|
public function mergeWith($data) |
913
|
|
|
{ |
914
|
|
|
if(is_array($data) || ($data instanceof Traversable)) |
915
|
|
|
{ |
916
|
|
|
foreach($data as $item) |
917
|
|
|
$this->add($item); |
918
|
|
|
} |
919
|
|
|
else if($data!==null) |
920
|
|
|
throw new TInvalidDataTypeException('list_data_not_iterable'); |
921
|
|
|
} |
922
|
|
|
public function offsetExists($offset) |
923
|
|
|
{ |
924
|
|
|
return ($offset>=0 && $offset<$this->_c); |
925
|
|
|
} |
926
|
|
|
public function offsetGet($offset) |
927
|
|
|
{ |
928
|
|
|
return $this->itemAt($offset); |
929
|
|
|
} |
930
|
|
|
public function offsetSet($offset,$item) |
931
|
|
|
{ |
932
|
|
|
if($offset===null || $offset===$this->_c) |
933
|
|
|
$this->insertAt($this->_c,$item); |
934
|
|
|
else |
935
|
|
|
{ |
936
|
|
|
$this->removeAt($offset); |
937
|
|
|
$this->insertAt($offset,$item); |
938
|
|
|
} |
939
|
|
|
} |
940
|
|
|
public function offsetUnset($offset) |
941
|
|
|
{ |
942
|
|
|
$this->removeAt($offset); |
943
|
|
|
} |
944
|
|
|
} |
945
|
|
|
class TListIterator extends ArrayIterator |
946
|
|
|
{ |
947
|
|
|
} |
948
|
|
|
abstract class TCache extends TModule implements ICache, ArrayAccess |
949
|
|
|
{ |
950
|
|
|
private $_prefix=null; |
951
|
|
|
private $_primary=true; |
952
|
|
|
public function init($config) |
953
|
|
|
{ |
954
|
|
|
if($this->_prefix===null) |
955
|
|
|
$this->_prefix=$this->getApplication()->getUniqueID(); |
956
|
|
|
if($this->_primary) |
957
|
|
|
{ |
958
|
|
|
if($this->getApplication()->getCache()===null) |
959
|
|
|
$this->getApplication()->setCache($this); |
960
|
|
|
else |
961
|
|
|
throw new TConfigurationException('cache_primary_duplicated',get_class($this)); |
962
|
|
|
} |
963
|
|
|
} |
964
|
|
|
public function getPrimaryCache() |
965
|
|
|
{ |
966
|
|
|
return $this->_primary; |
967
|
|
|
} |
968
|
|
|
public function setPrimaryCache($value) |
969
|
|
|
{ |
970
|
|
|
$this->_primary=TPropertyValue::ensureBoolean($value); |
971
|
|
|
} |
972
|
|
|
public function getKeyPrefix() |
973
|
|
|
{ |
974
|
|
|
return $this->_prefix; |
975
|
|
|
} |
976
|
|
|
public function setKeyPrefix($value) |
977
|
|
|
{ |
978
|
|
|
$this->_prefix=$value; |
979
|
|
|
} |
980
|
|
|
protected function generateUniqueKey($key) |
981
|
|
|
{ |
982
|
|
|
return md5($this->_prefix.$key); |
983
|
|
|
} |
984
|
|
|
public function get($id) |
985
|
|
|
{ |
986
|
|
|
if(($data=$this->getValue($this->generateUniqueKey($id)))!==false) |
987
|
|
|
{ |
988
|
|
|
if(!is_array($data)) |
989
|
|
|
return false; |
990
|
|
|
if(!($data[1] instanceof ICacheDependency) || !$data[1]->getHasChanged()) |
991
|
|
|
return $data[0]; |
992
|
|
|
} |
993
|
|
|
return false; |
994
|
|
|
} |
995
|
|
|
public function set($id,$value,$expire=0,$dependency=null) |
996
|
|
|
{ |
997
|
|
|
if(empty($value) && $expire === 0) |
998
|
|
|
$this->delete($id); |
999
|
|
|
else |
1000
|
|
|
{ |
1001
|
|
|
$data=array($value,$dependency); |
1002
|
|
|
return $this->setValue($this->generateUniqueKey($id),$data,$expire); |
1003
|
|
|
} |
1004
|
|
|
} |
1005
|
|
|
public function add($id,$value,$expire=0,$dependency=null) |
1006
|
|
|
{ |
1007
|
|
|
if(empty($value) && $expire === 0) |
1008
|
|
|
return false; |
1009
|
|
|
$data=array($value,$dependency); |
1010
|
|
|
return $this->addValue($this->generateUniqueKey($id),$data,$expire); |
1011
|
|
|
} |
1012
|
|
|
public function delete($id) |
1013
|
|
|
{ |
1014
|
|
|
return $this->deleteValue($this->generateUniqueKey($id)); |
1015
|
|
|
} |
1016
|
|
|
public function flush() |
1017
|
|
|
{ |
1018
|
|
|
throw new TNotSupportedException('cache_flush_unsupported'); |
1019
|
|
|
} |
1020
|
|
|
abstract protected function getValue($key); |
|
|
|
|
1021
|
|
|
abstract protected function setValue($key,$value,$expire); |
|
|
|
|
1022
|
|
|
abstract protected function addValue($key,$value,$expire); |
|
|
|
|
1023
|
|
|
abstract protected function deleteValue($key); |
|
|
|
|
1024
|
|
|
public function offsetExists($id) |
1025
|
|
|
{ |
1026
|
|
|
return $this->get($id) !== false; |
1027
|
|
|
} |
1028
|
|
|
public function offsetGet($id) |
1029
|
|
|
{ |
1030
|
|
|
return $this->get($id); |
1031
|
|
|
} |
1032
|
|
|
public function offsetSet($id, $value) |
1033
|
|
|
{ |
1034
|
|
|
$this->set($id, $value); |
1035
|
|
|
} |
1036
|
|
|
public function offsetUnset($id) |
1037
|
|
|
{ |
1038
|
|
|
$this->delete($id); |
1039
|
|
|
} |
1040
|
|
|
} |
1041
|
|
|
abstract class TCacheDependency extends TComponent implements ICacheDependency |
1042
|
|
|
{ |
1043
|
|
|
} |
1044
|
|
|
class TFileCacheDependency extends TCacheDependency |
1045
|
|
|
{ |
1046
|
|
|
private $_fileName; |
1047
|
|
|
private $_timestamp; |
1048
|
|
|
public function __construct($fileName) |
1049
|
|
|
{ |
1050
|
|
|
$this->setFileName($fileName); |
1051
|
|
|
} |
1052
|
|
|
public function getFileName() |
1053
|
|
|
{ |
1054
|
|
|
return $this->_fileName; |
1055
|
|
|
} |
1056
|
|
|
public function setFileName($value) |
1057
|
|
|
{ |
1058
|
|
|
$this->_fileName=$value; |
1059
|
|
|
$this->_timestamp=@filemtime($value); |
1060
|
|
|
} |
1061
|
|
|
public function getTimestamp() |
1062
|
|
|
{ |
1063
|
|
|
return $this->_timestamp; |
1064
|
|
|
} |
1065
|
|
|
public function getHasChanged() |
1066
|
|
|
{ |
1067
|
|
|
return @filemtime($this->_fileName)!==$this->_timestamp; |
1068
|
|
|
} |
1069
|
|
|
} |
1070
|
|
|
class TDirectoryCacheDependency extends TCacheDependency |
1071
|
|
|
{ |
1072
|
|
|
private $_recursiveCheck=true; |
1073
|
|
|
private $_recursiveLevel=-1; |
1074
|
|
|
private $_timestamps; |
1075
|
|
|
private $_directory; |
1076
|
|
|
public function __construct($directory) |
1077
|
|
|
{ |
1078
|
|
|
$this->setDirectory($directory); |
1079
|
|
|
} |
1080
|
|
|
public function getDirectory() |
1081
|
|
|
{ |
1082
|
|
|
return $this->_directory; |
1083
|
|
|
} |
1084
|
|
|
public function setDirectory($directory) |
1085
|
|
|
{ |
1086
|
|
|
if(($path=realpath($directory))===false || !is_dir($path)) |
1087
|
|
|
throw new TInvalidDataValueException('directorycachedependency_directory_invalid',$directory); |
1088
|
|
|
$this->_directory=$path; |
1089
|
|
|
$this->_timestamps=$this->generateTimestamps($path); |
1090
|
|
|
} |
1091
|
|
|
public function getRecursiveCheck() |
1092
|
|
|
{ |
1093
|
|
|
return $this->_recursiveCheck; |
1094
|
|
|
} |
1095
|
|
|
public function setRecursiveCheck($value) |
1096
|
|
|
{ |
1097
|
|
|
$this->_recursiveCheck=TPropertyValue::ensureBoolean($value); |
1098
|
|
|
} |
1099
|
|
|
public function getRecursiveLevel() |
1100
|
|
|
{ |
1101
|
|
|
return $this->_recursiveLevel; |
1102
|
|
|
} |
1103
|
|
|
public function setRecursiveLevel($value) |
1104
|
|
|
{ |
1105
|
|
|
$this->_recursiveLevel=TPropertyValue::ensureInteger($value); |
1106
|
|
|
} |
1107
|
|
|
public function getHasChanged() |
1108
|
|
|
{ |
1109
|
|
|
return $this->generateTimestamps($this->_directory)!=$this->_timestamps; |
1110
|
|
|
} |
1111
|
|
|
protected function validateFile($fileName) |
1112
|
|
|
{ |
1113
|
|
|
return true; |
1114
|
|
|
} |
1115
|
|
|
protected function validateDirectory($directory) |
1116
|
|
|
{ |
1117
|
|
|
return true; |
1118
|
|
|
} |
1119
|
|
|
protected function generateTimestamps($directory,$level=0) |
1120
|
|
|
{ |
1121
|
|
|
if(($dir=opendir($directory))===false) |
1122
|
|
|
throw new TIOException('directorycachedependency_directory_invalid',$directory); |
1123
|
|
|
$timestamps=array(); |
1124
|
|
|
while(($file=readdir($dir))!==false) |
1125
|
|
|
{ |
1126
|
|
|
$path=$directory.DIRECTORY_SEPARATOR.$file; |
1127
|
|
|
if($file==='.' || $file==='..') |
1128
|
|
|
continue; |
1129
|
|
|
else if(is_dir($path)) |
1130
|
|
|
{ |
1131
|
|
|
if(($this->_recursiveLevel<0 || $level<$this->_recursiveLevel) && $this->validateDirectory($path)) |
1132
|
|
|
$timestamps=array_merge($this->generateTimestamps($path,$level+1)); |
1133
|
|
|
} |
1134
|
|
|
else if($this->validateFile($path)) |
1135
|
|
|
$timestamps[$path]=filemtime($path); |
1136
|
|
|
} |
1137
|
|
|
closedir($dir); |
1138
|
|
|
return $timestamps; |
1139
|
|
|
} |
1140
|
|
|
} |
1141
|
|
|
class TGlobalStateCacheDependency extends TCacheDependency |
1142
|
|
|
{ |
1143
|
|
|
private $_stateName; |
1144
|
|
|
private $_stateValue; |
1145
|
|
|
public function __construct($name) |
1146
|
|
|
{ |
1147
|
|
|
$this->setStateName($name); |
1148
|
|
|
} |
1149
|
|
|
public function getStateName() |
1150
|
|
|
{ |
1151
|
|
|
return $this->_stateName; |
1152
|
|
|
} |
1153
|
|
|
public function setStateName($value) |
1154
|
|
|
{ |
1155
|
|
|
$this->_stateName=$value; |
1156
|
|
|
$this->_stateValue=Prado::getApplication()->getGlobalState($value); |
1157
|
|
|
} |
1158
|
|
|
public function getHasChanged() |
1159
|
|
|
{ |
1160
|
|
|
return $this->_stateValue!==Prado::getApplication()->getGlobalState($this->_stateName); |
1161
|
|
|
} |
1162
|
|
|
} |
1163
|
|
|
class TChainedCacheDependency extends TCacheDependency |
1164
|
|
|
{ |
1165
|
|
|
private $_dependencies=null; |
1166
|
|
|
public function getDependencies() |
1167
|
|
|
{ |
1168
|
|
|
if($this->_dependencies===null) |
1169
|
|
|
$this->_dependencies=new TCacheDependencyList; |
1170
|
|
|
return $this->_dependencies; |
1171
|
|
|
} |
1172
|
|
|
public function getHasChanged() |
1173
|
|
|
{ |
1174
|
|
|
if($this->_dependencies!==null) |
1175
|
|
|
{ |
1176
|
|
|
foreach($this->_dependencies as $dependency) |
1177
|
|
|
if($dependency->getHasChanged()) |
1178
|
|
|
return true; |
1179
|
|
|
} |
1180
|
|
|
return false; |
1181
|
|
|
} |
1182
|
|
|
} |
1183
|
|
|
class TApplicationStateCacheDependency extends TCacheDependency |
1184
|
|
|
{ |
1185
|
|
|
public function getHasChanged() |
1186
|
|
|
{ |
1187
|
|
|
return Prado::getApplication()->getMode()!==TApplicationMode::Performance; |
1188
|
|
|
} |
1189
|
|
|
} |
1190
|
|
|
class TCacheDependencyList extends TList |
1191
|
|
|
{ |
1192
|
|
|
public function insertAt($index,$item) |
1193
|
|
|
{ |
1194
|
|
|
if($item instanceof ICacheDependency) |
1195
|
|
|
parent::insertAt($index,$item); |
1196
|
|
|
else |
1197
|
|
|
throw new TInvalidDataTypeException('cachedependencylist_cachedependency_required'); |
1198
|
|
|
} |
1199
|
|
|
} |
1200
|
|
|
class TTextWriter extends TComponent implements ITextWriter |
1201
|
|
|
{ |
1202
|
|
|
private $_str=''; |
1203
|
|
|
public function flush() |
1204
|
|
|
{ |
1205
|
|
|
$str=$this->_str; |
1206
|
|
|
$this->_str=''; |
1207
|
|
|
return $str; |
1208
|
|
|
} |
1209
|
|
|
public function write($str) |
1210
|
|
|
{ |
1211
|
|
|
$this->_str.=$str; |
1212
|
|
|
} |
1213
|
|
|
public function writeLine($str='') |
1214
|
|
|
{ |
1215
|
|
|
$this->write($str."\n"); |
1216
|
|
|
} |
1217
|
|
|
} |
1218
|
|
|
class TPriorityList extends TList |
1219
|
|
|
{ |
1220
|
|
|
private $_d=array(); |
|
|
|
|
1221
|
|
|
private $_o=false; |
1222
|
|
|
private $_fd=null; |
1223
|
|
|
private $_c=0; |
|
|
|
|
1224
|
|
|
private $_dp=10; |
1225
|
|
|
private $_p=8; |
1226
|
|
|
public function __construct($data=null,$readOnly=false,$defaultPriority=10,$precision=8) |
1227
|
|
|
{ |
1228
|
|
|
parent::__construct(); |
1229
|
|
|
if($data!==null) |
1230
|
|
|
$this->copyFrom($data); |
1231
|
|
|
$this->setReadOnly($readOnly); |
1232
|
|
|
$this->setPrecision($precision); |
1233
|
|
|
$this->setDefaultPriority($defaultPriority); |
1234
|
|
|
} |
1235
|
|
|
public function count() |
1236
|
|
|
{ |
1237
|
|
|
return $this->getCount(); |
1238
|
|
|
} |
1239
|
|
|
public function getCount() |
1240
|
|
|
{ |
1241
|
|
|
return $this->_c; |
1242
|
|
|
} |
1243
|
|
|
public function getPriorityCount($priority=null) |
1244
|
|
|
{ |
1245
|
|
|
if($priority===null) |
1246
|
|
|
$priority=$this->getDefaultPriority(); |
1247
|
|
|
$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); |
1248
|
|
|
if(!isset($this->_d[$priority]) || !is_array($this->_d[$priority])) |
1249
|
|
|
return false; |
1250
|
|
|
return count($this->_d[$priority]); |
1251
|
|
|
} |
1252
|
|
|
public function getDefaultPriority() |
1253
|
|
|
{ |
1254
|
|
|
return $this->_dp; |
1255
|
|
|
} |
1256
|
|
|
protected function setDefaultPriority($value) |
1257
|
|
|
{ |
1258
|
|
|
$this->_dp=(string)round(TPropertyValue::ensureFloat($value),$this->_p); |
|
|
|
|
1259
|
|
|
} |
1260
|
|
|
public function getPrecision() |
1261
|
|
|
{ |
1262
|
|
|
return $this->_p; |
1263
|
|
|
} |
1264
|
|
|
protected function setPrecision($value) |
1265
|
|
|
{ |
1266
|
|
|
$this->_p=TPropertyValue::ensureInteger($value); |
1267
|
|
|
} |
1268
|
|
|
public function getIterator() |
1269
|
|
|
{ |
1270
|
|
|
return new ArrayIterator($this->flattenPriorities()); |
1271
|
|
|
} |
1272
|
|
|
public function getPriorities() |
1273
|
|
|
{ |
1274
|
|
|
$this->sortPriorities(); |
1275
|
|
|
return array_keys($this->_d); |
1276
|
|
|
} |
1277
|
|
|
protected function sortPriorities() { |
1278
|
|
|
if(!$this->_o) { |
1279
|
|
|
ksort($this->_d,SORT_NUMERIC); |
1280
|
|
|
$this->_o=true; |
1281
|
|
|
} |
1282
|
|
|
} |
1283
|
|
|
protected function flattenPriorities() { |
1284
|
|
|
if(is_array($this->_fd)) |
1285
|
|
|
return $this->_fd; |
1286
|
|
|
$this->sortPriorities(); |
1287
|
|
|
$this->_fd=array(); |
1288
|
|
|
foreach($this->_d as $priority => $itemsatpriority) |
1289
|
|
|
$this->_fd=array_merge($this->_fd,$itemsatpriority); |
1290
|
|
|
return $this->_fd; |
1291
|
|
|
} |
1292
|
|
|
public function itemAt($index) |
1293
|
|
|
{ |
1294
|
|
|
if($index>=0&&$index<$this->getCount()) { |
1295
|
|
|
$arr=$this->flattenPriorities(); |
1296
|
|
|
return $arr[$index]; |
1297
|
|
|
} else |
1298
|
|
|
throw new TInvalidDataValueException('list_index_invalid',$index); |
1299
|
|
|
} |
1300
|
|
|
public function itemsAtPriority($priority=null) |
1301
|
|
|
{ |
1302
|
|
|
if($priority===null) |
1303
|
|
|
$priority=$this->getDefaultPriority(); |
1304
|
|
|
$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); |
1305
|
|
|
return isset($this->_d[$priority])?$this->_d[$priority]:null; |
1306
|
|
|
} |
1307
|
|
|
public function itemAtIndexInPriority($index,$priority=null) |
1308
|
|
|
{ |
1309
|
|
|
if($priority===null) |
1310
|
|
|
$priority=$this->getDefaultPriority(); |
1311
|
|
|
$priority=(string)round(TPropertyValue::ensureFloat($priority), $this->_p); |
1312
|
|
|
return !isset($this->_d[$priority])?false:( |
1313
|
|
|
isset($this->_d[$priority][$index])?$this->_d[$priority][$index]:false |
1314
|
|
|
); |
1315
|
|
|
} |
1316
|
|
|
public function add($item,$priority=null) |
1317
|
|
|
{ |
1318
|
|
|
if($this->getReadOnly()) |
1319
|
|
|
throw new TInvalidOperationException('list_readonly',get_class($this)); |
1320
|
|
|
return $this->insertAtIndexInPriority($item,false,$priority,true); |
1321
|
|
|
} |
1322
|
|
|
public function insertAt($index,$item) |
1323
|
|
|
{ |
1324
|
|
|
if($this->getReadOnly()) |
1325
|
|
|
throw new TInvalidOperationException('list_readonly',get_class($this)); |
1326
|
|
|
if(($priority=$this->priorityAt($index,true))!==false) |
1327
|
|
|
$this->insertAtIndexInPriority($item,$priority[1],$priority[0]); |
1328
|
|
|
else |
1329
|
|
|
throw new TInvalidDataValueException('list_index_invalid',$index); |
1330
|
|
|
} |
1331
|
|
|
public function insertAtIndexInPriority($item,$index=false,$priority=null,$preserveCache=false) |
1332
|
|
|
{ |
1333
|
|
|
if($this->getReadOnly()) |
1334
|
|
|
throw new TInvalidOperationException('list_readonly',get_class($this)); |
1335
|
|
|
if($priority===null) |
1336
|
|
|
$priority=$this->getDefaultPriority(); |
1337
|
|
|
$priority=(string)round(TPropertyValue::ensureFloat($priority), $this->_p); |
1338
|
|
|
if($preserveCache) { |
1339
|
|
|
$this->sortPriorities(); |
1340
|
|
|
$cc=0; |
1341
|
|
|
foreach($this->_d as $prioritykey=>$items) |
1342
|
|
|
if($prioritykey>=$priority) |
1343
|
|
|
break; |
1344
|
|
|
else |
1345
|
|
|
$cc+=count($items); |
1346
|
|
|
if($index===false&&isset($this->_d[$priority])) { |
1347
|
|
|
$c=count($this->_d[$priority]); |
1348
|
|
|
$c+=$cc; |
1349
|
|
|
$this->_d[$priority][]=$item; |
1350
|
|
|
} else if(isset($this->_d[$priority])) { |
1351
|
|
|
$c=$index+$cc; |
1352
|
|
|
array_splice($this->_d[$priority],$index,0,array($item)); |
1353
|
|
|
} else { |
1354
|
|
|
$c = $cc; |
1355
|
|
|
$this->_o = false; |
1356
|
|
|
$this->_d[$priority]=array($item); |
1357
|
|
|
} |
1358
|
|
|
if($this->_fd&&is_array($this->_fd)) array_splice($this->_fd,$c,0,array($item)); |
|
|
|
|
1359
|
|
|
} else { |
1360
|
|
|
$c=null; |
1361
|
|
|
if($index===false&&isset($this->_d[$priority])) { |
1362
|
|
|
$cc=count($this->_d[$priority]); |
1363
|
|
|
$this->_d[$priority][]=$item; |
1364
|
|
|
} else if(isset($this->_d[$priority])) { |
1365
|
|
|
$cc=$index; |
1366
|
|
|
array_splice($this->_d[$priority],$index,0,array($item)); |
1367
|
|
|
} else { |
1368
|
|
|
$cc=0; |
1369
|
|
|
$this->_o=false; |
1370
|
|
|
$this->_d[$priority]=array($item); |
1371
|
|
|
} |
1372
|
|
|
if($this->_fd&&is_array($this->_fd)&&count($this->_d)==1) |
|
|
|
|
1373
|
|
|
array_splice($this->_fd,$cc,0,array($item)); |
1374
|
|
|
else |
1375
|
|
|
$this->_fd=null; |
|
|
|
|
1376
|
|
|
} |
1377
|
|
|
$this->_c++; |
1378
|
|
|
return $c; |
1379
|
|
|
} |
1380
|
|
|
public function remove($item,$priority=false) |
1381
|
|
|
{ |
1382
|
|
|
if($this->getReadOnly()) |
1383
|
|
|
throw new TInvalidOperationException('list_readonly',get_class($this)); |
1384
|
|
|
if(($p=$this->priorityOf($item,true))!==false) |
1385
|
|
|
{ |
1386
|
|
|
if($priority!==false) { |
1387
|
|
|
if($priority===null) |
1388
|
|
|
$priority=$this->getDefaultPriority(); |
1389
|
|
|
$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); |
1390
|
|
|
if($p[0]!=$priority) |
1391
|
|
|
throw new TInvalidDataValueException('list_item_inexistent'); |
1392
|
|
|
} |
1393
|
|
|
$this->removeAtIndexInPriority($p[1],$p[0]); |
1394
|
|
|
return $p[2]; |
1395
|
|
|
} |
1396
|
|
|
else |
1397
|
|
|
throw new TInvalidDataValueException('list_item_inexistent'); |
1398
|
|
|
} |
1399
|
|
|
public function removeAt($index) |
1400
|
|
|
{ |
1401
|
|
|
if($this->getReadOnly()) |
1402
|
|
|
throw new TInvalidOperationException('list_readonly',get_class($this)); |
1403
|
|
|
if(($priority=$this->priorityAt($index, true))!==false) |
1404
|
|
|
return $this->removeAtIndexInPriority($priority[1],$priority[0]); |
1405
|
|
|
throw new TInvalidDataValueException('list_index_invalid',$index); |
1406
|
|
|
} |
1407
|
|
|
public function removeAtIndexInPriority($index, $priority=null) |
1408
|
|
|
{ |
1409
|
|
|
if($this->getReadOnly()) |
1410
|
|
|
throw new TInvalidOperationException('list_readonly',get_class($this)); |
1411
|
|
|
if($priority===null) |
1412
|
|
|
$priority=$this->getDefaultPriority(); |
1413
|
|
|
$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); |
1414
|
|
|
if(!isset($this->_d[$priority])||$index<0||$index>=count($this->_d[$priority])) |
1415
|
|
|
throw new TInvalidDataValueException('list_item_inexistent'); |
1416
|
|
|
$value=array_splice($this->_d[$priority],$index,1); |
1417
|
|
|
$value=$value[0]; |
1418
|
|
|
if(!count($this->_d[$priority])) |
1419
|
|
|
unset($this->_d[$priority]); |
1420
|
|
|
$this->_c--; |
1421
|
|
|
$this->_fd=null; |
|
|
|
|
1422
|
|
|
return $value; |
1423
|
|
|
} |
1424
|
|
|
public function clear() |
1425
|
|
|
{ |
1426
|
|
|
if($this->getReadOnly()) |
1427
|
|
|
throw new TInvalidOperationException('list_readonly',get_class($this)); |
1428
|
|
|
$d=array_reverse($this->_d,true); |
|
|
|
|
1429
|
|
|
foreach($this->_d as $priority=>$items) { |
1430
|
|
|
for($index=count($items)-1;$index>=0;$index--) |
1431
|
|
|
$this->removeAtIndexInPriority($index,$priority); |
1432
|
|
|
unset($this->_d[$priority]); |
1433
|
|
|
} |
1434
|
|
|
} |
1435
|
|
|
public function contains($item) |
1436
|
|
|
{ |
1437
|
|
|
return $this->indexOf($item)>=0; |
1438
|
|
|
} |
1439
|
|
|
public function indexOf($item) |
1440
|
|
|
{ |
1441
|
|
|
if(($index=array_search($item,$this->flattenPriorities(),true))===false) |
1442
|
|
|
return -1; |
1443
|
|
|
else |
1444
|
|
|
return $index; |
1445
|
|
|
} |
1446
|
|
|
public function priorityOf($item,$withindex = false) |
1447
|
|
|
{ |
1448
|
|
|
$this->sortPriorities(); |
1449
|
|
|
$absindex = 0; |
1450
|
|
|
foreach($this->_d as $priority=>$items) { |
1451
|
|
|
if(($index=array_search($item,$items,true))!==false) { |
1452
|
|
|
$absindex+=$index; |
1453
|
|
|
return $withindex?array($priority,$index,$absindex, |
1454
|
|
|
'priority'=>$priority,'index'=>$index,'absindex'=>$absindex):$priority; |
1455
|
|
|
} else |
1456
|
|
|
$absindex+=count($items); |
1457
|
|
|
} |
1458
|
|
|
return false; |
1459
|
|
|
} |
1460
|
|
|
public function priorityAt($index,$withindex = false) |
1461
|
|
|
{ |
1462
|
|
|
if($index<0||$index>=$this->getCount()) |
1463
|
|
|
throw new TInvalidDataValueException('list_index_invalid',$index); |
1464
|
|
|
$absindex=$index; |
1465
|
|
|
$this->sortPriorities(); |
1466
|
|
|
foreach($this->_d as $priority=>$items) { |
1467
|
|
|
if($index>=($c=count($items))) |
1468
|
|
|
$index-=$c; |
1469
|
|
|
else |
1470
|
|
|
return $withindex?array($priority,$index,$absindex, |
1471
|
|
|
'priority'=>$priority,'index'=>$index,'absindex'=>$absindex):$priority; |
1472
|
|
|
} |
1473
|
|
|
return false; |
1474
|
|
|
} |
1475
|
|
|
public function insertBefore($indexitem, $item) |
1476
|
|
|
{ |
1477
|
|
|
if($this->getReadOnly()) |
1478
|
|
|
throw new TInvalidOperationException('list_readonly',get_class($this)); |
1479
|
|
|
if(($priority=$this->priorityOf($indexitem,true))===false) |
1480
|
|
|
throw new TInvalidDataValueException('list_item_inexistent'); |
1481
|
|
|
$this->insertAtIndexInPriority($item,$priority[1],$priority[0]); |
1482
|
|
|
return $priority[2]; |
1483
|
|
|
} |
1484
|
|
|
public function insertAfter($indexitem, $item) |
1485
|
|
|
{ |
1486
|
|
|
if($this->getReadOnly()) |
1487
|
|
|
throw new TInvalidOperationException('list_readonly',get_class($this)); |
1488
|
|
|
if(($priority=$this->priorityOf($indexitem,true))===false) |
1489
|
|
|
throw new TInvalidDataValueException('list_item_inexistent'); |
1490
|
|
|
$this->insertAtIndexInPriority($item,$priority[1]+1,$priority[0]); |
1491
|
|
|
return $priority[2]+1; |
1492
|
|
|
} |
1493
|
|
|
public function toArray() |
1494
|
|
|
{ |
1495
|
|
|
return $this->flattenPriorities(); |
1496
|
|
|
} |
1497
|
|
|
public function toPriorityArray() |
1498
|
|
|
{ |
1499
|
|
|
$this->sortPriorities(); |
1500
|
|
|
return $this->_d; |
1501
|
|
|
} |
1502
|
|
|
public function toArrayBelowPriority($priority,$inclusive=false) |
1503
|
|
|
{ |
1504
|
|
|
$this->sortPriorities(); |
1505
|
|
|
$items=array(); |
1506
|
|
|
foreach($this->_d as $itemspriority=>$itemsatpriority) |
1507
|
|
|
{ |
1508
|
|
|
if((!$inclusive&&$itemspriority>=$priority)||$itemspriority>$priority) |
1509
|
|
|
break; |
1510
|
|
|
$items=array_merge($items,$itemsatpriority); |
1511
|
|
|
} |
1512
|
|
|
return $items; |
1513
|
|
|
} |
1514
|
|
|
public function toArrayAbovePriority($priority,$inclusive=true) |
1515
|
|
|
{ |
1516
|
|
|
$this->sortPriorities(); |
1517
|
|
|
$items=array(); |
1518
|
|
|
foreach($this->_d as $itemspriority=>$itemsatpriority) |
1519
|
|
|
{ |
1520
|
|
|
if((!$inclusive&&$itemspriority<=$priority)||$itemspriority<$priority) |
1521
|
|
|
continue; |
1522
|
|
|
$items=array_merge($items,$itemsatpriority); |
1523
|
|
|
} |
1524
|
|
|
return $items; |
1525
|
|
|
} |
1526
|
|
|
public function copyFrom($data) |
1527
|
|
|
{ |
1528
|
|
|
if($data instanceof TPriorityList) |
1529
|
|
|
{ |
1530
|
|
|
if($this->getCount()>0) |
1531
|
|
|
$this->clear(); |
1532
|
|
|
foreach($data->getPriorities() as $priority) |
1533
|
|
|
{ |
1534
|
|
|
foreach($data->itemsAtPriority($priority) as $index=>$item) |
1535
|
|
|
$this->insertAtIndexInPriority($item,$index,$priority); |
1536
|
|
|
} |
1537
|
|
|
} else if(is_array($data)||$data instanceof Traversable) { |
1538
|
|
|
if($this->getCount()>0) |
1539
|
|
|
$this->clear(); |
1540
|
|
|
foreach($data as $key=>$item) |
1541
|
|
|
$this->add($item); |
1542
|
|
|
} else if($data!==null) |
1543
|
|
|
throw new TInvalidDataTypeException('map_data_not_iterable'); |
1544
|
|
|
} |
1545
|
|
|
public function mergeWith($data) |
1546
|
|
|
{ |
1547
|
|
|
if($data instanceof TPriorityList) |
1548
|
|
|
{ |
1549
|
|
|
foreach($data->getPriorities() as $priority) |
1550
|
|
|
{ |
1551
|
|
|
foreach($data->itemsAtPriority($priority) as $index=>$item) |
1552
|
|
|
$this->insertAtIndexInPriority($item,false,$priority); |
1553
|
|
|
} |
1554
|
|
|
} |
1555
|
|
|
else if(is_array($data)||$data instanceof Traversable) |
1556
|
|
|
{ |
1557
|
|
|
foreach($data as $priority=>$item) |
1558
|
|
|
$this->add($item); |
1559
|
|
|
} |
1560
|
|
|
else if($data!==null) |
1561
|
|
|
throw new TInvalidDataTypeException('map_data_not_iterable'); |
1562
|
|
|
} |
1563
|
|
|
public function offsetExists($offset) |
1564
|
|
|
{ |
1565
|
|
|
return ($offset>=0&&$offset<$this->getCount()); |
1566
|
|
|
} |
1567
|
|
|
public function offsetGet($offset) |
1568
|
|
|
{ |
1569
|
|
|
return $this->itemAt($offset); |
1570
|
|
|
} |
1571
|
|
|
public function offsetSet($offset,$item) |
1572
|
|
|
{ |
1573
|
|
|
if($offset===null) |
1574
|
|
|
return $this->add($item); |
1575
|
|
|
if($offset===$this->getCount()) { |
1576
|
|
|
$priority=$this->priorityAt($offset-1,true); |
1577
|
|
|
$priority[1]++; |
1578
|
|
|
} else { |
1579
|
|
|
$priority=$this->priorityAt($offset,true); |
1580
|
|
|
$this->removeAtIndexInPriority($priority[1],$priority[0]); |
1581
|
|
|
} |
1582
|
|
|
$this->insertAtIndexInPriority($item,$priority[1],$priority[0]); |
1583
|
|
|
} |
1584
|
|
|
public function offsetUnset($offset) |
1585
|
|
|
{ |
1586
|
|
|
$this->removeAt($offset); |
1587
|
|
|
} |
1588
|
|
|
} |
1589
|
|
|
class TMap extends TComponent implements IteratorAggregate,ArrayAccess,Countable |
|
|
|
|
1590
|
|
|
{ |
1591
|
|
|
private $_d=array(); |
1592
|
|
|
private $_r=false; |
1593
|
|
|
protected function _getZappableSleepProps(&$exprops) |
1594
|
|
|
{ |
1595
|
|
|
parent::_getZappableSleepProps($exprops); |
1596
|
|
|
if ($this->_d===array()) |
1597
|
|
|
$exprops[] = "\0TMap\0_d"; |
1598
|
|
|
if ($this->_r===false) |
1599
|
|
|
$exprops[] = "\0TMap\0_r"; |
1600
|
|
|
} |
1601
|
|
|
public function __construct($data=null,$readOnly=false) |
1602
|
|
|
{ |
1603
|
|
|
if($data!==null) |
1604
|
|
|
$this->copyFrom($data); |
1605
|
|
|
$this->setReadOnly($readOnly); |
1606
|
|
|
} |
1607
|
|
|
public function getReadOnly() |
1608
|
|
|
{ |
1609
|
|
|
return $this->_r; |
1610
|
|
|
} |
1611
|
|
|
protected function setReadOnly($value) |
1612
|
|
|
{ |
1613
|
|
|
$this->_r=TPropertyValue::ensureBoolean($value); |
1614
|
|
|
} |
1615
|
|
|
public function getIterator() |
1616
|
|
|
{ |
1617
|
|
|
return new ArrayIterator( $this->_d ); |
1618
|
|
|
} |
1619
|
|
|
public function count() |
1620
|
|
|
{ |
1621
|
|
|
return $this->getCount(); |
1622
|
|
|
} |
1623
|
|
|
public function getCount() |
1624
|
|
|
{ |
1625
|
|
|
return count($this->_d); |
1626
|
|
|
} |
1627
|
|
|
public function getKeys() |
1628
|
|
|
{ |
1629
|
|
|
return array_keys($this->_d); |
1630
|
|
|
} |
1631
|
|
|
public function itemAt($key) |
1632
|
|
|
{ |
1633
|
|
|
return isset($this->_d[$key]) ? $this->_d[$key] : null; |
1634
|
|
|
} |
1635
|
|
|
public function add($key,$value) |
1636
|
|
|
{ |
1637
|
|
|
if(!$this->_r) |
1638
|
|
|
$this->_d[$key]=$value; |
1639
|
|
|
else |
1640
|
|
|
throw new TInvalidOperationException('map_readonly',get_class($this)); |
1641
|
|
|
} |
1642
|
|
|
public function remove($key) |
1643
|
|
|
{ |
1644
|
|
|
if(!$this->_r) |
1645
|
|
|
{ |
1646
|
|
|
if(isset($this->_d[$key]) || array_key_exists($key,$this->_d)) |
1647
|
|
|
{ |
1648
|
|
|
$value=$this->_d[$key]; |
1649
|
|
|
unset($this->_d[$key]); |
1650
|
|
|
return $value; |
1651
|
|
|
} |
1652
|
|
|
else |
1653
|
|
|
return null; |
1654
|
|
|
} |
1655
|
|
|
else |
1656
|
|
|
throw new TInvalidOperationException('map_readonly',get_class($this)); |
1657
|
|
|
} |
1658
|
|
|
public function clear() |
1659
|
|
|
{ |
1660
|
|
|
foreach(array_keys($this->_d) as $key) |
1661
|
|
|
$this->remove($key); |
1662
|
|
|
} |
1663
|
|
|
public function contains($key) |
1664
|
|
|
{ |
1665
|
|
|
return isset($this->_d[$key]) || array_key_exists($key,$this->_d); |
1666
|
|
|
} |
1667
|
|
|
public function toArray() |
1668
|
|
|
{ |
1669
|
|
|
return $this->_d; |
1670
|
|
|
} |
1671
|
|
|
public function copyFrom($data) |
1672
|
|
|
{ |
1673
|
|
|
if(is_array($data) || $data instanceof Traversable) |
1674
|
|
|
{ |
1675
|
|
|
if($this->getCount()>0) |
1676
|
|
|
$this->clear(); |
1677
|
|
|
foreach($data as $key=>$value) |
1678
|
|
|
$this->add($key,$value); |
1679
|
|
|
} |
1680
|
|
|
else if($data!==null) |
1681
|
|
|
throw new TInvalidDataTypeException('map_data_not_iterable'); |
1682
|
|
|
} |
1683
|
|
|
public function mergeWith($data) |
1684
|
|
|
{ |
1685
|
|
|
if(is_array($data) || $data instanceof Traversable) |
1686
|
|
|
{ |
1687
|
|
|
foreach($data as $key=>$value) |
1688
|
|
|
$this->add($key,$value); |
1689
|
|
|
} |
1690
|
|
|
else if($data!==null) |
1691
|
|
|
throw new TInvalidDataTypeException('map_data_not_iterable'); |
1692
|
|
|
} |
1693
|
|
|
public function offsetExists($offset) |
1694
|
|
|
{ |
1695
|
|
|
return $this->contains($offset); |
1696
|
|
|
} |
1697
|
|
|
public function offsetGet($offset) |
1698
|
|
|
{ |
1699
|
|
|
return $this->itemAt($offset); |
1700
|
|
|
} |
1701
|
|
|
public function offsetSet($offset,$item) |
1702
|
|
|
{ |
1703
|
|
|
$this->add($offset,$item); |
1704
|
|
|
} |
1705
|
|
|
public function offsetUnset($offset) |
1706
|
|
|
{ |
1707
|
|
|
$this->remove($offset); |
1708
|
|
|
} |
1709
|
|
|
} |
1710
|
|
|
class TMapIterator extends ArrayIterator |
1711
|
|
|
{ |
1712
|
|
|
} |
1713
|
|
|
class TPriorityMap extends TMap |
1714
|
|
|
{ |
1715
|
|
|
private $_d=array(); |
|
|
|
|
1716
|
|
|
private $_r=false; |
|
|
|
|
1717
|
|
|
private $_o=false; |
1718
|
|
|
private $_fd=null; |
1719
|
|
|
private $_c=0; |
1720
|
|
|
private $_dp=10; |
1721
|
|
|
private $_p=8; |
1722
|
|
|
public function __construct($data=null,$readOnly=false,$defaultPriority=10,$precision=8) |
1723
|
|
|
{ |
1724
|
|
|
if($data!==null) |
1725
|
|
|
$this->copyFrom($data); |
1726
|
|
|
$this->setReadOnly($readOnly); |
1727
|
|
|
$this->setPrecision($precision); |
1728
|
|
|
$this->setDefaultPriority($defaultPriority); |
1729
|
|
|
} |
1730
|
|
|
public function getReadOnly() |
1731
|
|
|
{ |
1732
|
|
|
return $this->_r; |
1733
|
|
|
} |
1734
|
|
|
protected function setReadOnly($value) |
1735
|
|
|
{ |
1736
|
|
|
$this->_r=TPropertyValue::ensureBoolean($value); |
1737
|
|
|
} |
1738
|
|
|
public function getDefaultPriority() |
1739
|
|
|
{ |
1740
|
|
|
return $this->_dp; |
1741
|
|
|
} |
1742
|
|
|
protected function setDefaultPriority($value) |
1743
|
|
|
{ |
1744
|
|
|
$this->_dp = (string)round(TPropertyValue::ensureFloat($value), $this->_p); |
|
|
|
|
1745
|
|
|
} |
1746
|
|
|
public function getPrecision() |
1747
|
|
|
{ |
1748
|
|
|
return $this->_p; |
1749
|
|
|
} |
1750
|
|
|
protected function setPrecision($value) |
1751
|
|
|
{ |
1752
|
|
|
$this->_p=TPropertyValue::ensureInteger($value); |
1753
|
|
|
} |
1754
|
|
|
public function getIterator() |
1755
|
|
|
{ |
1756
|
|
|
return new ArrayIterator($this->flattenPriorities()); |
1757
|
|
|
} |
1758
|
|
|
protected function sortPriorities() { |
1759
|
|
|
if(!$this->_o) { |
1760
|
|
|
ksort($this->_d, SORT_NUMERIC); |
1761
|
|
|
$this->_o=true; |
1762
|
|
|
} |
1763
|
|
|
} |
1764
|
|
|
protected function flattenPriorities() { |
1765
|
|
|
if(is_array($this->_fd)) |
1766
|
|
|
return $this->_fd; |
1767
|
|
|
$this->sortPriorities(); |
1768
|
|
|
$this->_fd = array(); |
1769
|
|
|
foreach($this->_d as $priority => $itemsatpriority) |
1770
|
|
|
$this->_fd = array_merge($this->_fd, $itemsatpriority); |
1771
|
|
|
return $this->_fd; |
1772
|
|
|
} |
1773
|
|
|
public function count() |
1774
|
|
|
{ |
1775
|
|
|
return $this->getCount(); |
1776
|
|
|
} |
1777
|
|
|
public function getCount() |
1778
|
|
|
{ |
1779
|
|
|
return $this->_c; |
1780
|
|
|
} |
1781
|
|
|
public function getPriorityCount($priority=null) |
1782
|
|
|
{ |
1783
|
|
|
if($priority===null) |
1784
|
|
|
$priority=$this->getDefaultPriority(); |
1785
|
|
|
$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); |
1786
|
|
|
if(!isset($this->_d[$priority])||!is_array($this->_d[$priority])) |
1787
|
|
|
return false; |
1788
|
|
|
return count($this->_d[$priority]); |
1789
|
|
|
} |
1790
|
|
|
public function getPriorities() |
1791
|
|
|
{ |
1792
|
|
|
$this->sortPriorities(); |
1793
|
|
|
return array_keys($this->_d); |
1794
|
|
|
} |
1795
|
|
|
public function getKeys() |
1796
|
|
|
{ |
1797
|
|
|
return array_keys($this->flattenPriorities()); |
1798
|
|
|
} |
1799
|
|
|
public function itemAt($key,$priority=false) |
1800
|
|
|
{ |
1801
|
|
|
if($priority===false){ |
1802
|
|
|
$map=$this->flattenPriorities(); |
1803
|
|
|
return isset($map[$key])?$map[$key]:null; |
1804
|
|
|
} else { |
1805
|
|
|
if($priority===null) |
1806
|
|
|
$priority=$this->getDefaultPriority(); |
1807
|
|
|
$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); |
1808
|
|
|
return (isset($this->_d[$priority])&&isset($this->_d[$priority][$key]))?$this->_d[$priority][$key]:null; |
1809
|
|
|
} |
1810
|
|
|
} |
1811
|
|
|
public function setPriorityAt($key,$priority=null) |
1812
|
|
|
{ |
1813
|
|
|
if($priority===null) |
1814
|
|
|
$priority=$this->getDefaultPriority(); |
1815
|
|
|
$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); |
1816
|
|
|
$oldpriority=$this->priorityAt($key); |
1817
|
|
|
if($oldpriority!==false&&$oldpriority!=$priority) { |
1818
|
|
|
$value=$this->remove($key,$oldpriority); |
1819
|
|
|
$this->add($key,$value,$priority); |
1820
|
|
|
} |
1821
|
|
|
return $oldpriority; |
1822
|
|
|
} |
1823
|
|
|
public function itemsAtPriority($priority=null) |
1824
|
|
|
{ |
1825
|
|
|
if($priority===null) |
1826
|
|
|
$priority=$this->getDefaultPriority(); |
1827
|
|
|
$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); |
1828
|
|
|
return isset($this->_d[$priority])?$this->_d[$priority]:null; |
1829
|
|
|
} |
1830
|
|
|
public function priorityOf($item) |
1831
|
|
|
{ |
1832
|
|
|
$this->sortPriorities(); |
1833
|
|
|
foreach($this->_d as $priority=>$items) |
1834
|
|
|
if(($index=array_search($item,$items,true))!==false) |
1835
|
|
|
return $priority; |
1836
|
|
|
return false; |
1837
|
|
|
} |
1838
|
|
|
public function priorityAt($key) |
1839
|
|
|
{ |
1840
|
|
|
$this->sortPriorities(); |
1841
|
|
|
foreach($this->_d as $priority=>$items) |
1842
|
|
|
if(array_key_exists($key,$items)) |
1843
|
|
|
return $priority; |
1844
|
|
|
return false; |
1845
|
|
|
} |
1846
|
|
|
public function add($key,$value,$priority=null) |
1847
|
|
|
{ |
1848
|
|
|
if($priority===null) |
1849
|
|
|
$priority=$this->getDefaultPriority(); |
1850
|
|
|
$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); |
1851
|
|
|
if(!$this->_r) |
1852
|
|
|
{ |
1853
|
|
|
foreach($this->_d as $innerpriority=>$items) |
1854
|
|
|
if(array_key_exists($key,$items)) |
1855
|
|
|
{ |
1856
|
|
|
unset($this->_d[$innerpriority][$key]); |
1857
|
|
|
$this->_c--; |
1858
|
|
|
if(count($this->_d[$innerpriority])===0) |
1859
|
|
|
unset($this->_d[$innerpriority]); |
1860
|
|
|
} |
1861
|
|
|
if(!isset($this->_d[$priority])) { |
1862
|
|
|
$this->_d[$priority]=array($key=>$value); |
1863
|
|
|
$this->_o=false; |
1864
|
|
|
} |
1865
|
|
|
else |
1866
|
|
|
$this->_d[$priority][$key]=$value; |
1867
|
|
|
$this->_c++; |
1868
|
|
|
$this->_fd=null; |
|
|
|
|
1869
|
|
|
} |
1870
|
|
|
else |
1871
|
|
|
throw new TInvalidOperationException('map_readonly',get_class($this)); |
1872
|
|
|
return $priority; |
1873
|
|
|
} |
1874
|
|
|
public function remove($key,$priority=false) |
1875
|
|
|
{ |
1876
|
|
|
if(!$this->_r) |
1877
|
|
|
{ |
1878
|
|
|
if($priority===null) |
1879
|
|
|
$priority=$this->getDefaultPriority(); |
1880
|
|
|
if($priority===false) |
1881
|
|
|
{ |
1882
|
|
|
$this->sortPriorities(); |
1883
|
|
|
foreach($this->_d as $priority=>$items) |
1884
|
|
|
if(array_key_exists($key,$items)) |
1885
|
|
|
{ |
1886
|
|
|
$value=$this->_d[$priority][$key]; |
1887
|
|
|
unset($this->_d[$priority][$key]); |
1888
|
|
|
$this->_c--; |
1889
|
|
|
if(count($this->_d[$priority])===0) |
1890
|
|
|
{ |
1891
|
|
|
unset($this->_d[$priority]); |
1892
|
|
|
$this->_o=false; |
1893
|
|
|
} |
1894
|
|
|
$this->_fd=null; |
|
|
|
|
1895
|
|
|
return $value; |
1896
|
|
|
} |
1897
|
|
|
return null; |
1898
|
|
|
} |
1899
|
|
|
else |
1900
|
|
|
{ |
1901
|
|
|
$priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p); |
1902
|
|
|
if(isset($this->_d[$priority])&&(isset($this->_d[$priority][$key])||array_key_exists($key,$this->_d[$priority]))) |
1903
|
|
|
{ |
1904
|
|
|
$value=$this->_d[$priority][$key]; |
1905
|
|
|
unset($this->_d[$priority][$key]); |
1906
|
|
|
$this->_c--; |
1907
|
|
|
if(count($this->_d[$priority])===0) { |
1908
|
|
|
unset($this->_d[$priority]); |
1909
|
|
|
$this->_o=false; |
1910
|
|
|
} |
1911
|
|
|
$this->_fd=null; |
1912
|
|
|
return $value; |
1913
|
|
|
} |
1914
|
|
|
else |
1915
|
|
|
return null; |
1916
|
|
|
} |
1917
|
|
|
} |
1918
|
|
|
else |
1919
|
|
|
throw new TInvalidOperationException('map_readonly',get_class($this)); |
1920
|
|
|
} |
1921
|
|
|
public function clear() |
1922
|
|
|
{ |
1923
|
|
|
foreach($this->_d as $priority=>$items) |
1924
|
|
|
foreach(array_keys($items) as $key) |
1925
|
|
|
$this->remove($key); |
1926
|
|
|
} |
1927
|
|
|
public function contains($key) |
1928
|
|
|
{ |
1929
|
|
|
$map=$this->flattenPriorities(); |
1930
|
|
|
return isset($map[$key])||array_key_exists($key,$map); |
1931
|
|
|
} |
1932
|
|
|
public function toArray() |
1933
|
|
|
{ |
1934
|
|
|
return $this->flattenPriorities(); |
1935
|
|
|
} |
1936
|
|
|
public function toArrayBelowPriority($priority,$inclusive=false) |
1937
|
|
|
{ |
1938
|
|
|
$this->sortPriorities(); |
1939
|
|
|
$items=array(); |
1940
|
|
|
foreach($this->_d as $itemspriority=>$itemsatpriority) |
1941
|
|
|
{ |
1942
|
|
|
if((!$inclusive&&$itemspriority>=$priority)||$itemspriority>$priority) |
1943
|
|
|
break; |
1944
|
|
|
$items=array_merge($items,$itemsatpriority); |
1945
|
|
|
} |
1946
|
|
|
return $items; |
1947
|
|
|
} |
1948
|
|
|
public function toArrayAbovePriority($priority,$inclusive=true) |
1949
|
|
|
{ |
1950
|
|
|
$this->sortPriorities(); |
1951
|
|
|
$items=array(); |
1952
|
|
|
foreach($this->_d as $itemspriority=>$itemsatpriority) |
1953
|
|
|
{ |
1954
|
|
|
if((!$inclusive&&$itemspriority<=$priority)||$itemspriority<$priority) |
1955
|
|
|
continue; |
1956
|
|
|
$items=array_merge($items,$itemsatpriority); |
1957
|
|
|
} |
1958
|
|
|
return $items; |
1959
|
|
|
} |
1960
|
|
|
public function copyFrom($data) |
1961
|
|
|
{ |
1962
|
|
|
if($data instanceof TPriorityMap) |
1963
|
|
|
{ |
1964
|
|
|
if($this->getCount()>0) |
1965
|
|
|
$this->clear(); |
1966
|
|
|
foreach($data->getPriorities() as $priority) { |
1967
|
|
|
foreach($data->itemsAtPriority($priority) as $key => $value) { |
1968
|
|
|
$this->add($key,$value,$priority); |
1969
|
|
|
} |
1970
|
|
|
} |
1971
|
|
|
} |
1972
|
|
|
else if(is_array($data)||$data instanceof Traversable) |
1973
|
|
|
{ |
1974
|
|
|
if($this->getCount()>0) |
1975
|
|
|
$this->clear(); |
1976
|
|
|
foreach($data as $key=>$value) |
1977
|
|
|
$this->add($key,$value); |
1978
|
|
|
} |
1979
|
|
|
else if($data!==null) |
1980
|
|
|
throw new TInvalidDataTypeException('map_data_not_iterable'); |
1981
|
|
|
} |
1982
|
|
|
public function mergeWith($data) |
1983
|
|
|
{ |
1984
|
|
|
if($data instanceof TPriorityMap) |
1985
|
|
|
{ |
1986
|
|
|
foreach($data->getPriorities() as $priority) |
1987
|
|
|
{ |
1988
|
|
|
foreach($data->itemsAtPriority($priority) as $key => $value) |
1989
|
|
|
$this->add($key,$value,$priority); |
1990
|
|
|
} |
1991
|
|
|
} |
1992
|
|
|
else if(is_array($data)||$data instanceof Traversable) |
1993
|
|
|
{ |
1994
|
|
|
foreach($data as $key=>$value) |
1995
|
|
|
$this->add($key,$value); |
1996
|
|
|
} |
1997
|
|
|
else if($data!==null) |
1998
|
|
|
throw new TInvalidDataTypeException('map_data_not_iterable'); |
1999
|
|
|
} |
2000
|
|
|
public function offsetExists($offset) |
2001
|
|
|
{ |
2002
|
|
|
return $this->contains($offset); |
2003
|
|
|
} |
2004
|
|
|
public function offsetGet($offset) |
2005
|
|
|
{ |
2006
|
|
|
return $this->itemAt($offset); |
2007
|
|
|
} |
2008
|
|
|
public function offsetSet($offset,$item) |
2009
|
|
|
{ |
2010
|
|
|
$this->add($offset,$item); |
2011
|
|
|
} |
2012
|
|
|
public function offsetUnset($offset) |
2013
|
|
|
{ |
2014
|
|
|
$this->remove($offset); |
2015
|
|
|
} |
2016
|
|
|
} |
2017
|
|
|
class TStack extends TComponent implements IteratorAggregate,Countable |
|
|
|
|
2018
|
|
|
{ |
2019
|
|
|
private $_d=array(); |
2020
|
|
|
private $_c=0; |
2021
|
|
|
public function __construct($data=null) |
2022
|
|
|
{ |
2023
|
|
|
if($data!==null) |
2024
|
|
|
$this->copyFrom($data); |
2025
|
|
|
} |
2026
|
|
|
public function toArray() |
2027
|
|
|
{ |
2028
|
|
|
return $this->_d; |
2029
|
|
|
} |
2030
|
|
|
public function copyFrom($data) |
2031
|
|
|
{ |
2032
|
|
|
if(is_array($data) || ($data instanceof Traversable)) |
2033
|
|
|
{ |
2034
|
|
|
$this->clear(); |
2035
|
|
|
foreach($data as $item) |
2036
|
|
|
{ |
2037
|
|
|
$this->_d[]=$item; |
2038
|
|
|
++$this->_c; |
2039
|
|
|
} |
2040
|
|
|
} |
2041
|
|
|
else if($data!==null) |
2042
|
|
|
throw new TInvalidDataTypeException('stack_data_not_iterable'); |
2043
|
|
|
} |
2044
|
|
|
public function clear() |
2045
|
|
|
{ |
2046
|
|
|
$this->_c=0; |
2047
|
|
|
$this->_d=array(); |
2048
|
|
|
} |
2049
|
|
|
public function contains($item) |
2050
|
|
|
{ |
2051
|
|
|
return array_search($item,$this->_d,true)!==false; |
2052
|
|
|
} |
2053
|
|
|
public function peek() |
2054
|
|
|
{ |
2055
|
|
|
if($this->_c===0) |
2056
|
|
|
throw new TInvalidOperationException('stack_empty'); |
2057
|
|
|
else |
2058
|
|
|
return $this->_d[$this->_c-1]; |
2059
|
|
|
} |
2060
|
|
|
public function pop() |
2061
|
|
|
{ |
2062
|
|
|
if($this->_c===0) |
2063
|
|
|
throw new TInvalidOperationException('stack_empty'); |
2064
|
|
|
else |
2065
|
|
|
{ |
2066
|
|
|
--$this->_c; |
2067
|
|
|
return array_pop($this->_d); |
2068
|
|
|
} |
2069
|
|
|
} |
2070
|
|
|
public function push($item) |
2071
|
|
|
{ |
2072
|
|
|
++$this->_c; |
2073
|
|
|
$this->_d[] = $item; |
2074
|
|
|
} |
2075
|
|
|
public function getIterator() |
2076
|
|
|
{ |
2077
|
|
|
return new ArrayIterator( $this->_d ); |
2078
|
|
|
} |
2079
|
|
|
public function getCount() |
2080
|
|
|
{ |
2081
|
|
|
return $this->_c; |
2082
|
|
|
} |
2083
|
|
|
public function count() |
2084
|
|
|
{ |
2085
|
|
|
return $this->getCount(); |
2086
|
|
|
} |
2087
|
|
|
} |
2088
|
|
|
class TStackIterator implements Iterator |
2089
|
|
|
{ |
2090
|
|
|
private $_d; |
2091
|
|
|
private $_i; |
2092
|
|
|
private $_c; |
2093
|
|
|
public function __construct(&$data) |
2094
|
|
|
{ |
2095
|
|
|
$this->_d=&$data; |
2096
|
|
|
$this->_i=0; |
2097
|
|
|
$this->_c=count($this->_d); |
2098
|
|
|
} |
2099
|
|
|
public function rewind() |
2100
|
|
|
{ |
2101
|
|
|
$this->_i=0; |
2102
|
|
|
} |
2103
|
|
|
public function key() |
2104
|
|
|
{ |
2105
|
|
|
return $this->_i; |
2106
|
|
|
} |
2107
|
|
|
public function current() |
2108
|
|
|
{ |
2109
|
|
|
return $this->_d[$this->_i]; |
2110
|
|
|
} |
2111
|
|
|
public function next() |
2112
|
|
|
{ |
2113
|
|
|
$this->_i++; |
2114
|
|
|
} |
2115
|
|
|
public function valid() |
2116
|
|
|
{ |
2117
|
|
|
return $this->_i<$this->_c; |
2118
|
|
|
} |
2119
|
|
|
} |
2120
|
|
|
class TXmlElement extends TComponent |
2121
|
|
|
{ |
2122
|
|
|
private $_parent=null; |
2123
|
|
|
private $_tagName='unknown'; |
2124
|
|
|
private $_value=''; |
2125
|
|
|
private $_elements=null; |
2126
|
|
|
private $_attributes=null; |
2127
|
|
|
public function __construct($tagName) |
2128
|
|
|
{ |
2129
|
|
|
$this->setTagName($tagName); |
2130
|
|
|
} |
2131
|
|
|
public function getParent() |
2132
|
|
|
{ |
2133
|
|
|
return $this->_parent; |
2134
|
|
|
} |
2135
|
|
|
public function setParent($parent) |
2136
|
|
|
{ |
2137
|
|
|
$this->_parent=$parent; |
2138
|
|
|
} |
2139
|
|
|
public function getTagName() |
2140
|
|
|
{ |
2141
|
|
|
return $this->_tagName; |
2142
|
|
|
} |
2143
|
|
|
public function setTagName($tagName) |
2144
|
|
|
{ |
2145
|
|
|
$this->_tagName=$tagName; |
2146
|
|
|
} |
2147
|
|
|
public function getValue() |
2148
|
|
|
{ |
2149
|
|
|
return $this->_value; |
2150
|
|
|
} |
2151
|
|
|
public function setValue($value) |
2152
|
|
|
{ |
2153
|
|
|
$this->_value=TPropertyValue::ensureString($value); |
2154
|
|
|
} |
2155
|
|
|
public function getHasElement() |
2156
|
|
|
{ |
2157
|
|
|
return $this->_elements!==null && $this->_elements->getCount()>0; |
2158
|
|
|
} |
2159
|
|
|
public function getHasAttribute() |
2160
|
|
|
{ |
2161
|
|
|
return $this->_attributes!==null && $this->_attributes->getCount()>0; |
2162
|
|
|
} |
2163
|
|
|
public function getAttribute($name) |
2164
|
|
|
{ |
2165
|
|
|
if($this->_attributes!==null) |
2166
|
|
|
return $this->_attributes->itemAt($name); |
2167
|
|
|
else |
2168
|
|
|
return null; |
2169
|
|
|
} |
2170
|
|
|
public function setAttribute($name,$value) |
2171
|
|
|
{ |
2172
|
|
|
$this->getAttributes()->add($name,TPropertyValue::ensureString($value)); |
2173
|
|
|
} |
2174
|
|
|
public function getElements() |
2175
|
|
|
{ |
2176
|
|
|
if(!$this->_elements) |
2177
|
|
|
$this->_elements=new TXmlElementList($this); |
2178
|
|
|
return $this->_elements; |
2179
|
|
|
} |
2180
|
|
|
public function getAttributes() |
2181
|
|
|
{ |
2182
|
|
|
if(!$this->_attributes) |
2183
|
|
|
$this->_attributes=new TMap; |
2184
|
|
|
return $this->_attributes; |
2185
|
|
|
} |
2186
|
|
|
public function getElementByTagName($tagName) |
2187
|
|
|
{ |
2188
|
|
|
if($this->_elements) |
2189
|
|
|
{ |
2190
|
|
|
foreach($this->_elements as $element) |
2191
|
|
|
if($element->_tagName===$tagName) |
2192
|
|
|
return $element; |
2193
|
|
|
} |
2194
|
|
|
return null; |
2195
|
|
|
} |
2196
|
|
|
public function getElementsByTagName($tagName) |
2197
|
|
|
{ |
2198
|
|
|
$list=new TList; |
2199
|
|
|
if($this->_elements) |
2200
|
|
|
{ |
2201
|
|
|
foreach($this->_elements as $element) |
2202
|
|
|
if($element->_tagName===$tagName) |
2203
|
|
|
$list->add($element); |
2204
|
|
|
} |
2205
|
|
|
return $list; |
2206
|
|
|
} |
2207
|
|
|
public function toString($indent=0) |
2208
|
|
|
{ |
2209
|
|
|
$attr=''; |
2210
|
|
|
if($this->_attributes!==null) |
2211
|
|
|
{ |
2212
|
|
|
foreach($this->_attributes as $name=>$value) |
2213
|
|
|
{ |
2214
|
|
|
$value=$this->xmlEncode($value); |
2215
|
|
|
$attr.=" $name=\"$value\""; |
2216
|
|
|
} |
2217
|
|
|
} |
2218
|
|
|
$prefix=str_repeat(' ',$indent*4); |
2219
|
|
|
if($this->getHasElement()) |
2220
|
|
|
{ |
2221
|
|
|
$str=$prefix."<{$this->_tagName}$attr>\n"; |
2222
|
|
|
foreach($this->getElements() as $element) |
2223
|
|
|
$str.=$element->toString($indent+1)."\n"; |
2224
|
|
|
$str.=$prefix."</{$this->_tagName}>"; |
2225
|
|
|
return $str; |
2226
|
|
|
} |
2227
|
|
|
else if(($value=$this->getValue())!=='') |
2228
|
|
|
{ |
2229
|
|
|
$value=$this->xmlEncode($value); |
2230
|
|
|
return $prefix."<{$this->_tagName}$attr>$value</{$this->_tagName}>"; |
2231
|
|
|
} |
2232
|
|
|
else |
2233
|
|
|
return $prefix."<{$this->_tagName}$attr />"; |
2234
|
|
|
} |
2235
|
|
|
public function __toString() |
2236
|
|
|
{ |
2237
|
|
|
return $this->toString(); |
2238
|
|
|
} |
2239
|
|
|
private function xmlEncode($str) |
2240
|
|
|
{ |
2241
|
|
|
return strtr($str,array( |
2242
|
|
|
'>'=>'>', |
2243
|
|
|
'<'=>'<', |
2244
|
|
|
'&'=>'&', |
2245
|
|
|
'"'=>'"', |
2246
|
|
|
"\r"=>'
', |
2247
|
|
|
"\t"=>'	', |
2248
|
|
|
"\n"=>'
')); |
2249
|
|
|
} |
2250
|
|
|
} |
2251
|
|
|
class TXmlDocument extends TXmlElement |
2252
|
|
|
{ |
2253
|
|
|
private $_version; |
2254
|
|
|
private $_encoding; |
2255
|
|
|
public function __construct($version='1.0',$encoding='') |
2256
|
|
|
{ |
2257
|
|
|
parent::__construct(''); |
2258
|
|
|
$this->setVersion($version); |
2259
|
|
|
$this->setEncoding($encoding); |
2260
|
|
|
} |
2261
|
|
|
public function getVersion() |
2262
|
|
|
{ |
2263
|
|
|
return $this->_version; |
2264
|
|
|
} |
2265
|
|
|
public function setVersion($version) |
2266
|
|
|
{ |
2267
|
|
|
$this->_version=$version; |
2268
|
|
|
} |
2269
|
|
|
public function getEncoding() |
2270
|
|
|
{ |
2271
|
|
|
return $this->_encoding; |
2272
|
|
|
} |
2273
|
|
|
public function setEncoding($encoding) |
2274
|
|
|
{ |
2275
|
|
|
$this->_encoding=$encoding; |
2276
|
|
|
} |
2277
|
|
|
public function loadFromFile($file) |
2278
|
|
|
{ |
2279
|
|
|
if(($str=@file_get_contents($file))!==false) |
2280
|
|
|
return $this->loadFromString($str); |
2281
|
|
|
else |
2282
|
|
|
throw new TIOException('xmldocument_file_read_failed',$file); |
2283
|
|
|
} |
2284
|
|
|
public function loadFromString($string) |
2285
|
|
|
{ |
2286
|
|
|
$doc=new DOMDocument(); |
2287
|
|
|
if($doc->loadXML($string)===false) |
2288
|
|
|
return false; |
2289
|
|
|
$this->setEncoding($doc->encoding); |
2290
|
|
|
$this->setVersion($doc->xmlVersion); |
2291
|
|
|
$element=$doc->documentElement; |
2292
|
|
|
$this->setTagName($element->tagName); |
2293
|
|
|
$this->setValue($element->nodeValue); |
2294
|
|
|
$elements=$this->getElements(); |
2295
|
|
|
$attributes=$this->getAttributes(); |
2296
|
|
|
$elements->clear(); |
2297
|
|
|
$attributes->clear(); |
2298
|
|
|
static $bSimpleXml; |
2299
|
|
|
if($bSimpleXml === null) |
2300
|
|
|
$bSimpleXml = (boolean)function_exists('simplexml_load_string'); |
2301
|
|
|
if($bSimpleXml) |
2302
|
|
|
{ |
2303
|
|
|
$simpleDoc = simplexml_load_string($string); |
2304
|
|
|
$docNamespaces = $simpleDoc->getDocNamespaces(false); |
2305
|
|
|
$simpleDoc = null; |
|
|
|
|
2306
|
|
|
foreach($docNamespaces as $prefix => $uri) |
2307
|
|
|
{ |
2308
|
|
|
if($prefix === '') |
2309
|
|
|
$attributes->add('xmlns', $uri); |
2310
|
|
|
else |
2311
|
|
|
$attributes->add('xmlns:'.$prefix, $uri); |
2312
|
|
|
} |
2313
|
|
|
} |
2314
|
|
|
foreach($element->attributes as $name=>$attr) |
2315
|
|
|
$attributes->add(($attr->prefix === '' ? '' : $attr->prefix . ':') .$name,$attr->value); |
2316
|
|
|
foreach($element->childNodes as $child) |
2317
|
|
|
{ |
2318
|
|
|
if($child instanceof DOMElement) |
2319
|
|
|
$elements->add($this->buildElement($child)); |
2320
|
|
|
} |
2321
|
|
|
return true; |
2322
|
|
|
} |
2323
|
|
|
public function saveToFile($file) |
2324
|
|
|
{ |
2325
|
|
|
if(($fw=fopen($file,'w'))!==false) |
2326
|
|
|
{ |
2327
|
|
|
fwrite($fw,$this->saveToString()); |
2328
|
|
|
fclose($fw); |
2329
|
|
|
} |
2330
|
|
|
else |
2331
|
|
|
throw new TIOException('xmldocument_file_write_failed',$file); |
2332
|
|
|
} |
2333
|
|
|
public function saveToString() |
2334
|
|
|
{ |
2335
|
|
|
$version=empty($this->_version)?' version="1.0"':' version="'.$this->_version.'"'; |
2336
|
|
|
$encoding=empty($this->_encoding)?'':' encoding="'.$this->_encoding.'"'; |
2337
|
|
|
return "<?xml{$version}{$encoding}?>\n".$this->toString(0); |
2338
|
|
|
} |
2339
|
|
|
public function __toString() |
2340
|
|
|
{ |
2341
|
|
|
return $this->saveToString(); |
2342
|
|
|
} |
2343
|
|
|
protected function buildElement($node) |
2344
|
|
|
{ |
2345
|
|
|
$element=new TXmlElement($node->tagName); |
2346
|
|
|
$element->setValue($node->nodeValue); |
2347
|
|
|
foreach($node->attributes as $name=>$attr) |
2348
|
|
|
$element->getAttributes()->add(($attr->prefix === '' ? '' : $attr->prefix . ':') . $name,$attr->value); |
2349
|
|
|
foreach($node->childNodes as $child) |
2350
|
|
|
{ |
2351
|
|
|
if($child instanceof DOMElement) |
2352
|
|
|
$element->getElements()->add($this->buildElement($child)); |
2353
|
|
|
} |
2354
|
|
|
return $element; |
2355
|
|
|
} |
2356
|
|
|
} |
2357
|
|
|
class TXmlElementList extends TList |
2358
|
|
|
{ |
2359
|
|
|
private $_o; |
2360
|
|
|
public function __construct(TXmlElement $owner) |
2361
|
|
|
{ |
2362
|
|
|
$this->_o=$owner; |
2363
|
|
|
} |
2364
|
|
|
protected function getOwner() |
2365
|
|
|
{ |
2366
|
|
|
return $this->_o; |
2367
|
|
|
} |
2368
|
|
|
public function insertAt($index,$item) |
2369
|
|
|
{ |
2370
|
|
|
if($item instanceof TXmlElement) |
2371
|
|
|
{ |
2372
|
|
|
parent::insertAt($index,$item); |
2373
|
|
|
if($item->getParent()!==null) |
2374
|
|
|
$item->getParent()->getElements()->remove($item); |
2375
|
|
|
$item->setParent($this->_o); |
2376
|
|
|
} |
2377
|
|
|
else |
2378
|
|
|
throw new TInvalidDataTypeException('xmlelementlist_xmlelement_required'); |
2379
|
|
|
} |
2380
|
|
|
public function removeAt($index) |
2381
|
|
|
{ |
2382
|
|
|
$item=parent::removeAt($index); |
2383
|
|
|
if($item instanceof TXmlElement) |
2384
|
|
|
$item->setParent(null); |
2385
|
|
|
return $item; |
2386
|
|
|
} |
2387
|
|
|
} |
2388
|
|
|
class TAuthorizationRule extends TComponent |
2389
|
|
|
{ |
2390
|
|
|
private $_action; |
2391
|
|
|
private $_users; |
2392
|
|
|
private $_roles; |
2393
|
|
|
private $_verb; |
2394
|
|
|
private $_ipRules; |
2395
|
|
|
private $_everyone; |
2396
|
|
|
private $_guest; |
2397
|
|
|
private $_authenticated; |
2398
|
|
|
public function __construct($action,$users,$roles,$verb='',$ipRules='') |
2399
|
|
|
{ |
2400
|
|
|
$action=strtolower(trim($action)); |
2401
|
|
|
if($action==='allow' || $action==='deny') |
2402
|
|
|
$this->_action=$action; |
2403
|
|
|
else |
2404
|
|
|
throw new TInvalidDataValueException('authorizationrule_action_invalid',$action); |
2405
|
|
|
$this->_users=array(); |
2406
|
|
|
$this->_roles=array(); |
2407
|
|
|
$this->_ipRules=array(); |
2408
|
|
|
$this->_everyone=false; |
2409
|
|
|
$this->_guest=false; |
2410
|
|
|
$this->_authenticated=false; |
2411
|
|
|
if(trim($users)==='') |
2412
|
|
|
$users='*'; |
2413
|
|
|
foreach(explode(',',$users) as $user) |
2414
|
|
|
{ |
2415
|
|
|
if(($user=trim(strtolower($user)))!=='') |
2416
|
|
|
{ |
2417
|
|
|
if($user==='*') |
2418
|
|
|
{ |
2419
|
|
|
$this->_everyone=true; |
2420
|
|
|
break; |
2421
|
|
|
} |
2422
|
|
|
else if($user==='?') |
2423
|
|
|
$this->_guest=true; |
2424
|
|
|
else if($user==='@') |
2425
|
|
|
$this->_authenticated=true; |
2426
|
|
|
else |
2427
|
|
|
$this->_users[]=$user; |
2428
|
|
|
} |
2429
|
|
|
} |
2430
|
|
|
if(trim($roles)==='') |
2431
|
|
|
$roles='*'; |
2432
|
|
|
foreach(explode(',',$roles) as $role) |
2433
|
|
|
{ |
2434
|
|
|
if(($role=trim(strtolower($role)))!=='') |
2435
|
|
|
$this->_roles[]=$role; |
2436
|
|
|
} |
2437
|
|
|
if(($verb=trim(strtolower($verb)))==='') |
2438
|
|
|
$verb='*'; |
2439
|
|
|
if($verb==='*' || $verb==='get' || $verb==='post') |
2440
|
|
|
$this->_verb=$verb; |
2441
|
|
|
else |
2442
|
|
|
throw new TInvalidDataValueException('authorizationrule_verb_invalid',$verb); |
2443
|
|
|
if(trim($ipRules)==='') |
2444
|
|
|
$ipRules='*'; |
2445
|
|
|
foreach(explode(',',$ipRules) as $ipRule) |
2446
|
|
|
{ |
2447
|
|
|
if(($ipRule=trim($ipRule))!=='') |
2448
|
|
|
$this->_ipRules[]=$ipRule; |
2449
|
|
|
} |
2450
|
|
|
} |
2451
|
|
|
public function getAction() |
2452
|
|
|
{ |
2453
|
|
|
return $this->_action; |
2454
|
|
|
} |
2455
|
|
|
public function getUsers() |
2456
|
|
|
{ |
2457
|
|
|
return $this->_users; |
2458
|
|
|
} |
2459
|
|
|
public function getRoles() |
2460
|
|
|
{ |
2461
|
|
|
return $this->_roles; |
2462
|
|
|
} |
2463
|
|
|
public function getVerb() |
2464
|
|
|
{ |
2465
|
|
|
return $this->_verb; |
2466
|
|
|
} |
2467
|
|
|
public function getIPRules() |
2468
|
|
|
{ |
2469
|
|
|
return $this->_ipRules; |
2470
|
|
|
} |
2471
|
|
|
public function getGuestApplied() |
2472
|
|
|
{ |
2473
|
|
|
return $this->_guest || $this->_everyone; |
2474
|
|
|
} |
2475
|
|
|
public function getEveryoneApplied() |
2476
|
|
|
{ |
2477
|
|
|
return $this->_everyone; |
2478
|
|
|
} |
2479
|
|
|
public function getAuthenticatedApplied() |
2480
|
|
|
{ |
2481
|
|
|
return $this->_authenticated || $this->_everyone; |
2482
|
|
|
} |
2483
|
|
|
public function isUserAllowed(IUser $user,$verb,$ip) |
2484
|
|
|
{ |
2485
|
|
|
if($this->isVerbMatched($verb) && $this->isIpMatched($ip) && $this->isUserMatched($user) && $this->isRoleMatched($user)) |
2486
|
|
|
return ($this->_action==='allow')?1:-1; |
2487
|
|
|
else |
2488
|
|
|
return 0; |
2489
|
|
|
} |
2490
|
|
|
private function isIpMatched($ip) |
2491
|
|
|
{ |
2492
|
|
|
if(empty($this->_ipRules)) |
2493
|
|
|
return 1; |
2494
|
|
|
foreach($this->_ipRules as $rule) |
2495
|
|
|
{ |
2496
|
|
|
if($rule==='*' || $rule===$ip || (($pos=strpos($rule,'*'))!==false && strncmp($ip,$rule,$pos)===0)) |
2497
|
|
|
return 1; |
2498
|
|
|
} |
2499
|
|
|
return 0; |
2500
|
|
|
} |
2501
|
|
|
private function isUserMatched($user) |
2502
|
|
|
{ |
2503
|
|
|
return ($this->_everyone || ($this->_guest && $user->getIsGuest()) || ($this->_authenticated && !$user->getIsGuest()) || in_array(strtolower($user->getName()),$this->_users)); |
2504
|
|
|
} |
2505
|
|
|
private function isRoleMatched($user) |
2506
|
|
|
{ |
2507
|
|
|
foreach($this->_roles as $role) |
2508
|
|
|
{ |
2509
|
|
|
if($role==='*' || $user->isInRole($role)) |
2510
|
|
|
return true; |
2511
|
|
|
} |
2512
|
|
|
return false; |
2513
|
|
|
} |
2514
|
|
|
private function isVerbMatched($verb) |
2515
|
|
|
{ |
2516
|
|
|
return ($this->_verb==='*' || strcasecmp($verb,$this->_verb)===0); |
2517
|
|
|
} |
2518
|
|
|
} |
2519
|
|
|
class TAuthorizationRuleCollection extends TList |
2520
|
|
|
{ |
2521
|
|
|
public function isUserAllowed($user,$verb,$ip) |
2522
|
|
|
{ |
2523
|
|
|
if($user instanceof IUser) |
2524
|
|
|
{ |
2525
|
|
|
$verb=strtolower(trim($verb)); |
2526
|
|
|
foreach($this as $rule) |
2527
|
|
|
{ |
2528
|
|
|
if(($decision=$rule->isUserAllowed($user,$verb,$ip))!==0) |
2529
|
|
|
return ($decision>0); |
2530
|
|
|
} |
2531
|
|
|
return true; |
2532
|
|
|
} |
2533
|
|
|
else |
2534
|
|
|
return false; |
2535
|
|
|
} |
2536
|
|
|
public function insertAt($index,$item) |
2537
|
|
|
{ |
2538
|
|
|
if($item instanceof TAuthorizationRule) |
2539
|
|
|
parent::insertAt($index,$item); |
2540
|
|
|
else |
2541
|
|
|
throw new TInvalidDataTypeException('authorizationrulecollection_authorizationrule_required'); |
2542
|
|
|
} |
2543
|
|
|
} |
2544
|
|
|
class TSecurityManager extends TModule |
2545
|
|
|
{ |
2546
|
|
|
const STATE_VALIDATION_KEY = 'prado:securitymanager:validationkey'; |
2547
|
|
|
const STATE_ENCRYPTION_KEY = 'prado:securitymanager:encryptionkey'; |
2548
|
|
|
private $_validationKey = null; |
2549
|
|
|
private $_encryptionKey = null; |
2550
|
|
|
private $_hashAlgorithm = 'sha1'; |
2551
|
|
|
private $_cryptAlgorithm = 'rijndael-256'; |
2552
|
|
|
private $_mbstring; |
2553
|
|
|
public function init($config) |
2554
|
|
|
{ |
2555
|
|
|
$this->_mbstring=extension_loaded('mbstring'); |
2556
|
|
|
$this->getApplication()->setSecurityManager($this); |
2557
|
|
|
} |
2558
|
|
|
protected function generateRandomKey() |
2559
|
|
|
{ |
2560
|
|
|
return sprintf('%08x%08x%08x%08x',mt_rand(),mt_rand(),mt_rand(),mt_rand()); |
2561
|
|
|
} |
2562
|
|
|
public function getValidationKey() |
2563
|
|
|
{ |
2564
|
|
|
if(null === $this->_validationKey) { |
2565
|
|
|
if(null === ($this->_validationKey = $this->getApplication()->getGlobalState(self::STATE_VALIDATION_KEY))) { |
2566
|
|
|
$this->_validationKey = $this->generateRandomKey(); |
2567
|
|
|
$this->getApplication()->setGlobalState(self::STATE_VALIDATION_KEY, $this->_validationKey, null, true); |
2568
|
|
|
} |
2569
|
|
|
} |
2570
|
|
|
return $this->_validationKey; |
2571
|
|
|
} |
2572
|
|
|
public function setValidationKey($value) |
2573
|
|
|
{ |
2574
|
|
|
if('' === $value) |
2575
|
|
|
throw new TInvalidDataValueException('securitymanager_validationkey_invalid'); |
2576
|
|
|
$this->_validationKey = $value; |
2577
|
|
|
} |
2578
|
|
|
public function getEncryptionKey() |
2579
|
|
|
{ |
2580
|
|
|
if(null === $this->_encryptionKey) { |
2581
|
|
|
if(null === ($this->_encryptionKey = $this->getApplication()->getGlobalState(self::STATE_ENCRYPTION_KEY))) { |
2582
|
|
|
$this->_encryptionKey = $this->generateRandomKey(); |
2583
|
|
|
$this->getApplication()->setGlobalState(self::STATE_ENCRYPTION_KEY, $this->_encryptionKey, null, true); |
2584
|
|
|
} |
2585
|
|
|
} |
2586
|
|
|
return $this->_encryptionKey; |
2587
|
|
|
} |
2588
|
|
|
public function setEncryptionKey($value) |
2589
|
|
|
{ |
2590
|
|
|
if('' === $value) |
2591
|
|
|
throw new TInvalidDataValueException('securitymanager_encryptionkey_invalid'); |
2592
|
|
|
$this->_encryptionKey = $value; |
2593
|
|
|
} |
2594
|
|
|
public function getValidation() |
2595
|
|
|
{ |
2596
|
|
|
return $this->_hashAlgorithm; |
2597
|
|
|
} |
2598
|
|
|
public function getHashAlgorithm() |
2599
|
|
|
{ |
2600
|
|
|
return $this->_hashAlgorithm; |
2601
|
|
|
} |
2602
|
|
|
public function setValidation($value) |
2603
|
|
|
{ |
2604
|
|
|
$this->_hashAlgorithm = TPropertyValue::ensureEnum($value, 'TSecurityManagerValidationMode'); |
2605
|
|
|
} |
2606
|
|
|
public function setHashAlgorithm($value) |
2607
|
|
|
{ |
2608
|
|
|
$this->_hashAlgorithm = TPropertyValue::ensureString($value); |
2609
|
|
|
} |
2610
|
|
|
public function getEncryption() |
2611
|
|
|
{ |
2612
|
|
|
if(is_string($this->_cryptAlgorithm)) |
2613
|
|
|
return $this->_cryptAlgorithm; |
2614
|
|
|
return "3DES"; |
2615
|
|
|
} |
2616
|
|
|
public function setEncryption($value) |
2617
|
|
|
{ |
2618
|
|
|
$this->_cryptAlgorithm = $value; |
2619
|
|
|
} |
2620
|
|
|
public function getCryptAlgorithm() |
2621
|
|
|
{ |
2622
|
|
|
return $this->_cryptAlgorithm; |
2623
|
|
|
} |
2624
|
|
|
public function setCryptAlgorithm($value) |
2625
|
|
|
{ |
2626
|
|
|
$this->_cryptAlgorithm = $value; |
2627
|
|
|
} |
2628
|
|
|
public function encrypt($data) |
2629
|
|
|
{ |
2630
|
|
|
$module=$this->openCryptModule(); |
2631
|
|
|
$key = $this->substr(md5($this->getEncryptionKey()), 0, mcrypt_enc_get_key_size($module)); |
2632
|
|
|
srand(); |
2633
|
|
|
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($module), MCRYPT_RAND); |
2634
|
|
|
mcrypt_generic_init($module, $key, $iv); |
2635
|
|
|
$encrypted = $iv.mcrypt_generic($module, $data); |
2636
|
|
|
mcrypt_generic_deinit($module); |
2637
|
|
|
mcrypt_module_close($module); |
2638
|
|
|
return $encrypted; |
2639
|
|
|
} |
2640
|
|
|
public function decrypt($data) |
2641
|
|
|
{ |
2642
|
|
|
$module=$this->openCryptModule(); |
2643
|
|
|
$key = $this->substr(md5($this->getEncryptionKey()), 0, mcrypt_enc_get_key_size($module)); |
2644
|
|
|
$ivSize = mcrypt_enc_get_iv_size($module); |
2645
|
|
|
$iv = $this->substr($data, 0, $ivSize); |
2646
|
|
|
mcrypt_generic_init($module, $key, $iv); |
2647
|
|
|
$decrypted = mdecrypt_generic($module, $this->substr($data, $ivSize, $this->strlen($data))); |
2648
|
|
|
mcrypt_generic_deinit($module); |
2649
|
|
|
mcrypt_module_close($module); |
2650
|
|
|
return $decrypted; |
2651
|
|
|
} |
2652
|
|
|
protected function openCryptModule() |
2653
|
|
|
{ |
2654
|
|
|
if(extension_loaded('mcrypt')) |
2655
|
|
|
{ |
2656
|
|
|
if(is_array($this->_cryptAlgorithm)) |
2657
|
|
|
$module=@call_user_func_array('mcrypt_module_open',$this->_cryptAlgorithm); |
2658
|
|
|
else |
2659
|
|
|
$module=@mcrypt_module_open($this->_cryptAlgorithm,'', MCRYPT_MODE_CBC,''); |
2660
|
|
|
if($module===false) |
2661
|
|
|
throw new TNotSupportedException('securitymanager_mcryptextension_initfailed'); |
2662
|
|
|
return $module; |
2663
|
|
|
} |
2664
|
|
|
else |
2665
|
|
|
throw new TNotSupportedException('securitymanager_mcryptextension_required'); |
2666
|
|
|
} |
2667
|
|
|
public function hashData($data) |
2668
|
|
|
{ |
2669
|
|
|
$hmac = $this->computeHMAC($data); |
2670
|
|
|
return $hmac.$data; |
2671
|
|
|
} |
2672
|
|
|
public function validateData($data) |
2673
|
|
|
{ |
2674
|
|
|
$len=$this->strlen($this->computeHMAC('test')); |
2675
|
|
|
if($this->strlen($data) < $len) |
2676
|
|
|
return false; |
2677
|
|
|
$hmac = $this->substr($data, 0, $len); |
2678
|
|
|
$data2=$this->substr($data, $len, $this->strlen($data)); |
2679
|
|
|
return $hmac === $this->computeHMAC($data2) ? $data2 : false; |
2680
|
|
|
} |
2681
|
|
|
protected function computeHMAC($data) |
2682
|
|
|
{ |
2683
|
|
|
$key = $this->getValidationKey(); |
2684
|
|
|
if(function_exists('hash_hmac')) |
2685
|
|
|
return hash_hmac($this->_hashAlgorithm, $data, $key); |
2686
|
|
|
if(!strcasecmp($this->_hashAlgorithm,'sha1')) |
2687
|
|
|
{ |
2688
|
|
|
$pack = 'H40'; |
2689
|
|
|
$func = 'sha1'; |
2690
|
|
|
} else { |
2691
|
|
|
$pack = 'H32'; |
2692
|
|
|
$func = 'md5'; |
2693
|
|
|
} |
2694
|
|
|
$key = str_pad($func($key), 64, chr(0)); |
2695
|
|
|
return $func((str_repeat(chr(0x5C), 64) ^ substr($key, 0, 64)) . pack($pack, $func((str_repeat(chr(0x36), 64) ^ substr($key, 0, 64)) . $data))); |
2696
|
|
|
} |
2697
|
|
|
private function strlen($string) |
2698
|
|
|
{ |
2699
|
|
|
return $this->_mbstring ? mb_strlen($string,'8bit') : strlen($string); |
2700
|
|
|
} |
2701
|
|
|
private function substr($string,$start,$length) |
2702
|
|
|
{ |
2703
|
|
|
return $this->_mbstring ? mb_substr($string,$start,$length,'8bit') : substr($string,$start,$length); |
2704
|
|
|
} |
2705
|
|
|
} |
2706
|
|
|
class TSecurityManagerValidationMode extends TEnumerable |
2707
|
|
|
{ |
2708
|
|
|
const MD5 = 'MD5'; |
2709
|
|
|
const SHA1 = 'SHA1'; |
2710
|
|
|
} |
2711
|
|
|
class THttpUtility |
2712
|
|
|
{ |
2713
|
|
|
private static $_encodeTable=array('<'=>'<','>'=>'>','"'=>'"'); |
2714
|
|
|
private static $_decodeTable=array('<'=>'<','>'=>'>','"'=>'"'); |
2715
|
|
|
private static $_stripTable=array('<'=>'','>'=>'','"'=>''); |
2716
|
|
|
public static function htmlEncode($s) |
2717
|
|
|
{ |
2718
|
|
|
return strtr($s,self::$_encodeTable); |
2719
|
|
|
} |
2720
|
|
|
public static function htmlDecode($s) |
2721
|
|
|
{ |
2722
|
|
|
return strtr($s,self::$_decodeTable); |
2723
|
|
|
} |
2724
|
|
|
public static function htmlStrip($s) |
2725
|
|
|
{ |
2726
|
|
|
return strtr($s,self::$_stripTable); |
2727
|
|
|
} |
2728
|
|
|
} |
2729
|
|
|
class TJavaScript |
2730
|
|
|
{ |
2731
|
|
|
public static function renderScriptFiles($files) |
2732
|
|
|
{ |
2733
|
|
|
$str=''; |
2734
|
|
|
foreach($files as $file) |
2735
|
|
|
$str.= self::renderScriptFile($file); |
2736
|
|
|
return $str; |
2737
|
|
|
} |
2738
|
|
|
public static function renderScriptFile($file) |
2739
|
|
|
{ |
2740
|
|
|
return '<script type="text/javascript" src="'.THttpUtility::htmlEncode($file)."\"></script>\n"; |
2741
|
|
|
} |
2742
|
|
|
public static function renderScriptBlocks($scripts) |
2743
|
|
|
{ |
2744
|
|
|
if(count($scripts)) |
2745
|
|
|
return "<script type=\"text/javascript\">\n/*<![CDATA[*/\n".implode("\n",$scripts)."\n/*]]>*/\n</script>\n"; |
2746
|
|
|
else |
2747
|
|
|
return ''; |
2748
|
|
|
} |
2749
|
|
|
public static function renderScriptBlocksCallback($scripts) |
2750
|
|
|
{ |
2751
|
|
|
if(count($scripts)) |
2752
|
|
|
return implode("\n",$scripts)."\n"; |
2753
|
|
|
else |
2754
|
|
|
return ''; |
2755
|
|
|
} |
2756
|
|
|
public static function renderScriptBlock($script) |
2757
|
|
|
{ |
2758
|
|
|
return "<script type=\"text/javascript\">\n/*<![CDATA[*/\n{$script}\n/*]]>*/\n</script>\n"; |
2759
|
|
|
} |
2760
|
|
|
public static function quoteString($js) |
2761
|
|
|
{ |
2762
|
|
|
return self::jsonEncode($js,JSON_HEX_QUOT | JSON_HEX_APOS | JSON_HEX_TAG); |
2763
|
|
|
} |
2764
|
|
|
public static function quoteJsLiteral($js) |
2765
|
|
|
{ |
2766
|
|
|
if($js instanceof TJavaScriptLiteral) |
2767
|
|
|
return $js; |
2768
|
|
|
else |
2769
|
|
|
return new TJavaScriptLiteral($js); |
2770
|
|
|
} |
2771
|
|
|
public static function quoteFunction($js) |
2772
|
|
|
{ |
2773
|
|
|
return self::quoteJsLiteral($js); |
2774
|
|
|
} |
2775
|
|
|
public static function isJsLiteral($js) |
2776
|
|
|
{ |
2777
|
|
|
return ($js instanceof TJavaScriptLiteral); |
2778
|
|
|
} |
2779
|
|
|
public static function isFunction($js) |
2780
|
|
|
{ |
2781
|
|
|
return self::isJsLiteral($js); |
2782
|
|
|
} |
2783
|
|
|
public static function encode($value,$toMap=true,$encodeEmptyStrings=false) |
2784
|
|
|
{ |
2785
|
|
|
if(is_string($value)) |
2786
|
|
|
return self::quoteString($value); |
2787
|
|
|
else if(is_bool($value)) |
2788
|
|
|
return $value?'true':'false'; |
2789
|
|
|
else if(is_array($value)) |
2790
|
|
|
{ |
2791
|
|
|
$results=''; |
2792
|
|
|
if(($n=count($value))>0 && array_keys($value)!==range(0,$n-1)) |
2793
|
|
|
{ |
2794
|
|
|
foreach($value as $k=>$v) |
2795
|
|
|
{ |
2796
|
|
|
if($v!=='' || $encodeEmptyStrings) |
2797
|
|
|
{ |
2798
|
|
|
if($results!=='') |
2799
|
|
|
$results.=','; |
2800
|
|
|
$results.="'$k':".self::encode($v,$toMap,$encodeEmptyStrings); |
2801
|
|
|
} |
2802
|
|
|
} |
2803
|
|
|
return '{'.$results.'}'; |
2804
|
|
|
} |
2805
|
|
|
else |
2806
|
|
|
{ |
2807
|
|
|
foreach($value as $v) |
2808
|
|
|
{ |
2809
|
|
|
if($v!=='' || $encodeEmptyStrings) |
2810
|
|
|
{ |
2811
|
|
|
if($results!=='') |
2812
|
|
|
$results.=','; |
2813
|
|
|
$results.=self::encode($v,$toMap, $encodeEmptyStrings); |
2814
|
|
|
} |
2815
|
|
|
} |
2816
|
|
|
return '['.$results.']'; |
2817
|
|
|
} |
2818
|
|
|
} |
2819
|
|
|
else if(is_integer($value)) |
2820
|
|
|
return "$value"; |
2821
|
|
|
else if(is_float($value)) |
2822
|
|
|
{ |
2823
|
|
|
switch($value) |
2824
|
|
|
{ |
2825
|
|
|
case -INF: |
2826
|
|
|
return 'Number.NEGATIVE_INFINITY'; |
2827
|
|
|
break; |
|
|
|
|
2828
|
|
|
case INF: |
2829
|
|
|
return 'Number.POSITIVE_INFINITY'; |
2830
|
|
|
break; |
|
|
|
|
2831
|
|
|
default: |
2832
|
|
|
$locale=localeConv(); |
2833
|
|
|
if($locale['decimal_point']=='.') |
2834
|
|
|
return "$value"; |
2835
|
|
|
else |
2836
|
|
|
return str_replace($locale['decimal_point'], '.', "$value"); |
2837
|
|
|
break; |
|
|
|
|
2838
|
|
|
} |
2839
|
|
|
} |
2840
|
|
|
else if(is_object($value)) |
2841
|
|
|
if ($value instanceof TJavaScriptLiteral) |
2842
|
|
|
return $value->toJavaScriptLiteral(); |
2843
|
|
|
else |
2844
|
|
|
return self::encode(get_object_vars($value),$toMap); |
2845
|
|
|
else if($value===null) |
2846
|
|
|
return 'null'; |
2847
|
|
|
else |
2848
|
|
|
return ''; |
2849
|
|
|
} |
2850
|
|
|
public static function jsonEncode($value, $options = 0) |
2851
|
|
|
{ |
2852
|
|
|
if (($g=Prado::getApplication()->getGlobalization(false))!==null && |
2853
|
|
|
strtoupper($enc=$g->getCharset())!='UTF-8') { |
2854
|
|
|
self::convertToUtf8($value, $enc); |
2855
|
|
|
} |
2856
|
|
|
$s = @json_encode($value,$options); |
2857
|
|
|
self::checkJsonError(); |
2858
|
|
|
return $s; |
2859
|
|
|
} |
2860
|
|
|
private static function convertToUtf8(&$value, $sourceEncoding) { |
2861
|
|
|
if(is_string($value)) |
2862
|
|
|
$value=iconv($sourceEncoding, 'UTF-8', $value); |
2863
|
|
|
else if (is_array($value)) |
2864
|
|
|
{ |
2865
|
|
|
foreach($value as &$element) |
2866
|
|
|
self::convertToUtf8($element, $sourceEncoding); |
2867
|
|
|
} |
2868
|
|
|
} |
2869
|
|
|
public static function jsonDecode($value, $assoc = false, $depth = 512) |
2870
|
|
|
{ |
2871
|
|
|
$s= @json_decode($value, $assoc, $depth); |
2872
|
|
|
self::checkJsonError(); |
2873
|
|
|
return $s; |
2874
|
|
|
} |
2875
|
|
|
private static function checkJsonError() |
2876
|
|
|
{ |
2877
|
|
|
switch ($err = json_last_error()) |
2878
|
|
|
{ |
2879
|
|
|
case JSON_ERROR_NONE: |
2880
|
|
|
return; |
2881
|
|
|
break; |
|
|
|
|
2882
|
|
|
case JSON_ERROR_DEPTH: |
2883
|
|
|
$msg = 'Maximum stack depth exceeded'; |
2884
|
|
|
break; |
2885
|
|
|
case JSON_ERROR_STATE_MISMATCH: |
2886
|
|
|
$msg = 'Underflow or the modes mismatch'; |
2887
|
|
|
break; |
2888
|
|
|
case JSON_ERROR_CTRL_CHAR: |
2889
|
|
|
$msg = 'Unexpected control character found'; |
2890
|
|
|
break; |
2891
|
|
|
case JSON_ERROR_SYNTAX: |
2892
|
|
|
$msg = 'Syntax error, malformed JSON'; |
2893
|
|
|
break; |
2894
|
|
|
case JSON_ERROR_UTF8: |
2895
|
|
|
$msg = 'Malformed UTF-8 characters, possibly incorrectly encoded'; |
2896
|
|
|
break; |
2897
|
|
|
default: |
2898
|
|
|
$msg = 'Unknown error'; |
2899
|
|
|
break; |
2900
|
|
|
} |
2901
|
|
|
throw new Exception("JSON error ($err): $msg"); |
2902
|
|
|
} |
2903
|
|
|
public static function JSMin($code) |
2904
|
|
|
{ |
2905
|
|
|
Prado::using('System.Web.Javascripts.JSMin'); |
2906
|
|
|
return JSMin::minify($code); |
2907
|
|
|
} |
2908
|
|
|
} |
2909
|
|
|
class TUrlManager extends TModule |
2910
|
|
|
{ |
2911
|
|
|
public function constructUrl($serviceID,$serviceParam,$getItems,$encodeAmpersand,$encodeGetItems) |
2912
|
|
|
{ |
2913
|
|
|
$url=$serviceID.'='.urlencode($serviceParam); |
2914
|
|
|
$amp=$encodeAmpersand?'&':'&'; |
2915
|
|
|
$request=$this->getRequest(); |
2916
|
|
|
if(is_array($getItems) || $getItems instanceof Traversable) |
2917
|
|
|
{ |
2918
|
|
|
if($encodeGetItems) |
2919
|
|
|
{ |
2920
|
|
|
foreach($getItems as $name=>$value) |
2921
|
|
|
{ |
2922
|
|
|
if(is_array($value)) |
2923
|
|
|
{ |
2924
|
|
|
$name=urlencode($name.'[]'); |
2925
|
|
|
foreach($value as $v) |
2926
|
|
|
$url.=$amp.$name.'='.urlencode($v); |
2927
|
|
|
} |
2928
|
|
|
else |
2929
|
|
|
$url.=$amp.urlencode($name).'='.urlencode($value); |
2930
|
|
|
} |
2931
|
|
|
} |
2932
|
|
|
else |
2933
|
|
|
{ |
2934
|
|
|
foreach($getItems as $name=>$value) |
2935
|
|
|
{ |
2936
|
|
|
if(is_array($value)) |
2937
|
|
|
{ |
2938
|
|
|
foreach($value as $v) |
2939
|
|
|
$url.=$amp.$name.'[]='.$v; |
2940
|
|
|
} |
2941
|
|
|
else |
2942
|
|
|
$url.=$amp.$name.'='.$value; |
2943
|
|
|
} |
2944
|
|
|
} |
2945
|
|
|
} |
2946
|
|
|
switch($request->getUrlFormat()) |
2947
|
|
|
{ |
2948
|
|
|
case THttpRequestUrlFormat::Path: |
2949
|
|
|
return $request->getApplicationUrl().'/'.strtr($url,array($amp=>'/','?'=>'/','='=>$request->getUrlParamSeparator())); |
2950
|
|
|
case THttpRequestUrlFormat::HiddenPath: |
2951
|
|
|
return rtrim(dirname($request->getApplicationUrl()), '/').'/'.strtr($url,array($amp=>'/','?'=>'/','='=>$request->getUrlParamSeparator())); |
2952
|
|
|
default: |
2953
|
|
|
return $request->getApplicationUrl().'?'.$url; |
2954
|
|
|
} |
2955
|
|
|
} |
2956
|
|
|
public function parseUrl() |
2957
|
|
|
{ |
2958
|
|
|
$request=$this->getRequest(); |
2959
|
|
|
$pathInfo=trim($request->getPathInfo(),'/'); |
2960
|
|
|
if(($request->getUrlFormat()===THttpRequestUrlFormat::Path || |
2961
|
|
|
$request->getUrlFormat()===THttpRequestUrlFormat::HiddenPath) && |
2962
|
|
|
$pathInfo!=='') |
2963
|
|
|
{ |
2964
|
|
|
$separator=$request->getUrlParamSeparator(); |
2965
|
|
|
$paths=explode('/',$pathInfo); |
2966
|
|
|
$getVariables=array(); |
2967
|
|
|
foreach($paths as $path) |
2968
|
|
|
{ |
2969
|
|
|
if(($path=trim($path))!=='') |
2970
|
|
|
{ |
2971
|
|
|
if(($pos=strpos($path,$separator))!==false) |
2972
|
|
|
{ |
2973
|
|
|
$name=substr($path,0,$pos); |
2974
|
|
|
$value=substr($path,$pos+1); |
2975
|
|
|
if(($pos=strpos($name,'[]'))!==false) |
2976
|
|
|
$getVariables[substr($name,0,$pos)][]=$value; |
2977
|
|
|
else |
2978
|
|
|
$getVariables[$name]=$value; |
2979
|
|
|
} |
2980
|
|
|
else |
2981
|
|
|
$getVariables[$path]=''; |
2982
|
|
|
} |
2983
|
|
|
} |
2984
|
|
|
return $getVariables; |
2985
|
|
|
} |
2986
|
|
|
else |
2987
|
|
|
return array(); |
2988
|
|
|
} |
2989
|
|
|
} |
2990
|
|
|
class THttpRequest extends TApplicationComponent implements IteratorAggregate,ArrayAccess,Countable,IModule |
|
|
|
|
2991
|
|
|
{ |
2992
|
|
|
const CGIFIX__PATH_INFO = 1; |
2993
|
|
|
const CGIFIX__SCRIPT_NAME = 2; |
2994
|
|
|
private $_urlManager=null; |
2995
|
|
|
private $_urlManagerID=''; |
2996
|
|
|
private $_separator=','; |
2997
|
|
|
private $_serviceID=null; |
2998
|
|
|
private $_serviceParam=null; |
2999
|
|
|
private $_cookies=null; |
3000
|
|
|
private $_requestUri; |
3001
|
|
|
private $_pathInfo; |
3002
|
|
|
private $_cookieOnly=null; |
3003
|
|
|
private $_urlFormat=THttpRequestUrlFormat::Get; |
3004
|
|
|
private $_services; |
|
|
|
|
3005
|
|
|
private $_requestResolved=false; |
3006
|
|
|
private $_enableCookieValidation=false; |
3007
|
|
|
private $_cgiFix=0; |
3008
|
|
|
private $_enableCache=false; |
3009
|
|
|
private $_url=null; |
3010
|
|
|
private $_id; |
3011
|
|
|
private $_items=array(); |
3012
|
|
|
public function getID() |
3013
|
|
|
{ |
3014
|
|
|
return $this->_id; |
3015
|
|
|
} |
3016
|
|
|
public function setID($value) |
3017
|
|
|
{ |
3018
|
|
|
$this->_id=$value; |
3019
|
|
|
} |
3020
|
|
|
public function init($config) |
|
|
|
|
3021
|
|
|
{ |
3022
|
|
|
if(php_sapi_name()==='cli') |
3023
|
|
|
{ |
3024
|
|
|
$_SERVER['REMOTE_ADDR']='127.0.0.1'; |
3025
|
|
|
$_SERVER['REQUEST_METHOD']='GET'; |
3026
|
|
|
$_SERVER['SERVER_NAME']='localhost'; |
3027
|
|
|
$_SERVER['SERVER_PORT']=80; |
3028
|
|
|
$_SERVER['HTTP_USER_AGENT']=''; |
3029
|
|
|
} |
3030
|
|
|
if(isset($_SERVER['REQUEST_URI'])) |
3031
|
|
|
$this->_requestUri=$_SERVER['REQUEST_URI']; |
3032
|
|
|
else $this->_requestUri=$_SERVER['SCRIPT_NAME'].(empty($_SERVER['QUERY_STRING'])?'':'?'.$_SERVER['QUERY_STRING']); |
3033
|
|
|
if($this->_cgiFix&self::CGIFIX__PATH_INFO && isset($_SERVER['ORIG_PATH_INFO'])) |
3034
|
|
|
$this->_pathInfo=substr($_SERVER['ORIG_PATH_INFO'], strlen($_SERVER['SCRIPT_NAME'])); |
3035
|
|
|
elseif(isset($_SERVER['PATH_INFO'])) |
3036
|
|
|
$this->_pathInfo=$_SERVER['PATH_INFO']; |
3037
|
|
|
else if(strpos($_SERVER['PHP_SELF'],$_SERVER['SCRIPT_NAME'])===0 && $_SERVER['PHP_SELF']!==$_SERVER['SCRIPT_NAME']) |
3038
|
|
|
$this->_pathInfo=substr($_SERVER['PHP_SELF'],strlen($_SERVER['SCRIPT_NAME'])); |
3039
|
|
|
else |
3040
|
|
|
$this->_pathInfo=''; |
3041
|
|
|
if(get_magic_quotes_gpc()) |
3042
|
|
|
{ |
3043
|
|
|
if(isset($_GET)) |
3044
|
|
|
$_GET=$this->stripSlashes($_GET); |
3045
|
|
|
if(isset($_POST)) |
3046
|
|
|
$_POST=$this->stripSlashes($_POST); |
3047
|
|
|
if(isset($_REQUEST)) |
3048
|
|
|
$_REQUEST=$this->stripSlashes($_REQUEST); |
3049
|
|
|
if(isset($_COOKIE)) |
3050
|
|
|
$_COOKIE=$this->stripSlashes($_COOKIE); |
3051
|
|
|
} |
3052
|
|
|
$this->getApplication()->setRequest($this); |
3053
|
|
|
} |
3054
|
|
|
public function stripSlashes(&$data) |
3055
|
|
|
{ |
3056
|
|
|
return is_array($data)?array_map(array($this,'stripSlashes'),$data):stripslashes($data); |
3057
|
|
|
} |
3058
|
|
|
public function getUrl() |
|
|
|
|
3059
|
|
|
{ |
3060
|
|
|
if($this->_url===null) |
3061
|
|
|
{ |
3062
|
|
|
$secure=$this->getIsSecureConnection(); |
3063
|
|
|
$url=$secure?'https://':'http://'; |
3064
|
|
|
if(empty($_SERVER['HTTP_HOST'])) |
3065
|
|
|
{ |
3066
|
|
|
$url.=$_SERVER['SERVER_NAME']; |
3067
|
|
|
$port=$_SERVER['SERVER_PORT']; |
3068
|
|
|
if(($port!=80 && !$secure) || ($port!=443 && $secure)) |
3069
|
|
|
$url.=':'.$port; |
3070
|
|
|
} |
3071
|
|
|
else |
3072
|
|
|
$url.=$_SERVER['HTTP_HOST']; |
3073
|
|
|
$url.=$this->getRequestUri(); |
3074
|
|
|
$this->_url=new TUri($url); |
3075
|
|
|
} |
3076
|
|
|
return $this->_url; |
3077
|
|
|
} |
3078
|
|
|
public function setEnableCache($value) |
3079
|
|
|
{ |
3080
|
|
|
$this->_enableCache = TPropertyValue::ensureBoolean($value); |
3081
|
|
|
} |
3082
|
|
|
public function getEnableCache() |
3083
|
|
|
{ |
3084
|
|
|
return $this->_enableCache; |
3085
|
|
|
} |
3086
|
|
|
protected function getCacheKey() |
3087
|
|
|
{ |
3088
|
|
|
return $this->getID(); |
3089
|
|
|
} |
3090
|
|
|
protected function cacheUrlManager($manager) |
3091
|
|
|
{ |
3092
|
|
|
if($this->getEnableCache()) |
3093
|
|
|
{ |
3094
|
|
|
$cache = $this->getApplication()->getCache(); |
3095
|
|
|
if($cache !== null) |
3096
|
|
|
{ |
3097
|
|
|
$dependencies = null; |
3098
|
|
|
if($this->getApplication()->getMode() !== TApplicationMode::Performance) |
3099
|
|
|
if ($manager instanceof TUrlMapping && $fn = $manager->getConfigFile()) |
3100
|
|
|
{ |
3101
|
|
|
$fn = Prado::getPathOfNamespace($fn,$this->getApplication()->getConfigurationFileExt()); |
3102
|
|
|
$dependencies = new TFileCacheDependency($fn); |
3103
|
|
|
} |
3104
|
|
|
return $cache->set($this->getCacheKey(), $manager, 0, $dependencies); |
3105
|
|
|
} |
3106
|
|
|
} |
3107
|
|
|
return false; |
3108
|
|
|
} |
3109
|
|
|
protected function loadCachedUrlManager() |
3110
|
|
|
{ |
3111
|
|
|
if($this->getEnableCache()) |
3112
|
|
|
{ |
3113
|
|
|
$cache = $this->getApplication()->getCache(); |
3114
|
|
|
if($cache !== null) |
3115
|
|
|
{ |
3116
|
|
|
$manager = $cache->get($this->getCacheKey()); |
3117
|
|
|
if($manager instanceof TUrlManager) |
3118
|
|
|
return $manager; |
3119
|
|
|
} |
3120
|
|
|
} |
3121
|
|
|
return null; |
3122
|
|
|
} |
3123
|
|
|
public function getUrlManager() |
3124
|
|
|
{ |
3125
|
|
|
return $this->_urlManagerID; |
3126
|
|
|
} |
3127
|
|
|
public function setUrlManager($value) |
3128
|
|
|
{ |
3129
|
|
|
$this->_urlManagerID=$value; |
3130
|
|
|
} |
3131
|
|
|
public function getUrlManagerModule() |
3132
|
|
|
{ |
3133
|
|
|
if($this->_urlManager===null) |
3134
|
|
|
{ |
3135
|
|
|
if(($this->_urlManager = $this->loadCachedUrlManager())===null) |
3136
|
|
|
{ |
3137
|
|
|
if(empty($this->_urlManagerID)) |
3138
|
|
|
{ |
3139
|
|
|
$this->_urlManager=new TUrlManager; |
3140
|
|
|
$this->_urlManager->init(null); |
3141
|
|
|
} |
3142
|
|
|
else |
3143
|
|
|
{ |
3144
|
|
|
$this->_urlManager=$this->getApplication()->getModule($this->_urlManagerID); |
3145
|
|
|
if($this->_urlManager===null) |
3146
|
|
|
throw new TConfigurationException('httprequest_urlmanager_inexist',$this->_urlManagerID); |
3147
|
|
|
if(!($this->_urlManager instanceof TUrlManager)) |
3148
|
|
|
throw new TConfigurationException('httprequest_urlmanager_invalid',$this->_urlManagerID); |
3149
|
|
|
} |
3150
|
|
|
$this->cacheUrlManager($this->_urlManager); |
3151
|
|
|
} |
3152
|
|
|
} |
3153
|
|
|
return $this->_urlManager; |
3154
|
|
|
} |
3155
|
|
|
public function getUrlFormat() |
3156
|
|
|
{ |
3157
|
|
|
return $this->_urlFormat; |
3158
|
|
|
} |
3159
|
|
|
public function setUrlFormat($value) |
3160
|
|
|
{ |
3161
|
|
|
$this->_urlFormat=TPropertyValue::ensureEnum($value,'THttpRequestUrlFormat'); |
3162
|
|
|
} |
3163
|
|
|
public function getUrlParamSeparator() |
3164
|
|
|
{ |
3165
|
|
|
return $this->_separator; |
3166
|
|
|
} |
3167
|
|
|
public function setUrlParamSeparator($value) |
3168
|
|
|
{ |
3169
|
|
|
if(strlen($value)===1) |
3170
|
|
|
$this->_separator=$value; |
3171
|
|
|
else |
3172
|
|
|
throw new TInvalidDataValueException('httprequest_separator_invalid'); |
3173
|
|
|
} |
3174
|
|
|
public function getRequestType() |
|
|
|
|
3175
|
|
|
{ |
3176
|
|
|
return isset($_SERVER['REQUEST_METHOD'])?$_SERVER['REQUEST_METHOD']:null; |
3177
|
|
|
} |
3178
|
|
|
public function getContentType($mimetypeOnly = true) |
|
|
|
|
3179
|
|
|
{ |
3180
|
|
|
if(!isset($_SERVER['CONTENT_TYPE'])) |
3181
|
|
|
return null; |
3182
|
|
|
if($mimetypeOnly === true && ($_pos = strpos(';', $_SERVER['CONTENT_TYPE'])) !== false) |
3183
|
|
|
return substr($_SERVER['CONTENT_TYPE'], 0, $_pos); |
3184
|
|
|
return $_SERVER['CONTENT_TYPE']; |
3185
|
|
|
} |
3186
|
|
|
public function getIsSecureConnection() |
|
|
|
|
3187
|
|
|
{ |
3188
|
|
|
return isset($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'],'off'); |
3189
|
|
|
} |
3190
|
|
|
public function getPathInfo() |
3191
|
|
|
{ |
3192
|
|
|
return $this->_pathInfo; |
3193
|
|
|
} |
3194
|
|
|
public function getQueryString() |
|
|
|
|
3195
|
|
|
{ |
3196
|
|
|
return isset($_SERVER['QUERY_STRING'])?$_SERVER['QUERY_STRING']:null; |
3197
|
|
|
} |
3198
|
|
|
public function getHttpProtocolVersion() |
|
|
|
|
3199
|
|
|
{ |
3200
|
|
|
return isset($_SERVER['SERVER_PROTOCOL'])?$_SERVER['SERVER_PROTOCOL']:null; |
3201
|
|
|
} |
3202
|
|
|
public function getHeaders($case=null) |
|
|
|
|
3203
|
|
|
{ |
3204
|
|
|
static $result; |
3205
|
|
|
if($result === null && function_exists('apache_request_headers')) { |
3206
|
|
|
$result = apache_request_headers(); |
3207
|
|
|
} |
3208
|
|
|
elseif($result === null) { |
3209
|
|
|
$result = array(); |
3210
|
|
|
foreach($_SERVER as $key=>$value) { |
3211
|
|
|
if(strncasecmp($key, 'HTTP_', 5) !== 0) continue; |
3212
|
|
|
$key = str_replace(' ','-', ucwords(strtolower(str_replace('_',' ', substr($key, 5))))); |
3213
|
|
|
$result[$key] = $value; |
3214
|
|
|
} |
3215
|
|
|
} |
3216
|
|
|
if($case !== null) |
3217
|
|
|
return array_change_key_case($result, $case); |
3218
|
|
|
return $result; |
3219
|
|
|
} |
3220
|
|
|
public function getRequestUri() |
3221
|
|
|
{ |
3222
|
|
|
return $this->_requestUri; |
3223
|
|
|
} |
3224
|
|
|
public function getBaseUrl($forceSecureConnection=null) |
|
|
|
|
3225
|
|
|
{ |
3226
|
|
|
$url=$this->getUrl(); |
3227
|
|
|
$scheme=($forceSecureConnection)?"https": (($forceSecureConnection === null)?$url->getScheme():'http'); |
3228
|
|
|
$host=$url->getHost(); |
3229
|
|
|
if (($port=$url->getPort())) $host.=':'.$port; |
3230
|
|
|
return $scheme.'://'.$host; |
3231
|
|
|
} |
3232
|
|
|
public function getApplicationUrl() |
|
|
|
|
3233
|
|
|
{ |
3234
|
|
|
if($this->_cgiFix&self::CGIFIX__SCRIPT_NAME && isset($_SERVER['ORIG_SCRIPT_NAME'])) |
3235
|
|
|
return $_SERVER['ORIG_SCRIPT_NAME']; |
3236
|
|
|
return isset($_SERVER['SCRIPT_NAME'])?$_SERVER['SCRIPT_NAME']:null; |
3237
|
|
|
} |
3238
|
|
|
public function getAbsoluteApplicationUrl($forceSecureConnection=null) |
|
|
|
|
3239
|
|
|
{ |
3240
|
|
|
return $this->getBaseUrl($forceSecureConnection) . $this->getApplicationUrl(); |
3241
|
|
|
} |
3242
|
|
|
public function getApplicationFilePath() |
|
|
|
|
3243
|
|
|
{ |
3244
|
|
|
return realpath(isset($_SERVER['SCRIPT_FILENAME'])?$_SERVER['SCRIPT_FILENAME']:null); |
3245
|
|
|
} |
3246
|
|
|
public function getServerName() |
|
|
|
|
3247
|
|
|
{ |
3248
|
|
|
return isset($_SERVER['SERVER_NAME'])?$_SERVER['SERVER_NAME']:null; |
3249
|
|
|
} |
3250
|
|
|
public function getServerSoftware() |
|
|
|
|
3251
|
|
|
{ |
3252
|
|
|
return isset($_SERVER['SERVER_SOFTWARE'])?$_SERVER['SERVER_SOFTWARE']:null; |
3253
|
|
|
} |
3254
|
|
|
public function getServerPort() |
|
|
|
|
3255
|
|
|
{ |
3256
|
|
|
return isset($_SERVER['SERVER_PORT'])?$_SERVER['SERVER_PORT']:null; |
3257
|
|
|
} |
3258
|
|
|
public function getUrlReferrer() |
|
|
|
|
3259
|
|
|
{ |
3260
|
|
|
return isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:null; |
3261
|
|
|
} |
3262
|
|
|
public function getBrowser() |
3263
|
|
|
{ |
3264
|
|
|
try |
3265
|
|
|
{ |
3266
|
|
|
return get_browser(); |
3267
|
|
|
} |
3268
|
|
|
catch(TPhpErrorException $e) |
3269
|
|
|
{ |
3270
|
|
|
throw new TConfigurationException('httprequest_browscap_required'); |
3271
|
|
|
} |
3272
|
|
|
} |
3273
|
|
|
public function getUserAgent() |
|
|
|
|
3274
|
|
|
{ |
3275
|
|
|
return isset($_SERVER['HTTP_USER_AGENT'])?$_SERVER['HTTP_USER_AGENT']:null; |
3276
|
|
|
} |
3277
|
|
|
public function getUserHostAddress() |
|
|
|
|
3278
|
|
|
{ |
3279
|
|
|
return isset($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:null; |
3280
|
|
|
} |
3281
|
|
|
public function getUserHost() |
|
|
|
|
3282
|
|
|
{ |
3283
|
|
|
return isset($_SERVER['REMOTE_HOST'])?$_SERVER['REMOTE_HOST']:null; |
3284
|
|
|
} |
3285
|
|
|
public function getAcceptTypes() |
|
|
|
|
3286
|
|
|
{ |
3287
|
|
|
return isset($_SERVER['HTTP_ACCEPT'])?$_SERVER['HTTP_ACCEPT']:null; |
3288
|
|
|
} |
3289
|
|
|
public function getUserLanguages() |
3290
|
|
|
{ |
3291
|
|
|
return Prado::getUserLanguages(); |
3292
|
|
|
} |
3293
|
|
|
public function getEnableCookieValidation() |
3294
|
|
|
{ |
3295
|
|
|
return $this->_enableCookieValidation; |
3296
|
|
|
} |
3297
|
|
|
public function setEnableCookieValidation($value) |
3298
|
|
|
{ |
3299
|
|
|
$this->_enableCookieValidation=TPropertyValue::ensureBoolean($value); |
3300
|
|
|
} |
3301
|
|
|
public function getCgiFix() |
3302
|
|
|
{ |
3303
|
|
|
return $this->_cgiFix; |
3304
|
|
|
} |
3305
|
|
|
public function setCgiFix($value) |
3306
|
|
|
{ |
3307
|
|
|
$this->_cgiFix=TPropertyValue::ensureInteger($value); |
3308
|
|
|
} |
3309
|
|
|
public function getCookies() |
|
|
|
|
3310
|
|
|
{ |
3311
|
|
|
if($this->_cookies===null) |
3312
|
|
|
{ |
3313
|
|
|
$this->_cookies=new THttpCookieCollection; |
3314
|
|
|
if($this->getEnableCookieValidation()) |
3315
|
|
|
{ |
3316
|
|
|
$sm=$this->getApplication()->getSecurityManager(); |
3317
|
|
|
foreach($_COOKIE as $key=>$value) |
3318
|
|
|
{ |
3319
|
|
|
if(($value=$sm->validateData($value))!==false) |
3320
|
|
|
$this->_cookies->add(new THttpCookie($key,$value)); |
3321
|
|
|
} |
3322
|
|
|
} |
3323
|
|
|
else |
3324
|
|
|
{ |
3325
|
|
|
foreach($_COOKIE as $key=>$value) |
3326
|
|
|
$this->_cookies->add(new THttpCookie($key,$value)); |
3327
|
|
|
} |
3328
|
|
|
} |
3329
|
|
|
return $this->_cookies; |
3330
|
|
|
} |
3331
|
|
|
public function getUploadedFiles() |
|
|
|
|
3332
|
|
|
{ |
3333
|
|
|
return $_FILES; |
3334
|
|
|
} |
3335
|
|
|
public function getServerVariables() |
|
|
|
|
3336
|
|
|
{ |
3337
|
|
|
return $_SERVER; |
3338
|
|
|
} |
3339
|
|
|
public function getEnvironmentVariables() |
|
|
|
|
3340
|
|
|
{ |
3341
|
|
|
return $_ENV; |
3342
|
|
|
} |
3343
|
|
|
public function constructUrl($serviceID,$serviceParam,$getItems=null,$encodeAmpersand=true,$encodeGetItems=true) |
3344
|
|
|
{ |
3345
|
|
|
if ($this->_cookieOnly===null) |
3346
|
|
|
$this->_cookieOnly=(int)ini_get('session.use_cookies') && (int)ini_get('session.use_only_cookies'); |
3347
|
|
|
$url=$this->getUrlManagerModule()->constructUrl($serviceID,$serviceParam,$getItems,$encodeAmpersand,$encodeGetItems); |
3348
|
|
|
if(defined('SID') && SID != '' && !$this->_cookieOnly) |
3349
|
|
|
return $url . (strpos($url,'?')===false? '?' : ($encodeAmpersand?'&':'&')) . SID; |
3350
|
|
|
else |
3351
|
|
|
return $url; |
3352
|
|
|
} |
3353
|
|
|
protected function parseUrl() |
3354
|
|
|
{ |
3355
|
|
|
return $this->getUrlManagerModule()->parseUrl(); |
3356
|
|
|
} |
3357
|
|
|
public function resolveRequest($serviceIDs) |
|
|
|
|
3358
|
|
|
{ |
3359
|
|
|
$getParams=$this->parseUrl(); |
3360
|
|
|
foreach($getParams as $name=>$value) |
3361
|
|
|
$_GET[$name]=$value; |
3362
|
|
|
$this->_items=array_merge($_GET,$_POST); |
3363
|
|
|
$this->_requestResolved=true; |
3364
|
|
|
foreach($serviceIDs as $serviceID) |
3365
|
|
|
{ |
3366
|
|
|
if($this->contains($serviceID)) |
3367
|
|
|
{ |
3368
|
|
|
$this->setServiceID($serviceID); |
3369
|
|
|
$this->setServiceParameter($this->itemAt($serviceID)); |
3370
|
|
|
return $serviceID; |
3371
|
|
|
} |
3372
|
|
|
} |
3373
|
|
|
return null; |
3374
|
|
|
} |
3375
|
|
|
public function getRequestResolved() |
3376
|
|
|
{ |
3377
|
|
|
return $this->_requestResolved; |
3378
|
|
|
} |
3379
|
|
|
public function getServiceID() |
3380
|
|
|
{ |
3381
|
|
|
return $this->_serviceID; |
3382
|
|
|
} |
3383
|
|
|
public function setServiceID($value) |
3384
|
|
|
{ |
3385
|
|
|
$this->_serviceID=$value; |
3386
|
|
|
} |
3387
|
|
|
public function getServiceParameter() |
3388
|
|
|
{ |
3389
|
|
|
return $this->_serviceParam; |
3390
|
|
|
} |
3391
|
|
|
public function setServiceParameter($value) |
3392
|
|
|
{ |
3393
|
|
|
$this->_serviceParam=$value; |
3394
|
|
|
} |
3395
|
|
|
public function getIterator() |
3396
|
|
|
{ |
3397
|
|
|
return new ArrayIterator($this->_items); |
3398
|
|
|
} |
3399
|
|
|
public function getCount() |
3400
|
|
|
{ |
3401
|
|
|
return count($this->_items); |
3402
|
|
|
} |
3403
|
|
|
public function count() |
3404
|
|
|
{ |
3405
|
|
|
return $this->getCount(); |
3406
|
|
|
} |
3407
|
|
|
public function getKeys() |
3408
|
|
|
{ |
3409
|
|
|
return array_keys($this->_items); |
3410
|
|
|
} |
3411
|
|
|
public function itemAt($key) |
3412
|
|
|
{ |
3413
|
|
|
return isset($this->_items[$key]) ? $this->_items[$key] : null; |
3414
|
|
|
} |
3415
|
|
|
public function add($key,$value) |
3416
|
|
|
{ |
3417
|
|
|
$this->_items[$key]=$value; |
3418
|
|
|
} |
3419
|
|
|
public function remove($key) |
3420
|
|
|
{ |
3421
|
|
|
if(isset($this->_items[$key]) || array_key_exists($key,$this->_items)) |
3422
|
|
|
{ |
3423
|
|
|
$value=$this->_items[$key]; |
3424
|
|
|
unset($this->_items[$key]); |
3425
|
|
|
return $value; |
3426
|
|
|
} |
3427
|
|
|
else |
3428
|
|
|
return null; |
3429
|
|
|
} |
3430
|
|
|
public function clear() |
3431
|
|
|
{ |
3432
|
|
|
foreach(array_keys($this->_items) as $key) |
3433
|
|
|
$this->remove($key); |
3434
|
|
|
} |
3435
|
|
|
public function contains($key) |
3436
|
|
|
{ |
3437
|
|
|
return isset($this->_items[$key]) || array_key_exists($key,$this->_items); |
3438
|
|
|
} |
3439
|
|
|
public function toArray() |
3440
|
|
|
{ |
3441
|
|
|
return $this->_items; |
3442
|
|
|
} |
3443
|
|
|
public function offsetExists($offset) |
3444
|
|
|
{ |
3445
|
|
|
return $this->contains($offset); |
3446
|
|
|
} |
3447
|
|
|
public function offsetGet($offset) |
3448
|
|
|
{ |
3449
|
|
|
return $this->itemAt($offset); |
3450
|
|
|
} |
3451
|
|
|
public function offsetSet($offset,$item) |
3452
|
|
|
{ |
3453
|
|
|
$this->add($offset,$item); |
3454
|
|
|
} |
3455
|
|
|
public function offsetUnset($offset) |
3456
|
|
|
{ |
3457
|
|
|
$this->remove($offset); |
3458
|
|
|
} |
3459
|
|
|
} |
3460
|
|
|
class THttpCookieCollection extends TList |
3461
|
|
|
{ |
3462
|
|
|
private $_o; |
3463
|
|
|
public function __construct($owner=null) |
3464
|
|
|
{ |
3465
|
|
|
$this->_o=$owner; |
3466
|
|
|
} |
3467
|
|
|
public function insertAt($index,$item) |
3468
|
|
|
{ |
3469
|
|
|
if($item instanceof THttpCookie) |
3470
|
|
|
{ |
3471
|
|
|
parent::insertAt($index,$item); |
3472
|
|
|
if($this->_o instanceof THttpResponse) |
3473
|
|
|
$this->_o->addCookie($item); |
3474
|
|
|
} |
3475
|
|
|
else |
3476
|
|
|
throw new TInvalidDataTypeException('httpcookiecollection_httpcookie_required'); |
3477
|
|
|
} |
3478
|
|
|
public function removeAt($index) |
3479
|
|
|
{ |
3480
|
|
|
$item=parent::removeAt($index); |
3481
|
|
|
if($this->_o instanceof THttpResponse) |
3482
|
|
|
$this->_o->removeCookie($item); |
3483
|
|
|
return $item; |
3484
|
|
|
} |
3485
|
|
|
public function itemAt($index) |
3486
|
|
|
{ |
3487
|
|
|
if(is_integer($index)) |
3488
|
|
|
return parent::itemAt($index); |
3489
|
|
|
else |
3490
|
|
|
return $this->findCookieByName($index); |
3491
|
|
|
} |
3492
|
|
|
public function findCookieByName($name) |
3493
|
|
|
{ |
3494
|
|
|
foreach($this as $cookie) |
3495
|
|
|
if($cookie->getName()===$name) |
3496
|
|
|
return $cookie; |
3497
|
|
|
return null; |
3498
|
|
|
} |
3499
|
|
|
} |
3500
|
|
|
class THttpCookie extends TComponent |
3501
|
|
|
{ |
3502
|
|
|
private $_domain=''; |
3503
|
|
|
private $_name; |
3504
|
|
|
private $_value=''; |
3505
|
|
|
private $_expire=0; |
3506
|
|
|
private $_path='/'; |
3507
|
|
|
private $_secure=false; |
3508
|
|
|
private $_httpOnly=false; |
3509
|
|
|
public function __construct($name,$value) |
3510
|
|
|
{ |
3511
|
|
|
$this->_name=$name; |
3512
|
|
|
$this->_value=$value; |
3513
|
|
|
} |
3514
|
|
|
public function getDomain() |
3515
|
|
|
{ |
3516
|
|
|
return $this->_domain; |
3517
|
|
|
} |
3518
|
|
|
public function setDomain($value) |
3519
|
|
|
{ |
3520
|
|
|
$this->_domain=$value; |
3521
|
|
|
} |
3522
|
|
|
public function getExpire() |
3523
|
|
|
{ |
3524
|
|
|
return $this->_expire; |
3525
|
|
|
} |
3526
|
|
|
public function setExpire($value) |
3527
|
|
|
{ |
3528
|
|
|
$this->_expire=TPropertyValue::ensureInteger($value); |
3529
|
|
|
} |
3530
|
|
|
public function getHttpOnly() |
3531
|
|
|
{ |
3532
|
|
|
return $this->_httpOnly; |
3533
|
|
|
} |
3534
|
|
|
public function setHttpOnly($value) |
3535
|
|
|
{ |
3536
|
|
|
$this->_httpOnly = TPropertyValue::ensureBoolean($value); |
3537
|
|
|
} |
3538
|
|
|
public function getName() |
3539
|
|
|
{ |
3540
|
|
|
return $this->_name; |
3541
|
|
|
} |
3542
|
|
|
public function setName($value) |
3543
|
|
|
{ |
3544
|
|
|
$this->_name=$value; |
3545
|
|
|
} |
3546
|
|
|
public function getValue() |
3547
|
|
|
{ |
3548
|
|
|
return $this->_value; |
3549
|
|
|
} |
3550
|
|
|
public function setValue($value) |
3551
|
|
|
{ |
3552
|
|
|
$this->_value=$value; |
3553
|
|
|
} |
3554
|
|
|
public function getPath() |
3555
|
|
|
{ |
3556
|
|
|
return $this->_path; |
3557
|
|
|
} |
3558
|
|
|
public function setPath($value) |
3559
|
|
|
{ |
3560
|
|
|
$this->_path=$value; |
3561
|
|
|
} |
3562
|
|
|
public function getSecure() |
3563
|
|
|
{ |
3564
|
|
|
return $this->_secure; |
3565
|
|
|
} |
3566
|
|
|
public function setSecure($value) |
3567
|
|
|
{ |
3568
|
|
|
$this->_secure=TPropertyValue::ensureBoolean($value); |
3569
|
|
|
} |
3570
|
|
|
} |
3571
|
|
|
class TUri extends TComponent |
3572
|
|
|
{ |
3573
|
|
|
private static $_defaultPort=array( |
|
|
|
|
3574
|
|
|
'ftp'=>21, |
3575
|
|
|
'gopher'=>70, |
3576
|
|
|
'http'=>80, |
3577
|
|
|
'https'=>443, |
3578
|
|
|
'news'=>119, |
3579
|
|
|
'nntp'=>119, |
3580
|
|
|
'wais'=>210, |
3581
|
|
|
'telnet'=>23 |
3582
|
|
|
); |
3583
|
|
|
private $_scheme; |
3584
|
|
|
private $_host; |
3585
|
|
|
private $_port; |
3586
|
|
|
private $_user; |
3587
|
|
|
private $_pass; |
3588
|
|
|
private $_path; |
3589
|
|
|
private $_query; |
3590
|
|
|
private $_fragment; |
3591
|
|
|
private $_uri; |
3592
|
|
|
public function __construct($uri) |
3593
|
|
|
{ |
3594
|
|
|
if(($ret=@parse_url($uri))!==false) |
3595
|
|
|
{ |
3596
|
|
|
$this->_scheme=isset($ret['scheme'])?$ret['scheme']:''; |
3597
|
|
|
$this->_host=isset($ret['host'])?$ret['host']:''; |
3598
|
|
|
$this->_port=isset($ret['port'])?$ret['port']:''; |
3599
|
|
|
$this->_user=isset($ret['user'])?$ret['user']:''; |
3600
|
|
|
$this->_pass=isset($ret['pass'])?$ret['pass']:''; |
3601
|
|
|
$this->_path=isset($ret['path'])?$ret['path']:''; |
3602
|
|
|
$this->_query=isset($ret['query'])?$ret['query']:''; |
3603
|
|
|
$this->_fragment=isset($ret['fragment'])?$ret['fragment']:''; |
3604
|
|
|
$this->_uri=$uri; |
3605
|
|
|
} |
3606
|
|
|
else |
3607
|
|
|
{ |
3608
|
|
|
throw new TInvalidDataValueException('uri_format_invalid',$uri); |
3609
|
|
|
} |
3610
|
|
|
} |
3611
|
|
|
public function getUri() |
3612
|
|
|
{ |
3613
|
|
|
return $this->_uri; |
3614
|
|
|
} |
3615
|
|
|
public function getScheme() |
3616
|
|
|
{ |
3617
|
|
|
return $this->_scheme; |
3618
|
|
|
} |
3619
|
|
|
public function getHost() |
3620
|
|
|
{ |
3621
|
|
|
return $this->_host; |
3622
|
|
|
} |
3623
|
|
|
public function getPort() |
3624
|
|
|
{ |
3625
|
|
|
return $this->_port; |
3626
|
|
|
} |
3627
|
|
|
public function getUser() |
3628
|
|
|
{ |
3629
|
|
|
return $this->_user; |
3630
|
|
|
} |
3631
|
|
|
public function getPassword() |
3632
|
|
|
{ |
3633
|
|
|
return $this->_pass; |
3634
|
|
|
} |
3635
|
|
|
public function getPath() |
3636
|
|
|
{ |
3637
|
|
|
return $this->_path; |
3638
|
|
|
} |
3639
|
|
|
public function getQuery() |
3640
|
|
|
{ |
3641
|
|
|
return $this->_query; |
3642
|
|
|
} |
3643
|
|
|
public function getFragment() |
3644
|
|
|
{ |
3645
|
|
|
return $this->_fragment; |
3646
|
|
|
} |
3647
|
|
|
} |
3648
|
|
|
class THttpRequestUrlFormat extends TEnumerable |
3649
|
|
|
{ |
3650
|
|
|
const Get='Get'; |
3651
|
|
|
const Path='Path'; |
3652
|
|
|
const HiddenPath='HiddenPath'; |
3653
|
|
|
} |
3654
|
|
|
class THttpResponseAdapter extends TApplicationComponent |
3655
|
|
|
{ |
3656
|
|
|
private $_response; |
3657
|
|
|
public function __construct($response) |
3658
|
|
|
{ |
3659
|
|
|
$this->_response=$response; |
3660
|
|
|
} |
3661
|
|
|
public function getResponse() |
3662
|
|
|
{ |
3663
|
|
|
return $this->_response; |
3664
|
|
|
} |
3665
|
|
|
public function flushContent() |
3666
|
|
|
{ |
3667
|
|
|
$this->_response->flushContent(); |
3668
|
|
|
} |
3669
|
|
|
public function httpRedirect($url) |
3670
|
|
|
{ |
3671
|
|
|
$this->_response->httpRedirect($url); |
3672
|
|
|
} |
3673
|
|
|
public function createNewHtmlWriter($type, $writer) |
3674
|
|
|
{ |
3675
|
|
|
return $this->_response->createNewHtmlWriter($type,$writer); |
3676
|
|
|
} |
3677
|
|
|
} |
3678
|
|
|
class THttpResponse extends TModule implements ITextWriter |
3679
|
|
|
{ |
3680
|
|
|
const DEFAULT_CONTENTTYPE = 'text/html'; |
3681
|
|
|
const DEFAULT_CHARSET = 'UTF-8'; |
3682
|
|
|
private static $HTTP_STATUS_CODES = array( |
3683
|
|
|
100 => 'Continue', 101 => 'Switching Protocols', |
3684
|
|
|
200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', |
3685
|
|
|
300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect', |
3686
|
|
|
400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed', |
3687
|
|
|
500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported' |
3688
|
|
|
); |
3689
|
|
|
private $_bufferOutput=true; |
3690
|
|
|
private $_initialized=false; |
3691
|
|
|
private $_cookies=null; |
3692
|
|
|
private $_status=200; |
3693
|
|
|
private $_reason='OK'; |
3694
|
|
|
private $_htmlWriterType='System.Web.UI.THtmlWriter'; |
3695
|
|
|
private $_contentType=null; |
3696
|
|
|
private $_charset=''; |
3697
|
|
|
private $_adapter; |
3698
|
|
|
private $_httpHeaderSent; |
3699
|
|
|
private $_contentTypeHeaderSent; |
3700
|
|
|
public function __destruct() |
3701
|
|
|
{ |
3702
|
|
|
} |
3703
|
|
|
public function setAdapter(THttpResponseAdapter $adapter) |
3704
|
|
|
{ |
3705
|
|
|
$this->_adapter=$adapter; |
3706
|
|
|
} |
3707
|
|
|
public function getAdapter() |
3708
|
|
|
{ |
3709
|
|
|
return $this->_adapter; |
3710
|
|
|
} |
3711
|
|
|
public function getHasAdapter() |
3712
|
|
|
{ |
3713
|
|
|
return $this->_adapter!==null; |
3714
|
|
|
} |
3715
|
|
|
public function init($config) |
3716
|
|
|
{ |
3717
|
|
|
if($this->_bufferOutput) |
3718
|
|
|
ob_start(); |
3719
|
|
|
$this->_initialized=true; |
3720
|
|
|
$this->getApplication()->setResponse($this); |
3721
|
|
|
} |
3722
|
|
|
public function getCacheExpire() |
3723
|
|
|
{ |
3724
|
|
|
return session_cache_expire(); |
3725
|
|
|
} |
3726
|
|
|
public function setCacheExpire($value) |
3727
|
|
|
{ |
3728
|
|
|
session_cache_expire(TPropertyValue::ensureInteger($value)); |
3729
|
|
|
} |
3730
|
|
|
public function getCacheControl() |
3731
|
|
|
{ |
3732
|
|
|
return session_cache_limiter(); |
3733
|
|
|
} |
3734
|
|
|
public function setCacheControl($value) |
3735
|
|
|
{ |
3736
|
|
|
session_cache_limiter(TPropertyValue::ensureEnum($value,array('none','nocache','private','private_no_expire','public'))); |
3737
|
|
|
} |
3738
|
|
|
public function setContentType($type) |
3739
|
|
|
{ |
3740
|
|
|
if ($this->_contentTypeHeaderSent) |
3741
|
|
|
throw new Exception('Unable to alter content-type as it has been already sent'); |
3742
|
|
|
$this->_contentType = $type; |
3743
|
|
|
} |
3744
|
|
|
public function getContentType() |
3745
|
|
|
{ |
3746
|
|
|
return $this->_contentType; |
3747
|
|
|
} |
3748
|
|
|
public function getCharset() |
3749
|
|
|
{ |
3750
|
|
|
return $this->_charset; |
3751
|
|
|
} |
3752
|
|
|
public function setCharset($charset) |
3753
|
|
|
{ |
3754
|
|
|
$this->_charset = (strToLower($charset) === 'false') ? false : (string)$charset; |
3755
|
|
|
} |
3756
|
|
|
public function getBufferOutput() |
3757
|
|
|
{ |
3758
|
|
|
return $this->_bufferOutput; |
3759
|
|
|
} |
3760
|
|
|
public function setBufferOutput($value) |
3761
|
|
|
{ |
3762
|
|
|
if($this->_initialized) |
3763
|
|
|
throw new TInvalidOperationException('httpresponse_bufferoutput_unchangeable'); |
3764
|
|
|
else |
3765
|
|
|
$this->_bufferOutput=TPropertyValue::ensureBoolean($value); |
3766
|
|
|
} |
3767
|
|
|
public function getStatusCode() |
3768
|
|
|
{ |
3769
|
|
|
return $this->_status; |
3770
|
|
|
} |
3771
|
|
|
public function setStatusCode($status, $reason=null) |
3772
|
|
|
{ |
3773
|
|
|
if ($this->_httpHeaderSent) |
3774
|
|
|
throw new Exception('Unable to alter response as HTTP header already sent'); |
3775
|
|
|
$status=TPropertyValue::ensureInteger($status); |
3776
|
|
|
if(isset(self::$HTTP_STATUS_CODES[$status])) { |
3777
|
|
|
$this->_reason=self::$HTTP_STATUS_CODES[$status]; |
3778
|
|
|
}else{ |
3779
|
|
|
if($reason===null || $reason==='') { |
3780
|
|
|
throw new TInvalidDataValueException("response_status_reason_missing"); |
3781
|
|
|
} |
3782
|
|
|
$reason=TPropertyValue::ensureString($reason); |
3783
|
|
|
if(strpos($reason, "\r")!=false || strpos($reason, "\n")!=false) { |
|
|
|
|
3784
|
|
|
throw new TInvalidDataValueException("response_status_reason_barchars"); |
3785
|
|
|
} |
3786
|
|
|
$this->_reason=$reason; |
3787
|
|
|
} |
3788
|
|
|
$this->_status=$status; |
3789
|
|
|
} |
3790
|
|
|
public function getStatusReason() { |
3791
|
|
|
return $this->_reason; |
3792
|
|
|
} |
3793
|
|
|
public function getCookies() |
3794
|
|
|
{ |
3795
|
|
|
if($this->_cookies===null) |
3796
|
|
|
$this->_cookies=new THttpCookieCollection($this); |
3797
|
|
|
return $this->_cookies; |
3798
|
|
|
} |
3799
|
|
|
public function write($str) |
3800
|
|
|
{ |
3801
|
|
|
if (!$this->_bufferOutput and !$this->_httpHeaderSent) |
|
|
|
|
3802
|
|
|
$this->ensureHeadersSent(); |
3803
|
|
|
echo $str; |
3804
|
|
|
} |
3805
|
|
|
public function writeFile($fileName,$content=null,$mimeType=null,$headers=null,$forceDownload=true,$clientFileName=null,$fileSize=null) |
3806
|
|
|
{ |
3807
|
|
|
static $defaultMimeTypes=array( |
3808
|
|
|
'css'=>'text/css', |
3809
|
|
|
'gif'=>'image/gif', |
3810
|
|
|
'png'=>'image/png', |
3811
|
|
|
'jpg'=>'image/jpeg', |
3812
|
|
|
'jpeg'=>'image/jpeg', |
3813
|
|
|
'htm'=>'text/html', |
3814
|
|
|
'html'=>'text/html', |
3815
|
|
|
'js'=>'javascript/js', |
3816
|
|
|
'pdf'=>'application/pdf', |
3817
|
|
|
'xls'=>'application/vnd.ms-excel', |
3818
|
|
|
); |
3819
|
|
|
if($mimeType===null) |
3820
|
|
|
{ |
3821
|
|
|
$mimeType='text/plain'; |
3822
|
|
|
if(function_exists('mime_content_type')) |
3823
|
|
|
$mimeType=mime_content_type($fileName); |
3824
|
|
|
else if(($ext=strrchr($fileName,'.'))!==false) |
3825
|
|
|
{ |
3826
|
|
|
$ext=substr($ext,1); |
3827
|
|
|
if(isset($defaultMimeTypes[$ext])) |
3828
|
|
|
$mimeType=$defaultMimeTypes[$ext]; |
3829
|
|
|
} |
3830
|
|
|
} |
3831
|
|
|
if($clientFileName===null) |
3832
|
|
|
$clientFileName=basename($fileName); |
3833
|
|
|
else |
3834
|
|
|
$clientFileName=basename($clientFileName); |
3835
|
|
|
if($fileSize===null || $fileSize < 0) |
3836
|
|
|
$fileSize = ($content===null?filesize($fileName):strlen($content)); |
3837
|
|
|
$this->sendHttpHeader(); |
3838
|
|
|
if(is_array($headers)) |
3839
|
|
|
{ |
3840
|
|
|
foreach($headers as $h) |
3841
|
|
|
header($h); |
3842
|
|
|
} |
3843
|
|
|
else |
3844
|
|
|
{ |
3845
|
|
|
header('Pragma: public'); |
3846
|
|
|
header('Expires: 0'); |
3847
|
|
|
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); |
3848
|
|
|
header("Content-Type: $mimeType"); |
3849
|
|
|
$this->_contentTypeHeaderSent = true; |
3850
|
|
|
} |
3851
|
|
|
header('Content-Length: '.$fileSize); |
3852
|
|
|
header("Content-Disposition: " . ($forceDownload ? 'attachment' : 'inline') . "; filename=\"$clientFileName\""); |
3853
|
|
|
header('Content-Transfer-Encoding: binary'); |
3854
|
|
|
if($content===null) |
3855
|
|
|
readfile($fileName); |
3856
|
|
|
else |
3857
|
|
|
echo $content; |
3858
|
|
|
} |
3859
|
|
|
public function redirect($url) |
3860
|
|
|
{ |
3861
|
|
|
if($this->getHasAdapter()) |
3862
|
|
|
$this->_adapter->httpRedirect($url); |
3863
|
|
|
else |
3864
|
|
|
$this->httpRedirect($url); |
3865
|
|
|
} |
3866
|
|
|
public function httpRedirect($url) |
3867
|
|
|
{ |
3868
|
|
|
$this->ensureHeadersSent(); |
3869
|
|
|
$isIIS = (stripos($this->getRequest()->getServerSoftware(), "microsoft-iis") !== false); |
3870
|
|
|
if($url[0]==='/') |
3871
|
|
|
$url=$this->getRequest()->getBaseUrl().$url; |
3872
|
|
|
if ($this->_status >= 300 && $this->_status < 400) |
3873
|
|
|
{ |
3874
|
|
|
if($isIIS) |
3875
|
|
|
{ |
3876
|
|
|
header('HTTP/1.1 ' . $this->_status . ' ' . self::$HTTP_STATUS_CODES[ |
3877
|
|
|
array_key_exists($this->_status, self::$HTTP_STATUS_CODES) |
3878
|
|
|
? $this->_status |
3879
|
|
|
: 302 |
3880
|
|
|
]); |
3881
|
|
|
} |
3882
|
|
|
header('Location: '.str_replace('&','&',$url), true, $this->_status); |
3883
|
|
|
} else { |
3884
|
|
|
if($isIIS) |
3885
|
|
|
header('HTTP/1.1 302 '.self::$HTTP_STATUS_CODES[302]); |
3886
|
|
|
header('Location: '.str_replace('&','&',$url)); |
3887
|
|
|
} |
3888
|
|
|
if(!$this->getApplication()->getRequestCompleted()) |
3889
|
|
|
$this->getApplication()->onEndRequest(); |
3890
|
|
|
exit(); |
|
|
|
|
3891
|
|
|
} |
3892
|
|
|
public function reload() |
3893
|
|
|
{ |
3894
|
|
|
$this->redirect($this->getRequest()->getRequestUri()); |
3895
|
|
|
} |
3896
|
|
|
public function flush($continueBuffering = true) |
3897
|
|
|
{ |
3898
|
|
|
if($this->getHasAdapter()) |
3899
|
|
|
$this->_adapter->flushContent($continueBuffering); |
3900
|
|
|
else |
3901
|
|
|
$this->flushContent($continueBuffering); |
3902
|
|
|
} |
3903
|
|
|
public function ensureHeadersSent() |
3904
|
|
|
{ |
3905
|
|
|
$this->ensureHttpHeaderSent(); |
3906
|
|
|
$this->ensureContentTypeHeaderSent(); |
3907
|
|
|
} |
3908
|
|
|
public function flushContent($continueBuffering = true) |
3909
|
|
|
{ |
3910
|
|
|
$this->ensureHeadersSent(); |
3911
|
|
|
if($this->_bufferOutput) |
3912
|
|
|
{ |
3913
|
|
|
if (ob_get_length()>0) |
3914
|
|
|
{ |
3915
|
|
|
if (!$continueBuffering) |
3916
|
|
|
{ |
3917
|
|
|
$this->_bufferOutput = false; |
3918
|
|
|
ob_end_flush(); |
3919
|
|
|
} |
3920
|
|
|
else |
3921
|
|
|
ob_flush(); |
3922
|
|
|
flush(); |
3923
|
|
|
} |
3924
|
|
|
} |
3925
|
|
|
else |
3926
|
|
|
flush(); |
3927
|
|
|
} |
3928
|
|
|
protected function ensureHttpHeaderSent() |
3929
|
|
|
{ |
3930
|
|
|
if (!$this->_httpHeaderSent) |
3931
|
|
|
$this->sendHttpHeader(); |
3932
|
|
|
} |
3933
|
|
|
protected function sendHttpHeader() |
3934
|
|
|
{ |
3935
|
|
|
$protocol=$this->getRequest()->getHttpProtocolVersion(); |
3936
|
|
|
if($this->getRequest()->getHttpProtocolVersion() === null) |
3937
|
|
|
$protocol='HTTP/1.1'; |
3938
|
|
|
$phpSapiName = substr(php_sapi_name(), 0, 3); |
3939
|
|
|
$cgi = $phpSapiName == 'cgi' || $phpSapiName == 'fpm'; |
3940
|
|
|
header(($cgi ? 'Status:' : $protocol).' '.$this->_status.' '.$this->_reason, true, TPropertyValue::ensureInteger($this->_status)); |
3941
|
|
|
$this->_httpHeaderSent = true; |
3942
|
|
|
} |
3943
|
|
|
protected function ensureContentTypeHeaderSent() |
3944
|
|
|
{ |
3945
|
|
|
if (!$this->_contentTypeHeaderSent) |
3946
|
|
|
$this->sendContentTypeHeader(); |
3947
|
|
|
} |
3948
|
|
|
protected function sendContentTypeHeader() |
3949
|
|
|
{ |
3950
|
|
|
$contentType=$this->_contentType===null?self::DEFAULT_CONTENTTYPE:$this->_contentType; |
3951
|
|
|
$charset=$this->getCharset(); |
3952
|
|
|
if($charset === false) { |
3953
|
|
|
$this->appendHeader('Content-Type: '.$contentType); |
3954
|
|
|
return; |
3955
|
|
|
} |
3956
|
|
|
if($charset==='' && ($globalization=$this->getApplication()->getGlobalization(false))!==null) |
3957
|
|
|
$charset=$globalization->getCharset(); |
3958
|
|
|
if($charset==='') $charset = self::DEFAULT_CHARSET; |
3959
|
|
|
$this->appendHeader('Content-Type: '.$contentType.';charset='.$charset); |
3960
|
|
|
$this->_contentTypeHeaderSent = true; |
3961
|
|
|
} |
3962
|
|
|
public function getContents() |
3963
|
|
|
{ |
3964
|
|
|
return $this->_bufferOutput?ob_get_contents():''; |
3965
|
|
|
} |
3966
|
|
|
public function clear() |
3967
|
|
|
{ |
3968
|
|
|
if($this->_bufferOutput) |
3969
|
|
|
ob_clean(); |
3970
|
|
|
} |
3971
|
|
|
public function getHeaders($case=null) |
3972
|
|
|
{ |
3973
|
|
|
$result = array(); |
3974
|
|
|
$headers = headers_list(); |
3975
|
|
|
foreach($headers as $header) { |
3976
|
|
|
$tmp = explode(':', $header); |
3977
|
|
|
$key = trim(array_shift($tmp)); |
3978
|
|
|
$value = trim(implode(':', $tmp)); |
3979
|
|
|
if(isset($result[$key])) |
3980
|
|
|
$result[$key] .= ', ' . $value; |
3981
|
|
|
else |
3982
|
|
|
$result[$key] = $value; |
3983
|
|
|
} |
3984
|
|
|
if($case !== null) |
3985
|
|
|
return array_change_key_case($result, $case); |
3986
|
|
|
return $result; |
3987
|
|
|
} |
3988
|
|
|
public function appendHeader($value, $replace=true) |
3989
|
|
|
{ |
3990
|
|
|
header($value, $replace); |
3991
|
|
|
} |
3992
|
|
|
public function appendLog($message,$messageType=0,$destination='',$extraHeaders='') |
3993
|
|
|
{ |
3994
|
|
|
error_log($message,$messageType,$destination,$extraHeaders); |
3995
|
|
|
} |
3996
|
|
|
public function addCookie($cookie) |
3997
|
|
|
{ |
3998
|
|
|
$request=$this->getRequest(); |
3999
|
|
|
if($request->getEnableCookieValidation()) |
4000
|
|
|
{ |
4001
|
|
|
$value=$this->getApplication()->getSecurityManager()->hashData($cookie->getValue()); |
4002
|
|
|
setcookie( |
4003
|
|
|
$cookie->getName(), |
4004
|
|
|
$value, |
4005
|
|
|
$cookie->getExpire(), |
4006
|
|
|
$cookie->getPath(), |
4007
|
|
|
$cookie->getDomain(), |
4008
|
|
|
$cookie->getSecure(), |
4009
|
|
|
$cookie->getHttpOnly() |
4010
|
|
|
); |
4011
|
|
|
} |
4012
|
|
|
else { |
4013
|
|
|
setcookie( |
4014
|
|
|
$cookie->getName(), |
4015
|
|
|
$cookie->getValue(), |
4016
|
|
|
$cookie->getExpire(), |
4017
|
|
|
$cookie->getPath(), |
4018
|
|
|
$cookie->getDomain(), |
4019
|
|
|
$cookie->getSecure(), |
4020
|
|
|
$cookie->getHttpOnly() |
4021
|
|
|
); |
4022
|
|
|
} |
4023
|
|
|
} |
4024
|
|
|
public function removeCookie($cookie) |
4025
|
|
|
{ |
4026
|
|
|
setcookie( |
4027
|
|
|
$cookie->getName(), |
4028
|
|
|
null, |
4029
|
|
|
0, |
4030
|
|
|
$cookie->getPath(), |
4031
|
|
|
$cookie->getDomain(), |
4032
|
|
|
$cookie->getSecure(), |
4033
|
|
|
$cookie->getHttpOnly() |
4034
|
|
|
); |
4035
|
|
|
} |
4036
|
|
|
public function getHtmlWriterType() |
4037
|
|
|
{ |
4038
|
|
|
return $this->_htmlWriterType; |
4039
|
|
|
} |
4040
|
|
|
public function setHtmlWriterType($value) |
4041
|
|
|
{ |
4042
|
|
|
$this->_htmlWriterType=$value; |
4043
|
|
|
} |
4044
|
|
|
public function createHtmlWriter($type=null) |
4045
|
|
|
{ |
4046
|
|
|
if($type===null) |
4047
|
|
|
$type=$this->getHtmlWriterType(); |
4048
|
|
|
if($this->getHasAdapter()) |
4049
|
|
|
return $this->_adapter->createNewHtmlWriter($type, $this); |
4050
|
|
|
else |
4051
|
|
|
return $this->createNewHtmlWriter($type, $this); |
4052
|
|
|
} |
4053
|
|
|
public function createNewHtmlWriter($type, $writer) |
4054
|
|
|
{ |
4055
|
|
|
return Prado::createComponent($type, $writer); |
4056
|
|
|
} |
4057
|
|
|
} |
4058
|
|
|
class THttpSession extends TApplicationComponent implements IteratorAggregate,ArrayAccess,Countable,IModule |
|
|
|
|
4059
|
|
|
{ |
4060
|
|
|
private $_initialized=false; |
4061
|
|
|
private $_started=false; |
4062
|
|
|
private $_autoStart=false; |
4063
|
|
|
private $_cookie=null; |
4064
|
|
|
private $_id; |
4065
|
|
|
private $_customStorage=false; |
4066
|
|
|
public function getID() |
4067
|
|
|
{ |
4068
|
|
|
return $this->_id; |
4069
|
|
|
} |
4070
|
|
|
public function setID($value) |
4071
|
|
|
{ |
4072
|
|
|
$this->_id=$value; |
4073
|
|
|
} |
4074
|
|
|
public function init($config) |
4075
|
|
|
{ |
4076
|
|
|
if($this->_autoStart) |
4077
|
|
|
$this->open(); |
4078
|
|
|
$this->_initialized=true; |
4079
|
|
|
$this->getApplication()->setSession($this); |
4080
|
|
|
register_shutdown_function(array($this, "close")); |
4081
|
|
|
} |
4082
|
|
|
public function open() |
4083
|
|
|
{ |
4084
|
|
|
if(!$this->_started) |
4085
|
|
|
{ |
4086
|
|
|
if($this->_customStorage) |
4087
|
|
|
session_set_save_handler(array($this,'_open'),array($this,'_close'),array($this,'_read'),array($this,'_write'),array($this,'_destroy'),array($this,'_gc')); |
4088
|
|
|
if($this->_cookie!==null) |
4089
|
|
|
session_set_cookie_params($this->_cookie->getExpire(),$this->_cookie->getPath(),$this->_cookie->getDomain(),$this->_cookie->getSecure(),$this->_cookie->getHttpOnly()); |
4090
|
|
|
if(ini_get('session.auto_start')!=='1') |
4091
|
|
|
session_start(); |
4092
|
|
|
$this->_started=true; |
4093
|
|
|
} |
4094
|
|
|
} |
4095
|
|
|
public function close() |
4096
|
|
|
{ |
4097
|
|
|
if($this->_started) |
4098
|
|
|
{ |
4099
|
|
|
session_write_close(); |
4100
|
|
|
$this->_started=false; |
4101
|
|
|
} |
4102
|
|
|
} |
4103
|
|
|
public function destroy() |
4104
|
|
|
{ |
4105
|
|
|
if($this->_started) |
4106
|
|
|
{ |
4107
|
|
|
session_destroy(); |
4108
|
|
|
$this->_started=false; |
4109
|
|
|
} |
4110
|
|
|
} |
4111
|
|
|
public function regenerate($deleteOld=false) |
4112
|
|
|
{ |
4113
|
|
|
$old = $this->getSessionID(); |
4114
|
|
|
session_regenerate_id($deleteOld); |
4115
|
|
|
return $old; |
4116
|
|
|
} |
4117
|
|
|
public function getIsStarted() |
4118
|
|
|
{ |
4119
|
|
|
return $this->_started; |
4120
|
|
|
} |
4121
|
|
|
public function getSessionID() |
4122
|
|
|
{ |
4123
|
|
|
return session_id(); |
4124
|
|
|
} |
4125
|
|
|
public function setSessionID($value) |
4126
|
|
|
{ |
4127
|
|
|
if($this->_started) |
4128
|
|
|
throw new TInvalidOperationException('httpsession_sessionid_unchangeable'); |
4129
|
|
|
else |
4130
|
|
|
session_id($value); |
4131
|
|
|
} |
4132
|
|
|
public function getSessionName() |
4133
|
|
|
{ |
4134
|
|
|
return session_name(); |
4135
|
|
|
} |
4136
|
|
|
public function setSessionName($value) |
4137
|
|
|
{ |
4138
|
|
|
if($this->_started) |
4139
|
|
|
throw new TInvalidOperationException('httpsession_sessionname_unchangeable'); |
4140
|
|
|
else if(ctype_alnum($value)) |
4141
|
|
|
session_name($value); |
4142
|
|
|
else |
4143
|
|
|
throw new TInvalidDataValueException('httpsession_sessionname_invalid',$value); |
4144
|
|
|
} |
4145
|
|
|
public function getSavePath() |
4146
|
|
|
{ |
4147
|
|
|
return session_save_path(); |
4148
|
|
|
} |
4149
|
|
|
public function setSavePath($value) |
4150
|
|
|
{ |
4151
|
|
|
if($this->_started) |
4152
|
|
|
throw new TInvalidOperationException('httpsession_savepath_unchangeable'); |
4153
|
|
|
else if(is_dir($value)) |
4154
|
|
|
session_save_path($value); |
4155
|
|
|
else |
4156
|
|
|
throw new TInvalidDataValueException('httpsession_savepath_invalid',$value); |
4157
|
|
|
} |
4158
|
|
|
public function getUseCustomStorage() |
4159
|
|
|
{ |
4160
|
|
|
return $this->_customStorage; |
4161
|
|
|
} |
4162
|
|
|
public function setUseCustomStorage($value) |
4163
|
|
|
{ |
4164
|
|
|
$this->_customStorage=TPropertyValue::ensureBoolean($value); |
4165
|
|
|
} |
4166
|
|
|
public function getCookie() |
4167
|
|
|
{ |
4168
|
|
|
if($this->_cookie===null) |
4169
|
|
|
$this->_cookie=new THttpCookie($this->getSessionName(),$this->getSessionID()); |
4170
|
|
|
return $this->_cookie; |
4171
|
|
|
} |
4172
|
|
|
public function getCookieMode() |
4173
|
|
|
{ |
4174
|
|
|
if(ini_get('session.use_cookies')==='0') |
4175
|
|
|
return THttpSessionCookieMode::None; |
4176
|
|
|
else if(ini_get('session.use_only_cookies')==='0') |
4177
|
|
|
return THttpSessionCookieMode::Allow; |
4178
|
|
|
else |
4179
|
|
|
return THttpSessionCookieMode::Only; |
4180
|
|
|
} |
4181
|
|
|
public function setCookieMode($value) |
4182
|
|
|
{ |
4183
|
|
|
if($this->_started) |
4184
|
|
|
throw new TInvalidOperationException('httpsession_cookiemode_unchangeable'); |
4185
|
|
|
else |
4186
|
|
|
{ |
4187
|
|
|
$value=TPropertyValue::ensureEnum($value,'THttpSessionCookieMode'); |
4188
|
|
|
if($value===THttpSessionCookieMode::None) |
4189
|
|
|
{ |
4190
|
|
|
ini_set('session.use_cookies','0'); |
4191
|
|
|
ini_set('session.use_only_cookies','0'); |
4192
|
|
|
} |
4193
|
|
|
else if($value===THttpSessionCookieMode::Allow) |
4194
|
|
|
{ |
4195
|
|
|
ini_set('session.use_cookies','1'); |
4196
|
|
|
ini_set('session.use_only_cookies','0'); |
4197
|
|
|
} |
4198
|
|
|
else |
4199
|
|
|
{ |
4200
|
|
|
ini_set('session.use_cookies','1'); |
4201
|
|
|
ini_set('session.use_only_cookies','1'); |
4202
|
|
|
ini_set('session.use_trans_sid', 0); |
4203
|
|
|
} |
4204
|
|
|
} |
4205
|
|
|
} |
4206
|
|
|
public function getAutoStart() |
4207
|
|
|
{ |
4208
|
|
|
return $this->_autoStart; |
4209
|
|
|
} |
4210
|
|
|
public function setAutoStart($value) |
4211
|
|
|
{ |
4212
|
|
|
if($this->_initialized) |
4213
|
|
|
throw new TInvalidOperationException('httpsession_autostart_unchangeable'); |
4214
|
|
|
else |
4215
|
|
|
$this->_autoStart=TPropertyValue::ensureBoolean($value); |
4216
|
|
|
} |
4217
|
|
|
public function getGCProbability() |
4218
|
|
|
{ |
4219
|
|
|
return TPropertyValue::ensureInteger(ini_get('session.gc_probability')); |
4220
|
|
|
} |
4221
|
|
|
public function setGCProbability($value) |
4222
|
|
|
{ |
4223
|
|
|
if($this->_started) |
4224
|
|
|
throw new TInvalidOperationException('httpsession_gcprobability_unchangeable'); |
4225
|
|
|
else |
4226
|
|
|
{ |
4227
|
|
|
$value=TPropertyValue::ensureInteger($value); |
4228
|
|
|
if($value>=0 && $value<=100) |
4229
|
|
|
{ |
4230
|
|
|
ini_set('session.gc_probability',$value); |
4231
|
|
|
ini_set('session.gc_divisor','100'); |
4232
|
|
|
} |
4233
|
|
|
else |
4234
|
|
|
throw new TInvalidDataValueException('httpsession_gcprobability_invalid',$value); |
4235
|
|
|
} |
4236
|
|
|
} |
4237
|
|
|
public function getUseTransparentSessionID() |
4238
|
|
|
{ |
4239
|
|
|
return ini_get('session.use_trans_sid')==='1'; |
4240
|
|
|
} |
4241
|
|
|
public function setUseTransparentSessionID($value) |
4242
|
|
|
{ |
4243
|
|
|
if($this->_started) |
4244
|
|
|
throw new TInvalidOperationException('httpsession_transid_unchangeable'); |
4245
|
|
|
else |
4246
|
|
|
{ |
4247
|
|
|
$value=TPropertyValue::ensureBoolean($value); |
4248
|
|
|
if ($value && $this->getCookieMode()==THttpSessionCookieMode::Only) |
4249
|
|
|
throw new TInvalidOperationException('httpsession_transid_cookieonly'); |
4250
|
|
|
ini_set('session.use_trans_sid',$value?'1':'0'); |
4251
|
|
|
} |
4252
|
|
|
} |
4253
|
|
|
public function getTimeout() |
4254
|
|
|
{ |
4255
|
|
|
return TPropertyValue::ensureInteger(ini_get('session.gc_maxlifetime')); |
4256
|
|
|
} |
4257
|
|
|
public function setTimeout($value) |
4258
|
|
|
{ |
4259
|
|
|
if($this->_started) |
4260
|
|
|
throw new TInvalidOperationException('httpsession_maxlifetime_unchangeable'); |
4261
|
|
|
else |
4262
|
|
|
ini_set('session.gc_maxlifetime',$value); |
4263
|
|
|
} |
4264
|
|
|
public function _open($savePath,$sessionName) |
4265
|
|
|
{ |
4266
|
|
|
return true; |
4267
|
|
|
} |
4268
|
|
|
public function _close() |
4269
|
|
|
{ |
4270
|
|
|
return true; |
4271
|
|
|
} |
4272
|
|
|
public function _read($id) |
4273
|
|
|
{ |
4274
|
|
|
return ''; |
4275
|
|
|
} |
4276
|
|
|
public function _write($id,$data) |
4277
|
|
|
{ |
4278
|
|
|
return true; |
4279
|
|
|
} |
4280
|
|
|
public function _destroy($id) |
4281
|
|
|
{ |
4282
|
|
|
return true; |
4283
|
|
|
} |
4284
|
|
|
public function _gc($maxLifetime) |
4285
|
|
|
{ |
4286
|
|
|
return true; |
4287
|
|
|
} |
4288
|
|
|
public function getIterator() |
4289
|
|
|
{ |
4290
|
|
|
return new TSessionIterator; |
4291
|
|
|
} |
4292
|
|
|
public function getCount() |
|
|
|
|
4293
|
|
|
{ |
4294
|
|
|
return count($_SESSION); |
4295
|
|
|
} |
4296
|
|
|
public function count() |
4297
|
|
|
{ |
4298
|
|
|
return $this->getCount(); |
4299
|
|
|
} |
4300
|
|
|
public function getKeys() |
|
|
|
|
4301
|
|
|
{ |
4302
|
|
|
return array_keys($_SESSION); |
4303
|
|
|
} |
4304
|
|
|
public function itemAt($key) |
|
|
|
|
4305
|
|
|
{ |
4306
|
|
|
return isset($_SESSION[$key]) ? $_SESSION[$key] : null; |
4307
|
|
|
} |
4308
|
|
|
public function add($key,$value) |
|
|
|
|
4309
|
|
|
{ |
4310
|
|
|
$_SESSION[$key]=$value; |
4311
|
|
|
} |
4312
|
|
|
public function remove($key) |
|
|
|
|
4313
|
|
|
{ |
4314
|
|
|
if(isset($_SESSION[$key])) |
4315
|
|
|
{ |
4316
|
|
|
$value=$_SESSION[$key]; |
4317
|
|
|
unset($_SESSION[$key]); |
4318
|
|
|
return $value; |
4319
|
|
|
} |
4320
|
|
|
else |
4321
|
|
|
return null; |
4322
|
|
|
} |
4323
|
|
|
public function clear() |
|
|
|
|
4324
|
|
|
{ |
4325
|
|
|
foreach(array_keys($_SESSION) as $key) |
4326
|
|
|
unset($_SESSION[$key]); |
4327
|
|
|
} |
4328
|
|
|
public function contains($key) |
|
|
|
|
4329
|
|
|
{ |
4330
|
|
|
return isset($_SESSION[$key]); |
4331
|
|
|
} |
4332
|
|
|
public function toArray() |
|
|
|
|
4333
|
|
|
{ |
4334
|
|
|
return $_SESSION; |
4335
|
|
|
} |
4336
|
|
|
public function offsetExists($offset) |
|
|
|
|
4337
|
|
|
{ |
4338
|
|
|
return isset($_SESSION[$offset]); |
4339
|
|
|
} |
4340
|
|
|
public function offsetGet($offset) |
|
|
|
|
4341
|
|
|
{ |
4342
|
|
|
return isset($_SESSION[$offset]) ? $_SESSION[$offset] : null; |
4343
|
|
|
} |
4344
|
|
|
public function offsetSet($offset,$item) |
|
|
|
|
4345
|
|
|
{ |
4346
|
|
|
$_SESSION[$offset]=$item; |
4347
|
|
|
} |
4348
|
|
|
public function offsetUnset($offset) |
|
|
|
|
4349
|
|
|
{ |
4350
|
|
|
unset($_SESSION[$offset]); |
4351
|
|
|
} |
4352
|
|
|
} |
4353
|
|
|
class TSessionIterator implements Iterator |
4354
|
|
|
{ |
4355
|
|
|
private $_keys; |
4356
|
|
|
private $_key; |
4357
|
|
|
public function __construct() |
|
|
|
|
4358
|
|
|
{ |
4359
|
|
|
$this->_keys=array_keys($_SESSION); |
4360
|
|
|
} |
4361
|
|
|
public function rewind() |
4362
|
|
|
{ |
4363
|
|
|
$this->_key=reset($this->_keys); |
4364
|
|
|
} |
4365
|
|
|
public function key() |
4366
|
|
|
{ |
4367
|
|
|
return $this->_key; |
4368
|
|
|
} |
4369
|
|
|
public function current() |
|
|
|
|
4370
|
|
|
{ |
4371
|
|
|
return isset($_SESSION[$this->_key])?$_SESSION[$this->_key]:null; |
4372
|
|
|
} |
4373
|
|
|
public function next() |
|
|
|
|
4374
|
|
|
{ |
4375
|
|
|
do |
4376
|
|
|
{ |
4377
|
|
|
$this->_key=next($this->_keys); |
4378
|
|
|
} |
4379
|
|
|
while(!isset($_SESSION[$this->_key]) && $this->_key!==false); |
4380
|
|
|
} |
4381
|
|
|
public function valid() |
4382
|
|
|
{ |
4383
|
|
|
return $this->_key!==false; |
4384
|
|
|
} |
4385
|
|
|
} |
4386
|
|
|
class THttpSessionCookieMode extends TEnumerable |
4387
|
|
|
{ |
4388
|
|
|
const None='None'; |
4389
|
|
|
const Allow='Allow'; |
4390
|
|
|
const Only='Only'; |
4391
|
|
|
} |
4392
|
|
|
Prado::using('System.Web.UI.WebControls.*'); |
4393
|
|
|
class TAttributeCollection extends TMap |
4394
|
|
|
{ |
4395
|
|
|
private $_caseSensitive=false; |
4396
|
|
|
protected function _getZappableSleepProps(&$exprops) |
4397
|
|
|
{ |
4398
|
|
|
parent::_getZappableSleepProps($exprops); |
4399
|
|
|
if ($this->_caseSensitive===false) |
4400
|
|
|
$exprops[] = "\0TAttributeCollection\0_caseSensitive"; |
4401
|
|
|
} |
4402
|
|
|
public function __get($name) |
4403
|
|
|
{ |
4404
|
|
|
return $this->contains($name)?$this->itemAt($name):parent::__get($name); |
4405
|
|
|
} |
4406
|
|
|
public function __set($name,$value) |
4407
|
|
|
{ |
4408
|
|
|
$this->add($name,$value); |
4409
|
|
|
} |
4410
|
|
|
public function getCaseSensitive() |
4411
|
|
|
{ |
4412
|
|
|
return $this->_caseSensitive; |
4413
|
|
|
} |
4414
|
|
|
public function setCaseSensitive($value) |
4415
|
|
|
{ |
4416
|
|
|
$this->_caseSensitive=TPropertyValue::ensureBoolean($value); |
4417
|
|
|
} |
4418
|
|
|
public function itemAt($key) |
4419
|
|
|
{ |
4420
|
|
|
return parent::itemAt($this->_caseSensitive?$key:strtolower($key)); |
4421
|
|
|
} |
4422
|
|
|
public function add($key,$value) |
4423
|
|
|
{ |
4424
|
|
|
parent::add($this->_caseSensitive?$key:strtolower($key),$value); |
4425
|
|
|
} |
4426
|
|
|
public function remove($key) |
4427
|
|
|
{ |
4428
|
|
|
return parent::remove($this->_caseSensitive?$key:strtolower($key)); |
4429
|
|
|
} |
4430
|
|
|
public function contains($key) |
4431
|
|
|
{ |
4432
|
|
|
return parent::contains($this->_caseSensitive?$key:strtolower($key)); |
4433
|
|
|
} |
4434
|
|
|
public function hasProperty($name) |
4435
|
|
|
{ |
4436
|
|
|
return $this->contains($name) || parent::canGetProperty($name) || parent::canSetProperty($name); |
4437
|
|
|
} |
4438
|
|
|
public function canGetProperty($name) |
4439
|
|
|
{ |
4440
|
|
|
return $this->contains($name) || parent::canGetProperty($name); |
4441
|
|
|
} |
4442
|
|
|
public function canSetProperty($name) |
4443
|
|
|
{ |
4444
|
|
|
return true; |
4445
|
|
|
} |
4446
|
|
|
} |
4447
|
|
|
class TControlAdapter extends TApplicationComponent |
4448
|
|
|
{ |
4449
|
|
|
protected $_control; |
4450
|
|
|
public function __construct($control) |
4451
|
|
|
{ |
4452
|
|
|
$this->_control=$control; |
4453
|
|
|
} |
4454
|
|
|
public function getControl() |
4455
|
|
|
{ |
4456
|
|
|
return $this->_control; |
4457
|
|
|
} |
4458
|
|
|
public function getPage() |
4459
|
|
|
{ |
4460
|
|
|
return $this->_control?$this->_control->getPage():null; |
4461
|
|
|
} |
4462
|
|
|
public function createChildControls() |
4463
|
|
|
{ |
4464
|
|
|
$this->_control->createChildControls(); |
4465
|
|
|
} |
4466
|
|
|
public function loadState() |
4467
|
|
|
{ |
4468
|
|
|
$this->_control->loadState(); |
4469
|
|
|
} |
4470
|
|
|
public function saveState() |
4471
|
|
|
{ |
4472
|
|
|
$this->_control->saveState(); |
4473
|
|
|
} |
4474
|
|
|
public function onInit($param) |
4475
|
|
|
{ |
4476
|
|
|
$this->_control->onInit($param); |
4477
|
|
|
} |
4478
|
|
|
public function onLoad($param) |
4479
|
|
|
{ |
4480
|
|
|
$this->_control->onLoad($param); |
4481
|
|
|
} |
4482
|
|
|
public function onPreRender($param) |
4483
|
|
|
{ |
4484
|
|
|
$this->_control->onPreRender($param); |
4485
|
|
|
} |
4486
|
|
|
public function onUnload($param) |
4487
|
|
|
{ |
4488
|
|
|
$this->_control->onUnload($param); |
4489
|
|
|
} |
4490
|
|
|
public function render($writer) |
4491
|
|
|
{ |
4492
|
|
|
$this->_control->render($writer); |
4493
|
|
|
} |
4494
|
|
|
public function renderChildren($writer) |
4495
|
|
|
{ |
4496
|
|
|
$this->_control->renderChildren($writer); |
4497
|
|
|
} |
4498
|
|
|
} |
4499
|
|
|
class TControl extends TApplicationComponent implements IRenderable, IBindable |
4500
|
|
|
{ |
4501
|
|
|
const ID_FORMAT='/^[a-zA-Z_]\\w*$/'; |
4502
|
|
|
const ID_SEPARATOR='$'; |
4503
|
|
|
const CLIENT_ID_SEPARATOR='_'; |
4504
|
|
|
const AUTOMATIC_ID_PREFIX='ctl'; |
4505
|
|
|
const CS_CONSTRUCTED=0; |
4506
|
|
|
const CS_CHILD_INITIALIZED=1; |
4507
|
|
|
const CS_INITIALIZED=2; |
4508
|
|
|
const CS_STATE_LOADED=3; |
4509
|
|
|
const CS_LOADED=4; |
4510
|
|
|
const CS_PRERENDERED=5; |
4511
|
|
|
const IS_ID_SET=0x01; |
4512
|
|
|
const IS_DISABLE_VIEWSTATE=0x02; |
4513
|
|
|
const IS_SKIN_APPLIED=0x04; |
4514
|
|
|
const IS_STYLESHEET_APPLIED=0x08; |
4515
|
|
|
const IS_DISABLE_THEMING=0x10; |
4516
|
|
|
const IS_CHILD_CREATED=0x20; |
4517
|
|
|
const IS_CREATING_CHILD=0x40; |
4518
|
|
|
const RF_CONTROLS=0; const RF_CHILD_STATE=1; const RF_NAMED_CONTROLS=2; const RF_NAMED_CONTROLS_ID=3; const RF_SKIN_ID=4; const RF_DATA_BINDINGS=5; const RF_EVENTS=6; const RF_CONTROLSTATE=7; const RF_NAMED_OBJECTS=8; const RF_ADAPTER=9; const RF_AUTO_BINDINGS=10; |
|
|
|
|
4519
|
|
|
private $_id=''; |
4520
|
|
|
private $_uid; |
4521
|
|
|
private $_parent; |
4522
|
|
|
private $_page; |
4523
|
|
|
private $_namingContainer; |
4524
|
|
|
private $_tplControl; |
4525
|
|
|
private $_viewState=array(); |
4526
|
|
|
private $_tempState=array(); |
4527
|
|
|
private $_trackViewState=true; |
4528
|
|
|
private $_stage=0; |
4529
|
|
|
private $_flags=0; |
4530
|
|
|
private $_rf=array(); |
4531
|
|
|
public function __get($name) |
4532
|
|
|
{ |
4533
|
|
|
if(isset($this->_rf[self::RF_NAMED_OBJECTS][$name])) |
4534
|
|
|
return $this->_rf[self::RF_NAMED_OBJECTS][$name]; |
4535
|
|
|
else |
4536
|
|
|
return parent::__get($name); |
4537
|
|
|
} |
4538
|
|
|
public function __isset($name) { |
4539
|
|
|
if(isset($this->_rf[self::RF_NAMED_OBJECTS][$name])) { |
4540
|
|
|
return true; |
4541
|
|
|
} else { |
4542
|
|
|
return parent::__isset($name); |
4543
|
|
|
} |
4544
|
|
|
} |
4545
|
|
|
public function getHasAdapter() |
4546
|
|
|
{ |
4547
|
|
|
return isset($this->_rf[self::RF_ADAPTER]); |
4548
|
|
|
} |
4549
|
|
|
public function getAdapter() |
4550
|
|
|
{ |
4551
|
|
|
return isset($this->_rf[self::RF_ADAPTER])?$this->_rf[self::RF_ADAPTER]:null; |
4552
|
|
|
} |
4553
|
|
|
public function setAdapter(TControlAdapter $adapter) |
4554
|
|
|
{ |
4555
|
|
|
$this->_rf[self::RF_ADAPTER]=$adapter; |
4556
|
|
|
} |
4557
|
|
|
public function getParent() |
4558
|
|
|
{ |
4559
|
|
|
return $this->_parent; |
4560
|
|
|
} |
4561
|
|
|
public function getNamingContainer() |
4562
|
|
|
{ |
4563
|
|
|
if(!$this->_namingContainer && $this->_parent) |
4564
|
|
|
{ |
4565
|
|
|
if($this->_parent instanceof INamingContainer) |
4566
|
|
|
$this->_namingContainer=$this->_parent; |
4567
|
|
|
else |
4568
|
|
|
$this->_namingContainer=$this->_parent->getNamingContainer(); |
4569
|
|
|
} |
4570
|
|
|
return $this->_namingContainer; |
4571
|
|
|
} |
4572
|
|
|
public function getPage() |
4573
|
|
|
{ |
4574
|
|
|
if(!$this->_page) |
4575
|
|
|
{ |
4576
|
|
|
if($this->_parent) |
4577
|
|
|
$this->_page=$this->_parent->getPage(); |
4578
|
|
|
else if($this->_tplControl) |
4579
|
|
|
$this->_page=$this->_tplControl->getPage(); |
4580
|
|
|
} |
4581
|
|
|
return $this->_page; |
4582
|
|
|
} |
4583
|
|
|
public function setPage($page) |
4584
|
|
|
{ |
4585
|
|
|
$this->_page=$page; |
4586
|
|
|
} |
4587
|
|
|
public function setTemplateControl($control) |
4588
|
|
|
{ |
4589
|
|
|
$this->_tplControl=$control; |
4590
|
|
|
} |
4591
|
|
|
public function getTemplateControl() |
4592
|
|
|
{ |
4593
|
|
|
if(!$this->_tplControl && $this->_parent) |
4594
|
|
|
$this->_tplControl=$this->_parent->getTemplateControl(); |
4595
|
|
|
return $this->_tplControl; |
4596
|
|
|
} |
4597
|
|
|
public function getSourceTemplateControl() |
4598
|
|
|
{ |
4599
|
|
|
$control=$this; |
4600
|
|
|
while(($control instanceof TControl) && ($control=$control->getTemplateControl())!==null) |
4601
|
|
|
{ |
4602
|
|
|
if(($control instanceof TTemplateControl) && $control->getIsSourceTemplateControl()) |
4603
|
|
|
return $control; |
4604
|
|
|
} |
4605
|
|
|
return $this->getPage(); |
4606
|
|
|
} |
4607
|
|
|
protected function getControlStage() |
4608
|
|
|
{ |
4609
|
|
|
return $this->_stage; |
4610
|
|
|
} |
4611
|
|
|
protected function setControlStage($value) |
4612
|
|
|
{ |
4613
|
|
|
$this->_stage=$value; |
4614
|
|
|
} |
4615
|
|
|
public function getID($hideAutoID=true) |
4616
|
|
|
{ |
4617
|
|
|
if($hideAutoID) |
4618
|
|
|
return ($this->_flags & self::IS_ID_SET) ? $this->_id : ''; |
4619
|
|
|
else |
4620
|
|
|
return $this->_id; |
4621
|
|
|
} |
4622
|
|
|
public function setID($id) |
4623
|
|
|
{ |
4624
|
|
|
if(!preg_match(self::ID_FORMAT,$id)) |
4625
|
|
|
throw new TInvalidDataValueException('control_id_invalid',get_class($this),$id); |
4626
|
|
|
$this->_id=$id; |
4627
|
|
|
$this->_flags |= self::IS_ID_SET; |
4628
|
|
|
$this->clearCachedUniqueID($this instanceof INamingContainer); |
4629
|
|
|
if($this->_namingContainer) |
4630
|
|
|
$this->_namingContainer->clearNameTable(); |
4631
|
|
|
} |
4632
|
|
|
public function getUniqueID() |
4633
|
|
|
{ |
4634
|
|
|
if($this->_uid==='' || $this->_uid===null) { |
4635
|
|
|
$this->_uid=''; if($namingContainer=$this->getNamingContainer()) |
4636
|
|
|
{ |
4637
|
|
|
if($this->getPage()===$namingContainer) |
4638
|
|
|
return ($this->_uid=$this->_id); |
4639
|
|
|
else if(($prefix=$namingContainer->getUniqueID())==='') |
4640
|
|
|
return $this->_id; |
4641
|
|
|
else |
4642
|
|
|
return ($this->_uid=$prefix.self::ID_SEPARATOR.$this->_id); |
4643
|
|
|
} |
4644
|
|
|
else return $this->_id; |
4645
|
|
|
} |
4646
|
|
|
else |
4647
|
|
|
return $this->_uid; |
4648
|
|
|
} |
4649
|
|
|
public function focus() |
4650
|
|
|
{ |
4651
|
|
|
$this->getPage()->setFocus($this); |
4652
|
|
|
} |
4653
|
|
|
public function getClientID() |
4654
|
|
|
{ |
4655
|
|
|
return strtr($this->getUniqueID(),self::ID_SEPARATOR,self::CLIENT_ID_SEPARATOR); |
4656
|
|
|
} |
4657
|
|
|
public static function convertUniqueIdToClientId($uniqueID) |
4658
|
|
|
{ |
4659
|
|
|
return strtr($uniqueID,self::ID_SEPARATOR,self::CLIENT_ID_SEPARATOR); |
4660
|
|
|
} |
4661
|
|
|
public function getSkinID() |
4662
|
|
|
{ |
4663
|
|
|
return isset($this->_rf[self::RF_SKIN_ID])?$this->_rf[self::RF_SKIN_ID]:''; |
4664
|
|
|
} |
4665
|
|
|
public function setSkinID($value) |
4666
|
|
|
{ |
4667
|
|
|
if(($this->_flags & self::IS_SKIN_APPLIED) || $this->_stage>=self::CS_CHILD_INITIALIZED) |
4668
|
|
|
throw new TInvalidOperationException('control_skinid_unchangeable',get_class($this)); |
4669
|
|
|
else |
4670
|
|
|
$this->_rf[self::RF_SKIN_ID]=$value; |
4671
|
|
|
} |
4672
|
|
|
public function getIsSkinApplied() |
4673
|
|
|
{ |
4674
|
|
|
return ($this->_flags & self::IS_SKIN_APPLIED); |
4675
|
|
|
} |
4676
|
|
|
public function getEnableTheming() |
4677
|
|
|
{ |
4678
|
|
|
if($this->_flags & self::IS_DISABLE_THEMING) |
4679
|
|
|
return false; |
4680
|
|
|
else |
4681
|
|
|
return $this->_parent?$this->_parent->getEnableTheming():true; |
4682
|
|
|
} |
4683
|
|
|
public function setEnableTheming($value) |
4684
|
|
|
{ |
4685
|
|
|
if($this->_stage>=self::CS_CHILD_INITIALIZED) |
4686
|
|
|
throw new TInvalidOperationException('control_enabletheming_unchangeable',get_class($this),$this->getUniqueID()); |
4687
|
|
|
else if(TPropertyValue::ensureBoolean($value)) |
4688
|
|
|
$this->_flags &= ~self::IS_DISABLE_THEMING; |
4689
|
|
|
else |
4690
|
|
|
$this->_flags |= self::IS_DISABLE_THEMING; |
4691
|
|
|
} |
4692
|
|
|
public function getCustomData() |
4693
|
|
|
{ |
4694
|
|
|
return $this->getViewState('CustomData',null); |
4695
|
|
|
} |
4696
|
|
|
public function setCustomData($value) |
4697
|
|
|
{ |
4698
|
|
|
$this->setViewState('CustomData',$value,null); |
4699
|
|
|
} |
4700
|
|
|
public function getHasControls() |
4701
|
|
|
{ |
4702
|
|
|
return isset($this->_rf[self::RF_CONTROLS]) && $this->_rf[self::RF_CONTROLS]->getCount()>0; |
4703
|
|
|
} |
4704
|
|
|
public function getControls() |
4705
|
|
|
{ |
4706
|
|
|
if(!isset($this->_rf[self::RF_CONTROLS])) |
4707
|
|
|
$this->_rf[self::RF_CONTROLS]=$this->createControlCollection(); |
4708
|
|
|
return $this->_rf[self::RF_CONTROLS]; |
4709
|
|
|
} |
4710
|
|
|
protected function createControlCollection() |
4711
|
|
|
{ |
4712
|
|
|
return $this->getAllowChildControls()?new TControlCollection($this):new TEmptyControlCollection($this); |
4713
|
|
|
} |
4714
|
|
|
public function getVisible($checkParents=true) |
4715
|
|
|
{ |
4716
|
|
|
if($checkParents) |
4717
|
|
|
{ |
4718
|
|
|
for($control=$this;$control;$control=$control->_parent) |
4719
|
|
|
if(!$control->getVisible(false)) |
4720
|
|
|
return false; |
4721
|
|
|
return true; |
4722
|
|
|
} |
4723
|
|
|
else |
4724
|
|
|
return $this->getViewState('Visible',true); |
4725
|
|
|
} |
4726
|
|
|
public function setVisible($value) |
4727
|
|
|
{ |
4728
|
|
|
$this->setViewState('Visible',TPropertyValue::ensureBoolean($value),true); |
4729
|
|
|
} |
4730
|
|
|
public function getEnabled($checkParents=false) |
4731
|
|
|
{ |
4732
|
|
|
if($checkParents) |
4733
|
|
|
{ |
4734
|
|
|
for($control=$this;$control;$control=$control->_parent) |
4735
|
|
|
if(!$control->getViewState('Enabled',true)) |
4736
|
|
|
return false; |
4737
|
|
|
return true; |
4738
|
|
|
} |
4739
|
|
|
else |
4740
|
|
|
return $this->getViewState('Enabled',true); |
4741
|
|
|
} |
4742
|
|
|
public function setEnabled($value) |
4743
|
|
|
{ |
4744
|
|
|
$this->setViewState('Enabled',TPropertyValue::ensureBoolean($value),true); |
4745
|
|
|
} |
4746
|
|
|
public function getHasAttributes() |
4747
|
|
|
{ |
4748
|
|
|
if($attributes=$this->getViewState('Attributes',null)) |
4749
|
|
|
return $attributes->getCount()>0; |
4750
|
|
|
else |
4751
|
|
|
return false; |
4752
|
|
|
} |
4753
|
|
|
public function getAttributes() |
4754
|
|
|
{ |
4755
|
|
|
if($attributes=$this->getViewState('Attributes',null)) |
4756
|
|
|
return $attributes; |
4757
|
|
|
else |
4758
|
|
|
{ |
4759
|
|
|
$attributes=new TAttributeCollection; |
4760
|
|
|
$this->setViewState('Attributes',$attributes,null); |
4761
|
|
|
return $attributes; |
4762
|
|
|
} |
4763
|
|
|
} |
4764
|
|
|
public function hasAttribute($name) |
4765
|
|
|
{ |
4766
|
|
|
if($attributes=$this->getViewState('Attributes',null)) |
4767
|
|
|
return $attributes->contains($name); |
4768
|
|
|
else |
4769
|
|
|
return false; |
4770
|
|
|
} |
4771
|
|
|
public function getAttribute($name) |
4772
|
|
|
{ |
4773
|
|
|
if($attributes=$this->getViewState('Attributes',null)) |
4774
|
|
|
return $attributes->itemAt($name); |
4775
|
|
|
else |
4776
|
|
|
return null; |
4777
|
|
|
} |
4778
|
|
|
public function setAttribute($name,$value) |
4779
|
|
|
{ |
4780
|
|
|
$this->getAttributes()->add($name,$value); |
4781
|
|
|
} |
4782
|
|
|
public function removeAttribute($name) |
4783
|
|
|
{ |
4784
|
|
|
if($attributes=$this->getViewState('Attributes',null)) |
4785
|
|
|
return $attributes->remove($name); |
4786
|
|
|
else |
4787
|
|
|
return null; |
4788
|
|
|
} |
4789
|
|
|
public function getEnableViewState($checkParents=false) |
4790
|
|
|
{ |
4791
|
|
|
if($checkParents) |
4792
|
|
|
{ |
4793
|
|
|
for($control=$this;$control!==null;$control=$control->getParent()) |
4794
|
|
|
if($control->_flags & self::IS_DISABLE_VIEWSTATE) |
4795
|
|
|
return false; |
4796
|
|
|
return true; |
4797
|
|
|
} |
4798
|
|
|
else |
4799
|
|
|
return !($this->_flags & self::IS_DISABLE_VIEWSTATE); |
4800
|
|
|
} |
4801
|
|
|
public function setEnableViewState($value) |
4802
|
|
|
{ |
4803
|
|
|
if(TPropertyValue::ensureBoolean($value)) |
4804
|
|
|
$this->_flags &= ~self::IS_DISABLE_VIEWSTATE; |
4805
|
|
|
else |
4806
|
|
|
$this->_flags |= self::IS_DISABLE_VIEWSTATE; |
4807
|
|
|
} |
4808
|
|
|
protected function getControlState($key,$defaultValue=null) |
4809
|
|
|
{ |
4810
|
|
|
return isset($this->_rf[self::RF_CONTROLSTATE][$key])?$this->_rf[self::RF_CONTROLSTATE][$key]:$defaultValue; |
4811
|
|
|
} |
4812
|
|
|
protected function setControlState($key,$value,$defaultValue=null) |
4813
|
|
|
{ |
4814
|
|
|
if($value===$defaultValue) |
4815
|
|
|
unset($this->_rf[self::RF_CONTROLSTATE][$key]); |
4816
|
|
|
else |
4817
|
|
|
$this->_rf[self::RF_CONTROLSTATE][$key]=$value; |
4818
|
|
|
} |
4819
|
|
|
protected function clearControlState($key) |
4820
|
|
|
{ |
4821
|
|
|
unset($this->_rf[self::RF_CONTROLSTATE][$key]); |
4822
|
|
|
} |
4823
|
|
|
public function trackViewState($enabled) |
4824
|
|
|
{ |
4825
|
|
|
$this->_trackViewState=TPropertyValue::ensureBoolean($enabled); |
4826
|
|
|
} |
4827
|
|
|
public function getViewState($key,$defaultValue=null) |
4828
|
|
|
{ |
4829
|
|
|
if(isset($this->_viewState[$key])) |
4830
|
|
|
return $this->_viewState[$key]!==null?$this->_viewState[$key]:$defaultValue; |
4831
|
|
|
else if(isset($this->_tempState[$key])) |
4832
|
|
|
{ |
4833
|
|
|
if(is_object($this->_tempState[$key]) && $this->_trackViewState) |
4834
|
|
|
$this->_viewState[$key]=$this->_tempState[$key]; |
4835
|
|
|
return $this->_tempState[$key]; |
4836
|
|
|
} |
4837
|
|
|
else |
4838
|
|
|
return $defaultValue; |
4839
|
|
|
} |
4840
|
|
|
public function setViewState($key,$value,$defaultValue=null) |
4841
|
|
|
{ |
4842
|
|
|
if($this->_trackViewState) |
4843
|
|
|
{ |
4844
|
|
|
unset($this->_tempState[$key]); |
4845
|
|
|
$this->_viewState[$key]=$value; |
4846
|
|
|
} |
4847
|
|
|
else |
4848
|
|
|
{ |
4849
|
|
|
unset($this->_viewState[$key]); |
4850
|
|
|
if($value===$defaultValue) |
4851
|
|
|
unset($this->_tempState[$key]); |
4852
|
|
|
else |
4853
|
|
|
$this->_tempState[$key]=$value; |
4854
|
|
|
} |
4855
|
|
|
} |
4856
|
|
|
public function clearViewState($key) |
4857
|
|
|
{ |
4858
|
|
|
unset($this->_viewState[$key]); |
4859
|
|
|
unset($this->_tempState[$key]); |
4860
|
|
|
} |
4861
|
|
|
public function bindProperty($name,$expression) |
4862
|
|
|
{ |
4863
|
|
|
$this->_rf[self::RF_DATA_BINDINGS][$name]=$expression; |
4864
|
|
|
} |
4865
|
|
|
public function unbindProperty($name) |
4866
|
|
|
{ |
4867
|
|
|
unset($this->_rf[self::RF_DATA_BINDINGS][$name]); |
4868
|
|
|
} |
4869
|
|
|
public function autoBindProperty($name,$expression) |
4870
|
|
|
{ |
4871
|
|
|
$this->_rf[self::RF_AUTO_BINDINGS][$name]=$expression; |
4872
|
|
|
} |
4873
|
|
|
public function dataBind() |
4874
|
|
|
{ |
4875
|
|
|
$this->dataBindProperties(); |
4876
|
|
|
$this->onDataBinding(null); |
4877
|
|
|
$this->dataBindChildren(); |
4878
|
|
|
} |
4879
|
|
|
protected function dataBindProperties() |
4880
|
|
|
{ |
4881
|
|
|
if(isset($this->_rf[self::RF_DATA_BINDINGS])) |
4882
|
|
|
{ |
4883
|
|
|
if(($context=$this->getTemplateControl())===null) |
4884
|
|
|
$context=$this; |
4885
|
|
|
foreach($this->_rf[self::RF_DATA_BINDINGS] as $property=>$expression) |
4886
|
|
|
$this->setSubProperty($property,$context->evaluateExpression($expression)); |
4887
|
|
|
} |
4888
|
|
|
} |
4889
|
|
|
protected function autoDataBindProperties() |
4890
|
|
|
{ |
4891
|
|
|
if(isset($this->_rf[self::RF_AUTO_BINDINGS])) |
4892
|
|
|
{ |
4893
|
|
|
if(($context=$this->getTemplateControl())===null) |
4894
|
|
|
$context=$this; |
4895
|
|
|
foreach($this->_rf[self::RF_AUTO_BINDINGS] as $property=>$expression) |
4896
|
|
|
$this->setSubProperty($property,$context->evaluateExpression($expression)); |
4897
|
|
|
} |
4898
|
|
|
} |
4899
|
|
|
protected function dataBindChildren() |
4900
|
|
|
{ |
4901
|
|
|
if(isset($this->_rf[self::RF_CONTROLS])) |
4902
|
|
|
{ |
4903
|
|
|
foreach($this->_rf[self::RF_CONTROLS] as $control) |
4904
|
|
|
if($control instanceof IBindable) |
4905
|
|
|
$control->dataBind(); |
4906
|
|
|
} |
4907
|
|
|
} |
4908
|
|
|
final protected function getChildControlsCreated() |
4909
|
|
|
{ |
4910
|
|
|
return ($this->_flags & self::IS_CHILD_CREATED)!==0; |
4911
|
|
|
} |
4912
|
|
|
final protected function setChildControlsCreated($value) |
4913
|
|
|
{ |
4914
|
|
|
if($value) |
4915
|
|
|
$this->_flags |= self::IS_CHILD_CREATED; |
4916
|
|
|
else |
4917
|
|
|
{ |
4918
|
|
|
if($this->getHasControls() && ($this->_flags & self::IS_CHILD_CREATED)) |
4919
|
|
|
$this->getControls()->clear(); |
4920
|
|
|
$this->_flags &= ~self::IS_CHILD_CREATED; |
4921
|
|
|
} |
4922
|
|
|
} |
4923
|
|
|
public function ensureChildControls() |
4924
|
|
|
{ |
4925
|
|
|
if(!($this->_flags & self::IS_CHILD_CREATED) && !($this->_flags & self::IS_CREATING_CHILD)) |
4926
|
|
|
{ |
4927
|
|
|
try |
4928
|
|
|
{ |
4929
|
|
|
$this->_flags |= self::IS_CREATING_CHILD; |
4930
|
|
|
if(isset($this->_rf[self::RF_ADAPTER])) |
4931
|
|
|
$this->_rf[self::RF_ADAPTER]->createChildControls(); |
4932
|
|
|
else |
4933
|
|
|
$this->createChildControls(); |
4934
|
|
|
$this->_flags &= ~self::IS_CREATING_CHILD; |
4935
|
|
|
$this->_flags |= self::IS_CHILD_CREATED; |
4936
|
|
|
} |
4937
|
|
|
catch(Exception $e) |
4938
|
|
|
{ |
4939
|
|
|
$this->_flags &= ~self::IS_CREATING_CHILD; |
4940
|
|
|
$this->_flags |= self::IS_CHILD_CREATED; |
4941
|
|
|
throw $e; |
4942
|
|
|
} |
4943
|
|
|
} |
4944
|
|
|
} |
4945
|
|
|
public function createChildControls() |
4946
|
|
|
{ |
4947
|
|
|
} |
4948
|
|
|
public function findControl($id) |
4949
|
|
|
{ |
4950
|
|
|
$id=strtr($id,'.',self::ID_SEPARATOR); |
4951
|
|
|
$container=($this instanceof INamingContainer)?$this:$this->getNamingContainer(); |
4952
|
|
|
if(!$container || !$container->getHasControls()) |
4953
|
|
|
return null; |
4954
|
|
|
if(!isset($container->_rf[self::RF_NAMED_CONTROLS])) |
4955
|
|
|
{ |
4956
|
|
|
$container->_rf[self::RF_NAMED_CONTROLS]=array(); |
4957
|
|
|
$container->fillNameTable($container,$container->_rf[self::RF_CONTROLS]); |
4958
|
|
|
} |
4959
|
|
|
if(($pos=strpos($id,self::ID_SEPARATOR))===false) |
4960
|
|
|
return isset($container->_rf[self::RF_NAMED_CONTROLS][$id])?$container->_rf[self::RF_NAMED_CONTROLS][$id]:null; |
4961
|
|
|
else |
4962
|
|
|
{ |
4963
|
|
|
$cid=substr($id,0,$pos); |
4964
|
|
|
$sid=substr($id,$pos+1); |
4965
|
|
|
if(isset($container->_rf[self::RF_NAMED_CONTROLS][$cid])) |
4966
|
|
|
return $container->_rf[self::RF_NAMED_CONTROLS][$cid]->findControl($sid); |
4967
|
|
|
else |
4968
|
|
|
return null; |
4969
|
|
|
} |
4970
|
|
|
} |
4971
|
|
|
public function findControlsByType($type,$strict=true) |
4972
|
|
|
{ |
4973
|
|
|
$controls=array(); |
4974
|
|
|
if($this->getHasControls()) |
4975
|
|
|
{ |
4976
|
|
|
foreach($this->_rf[self::RF_CONTROLS] as $control) |
4977
|
|
|
{ |
4978
|
|
|
if(is_object($control) && (get_class($control)===$type || (!$strict && ($control instanceof $type)))) |
4979
|
|
|
$controls[]=$control; |
4980
|
|
|
if(($control instanceof TControl) && $control->getHasControls()) |
4981
|
|
|
$controls=array_merge($controls,$control->findControlsByType($type,$strict)); |
4982
|
|
|
} |
4983
|
|
|
} |
4984
|
|
|
return $controls; |
4985
|
|
|
} |
4986
|
|
|
public function findControlsByID($id) |
4987
|
|
|
{ |
4988
|
|
|
$controls=array(); |
4989
|
|
|
if($this->getHasControls()) |
4990
|
|
|
{ |
4991
|
|
|
foreach($this->_rf[self::RF_CONTROLS] as $control) |
4992
|
|
|
{ |
4993
|
|
|
if($control instanceof TControl) |
4994
|
|
|
{ |
4995
|
|
|
if($control->_id===$id) |
4996
|
|
|
$controls[]=$control; |
4997
|
|
|
$controls=array_merge($controls,$control->findControlsByID($id)); |
4998
|
|
|
} |
4999
|
|
|
} |
5000
|
|
|
} |
5001
|
|
|
return $controls; |
5002
|
|
|
} |
5003
|
|
|
public function clearNamingContainer() |
5004
|
|
|
{ |
5005
|
|
|
unset($this->_rf[self::RF_NAMED_CONTROLS_ID]); |
5006
|
|
|
$this->clearNameTable(); |
5007
|
|
|
} |
5008
|
|
|
public function registerObject($name,$object) |
5009
|
|
|
{ |
5010
|
|
|
if(isset($this->_rf[self::RF_NAMED_OBJECTS][$name])) |
5011
|
|
|
throw new TInvalidOperationException('control_object_reregistered',$name); |
5012
|
|
|
$this->_rf[self::RF_NAMED_OBJECTS][$name]=$object; |
5013
|
|
|
} |
5014
|
|
|
public function unregisterObject($name) |
5015
|
|
|
{ |
5016
|
|
|
unset($this->_rf[self::RF_NAMED_OBJECTS][$name]); |
5017
|
|
|
} |
5018
|
|
|
public function isObjectRegistered($name) |
5019
|
|
|
{ |
5020
|
|
|
return isset($this->_rf[self::RF_NAMED_OBJECTS][$name]); |
5021
|
|
|
} |
5022
|
|
|
public function getHasChildInitialized() |
5023
|
|
|
{ |
5024
|
|
|
return $this->getControlStage() >= self::CS_CHILD_INITIALIZED; |
5025
|
|
|
} |
5026
|
|
|
public function getHasInitialized() |
5027
|
|
|
{ |
5028
|
|
|
return $this->getControlStage() >= self::CS_INITIALIZED; |
5029
|
|
|
} |
5030
|
|
|
public function getHasLoadedPostData() |
5031
|
|
|
{ |
5032
|
|
|
return $this->getControlStage() >= self::CS_STATE_LOADED; |
5033
|
|
|
} |
5034
|
|
|
public function getHasLoaded() |
5035
|
|
|
{ |
5036
|
|
|
return $this->getControlStage() >= self::CS_LOADED; |
5037
|
|
|
} |
5038
|
|
|
public function getHasPreRendered() |
5039
|
|
|
{ |
5040
|
|
|
return $this->getControlStage() >= self::CS_PRERENDERED; |
5041
|
|
|
} |
5042
|
|
|
public function getRegisteredObject($name) |
5043
|
|
|
{ |
5044
|
|
|
return isset($this->_rf[self::RF_NAMED_OBJECTS][$name])?$this->_rf[self::RF_NAMED_OBJECTS][$name]:null; |
5045
|
|
|
} |
5046
|
|
|
public function getAllowChildControls() |
5047
|
|
|
{ |
5048
|
|
|
return true; |
5049
|
|
|
} |
5050
|
|
|
public function addParsedObject($object) |
5051
|
|
|
{ |
5052
|
|
|
$this->getControls()->add($object); |
5053
|
|
|
} |
5054
|
|
|
final protected function clearChildState() |
5055
|
|
|
{ |
5056
|
|
|
unset($this->_rf[self::RF_CHILD_STATE]); |
5057
|
|
|
} |
5058
|
|
|
final protected function isDescendentOf($ancestor) |
5059
|
|
|
{ |
5060
|
|
|
$control=$this; |
5061
|
|
|
while($control!==$ancestor && $control->_parent) |
5062
|
|
|
$control=$control->_parent; |
5063
|
|
|
return $control===$ancestor; |
5064
|
|
|
} |
5065
|
|
|
public function addedControl($control) |
5066
|
|
|
{ |
5067
|
|
|
if($control->_parent) |
5068
|
|
|
$control->_parent->getControls()->remove($control); |
5069
|
|
|
$control->_parent=$this; |
5070
|
|
|
$control->_page=$this->getPage(); |
5071
|
|
|
$namingContainer=($this instanceof INamingContainer)?$this:$this->_namingContainer; |
5072
|
|
|
if($namingContainer) |
5073
|
|
|
{ |
5074
|
|
|
$control->_namingContainer=$namingContainer; |
5075
|
|
|
if($control->_id==='') |
5076
|
|
|
$control->generateAutomaticID(); |
5077
|
|
|
else |
5078
|
|
|
$namingContainer->clearNameTable(); |
|
|
|
|
5079
|
|
|
$control->clearCachedUniqueID($control instanceof INamingContainer); |
5080
|
|
|
} |
5081
|
|
|
if($this->_stage>=self::CS_CHILD_INITIALIZED) |
5082
|
|
|
{ |
5083
|
|
|
$control->initRecursive($namingContainer); |
5084
|
|
|
if($this->_stage>=self::CS_STATE_LOADED) |
5085
|
|
|
{ |
5086
|
|
|
if(isset($this->_rf[self::RF_CHILD_STATE][$control->_id])) |
5087
|
|
|
{ |
5088
|
|
|
$state=$this->_rf[self::RF_CHILD_STATE][$control->_id]; |
5089
|
|
|
unset($this->_rf[self::RF_CHILD_STATE][$control->_id]); |
5090
|
|
|
} |
5091
|
|
|
else |
5092
|
|
|
$state=null; |
5093
|
|
|
$control->loadStateRecursive($state,!($this->_flags & self::IS_DISABLE_VIEWSTATE)); |
5094
|
|
|
if($this->_stage>=self::CS_LOADED) |
5095
|
|
|
{ |
5096
|
|
|
$control->loadRecursive(); |
5097
|
|
|
if($this->_stage>=self::CS_PRERENDERED) |
5098
|
|
|
$control->preRenderRecursive(); |
5099
|
|
|
} |
5100
|
|
|
} |
5101
|
|
|
} |
5102
|
|
|
} |
5103
|
|
|
public function removedControl($control) |
5104
|
|
|
{ |
5105
|
|
|
if($this->_namingContainer) |
5106
|
|
|
$this->_namingContainer->clearNameTable(); |
5107
|
|
|
$control->unloadRecursive(); |
5108
|
|
|
$control->_parent=null; |
5109
|
|
|
$control->_page=null; |
5110
|
|
|
$control->_namingContainer=null; |
5111
|
|
|
$control->_tplControl=null; |
5112
|
|
|
if(!($control->_flags & self::IS_ID_SET)) |
5113
|
|
|
$control->_id=''; |
5114
|
|
|
else |
5115
|
|
|
unset($this->_rf[self::RF_NAMED_OBJECTS][$control->_id]); |
5116
|
|
|
$control->clearCachedUniqueID(true); |
5117
|
|
|
} |
5118
|
|
|
protected function initRecursive($namingContainer=null) |
5119
|
|
|
{ |
5120
|
|
|
$this->ensureChildControls(); |
5121
|
|
|
if($this->getHasControls()) |
5122
|
|
|
{ |
5123
|
|
|
if($this instanceof INamingContainer) |
5124
|
|
|
$namingContainer=$this; |
5125
|
|
|
$page=$this->getPage(); |
5126
|
|
|
foreach($this->_rf[self::RF_CONTROLS] as $control) |
5127
|
|
|
{ |
5128
|
|
|
if($control instanceof TControl) |
5129
|
|
|
{ |
5130
|
|
|
$control->_namingContainer=$namingContainer; |
5131
|
|
|
$control->_page=$page; |
5132
|
|
|
if($control->_id==='' && $namingContainer) |
5133
|
|
|
$control->generateAutomaticID(); |
5134
|
|
|
$control->initRecursive($namingContainer); |
5135
|
|
|
} |
5136
|
|
|
} |
5137
|
|
|
} |
5138
|
|
|
if($this->_stage<self::CS_INITIALIZED) |
5139
|
|
|
{ |
5140
|
|
|
$this->_stage=self::CS_CHILD_INITIALIZED; |
5141
|
|
|
if(($page=$this->getPage()) && $this->getEnableTheming() && !($this->_flags & self::IS_SKIN_APPLIED)) |
5142
|
|
|
{ |
5143
|
|
|
$page->applyControlSkin($this); |
5144
|
|
|
$this->_flags |= self::IS_SKIN_APPLIED; |
5145
|
|
|
} |
5146
|
|
|
if(isset($this->_rf[self::RF_ADAPTER])) |
5147
|
|
|
$this->_rf[self::RF_ADAPTER]->onInit(null); |
5148
|
|
|
else |
5149
|
|
|
$this->onInit(null); |
5150
|
|
|
$this->_stage=self::CS_INITIALIZED; |
5151
|
|
|
} |
5152
|
|
|
} |
5153
|
|
|
protected function loadRecursive() |
5154
|
|
|
{ |
5155
|
|
|
if($this->_stage<self::CS_LOADED) |
5156
|
|
|
{ |
5157
|
|
|
if(isset($this->_rf[self::RF_ADAPTER])) |
5158
|
|
|
$this->_rf[self::RF_ADAPTER]->onLoad(null); |
5159
|
|
|
else |
5160
|
|
|
$this->onLoad(null); |
5161
|
|
|
} |
5162
|
|
|
if($this->getHasControls()) |
5163
|
|
|
{ |
5164
|
|
|
foreach($this->_rf[self::RF_CONTROLS] as $control) |
5165
|
|
|
{ |
5166
|
|
|
if($control instanceof TControl) |
5167
|
|
|
$control->loadRecursive(); |
5168
|
|
|
} |
5169
|
|
|
} |
5170
|
|
|
if($this->_stage<self::CS_LOADED) |
5171
|
|
|
$this->_stage=self::CS_LOADED; |
5172
|
|
|
} |
5173
|
|
|
protected function preRenderRecursive() |
5174
|
|
|
{ |
5175
|
|
|
$this->autoDataBindProperties(); |
5176
|
|
|
if($this->getVisible(false)) |
5177
|
|
|
{ |
5178
|
|
|
if(isset($this->_rf[self::RF_ADAPTER])) |
5179
|
|
|
$this->_rf[self::RF_ADAPTER]->onPreRender(null); |
5180
|
|
|
else |
5181
|
|
|
$this->onPreRender(null); |
5182
|
|
|
if($this->getHasControls()) |
5183
|
|
|
{ |
5184
|
|
|
foreach($this->_rf[self::RF_CONTROLS] as $control) |
5185
|
|
|
{ |
5186
|
|
|
if($control instanceof TControl) |
5187
|
|
|
$control->preRenderRecursive(); |
5188
|
|
|
else if($control instanceof TCompositeLiteral) |
5189
|
|
|
$control->evaluateDynamicContent(); |
5190
|
|
|
} |
5191
|
|
|
} |
5192
|
|
|
} |
5193
|
|
|
$this->_stage=self::CS_PRERENDERED; |
5194
|
|
|
} |
5195
|
|
|
protected function unloadRecursive() |
5196
|
|
|
{ |
5197
|
|
|
if(!($this->_flags & self::IS_ID_SET)) |
5198
|
|
|
$this->_id=''; |
5199
|
|
|
if($this->getHasControls()) |
5200
|
|
|
{ |
5201
|
|
|
foreach($this->_rf[self::RF_CONTROLS] as $control) |
5202
|
|
|
if($control instanceof TControl) |
5203
|
|
|
$control->unloadRecursive(); |
5204
|
|
|
} |
5205
|
|
|
if(isset($this->_rf[self::RF_ADAPTER])) |
5206
|
|
|
$this->_rf[self::RF_ADAPTER]->onUnload(null); |
5207
|
|
|
else |
5208
|
|
|
$this->onUnload(null); |
5209
|
|
|
} |
5210
|
|
|
public function onInit($param) |
5211
|
|
|
{ |
5212
|
|
|
$this->raiseEvent('OnInit',$this,$param); |
5213
|
|
|
} |
5214
|
|
|
public function onLoad($param) |
5215
|
|
|
{ |
5216
|
|
|
$this->raiseEvent('OnLoad',$this,$param); |
5217
|
|
|
} |
5218
|
|
|
public function onDataBinding($param) |
5219
|
|
|
{ |
5220
|
|
|
$this->raiseEvent('OnDataBinding',$this,$param); |
5221
|
|
|
} |
5222
|
|
|
public function onUnload($param) |
5223
|
|
|
{ |
5224
|
|
|
$this->raiseEvent('OnUnload',$this,$param); |
5225
|
|
|
} |
5226
|
|
|
public function onPreRender($param) |
5227
|
|
|
{ |
5228
|
|
|
$this->raiseEvent('OnPreRender',$this,$param); |
5229
|
|
|
} |
5230
|
|
|
protected function raiseBubbleEvent($sender,$param) |
5231
|
|
|
{ |
5232
|
|
|
$control=$this; |
5233
|
|
|
while($control=$control->_parent) |
5234
|
|
|
{ |
5235
|
|
|
if($control->bubbleEvent($sender,$param)) |
5236
|
|
|
break; |
5237
|
|
|
} |
5238
|
|
|
} |
5239
|
|
|
public function bubbleEvent($sender,$param) |
5240
|
|
|
{ |
5241
|
|
|
return false; |
5242
|
|
|
} |
5243
|
|
|
public function broadcastEvent($name,$sender,$param) |
5244
|
|
|
{ |
5245
|
|
|
$rootControl=(($page=$this->getPage())===null)?$this:$page; |
5246
|
|
|
$rootControl->broadcastEventInternal($name,$sender,new TBroadcastEventParameter($name,$param)); |
5247
|
|
|
} |
5248
|
|
|
private function broadcastEventInternal($name,$sender,$param) |
5249
|
|
|
{ |
5250
|
|
|
if($this->hasEvent($name)) |
5251
|
|
|
$this->raiseEvent($name,$sender,$param->getParameter()); |
5252
|
|
|
if($this instanceof IBroadcastEventReceiver) |
5253
|
|
|
$this->broadcastEventReceived($sender,$param); |
5254
|
|
|
if($this->getHasControls()) |
5255
|
|
|
{ |
5256
|
|
|
foreach($this->_rf[self::RF_CONTROLS] as $control) |
5257
|
|
|
{ |
5258
|
|
|
if($control instanceof TControl) |
5259
|
|
|
$control->broadcastEventInternal($name,$sender,$param); |
5260
|
|
|
} |
5261
|
|
|
} |
5262
|
|
|
} |
5263
|
|
|
protected function traverseChildControls($param,$preCallback=null,$postCallback=null) |
5264
|
|
|
{ |
5265
|
|
|
if($preCallback!==null) |
5266
|
|
|
call_user_func($preCallback,$this,$param); |
5267
|
|
|
if($this->getHasControls()) |
5268
|
|
|
{ |
5269
|
|
|
foreach($this->_rf[self::RF_CONTROLS] as $control) |
5270
|
|
|
{ |
5271
|
|
|
if($control instanceof TControl) |
5272
|
|
|
{ |
5273
|
|
|
$control->traverseChildControls($param,$preCallback,$postCallback); |
5274
|
|
|
} |
5275
|
|
|
} |
5276
|
|
|
} |
5277
|
|
|
if($postCallback!==null) |
5278
|
|
|
call_user_func($postCallback,$this,$param); |
5279
|
|
|
} |
5280
|
|
|
public function renderControl($writer) |
5281
|
|
|
{ |
5282
|
|
|
if($this instanceof IActiveControl || $this->getVisible(false)) |
5283
|
|
|
{ |
5284
|
|
|
if(isset($this->_rf[self::RF_ADAPTER])) |
5285
|
|
|
$this->_rf[self::RF_ADAPTER]->render($writer); |
5286
|
|
|
else |
5287
|
|
|
$this->render($writer); |
5288
|
|
|
} |
5289
|
|
|
} |
5290
|
|
|
public function render($writer) |
5291
|
|
|
{ |
5292
|
|
|
$this->renderChildren($writer); |
5293
|
|
|
} |
5294
|
|
|
public function renderChildren($writer) |
5295
|
|
|
{ |
5296
|
|
|
if($this->getHasControls()) |
5297
|
|
|
{ |
5298
|
|
|
foreach($this->_rf[self::RF_CONTROLS] as $control) |
5299
|
|
|
{ |
5300
|
|
|
if(is_string($control)) |
5301
|
|
|
$writer->write($control); |
5302
|
|
|
else if($control instanceof TControl) |
5303
|
|
|
$control->renderControl($writer); |
5304
|
|
|
else if($control instanceof IRenderable) |
5305
|
|
|
$control->render($writer); |
5306
|
|
|
} |
5307
|
|
|
} |
5308
|
|
|
} |
5309
|
|
|
public function saveState() |
5310
|
|
|
{ |
5311
|
|
|
} |
5312
|
|
|
public function loadState() |
5313
|
|
|
{ |
5314
|
|
|
} |
5315
|
|
|
protected function loadStateRecursive(&$state,$needViewState=true) |
5316
|
|
|
{ |
5317
|
|
|
if(is_array($state)) |
5318
|
|
|
{ |
5319
|
|
|
$needViewState=($needViewState && !($this->_flags & self::IS_DISABLE_VIEWSTATE)); |
5320
|
|
|
if(isset($state[1])) |
5321
|
|
|
{ |
5322
|
|
|
$this->_rf[self::RF_CONTROLSTATE]=&$state[1]; |
5323
|
|
|
unset($state[1]); |
5324
|
|
|
} |
5325
|
|
|
else |
5326
|
|
|
unset($this->_rf[self::RF_CONTROLSTATE]); |
5327
|
|
|
if($needViewState) |
5328
|
|
|
{ |
5329
|
|
|
if(isset($state[0])) |
5330
|
|
|
$this->_viewState=&$state[0]; |
5331
|
|
|
else |
5332
|
|
|
$this->_viewState=array(); |
5333
|
|
|
} |
5334
|
|
|
unset($state[0]); |
5335
|
|
|
if($this->getHasControls()) |
5336
|
|
|
{ |
5337
|
|
|
foreach($this->_rf[self::RF_CONTROLS] as $control) |
5338
|
|
|
{ |
5339
|
|
|
if($control instanceof TControl) |
5340
|
|
|
{ |
5341
|
|
|
if(isset($state[$control->_id])) |
5342
|
|
|
{ |
5343
|
|
|
$control->loadStateRecursive($state[$control->_id],$needViewState); |
5344
|
|
|
unset($state[$control->_id]); |
5345
|
|
|
} |
5346
|
|
|
} |
5347
|
|
|
} |
5348
|
|
|
} |
5349
|
|
|
if(!empty($state)) |
5350
|
|
|
$this->_rf[self::RF_CHILD_STATE]=&$state; |
5351
|
|
|
} |
5352
|
|
|
$this->_stage=self::CS_STATE_LOADED; |
5353
|
|
|
if(isset($this->_rf[self::RF_ADAPTER])) |
5354
|
|
|
$this->_rf[self::RF_ADAPTER]->loadState(); |
5355
|
|
|
else |
5356
|
|
|
$this->loadState(); |
5357
|
|
|
} |
5358
|
|
|
protected function &saveStateRecursive($needViewState=true) |
5359
|
|
|
{ |
5360
|
|
|
if(isset($this->_rf[self::RF_ADAPTER])) |
5361
|
|
|
$this->_rf[self::RF_ADAPTER]->saveState(); |
5362
|
|
|
else |
5363
|
|
|
$this->saveState(); |
5364
|
|
|
$needViewState=($needViewState && !($this->_flags & self::IS_DISABLE_VIEWSTATE)); |
5365
|
|
|
$state=array(); |
5366
|
|
|
if($this->getHasControls()) |
5367
|
|
|
{ |
5368
|
|
|
foreach($this->_rf[self::RF_CONTROLS] as $control) |
5369
|
|
|
{ |
5370
|
|
|
if($control instanceof TControl) |
5371
|
|
|
{ |
5372
|
|
|
if(count($tmp = &$control->saveStateRecursive($needViewState))) |
5373
|
|
|
$state[$control->_id]=$tmp; |
5374
|
|
|
} |
5375
|
|
|
} |
5376
|
|
|
} |
5377
|
|
|
if($needViewState && !empty($this->_viewState)) |
5378
|
|
|
$state[0]=&$this->_viewState; |
5379
|
|
|
if(isset($this->_rf[self::RF_CONTROLSTATE])) |
5380
|
|
|
$state[1]=&$this->_rf[self::RF_CONTROLSTATE]; |
5381
|
|
|
return $state; |
5382
|
|
|
} |
5383
|
|
|
public function applyStyleSheetSkin($page) |
5384
|
|
|
{ |
5385
|
|
|
if($page && !($this->_flags & self::IS_STYLESHEET_APPLIED)) |
5386
|
|
|
{ |
5387
|
|
|
$page->applyControlStyleSheet($this); |
5388
|
|
|
$this->_flags |= self::IS_STYLESHEET_APPLIED; |
5389
|
|
|
} |
5390
|
|
|
else if($this->_flags & self::IS_STYLESHEET_APPLIED) |
5391
|
|
|
throw new TInvalidOperationException('control_stylesheet_applied',get_class($this)); |
5392
|
|
|
} |
5393
|
|
|
private function clearCachedUniqueID($recursive) |
5394
|
|
|
{ |
5395
|
|
|
if($recursive && $this->_uid!==null && isset($this->_rf[self::RF_CONTROLS])) |
5396
|
|
|
{ |
5397
|
|
|
foreach($this->_rf[self::RF_CONTROLS] as $control) |
5398
|
|
|
if($control instanceof TControl) |
5399
|
|
|
$control->clearCachedUniqueID($recursive); |
5400
|
|
|
} |
5401
|
|
|
$this->_uid=null; |
5402
|
|
|
} |
5403
|
|
|
private function generateAutomaticID() |
5404
|
|
|
{ |
5405
|
|
|
$this->_flags &= ~self::IS_ID_SET; |
5406
|
|
|
if(!isset($this->_namingContainer->_rf[self::RF_NAMED_CONTROLS_ID])) |
|
|
|
|
5407
|
|
|
$this->_namingContainer->_rf[self::RF_NAMED_CONTROLS_ID]=0; |
|
|
|
|
5408
|
|
|
$id=$this->_namingContainer->_rf[self::RF_NAMED_CONTROLS_ID]++; |
|
|
|
|
5409
|
|
|
$this->_id=self::AUTOMATIC_ID_PREFIX . $id; |
5410
|
|
|
$this->_namingContainer->clearNameTable(); |
5411
|
|
|
} |
5412
|
|
|
private function clearNameTable() |
5413
|
|
|
{ |
5414
|
|
|
unset($this->_rf[self::RF_NAMED_CONTROLS]); |
5415
|
|
|
} |
5416
|
|
|
private function fillNameTable($container,$controls) |
5417
|
|
|
{ |
5418
|
|
|
foreach($controls as $control) |
5419
|
|
|
{ |
5420
|
|
|
if($control instanceof TControl) |
5421
|
|
|
{ |
5422
|
|
|
if($control->_id!=='') |
5423
|
|
|
{ |
5424
|
|
|
if(isset($container->_rf[self::RF_NAMED_CONTROLS][$control->_id])) |
5425
|
|
|
throw new TInvalidDataValueException('control_id_nonunique',get_class($control),$control->_id); |
5426
|
|
|
else |
5427
|
|
|
$container->_rf[self::RF_NAMED_CONTROLS][$control->_id]=$control; |
5428
|
|
|
} |
5429
|
|
|
if(!($control instanceof INamingContainer) && $control->getHasControls()) |
5430
|
|
|
$this->fillNameTable($container,$control->_rf[self::RF_CONTROLS]); |
5431
|
|
|
} |
5432
|
|
|
} |
5433
|
|
|
} |
5434
|
|
|
} |
5435
|
|
|
class TControlCollection extends TList |
5436
|
|
|
{ |
5437
|
|
|
private $_o; |
5438
|
|
|
public function __construct(TControl $owner,$readOnly=false) |
5439
|
|
|
{ |
5440
|
|
|
$this->_o=$owner; |
5441
|
|
|
parent::__construct(null,$readOnly); |
5442
|
|
|
} |
5443
|
|
|
protected function getOwner() |
5444
|
|
|
{ |
5445
|
|
|
return $this->_o; |
5446
|
|
|
} |
5447
|
|
|
public function insertAt($index,$item) |
5448
|
|
|
{ |
5449
|
|
|
if($item instanceof TControl) |
5450
|
|
|
{ |
5451
|
|
|
parent::insertAt($index,$item); |
5452
|
|
|
$this->_o->addedControl($item); |
5453
|
|
|
} |
5454
|
|
|
else if(is_string($item) || ($item instanceof IRenderable)) |
5455
|
|
|
parent::insertAt($index,$item); |
5456
|
|
|
else |
5457
|
|
|
throw new TInvalidDataTypeException('controlcollection_control_required'); |
5458
|
|
|
} |
5459
|
|
|
public function removeAt($index) |
5460
|
|
|
{ |
5461
|
|
|
$item=parent::removeAt($index); |
5462
|
|
|
if($item instanceof TControl) |
5463
|
|
|
$this->_o->removedControl($item); |
5464
|
|
|
return $item; |
5465
|
|
|
} |
5466
|
|
|
public function clear() |
5467
|
|
|
{ |
5468
|
|
|
parent::clear(); |
5469
|
|
|
if($this->_o instanceof INamingContainer) |
5470
|
|
|
$this->_o->clearNamingContainer(); |
5471
|
|
|
} |
5472
|
|
|
} |
5473
|
|
|
class TEmptyControlCollection extends TControlCollection |
5474
|
|
|
{ |
5475
|
|
|
public function __construct(TControl $owner) |
5476
|
|
|
{ |
5477
|
|
|
parent::__construct($owner,true); |
5478
|
|
|
} |
5479
|
|
|
public function insertAt($index,$item) |
5480
|
|
|
{ |
5481
|
|
|
if(!is_string($item)) parent::insertAt($index,$item); } |
5482
|
|
|
} |
5483
|
|
|
interface INamingContainer |
5484
|
|
|
{ |
5485
|
|
|
} |
5486
|
|
|
interface IPostBackEventHandler |
5487
|
|
|
{ |
5488
|
|
|
public function raisePostBackEvent($param); |
|
|
|
|
5489
|
|
|
} |
5490
|
|
|
interface IPostBackDataHandler |
5491
|
|
|
{ |
5492
|
|
|
public function loadPostData($key,$values); |
5493
|
|
|
public function raisePostDataChangedEvent(); |
|
|
|
|
5494
|
|
|
public function getDataChanged(); |
5495
|
|
|
} |
5496
|
|
|
interface IValidator |
5497
|
|
|
{ |
5498
|
|
|
public function validate(); |
5499
|
|
|
public function getIsValid(); |
5500
|
|
|
public function setIsValid($value); |
|
|
|
|
5501
|
|
|
public function getErrorMessage(); |
5502
|
|
|
public function setErrorMessage($value); |
|
|
|
|
5503
|
|
|
} |
5504
|
|
|
interface IValidatable |
5505
|
|
|
{ |
5506
|
|
|
public function getValidationPropertyValue(); |
5507
|
|
|
public function getIsValid(); |
5508
|
|
|
public function setIsValid($value); |
5509
|
|
|
} |
5510
|
|
|
interface IBroadcastEventReceiver |
5511
|
|
|
{ |
5512
|
|
|
public function broadcastEventReceived($sender,$param); |
|
|
|
|
5513
|
|
|
} |
5514
|
|
|
interface ITheme |
5515
|
|
|
{ |
5516
|
|
|
public function applySkin($control); |
|
|
|
|
5517
|
|
|
} |
5518
|
|
|
interface ITemplate |
5519
|
|
|
{ |
5520
|
|
|
public function instantiateIn($parent); |
|
|
|
|
5521
|
|
|
} |
5522
|
|
|
interface IButtonControl |
5523
|
|
|
{ |
5524
|
|
|
public function getText(); |
5525
|
|
|
public function setText($value); |
|
|
|
|
5526
|
|
|
public function getCausesValidation(); |
5527
|
|
|
public function setCausesValidation($value); |
|
|
|
|
5528
|
|
|
public function getCommandName(); |
5529
|
|
|
public function setCommandName($value); |
|
|
|
|
5530
|
|
|
public function getCommandParameter(); |
5531
|
|
|
public function setCommandParameter($value); |
|
|
|
|
5532
|
|
|
public function getValidationGroup(); |
5533
|
|
|
public function setValidationGroup($value); |
|
|
|
|
5534
|
|
|
public function onClick($param); |
|
|
|
|
5535
|
|
|
public function onCommand($param); |
|
|
|
|
5536
|
|
|
public function setIsDefaultButton($value); |
|
|
|
|
5537
|
|
|
public function getIsDefaultButton(); |
5538
|
|
|
} |
5539
|
|
|
interface ISurroundable |
5540
|
|
|
{ |
5541
|
|
|
public function getSurroundingTag(); |
5542
|
|
|
public function getSurroundingTagID(); |
5543
|
|
|
} |
5544
|
|
|
class TBroadcastEventParameter extends TEventParameter |
5545
|
|
|
{ |
5546
|
|
|
private $_name; |
5547
|
|
|
private $_param; |
5548
|
|
|
public function __construct($name='',$parameter=null) |
5549
|
|
|
{ |
5550
|
|
|
$this->_name=$name; |
5551
|
|
|
$this->_param=$parameter; |
5552
|
|
|
} |
5553
|
|
|
public function getName() |
5554
|
|
|
{ |
5555
|
|
|
return $this->_name; |
5556
|
|
|
} |
5557
|
|
|
public function setName($value) |
5558
|
|
|
{ |
5559
|
|
|
$this->_name=$value; |
5560
|
|
|
} |
5561
|
|
|
public function getParameter() |
5562
|
|
|
{ |
5563
|
|
|
return $this->_param; |
5564
|
|
|
} |
5565
|
|
|
public function setParameter($value) |
5566
|
|
|
{ |
5567
|
|
|
$this->_param=$value; |
5568
|
|
|
} |
5569
|
|
|
} |
5570
|
|
|
class TCommandEventParameter extends TEventParameter |
5571
|
|
|
{ |
5572
|
|
|
private $_name; |
5573
|
|
|
private $_param; |
5574
|
|
|
public function __construct($name='',$parameter='') |
5575
|
|
|
{ |
5576
|
|
|
$this->_name=$name; |
5577
|
|
|
$this->_param=$parameter; |
5578
|
|
|
} |
5579
|
|
|
public function getCommandName() |
5580
|
|
|
{ |
5581
|
|
|
return $this->_name; |
5582
|
|
|
} |
5583
|
|
|
public function getCommandParameter() |
5584
|
|
|
{ |
5585
|
|
|
return $this->_param; |
5586
|
|
|
} |
5587
|
|
|
} |
5588
|
|
|
class TCompositeLiteral extends TComponent implements IRenderable, IBindable |
5589
|
|
|
{ |
5590
|
|
|
const TYPE_EXPRESSION=0; |
5591
|
|
|
const TYPE_STATEMENTS=1; |
5592
|
|
|
const TYPE_DATABINDING=2; |
5593
|
|
|
private $_container=null; |
5594
|
|
|
private $_items=array(); |
5595
|
|
|
private $_expressions=array(); |
5596
|
|
|
private $_statements=array(); |
5597
|
|
|
private $_bindings=array(); |
5598
|
|
|
public function __construct($items) |
5599
|
|
|
{ |
5600
|
|
|
$this->_items=array(); |
5601
|
|
|
$this->_expressions=array(); |
5602
|
|
|
$this->_statements=array(); |
5603
|
|
|
foreach($items as $id=>$item) |
5604
|
|
|
{ |
5605
|
|
|
if(is_array($item)) |
5606
|
|
|
{ |
5607
|
|
|
if($item[0]===self::TYPE_EXPRESSION) |
5608
|
|
|
$this->_expressions[$id]=$item[1]; |
5609
|
|
|
else if($item[0]===self::TYPE_STATEMENTS) |
5610
|
|
|
$this->_statements[$id]=$item[1]; |
5611
|
|
|
else if($item[0]===self::TYPE_DATABINDING) |
5612
|
|
|
$this->_bindings[$id]=$item[1]; |
5613
|
|
|
$this->_items[$id]=''; |
5614
|
|
|
} |
5615
|
|
|
else |
5616
|
|
|
$this->_items[$id]=$item; |
5617
|
|
|
} |
5618
|
|
|
} |
5619
|
|
|
public function getContainer() |
5620
|
|
|
{ |
5621
|
|
|
return $this->_container; |
5622
|
|
|
} |
5623
|
|
|
public function setContainer(TComponent $value) |
5624
|
|
|
{ |
5625
|
|
|
$this->_container=$value; |
5626
|
|
|
} |
5627
|
|
|
public function evaluateDynamicContent() |
5628
|
|
|
{ |
5629
|
|
|
$context=$this->_container===null?$this:$this->_container; |
5630
|
|
|
foreach($this->_expressions as $id=>$expression) |
5631
|
|
|
$this->_items[$id]=$context->evaluateExpression($expression); |
5632
|
|
|
foreach($this->_statements as $id=>$statement) |
5633
|
|
|
$this->_items[$id]=$context->evaluateStatements($statement); |
5634
|
|
|
} |
5635
|
|
|
public function dataBind() |
5636
|
|
|
{ |
5637
|
|
|
$context=$this->_container===null?$this:$this->_container; |
5638
|
|
|
foreach($this->_bindings as $id=>$binding) |
5639
|
|
|
$this->_items[$id]=$context->evaluateExpression($binding); |
5640
|
|
|
} |
5641
|
|
|
public function render($writer) |
5642
|
|
|
{ |
5643
|
|
|
$writer->write(implode('',$this->_items)); |
5644
|
|
|
} |
5645
|
|
|
} |
5646
|
|
|
class TFont extends TComponent |
5647
|
|
|
{ |
5648
|
|
|
const IS_BOLD=0x01; |
5649
|
|
|
const IS_ITALIC=0x02; |
5650
|
|
|
const IS_OVERLINE=0x04; |
5651
|
|
|
const IS_STRIKEOUT=0x08; |
5652
|
|
|
const IS_UNDERLINE=0x10; |
5653
|
|
|
const IS_SET_BOLD=0x01000; |
5654
|
|
|
const IS_SET_ITALIC=0x02000; |
5655
|
|
|
const IS_SET_OVERLINE=0x04000; |
5656
|
|
|
const IS_SET_STRIKEOUT=0x08000; |
5657
|
|
|
const IS_SET_UNDERLINE=0x10000; |
5658
|
|
|
const IS_SET_SIZE=0x20000; |
5659
|
|
|
const IS_SET_NAME=0x40000; |
5660
|
|
|
private $_flags=0; |
5661
|
|
|
private $_name=''; |
5662
|
|
|
private $_size=''; |
5663
|
|
|
protected function _getZappableSleepProps(&$exprops) |
5664
|
|
|
{ |
5665
|
|
|
parent::_getZappableSleepProps($exprops); |
5666
|
|
|
if ($this->_flags===0) |
5667
|
|
|
$exprops[] = "\0TFont\0_flags"; |
5668
|
|
|
if ($this->_name==='') |
5669
|
|
|
$exprops[] = "\0TFont\0_name"; |
5670
|
|
|
if ($this->_size==='') |
5671
|
|
|
$exprops[] = "\0TFont\0_size"; |
5672
|
|
|
} |
5673
|
|
|
public function getBold() |
5674
|
|
|
{ |
5675
|
|
|
return ($this->_flags & self::IS_BOLD)!==0; |
5676
|
|
|
} |
5677
|
|
|
public function setBold($value) |
5678
|
|
|
{ |
5679
|
|
|
$this->_flags |= self::IS_SET_BOLD; |
5680
|
|
|
if(TPropertyValue::ensureBoolean($value)) |
5681
|
|
|
$this->_flags |= self::IS_BOLD; |
5682
|
|
|
else |
5683
|
|
|
$this->_flags &= ~self::IS_BOLD; |
5684
|
|
|
} |
5685
|
|
|
public function getItalic() |
5686
|
|
|
{ |
5687
|
|
|
return ($this->_flags & self::IS_ITALIC)!==0; |
5688
|
|
|
} |
5689
|
|
|
public function setItalic($value) |
5690
|
|
|
{ |
5691
|
|
|
$this->_flags |= self::IS_SET_ITALIC; |
5692
|
|
|
if(TPropertyValue::ensureBoolean($value)) |
5693
|
|
|
$this->_flags |= self::IS_ITALIC; |
5694
|
|
|
else |
5695
|
|
|
$this->_flags &= ~self::IS_ITALIC; |
5696
|
|
|
} |
5697
|
|
|
public function getOverline() |
5698
|
|
|
{ |
5699
|
|
|
return ($this->_flags & self::IS_OVERLINE)!==0; |
5700
|
|
|
} |
5701
|
|
|
public function setOverline($value) |
5702
|
|
|
{ |
5703
|
|
|
$this->_flags |= self::IS_SET_OVERLINE; |
5704
|
|
|
if(TPropertyValue::ensureBoolean($value)) |
5705
|
|
|
$this->_flags |= self::IS_OVERLINE; |
5706
|
|
|
else |
5707
|
|
|
$this->_flags &= ~self::IS_OVERLINE; |
5708
|
|
|
} |
5709
|
|
|
public function getSize() |
5710
|
|
|
{ |
5711
|
|
|
return $this->_size; |
5712
|
|
|
} |
5713
|
|
|
public function setSize($value) |
5714
|
|
|
{ |
5715
|
|
|
$this->_flags |= self::IS_SET_SIZE; |
5716
|
|
|
$this->_size=$value; |
5717
|
|
|
} |
5718
|
|
|
public function getStrikeout() |
5719
|
|
|
{ |
5720
|
|
|
return ($this->_flags & self::IS_STRIKEOUT)!==0; |
5721
|
|
|
} |
5722
|
|
|
public function setStrikeout($value) |
5723
|
|
|
{ |
5724
|
|
|
$this->_flags |= self::IS_SET_STRIKEOUT; |
5725
|
|
|
if(TPropertyValue::ensureBoolean($value)) |
5726
|
|
|
$this->_flags |= self::IS_STRIKEOUT; |
5727
|
|
|
else |
5728
|
|
|
$this->_flags &= ~self::IS_STRIKEOUT; |
5729
|
|
|
} |
5730
|
|
|
public function getUnderline() |
5731
|
|
|
{ |
5732
|
|
|
return ($this->_flags & self::IS_UNDERLINE)!==0; |
5733
|
|
|
} |
5734
|
|
|
public function setUnderline($value) |
5735
|
|
|
{ |
5736
|
|
|
$this->_flags |= self::IS_SET_UNDERLINE; |
5737
|
|
|
if(TPropertyValue::ensureBoolean($value)) |
5738
|
|
|
$this->_flags |= self::IS_UNDERLINE; |
5739
|
|
|
else |
5740
|
|
|
$this->_flags &= ~self::IS_UNDERLINE; |
5741
|
|
|
} |
5742
|
|
|
public function getName() |
5743
|
|
|
{ |
5744
|
|
|
return $this->_name; |
5745
|
|
|
} |
5746
|
|
|
public function setName($value) |
5747
|
|
|
{ |
5748
|
|
|
$this->_flags |= self::IS_SET_NAME; |
5749
|
|
|
$this->_name=$value; |
5750
|
|
|
} |
5751
|
|
|
public function getIsEmpty() |
5752
|
|
|
{ |
5753
|
|
|
return !$this->_flags; |
5754
|
|
|
} |
5755
|
|
|
public function reset() |
5756
|
|
|
{ |
5757
|
|
|
$this->_flags=0; |
5758
|
|
|
$this->_name=''; |
5759
|
|
|
$this->_size=''; |
5760
|
|
|
} |
5761
|
|
|
public function mergeWith($font) |
5762
|
|
|
{ |
5763
|
|
|
if($font===null || $font->_flags===0) |
5764
|
|
|
return; |
5765
|
|
|
if(!($this->_flags & self::IS_SET_BOLD) && ($font->_flags & self::IS_SET_BOLD)) |
5766
|
|
|
$this->setBold($font->getBold()); |
5767
|
|
|
if(!($this->_flags & self::IS_SET_ITALIC) && ($font->_flags & self::IS_SET_ITALIC)) |
5768
|
|
|
$this->setItalic($font->getItalic()); |
5769
|
|
|
if(!($this->_flags & self::IS_SET_OVERLINE) && ($font->_flags & self::IS_SET_OVERLINE)) |
5770
|
|
|
$this->setOverline($font->getOverline()); |
5771
|
|
|
if(!($this->_flags & self::IS_SET_STRIKEOUT) && ($font->_flags & self::IS_SET_STRIKEOUT)) |
5772
|
|
|
$this->setStrikeout($font->getStrikeout()); |
5773
|
|
|
if(!($this->_flags & self::IS_SET_UNDERLINE) && ($font->_flags & self::IS_SET_UNDERLINE)) |
5774
|
|
|
$this->setUnderline($font->getUnderline()); |
5775
|
|
|
if(!($this->_flags & self::IS_SET_SIZE) && ($font->_flags & self::IS_SET_SIZE)) |
5776
|
|
|
$this->setSize($font->getSize()); |
5777
|
|
|
if(!($this->_flags & self::IS_SET_NAME) && ($font->_flags & self::IS_SET_NAME)) |
5778
|
|
|
$this->setName($font->getName()); |
5779
|
|
|
} |
5780
|
|
|
public function copyFrom($font) |
5781
|
|
|
{ |
5782
|
|
|
if($font===null || $font->_flags===0) |
5783
|
|
|
return; |
5784
|
|
|
if($font->_flags & self::IS_SET_BOLD) |
5785
|
|
|
$this->setBold($font->getBold()); |
5786
|
|
|
if($font->_flags & self::IS_SET_ITALIC) |
5787
|
|
|
$this->setItalic($font->getItalic()); |
5788
|
|
|
if($font->_flags & self::IS_SET_OVERLINE) |
5789
|
|
|
$this->setOverline($font->getOverline()); |
5790
|
|
|
if($font->_flags & self::IS_SET_STRIKEOUT) |
5791
|
|
|
$this->setStrikeout($font->getStrikeout()); |
5792
|
|
|
if($font->_flags & self::IS_SET_UNDERLINE) |
5793
|
|
|
$this->setUnderline($font->getUnderline()); |
5794
|
|
|
if($font->_flags & self::IS_SET_SIZE) |
5795
|
|
|
$this->setSize($font->getSize()); |
5796
|
|
|
if($font->_flags & self::IS_SET_NAME) |
5797
|
|
|
$this->setName($font->getName()); |
5798
|
|
|
} |
5799
|
|
|
public function toString() |
5800
|
|
|
{ |
5801
|
|
|
if($this->_flags===0) |
5802
|
|
|
return ''; |
5803
|
|
|
$str=''; |
5804
|
|
|
if($this->_flags & self::IS_SET_BOLD) |
5805
|
|
|
$str.='font-weight:'.(($this->_flags & self::IS_BOLD)?'bold;':'normal;'); |
5806
|
|
|
if($this->_flags & self::IS_SET_ITALIC) |
5807
|
|
|
$str.='font-style:'.(($this->_flags & self::IS_ITALIC)?'italic;':'normal;'); |
5808
|
|
|
$textDec=''; |
5809
|
|
|
if($this->_flags & self::IS_UNDERLINE) |
5810
|
|
|
$textDec.='underline'; |
5811
|
|
|
if($this->_flags & self::IS_OVERLINE) |
5812
|
|
|
$textDec.=' overline'; |
5813
|
|
|
if($this->_flags & self::IS_STRIKEOUT) |
5814
|
|
|
$textDec.=' line-through'; |
5815
|
|
|
$textDec=ltrim($textDec); |
5816
|
|
|
if($textDec!=='') |
5817
|
|
|
$str.='text-decoration:'.$textDec.';'; |
5818
|
|
|
if($this->_size!=='') |
5819
|
|
|
$str.='font-size:'.$this->_size.';'; |
5820
|
|
|
if($this->_name!=='') |
5821
|
|
|
$str.='font-family:'.$this->_name.';'; |
5822
|
|
|
return $str; |
5823
|
|
|
} |
5824
|
|
|
public function addAttributesToRender($writer) |
5825
|
|
|
{ |
5826
|
|
|
if($this->_flags===0) |
5827
|
|
|
return; |
5828
|
|
|
if($this->_flags & self::IS_SET_BOLD) |
5829
|
|
|
$writer->addStyleAttribute('font-weight',(($this->_flags & self::IS_BOLD)?'bold':'normal')); |
5830
|
|
|
if($this->_flags & self::IS_SET_ITALIC) |
5831
|
|
|
$writer->addStyleAttribute('font-style',(($this->_flags & self::IS_ITALIC)?'italic':'normal')); |
5832
|
|
|
$textDec=''; |
5833
|
|
|
if($this->_flags & self::IS_UNDERLINE) |
5834
|
|
|
$textDec.='underline'; |
5835
|
|
|
if($this->_flags & self::IS_OVERLINE) |
5836
|
|
|
$textDec.=' overline'; |
5837
|
|
|
if($this->_flags & self::IS_STRIKEOUT) |
5838
|
|
|
$textDec.=' line-through'; |
5839
|
|
|
$textDec=ltrim($textDec); |
5840
|
|
|
if($textDec!=='') |
5841
|
|
|
$writer->addStyleAttribute('text-decoration',$textDec); |
5842
|
|
|
if($this->_size!=='') |
5843
|
|
|
$writer->addStyleAttribute('font-size',$this->_size); |
5844
|
|
|
if($this->_name!=='') |
5845
|
|
|
$writer->addStyleAttribute('font-family',$this->_name); |
5846
|
|
|
} |
5847
|
|
|
} |
5848
|
|
|
class TStyle extends TComponent |
5849
|
|
|
{ |
5850
|
|
|
private $_fields=array(); |
5851
|
|
|
private $_font=null; |
5852
|
|
|
private $_class=null; |
5853
|
|
|
private $_customStyle=null; |
5854
|
|
|
private $_displayStyle='Fixed'; |
5855
|
|
|
protected function _getZappableSleepProps(&$exprops) |
5856
|
|
|
{ |
5857
|
|
|
parent::_getZappableSleepProps($exprops); |
5858
|
|
|
if ($this->_fields===array()) |
5859
|
|
|
$exprops[] = "\0TStyle\0_fields"; |
5860
|
|
|
if($this->_font===null) |
5861
|
|
|
$exprops[] = "\0TStyle\0_font"; |
5862
|
|
|
if($this->_class===null) |
5863
|
|
|
$exprops[] = "\0TStyle\0_class"; |
5864
|
|
|
if ($this->_customStyle===null) |
5865
|
|
|
$exprops[] = "\0TStyle\0_customStyle"; |
5866
|
|
|
if ($this->_displayStyle==='Fixed') |
5867
|
|
|
$exprops[] = "\0TStyle\0_displayStyle"; |
5868
|
|
|
} |
5869
|
|
|
public function __construct($style=null) |
5870
|
|
|
{ |
5871
|
|
|
parent::__construct(); |
5872
|
|
|
if($style!==null) |
5873
|
|
|
$this->copyFrom($style); |
5874
|
|
|
} |
5875
|
|
|
public function __clone() |
5876
|
|
|
{ |
5877
|
|
|
if($this->_font!==null) |
5878
|
|
|
$this->_font = clone($this->_font); |
5879
|
|
|
} |
5880
|
|
|
public function getBackColor() |
5881
|
|
|
{ |
5882
|
|
|
return isset($this->_fields['background-color'])?$this->_fields['background-color']:''; |
5883
|
|
|
} |
5884
|
|
|
public function setBackColor($value) |
5885
|
|
|
{ |
5886
|
|
|
if(trim($value)==='') |
5887
|
|
|
unset($this->_fields['background-color']); |
5888
|
|
|
else |
5889
|
|
|
$this->_fields['background-color']=$value; |
5890
|
|
|
} |
5891
|
|
|
public function getBorderColor() |
5892
|
|
|
{ |
5893
|
|
|
return isset($this->_fields['border-color'])?$this->_fields['border-color']:''; |
5894
|
|
|
} |
5895
|
|
|
public function setBorderColor($value) |
5896
|
|
|
{ |
5897
|
|
|
if(trim($value)==='') |
5898
|
|
|
unset($this->_fields['border-color']); |
5899
|
|
|
else |
5900
|
|
|
$this->_fields['border-color']=$value; |
5901
|
|
|
} |
5902
|
|
|
public function getBorderStyle() |
5903
|
|
|
{ |
5904
|
|
|
return isset($this->_fields['border-style'])?$this->_fields['border-style']:''; |
5905
|
|
|
} |
5906
|
|
|
public function setBorderStyle($value) |
5907
|
|
|
{ |
5908
|
|
|
if(trim($value)==='') |
5909
|
|
|
unset($this->_fields['border-style']); |
5910
|
|
|
else |
5911
|
|
|
$this->_fields['border-style']=$value; |
5912
|
|
|
} |
5913
|
|
|
public function getBorderWidth() |
5914
|
|
|
{ |
5915
|
|
|
return isset($this->_fields['border-width'])?$this->_fields['border-width']:''; |
5916
|
|
|
} |
5917
|
|
|
public function setBorderWidth($value) |
5918
|
|
|
{ |
5919
|
|
|
if(trim($value)==='') |
5920
|
|
|
unset($this->_fields['border-width']); |
5921
|
|
|
else |
5922
|
|
|
$this->_fields['border-width']=$value; |
5923
|
|
|
} |
5924
|
|
|
public function getCssClass() |
5925
|
|
|
{ |
5926
|
|
|
return $this->_class===null?'':$this->_class; |
5927
|
|
|
} |
5928
|
|
|
public function hasCssClass() |
5929
|
|
|
{ |
5930
|
|
|
return ($this->_class!==null); |
5931
|
|
|
} |
5932
|
|
|
public function setCssClass($value) |
5933
|
|
|
{ |
5934
|
|
|
$this->_class=$value; |
5935
|
|
|
} |
5936
|
|
|
public function getFont() |
5937
|
|
|
{ |
5938
|
|
|
if($this->_font===null) |
5939
|
|
|
$this->_font=new TFont; |
5940
|
|
|
return $this->_font; |
5941
|
|
|
} |
5942
|
|
|
public function hasFont() |
5943
|
|
|
{ |
5944
|
|
|
return $this->_font !== null; |
5945
|
|
|
} |
5946
|
|
|
public function setDisplayStyle($value) |
5947
|
|
|
{ |
5948
|
|
|
$this->_displayStyle = TPropertyValue::ensureEnum($value, 'TDisplayStyle'); |
5949
|
|
|
switch($this->_displayStyle) |
5950
|
|
|
{ |
5951
|
|
|
case TDisplayStyle::None: |
5952
|
|
|
$this->_fields['display'] = 'none'; |
5953
|
|
|
break; |
5954
|
|
|
case TDisplayStyle::Dynamic: |
5955
|
|
|
$this->_fields['display'] = ''; break; |
|
|
|
|
5956
|
|
|
case TDisplayStyle::Fixed: |
5957
|
|
|
$this->_fields['visibility'] = 'visible'; |
5958
|
|
|
break; |
5959
|
|
|
case TDisplayStyle::Hidden: |
5960
|
|
|
$this->_fields['visibility'] = 'hidden'; |
5961
|
|
|
break; |
5962
|
|
|
} |
5963
|
|
|
} |
5964
|
|
|
public function getDisplayStyle() |
5965
|
|
|
{ |
5966
|
|
|
return $this->_displayStyle; |
5967
|
|
|
} |
5968
|
|
|
public function getForeColor() |
5969
|
|
|
{ |
5970
|
|
|
return isset($this->_fields['color'])?$this->_fields['color']:''; |
5971
|
|
|
} |
5972
|
|
|
public function setForeColor($value) |
5973
|
|
|
{ |
5974
|
|
|
if(trim($value)==='') |
5975
|
|
|
unset($this->_fields['color']); |
5976
|
|
|
else |
5977
|
|
|
$this->_fields['color']=$value; |
5978
|
|
|
} |
5979
|
|
|
public function getHeight() |
5980
|
|
|
{ |
5981
|
|
|
return isset($this->_fields['height'])?$this->_fields['height']:''; |
5982
|
|
|
} |
5983
|
|
|
public function setHeight($value) |
5984
|
|
|
{ |
5985
|
|
|
if(trim($value)==='') |
5986
|
|
|
unset($this->_fields['height']); |
5987
|
|
|
else |
5988
|
|
|
$this->_fields['height']=$value; |
5989
|
|
|
} |
5990
|
|
|
public function getCustomStyle() |
5991
|
|
|
{ |
5992
|
|
|
return $this->_customStyle===null?'':$this->_customStyle; |
5993
|
|
|
} |
5994
|
|
|
public function setCustomStyle($value) |
5995
|
|
|
{ |
5996
|
|
|
$this->_customStyle=$value; |
5997
|
|
|
} |
5998
|
|
|
public function getStyleField($name) |
5999
|
|
|
{ |
6000
|
|
|
return isset($this->_fields[$name])?$this->_fields[$name]:''; |
6001
|
|
|
} |
6002
|
|
|
public function setStyleField($name,$value) |
6003
|
|
|
{ |
6004
|
|
|
$this->_fields[$name]=$value; |
6005
|
|
|
} |
6006
|
|
|
public function clearStyleField($name) |
6007
|
|
|
{ |
6008
|
|
|
unset($this->_fields[$name]); |
6009
|
|
|
} |
6010
|
|
|
public function hasStyleField($name) |
6011
|
|
|
{ |
6012
|
|
|
return isset($this->_fields[$name]); |
6013
|
|
|
} |
6014
|
|
|
public function getWidth() |
6015
|
|
|
{ |
6016
|
|
|
return isset($this->_fields['width'])?$this->_fields['width']:''; |
6017
|
|
|
} |
6018
|
|
|
public function setWidth($value) |
6019
|
|
|
{ |
6020
|
|
|
$this->_fields['width']=$value; |
6021
|
|
|
} |
6022
|
|
|
public function reset() |
6023
|
|
|
{ |
6024
|
|
|
$this->_fields=array(); |
6025
|
|
|
$this->_font=null; |
6026
|
|
|
$this->_class=null; |
6027
|
|
|
$this->_customStyle=null; |
6028
|
|
|
} |
6029
|
|
|
public function copyFrom($style) |
6030
|
|
|
{ |
6031
|
|
|
if($style instanceof TStyle) |
6032
|
|
|
{ |
6033
|
|
|
$this->_fields=array_merge($this->_fields,$style->_fields); |
6034
|
|
|
if($style->_class!==null) |
6035
|
|
|
$this->_class=$style->_class; |
6036
|
|
|
if($style->_customStyle!==null) |
6037
|
|
|
$this->_customStyle=$style->_customStyle; |
6038
|
|
|
if($style->_font!==null) |
6039
|
|
|
$this->getFont()->copyFrom($style->_font); |
6040
|
|
|
} |
6041
|
|
|
} |
6042
|
|
|
public function mergeWith($style) |
6043
|
|
|
{ |
6044
|
|
|
if($style instanceof TStyle) |
6045
|
|
|
{ |
6046
|
|
|
$this->_fields=array_merge($style->_fields,$this->_fields); |
6047
|
|
|
if($this->_class===null) |
6048
|
|
|
$this->_class=$style->_class; |
6049
|
|
|
if($this->_customStyle===null) |
6050
|
|
|
$this->_customStyle=$style->_customStyle; |
6051
|
|
|
if($style->_font!==null) |
6052
|
|
|
$this->getFont()->mergeWith($style->_font); |
6053
|
|
|
} |
6054
|
|
|
} |
6055
|
|
|
public function addAttributesToRender($writer) |
6056
|
|
|
{ |
6057
|
|
|
if($this->_customStyle!==null) |
6058
|
|
|
{ |
6059
|
|
|
foreach(explode(';',$this->_customStyle) as $style) |
6060
|
|
|
{ |
6061
|
|
|
$arr=explode(':',$style,2); |
6062
|
|
|
if(isset($arr[1]) && trim($arr[0])!=='') |
6063
|
|
|
$writer->addStyleAttribute(trim($arr[0]),trim($arr[1])); |
6064
|
|
|
} |
6065
|
|
|
} |
6066
|
|
|
$writer->addStyleAttributes($this->_fields); |
6067
|
|
|
if($this->_font!==null) |
6068
|
|
|
$this->_font->addAttributesToRender($writer); |
6069
|
|
|
if($this->_class!==null) |
6070
|
|
|
$writer->addAttribute('class',$this->_class); |
6071
|
|
|
} |
6072
|
|
|
public function getStyleFields() |
6073
|
|
|
{ |
6074
|
|
|
return $this->_fields; |
6075
|
|
|
} |
6076
|
|
|
} |
6077
|
|
|
class TDisplayStyle extends TEnumerable |
6078
|
|
|
{ |
6079
|
|
|
const None='None'; |
6080
|
|
|
const Dynamic='Dynamic'; |
6081
|
|
|
const Fixed='Fixed'; |
6082
|
|
|
const Hidden='Hidden'; |
6083
|
|
|
} |
6084
|
|
|
class TTableStyle extends TStyle |
6085
|
|
|
{ |
6086
|
|
|
private $_backImageUrl=null; |
6087
|
|
|
private $_horizontalAlign=null; |
6088
|
|
|
private $_cellPadding=null; |
6089
|
|
|
private $_cellSpacing=null; |
6090
|
|
|
private $_gridLines=null; |
6091
|
|
|
private $_borderCollapse=null; |
6092
|
|
|
protected function _getZappableSleepProps(&$exprops) |
6093
|
|
|
{ |
6094
|
|
|
parent::_getZappableSleepProps($exprops); |
6095
|
|
|
if ($this->_backImageUrl===null) |
6096
|
|
|
$exprops[] = "\0TTableStyle\0_backImageUrl"; |
6097
|
|
|
if ($this->_horizontalAlign===null) |
6098
|
|
|
$exprops[] = "\0TTableStyle\0_horizontalAlign"; |
6099
|
|
|
if ($this->_cellPadding===null) |
6100
|
|
|
$exprops[] = "\0TTableStyle\0_cellPadding"; |
6101
|
|
|
if ($this->_cellSpacing===null) |
6102
|
|
|
$exprops[] = "\0TTableStyle\0_cellSpacing"; |
6103
|
|
|
if ($this->_gridLines===null) |
6104
|
|
|
$exprops[] = "\0TTableStyle\0_gridLines"; |
6105
|
|
|
if ($this->_borderCollapse===null) |
6106
|
|
|
$exprops[] = "\0TTableStyle\0_borderCollapse"; |
6107
|
|
|
} |
6108
|
|
|
public function reset() |
6109
|
|
|
{ |
6110
|
|
|
$this->_backImageUrl=null; |
6111
|
|
|
$this->_horizontalAlign=null; |
6112
|
|
|
$this->_cellPadding=null; |
6113
|
|
|
$this->_cellSpacing=null; |
6114
|
|
|
$this->_gridLines=null; |
6115
|
|
|
$this->_borderCollapse=null; |
6116
|
|
|
} |
6117
|
|
|
public function copyFrom($style) |
6118
|
|
|
{ |
6119
|
|
|
parent::copyFrom($style); |
6120
|
|
|
if($style instanceof TTableStyle) |
6121
|
|
|
{ |
6122
|
|
|
if($style->_backImageUrl!==null) |
6123
|
|
|
$this->_backImageUrl=$style->_backImageUrl; |
6124
|
|
|
if($style->_horizontalAlign!==null) |
6125
|
|
|
$this->_horizontalAlign=$style->_horizontalAlign; |
6126
|
|
|
if($style->_cellPadding!==null) |
6127
|
|
|
$this->_cellPadding=$style->_cellPadding; |
6128
|
|
|
if($style->_cellSpacing!==null) |
6129
|
|
|
$this->_cellSpacing=$style->_cellSpacing; |
6130
|
|
|
if($style->_gridLines!==null) |
6131
|
|
|
$this->_gridLines=$style->_gridLines; |
6132
|
|
|
if($style->_borderCollapse!==null) |
6133
|
|
|
$this->_borderCollapse=$style->_borderCollapse; |
6134
|
|
|
} |
6135
|
|
|
} |
6136
|
|
|
public function mergeWith($style) |
6137
|
|
|
{ |
6138
|
|
|
parent::mergeWith($style); |
6139
|
|
|
if($style instanceof TTableStyle) |
6140
|
|
|
{ |
6141
|
|
|
if($this->_backImageUrl===null && $style->_backImageUrl!==null) |
6142
|
|
|
$this->_backImageUrl=$style->_backImageUrl; |
6143
|
|
|
if($this->_horizontalAlign===null && $style->_horizontalAlign!==null) |
6144
|
|
|
$this->_horizontalAlign=$style->_horizontalAlign; |
6145
|
|
|
if($this->_cellPadding===null && $style->_cellPadding!==null) |
6146
|
|
|
$this->_cellPadding=$style->_cellPadding; |
6147
|
|
|
if($this->_cellSpacing===null && $style->_cellSpacing!==null) |
6148
|
|
|
$this->_cellSpacing=$style->_cellSpacing; |
6149
|
|
|
if($this->_gridLines===null && $style->_gridLines!==null) |
6150
|
|
|
$this->_gridLines=$style->_gridLines; |
6151
|
|
|
if($this->_borderCollapse===null && $style->_borderCollapse!==null) |
6152
|
|
|
$this->_borderCollapse=$style->_borderCollapse; |
6153
|
|
|
} |
6154
|
|
|
} |
6155
|
|
|
public function addAttributesToRender($writer) |
6156
|
|
|
{ |
6157
|
|
|
if(($url=trim($this->getBackImageUrl()))!=='') |
6158
|
|
|
$writer->addStyleAttribute('background-image','url('.$url.')'); |
6159
|
|
|
if(($horizontalAlign=$this->getHorizontalAlign())!==THorizontalAlign::NotSet) |
6160
|
|
|
$writer->addStyleAttribute('text-align',strtolower($horizontalAlign)); |
6161
|
|
|
if(($cellPadding=$this->getCellPadding())>=0) |
6162
|
|
|
$writer->addAttribute('cellpadding',"$cellPadding"); |
6163
|
|
|
if(($cellSpacing=$this->getCellSpacing())>=0) |
6164
|
|
|
$writer->addAttribute('cellspacing',"$cellSpacing"); |
6165
|
|
|
if($this->getBorderCollapse()) |
6166
|
|
|
$writer->addStyleAttribute('border-collapse','collapse'); |
6167
|
|
|
switch($this->getGridLines()) |
6168
|
|
|
{ |
6169
|
|
|
case TTableGridLines::Horizontal : $writer->addAttribute('rules','rows'); break; |
|
|
|
|
6170
|
|
|
case TTableGridLines::Vertical : $writer->addAttribute('rules','cols'); break; |
|
|
|
|
6171
|
|
|
case TTableGridLines::Both : $writer->addAttribute('rules','all'); break; |
|
|
|
|
6172
|
|
|
} |
6173
|
|
|
parent::addAttributesToRender($writer); |
6174
|
|
|
} |
6175
|
|
|
public function getBackImageUrl() |
6176
|
|
|
{ |
6177
|
|
|
return $this->_backImageUrl===null?'':$this->_backImageUrl; |
6178
|
|
|
} |
6179
|
|
|
public function setBackImageUrl($value) |
6180
|
|
|
{ |
6181
|
|
|
$this->_backImageUrl=$value; |
6182
|
|
|
} |
6183
|
|
|
public function getHorizontalAlign() |
6184
|
|
|
{ |
6185
|
|
|
return $this->_horizontalAlign===null?THorizontalAlign::NotSet:$this->_horizontalAlign; |
6186
|
|
|
} |
6187
|
|
|
public function setHorizontalAlign($value) |
6188
|
|
|
{ |
6189
|
|
|
$this->_horizontalAlign=TPropertyValue::ensureEnum($value,'THorizontalAlign'); |
6190
|
|
|
} |
6191
|
|
|
public function getCellPadding() |
6192
|
|
|
{ |
6193
|
|
|
return $this->_cellPadding===null?-1:$this->_cellPadding; |
6194
|
|
|
} |
6195
|
|
|
public function setCellPadding($value) |
6196
|
|
|
{ |
6197
|
|
|
if(($this->_cellPadding=TPropertyValue::ensureInteger($value))<-1) |
6198
|
|
|
throw new TInvalidDataValueException('tablestyle_cellpadding_invalid'); |
6199
|
|
|
} |
6200
|
|
|
public function getCellSpacing() |
6201
|
|
|
{ |
6202
|
|
|
return $this->_cellSpacing===null?-1:$this->_cellSpacing; |
6203
|
|
|
} |
6204
|
|
|
public function setCellSpacing($value) |
6205
|
|
|
{ |
6206
|
|
|
if(($this->_cellSpacing=TPropertyValue::ensureInteger($value))<-1) |
6207
|
|
|
throw new TInvalidDataValueException('tablestyle_cellspacing_invalid'); |
6208
|
|
|
} |
6209
|
|
|
public function getGridLines() |
6210
|
|
|
{ |
6211
|
|
|
return $this->_gridLines===null?TTableGridLines::None:$this->_gridLines; |
6212
|
|
|
} |
6213
|
|
|
public function setGridLines($value) |
6214
|
|
|
{ |
6215
|
|
|
$this->_gridLines=TPropertyValue::ensureEnum($value,'TTableGridLines'); |
6216
|
|
|
} |
6217
|
|
|
public function getBorderCollapse() |
6218
|
|
|
{ |
6219
|
|
|
return $this->_borderCollapse===null?false:$this->_borderCollapse; |
6220
|
|
|
} |
6221
|
|
|
public function setBorderCollapse($value) |
6222
|
|
|
{ |
6223
|
|
|
$this->_borderCollapse=TPropertyValue::ensureBoolean($value); |
6224
|
|
|
} |
6225
|
|
|
} |
6226
|
|
|
class TTableItemStyle extends TStyle |
6227
|
|
|
{ |
6228
|
|
|
private $_horizontalAlign=null; |
6229
|
|
|
private $_verticalAlign=null; |
6230
|
|
|
private $_wrap=null; |
6231
|
|
|
protected function _getZappableSleepProps(&$exprops) |
6232
|
|
|
{ |
6233
|
|
|
parent::_getZappableSleepProps($exprops); |
6234
|
|
|
if ($this->_horizontalAlign===null) |
6235
|
|
|
$exprops[] = "\0TTableItemStyle\0_horizontalAlign"; |
6236
|
|
|
if ($this->_verticalAlign===null) |
6237
|
|
|
$exprops[] = "\0TTableItemStyle\0_verticalAlign"; |
6238
|
|
|
if ($this->_wrap===null) |
6239
|
|
|
$exprops[] = "\0TTableItemStyle\0_wrap"; |
6240
|
|
|
} |
6241
|
|
|
public function reset() |
6242
|
|
|
{ |
6243
|
|
|
parent::reset(); |
6244
|
|
|
$this->_verticalAlign=null; |
6245
|
|
|
$this->_horizontalAlign=null; |
6246
|
|
|
$this->_wrap=null; |
6247
|
|
|
} |
6248
|
|
|
public function copyFrom($style) |
6249
|
|
|
{ |
6250
|
|
|
parent::copyFrom($style); |
6251
|
|
|
if($style instanceof TTableItemStyle) |
6252
|
|
|
{ |
6253
|
|
|
if($this->_verticalAlign===null && $style->_verticalAlign!==null) |
6254
|
|
|
$this->_verticalAlign=$style->_verticalAlign; |
6255
|
|
|
if($this->_horizontalAlign===null && $style->_horizontalAlign!==null) |
6256
|
|
|
$this->_horizontalAlign=$style->_horizontalAlign; |
6257
|
|
|
if($this->_wrap===null && $style->_wrap!==null) |
6258
|
|
|
$this->_wrap=$style->_wrap; |
6259
|
|
|
} |
6260
|
|
|
} |
6261
|
|
|
public function mergeWith($style) |
6262
|
|
|
{ |
6263
|
|
|
parent::mergeWith($style); |
6264
|
|
|
if($style instanceof TTableItemStyle) |
6265
|
|
|
{ |
6266
|
|
|
if($style->_verticalAlign!==null) |
6267
|
|
|
$this->_verticalAlign=$style->_verticalAlign; |
6268
|
|
|
if($style->_horizontalAlign!==null) |
6269
|
|
|
$this->_horizontalAlign=$style->_horizontalAlign; |
6270
|
|
|
if($style->_wrap!==null) |
6271
|
|
|
$this->_wrap=$style->_wrap; |
6272
|
|
|
} |
6273
|
|
|
} |
6274
|
|
|
public function addAttributesToRender($writer) |
6275
|
|
|
{ |
6276
|
|
|
if(!$this->getWrap()) |
|
|
|
|
6277
|
|
|
$writer->addStyleAttribute('white-space','nowrap'); |
6278
|
|
|
if(($horizontalAlign=$this->getHorizontalAlign())!==THorizontalAlign::NotSet) |
6279
|
|
|
$writer->addAttribute('align',strtolower($horizontalAlign)); |
6280
|
|
|
if(($verticalAlign=$this->getVerticalAlign())!==TVerticalAlign::NotSet) |
6281
|
|
|
$writer->addAttribute('valign',strtolower($verticalAlign)); |
6282
|
|
|
parent::addAttributesToRender($writer); |
6283
|
|
|
} |
6284
|
|
|
public function getHorizontalAlign() |
6285
|
|
|
{ |
6286
|
|
|
return $this->_horizontalAlign===null?THorizontalAlign::NotSet:$this->_horizontalAlign; |
6287
|
|
|
} |
6288
|
|
|
public function setHorizontalAlign($value) |
6289
|
|
|
{ |
6290
|
|
|
$this->_horizontalAlign=TPropertyValue::ensureEnum($value,'THorizontalAlign'); |
6291
|
|
|
} |
6292
|
|
|
public function getVerticalAlign() |
6293
|
|
|
{ |
6294
|
|
|
return $this->_verticalAlign===null?TVerticalAlign::NotSet:$this->_verticalAlign; |
6295
|
|
|
} |
6296
|
|
|
public function setVerticalAlign($value) |
6297
|
|
|
{ |
6298
|
|
|
$this->_verticalAlign=TPropertyValue::ensureEnum($value,'TVerticalAlign'); |
6299
|
|
|
} |
6300
|
|
|
public function getWrap() |
6301
|
|
|
{ |
6302
|
|
|
return $this->_wrap===null?true:$this->_wrap; |
6303
|
|
|
} |
6304
|
|
|
public function setWrap($value) |
6305
|
|
|
{ |
6306
|
|
|
$this->_wrap=TPropertyValue::ensureBoolean($value); |
6307
|
|
|
} |
6308
|
|
|
} |
6309
|
|
|
class THorizontalAlign extends TEnumerable |
6310
|
|
|
{ |
6311
|
|
|
const NotSet='NotSet'; |
6312
|
|
|
const Left='Left'; |
6313
|
|
|
const Right='Right'; |
6314
|
|
|
const Center='Center'; |
6315
|
|
|
const Justify='Justify'; |
6316
|
|
|
} |
6317
|
|
|
class TVerticalAlign extends TEnumerable |
6318
|
|
|
{ |
6319
|
|
|
const NotSet='NotSet'; |
6320
|
|
|
const Top='Top'; |
6321
|
|
|
const Bottom='Bottom'; |
6322
|
|
|
const Middle='Middle'; |
6323
|
|
|
} |
6324
|
|
|
class TTableGridLines extends TEnumerable |
6325
|
|
|
{ |
6326
|
|
|
const None='None'; |
6327
|
|
|
const Horizontal='Horizontal'; |
6328
|
|
|
const Vertical='Vertical'; |
6329
|
|
|
const Both='Both'; |
6330
|
|
|
} |
6331
|
|
|
class TWebControlAdapter extends TControlAdapter |
6332
|
|
|
{ |
6333
|
|
|
public function render($writer) |
6334
|
|
|
{ |
6335
|
|
|
$this->renderBeginTag($writer); |
6336
|
|
|
$this->renderContents($writer); |
6337
|
|
|
$this->renderEndTag($writer); |
6338
|
|
|
} |
6339
|
|
|
public function renderBeginTag($writer) |
6340
|
|
|
{ |
6341
|
|
|
$this->getControl()->renderBeginTag($writer); |
6342
|
|
|
} |
6343
|
|
|
public function renderContents($writer) |
6344
|
|
|
{ |
6345
|
|
|
$this->getControl()->renderContents($writer); |
6346
|
|
|
} |
6347
|
|
|
public function renderEndTag($writer) |
6348
|
|
|
{ |
6349
|
|
|
$this->getControl()->renderEndTag($writer); |
6350
|
|
|
} |
6351
|
|
|
} |
6352
|
|
|
class TWebControlDecorator extends TComponent { |
6353
|
|
|
private $_internalonly; |
6354
|
|
|
private $_usestate = false; |
6355
|
|
|
private $_control; |
6356
|
|
|
private $_outercontrol; |
6357
|
|
|
private $_addedTemplateDecoration=false; |
6358
|
|
|
private $_pretagtext = ''; |
6359
|
|
|
private $_precontentstext = ''; |
6360
|
|
|
private $_postcontentstext = ''; |
6361
|
|
|
private $_posttagtext = ''; |
6362
|
|
|
private $_pretagtemplate; |
6363
|
|
|
private $_precontentstemplate; |
6364
|
|
|
private $_postcontentstemplate; |
6365
|
|
|
private $_posttagtemplate; |
6366
|
|
|
public function __construct($control, $onlyinternal = false) { |
6367
|
|
|
$this->_control = $control; |
6368
|
|
|
$this->_internalonly = $onlyinternal; |
6369
|
|
|
} |
6370
|
|
|
public function getUseState() |
6371
|
|
|
{ |
6372
|
|
|
return $this->_usestate; |
6373
|
|
|
} |
6374
|
|
|
public function setUseState($value) |
6375
|
|
|
{ |
6376
|
|
|
$this->_usestate = TPropertyValue::ensureBoolean($value); |
6377
|
|
|
} |
6378
|
|
|
public function getPreTagText() { |
6379
|
|
|
return $this->_pretagtext; |
6380
|
|
|
} |
6381
|
|
|
public function setPreTagText($value) { |
6382
|
|
|
if(!$this->_internalonly && !$this->_control->getIsSkinApplied()) |
6383
|
|
|
$this->_pretagtext = TPropertyValue::ensureString($value); |
6384
|
|
|
} |
6385
|
|
|
public function getPreContentsText() { |
6386
|
|
|
return $this->_precontentstext; |
6387
|
|
|
} |
6388
|
|
|
public function setPreContentsText($value) { |
6389
|
|
|
if(!$this->_control->getIsSkinApplied()) |
6390
|
|
|
$this->_precontentstext = TPropertyValue::ensureString($value); |
6391
|
|
|
} |
6392
|
|
|
public function getPostContentsText() { |
6393
|
|
|
return $this->_postcontentstext; |
6394
|
|
|
} |
6395
|
|
|
public function setPostContentsText($value) { |
6396
|
|
|
if(!$this->_control->getIsSkinApplied()) |
6397
|
|
|
$this->_postcontentstext = TPropertyValue::ensureString($value); |
6398
|
|
|
} |
6399
|
|
|
public function getPostTagText() { |
6400
|
|
|
return $this->_posttagtext; |
6401
|
|
|
} |
6402
|
|
|
public function setPostTagText($value) { |
6403
|
|
|
if(!$this->_internalonly && !$this->_control->getIsSkinApplied()) |
6404
|
|
|
$this->_posttagtext = TPropertyValue::ensureString($value); |
6405
|
|
|
} |
6406
|
|
|
public function getPreTagTemplate() { |
6407
|
|
|
return $this->_pretagtemplate; |
6408
|
|
|
} |
6409
|
|
|
public function setPreTagTemplate($value) { |
6410
|
|
|
if(!$this->_internalonly && !$this->_control->getIsSkinApplied()) |
6411
|
|
|
$this->_pretagtemplate = $value; |
6412
|
|
|
} |
6413
|
|
|
public function getPreContentsTemplate() { |
6414
|
|
|
return $this->_precontentstemplate; |
6415
|
|
|
} |
6416
|
|
|
public function setPreContentsTemplate($value) { |
6417
|
|
|
if(!$this->_control->getIsSkinApplied()) |
6418
|
|
|
$this->_precontentstemplate = $value; |
6419
|
|
|
} |
6420
|
|
|
public function getPostContentsTemplate() { |
6421
|
|
|
return $this->_postcontentstemplate; |
6422
|
|
|
} |
6423
|
|
|
public function setPostContentsTemplate($value) { |
6424
|
|
|
if(!$this->_control->getIsSkinApplied()) |
6425
|
|
|
$this->_postcontentstemplate = $value; |
6426
|
|
|
} |
6427
|
|
|
public function getPostTagTemplate() { |
6428
|
|
|
return $this->_posttagtemplate; |
6429
|
|
|
} |
6430
|
|
|
public function setPostTagTemplate($value) { |
6431
|
|
|
if(!$this->_internalonly && !$this->_control->getIsSkinApplied()) |
6432
|
|
|
$this->_posttagtemplate = $value; |
6433
|
|
|
} |
6434
|
|
|
public function instantiate($outercontrol = null) { |
6435
|
|
|
if($this->getPreTagTemplate() || $this->getPreContentsTemplate() || |
6436
|
|
|
$this->getPostContentsTemplate() || $this->getPostTagTemplate()) { |
6437
|
|
|
$this->_outercontrol = $outercontrol; |
6438
|
|
|
if($this->getUseState()) |
6439
|
|
|
$this->ensureTemplateDecoration(); |
6440
|
|
|
else |
6441
|
|
|
$this->_control->getPage()->onSaveStateComplete[] = array($this, 'ensureTemplateDecoration'); |
6442
|
|
|
} |
6443
|
|
|
} |
6444
|
|
|
public function ensureTemplateDecoration($sender=null, $param=null) { |
6445
|
|
|
$control = $this->_control; |
6446
|
|
|
$outercontrol = $this->_outercontrol; |
6447
|
|
|
if($outercontrol === null) |
6448
|
|
|
$outercontrol = $control; |
6449
|
|
|
if($this->_addedTemplateDecoration) |
6450
|
|
|
return $this->_addedTemplateDecoration; |
6451
|
|
|
$this->_addedTemplateDecoration = true; |
6452
|
|
|
if($this->getPreContentsTemplate()) |
6453
|
|
|
{ |
6454
|
|
|
$precontents = Prado::createComponent('TCompositeControl'); |
6455
|
|
|
$this->getPreContentsTemplate()->instantiateIn($precontents); |
6456
|
|
|
$control->getControls()->insertAt(0, $precontents); |
6457
|
|
|
} |
6458
|
|
|
if($this->getPostContentsTemplate()) |
6459
|
|
|
{ |
6460
|
|
|
$postcontents = Prado::createComponent('TCompositeControl'); |
6461
|
|
|
$this->getPostContentsTemplate()->instantiateIn($postcontents); |
6462
|
|
|
$control->getControls()->add($postcontents); |
6463
|
|
|
} |
6464
|
|
|
if(!$outercontrol->getParent()) |
6465
|
|
|
return $this->_addedTemplateDecoration; |
6466
|
|
|
if($this->getPreTagTemplate()) |
6467
|
|
|
{ |
6468
|
|
|
$pretag = Prado::createComponent('TCompositeControl'); |
6469
|
|
|
$this->getPreTagTemplate()->instantiateIn($pretag); |
6470
|
|
|
$outercontrol->getParent()->getControls()->insertBefore($outercontrol, $pretag); |
6471
|
|
|
} |
6472
|
|
|
if($this->getPostTagTemplate()) |
6473
|
|
|
{ |
6474
|
|
|
$posttag = Prado::createComponent('TCompositeControl'); |
6475
|
|
|
$this->getPostTagTemplate()->instantiateIn($posttag); |
6476
|
|
|
$outercontrol->getParent()->getControls()->insertAfter($outercontrol, $posttag); |
6477
|
|
|
} |
6478
|
|
|
return true; |
6479
|
|
|
} |
6480
|
|
|
public function renderPreTagText($writer) { |
6481
|
|
|
$writer->write($this->getPreTagText()); |
6482
|
|
|
} |
6483
|
|
|
public function renderPreContentsText($writer) { |
6484
|
|
|
$writer->write($this->getPreContentsText()); |
6485
|
|
|
} |
6486
|
|
|
public function renderPostContentsText($writer) { |
6487
|
|
|
$writer->write($this->getPostContentsText()); |
6488
|
|
|
} |
6489
|
|
|
public function renderPostTagText($writer) { |
6490
|
|
|
$writer->write($this->getPostTagText()); |
6491
|
|
|
} |
6492
|
|
|
} |
6493
|
|
|
class TWebControl extends TControl implements IStyleable |
6494
|
|
|
{ |
6495
|
|
|
private $_ensureid=false; |
6496
|
|
|
protected $_decorator; |
6497
|
|
|
public function setEnsureId($value) |
6498
|
|
|
{ |
6499
|
|
|
$this->_ensureid |= TPropertyValue::ensureBoolean($value); |
6500
|
|
|
} |
6501
|
|
|
public function getEnsureId() |
6502
|
|
|
{ |
6503
|
|
|
return $this->_ensureid; |
6504
|
|
|
} |
6505
|
|
|
public function getDecorator($create=true) |
6506
|
|
|
{ |
6507
|
|
|
if($create && !$this->_decorator) |
6508
|
|
|
$this->_decorator = Prado::createComponent('TWebControlDecorator', $this); |
6509
|
|
|
return $this->_decorator; |
6510
|
|
|
} |
6511
|
|
|
public function copyBaseAttributes(TWebControl $control) |
6512
|
|
|
{ |
6513
|
|
|
$this->setAccessKey($control->getAccessKey()); |
6514
|
|
|
$this->setToolTip($control->getToolTip()); |
6515
|
|
|
$this->setTabIndex($control->getTabIndex()); |
6516
|
|
|
if(!$control->getEnabled()) |
6517
|
|
|
$this->setEnabled(false); |
6518
|
|
|
if($control->getHasAttributes()) |
6519
|
|
|
$this->getAttributes()->copyFrom($control->getAttributes()); |
6520
|
|
|
} |
6521
|
|
|
public function getAccessKey() |
6522
|
|
|
{ |
6523
|
|
|
return $this->getViewState('AccessKey',''); |
6524
|
|
|
} |
6525
|
|
|
public function setAccessKey($value) |
6526
|
|
|
{ |
6527
|
|
|
if(strlen($value)>1) |
6528
|
|
|
throw new TInvalidDataValueException('webcontrol_accesskey_invalid',get_class($this),$value); |
6529
|
|
|
$this->setViewState('AccessKey',$value,''); |
6530
|
|
|
} |
6531
|
|
|
public function getBackColor() |
6532
|
|
|
{ |
6533
|
|
|
if($style=$this->getViewState('Style',null)) |
6534
|
|
|
return $style->getBackColor(); |
6535
|
|
|
else |
6536
|
|
|
return ''; |
6537
|
|
|
} |
6538
|
|
|
public function setBackColor($value) |
6539
|
|
|
{ |
6540
|
|
|
$this->getStyle()->setBackColor($value); |
6541
|
|
|
} |
6542
|
|
|
public function getBorderColor() |
6543
|
|
|
{ |
6544
|
|
|
if($style=$this->getViewState('Style',null)) |
6545
|
|
|
return $style->getBorderColor(); |
6546
|
|
|
else |
6547
|
|
|
return ''; |
6548
|
|
|
} |
6549
|
|
|
public function setBorderColor($value) |
6550
|
|
|
{ |
6551
|
|
|
$this->getStyle()->setBorderColor($value); |
6552
|
|
|
} |
6553
|
|
|
public function getBorderStyle() |
6554
|
|
|
{ |
6555
|
|
|
if($style=$this->getViewState('Style',null)) |
6556
|
|
|
return $style->getBorderStyle(); |
6557
|
|
|
else |
6558
|
|
|
return ''; |
6559
|
|
|
} |
6560
|
|
|
public function setBorderStyle($value) |
6561
|
|
|
{ |
6562
|
|
|
$this->getStyle()->setBorderStyle($value); |
6563
|
|
|
} |
6564
|
|
|
public function getBorderWidth() |
6565
|
|
|
{ |
6566
|
|
|
if($style=$this->getViewState('Style',null)) |
6567
|
|
|
return $style->getBorderWidth(); |
6568
|
|
|
else |
6569
|
|
|
return ''; |
6570
|
|
|
} |
6571
|
|
|
public function setBorderWidth($value) |
6572
|
|
|
{ |
6573
|
|
|
$this->getStyle()->setBorderWidth($value); |
6574
|
|
|
} |
6575
|
|
|
public function getFont() |
6576
|
|
|
{ |
6577
|
|
|
return $this->getStyle()->getFont(); |
6578
|
|
|
} |
6579
|
|
|
public function getForeColor() |
6580
|
|
|
{ |
6581
|
|
|
if($style=$this->getViewState('Style',null)) |
6582
|
|
|
return $style->getForeColor(); |
6583
|
|
|
else |
6584
|
|
|
return ''; |
6585
|
|
|
} |
6586
|
|
|
public function setForeColor($value) |
6587
|
|
|
{ |
6588
|
|
|
$this->getStyle()->setForeColor($value); |
6589
|
|
|
} |
6590
|
|
|
public function getHeight() |
6591
|
|
|
{ |
6592
|
|
|
if($style=$this->getViewState('Style',null)) |
6593
|
|
|
return $style->getHeight(); |
6594
|
|
|
else |
6595
|
|
|
return ''; |
6596
|
|
|
} |
6597
|
|
|
public function setDisplay($value) |
6598
|
|
|
{ |
6599
|
|
|
$this->getStyle()->setDisplayStyle($value); |
6600
|
|
|
} |
6601
|
|
|
public function getDisplay() |
6602
|
|
|
{ |
6603
|
|
|
return $this->getStyle()->getDisplayStyle(); |
6604
|
|
|
} |
6605
|
|
|
public function setCssClass($value) |
6606
|
|
|
{ |
6607
|
|
|
$this->getStyle()->setCssClass($value); |
6608
|
|
|
} |
6609
|
|
|
public function getCssClass() |
6610
|
|
|
{ |
6611
|
|
|
if($style=$this->getViewState('Style',null)) |
6612
|
|
|
return $style->getCssClass(); |
6613
|
|
|
else |
6614
|
|
|
return ''; |
6615
|
|
|
} |
6616
|
|
|
public function setHeight($value) |
6617
|
|
|
{ |
6618
|
|
|
$this->getStyle()->setHeight($value); |
6619
|
|
|
} |
6620
|
|
|
public function getHasStyle() |
6621
|
|
|
{ |
6622
|
|
|
return $this->getViewState('Style',null)!==null; |
6623
|
|
|
} |
6624
|
|
|
protected function createStyle() |
6625
|
|
|
{ |
6626
|
|
|
return new TStyle; |
6627
|
|
|
} |
6628
|
|
|
public function getStyle() |
6629
|
|
|
{ |
6630
|
|
|
if($style=$this->getViewState('Style',null)) |
6631
|
|
|
return $style; |
6632
|
|
|
else |
6633
|
|
|
{ |
6634
|
|
|
$style=$this->createStyle(); |
6635
|
|
|
$this->setViewState('Style',$style,null); |
6636
|
|
|
return $style; |
6637
|
|
|
} |
6638
|
|
|
} |
6639
|
|
|
public function setStyle($value) |
6640
|
|
|
{ |
6641
|
|
|
if(is_string($value)) |
6642
|
|
|
$this->getStyle()->setCustomStyle($value); |
6643
|
|
|
else |
6644
|
|
|
throw new TInvalidDataValueException('webcontrol_style_invalid',get_class($this)); |
6645
|
|
|
} |
6646
|
|
|
public function clearStyle() |
6647
|
|
|
{ |
6648
|
|
|
$this->clearViewState('Style'); |
6649
|
|
|
} |
6650
|
|
|
public function getTabIndex() |
6651
|
|
|
{ |
6652
|
|
|
return $this->getViewState('TabIndex',0); |
6653
|
|
|
} |
6654
|
|
|
public function setTabIndex($value) |
6655
|
|
|
{ |
6656
|
|
|
$this->setViewState('TabIndex',TPropertyValue::ensureInteger($value),0); |
6657
|
|
|
} |
6658
|
|
|
protected function getTagName() |
6659
|
|
|
{ |
6660
|
|
|
return 'span'; |
6661
|
|
|
} |
6662
|
|
|
public function getToolTip() |
6663
|
|
|
{ |
6664
|
|
|
return $this->getViewState('ToolTip',''); |
6665
|
|
|
} |
6666
|
|
|
public function setToolTip($value) |
6667
|
|
|
{ |
6668
|
|
|
$this->setViewState('ToolTip',$value,''); |
6669
|
|
|
} |
6670
|
|
|
public function getWidth() |
6671
|
|
|
{ |
6672
|
|
|
if($style=$this->getViewState('Style',null)) |
6673
|
|
|
return $style->getWidth(); |
6674
|
|
|
else |
6675
|
|
|
return ''; |
6676
|
|
|
} |
6677
|
|
|
public function setWidth($value) |
6678
|
|
|
{ |
6679
|
|
|
$this->getStyle()->setWidth($value); |
6680
|
|
|
} |
6681
|
|
|
public function onPreRender($param) { |
6682
|
|
|
if($decorator = $this->getDecorator(false)) |
6683
|
|
|
$decorator->instantiate(); |
6684
|
|
|
parent::onPreRender($param); |
6685
|
|
|
} |
6686
|
|
|
protected function addAttributesToRender($writer) |
6687
|
|
|
{ |
6688
|
|
|
if($this->getID()!=='' || $this->getEnsureId()) |
6689
|
|
|
$writer->addAttribute('id',$this->getClientID()); |
6690
|
|
|
if(($accessKey=$this->getAccessKey())!=='') |
6691
|
|
|
$writer->addAttribute('accesskey',$accessKey); |
6692
|
|
|
if(!$this->getEnabled()) |
6693
|
|
|
$writer->addAttribute('disabled','disabled'); |
6694
|
|
|
if(($tabIndex=$this->getTabIndex())>0) |
6695
|
|
|
$writer->addAttribute('tabindex',"$tabIndex"); |
6696
|
|
|
if(($toolTip=$this->getToolTip())!=='') |
6697
|
|
|
$writer->addAttribute('title',$toolTip); |
6698
|
|
|
if($style=$this->getViewState('Style',null)) |
6699
|
|
|
$style->addAttributesToRender($writer); |
6700
|
|
|
if($this->getHasAttributes()) |
6701
|
|
|
{ |
6702
|
|
|
foreach($this->getAttributes() as $name=>$value) |
6703
|
|
|
$writer->addAttribute($name,$value); |
6704
|
|
|
} |
6705
|
|
|
} |
6706
|
|
|
public function render($writer) |
6707
|
|
|
{ |
6708
|
|
|
$this->renderBeginTag($writer); |
6709
|
|
|
$this->renderContents($writer); |
6710
|
|
|
$this->renderEndTag($writer); |
6711
|
|
|
} |
6712
|
|
|
public function renderBeginTag($writer) |
6713
|
|
|
{ |
6714
|
|
|
if($decorator = $this->getDecorator(false)) { |
6715
|
|
|
$decorator->renderPreTagText($writer); |
6716
|
|
|
$this->addAttributesToRender($writer); |
6717
|
|
|
$writer->renderBeginTag($this->getTagName()); |
6718
|
|
|
$decorator->renderPreContentsText($writer); |
6719
|
|
|
} else { |
6720
|
|
|
$this->addAttributesToRender($writer); |
6721
|
|
|
$writer->renderBeginTag($this->getTagName()); |
6722
|
|
|
} |
6723
|
|
|
} |
6724
|
|
|
public function renderContents($writer) |
6725
|
|
|
{ |
6726
|
|
|
parent::renderChildren($writer); |
6727
|
|
|
} |
6728
|
|
|
public function renderEndTag($writer) |
6729
|
|
|
{ |
6730
|
|
|
if($decorator = $this->getDecorator(false)) { |
6731
|
|
|
$decorator->renderPostContentsText($writer); |
6732
|
|
|
$writer->renderEndTag(); |
6733
|
|
|
$decorator->renderPostTagText($writer); |
6734
|
|
|
} else |
6735
|
|
|
$writer->renderEndTag($writer); |
6736
|
|
|
} |
6737
|
|
|
} |
6738
|
|
|
class TCompositeControl extends TControl implements INamingContainer |
6739
|
|
|
{ |
6740
|
|
|
protected function initRecursive($namingContainer=null) |
6741
|
|
|
{ |
6742
|
|
|
$this->ensureChildControls(); |
6743
|
|
|
parent::initRecursive($namingContainer); |
6744
|
|
|
} |
6745
|
|
|
} |
6746
|
|
|
class TTemplateControl extends TCompositeControl |
6747
|
|
|
{ |
6748
|
|
|
const EXT_TEMPLATE='.tpl'; |
6749
|
|
|
private static $_template=array(); |
6750
|
|
|
private $_localTemplate=null; |
6751
|
|
|
private $_master=null; |
6752
|
|
|
private $_masterClass=''; |
6753
|
|
|
private $_contents=array(); |
6754
|
|
|
private $_placeholders=array(); |
6755
|
|
|
public function getTemplate() |
6756
|
|
|
{ |
6757
|
|
|
if($this->_localTemplate===null) |
6758
|
|
|
{ |
6759
|
|
|
$class=get_class($this); |
6760
|
|
|
if(!isset(self::$_template[$class])) |
6761
|
|
|
self::$_template[$class]=$this->loadTemplate(); |
6762
|
|
|
return self::$_template[$class]; |
6763
|
|
|
} |
6764
|
|
|
else |
6765
|
|
|
return $this->_localTemplate; |
6766
|
|
|
} |
6767
|
|
|
public function setTemplate($value) |
6768
|
|
|
{ |
6769
|
|
|
$this->_localTemplate=$value; |
6770
|
|
|
} |
6771
|
|
|
public function getIsSourceTemplateControl() |
6772
|
|
|
{ |
6773
|
|
|
if(($template=$this->getTemplate())!==null) |
6774
|
|
|
return $template->getIsSourceTemplate(); |
6775
|
|
|
else |
6776
|
|
|
return false; |
6777
|
|
|
} |
6778
|
|
|
public function getTemplateDirectory() |
6779
|
|
|
{ |
6780
|
|
|
if(($template=$this->getTemplate())!==null) |
6781
|
|
|
return $template->getContextPath(); |
6782
|
|
|
else |
6783
|
|
|
return ''; |
6784
|
|
|
} |
6785
|
|
|
protected function loadTemplate() |
6786
|
|
|
{ |
6787
|
|
|
$template=$this->getService()->getTemplateManager()->getTemplateByClassName(get_class($this)); |
|
|
|
|
6788
|
|
|
return $template; |
6789
|
|
|
} |
6790
|
|
|
public function createChildControls() |
6791
|
|
|
{ |
6792
|
|
|
if($tpl=$this->getTemplate()) |
6793
|
|
|
{ |
6794
|
|
|
foreach($tpl->getDirective() as $name=>$value) |
6795
|
|
|
{ |
6796
|
|
|
if(is_string($value)) |
6797
|
|
|
$this->setSubProperty($name,$value); |
6798
|
|
|
else |
6799
|
|
|
throw new TConfigurationException('templatecontrol_directive_invalid',get_class($this),$name); |
6800
|
|
|
} |
6801
|
|
|
$tpl->instantiateIn($this); |
6802
|
|
|
} |
6803
|
|
|
} |
6804
|
|
|
public function registerContent($id,TContent $object) |
6805
|
|
|
{ |
6806
|
|
|
if(isset($this->_contents[$id])) |
6807
|
|
|
throw new TConfigurationException('templatecontrol_contentid_duplicated',$id); |
6808
|
|
|
else |
6809
|
|
|
$this->_contents[$id]=$object; |
6810
|
|
|
} |
6811
|
|
|
public function registerContentPlaceHolder($id,TContentPlaceHolder $object) |
6812
|
|
|
{ |
6813
|
|
|
if(isset($this->_placeholders[$id])) |
6814
|
|
|
throw new TConfigurationException('templatecontrol_placeholderid_duplicated',$id); |
6815
|
|
|
else |
6816
|
|
|
$this->_placeholders[$id]=$object; |
6817
|
|
|
} |
6818
|
|
|
public function getMasterClass() |
6819
|
|
|
{ |
6820
|
|
|
return $this->_masterClass; |
6821
|
|
|
} |
6822
|
|
|
public function setMasterClass($value) |
6823
|
|
|
{ |
6824
|
|
|
$this->_masterClass=$value; |
6825
|
|
|
} |
6826
|
|
|
public function getMaster() |
6827
|
|
|
{ |
6828
|
|
|
return $this->_master; |
6829
|
|
|
} |
6830
|
|
|
public function injectContent($id,$content) |
6831
|
|
|
{ |
6832
|
|
|
if(isset($this->_placeholders[$id])) |
6833
|
|
|
{ |
6834
|
|
|
$placeholder=$this->_placeholders[$id]; |
6835
|
|
|
$controls=$placeholder->getParent()->getControls(); |
6836
|
|
|
$loc=$controls->remove($placeholder); |
6837
|
|
|
$controls->insertAt($loc,$content); |
6838
|
|
|
} |
6839
|
|
|
else |
6840
|
|
|
throw new TConfigurationException('templatecontrol_placeholder_inexistent',$id); |
6841
|
|
|
} |
6842
|
|
|
protected function initRecursive($namingContainer=null) |
6843
|
|
|
{ |
6844
|
|
|
$this->ensureChildControls(); |
6845
|
|
|
if($this->_masterClass!=='') |
6846
|
|
|
{ |
6847
|
|
|
$master=Prado::createComponent($this->_masterClass); |
6848
|
|
|
if(!($master instanceof TTemplateControl)) |
6849
|
|
|
throw new TInvalidDataValueException('templatecontrol_mastercontrol_invalid'); |
6850
|
|
|
$this->_master=$master; |
6851
|
|
|
$this->getControls()->clear(); |
6852
|
|
|
$this->getControls()->add($master); |
6853
|
|
|
$master->ensureChildControls(); |
6854
|
|
|
foreach($this->_contents as $id=>$content) |
6855
|
|
|
$master->injectContent($id,$content); |
6856
|
|
|
} |
6857
|
|
|
else if(!empty($this->_contents)) |
6858
|
|
|
throw new TConfigurationException('templatecontrol_mastercontrol_required',get_class($this)); |
6859
|
|
|
parent::initRecursive($namingContainer); |
6860
|
|
|
} |
6861
|
|
|
public function tryToUpdateView($arObj, $throwExceptions = false) |
6862
|
|
|
{ |
6863
|
|
|
$objAttrs = get_class_vars(get_class($arObj)); |
6864
|
|
|
foreach (array_keys($objAttrs) as $key) |
6865
|
|
|
{ |
6866
|
|
|
try |
6867
|
|
|
{ |
6868
|
|
|
if ($key != "RELATIONS") |
6869
|
|
|
{ |
6870
|
|
|
$control = $this->{$key}; |
6871
|
|
|
if ($control instanceof TTextBox) |
6872
|
|
|
$control->Text = $arObj->{$key}; |
6873
|
|
|
elseif ($control instanceof TCheckBox) |
6874
|
|
|
$control->Checked = (boolean) $arObj->{$key}; |
6875
|
|
|
elseif ($control instanceof TDatePicker) |
6876
|
|
|
$control->Date = $arObj->{$key}; |
6877
|
|
|
} |
6878
|
|
|
else |
6879
|
|
|
{ |
6880
|
|
|
foreach ($objAttrs["RELATIONS"] as $relKey => $relValues) |
6881
|
|
|
{ |
6882
|
|
|
$relControl = $this->{$relKey}; |
6883
|
|
|
switch ($relValues[0]) |
6884
|
|
|
{ |
6885
|
|
|
case TActiveRecord::BELONGS_TO: |
6886
|
|
|
case TActiveRecord::HAS_ONE: |
6887
|
|
|
$relControl->Text = $arObj->{$relKey}; |
6888
|
|
|
break; |
6889
|
|
|
case TActiveRecord::HAS_MANY: |
6890
|
|
|
if ($relControl instanceof TListControl) |
6891
|
|
|
{ |
6892
|
|
|
$relControl->DataSource = $arObj->{$relKey}; |
|
|
|
|
6893
|
|
|
$relControl->dataBind(); |
6894
|
|
|
} |
6895
|
|
|
break; |
6896
|
|
|
} |
6897
|
|
|
} |
6898
|
|
|
break; |
6899
|
|
|
} |
6900
|
|
|
} |
6901
|
|
|
catch (Exception $ex) |
6902
|
|
|
{ |
6903
|
|
|
if ($throwExceptions) |
6904
|
|
|
throw $ex; |
6905
|
|
|
} |
6906
|
|
|
} |
6907
|
|
|
} |
6908
|
|
|
public function tryToUpdateAR($arObj, $throwExceptions = false) |
6909
|
|
|
{ |
6910
|
|
|
$objAttrs = get_class_vars(get_class($arObj)); |
6911
|
|
|
foreach (array_keys($objAttrs) as $key) |
6912
|
|
|
{ |
6913
|
|
|
try |
6914
|
|
|
{ |
6915
|
|
|
if ($key == "RELATIONS") |
6916
|
|
|
break; |
6917
|
|
|
$control = $this->{$key}; |
6918
|
|
|
if ($control instanceof TTextBox) |
6919
|
|
|
$arObj->{$key} = $control->Text; |
6920
|
|
|
elseif ($control instanceof TCheckBox) |
6921
|
|
|
$arObj->{$key} = $control->Checked; |
6922
|
|
|
elseif ($control instanceof TDatePicker) |
6923
|
|
|
$arObj->{$key} = $control->Date; |
6924
|
|
|
} |
6925
|
|
|
catch (Exception $ex) |
|
|
|
|
6926
|
|
|
{ |
6927
|
|
|
if ($throwExceptions) |
6928
|
|
|
throw $ex; |
6929
|
|
|
} |
6930
|
|
|
} |
6931
|
|
|
} |
6932
|
|
|
} |
6933
|
|
|
class TForm extends TControl |
6934
|
|
|
{ |
6935
|
|
|
public function onInit($param) |
6936
|
|
|
{ |
6937
|
|
|
parent::onInit($param); |
6938
|
|
|
$this->getPage()->setForm($this); |
6939
|
|
|
} |
6940
|
|
|
protected function addAttributesToRender($writer) |
6941
|
|
|
{ |
6942
|
|
|
$writer->addAttribute('id',$this->getClientID()); |
6943
|
|
|
$writer->addAttribute('method',$this->getMethod()); |
6944
|
|
|
$uri=$this->getRequest()->getRequestURI(); |
6945
|
|
|
$writer->addAttribute('action',str_replace('&','&',str_replace('&','&',$uri))); |
6946
|
|
|
if(($enctype=$this->getEnctype())!=='') |
6947
|
|
|
$writer->addAttribute('enctype',$enctype); |
6948
|
|
|
$attributes=$this->getAttributes(); |
6949
|
|
|
$attributes->remove('action'); |
6950
|
|
|
$writer->addAttributes($attributes); |
6951
|
|
|
if(($butt=$this->getDefaultButton())!=='') |
6952
|
|
|
{ |
6953
|
|
|
if(($button=$this->findControl($butt))!==null) |
6954
|
|
|
$this->getPage()->getClientScript()->registerDefaultButton($this, $button); |
6955
|
|
|
else |
6956
|
|
|
throw new TInvalidDataValueException('form_defaultbutton_invalid',$butt); |
6957
|
|
|
} |
6958
|
|
|
} |
6959
|
|
|
public function render($writer) |
6960
|
|
|
{ |
6961
|
|
|
$page=$this->getPage(); |
6962
|
|
|
$this->addAttributesToRender($writer); |
6963
|
|
|
$writer->renderBeginTag('form'); |
6964
|
|
|
$cs=$page->getClientScript(); |
6965
|
|
|
if($page->getClientSupportsJavaScript()) |
6966
|
|
|
{ |
6967
|
|
|
$cs->renderHiddenFieldsBegin($writer); |
6968
|
|
|
$cs->renderScriptFilesBegin($writer); |
6969
|
|
|
$cs->renderBeginScripts($writer); |
6970
|
|
|
$page->beginFormRender($writer); |
6971
|
|
|
$this->renderChildren($writer); |
6972
|
|
|
$cs->renderHiddenFieldsEnd($writer); |
6973
|
|
|
$page->endFormRender($writer); |
6974
|
|
|
$cs->renderScriptFilesEnd($writer); |
6975
|
|
|
$cs->renderEndScripts($writer); |
6976
|
|
|
} |
6977
|
|
|
else |
6978
|
|
|
{ |
6979
|
|
|
$cs->renderHiddenFieldsBegin($writer); |
6980
|
|
|
$page->beginFormRender($writer); |
6981
|
|
|
$this->renderChildren($writer); |
6982
|
|
|
$page->endFormRender($writer); |
6983
|
|
|
$cs->renderHiddenFieldsEnd($writer); |
6984
|
|
|
} |
6985
|
|
|
$writer->renderEndTag(); |
6986
|
|
|
} |
6987
|
|
|
public function getDefaultButton() |
6988
|
|
|
{ |
6989
|
|
|
return $this->getViewState('DefaultButton',''); |
6990
|
|
|
} |
6991
|
|
|
public function setDefaultButton($value) |
6992
|
|
|
{ |
6993
|
|
|
$this->setViewState('DefaultButton',$value,''); |
6994
|
|
|
} |
6995
|
|
|
public function getMethod() |
6996
|
|
|
{ |
6997
|
|
|
return $this->getViewState('Method','post'); |
6998
|
|
|
} |
6999
|
|
|
public function setMethod($value) |
7000
|
|
|
{ |
7001
|
|
|
$this->setViewState('Method',TPropertyValue::ensureEnum($value,'post','get'),'post'); |
7002
|
|
|
} |
7003
|
|
|
public function getEnctype() |
7004
|
|
|
{ |
7005
|
|
|
return $this->getViewState('Enctype',''); |
7006
|
|
|
} |
7007
|
|
|
public function setEnctype($value) |
7008
|
|
|
{ |
7009
|
|
|
$this->setViewState('Enctype',$value,''); |
7010
|
|
|
} |
7011
|
|
|
public function getName() |
7012
|
|
|
{ |
7013
|
|
|
return $this->getUniqueID(); |
7014
|
|
|
} |
7015
|
|
|
} |
7016
|
|
|
class TClientScriptManager extends TApplicationComponent |
7017
|
|
|
{ |
7018
|
|
|
const SCRIPT_PATH='Web/Javascripts/source'; |
7019
|
|
|
const PACKAGES_FILE='Web/Javascripts/packages.php'; |
7020
|
|
|
const CSS_PACKAGES_FILE='Web/Javascripts/css-packages.php'; |
7021
|
|
|
private $_page; |
7022
|
|
|
private $_hiddenFields=array(); |
7023
|
|
|
private $_beginScripts=array(); |
7024
|
|
|
private $_endScripts=array(); |
7025
|
|
|
private $_scriptFiles=array(); |
7026
|
|
|
private $_headScriptFiles=array(); |
7027
|
|
|
private $_headScripts=array(); |
7028
|
|
|
private $_styleSheetFiles=array(); |
7029
|
|
|
private $_styleSheets=array(); |
7030
|
|
|
private $_registeredPradoScripts=array(); |
7031
|
|
|
private static $_pradoScripts; |
7032
|
|
|
private static $_pradoPackages; |
7033
|
|
|
private $_registeredPradoStyles=array(); |
7034
|
|
|
private static $_pradoStyles; |
7035
|
|
|
private static $_pradoStylePackages; |
7036
|
|
|
private $_renderedHiddenFields; |
7037
|
|
|
private $_renderedScriptFiles=array(); |
7038
|
|
|
private $_expandedPradoScripts; |
7039
|
|
|
private $_expandedPradoStyles; |
7040
|
|
|
public function __construct(TPage $owner) |
7041
|
|
|
{ |
7042
|
|
|
$this->_page=$owner; |
7043
|
|
|
} |
7044
|
|
|
public function getRequiresHead() |
7045
|
|
|
{ |
7046
|
|
|
return count($this->_styleSheetFiles) || count($this->_styleSheets) |
7047
|
|
|
|| count($this->_headScriptFiles) || count($this->_headScripts); |
7048
|
|
|
} |
7049
|
|
|
public static function getPradoPackages() |
7050
|
|
|
{ |
7051
|
|
|
return self::$_pradoPackages; |
7052
|
|
|
} |
7053
|
|
|
public static function getPradoScripts() |
7054
|
|
|
{ |
7055
|
|
|
return self::$_pradoScripts; |
7056
|
|
|
} |
7057
|
|
|
public function registerPradoScript($name) |
7058
|
|
|
{ |
7059
|
|
|
$this->registerPradoScriptInternal($name); |
7060
|
|
|
$params=func_get_args(); |
7061
|
|
|
$this->_page->registerCachingAction('Page.ClientScript','registerPradoScript',$params); |
7062
|
|
|
} |
7063
|
|
|
protected function registerPradoScriptInternal($name) |
7064
|
|
|
{ |
7065
|
|
|
if(!isset($this->_registeredPradoScripts[$name])) |
7066
|
|
|
{ |
7067
|
|
|
if(self::$_pradoScripts === null) |
7068
|
|
|
{ |
7069
|
|
|
$packageFile = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::PACKAGES_FILE; |
7070
|
|
|
list($packages,$deps)= include($packageFile); |
7071
|
|
|
self::$_pradoScripts = $deps; |
7072
|
|
|
self::$_pradoPackages = $packages; |
7073
|
|
|
} |
7074
|
|
|
if (isset(self::$_pradoScripts[$name])) |
7075
|
|
|
$this->_registeredPradoScripts[$name]=true; |
7076
|
|
|
else |
7077
|
|
|
throw new TInvalidOperationException('csmanager_pradoscript_invalid',$name); |
7078
|
|
|
if(($packages=array_keys($this->_registeredPradoScripts))!==array()) |
7079
|
|
|
{ |
7080
|
|
|
$base = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::SCRIPT_PATH; |
7081
|
|
|
list($path,$baseUrl)=$this->getPackagePathUrl($base); |
7082
|
|
|
$packagesUrl=array(); |
7083
|
|
|
$isDebug=$this->getApplication()->getMode()===TApplicationMode::Debug; |
7084
|
|
|
foreach ($packages as $p) |
7085
|
|
|
{ |
7086
|
|
|
foreach (self::$_pradoScripts[$p] as $dep) |
7087
|
|
|
{ |
7088
|
|
|
foreach (self::$_pradoPackages[$dep] as $script) |
7089
|
|
|
if (!isset($this->_expandedPradoScripts[$script])) |
7090
|
|
|
{ |
7091
|
|
|
$this->_expandedPradoScripts[$script] = true; |
7092
|
|
|
if($isDebug) |
7093
|
|
|
{ |
7094
|
|
|
if (!in_array($url=$baseUrl.'/'.$script,$packagesUrl)) |
7095
|
|
|
$packagesUrl[]=$url; |
7096
|
|
|
} else { |
7097
|
|
|
if (!in_array($url=$baseUrl.'/min/'.$script,$packagesUrl)) |
7098
|
|
|
{ |
7099
|
|
|
if(!is_file($filePath=$path.'/min/'.$script)) |
7100
|
|
|
{ |
7101
|
|
|
$dirPath=dirname($filePath); |
7102
|
|
|
if(!is_dir($dirPath)) |
7103
|
|
|
mkdir($dirPath, PRADO_CHMOD, true); |
7104
|
|
|
file_put_contents($filePath, TJavaScript::JSMin(file_get_contents($base.'/'.$script))); |
7105
|
|
|
chmod($filePath, PRADO_CHMOD); |
7106
|
|
|
} |
7107
|
|
|
$packagesUrl[]=$url; |
7108
|
|
|
} |
7109
|
|
|
} |
7110
|
|
|
} |
7111
|
|
|
} |
7112
|
|
|
} |
7113
|
|
|
foreach($packagesUrl as $url) |
7114
|
|
|
$this->registerScriptFile($url,$url); |
7115
|
|
|
} |
7116
|
|
|
} |
7117
|
|
|
} |
7118
|
|
|
public function getPradoScriptAssetUrl() |
7119
|
|
|
{ |
7120
|
|
|
$base = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::SCRIPT_PATH; |
7121
|
|
|
$assets = Prado::getApplication()->getAssetManager(); |
7122
|
|
|
return $assets->getPublishedUrl($base); |
7123
|
|
|
} |
7124
|
|
|
public function getScriptUrls() |
7125
|
|
|
{ |
7126
|
|
|
$scripts = array_values($this->_headScriptFiles); |
7127
|
|
|
$scripts = array_merge($scripts, array_values($this->_scriptFiles)); |
7128
|
|
|
$scripts = array_unique($scripts); |
7129
|
|
|
return $scripts; |
7130
|
|
|
} |
7131
|
|
|
protected function getPackagePathUrl($base) |
7132
|
|
|
{ |
7133
|
|
|
$assets = Prado::getApplication()->getAssetManager(); |
7134
|
|
|
if(strpos($base, $assets->getBaseUrl())===false) |
7135
|
|
|
{ |
7136
|
|
|
if(($dir = Prado::getPathOfNameSpace($base)) !== null) { |
7137
|
|
|
$base = $dir; |
7138
|
|
|
} |
7139
|
|
|
return array($assets->getPublishedPath($base), $assets->publishFilePath($base)); |
7140
|
|
|
} |
7141
|
|
|
else |
7142
|
|
|
{ |
7143
|
|
|
return array($assets->getBasePath().str_replace($assets->getBaseUrl(),'',$base), $base); |
7144
|
|
|
} |
7145
|
|
|
} |
7146
|
|
|
public function getCallbackReference(ICallbackEventHandler $callbackHandler, $options=null) |
7147
|
|
|
{ |
7148
|
|
|
$options = !is_array($options) ? array() : $options; |
7149
|
|
|
$class = new ReflectionClass($callbackHandler); |
|
|
|
|
7150
|
|
|
$clientSide = $callbackHandler->getActiveControl()->getClientSide(); |
7151
|
|
|
$options = array_merge($options, $clientSide->getOptions()->toArray()); |
7152
|
|
|
$optionString = TJavaScript::encode($options); |
7153
|
|
|
$this->registerPradoScriptInternal('ajax'); |
7154
|
|
|
$id = $callbackHandler->getUniqueID(); |
7155
|
|
|
return "new Prado.CallbackRequest('{$id}',{$optionString})"; |
7156
|
|
|
} |
7157
|
|
|
public function registerCallbackControl($class, $options) |
7158
|
|
|
{ |
7159
|
|
|
$optionString=TJavaScript::encode($options); |
7160
|
|
|
$code="new {$class}({$optionString});"; |
7161
|
|
|
$this->_endScripts[sprintf('%08X', crc32($code))]=$code; |
7162
|
|
|
$this->registerPradoScriptInternal('ajax'); |
7163
|
|
|
$params=func_get_args(); |
7164
|
|
|
$this->_page->registerCachingAction('Page.ClientScript','registerCallbackControl',$params); |
7165
|
|
|
} |
7166
|
|
|
public function registerPostBackControl($class,$options) |
7167
|
|
|
{ |
7168
|
|
|
if($class === null) { |
7169
|
|
|
return; |
7170
|
|
|
} |
7171
|
|
|
if(!isset($options['FormID']) && ($form=$this->_page->getForm())!==null) |
7172
|
|
|
$options['FormID']=$form->getClientID(); |
7173
|
|
|
$optionString=TJavaScript::encode($options); |
7174
|
|
|
$code="new {$class}({$optionString});"; |
7175
|
|
|
$this->_endScripts[sprintf('%08X', crc32($code))]=$code; |
7176
|
|
|
$this->registerPradoScriptInternal('prado'); |
7177
|
|
|
$params=func_get_args(); |
7178
|
|
|
$this->_page->registerCachingAction('Page.ClientScript','registerPostBackControl',$params); |
7179
|
|
|
} |
7180
|
|
|
public function registerDefaultButton($panel, $button) |
7181
|
|
|
{ |
7182
|
|
|
$panelID=is_string($panel)?$panel:$panel->getUniqueID(); |
7183
|
|
|
if(is_string($button)) |
7184
|
|
|
$buttonID=$button; |
7185
|
|
|
else |
7186
|
|
|
{ |
7187
|
|
|
$button->setIsDefaultButton(true); |
7188
|
|
|
$buttonID=$button->getUniqueID(); |
7189
|
|
|
} |
7190
|
|
|
$options = TJavaScript::encode($this->getDefaultButtonOptions($panelID, $buttonID)); |
7191
|
|
|
$code = "new Prado.WebUI.DefaultButton($options);"; |
7192
|
|
|
$this->_endScripts['prado:'.$panelID]=$code; |
7193
|
|
|
$this->registerPradoScriptInternal('prado'); |
7194
|
|
|
$params=array($panelID,$buttonID); |
7195
|
|
|
$this->_page->registerCachingAction('Page.ClientScript','registerDefaultButton',$params); |
7196
|
|
|
} |
7197
|
|
|
protected function getDefaultButtonOptions($panelID, $buttonID) |
7198
|
|
|
{ |
7199
|
|
|
$options['ID'] = TControl::convertUniqueIdToClientId($panelID); |
|
|
|
|
7200
|
|
|
$options['Panel'] = TControl::convertUniqueIdToClientId($panelID); |
7201
|
|
|
$options['Target'] = TControl::convertUniqueIdToClientId($buttonID); |
7202
|
|
|
$options['EventTarget'] = $buttonID; |
7203
|
|
|
$options['Event'] = 'click'; |
7204
|
|
|
return $options; |
7205
|
|
|
} |
7206
|
|
|
public function registerFocusControl($target) |
7207
|
|
|
{ |
7208
|
|
|
$this->registerPradoScriptInternal('jquery'); |
7209
|
|
|
if($target instanceof TControl) |
7210
|
|
|
$target=$target->getClientID(); |
7211
|
|
|
$this->_endScripts['prado:focus'] = 'jQuery(\'#'.$target.'\').focus();'; |
7212
|
|
|
$params=func_get_args(); |
7213
|
|
|
$this->_page->registerCachingAction('Page.ClientScript','registerFocusControl',$params); |
7214
|
|
|
} |
7215
|
|
|
public function registerPradoStyle($name) |
7216
|
|
|
{ |
7217
|
|
|
$this->registerPradoStyleInternal($name); |
7218
|
|
|
$params=func_get_args(); |
7219
|
|
|
$this->_page->registerCachingAction('Page.ClientScript','registerPradoStyle',$params); |
7220
|
|
|
} |
7221
|
|
|
protected function registerPradoStyleInternal($name) |
7222
|
|
|
{ |
7223
|
|
|
if(!isset($this->_registeredPradoStyles[$name])) |
7224
|
|
|
{ |
7225
|
|
|
$base = $this->getPradoScriptAssetUrl(); |
7226
|
|
|
if(self::$_pradoStyles === null) |
7227
|
|
|
{ |
7228
|
|
|
$packageFile = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::CSS_PACKAGES_FILE; |
7229
|
|
|
list($packages,$deps)= include($packageFile); |
7230
|
|
|
self::$_pradoStyles = $deps; |
7231
|
|
|
self::$_pradoStylePackages = $packages; |
7232
|
|
|
} |
7233
|
|
|
if (isset(self::$_pradoStyles[$name])) |
7234
|
|
|
$this->_registeredPradoStyles[$name]=true; |
7235
|
|
|
else |
7236
|
|
|
throw new TInvalidOperationException('csmanager_pradostyle_invalid',$name); |
7237
|
|
|
if(($packages=array_keys($this->_registeredPradoStyles))!==array()) |
7238
|
|
|
{ |
7239
|
|
|
$base = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::SCRIPT_PATH; |
7240
|
|
|
list($path,$baseUrl)=$this->getPackagePathUrl($base); |
|
|
|
|
7241
|
|
|
$packagesUrl=array(); |
7242
|
|
|
$isDebug=$this->getApplication()->getMode()===TApplicationMode::Debug; |
|
|
|
|
7243
|
|
|
foreach ($packages as $p) |
7244
|
|
|
{ |
7245
|
|
|
foreach (self::$_pradoStyles[$p] as $dep) |
7246
|
|
|
{ |
7247
|
|
|
foreach (self::$_pradoStylePackages[$dep] as $style) |
7248
|
|
|
if (!isset($this->_expandedPradoStyles[$style])) |
7249
|
|
|
{ |
7250
|
|
|
$this->_expandedPradoStyles[$style] = true; |
7251
|
|
|
if (!in_array($url=$baseUrl.'/'.$style,$packagesUrl)) |
7252
|
|
|
$packagesUrl[]=$url; |
7253
|
|
|
} |
7254
|
|
|
} |
7255
|
|
|
} |
7256
|
|
|
foreach($packagesUrl as $url) |
7257
|
|
|
$this->registerStyleSheetFile($url,$url); |
7258
|
|
|
} |
7259
|
|
|
} |
7260
|
|
|
} |
7261
|
|
|
public function registerStyleSheetFile($key,$url,$media='') |
7262
|
|
|
{ |
7263
|
|
|
if($media==='') |
7264
|
|
|
$this->_styleSheetFiles[$key]=$url; |
7265
|
|
|
else |
7266
|
|
|
$this->_styleSheetFiles[$key]=array($url,$media); |
7267
|
|
|
$params=func_get_args(); |
7268
|
|
|
$this->_page->registerCachingAction('Page.ClientScript','registerStyleSheetFile',$params); |
7269
|
|
|
} |
7270
|
|
|
public function registerStyleSheet($key,$css,$media='') |
7271
|
|
|
{ |
7272
|
|
|
$this->_styleSheets[$key]=$css; |
7273
|
|
|
$params=func_get_args(); |
7274
|
|
|
$this->_page->registerCachingAction('Page.ClientScript','registerStyleSheet',$params); |
7275
|
|
|
} |
7276
|
|
|
public function getStyleSheetUrls() |
7277
|
|
|
{ |
7278
|
|
|
$stylesheets = array_values( |
7279
|
|
|
array_map(function($e) { |
7280
|
|
|
return is_array($e) ? $e[0] : $e; |
7281
|
|
|
}, $this->_styleSheetFiles) |
7282
|
|
|
); |
7283
|
|
|
foreach(Prado::getApplication()->getAssetManager()->getPublished() as $path=>$url) |
7284
|
|
|
if (substr($url,strlen($url)-4)=='.css') |
7285
|
|
|
$stylesheets[] = $url; |
7286
|
|
|
$stylesheets = array_unique($stylesheets); |
7287
|
|
|
return $stylesheets; |
7288
|
|
|
} |
7289
|
|
|
public function getStyleSheetCodes() |
7290
|
|
|
{ |
7291
|
|
|
return array_unique(array_values($this->_styleSheets)); |
7292
|
|
|
} |
7293
|
|
|
public function registerHeadScriptFile($key,$url) |
7294
|
|
|
{ |
7295
|
|
|
$this->checkIfNotInRender(); |
7296
|
|
|
$this->_headScriptFiles[$key]=$url; |
7297
|
|
|
$params=func_get_args(); |
7298
|
|
|
$this->_page->registerCachingAction('Page.ClientScript','registerHeadScriptFile',$params); |
7299
|
|
|
} |
7300
|
|
|
public function registerHeadScript($key,$script) |
7301
|
|
|
{ |
7302
|
|
|
$this->checkIfNotInRender(); |
7303
|
|
|
$this->_headScripts[$key]=$script; |
7304
|
|
|
$params=func_get_args(); |
7305
|
|
|
$this->_page->registerCachingAction('Page.ClientScript','registerHeadScript',$params); |
7306
|
|
|
} |
7307
|
|
|
public function registerScriptFile($key, $url) |
7308
|
|
|
{ |
7309
|
|
|
$this->_scriptFiles[$key]=$url; |
7310
|
|
|
$params=func_get_args(); |
7311
|
|
|
$this->_page->registerCachingAction('Page.ClientScript','registerScriptFile',$params); |
7312
|
|
|
} |
7313
|
|
|
public function registerBeginScript($key,$script) |
7314
|
|
|
{ |
7315
|
|
|
$this->checkIfNotInRender(); |
7316
|
|
|
$this->_beginScripts[$key]=$script; |
7317
|
|
|
$params=func_get_args(); |
7318
|
|
|
$this->_page->registerCachingAction('Page.ClientScript','registerBeginScript',$params); |
7319
|
|
|
} |
7320
|
|
|
public function registerEndScript($key,$script) |
7321
|
|
|
{ |
7322
|
|
|
$this->_endScripts[$key]=$script; |
7323
|
|
|
$params=func_get_args(); |
7324
|
|
|
$this->_page->registerCachingAction('Page.ClientScript','registerEndScript',$params); |
7325
|
|
|
} |
7326
|
|
|
public function registerHiddenField($name,$value) |
7327
|
|
|
{ |
7328
|
|
|
$this->_hiddenFields[$name]=$value; |
7329
|
|
|
$params=func_get_args(); |
7330
|
|
|
$this->_page->registerCachingAction('Page.ClientScript','registerHiddenField',$params); |
7331
|
|
|
} |
7332
|
|
|
public function isStyleSheetFileRegistered($key) |
7333
|
|
|
{ |
7334
|
|
|
return isset($this->_styleSheetFiles[$key]); |
7335
|
|
|
} |
7336
|
|
|
public function isStyleSheetRegistered($key) |
7337
|
|
|
{ |
7338
|
|
|
return isset($this->_styleSheets[$key]); |
7339
|
|
|
} |
7340
|
|
|
public function isHeadScriptFileRegistered($key) |
7341
|
|
|
{ |
7342
|
|
|
return isset($this->_headScriptFiles[$key]); |
7343
|
|
|
} |
7344
|
|
|
public function isHeadScriptRegistered($key) |
7345
|
|
|
{ |
7346
|
|
|
return isset($this->_headScripts[$key]); |
7347
|
|
|
} |
7348
|
|
|
public function isScriptFileRegistered($key) |
7349
|
|
|
{ |
7350
|
|
|
return isset($this->_scriptFiles[$key]); |
7351
|
|
|
} |
7352
|
|
|
public function isBeginScriptRegistered($key) |
7353
|
|
|
{ |
7354
|
|
|
return isset($this->_beginScripts[$key]); |
7355
|
|
|
} |
7356
|
|
|
public function isEndScriptRegistered($key) |
7357
|
|
|
{ |
7358
|
|
|
return isset($this->_endScripts[$key]); |
7359
|
|
|
} |
7360
|
|
|
public function hasEndScripts() |
7361
|
|
|
{ |
7362
|
|
|
return count($this->_endScripts) > 0; |
7363
|
|
|
} |
7364
|
|
|
public function hasBeginScripts() |
7365
|
|
|
{ |
7366
|
|
|
return count($this->_beginScripts) > 0; |
7367
|
|
|
} |
7368
|
|
|
public function isHiddenFieldRegistered($key) |
7369
|
|
|
{ |
7370
|
|
|
return isset($this->_hiddenFields[$key]); |
7371
|
|
|
} |
7372
|
|
|
public function renderStyleSheetFiles($writer) |
7373
|
|
|
{ |
7374
|
|
|
$str=''; |
7375
|
|
|
foreach($this->_styleSheetFiles as $url) |
7376
|
|
|
{ |
7377
|
|
|
if(is_array($url)) |
7378
|
|
|
$str.="<link rel=\"stylesheet\" type=\"text/css\" media=\"{$url[1]}\" href=\"".THttpUtility::htmlEncode($url[0])."\" />\n"; |
7379
|
|
|
else |
7380
|
|
|
$str.="<link rel=\"stylesheet\" type=\"text/css\" href=\"".THttpUtility::htmlEncode($url)."\" />\n"; |
7381
|
|
|
} |
7382
|
|
|
$writer->write($str); |
7383
|
|
|
} |
7384
|
|
|
public function renderStyleSheets($writer) |
7385
|
|
|
{ |
7386
|
|
|
if(count($this->_styleSheets)) |
7387
|
|
|
$writer->write("<style type=\"text/css\">\n/*<![CDATA[*/\n".implode("\n",$this->_styleSheets)."\n/*]]>*/\n</style>\n"); |
7388
|
|
|
} |
7389
|
|
|
public function renderHeadScriptFiles($writer) |
7390
|
|
|
{ |
7391
|
|
|
$this->renderScriptFiles($writer,$this->_headScriptFiles); |
7392
|
|
|
} |
7393
|
|
|
public function renderHeadScripts($writer) |
7394
|
|
|
{ |
7395
|
|
|
$writer->write(TJavaScript::renderScriptBlocks($this->_headScripts)); |
7396
|
|
|
} |
7397
|
|
|
public function renderScriptFilesBegin($writer) |
7398
|
|
|
{ |
7399
|
|
|
$this->renderAllPendingScriptFiles($writer); |
7400
|
|
|
} |
7401
|
|
|
public function renderScriptFilesEnd($writer) |
7402
|
|
|
{ |
7403
|
|
|
$this->renderAllPendingScriptFiles($writer); |
7404
|
|
|
} |
7405
|
|
|
public function markScriptFileAsRendered($url) |
7406
|
|
|
{ |
7407
|
|
|
$this->_renderedScriptFiles[$url] = $url; |
7408
|
|
|
$params=func_get_args(); |
7409
|
|
|
$this->_page->registerCachingAction('Page.ClientScript','markScriptFileAsRendered',$params); |
7410
|
|
|
} |
7411
|
|
|
protected function renderScriptFiles($writer, Array $scripts) |
7412
|
|
|
{ |
7413
|
|
|
foreach($scripts as $script) |
7414
|
|
|
{ |
7415
|
|
|
$writer->write(TJavaScript::renderScriptFile($script)); |
7416
|
|
|
$this->markScriptFileAsRendered($script); |
7417
|
|
|
} |
7418
|
|
|
} |
7419
|
|
|
protected function getRenderedScriptFiles() |
7420
|
|
|
{ |
7421
|
|
|
return $this->_renderedScriptFiles; |
7422
|
|
|
} |
7423
|
|
|
public function renderAllPendingScriptFiles($writer) |
7424
|
|
|
{ |
7425
|
|
|
if(!empty($this->_scriptFiles)) |
7426
|
|
|
{ |
7427
|
|
|
$addedScripts = array_diff($this->_scriptFiles,$this->getRenderedScriptFiles()); |
7428
|
|
|
$this->renderScriptFiles($writer,$addedScripts); |
7429
|
|
|
} |
7430
|
|
|
} |
7431
|
|
|
public function renderBeginScripts($writer) |
7432
|
|
|
{ |
7433
|
|
|
$writer->write(TJavaScript::renderScriptBlocks($this->_beginScripts)); |
7434
|
|
|
} |
7435
|
|
|
public function renderEndScripts($writer) |
7436
|
|
|
{ |
7437
|
|
|
$writer->write(TJavaScript::renderScriptBlocks($this->_endScripts)); |
7438
|
|
|
} |
7439
|
|
|
public function renderBeginScriptsCallback($writer) |
7440
|
|
|
{ |
7441
|
|
|
$writer->write(TJavaScript::renderScriptBlocksCallback($this->_beginScripts)); |
7442
|
|
|
} |
7443
|
|
|
public function renderEndScriptsCallback($writer) |
7444
|
|
|
{ |
7445
|
|
|
$writer->write(TJavaScript::renderScriptBlocksCallback($this->_endScripts)); |
7446
|
|
|
} |
7447
|
|
|
public function renderHiddenFieldsBegin($writer) |
7448
|
|
|
{ |
7449
|
|
|
$this->renderHiddenFieldsInt($writer,true); |
7450
|
|
|
} |
7451
|
|
|
public function renderHiddenFieldsEnd($writer) |
7452
|
|
|
{ |
7453
|
|
|
$this->renderHiddenFieldsInt($writer,false); |
7454
|
|
|
} |
7455
|
|
|
public function flushScriptFiles($writer, $control=null) |
7456
|
|
|
{ |
7457
|
|
|
if(!$this->_page->getIsCallback()) |
7458
|
|
|
{ |
7459
|
|
|
$this->_page->ensureRenderInForm($control); |
7460
|
|
|
$this->renderAllPendingScriptFiles($writer); |
7461
|
|
|
} |
7462
|
|
|
} |
7463
|
|
|
protected function renderHiddenFieldsInt($writer, $initial) |
7464
|
|
|
{ |
7465
|
|
|
if ($initial) $this->_renderedHiddenFields = array(); |
7466
|
|
|
$str=''; |
7467
|
|
|
foreach($this->_hiddenFields as $name=>$value) |
7468
|
|
|
{ |
7469
|
|
|
if (in_array($name,$this->_renderedHiddenFields)) continue; |
7470
|
|
|
$id=strtr($name,':','_'); |
7471
|
|
|
if(is_array($value)) |
7472
|
|
|
{ |
7473
|
|
|
foreach($value as $v) |
7474
|
|
|
$str.='<input type="hidden" name="'.$name.'[]" id="'.$id.'" value="'.THttpUtility::htmlEncode($value)."\" />\n"; |
7475
|
|
|
} |
7476
|
|
|
else |
7477
|
|
|
{ |
7478
|
|
|
$str.='<input type="hidden" name="'.$name.'" id="'.$id.'" value="'.THttpUtility::htmlEncode($value)."\" />\n"; |
7479
|
|
|
} |
7480
|
|
|
$this->_renderedHiddenFields[] = $name; |
7481
|
|
|
} |
7482
|
|
|
if($str!=='') |
7483
|
|
|
$writer->write("<div style=\"visibility:hidden;\">\n".$str."</div>\n"); |
7484
|
|
|
} |
7485
|
|
|
public function getHiddenFields() |
7486
|
|
|
{ |
7487
|
|
|
return $this->_hiddenFields; |
7488
|
|
|
} |
7489
|
|
|
protected function checkIfNotInRender() |
7490
|
|
|
{ |
7491
|
|
|
if ($form = $this->_page->InFormRender) |
|
|
|
|
7492
|
|
|
throw new Exception('Operation invalid when page is already rendering'); |
7493
|
|
|
} |
7494
|
|
|
} |
7495
|
|
|
abstract class TClientSideOptions extends TComponent |
7496
|
|
|
{ |
7497
|
|
|
private $_options; |
7498
|
|
|
protected function setFunction($name, $code) |
7499
|
|
|
{ |
7500
|
|
|
if(!TJavaScript::isJsLiteral($code)) |
7501
|
|
|
$code = TJavaScript::quoteJsLiteral($this->ensureFunction($code)); |
7502
|
|
|
$this->setOption($name, $code); |
7503
|
|
|
} |
7504
|
|
|
protected function getOption($name) |
7505
|
|
|
{ |
7506
|
|
|
if ($this->_options) |
7507
|
|
|
return $this->_options->itemAt($name); |
7508
|
|
|
else |
7509
|
|
|
return null; |
7510
|
|
|
} |
7511
|
|
|
protected function setOption($name, $value) |
7512
|
|
|
{ |
7513
|
|
|
$this->getOptions()->add($name, $value); |
7514
|
|
|
} |
7515
|
|
|
public function getOptions() |
7516
|
|
|
{ |
7517
|
|
|
if (!$this->_options) |
7518
|
|
|
$this->_options = Prado::createComponent('System.Collections.TMap'); |
7519
|
|
|
return $this->_options; |
7520
|
|
|
} |
7521
|
|
|
protected function ensureFunction($javascript) |
7522
|
|
|
{ |
7523
|
|
|
return "function(sender, parameter){ {$javascript} }"; |
7524
|
|
|
} |
7525
|
|
|
} |
7526
|
|
|
class TPage extends TTemplateControl |
7527
|
|
|
{ |
7528
|
|
|
const FIELD_POSTBACK_TARGET='PRADO_POSTBACK_TARGET'; |
7529
|
|
|
const FIELD_POSTBACK_PARAMETER='PRADO_POSTBACK_PARAMETER'; |
7530
|
|
|
const FIELD_LASTFOCUS='PRADO_LASTFOCUS'; |
7531
|
|
|
const FIELD_PAGESTATE='PRADO_PAGESTATE'; |
7532
|
|
|
const FIELD_CALLBACK_TARGET='PRADO_CALLBACK_TARGET'; |
7533
|
|
|
const FIELD_CALLBACK_PARAMETER='PRADO_CALLBACK_PARAMETER'; |
7534
|
|
|
private static $_systemPostFields=array( |
7535
|
|
|
'PRADO_POSTBACK_TARGET'=>true, |
7536
|
|
|
'PRADO_POSTBACK_PARAMETER'=>true, |
7537
|
|
|
'PRADO_LASTFOCUS'=>true, |
7538
|
|
|
'PRADO_PAGESTATE'=>true, |
7539
|
|
|
'PRADO_CALLBACK_TARGET'=>true, |
7540
|
|
|
'PRADO_CALLBACK_PARAMETER'=>true |
7541
|
|
|
); |
7542
|
|
|
private $_form; |
7543
|
|
|
private $_head; |
7544
|
|
|
private $_validators=array(); |
7545
|
|
|
private $_validated=false; |
7546
|
|
|
private $_theme; |
7547
|
|
|
private $_title; |
7548
|
|
|
private $_styleSheet; |
7549
|
|
|
private $_clientScript; |
7550
|
|
|
protected $_postData; |
7551
|
|
|
protected $_restPostData; |
7552
|
|
|
protected $_controlsPostDataChanged=array(); |
|
|
|
|
7553
|
|
|
protected $_controlsRequiringPostData=array(); |
|
|
|
|
7554
|
|
|
protected $_controlsRegisteredForPostData=array(); |
|
|
|
|
7555
|
|
|
private $_postBackEventTarget; |
7556
|
|
|
private $_postBackEventParameter; |
7557
|
|
|
protected $_formRendered=false; |
7558
|
|
|
protected $_inFormRender=false; |
7559
|
|
|
private $_focus; |
7560
|
|
|
private $_pagePath=''; |
7561
|
|
|
private $_enableStateValidation=true; |
7562
|
|
|
private $_enableStateEncryption=false; |
7563
|
|
|
private $_enableStateCompression=true; |
7564
|
|
|
private $_statePersisterClass='System.Web.UI.TPageStatePersister'; |
7565
|
|
|
private $_statePersister; |
7566
|
|
|
private $_cachingStack; |
7567
|
|
|
private $_clientState=''; |
7568
|
|
|
protected $_isLoadingPostData=false; |
7569
|
|
|
private $_enableJavaScript=true; |
7570
|
|
|
private $_writer; |
7571
|
|
|
public function __construct() |
7572
|
|
|
{ |
7573
|
|
|
$this->setPage($this); |
7574
|
|
|
} |
7575
|
|
|
public function run($writer) |
7576
|
|
|
{ |
7577
|
|
|
$this->_writer = $writer; |
7578
|
|
|
$this->determinePostBackMode(); |
7579
|
|
|
if($this->getIsPostBack()) |
7580
|
|
|
{ |
7581
|
|
|
if($this->getIsCallback()) |
7582
|
|
|
$this->processCallbackRequest($writer); |
7583
|
|
|
else |
7584
|
|
|
$this->processPostBackRequest($writer); |
7585
|
|
|
} |
7586
|
|
|
else |
7587
|
|
|
$this->processNormalRequest($writer); |
7588
|
|
|
$this->_writer = null; |
7589
|
|
|
} |
7590
|
|
|
protected function processNormalRequest($writer) |
7591
|
|
|
{ |
7592
|
|
|
$this->onPreInit(null); |
7593
|
|
|
$this->initRecursive(); |
7594
|
|
|
$this->onInitComplete(null); |
7595
|
|
|
$this->onPreLoad(null); |
7596
|
|
|
$this->loadRecursive(); |
7597
|
|
|
$this->onLoadComplete(null); |
7598
|
|
|
$this->preRenderRecursive(); |
7599
|
|
|
$this->onPreRenderComplete(null); |
7600
|
|
|
$this->savePageState(); |
7601
|
|
|
$this->onSaveStateComplete(null); |
7602
|
|
|
$this->renderControl($writer); |
7603
|
|
|
$this->unloadRecursive(); |
7604
|
|
|
} |
7605
|
|
|
protected function processPostBackRequest($writer) |
7606
|
|
|
{ |
7607
|
|
|
$this->onPreInit(null); |
7608
|
|
|
$this->initRecursive(); |
7609
|
|
|
$this->onInitComplete(null); |
7610
|
|
|
$this->_restPostData=new TMap; |
7611
|
|
|
$this->loadPageState(); |
7612
|
|
|
$this->processPostData($this->_postData,true); |
7613
|
|
|
$this->onPreLoad(null); |
7614
|
|
|
$this->loadRecursive(); |
7615
|
|
|
$this->processPostData($this->_restPostData,false); |
7616
|
|
|
$this->raiseChangedEvents(); |
7617
|
|
|
$this->raisePostBackEvent(); |
7618
|
|
|
$this->onLoadComplete(null); |
7619
|
|
|
$this->preRenderRecursive(); |
7620
|
|
|
$this->onPreRenderComplete(null); |
7621
|
|
|
$this->savePageState(); |
7622
|
|
|
$this->onSaveStateComplete(null); |
7623
|
|
|
$this->renderControl($writer); |
7624
|
|
|
$this->unloadRecursive(); |
7625
|
|
|
} |
7626
|
|
|
protected static function decodeUTF8($data, $enc) |
7627
|
|
|
{ |
7628
|
|
|
if(is_array($data)) |
7629
|
|
|
{ |
7630
|
|
|
foreach($data as $k=>$v) |
7631
|
|
|
$data[$k]=self::decodeUTF8($v, $enc); |
7632
|
|
|
return $data; |
7633
|
|
|
} elseif(is_string($data)) { |
7634
|
|
|
return iconv('UTF-8',$enc.'//IGNORE',$data); |
7635
|
|
|
} else { |
7636
|
|
|
return $data; |
7637
|
|
|
} |
7638
|
|
|
} |
7639
|
|
|
protected function processCallbackRequest($writer) |
7640
|
|
|
{ |
7641
|
|
|
Prado::using('System.Web.UI.ActiveControls.TActivePageAdapter'); |
7642
|
|
|
Prado::using('System.Web.UI.JuiControls.TJuiControlOptions'); |
7643
|
|
|
$this->setAdapter(new TActivePageAdapter($this)); |
7644
|
|
|
$callbackEventParameter = $this->getRequest()->itemAt(TPage::FIELD_CALLBACK_PARAMETER); |
|
|
|
|
7645
|
|
|
if(strlen($callbackEventParameter) > 0) |
7646
|
|
|
$this->_postData[TPage::FIELD_CALLBACK_PARAMETER]=TJavaScript::jsonDecode((string)$callbackEventParameter); |
|
|
|
|
7647
|
|
|
if (($g=$this->getApplication()->getGlobalization(false))!==null && |
7648
|
|
|
strtoupper($enc=$g->getCharset())!='UTF-8') |
7649
|
|
|
foreach ($this->_postData as $k=>$v) |
7650
|
|
|
$this->_postData[$k]=self::decodeUTF8($v, $enc); |
7651
|
|
|
$this->onPreInit(null); |
7652
|
|
|
$this->initRecursive(); |
7653
|
|
|
$this->onInitComplete(null); |
7654
|
|
|
$this->_restPostData=new TMap; |
7655
|
|
|
$this->loadPageState(); |
7656
|
|
|
$this->processPostData($this->_postData,true); |
7657
|
|
|
$this->onPreLoad(null); |
7658
|
|
|
$this->loadRecursive(); |
7659
|
|
|
$this->processPostData($this->_restPostData,false); |
7660
|
|
|
$this->raiseChangedEvents(); |
7661
|
|
|
$this->getAdapter()->processCallbackEvent($writer); |
7662
|
|
|
$this->onLoadComplete(null); |
7663
|
|
|
$this->preRenderRecursive(); |
7664
|
|
|
$this->onPreRenderComplete(null); |
7665
|
|
|
$this->savePageState(); |
7666
|
|
|
$this->onSaveStateComplete(null); |
7667
|
|
|
$this->getAdapter()->renderCallbackResponse($writer); |
7668
|
|
|
$this->unloadRecursive(); |
7669
|
|
|
} |
7670
|
|
|
public function getCallbackClient() |
7671
|
|
|
{ |
7672
|
|
|
if($this->getAdapter() !== null) |
7673
|
|
|
return $this->getAdapter()->getCallbackClientHandler(); |
7674
|
|
|
else |
7675
|
|
|
return new TCallbackClientScript(); |
7676
|
|
|
} |
7677
|
|
|
public function setCallbackClient($client) |
7678
|
|
|
{ |
7679
|
|
|
$this->getAdapter()->setCallbackClientHandler($client); |
7680
|
|
|
} |
7681
|
|
|
public function getCallbackEventTarget() |
7682
|
|
|
{ |
7683
|
|
|
return $this->getAdapter()->getCallbackEventTarget(); |
7684
|
|
|
} |
7685
|
|
|
public function setCallbackEventTarget(TControl $control) |
7686
|
|
|
{ |
7687
|
|
|
$this->getAdapter()->setCallbackEventTarget($control); |
7688
|
|
|
} |
7689
|
|
|
public function getCallbackEventParameter() |
7690
|
|
|
{ |
7691
|
|
|
return $this->getAdapter()->getCallbackEventParameter(); |
7692
|
|
|
} |
7693
|
|
|
public function setCallbackEventParameter($value) |
7694
|
|
|
{ |
7695
|
|
|
$this->getAdapter()->setCallbackEventParameter($value); |
7696
|
|
|
} |
7697
|
|
|
public function getForm() |
7698
|
|
|
{ |
7699
|
|
|
return $this->_form; |
7700
|
|
|
} |
7701
|
|
|
public function setForm(TForm $form) |
7702
|
|
|
{ |
7703
|
|
|
if($this->_form===null) |
7704
|
|
|
$this->_form=$form; |
7705
|
|
|
else |
7706
|
|
|
throw new TInvalidOperationException('page_form_duplicated'); |
7707
|
|
|
} |
7708
|
|
|
public function getValidators($validationGroup=null) |
7709
|
|
|
{ |
7710
|
|
|
if(!$this->_validators) |
|
|
|
|
7711
|
|
|
$this->_validators=new TList; |
|
|
|
|
7712
|
|
|
if(empty($validationGroup) === true) |
7713
|
|
|
return $this->_validators; |
7714
|
|
|
else |
7715
|
|
|
{ |
7716
|
|
|
$list=new TList; |
7717
|
|
|
foreach($this->_validators as $validator) |
7718
|
|
|
if($validator->getValidationGroup()===$validationGroup) |
7719
|
|
|
$list->add($validator); |
7720
|
|
|
return $list; |
7721
|
|
|
} |
7722
|
|
|
} |
7723
|
|
|
public function validate($validationGroup=null) |
7724
|
|
|
{ |
7725
|
|
|
$this->_validated=true; |
7726
|
|
|
if($this->_validators && $this->_validators->getCount()) |
|
|
|
|
7727
|
|
|
{ |
7728
|
|
|
if($validationGroup===null) |
7729
|
|
|
{ |
7730
|
|
|
foreach($this->_validators as $validator) |
7731
|
|
|
$validator->validate(); |
7732
|
|
|
} |
7733
|
|
|
else |
7734
|
|
|
{ |
7735
|
|
|
foreach($this->_validators as $validator) |
7736
|
|
|
{ |
7737
|
|
|
if($validator->getValidationGroup()===$validationGroup) |
7738
|
|
|
$validator->validate(); |
7739
|
|
|
} |
7740
|
|
|
} |
7741
|
|
|
} |
7742
|
|
|
} |
7743
|
|
|
public function getIsValid() |
7744
|
|
|
{ |
7745
|
|
|
if($this->_validated) |
7746
|
|
|
{ |
7747
|
|
|
if($this->_validators && $this->_validators->getCount()) |
|
|
|
|
7748
|
|
|
{ |
7749
|
|
|
foreach($this->_validators as $validator) |
7750
|
|
|
if(!$validator->getIsValid()) |
7751
|
|
|
return false; |
7752
|
|
|
} |
7753
|
|
|
return true; |
7754
|
|
|
} |
7755
|
|
|
else |
7756
|
|
|
throw new TInvalidOperationException('page_isvalid_unknown'); |
7757
|
|
|
} |
7758
|
|
|
public function getTheme() |
7759
|
|
|
{ |
7760
|
|
|
if(is_string($this->_theme)) |
7761
|
|
|
$this->_theme=$this->getService()->getThemeManager()->getTheme($this->_theme); |
|
|
|
|
7762
|
|
|
return $this->_theme; |
7763
|
|
|
} |
7764
|
|
|
public function setTheme($value) |
7765
|
|
|
{ |
7766
|
|
|
$this->_theme=empty($value)?null:$value; |
7767
|
|
|
} |
7768
|
|
|
public function getStyleSheetTheme() |
7769
|
|
|
{ |
7770
|
|
|
if(is_string($this->_styleSheet)) |
7771
|
|
|
$this->_styleSheet=$this->getService()->getThemeManager()->getTheme($this->_styleSheet); |
|
|
|
|
7772
|
|
|
return $this->_styleSheet; |
7773
|
|
|
} |
7774
|
|
|
public function setStyleSheetTheme($value) |
7775
|
|
|
{ |
7776
|
|
|
$this->_styleSheet=empty($value)?null:$value; |
7777
|
|
|
} |
7778
|
|
|
public function applyControlSkin($control) |
7779
|
|
|
{ |
7780
|
|
|
if(($theme=$this->getTheme())!==null) |
7781
|
|
|
$theme->applySkin($control); |
7782
|
|
|
} |
7783
|
|
|
public function applyControlStyleSheet($control) |
7784
|
|
|
{ |
7785
|
|
|
if(($theme=$this->getStyleSheetTheme())!==null) |
7786
|
|
|
$theme->applySkin($control); |
7787
|
|
|
} |
7788
|
|
|
public function getClientScript() |
7789
|
|
|
{ |
7790
|
|
|
if(!$this->_clientScript) { |
7791
|
|
|
$className = $classPath = $this->getService()->getClientScriptManagerClass(); |
|
|
|
|
7792
|
|
|
Prado::using($className); |
7793
|
|
|
if(($pos=strrpos($className,'.'))!==false) |
7794
|
|
|
$className=substr($className,$pos+1); |
7795
|
|
|
if(!class_exists($className,false) || ($className!=='TClientScriptManager' && !is_subclass_of($className,'TClientScriptManager'))) |
7796
|
|
|
throw new THttpException(404,'page_csmanagerclass_invalid',$classPath); |
7797
|
|
|
$this->_clientScript=new $className($this); |
7798
|
|
|
} |
7799
|
|
|
return $this->_clientScript; |
7800
|
|
|
} |
7801
|
|
|
public function onPreInit($param) |
7802
|
|
|
{ |
7803
|
|
|
$this->raiseEvent('OnPreInit',$this,$param); |
7804
|
|
|
} |
7805
|
|
|
public function onInitComplete($param) |
7806
|
|
|
{ |
7807
|
|
|
$this->raiseEvent('OnInitComplete',$this,$param); |
7808
|
|
|
} |
7809
|
|
|
public function onPreLoad($param) |
7810
|
|
|
{ |
7811
|
|
|
$this->raiseEvent('OnPreLoad',$this,$param); |
7812
|
|
|
} |
7813
|
|
|
public function onLoadComplete($param) |
7814
|
|
|
{ |
7815
|
|
|
$this->raiseEvent('OnLoadComplete',$this,$param); |
7816
|
|
|
} |
7817
|
|
|
public function onPreRenderComplete($param) |
7818
|
|
|
{ |
7819
|
|
|
$this->raiseEvent('OnPreRenderComplete',$this,$param); |
7820
|
|
|
$cs=$this->getClientScript(); |
7821
|
|
|
$theme=$this->getTheme(); |
7822
|
|
|
if($theme instanceof ITheme) |
7823
|
|
|
{ |
7824
|
|
|
foreach($theme->getStyleSheetFiles() as $url) |
7825
|
|
|
$cs->registerStyleSheetFile($url,$url,$this->getCssMediaType($url)); |
7826
|
|
|
foreach($theme->getJavaScriptFiles() as $url) |
7827
|
|
|
$cs->registerHeadScriptFile($url,$url); |
7828
|
|
|
} |
7829
|
|
|
$styleSheet=$this->getStyleSheetTheme(); |
7830
|
|
|
if($styleSheet instanceof ITheme) |
7831
|
|
|
{ |
7832
|
|
|
foreach($styleSheet->getStyleSheetFiles() as $url) |
7833
|
|
|
$cs->registerStyleSheetFile($url,$url,$this->getCssMediaType($url)); |
7834
|
|
|
foreach($styleSheet->getJavaScriptFiles() as $url) |
7835
|
|
|
$cs->registerHeadScriptFile($url,$url); |
7836
|
|
|
} |
7837
|
|
|
if($cs->getRequiresHead() && $this->getHead()===null) |
7838
|
|
|
throw new TConfigurationException('page_head_required'); |
7839
|
|
|
} |
7840
|
|
|
private function getCssMediaType($url) |
7841
|
|
|
{ |
7842
|
|
|
$segs=explode('.',basename($url)); |
7843
|
|
|
if(isset($segs[2])) |
7844
|
|
|
return $segs[count($segs)-2]; |
7845
|
|
|
else |
7846
|
|
|
return ''; |
7847
|
|
|
} |
7848
|
|
|
public function onSaveStateComplete($param) |
7849
|
|
|
{ |
7850
|
|
|
$this->raiseEvent('OnSaveStateComplete',$this,$param); |
7851
|
|
|
} |
7852
|
|
|
private function determinePostBackMode() |
7853
|
|
|
{ |
7854
|
|
|
$postData=$this->getRequest(); |
7855
|
|
|
if($postData->contains(self::FIELD_PAGESTATE) || $postData->contains(self::FIELD_POSTBACK_TARGET)) |
7856
|
|
|
$this->_postData=$postData; |
7857
|
|
|
} |
7858
|
|
|
public function getIsPostBack() |
7859
|
|
|
{ |
7860
|
|
|
return $this->_postData!==null; |
7861
|
|
|
} |
7862
|
|
|
public function getIsCallback() |
7863
|
|
|
{ |
7864
|
|
|
return $this->getIsPostBack() && $this->getRequest()->contains(self::FIELD_CALLBACK_TARGET); |
7865
|
|
|
} |
7866
|
|
|
public function saveState() |
7867
|
|
|
{ |
7868
|
|
|
parent::saveState(); |
7869
|
|
|
$this->setViewState('ControlsRequiringPostBack',$this->_controlsRegisteredForPostData,array()); |
7870
|
|
|
} |
7871
|
|
|
public function loadState() |
7872
|
|
|
{ |
7873
|
|
|
parent::loadState(); |
7874
|
|
|
$this->_controlsRequiringPostData=$this->getViewState('ControlsRequiringPostBack',array()); |
|
|
|
|
7875
|
|
|
} |
7876
|
|
|
protected function loadPageState() |
7877
|
|
|
{ |
7878
|
|
|
$state=$this->getStatePersister()->load(); |
7879
|
|
|
$this->loadStateRecursive($state,$this->getEnableViewState()); |
7880
|
|
|
} |
7881
|
|
|
protected function savePageState() |
7882
|
|
|
{ |
7883
|
|
|
$state=&$this->saveStateRecursive($this->getEnableViewState()); |
7884
|
|
|
$this->getStatePersister()->save($state); |
7885
|
|
|
} |
7886
|
|
|
protected function isSystemPostField($field) |
7887
|
|
|
{ |
7888
|
|
|
return isset(self::$_systemPostFields[$field]); |
7889
|
|
|
} |
7890
|
|
|
public function registerRequiresPostData($control) |
7891
|
|
|
{ |
7892
|
|
|
$id=is_string($control)?$control:$control->getUniqueID(); |
7893
|
|
|
$this->_controlsRegisteredForPostData[$id]=true; |
7894
|
|
|
$params=func_get_args(); |
|
|
|
|
7895
|
|
|
foreach($this->getCachingStack() as $item) |
7896
|
|
|
$item->registerAction('Page','registerRequiresPostData',array($id)); |
7897
|
|
|
} |
7898
|
|
|
public function getPostBackEventTarget() |
7899
|
|
|
{ |
7900
|
|
|
if($this->_postBackEventTarget===null && $this->_postData!==null) |
7901
|
|
|
{ |
7902
|
|
|
$eventTarget=$this->_postData->itemAt(self::FIELD_POSTBACK_TARGET); |
|
|
|
|
7903
|
|
|
if(!empty($eventTarget)) |
7904
|
|
|
$this->_postBackEventTarget=$this->findControl($eventTarget); |
7905
|
|
|
} |
7906
|
|
|
return $this->_postBackEventTarget; |
7907
|
|
|
} |
7908
|
|
|
public function setPostBackEventTarget(TControl $control) |
7909
|
|
|
{ |
7910
|
|
|
$this->_postBackEventTarget=$control; |
7911
|
|
|
} |
7912
|
|
|
public function getPostBackEventParameter() |
7913
|
|
|
{ |
7914
|
|
|
if($this->_postBackEventParameter===null && $this->_postData!==null) |
7915
|
|
|
{ |
7916
|
|
|
if(($this->_postBackEventParameter=$this->_postData->itemAt(self::FIELD_POSTBACK_PARAMETER))===null) |
|
|
|
|
7917
|
|
|
$this->_postBackEventParameter=''; |
7918
|
|
|
} |
7919
|
|
|
return $this->_postBackEventParameter; |
7920
|
|
|
} |
7921
|
|
|
public function setPostBackEventParameter($value) |
7922
|
|
|
{ |
7923
|
|
|
$this->_postBackEventParameter=$value; |
7924
|
|
|
} |
7925
|
|
|
protected function processPostData($postData,$beforeLoad) |
7926
|
|
|
{ |
7927
|
|
|
$this->_isLoadingPostData=true; |
7928
|
|
|
if($beforeLoad) |
7929
|
|
|
$this->_restPostData=new TMap; |
7930
|
|
|
foreach($postData as $key=>$value) |
7931
|
|
|
{ |
7932
|
|
|
if($this->isSystemPostField($key)) |
7933
|
|
|
continue; |
7934
|
|
|
else if($control=$this->findControl($key)) |
7935
|
|
|
{ |
7936
|
|
|
if($control instanceof IPostBackDataHandler) |
7937
|
|
|
{ |
7938
|
|
|
if($control->loadPostData($key,$postData)) |
7939
|
|
|
$this->_controlsPostDataChanged[]=$control; |
7940
|
|
|
} |
7941
|
|
|
else if($control instanceof IPostBackEventHandler && |
7942
|
|
|
empty($this->_postData[self::FIELD_POSTBACK_TARGET])) |
7943
|
|
|
{ |
7944
|
|
|
$this->_postData->add(self::FIELD_POSTBACK_TARGET,$key); } |
7945
|
|
|
unset($this->_controlsRequiringPostData[$key]); |
7946
|
|
|
} |
7947
|
|
|
else if($beforeLoad) |
7948
|
|
|
$this->_restPostData->add($key,$value); |
7949
|
|
|
} |
7950
|
|
|
foreach($this->_controlsRequiringPostData as $key=>$value) |
7951
|
|
|
{ |
7952
|
|
|
if($control=$this->findControl($key)) |
7953
|
|
|
{ |
7954
|
|
|
if($control instanceof IPostBackDataHandler) |
7955
|
|
|
{ |
7956
|
|
|
if($control->loadPostData($key,$this->_postData)) |
7957
|
|
|
$this->_controlsPostDataChanged[]=$control; |
7958
|
|
|
} |
7959
|
|
|
else |
7960
|
|
|
throw new TInvalidDataValueException('page_postbackcontrol_invalid',$key); |
7961
|
|
|
unset($this->_controlsRequiringPostData[$key]); |
7962
|
|
|
} |
7963
|
|
|
} |
7964
|
|
|
$this->_isLoadingPostData=false; |
7965
|
|
|
} |
7966
|
|
|
public function getIsLoadingPostData() |
7967
|
|
|
{ |
7968
|
|
|
return $this->_isLoadingPostData; |
7969
|
|
|
} |
7970
|
|
|
protected function raiseChangedEvents() |
7971
|
|
|
{ |
7972
|
|
|
foreach($this->_controlsPostDataChanged as $control) |
7973
|
|
|
$control->raisePostDataChangedEvent(); |
7974
|
|
|
} |
7975
|
|
|
protected function raisePostBackEvent() |
7976
|
|
|
{ |
7977
|
|
|
if(($postBackHandler=$this->getPostBackEventTarget())===null) |
7978
|
|
|
$this->validate(); |
7979
|
|
|
else if($postBackHandler instanceof IPostBackEventHandler) |
7980
|
|
|
$postBackHandler->raisePostBackEvent($this->getPostBackEventParameter()); |
7981
|
|
|
} |
7982
|
|
|
public function getInFormRender() |
7983
|
|
|
{ |
7984
|
|
|
return $this->_inFormRender; |
7985
|
|
|
} |
7986
|
|
|
public function ensureRenderInForm($control) |
7987
|
|
|
{ |
7988
|
|
|
if(!$this->getIsCallback() && !$this->_inFormRender) |
7989
|
|
|
throw new TConfigurationException('page_control_outofform',get_class($control), $control ? $control->getUniqueID() : null); |
7990
|
|
|
} |
7991
|
|
|
public function beginFormRender($writer) |
7992
|
|
|
{ |
7993
|
|
|
if($this->_formRendered) |
7994
|
|
|
throw new TConfigurationException('page_form_duplicated'); |
7995
|
|
|
$this->_formRendered=true; |
7996
|
|
|
$this->getClientScript()->registerHiddenField(self::FIELD_PAGESTATE,$this->getClientState()); |
7997
|
|
|
$this->_inFormRender=true; |
7998
|
|
|
} |
7999
|
|
|
public function endFormRender($writer) |
8000
|
|
|
{ |
8001
|
|
|
if($this->_focus) |
8002
|
|
|
{ |
8003
|
|
|
if(($this->_focus instanceof TControl) && $this->_focus->getVisible(true)) |
8004
|
|
|
$focus=$this->_focus->getClientID(); |
8005
|
|
|
else |
8006
|
|
|
$focus=$this->_focus; |
8007
|
|
|
$this->getClientScript()->registerFocusControl($focus); |
8008
|
|
|
} |
8009
|
|
|
else if($this->_postData && ($lastFocus=$this->_postData->itemAt(self::FIELD_LASTFOCUS))!==null) |
|
|
|
|
8010
|
|
|
$this->getClientScript()->registerFocusControl($lastFocus); |
8011
|
|
|
$this->_inFormRender=false; |
8012
|
|
|
} |
8013
|
|
|
public function setFocus($value) |
8014
|
|
|
{ |
8015
|
|
|
$this->_focus=$value; |
8016
|
|
|
} |
8017
|
|
|
public function getClientSupportsJavaScript() |
8018
|
|
|
{ |
8019
|
|
|
return $this->_enableJavaScript; |
8020
|
|
|
} |
8021
|
|
|
public function setClientSupportsJavaScript($value) |
8022
|
|
|
{ |
8023
|
|
|
$this->_enableJavaScript=TPropertyValue::ensureBoolean($value); |
8024
|
|
|
} |
8025
|
|
|
public function getHead() |
8026
|
|
|
{ |
8027
|
|
|
return $this->_head; |
8028
|
|
|
} |
8029
|
|
|
public function setHead(THead $value) |
8030
|
|
|
{ |
8031
|
|
|
if($this->_head) |
8032
|
|
|
throw new TInvalidOperationException('page_head_duplicated'); |
8033
|
|
|
$this->_head=$value; |
8034
|
|
|
if($this->_title!==null) |
8035
|
|
|
{ |
8036
|
|
|
$this->_head->setTitle($this->_title); |
8037
|
|
|
$this->_title=null; |
8038
|
|
|
} |
8039
|
|
|
} |
8040
|
|
|
public function getTitle() |
8041
|
|
|
{ |
8042
|
|
|
if($this->_head) |
8043
|
|
|
return $this->_head->getTitle(); |
8044
|
|
|
else |
8045
|
|
|
return $this->_title===null ? '' : $this->_title; |
8046
|
|
|
} |
8047
|
|
|
public function setTitle($value) |
8048
|
|
|
{ |
8049
|
|
|
if($this->_head) |
8050
|
|
|
$this->_head->setTitle($value); |
8051
|
|
|
else |
8052
|
|
|
$this->_title=$value; |
8053
|
|
|
} |
8054
|
|
|
public function getClientState() |
8055
|
|
|
{ |
8056
|
|
|
return $this->_clientState; |
8057
|
|
|
} |
8058
|
|
|
public function setClientState($state) |
8059
|
|
|
{ |
8060
|
|
|
$this->_clientState=$state; |
8061
|
|
|
} |
8062
|
|
|
public function getRequestClientState() |
8063
|
|
|
{ |
8064
|
|
|
return $this->getRequest()->itemAt(self::FIELD_PAGESTATE); |
8065
|
|
|
} |
8066
|
|
|
public function getStatePersisterClass() |
8067
|
|
|
{ |
8068
|
|
|
return $this->_statePersisterClass; |
8069
|
|
|
} |
8070
|
|
|
public function setStatePersisterClass($value) |
8071
|
|
|
{ |
8072
|
|
|
$this->_statePersisterClass=$value; |
8073
|
|
|
} |
8074
|
|
|
public function getStatePersister() |
8075
|
|
|
{ |
8076
|
|
|
if($this->_statePersister===null) |
8077
|
|
|
{ |
8078
|
|
|
$this->_statePersister=Prado::createComponent($this->_statePersisterClass); |
8079
|
|
|
if(!($this->_statePersister instanceof IPageStatePersister)) |
8080
|
|
|
throw new TInvalidDataTypeException('page_statepersister_invalid'); |
8081
|
|
|
$this->_statePersister->setPage($this); |
8082
|
|
|
} |
8083
|
|
|
return $this->_statePersister; |
8084
|
|
|
} |
8085
|
|
|
public function getEnableStateValidation() |
8086
|
|
|
{ |
8087
|
|
|
return $this->_enableStateValidation; |
8088
|
|
|
} |
8089
|
|
|
public function setEnableStateValidation($value) |
8090
|
|
|
{ |
8091
|
|
|
$this->_enableStateValidation=TPropertyValue::ensureBoolean($value); |
8092
|
|
|
} |
8093
|
|
|
public function getEnableStateEncryption() |
8094
|
|
|
{ |
8095
|
|
|
return $this->_enableStateEncryption; |
8096
|
|
|
} |
8097
|
|
|
public function setEnableStateEncryption($value) |
8098
|
|
|
{ |
8099
|
|
|
$this->_enableStateEncryption=TPropertyValue::ensureBoolean($value); |
8100
|
|
|
} |
8101
|
|
|
public function getEnableStateCompression() |
8102
|
|
|
{ |
8103
|
|
|
return $this->_enableStateCompression; |
8104
|
|
|
} |
8105
|
|
|
public function setEnableStateCompression($value) |
8106
|
|
|
{ |
8107
|
|
|
$this->_enableStateCompression=TPropertyValue::ensureBoolean($value); |
8108
|
|
|
} |
8109
|
|
|
public function getPagePath() |
8110
|
|
|
{ |
8111
|
|
|
return $this->_pagePath; |
8112
|
|
|
} |
8113
|
|
|
public function setPagePath($value) |
8114
|
|
|
{ |
8115
|
|
|
$this->_pagePath=$value; |
8116
|
|
|
} |
8117
|
|
|
public function registerCachingAction($context,$funcName,$funcParams) |
8118
|
|
|
{ |
8119
|
|
|
if($this->_cachingStack) |
8120
|
|
|
{ |
8121
|
|
|
foreach($this->_cachingStack as $cache) |
8122
|
|
|
$cache->registerAction($context,$funcName,$funcParams); |
8123
|
|
|
} |
8124
|
|
|
} |
8125
|
|
|
public function getCachingStack() |
8126
|
|
|
{ |
8127
|
|
|
if(!$this->_cachingStack) |
8128
|
|
|
$this->_cachingStack=new TStack; |
8129
|
|
|
return $this->_cachingStack; |
8130
|
|
|
} |
8131
|
|
|
public function flushWriter() |
8132
|
|
|
{ |
8133
|
|
|
if ($this->_writer) |
8134
|
|
|
$this->Response->write($this->_writer->flush()); |
8135
|
|
|
} |
8136
|
|
|
} |
8137
|
|
|
interface IPageStatePersister |
8138
|
|
|
{ |
8139
|
|
|
public function getPage(); |
|
|
|
|
8140
|
|
|
public function setPage(TPage $page); |
|
|
|
|
8141
|
|
|
public function save($state); |
|
|
|
|
8142
|
|
|
public function load(); |
8143
|
|
|
} |
8144
|
|
|
class TPageStateFormatter |
8145
|
|
|
{ |
8146
|
|
|
public static function serialize($page,$data) |
8147
|
|
|
{ |
8148
|
|
|
$sm=$page->getApplication()->getSecurityManager(); |
8149
|
|
|
if($page->getEnableStateValidation()) |
8150
|
|
|
$str=$sm->hashData(serialize($data)); |
8151
|
|
|
else |
8152
|
|
|
$str=serialize($data); |
8153
|
|
|
if($page->getEnableStateCompression() && extension_loaded('zlib')) |
8154
|
|
|
$str=gzcompress($str); |
8155
|
|
|
if($page->getEnableStateEncryption()) |
8156
|
|
|
$str=$sm->encrypt($str); |
8157
|
|
|
return base64_encode($str); |
8158
|
|
|
} |
8159
|
|
|
public static function unserialize($page,$data) |
8160
|
|
|
{ |
8161
|
|
|
$str=base64_decode($data); |
8162
|
|
|
if($str==='') |
8163
|
|
|
return null; |
8164
|
|
|
if($str!==false) |
8165
|
|
|
{ |
8166
|
|
|
$sm=$page->getApplication()->getSecurityManager(); |
8167
|
|
|
if($page->getEnableStateEncryption()) |
8168
|
|
|
$str=$sm->decrypt($str); |
8169
|
|
|
if($page->getEnableStateCompression() && extension_loaded('zlib')) |
8170
|
|
|
$str=@gzuncompress($str); |
8171
|
|
|
if($page->getEnableStateValidation()) |
8172
|
|
|
{ |
8173
|
|
|
if(($str=$sm->validateData($str))!==false) |
8174
|
|
|
return unserialize($str); |
8175
|
|
|
} |
8176
|
|
|
else |
8177
|
|
|
return unserialize($str); |
8178
|
|
|
} |
8179
|
|
|
return null; |
8180
|
|
|
} |
8181
|
|
|
} |
8182
|
|
|
class TOutputCache extends TControl implements INamingContainer |
8183
|
|
|
{ |
8184
|
|
|
const CACHE_ID_PREFIX='prado:outputcache'; |
8185
|
|
|
private $_cacheModuleID=''; |
8186
|
|
|
private $_dataCached=false; |
8187
|
|
|
private $_cacheAvailable=false; |
8188
|
|
|
private $_cacheChecked=false; |
8189
|
|
|
private $_cacheKey=null; |
8190
|
|
|
private $_duration=60; |
8191
|
|
|
private $_cache=null; |
8192
|
|
|
private $_contents; |
8193
|
|
|
private $_state; |
8194
|
|
|
private $_actions=array(); |
8195
|
|
|
private $_varyByParam=''; |
8196
|
|
|
private $_keyPrefix=''; |
8197
|
|
|
private $_varyBySession=false; |
8198
|
|
|
private $_cachePostBack=false; |
8199
|
|
|
private $_cacheTime=0; |
8200
|
|
|
public function getAllowChildControls() |
8201
|
|
|
{ |
8202
|
|
|
$this->determineCacheability(); |
8203
|
|
|
return !$this->_dataCached; |
8204
|
|
|
} |
8205
|
|
|
private function determineCacheability() |
8206
|
|
|
{ |
8207
|
|
|
if(!$this->_cacheChecked) |
8208
|
|
|
{ |
8209
|
|
|
$this->_cacheChecked=true; |
8210
|
|
|
if($this->_duration>0 && ($this->_cachePostBack || !$this->getPage()->getIsPostBack())) |
8211
|
|
|
{ |
8212
|
|
|
if($this->_cacheModuleID!=='') |
8213
|
|
|
{ |
8214
|
|
|
$this->_cache=$this->getApplication()->getModule($this->_cacheModuleID); |
8215
|
|
|
if(!($this->_cache instanceof ICache)) |
8216
|
|
|
throw new TConfigurationException('outputcache_cachemoduleid_invalid',$this->_cacheModuleID); |
8217
|
|
|
} |
8218
|
|
|
else |
8219
|
|
|
$this->_cache=$this->getApplication()->getCache(); |
8220
|
|
|
if($this->_cache!==null) |
8221
|
|
|
{ |
8222
|
|
|
$this->_cacheAvailable=true; |
8223
|
|
|
$data=$this->_cache->get($this->getCacheKey()); |
8224
|
|
|
if(is_array($data)) |
8225
|
|
|
{ |
8226
|
|
|
$param=new TOutputCacheCheckDependencyEventParameter; |
8227
|
|
|
$param->setCacheTime(isset($data[3])?$data[3]:0); |
8228
|
|
|
$this->onCheckDependency($param); |
8229
|
|
|
$this->_dataCached=$param->getIsValid(); |
8230
|
|
|
} |
8231
|
|
|
else |
8232
|
|
|
$this->_dataCached=false; |
8233
|
|
|
if($this->_dataCached) |
8234
|
|
|
list($this->_contents,$this->_state,$this->_actions,$this->_cacheTime)=$data; |
8235
|
|
|
} |
8236
|
|
|
} |
8237
|
|
|
} |
8238
|
|
|
} |
8239
|
|
|
protected function initRecursive($namingContainer=null) |
8240
|
|
|
{ |
8241
|
|
|
if($this->_cacheAvailable && !$this->_dataCached) |
8242
|
|
|
{ |
8243
|
|
|
$stack=$this->getPage()->getCachingStack(); |
8244
|
|
|
$stack->push($this); |
8245
|
|
|
parent::initRecursive($namingContainer); |
8246
|
|
|
$stack->pop(); |
8247
|
|
|
} |
8248
|
|
|
else |
8249
|
|
|
parent::initRecursive($namingContainer); |
8250
|
|
|
} |
8251
|
|
|
protected function loadRecursive() |
8252
|
|
|
{ |
8253
|
|
|
if($this->_cacheAvailable && !$this->_dataCached) |
8254
|
|
|
{ |
8255
|
|
|
$stack=$this->getPage()->getCachingStack(); |
8256
|
|
|
$stack->push($this); |
8257
|
|
|
parent::loadRecursive(); |
8258
|
|
|
$stack->pop(); |
8259
|
|
|
} |
8260
|
|
|
else |
8261
|
|
|
{ |
8262
|
|
|
if($this->_dataCached) |
8263
|
|
|
$this->performActions(); |
8264
|
|
|
parent::loadRecursive(); |
8265
|
|
|
} |
8266
|
|
|
} |
8267
|
|
|
private function performActions() |
8268
|
|
|
{ |
8269
|
|
|
$page=$this->getPage(); |
8270
|
|
|
$cs=$page->getClientScript(); |
8271
|
|
|
foreach($this->_actions as $action) |
8272
|
|
|
{ |
8273
|
|
|
if($action[0]==='Page.ClientScript') |
8274
|
|
|
call_user_func_array(array($cs,$action[1]),$action[2]); |
8275
|
|
|
else if($action[0]==='Page') |
8276
|
|
|
call_user_func_array(array($page,$action[1]),$action[2]); |
8277
|
|
|
else |
8278
|
|
|
call_user_func_array(array($this->getSubProperty($action[0]),$action[1]),$action[2]); |
8279
|
|
|
} |
8280
|
|
|
} |
8281
|
|
|
protected function preRenderRecursive() |
8282
|
|
|
{ |
8283
|
|
|
if($this->_cacheAvailable && !$this->_dataCached) |
8284
|
|
|
{ |
8285
|
|
|
$stack=$this->getPage()->getCachingStack(); |
8286
|
|
|
$stack->push($this); |
8287
|
|
|
parent::preRenderRecursive(); |
8288
|
|
|
$stack->pop(); |
8289
|
|
|
} |
8290
|
|
|
else |
8291
|
|
|
parent::preRenderRecursive(); |
8292
|
|
|
} |
8293
|
|
|
protected function loadStateRecursive(&$state,$needViewState=true) |
8294
|
|
|
{ |
8295
|
|
|
$st=unserialize($state); |
8296
|
|
|
parent::loadStateRecursive($st,$needViewState); |
8297
|
|
|
} |
8298
|
|
|
protected function &saveStateRecursive($needViewState=true) |
8299
|
|
|
{ |
8300
|
|
|
if($this->_dataCached) |
8301
|
|
|
return $this->_state; |
8302
|
|
|
else |
8303
|
|
|
{ |
8304
|
|
|
$st=parent::saveStateRecursive($needViewState); |
8305
|
|
|
$this->_state=serialize($st); |
8306
|
|
|
return $this->_state; |
8307
|
|
|
} |
8308
|
|
|
} |
8309
|
|
|
public function registerAction($context,$funcName,$funcParams) |
8310
|
|
|
{ |
8311
|
|
|
$this->_actions[]=array($context,$funcName,$funcParams); |
8312
|
|
|
} |
8313
|
|
|
public function getCacheKey() |
8314
|
|
|
{ |
8315
|
|
|
if($this->_cacheKey===null) |
8316
|
|
|
$this->_cacheKey=$this->calculateCacheKey(); |
8317
|
|
|
return $this->_cacheKey; |
8318
|
|
|
} |
8319
|
|
|
protected function calculateCacheKey() |
8320
|
|
|
{ |
8321
|
|
|
$key=$this->getBaseCacheKey(); |
8322
|
|
|
if($this->_varyBySession) |
8323
|
|
|
$key.=$this->getSession()->getSessionID(); |
8324
|
|
|
if($this->_varyByParam!=='') |
8325
|
|
|
{ |
8326
|
|
|
$params=array(); |
8327
|
|
|
$request=$this->getRequest(); |
8328
|
|
|
foreach(explode(',',$this->_varyByParam) as $name) |
8329
|
|
|
{ |
8330
|
|
|
$name=trim($name); |
8331
|
|
|
$params[$name]=$request->itemAt($name); |
8332
|
|
|
} |
8333
|
|
|
$key.=serialize($params); |
8334
|
|
|
} |
8335
|
|
|
$param=new TOutputCacheCalculateKeyEventParameter; |
8336
|
|
|
$this->onCalculateKey($param); |
8337
|
|
|
$key.=$param->getCacheKey(); |
8338
|
|
|
return $key; |
8339
|
|
|
} |
8340
|
|
|
protected function getBaseCacheKey() |
8341
|
|
|
{ |
8342
|
|
|
return self::CACHE_ID_PREFIX.$this->_keyPrefix.$this->getPage()->getPagePath().$this->getUniqueID(); |
8343
|
|
|
} |
8344
|
|
|
public function getCacheModuleID() |
8345
|
|
|
{ |
8346
|
|
|
return $this->_cacheModuleID; |
8347
|
|
|
} |
8348
|
|
|
public function setCacheModuleID($value) |
8349
|
|
|
{ |
8350
|
|
|
$this->_cacheModuleID=$value; |
8351
|
|
|
} |
8352
|
|
|
public function setCacheKeyPrefix($value) |
8353
|
|
|
{ |
8354
|
|
|
$this->_keyPrefix=$value; |
8355
|
|
|
} |
8356
|
|
|
public function getCacheTime() |
8357
|
|
|
{ |
8358
|
|
|
return $this->_cacheTime; |
8359
|
|
|
} |
8360
|
|
|
protected function getCacheDependency() |
8361
|
|
|
{ |
8362
|
|
|
return null; |
8363
|
|
|
} |
8364
|
|
|
public function getContentCached() |
8365
|
|
|
{ |
8366
|
|
|
return $this->_dataCached; |
8367
|
|
|
} |
8368
|
|
|
public function getDuration() |
8369
|
|
|
{ |
8370
|
|
|
return $this->_duration; |
8371
|
|
|
} |
8372
|
|
|
public function setDuration($value) |
8373
|
|
|
{ |
8374
|
|
|
if(($value=TPropertyValue::ensureInteger($value))<0) |
8375
|
|
|
throw new TInvalidDataValueException('outputcache_duration_invalid',get_class($this)); |
8376
|
|
|
$this->_duration=$value; |
8377
|
|
|
} |
8378
|
|
|
public function getVaryByParam() |
8379
|
|
|
{ |
8380
|
|
|
return $this->_varyByParam; |
8381
|
|
|
} |
8382
|
|
|
public function setVaryByParam($value) |
8383
|
|
|
{ |
8384
|
|
|
$this->_varyByParam=trim($value); |
8385
|
|
|
} |
8386
|
|
|
public function getVaryBySession() |
8387
|
|
|
{ |
8388
|
|
|
return $this->_varyBySession; |
8389
|
|
|
} |
8390
|
|
|
public function setVaryBySession($value) |
8391
|
|
|
{ |
8392
|
|
|
$this->_varyBySession=TPropertyValue::ensureBoolean($value); |
8393
|
|
|
} |
8394
|
|
|
public function getCachingPostBack() |
8395
|
|
|
{ |
8396
|
|
|
return $this->_cachePostBack; |
8397
|
|
|
} |
8398
|
|
|
public function setCachingPostBack($value) |
8399
|
|
|
{ |
8400
|
|
|
$this->_cachePostBack=TPropertyValue::ensureBoolean($value); |
8401
|
|
|
} |
8402
|
|
|
public function onCheckDependency($param) |
8403
|
|
|
{ |
8404
|
|
|
$this->raiseEvent('OnCheckDependency',$this,$param); |
8405
|
|
|
} |
8406
|
|
|
public function onCalculateKey($param) |
8407
|
|
|
{ |
8408
|
|
|
$this->raiseEvent('OnCalculateKey',$this,$param); |
8409
|
|
|
} |
8410
|
|
|
public function render($writer) |
8411
|
|
|
{ |
8412
|
|
|
if($this->_dataCached) |
8413
|
|
|
$writer->write($this->_contents); |
8414
|
|
|
else if($this->_cacheAvailable) |
8415
|
|
|
{ |
8416
|
|
|
$textwriter = new TTextWriter(); |
8417
|
|
|
$multiwriter = new TOutputCacheTextWriterMulti(array($writer->getWriter(),$textwriter)); |
8418
|
|
|
$htmlWriter = Prado::createComponent($this->GetResponse()->getHtmlWriterType(), $multiwriter); |
8419
|
|
|
$stack=$this->getPage()->getCachingStack(); |
8420
|
|
|
$stack->push($this); |
8421
|
|
|
parent::render($htmlWriter); |
8422
|
|
|
$stack->pop(); |
8423
|
|
|
$content=$textwriter->flush(); |
8424
|
|
|
$data=array($content,$this->_state,$this->_actions,time()); |
8425
|
|
|
$this->_cache->set($this->getCacheKey(),$data,$this->getDuration(),$this->getCacheDependency()); |
|
|
|
|
8426
|
|
|
} |
8427
|
|
|
else |
8428
|
|
|
parent::render($writer); |
8429
|
|
|
} |
8430
|
|
|
} |
8431
|
|
|
class TOutputCacheCheckDependencyEventParameter extends TEventParameter |
8432
|
|
|
{ |
8433
|
|
|
private $_isValid=true; |
8434
|
|
|
private $_cacheTime=0; |
8435
|
|
|
public function getIsValid() |
8436
|
|
|
{ |
8437
|
|
|
return $this->_isValid; |
8438
|
|
|
} |
8439
|
|
|
public function setIsValid($value) |
8440
|
|
|
{ |
8441
|
|
|
$this->_isValid=TPropertyValue::ensureBoolean($value); |
8442
|
|
|
} |
8443
|
|
|
public function getCacheTime() |
8444
|
|
|
{ |
8445
|
|
|
return $this->_cacheTime; |
8446
|
|
|
} |
8447
|
|
|
public function setCacheTime($value) |
8448
|
|
|
{ |
8449
|
|
|
$this->_cacheTime=TPropertyValue::ensureInteger($value); |
8450
|
|
|
} |
8451
|
|
|
} |
8452
|
|
|
class TOutputCacheCalculateKeyEventParameter extends TEventParameter |
8453
|
|
|
{ |
8454
|
|
|
private $_cacheKey=''; |
8455
|
|
|
public function getCacheKey() |
8456
|
|
|
{ |
8457
|
|
|
return $this->_cacheKey; |
8458
|
|
|
} |
8459
|
|
|
public function setCacheKey($value) |
8460
|
|
|
{ |
8461
|
|
|
$this->_cacheKey=TPropertyValue::ensureString($value); |
8462
|
|
|
} |
8463
|
|
|
} |
8464
|
|
|
class TOutputCacheTextWriterMulti extends TTextWriter |
8465
|
|
|
{ |
8466
|
|
|
protected $_writers; |
8467
|
|
|
public function __construct(Array $writers) |
8468
|
|
|
{ |
8469
|
|
|
$this->_writers = $writers; |
8470
|
|
|
} |
8471
|
|
|
public function write($s) |
8472
|
|
|
{ |
8473
|
|
|
foreach($this->_writers as $writer) |
8474
|
|
|
$writer->write($s); |
8475
|
|
|
} |
8476
|
|
|
public function flush() |
8477
|
|
|
{ |
8478
|
|
|
foreach($this->_writers as $writer) |
8479
|
|
|
$s = $writer->flush(); |
8480
|
|
|
return $s; |
|
|
|
|
8481
|
|
|
} |
8482
|
|
|
} |
8483
|
|
|
class TTemplateManager extends TModule |
8484
|
|
|
{ |
8485
|
|
|
const TEMPLATE_FILE_EXT='.tpl'; |
8486
|
|
|
const TEMPLATE_CACHE_PREFIX='prado:template:'; |
8487
|
|
|
public function init($config) |
8488
|
|
|
{ |
8489
|
|
|
$this->getService()->setTemplateManager($this); |
|
|
|
|
8490
|
|
|
} |
8491
|
|
|
public function getTemplateByClassName($className) |
8492
|
|
|
{ |
8493
|
|
|
$class=new ReflectionClass($className); |
8494
|
|
|
$tplFile=dirname($class->getFileName()).DIRECTORY_SEPARATOR.$className.self::TEMPLATE_FILE_EXT; |
8495
|
|
|
return $this->getTemplateByFileName($tplFile); |
8496
|
|
|
} |
8497
|
|
|
public function getTemplateByFileName($fileName) |
8498
|
|
|
{ |
8499
|
|
|
if(($fileName=$this->getLocalizedTemplate($fileName))!==null) |
8500
|
|
|
{ |
8501
|
|
|
if(($cache=$this->getApplication()->getCache())===null) |
8502
|
|
|
return new TTemplate(file_get_contents($fileName),dirname($fileName),$fileName); |
8503
|
|
|
else |
8504
|
|
|
{ |
8505
|
|
|
$array=$cache->get(self::TEMPLATE_CACHE_PREFIX.$fileName); |
8506
|
|
|
if(is_array($array)) |
8507
|
|
|
{ |
8508
|
|
|
list($template,$timestamps)=$array; |
8509
|
|
|
if($this->getApplication()->getMode()===TApplicationMode::Performance) |
8510
|
|
|
return $template; |
8511
|
|
|
$cacheValid=true; |
8512
|
|
|
foreach($timestamps as $tplFile=>$timestamp) |
8513
|
|
|
{ |
8514
|
|
|
if(!is_file($tplFile) || filemtime($tplFile)>$timestamp) |
8515
|
|
|
{ |
8516
|
|
|
$cacheValid=false; |
8517
|
|
|
break; |
8518
|
|
|
} |
8519
|
|
|
} |
8520
|
|
|
if($cacheValid) |
8521
|
|
|
return $template; |
8522
|
|
|
} |
8523
|
|
|
$template=new TTemplate(file_get_contents($fileName),dirname($fileName),$fileName); |
8524
|
|
|
$includedFiles=$template->getIncludedFiles(); |
8525
|
|
|
$timestamps=array(); |
8526
|
|
|
$timestamps[$fileName]=filemtime($fileName); |
8527
|
|
|
foreach($includedFiles as $includedFile) |
8528
|
|
|
$timestamps[$includedFile]=filemtime($includedFile); |
8529
|
|
|
$cache->set(self::TEMPLATE_CACHE_PREFIX.$fileName,array($template,$timestamps)); |
8530
|
|
|
return $template; |
8531
|
|
|
} |
8532
|
|
|
} |
8533
|
|
|
else |
8534
|
|
|
return null; |
8535
|
|
|
} |
8536
|
|
|
protected function getLocalizedTemplate($filename) |
8537
|
|
|
{ |
8538
|
|
|
if(($app=$this->getApplication()->getGlobalization(false))===null) |
8539
|
|
|
return is_file($filename)?$filename:null; |
8540
|
|
|
foreach($app->getLocalizedResource($filename) as $file) |
8541
|
|
|
{ |
8542
|
|
|
if(($file=realpath($file))!==false && is_file($file)) |
8543
|
|
|
return $file; |
8544
|
|
|
} |
8545
|
|
|
return null; |
8546
|
|
|
} |
8547
|
|
|
} |
8548
|
|
|
class TTemplate extends TApplicationComponent implements ITemplate |
8549
|
|
|
{ |
8550
|
|
|
const REGEX_RULES='/<!--.*?--!>|<!---.*?--->|<\/?com:([\w\.]+)((?:\s*[\w\.]+\s*=\s*\'.*?\'|\s*[\w\.]+\s*=\s*".*?"|\s*[\w\.]+\s*=\s*<%.*?%>)*)\s*\/?>|<\/?prop:([\w\.\-]+)\s*>|<%@\s*((?:\s*[\w\.]+\s*=\s*\'.*?\'|\s*[\w\.]+\s*=\s*".*?")*)\s*%>|<%[%#~\/\\$=\\[](.*?)%>|<prop:([\w\.\-]+)((?:\s*[\w\.\-]+\s*=\s*\'.*?\'|\s*[\w\.\-]+\s*=\s*".*?"|\s*[\w\.\-]+\s*=\s*<%.*?%>)*)\s*\/>/msS'; |
8551
|
|
|
const CONFIG_DATABIND=0; |
8552
|
|
|
const CONFIG_EXPRESSION=1; |
8553
|
|
|
const CONFIG_ASSET=2; |
8554
|
|
|
const CONFIG_PARAMETER=3; |
8555
|
|
|
const CONFIG_LOCALIZATION=4; |
8556
|
|
|
const CONFIG_TEMPLATE=5; |
8557
|
|
|
private $_tpl=array(); |
8558
|
|
|
private $_directive=array(); |
8559
|
|
|
private $_contextPath; |
8560
|
|
|
private $_tplFile=null; |
8561
|
|
|
private $_startingLine=0; |
8562
|
|
|
private $_content; |
8563
|
|
|
private $_sourceTemplate=true; |
8564
|
|
|
private $_hashCode=''; |
8565
|
|
|
private $_tplControl=null; |
8566
|
|
|
private $_includedFiles=array(); |
8567
|
|
|
private $_includeAtLine=array(); |
8568
|
|
|
private $_includeLines=array(); |
8569
|
|
|
public function __construct($template,$contextPath,$tplFile=null,$startingLine=0,$sourceTemplate=true) |
8570
|
|
|
{ |
8571
|
|
|
$this->_sourceTemplate=$sourceTemplate; |
8572
|
|
|
$this->_contextPath=$contextPath; |
8573
|
|
|
$this->_tplFile=$tplFile; |
8574
|
|
|
$this->_startingLine=$startingLine; |
8575
|
|
|
$this->_content=$template; |
8576
|
|
|
$this->_hashCode=md5($template); |
8577
|
|
|
$this->parse($template); |
8578
|
|
|
$this->_content=null; } |
8579
|
|
|
public function getTemplateFile() |
8580
|
|
|
{ |
8581
|
|
|
return $this->_tplFile; |
8582
|
|
|
} |
8583
|
|
|
public function getIsSourceTemplate() |
8584
|
|
|
{ |
8585
|
|
|
return $this->_sourceTemplate; |
8586
|
|
|
} |
8587
|
|
|
public function getContextPath() |
8588
|
|
|
{ |
8589
|
|
|
return $this->_contextPath; |
8590
|
|
|
} |
8591
|
|
|
public function getDirective() |
8592
|
|
|
{ |
8593
|
|
|
return $this->_directive; |
8594
|
|
|
} |
8595
|
|
|
public function getHashCode() |
8596
|
|
|
{ |
8597
|
|
|
return $this->_hashCode; |
8598
|
|
|
} |
8599
|
|
|
public function &getItems() |
8600
|
|
|
{ |
8601
|
|
|
return $this->_tpl; |
8602
|
|
|
} |
8603
|
|
|
public function instantiateIn($tplControl,$parentControl=null) |
8604
|
|
|
{ |
8605
|
|
|
$this->_tplControl=$tplControl; |
8606
|
|
|
if($parentControl===null) |
8607
|
|
|
$parentControl=$tplControl; |
8608
|
|
|
if(($page=$tplControl->getPage())===null) |
8609
|
|
|
$page=$this->getService()->getRequestedPage(); |
|
|
|
|
8610
|
|
|
$controls=array(); |
8611
|
|
|
$directChildren=array(); |
8612
|
|
|
foreach($this->_tpl as $key=>$object) |
8613
|
|
|
{ |
8614
|
|
|
if($object[0]===-1) |
8615
|
|
|
$parent=$parentControl; |
8616
|
|
|
else if(isset($controls[$object[0]])) |
8617
|
|
|
$parent=$controls[$object[0]]; |
8618
|
|
|
else |
8619
|
|
|
continue; |
8620
|
|
|
if(isset($object[2])) { |
8621
|
|
|
$component=Prado::createComponent($object[1]); |
8622
|
|
|
$properties=&$object[2]; |
8623
|
|
|
if($component instanceof TControl) |
8624
|
|
|
{ |
8625
|
|
|
if($component instanceof TOutputCache) |
8626
|
|
|
$component->setCacheKeyPrefix($this->_hashCode.$key); |
8627
|
|
|
$component->setTemplateControl($tplControl); |
8628
|
|
|
if(isset($properties['id'])) |
8629
|
|
|
{ |
8630
|
|
|
if(is_array($properties['id'])) |
8631
|
|
|
$properties['id']=$component->evaluateExpression($properties['id'][1]); |
8632
|
|
|
$tplControl->registerObject($properties['id'],$component); |
8633
|
|
|
} |
8634
|
|
|
if(isset($properties['skinid'])) |
8635
|
|
|
{ |
8636
|
|
|
if(is_array($properties['skinid'])) |
8637
|
|
|
$component->setSkinID($component->evaluateExpression($properties['skinid'][1])); |
8638
|
|
|
else |
8639
|
|
|
$component->setSkinID($properties['skinid']); |
8640
|
|
|
unset($properties['skinid']); |
8641
|
|
|
} |
8642
|
|
|
$component->trackViewState(false); |
8643
|
|
|
$component->applyStyleSheetSkin($page); |
8644
|
|
|
foreach($properties as $name=>$value) |
8645
|
|
|
$this->configureControl($component,$name,$value); |
8646
|
|
|
$component->trackViewState(true); |
8647
|
|
|
if($parent===$parentControl) |
8648
|
|
|
$directChildren[]=$component; |
8649
|
|
|
else |
8650
|
|
|
$component->createdOnTemplate($parent); |
8651
|
|
|
if($component->getAllowChildControls()) |
8652
|
|
|
$controls[$key]=$component; |
8653
|
|
|
} |
8654
|
|
|
else if($component instanceof TComponent) |
8655
|
|
|
{ |
8656
|
|
|
$controls[$key]=$component; |
8657
|
|
|
if(isset($properties['id'])) |
8658
|
|
|
{ |
8659
|
|
|
if(is_array($properties['id'])) |
8660
|
|
|
$properties['id']=$component->evaluateExpression($properties['id'][1]); |
8661
|
|
|
$tplControl->registerObject($properties['id'],$component); |
8662
|
|
|
if(!$component->hasProperty('id')) |
8663
|
|
|
unset($properties['id']); |
8664
|
|
|
} |
8665
|
|
|
foreach($properties as $name=>$value) |
8666
|
|
|
$this->configureComponent($component,$name,$value); |
8667
|
|
|
if($parent===$parentControl) |
8668
|
|
|
$directChildren[]=$component; |
8669
|
|
|
else |
8670
|
|
|
$component->createdOnTemplate($parent); |
8671
|
|
|
} |
8672
|
|
|
} |
8673
|
|
|
else |
8674
|
|
|
{ |
8675
|
|
|
if($object[1] instanceof TCompositeLiteral) |
8676
|
|
|
{ |
8677
|
|
|
$o=clone $object[1]; |
8678
|
|
|
$o->setContainer($tplControl); |
8679
|
|
|
if($parent===$parentControl) |
8680
|
|
|
$directChildren[]=$o; |
8681
|
|
|
else |
8682
|
|
|
$parent->addParsedObject($o); |
8683
|
|
|
} |
8684
|
|
|
else |
8685
|
|
|
{ |
8686
|
|
|
if($parent===$parentControl) |
8687
|
|
|
$directChildren[]=$object[1]; |
8688
|
|
|
else |
8689
|
|
|
$parent->addParsedObject($object[1]); |
8690
|
|
|
} |
8691
|
|
|
} |
8692
|
|
|
} |
8693
|
|
|
foreach($directChildren as $control) |
8694
|
|
|
{ |
8695
|
|
|
if($control instanceof TComponent) |
8696
|
|
|
$control->createdOnTemplate($parentControl); |
8697
|
|
|
else |
8698
|
|
|
$parentControl->addParsedObject($control); |
8699
|
|
|
} |
8700
|
|
|
} |
8701
|
|
|
protected function configureControl($control,$name,$value) |
8702
|
|
|
{ |
8703
|
|
|
if(strncasecmp($name,'on',2)===0) $this->configureEvent($control,$name,$value,$control); |
8704
|
|
|
else if(($pos=strrpos($name,'.'))===false) $this->configureProperty($control,$name,$value); |
8705
|
|
|
else $this->configureSubProperty($control,$name,$value); |
8706
|
|
|
} |
8707
|
|
|
protected function configureComponent($component,$name,$value) |
8708
|
|
|
{ |
8709
|
|
|
if(strpos($name,'.')===false) $this->configureProperty($component,$name,$value); |
8710
|
|
|
else $this->configureSubProperty($component,$name,$value); |
8711
|
|
|
} |
8712
|
|
|
protected function configureEvent($control,$name,$value,$contextControl) |
8713
|
|
|
{ |
8714
|
|
|
if(strpos($value,'.')===false) |
8715
|
|
|
$control->attachEventHandler($name,array($contextControl,'TemplateControl.'.$value)); |
8716
|
|
|
else |
8717
|
|
|
$control->attachEventHandler($name,array($contextControl,$value)); |
8718
|
|
|
} |
8719
|
|
|
protected function configureProperty($component,$name,$value) |
8720
|
|
|
{ |
8721
|
|
|
if(is_array($value)) |
8722
|
|
|
{ |
8723
|
|
|
switch($value[0]) |
8724
|
|
|
{ |
8725
|
|
|
case self::CONFIG_DATABIND: |
8726
|
|
|
$component->bindProperty($name,$value[1]); |
8727
|
|
|
break; |
8728
|
|
|
case self::CONFIG_EXPRESSION: |
8729
|
|
|
if($component instanceof TControl) |
8730
|
|
|
$component->autoBindProperty($name,$value[1]); |
8731
|
|
|
else |
8732
|
|
|
{ |
8733
|
|
|
$setter='set'.$name; |
8734
|
|
|
$component->$setter($this->_tplControl->evaluateExpression($value[1])); |
8735
|
|
|
} |
8736
|
|
|
break; |
8737
|
|
|
case self::CONFIG_TEMPLATE: |
8738
|
|
|
$setter='set'.$name; |
8739
|
|
|
$component->$setter($value[1]); |
8740
|
|
|
break; |
8741
|
|
|
case self::CONFIG_ASSET: $setter='set'.$name; |
|
|
|
|
8742
|
|
|
$url=$this->publishFilePath($this->_contextPath.DIRECTORY_SEPARATOR.$value[1]); |
8743
|
|
|
$component->$setter($url); |
8744
|
|
|
break; |
8745
|
|
|
case self::CONFIG_PARAMETER: $setter='set'.$name; |
|
|
|
|
8746
|
|
|
$component->$setter($this->getApplication()->getParameters()->itemAt($value[1])); |
8747
|
|
|
break; |
8748
|
|
|
case self::CONFIG_LOCALIZATION: |
8749
|
|
|
$setter='set'.$name; |
8750
|
|
|
$component->$setter(Prado::localize($value[1])); |
8751
|
|
|
break; |
8752
|
|
|
default: throw new TConfigurationException('template_tag_unexpected',$name,$value[1]); |
|
|
|
|
8753
|
|
|
break; |
|
|
|
|
8754
|
|
|
} |
8755
|
|
|
} |
8756
|
|
|
else |
8757
|
|
|
{ |
8758
|
|
|
if (substr($name,0,2)=='js') |
8759
|
|
|
if ($value and !($value instanceof TJavaScriptLiteral)) |
|
|
|
|
8760
|
|
|
$value = new TJavaScriptLiteral($value); |
8761
|
|
|
$setter='set'.$name; |
8762
|
|
|
$component->$setter($value); |
8763
|
|
|
} |
8764
|
|
|
} |
8765
|
|
|
protected function configureSubProperty($component,$name,$value) |
8766
|
|
|
{ |
8767
|
|
|
if(is_array($value)) |
8768
|
|
|
{ |
8769
|
|
|
switch($value[0]) |
8770
|
|
|
{ |
8771
|
|
|
case self::CONFIG_DATABIND: $component->bindProperty($name,$value[1]); |
|
|
|
|
8772
|
|
|
break; |
8773
|
|
|
case self::CONFIG_EXPRESSION: if($component instanceof TControl) |
|
|
|
|
8774
|
|
|
$component->autoBindProperty($name,$value[1]); |
8775
|
|
|
else |
8776
|
|
|
$component->setSubProperty($name,$this->_tplControl->evaluateExpression($value[1])); |
8777
|
|
|
break; |
8778
|
|
|
case self::CONFIG_TEMPLATE: |
8779
|
|
|
$component->setSubProperty($name,$value[1]); |
8780
|
|
|
break; |
8781
|
|
|
case self::CONFIG_ASSET: $url=$this->publishFilePath($this->_contextPath.DIRECTORY_SEPARATOR.$value[1]); |
|
|
|
|
8782
|
|
|
$component->setSubProperty($name,$url); |
8783
|
|
|
break; |
8784
|
|
|
case self::CONFIG_PARAMETER: $component->setSubProperty($name,$this->getApplication()->getParameters()->itemAt($value[1])); |
|
|
|
|
8785
|
|
|
break; |
8786
|
|
|
case self::CONFIG_LOCALIZATION: |
8787
|
|
|
$component->setSubProperty($name,Prado::localize($value[1])); |
8788
|
|
|
break; |
8789
|
|
|
default: throw new TConfigurationException('template_tag_unexpected',$name,$value[1]); |
|
|
|
|
8790
|
|
|
break; |
|
|
|
|
8791
|
|
|
} |
8792
|
|
|
} |
8793
|
|
|
else |
8794
|
|
|
$component->setSubProperty($name,$value); |
8795
|
|
|
} |
8796
|
|
|
protected function parse($input) |
8797
|
|
|
{ |
8798
|
|
|
$input=$this->preprocess($input); |
8799
|
|
|
$tpl=&$this->_tpl; |
8800
|
|
|
$n=preg_match_all(self::REGEX_RULES,$input,$matches,PREG_SET_ORDER|PREG_OFFSET_CAPTURE); |
8801
|
|
|
$expectPropEnd=false; |
8802
|
|
|
$textStart=0; |
8803
|
|
|
$stack=array(); |
8804
|
|
|
$container=-1; |
8805
|
|
|
$matchEnd=0; |
8806
|
|
|
$c=0; |
8807
|
|
|
$this->_directive=null; |
|
|
|
|
8808
|
|
|
try |
8809
|
|
|
{ |
8810
|
|
|
for($i=0;$i<$n;++$i) |
8811
|
|
|
{ |
8812
|
|
|
$match=&$matches[$i]; |
8813
|
|
|
$str=$match[0][0]; |
8814
|
|
|
$matchStart=$match[0][1]; |
8815
|
|
|
$matchEnd=$matchStart+strlen($str)-1; |
8816
|
|
|
if(strpos($str,'<com:')===0) { |
8817
|
|
|
if($expectPropEnd) |
8818
|
|
|
continue; |
8819
|
|
|
if($matchStart>$textStart) |
8820
|
|
|
$tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart)); |
8821
|
|
|
$textStart=$matchEnd+1; |
8822
|
|
|
$type=$match[1][0]; |
8823
|
|
|
$attributes=$this->parseAttributes($match[2][0],$match[2][1]); |
8824
|
|
|
$this->validateAttributes($type,$attributes); |
8825
|
|
|
$tpl[$c++]=array($container,$type,$attributes); |
8826
|
|
|
if($str[strlen($str)-2]!=='/') { |
8827
|
|
|
$stack[] = $type; |
8828
|
|
|
$container=$c-1; |
8829
|
|
|
} |
8830
|
|
|
} |
8831
|
|
|
else if(strpos($str,'</com:')===0) { |
8832
|
|
|
if($expectPropEnd) |
8833
|
|
|
continue; |
8834
|
|
|
if($matchStart>$textStart) |
8835
|
|
|
$tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart)); |
8836
|
|
|
$textStart=$matchEnd+1; |
8837
|
|
|
$type=$match[1][0]; |
8838
|
|
|
if(empty($stack)) |
8839
|
|
|
throw new TConfigurationException('template_closingtag_unexpected',"</com:$type>"); |
8840
|
|
|
$name=array_pop($stack); |
8841
|
|
|
if($name!==$type) |
8842
|
|
|
{ |
8843
|
|
|
$tag=$name[0]==='@' ? '</prop:'.substr($name,1).'>' : "</com:$name>"; |
8844
|
|
|
throw new TConfigurationException('template_closingtag_expected',$tag); |
8845
|
|
|
} |
8846
|
|
|
$container=$tpl[$container][0]; |
8847
|
|
|
} |
8848
|
|
|
else if(strpos($str,'<%@')===0) { |
8849
|
|
|
if($expectPropEnd) |
8850
|
|
|
continue; |
8851
|
|
|
if($matchStart>$textStart) |
8852
|
|
|
$tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart)); |
8853
|
|
|
$textStart=$matchEnd+1; |
8854
|
|
|
if(isset($tpl[0]) || $this->_directive!==null) |
8855
|
|
|
throw new TConfigurationException('template_directive_nonunique'); |
8856
|
|
|
$this->_directive=$this->parseAttributes($match[4][0],$match[4][1]); |
8857
|
|
|
} |
8858
|
|
|
else if(strpos($str,'<%')===0) { |
8859
|
|
|
if($expectPropEnd) |
8860
|
|
|
continue; |
8861
|
|
|
if($matchStart>$textStart) |
8862
|
|
|
$tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart)); |
8863
|
|
|
$textStart=$matchEnd+1; |
8864
|
|
|
$literal=trim($match[5][0]); |
8865
|
|
|
if($str[2]==='=') $tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_EXPRESSION,$literal)); |
8866
|
|
|
else if($str[2]==='%') $tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_STATEMENTS,$literal)); |
8867
|
|
|
else if($str[2]==='#') |
8868
|
|
|
$tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_DATABINDING,$literal)); |
8869
|
|
|
else if($str[2]==='$') |
8870
|
|
|
$tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_EXPRESSION,"\$this->getApplication()->getParameters()->itemAt('$literal')")); |
8871
|
|
|
else if($str[2]==='~') |
8872
|
|
|
$tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_EXPRESSION,"\$this->publishFilePath('$this->_contextPath/$literal')")); |
8873
|
|
|
else if($str[2]==='/') |
8874
|
|
|
$tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_EXPRESSION,"rtrim(dirname(\$this->getApplication()->getRequest()->getApplicationUrl()), '\/').'/$literal'")); |
8875
|
|
|
else if($str[2]==='[') |
8876
|
|
|
{ |
8877
|
|
|
$literal=strtr(trim(substr($literal,0,strlen($literal)-1)),array("'"=>"\'","\\"=>"\\\\")); |
8878
|
|
|
$tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_EXPRESSION,"Prado::localize('$literal')")); |
8879
|
|
|
} |
8880
|
|
|
} |
8881
|
|
|
else if(strpos($str,'<prop:')===0) { |
8882
|
|
|
if(strrpos($str,'/>')===strlen($str)-2) { |
8883
|
|
|
if($expectPropEnd) |
8884
|
|
|
continue; |
8885
|
|
|
if($matchStart>$textStart) |
8886
|
|
|
$tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart)); |
8887
|
|
|
$textStart=$matchEnd+1; |
8888
|
|
|
$prop=strtolower($match[6][0]); |
8889
|
|
|
$attrs=$this->parseAttributes($match[7][0],$match[7][1]); |
8890
|
|
|
$attributes=array(); |
8891
|
|
|
foreach($attrs as $name=>$value) |
8892
|
|
|
$attributes[$prop.'.'.$name]=$value; |
8893
|
|
|
$type=$tpl[$container][1]; |
8894
|
|
|
$this->validateAttributes($type,$attributes); |
8895
|
|
|
foreach($attributes as $name=>$value) |
8896
|
|
|
{ |
8897
|
|
|
if(isset($tpl[$container][2][$name])) |
8898
|
|
|
throw new TConfigurationException('template_property_duplicated',$name); |
8899
|
|
|
$tpl[$container][2][$name]=$value; |
8900
|
|
|
} |
8901
|
|
|
} |
8902
|
|
|
else { |
8903
|
|
|
$prop=strtolower($match[3][0]); |
8904
|
|
|
$stack[] = '@'.$prop; |
8905
|
|
|
if(!$expectPropEnd) |
8906
|
|
|
{ |
8907
|
|
|
if($matchStart>$textStart) |
8908
|
|
|
$tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart)); |
8909
|
|
|
$textStart=$matchEnd+1; |
8910
|
|
|
$expectPropEnd=true; |
8911
|
|
|
} |
8912
|
|
|
} |
8913
|
|
|
} |
8914
|
|
|
else if(strpos($str,'</prop:')===0) { |
8915
|
|
|
$prop=strtolower($match[3][0]); |
8916
|
|
|
if(empty($stack)) |
8917
|
|
|
throw new TConfigurationException('template_closingtag_unexpected',"</prop:$prop>"); |
8918
|
|
|
$name=array_pop($stack); |
8919
|
|
|
if($name!=='@'.$prop) |
8920
|
|
|
{ |
8921
|
|
|
$tag=$name[0]==='@' ? '</prop:'.substr($name,1).'>' : "</com:$name>"; |
8922
|
|
|
throw new TConfigurationException('template_closingtag_expected',$tag); |
8923
|
|
|
} |
8924
|
|
|
if(($last=count($stack))<1 || $stack[$last-1][0]!=='@') |
8925
|
|
|
{ |
8926
|
|
|
if($matchStart>$textStart) |
8927
|
|
|
{ |
8928
|
|
|
$value=substr($input,$textStart,$matchStart-$textStart); |
8929
|
|
|
if(substr($prop,-8,8)==='template') |
8930
|
|
|
$value=$this->parseTemplateProperty($value,$textStart); |
8931
|
|
|
else |
8932
|
|
|
$value=$this->parseAttribute($value); |
8933
|
|
|
if($container>=0) |
8934
|
|
|
{ |
8935
|
|
|
$type=$tpl[$container][1]; |
8936
|
|
|
$this->validateAttributes($type,array($prop=>$value)); |
8937
|
|
|
if(isset($tpl[$container][2][$prop])) |
8938
|
|
|
throw new TConfigurationException('template_property_duplicated',$prop); |
8939
|
|
|
$tpl[$container][2][$prop]=$value; |
8940
|
|
|
} |
8941
|
|
|
else $this->_directive[$prop]=$value; |
8942
|
|
|
$textStart=$matchEnd+1; |
8943
|
|
|
} |
8944
|
|
|
$expectPropEnd=false; |
8945
|
|
|
} |
8946
|
|
|
} |
8947
|
|
|
else if(strpos($str,'<!--')===0) { |
8948
|
|
|
if($expectPropEnd) |
8949
|
|
|
throw new TConfigurationException('template_comments_forbidden'); |
8950
|
|
|
if($matchStart>$textStart) |
8951
|
|
|
$tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart)); |
8952
|
|
|
$textStart=$matchEnd+1; |
8953
|
|
|
} |
8954
|
|
|
else |
8955
|
|
|
throw new TConfigurationException('template_matching_unexpected',$match); |
8956
|
|
|
} |
8957
|
|
|
if(!empty($stack)) |
8958
|
|
|
{ |
8959
|
|
|
$name=array_pop($stack); |
8960
|
|
|
$tag=$name[0]==='@' ? '</prop:'.substr($name,1).'>' : "</com:$name>"; |
8961
|
|
|
throw new TConfigurationException('template_closingtag_expected',$tag); |
8962
|
|
|
} |
8963
|
|
|
if($textStart<strlen($input)) |
8964
|
|
|
$tpl[$c++]=array($container,substr($input,$textStart)); |
8965
|
|
|
} |
8966
|
|
|
catch(Exception $e) |
8967
|
|
|
{ |
8968
|
|
|
if(($e instanceof TException) && ($e instanceof TTemplateException)) |
8969
|
|
|
throw $e; |
8970
|
|
|
if($matchEnd===0) |
8971
|
|
|
$line=$this->_startingLine+1; |
8972
|
|
|
else |
8973
|
|
|
$line=$this->_startingLine+count(explode("\n",substr($input,0,$matchEnd+1))); |
8974
|
|
|
$this->handleException($e,$line,$input); |
8975
|
|
|
} |
8976
|
|
|
if($this->_directive===null) |
8977
|
|
|
$this->_directive=array(); |
8978
|
|
|
$objects=array(); |
8979
|
|
|
$parent=null; |
8980
|
|
|
$merged=array(); |
8981
|
|
|
foreach($tpl as $id=>$object) |
8982
|
|
|
{ |
8983
|
|
|
if(isset($object[2]) || $object[0]!==$parent) |
8984
|
|
|
{ |
8985
|
|
|
if($parent!==null) |
8986
|
|
|
{ |
8987
|
|
|
if(count($merged[1])===1 && is_string($merged[1][0])) |
8988
|
|
|
$objects[$id-1]=array($merged[0],$merged[1][0]); |
8989
|
|
|
else |
8990
|
|
|
$objects[$id-1]=array($merged[0],new TCompositeLiteral($merged[1])); |
8991
|
|
|
} |
8992
|
|
|
if(isset($object[2])) |
8993
|
|
|
{ |
8994
|
|
|
$parent=null; |
8995
|
|
|
$objects[$id]=$object; |
8996
|
|
|
} |
8997
|
|
|
else |
8998
|
|
|
{ |
8999
|
|
|
$parent=$object[0]; |
9000
|
|
|
$merged=array($parent,array($object[1])); |
9001
|
|
|
} |
9002
|
|
|
} |
9003
|
|
|
else |
9004
|
|
|
$merged[1][]=$object[1]; |
9005
|
|
|
} |
9006
|
|
|
if($parent!==null) |
9007
|
|
|
{ |
9008
|
|
|
if(count($merged[1])===1 && is_string($merged[1][0])) |
9009
|
|
|
$objects[$id]=array($merged[0],$merged[1][0]); |
|
|
|
|
9010
|
|
|
else |
9011
|
|
|
$objects[$id]=array($merged[0],new TCompositeLiteral($merged[1])); |
9012
|
|
|
} |
9013
|
|
|
$tpl=$objects; |
9014
|
|
|
return $objects; |
9015
|
|
|
} |
9016
|
|
|
protected function parseAttributes($str,$offset) |
9017
|
|
|
{ |
9018
|
|
|
if($str==='') |
9019
|
|
|
return array(); |
9020
|
|
|
$pattern='/([\w\.\-]+)\s*=\s*(\'.*?\'|".*?"|<%.*?%>)/msS'; |
9021
|
|
|
$attributes=array(); |
9022
|
|
|
$n=preg_match_all($pattern,$str,$matches,PREG_SET_ORDER|PREG_OFFSET_CAPTURE); |
9023
|
|
|
for($i=0;$i<$n;++$i) |
9024
|
|
|
{ |
9025
|
|
|
$match=&$matches[$i]; |
9026
|
|
|
$name=strtolower($match[1][0]); |
9027
|
|
|
if(isset($attributes[$name])) |
9028
|
|
|
throw new TConfigurationException('template_property_duplicated',$name); |
9029
|
|
|
$value=$match[2][0]; |
9030
|
|
|
if(substr($name,-8,8)==='template') |
9031
|
|
|
{ |
9032
|
|
|
if($value[0]==='\'' || $value[0]==='"') |
9033
|
|
|
$attributes[$name]=$this->parseTemplateProperty(substr($value,1,strlen($value)-2),$match[2][1]+1); |
9034
|
|
|
else |
9035
|
|
|
$attributes[$name]=$this->parseTemplateProperty($value,$match[2][1]); |
9036
|
|
|
} |
9037
|
|
|
else |
9038
|
|
|
{ |
9039
|
|
|
if($value[0]==='\'' || $value[0]==='"') |
9040
|
|
|
$attributes[$name]=$this->parseAttribute(substr($value,1,strlen($value)-2)); |
9041
|
|
|
else |
9042
|
|
|
$attributes[$name]=$this->parseAttribute($value); |
9043
|
|
|
} |
9044
|
|
|
} |
9045
|
|
|
return $attributes; |
9046
|
|
|
} |
9047
|
|
|
protected function parseTemplateProperty($content,$offset) |
9048
|
|
|
{ |
9049
|
|
|
$line=$this->_startingLine+count(explode("\n",substr($this->_content,0,$offset)))-1; |
9050
|
|
|
return array(self::CONFIG_TEMPLATE,new TTemplate($content,$this->_contextPath,$this->_tplFile,$line,false)); |
9051
|
|
|
} |
9052
|
|
|
protected function parseAttribute($value) |
9053
|
|
|
{ |
9054
|
|
|
if(($n=preg_match_all('/<%[#=].*?%>/msS',$value,$matches,PREG_OFFSET_CAPTURE))>0) |
9055
|
|
|
{ |
9056
|
|
|
$isDataBind=false; |
9057
|
|
|
$textStart=0; |
9058
|
|
|
$expr=''; |
9059
|
|
|
for($i=0;$i<$n;++$i) |
9060
|
|
|
{ |
9061
|
|
|
$match=$matches[0][$i]; |
9062
|
|
|
$token=$match[0]; |
9063
|
|
|
$offset=$match[1]; |
9064
|
|
|
$length=strlen($token); |
9065
|
|
|
if($token[2]==='#') |
9066
|
|
|
$isDataBind=true; |
9067
|
|
|
if($offset>$textStart) |
9068
|
|
|
$expr.=".'".strtr(substr($value,$textStart,$offset-$textStart),array("'"=>"\\'","\\"=>"\\\\"))."'"; |
9069
|
|
|
$expr.='.('.substr($token,3,$length-5).')'; |
9070
|
|
|
$textStart=$offset+$length; |
9071
|
|
|
} |
9072
|
|
|
$length=strlen($value); |
9073
|
|
|
if($length>$textStart) |
9074
|
|
|
$expr.=".'".strtr(substr($value,$textStart,$length-$textStart),array("'"=>"\\'","\\"=>"\\\\"))."'"; |
9075
|
|
|
if($isDataBind) |
9076
|
|
|
return array(self::CONFIG_DATABIND,ltrim($expr,'.')); |
9077
|
|
|
else |
9078
|
|
|
return array(self::CONFIG_EXPRESSION,ltrim($expr,'.')); |
9079
|
|
|
} |
9080
|
|
|
else if(preg_match('/\\s*(<%~.*?%>|<%\\$.*?%>|<%\\[.*?\\]%>|<%\/.*?%>)\\s*/msS',$value,$matches) && $matches[0]===$value) |
9081
|
|
|
{ |
9082
|
|
|
$value=$matches[1]; |
9083
|
|
|
if($value[2]==='~') |
9084
|
|
|
return array(self::CONFIG_ASSET,trim(substr($value,3,strlen($value)-5))); |
9085
|
|
|
elseif($value[2]==='[') |
9086
|
|
|
return array(self::CONFIG_LOCALIZATION,trim(substr($value,3,strlen($value)-6))); |
9087
|
|
|
elseif($value[2]==='$') |
9088
|
|
|
return array(self::CONFIG_PARAMETER,trim(substr($value,3,strlen($value)-5))); |
9089
|
|
|
elseif($value[2]==='/') { |
9090
|
|
|
$literal = trim(substr($value,3,strlen($value)-5)); |
9091
|
|
|
return array(self::CONFIG_EXPRESSION,"rtrim(dirname(\$this->getApplication()->getRequest()->getApplicationUrl()), '\/').'/$literal'"); |
9092
|
|
|
} |
9093
|
|
|
} |
9094
|
|
|
else |
9095
|
|
|
return $value; |
9096
|
|
|
} |
9097
|
|
|
protected function validateAttributes($type,$attributes) |
9098
|
|
|
{ |
9099
|
|
|
Prado::using($type); |
9100
|
|
|
if(($pos=strrpos($type,'.'))!==false) |
9101
|
|
|
$className=substr($type,$pos+1); |
9102
|
|
|
else |
9103
|
|
|
$className=$type; |
9104
|
|
|
$class=new ReflectionClass($className); |
9105
|
|
|
if(is_subclass_of($className,'TControl') || $className==='TControl') |
9106
|
|
|
{ |
9107
|
|
|
foreach($attributes as $name=>$att) |
9108
|
|
|
{ |
9109
|
|
|
if(($pos=strpos($name,'.'))!==false) |
9110
|
|
|
{ |
9111
|
|
|
$subname=substr($name,0,$pos); |
9112
|
|
|
if(!$class->hasMethod('get'.$subname)) |
9113
|
|
|
throw new TConfigurationException('template_property_unknown',$type,$subname); |
9114
|
|
|
} |
9115
|
|
|
else if(strncasecmp($name,'on',2)===0) |
9116
|
|
|
{ |
9117
|
|
|
if(!$class->hasMethod($name)) |
9118
|
|
|
throw new TConfigurationException('template_event_unknown',$type,$name); |
9119
|
|
|
else if(!is_string($att)) |
9120
|
|
|
throw new TConfigurationException('template_eventhandler_invalid',$type,$name); |
9121
|
|
|
} |
9122
|
|
|
else |
9123
|
|
|
{ |
9124
|
|
|
if (! ($class->hasMethod('set'.$name) || $class->hasMethod('setjs'.$name) || $this->isClassBehaviorMethod($class,'set'.$name)) ) |
9125
|
|
|
{ |
9126
|
|
|
if ($class->hasMethod('get'.$name) || $class->hasMethod('getjs'.$name)) |
9127
|
|
|
throw new TConfigurationException('template_property_readonly',$type,$name); |
9128
|
|
|
else |
9129
|
|
|
throw new TConfigurationException('template_property_unknown',$type,$name); |
9130
|
|
|
} |
9131
|
|
|
else if(is_array($att) && $att[0]!==self::CONFIG_EXPRESSION) |
9132
|
|
|
{ |
9133
|
|
|
if(strcasecmp($name,'id')===0) |
9134
|
|
|
throw new TConfigurationException('template_controlid_invalid',$type); |
9135
|
|
|
else if(strcasecmp($name,'skinid')===0) |
9136
|
|
|
throw new TConfigurationException('template_controlskinid_invalid',$type); |
9137
|
|
|
} |
9138
|
|
|
} |
9139
|
|
|
} |
9140
|
|
|
} |
9141
|
|
|
else if(is_subclass_of($className,'TComponent') || $className==='TComponent') |
9142
|
|
|
{ |
9143
|
|
|
foreach($attributes as $name=>$att) |
9144
|
|
|
{ |
9145
|
|
|
if(is_array($att) && ($att[0]===self::CONFIG_DATABIND)) |
9146
|
|
|
throw new TConfigurationException('template_databind_forbidden',$type,$name); |
9147
|
|
|
if(($pos=strpos($name,'.'))!==false) |
9148
|
|
|
{ |
9149
|
|
|
$subname=substr($name,0,$pos); |
9150
|
|
|
if(!$class->hasMethod('get'.$subname)) |
9151
|
|
|
throw new TConfigurationException('template_property_unknown',$type,$subname); |
9152
|
|
|
} |
9153
|
|
|
else if(strncasecmp($name,'on',2)===0) |
9154
|
|
|
throw new TConfigurationException('template_event_forbidden',$type,$name); |
9155
|
|
|
else |
9156
|
|
|
{ |
9157
|
|
|
if(strcasecmp($name,'id')!==0 && !($class->hasMethod('set'.$name) || $this->isClassBehaviorMethod($class,'set'.$name))) |
9158
|
|
|
{ |
9159
|
|
|
if($class->hasMethod('get'.$name)) |
9160
|
|
|
throw new TConfigurationException('template_property_readonly',$type,$name); |
9161
|
|
|
else |
9162
|
|
|
throw new TConfigurationException('template_property_unknown',$type,$name); |
9163
|
|
|
} |
9164
|
|
|
} |
9165
|
|
|
} |
9166
|
|
|
} |
9167
|
|
|
else |
9168
|
|
|
throw new TConfigurationException('template_component_required',$type); |
9169
|
|
|
} |
9170
|
|
|
public function getIncludedFiles() |
9171
|
|
|
{ |
9172
|
|
|
return $this->_includedFiles; |
9173
|
|
|
} |
9174
|
|
|
protected function handleException($e,$line,$input=null) |
9175
|
|
|
{ |
9176
|
|
|
$srcFile=$this->_tplFile; |
9177
|
|
|
if(($n=count($this->_includedFiles))>0) { |
9178
|
|
|
for($i=$n-1;$i>=0;--$i) |
9179
|
|
|
{ |
9180
|
|
|
if($this->_includeAtLine[$i]<=$line) |
9181
|
|
|
{ |
9182
|
|
|
if($line<$this->_includeAtLine[$i]+$this->_includeLines[$i]) |
9183
|
|
|
{ |
9184
|
|
|
$line=$line-$this->_includeAtLine[$i]+1; |
9185
|
|
|
$srcFile=$this->_includedFiles[$i]; |
9186
|
|
|
break; |
9187
|
|
|
} |
9188
|
|
|
else |
9189
|
|
|
$line=$line-$this->_includeLines[$i]+1; |
9190
|
|
|
} |
9191
|
|
|
} |
9192
|
|
|
} |
9193
|
|
|
$exception=new TTemplateException('template_format_invalid',$e->getMessage()); |
9194
|
|
|
$exception->setLineNumber($line); |
9195
|
|
|
if(!empty($srcFile)) |
9196
|
|
|
$exception->setTemplateFile($srcFile); |
9197
|
|
|
else |
9198
|
|
|
$exception->setTemplateSource($input); |
9199
|
|
|
throw $exception; |
9200
|
|
|
} |
9201
|
|
|
protected function preprocess($input) |
9202
|
|
|
{ |
9203
|
|
|
if($n=preg_match_all('/<%include(.*?)%>/',$input,$matches,PREG_SET_ORDER|PREG_OFFSET_CAPTURE)) |
9204
|
|
|
{ |
9205
|
|
|
for($i=0;$i<$n;++$i) |
9206
|
|
|
{ |
9207
|
|
|
$filePath=Prado::getPathOfNamespace(trim($matches[$i][1][0]),TTemplateManager::TEMPLATE_FILE_EXT); |
9208
|
|
|
if($filePath!==null && is_file($filePath)) |
9209
|
|
|
$this->_includedFiles[]=$filePath; |
9210
|
|
|
else |
9211
|
|
|
{ |
9212
|
|
|
$errorLine=count(explode("\n",substr($input,0,$matches[$i][0][1]+1))); |
9213
|
|
|
$this->handleException(new TConfigurationException('template_include_invalid',trim($matches[$i][1][0])),$errorLine,$input); |
9214
|
|
|
} |
9215
|
|
|
} |
9216
|
|
|
$base=0; |
9217
|
|
|
for($i=0;$i<$n;++$i) |
9218
|
|
|
{ |
9219
|
|
|
$ext=file_get_contents($this->_includedFiles[$i]); |
9220
|
|
|
$length=strlen($matches[$i][0][0]); |
9221
|
|
|
$offset=$base+$matches[$i][0][1]; |
9222
|
|
|
$this->_includeAtLine[$i]=count(explode("\n",substr($input,0,$offset))); |
9223
|
|
|
$this->_includeLines[$i]=count(explode("\n",$ext)); |
9224
|
|
|
$input=substr_replace($input,$ext,$offset,$length); |
9225
|
|
|
$base+=strlen($ext)-$length; |
9226
|
|
|
} |
9227
|
|
|
} |
9228
|
|
|
return $input; |
9229
|
|
|
} |
9230
|
|
|
protected function isClassBehaviorMethod(ReflectionClass $class,$method) |
9231
|
|
|
{ |
9232
|
|
|
$component=new ReflectionClass('TComponent'); |
9233
|
|
|
$behaviors=$component->getStaticProperties(); |
9234
|
|
|
if(!isset($behaviors['_um'])) |
9235
|
|
|
return false; |
9236
|
|
|
foreach($behaviors['_um'] as $name=>$list) |
|
|
|
|
9237
|
|
|
{ |
9238
|
|
|
if(strtolower($class->getShortName())!==$name && !$class->isSubclassOf($name)) continue; |
9239
|
|
|
foreach($list as $param) |
9240
|
|
|
{ |
9241
|
|
|
if(method_exists($param->getBehavior(),$method)) |
9242
|
|
|
return true; |
9243
|
|
|
} |
9244
|
|
|
} |
9245
|
|
|
return false; |
9246
|
|
|
} |
9247
|
|
|
} |
9248
|
|
|
class TThemeManager extends TModule |
9249
|
|
|
{ |
9250
|
|
|
const DEFAULT_BASEPATH='themes'; |
9251
|
|
|
const DEFAULT_THEMECLASS = 'TTheme'; |
9252
|
|
|
private $_themeClass=self::DEFAULT_THEMECLASS; |
9253
|
|
|
private $_initialized=false; |
9254
|
|
|
private $_basePath=null; |
9255
|
|
|
private $_baseUrl=null; |
9256
|
|
|
public function init($config) |
9257
|
|
|
{ |
9258
|
|
|
$this->_initialized=true; |
9259
|
|
|
$service=$this->getService(); |
9260
|
|
|
if($service instanceof TPageService) |
9261
|
|
|
$service->setThemeManager($this); |
9262
|
|
|
else |
9263
|
|
|
throw new TConfigurationException('thememanager_service_unavailable'); |
9264
|
|
|
} |
9265
|
|
|
public function getTheme($name) |
9266
|
|
|
{ |
9267
|
|
|
$themePath=$this->getBasePath().DIRECTORY_SEPARATOR.$name; |
9268
|
|
|
$themeUrl=rtrim($this->getBaseUrl(),'/').'/'.$name; |
9269
|
|
|
return Prado::createComponent($this->getThemeClass(), $themePath, $themeUrl); |
9270
|
|
|
} |
9271
|
|
|
public function setThemeClass($class) { |
9272
|
|
|
$this->_themeClass = $class===null ? self::DEFAULT_THEMECLASS : (string)$class; |
9273
|
|
|
} |
9274
|
|
|
public function getThemeClass() { |
9275
|
|
|
return $this->_themeClass; |
9276
|
|
|
} |
9277
|
|
|
public function getAvailableThemes() |
9278
|
|
|
{ |
9279
|
|
|
$themes=array(); |
9280
|
|
|
$basePath=$this->getBasePath(); |
9281
|
|
|
$folder=@opendir($basePath); |
9282
|
|
|
while($file=@readdir($folder)) |
9283
|
|
|
{ |
9284
|
|
|
if($file!=='.' && $file!=='..' && $file!=='.svn' && is_dir($basePath.DIRECTORY_SEPARATOR.$file)) |
9285
|
|
|
$themes[]=$file; |
9286
|
|
|
} |
9287
|
|
|
closedir($folder); |
9288
|
|
|
return $themes; |
9289
|
|
|
} |
9290
|
|
|
public function getBasePath() |
9291
|
|
|
{ |
9292
|
|
|
if($this->_basePath===null) |
9293
|
|
|
{ |
9294
|
|
|
$this->_basePath=dirname($this->getRequest()->getApplicationFilePath()).DIRECTORY_SEPARATOR.self::DEFAULT_BASEPATH; |
9295
|
|
|
if(($basePath=realpath($this->_basePath))===false || !is_dir($basePath)) |
9296
|
|
|
throw new TConfigurationException('thememanager_basepath_invalid2',$this->_basePath); |
9297
|
|
|
$this->_basePath=$basePath; |
9298
|
|
|
} |
9299
|
|
|
return $this->_basePath; |
9300
|
|
|
} |
9301
|
|
|
public function setBasePath($value) |
9302
|
|
|
{ |
9303
|
|
|
if($this->_initialized) |
9304
|
|
|
throw new TInvalidOperationException('thememanager_basepath_unchangeable'); |
9305
|
|
|
else |
9306
|
|
|
{ |
9307
|
|
|
$this->_basePath=Prado::getPathOfNamespace($value); |
9308
|
|
|
if($this->_basePath===null || !is_dir($this->_basePath)) |
9309
|
|
|
throw new TInvalidDataValueException('thememanager_basepath_invalid',$value); |
9310
|
|
|
} |
9311
|
|
|
} |
9312
|
|
|
public function getBaseUrl() |
9313
|
|
|
{ |
9314
|
|
|
if($this->_baseUrl===null) |
9315
|
|
|
{ |
9316
|
|
|
$appPath=dirname($this->getRequest()->getApplicationFilePath()); |
9317
|
|
|
$basePath=$this->getBasePath(); |
9318
|
|
|
if(strpos($basePath,$appPath)===false) |
9319
|
|
|
throw new TConfigurationException('thememanager_baseurl_required'); |
9320
|
|
|
$appUrl=rtrim(dirname($this->getRequest()->getApplicationUrl()),'/\\'); |
9321
|
|
|
$this->_baseUrl=$appUrl.strtr(substr($basePath,strlen($appPath)),'\\','/'); |
9322
|
|
|
} |
9323
|
|
|
return $this->_baseUrl; |
9324
|
|
|
} |
9325
|
|
|
public function setBaseUrl($value) |
9326
|
|
|
{ |
9327
|
|
|
$this->_baseUrl=rtrim($value,'/'); |
9328
|
|
|
} |
9329
|
|
|
} |
9330
|
|
|
class TTheme extends TApplicationComponent implements ITheme |
9331
|
|
|
{ |
9332
|
|
|
const THEME_CACHE_PREFIX='prado:theme:'; |
9333
|
|
|
const SKIN_FILE_EXT='.skin'; |
9334
|
|
|
private $_themePath; |
9335
|
|
|
private $_themeUrl; |
9336
|
|
|
private $_skins=null; |
9337
|
|
|
private $_name=''; |
9338
|
|
|
private $_cssFiles=array(); |
9339
|
|
|
private $_jsFiles=array(); |
9340
|
|
|
public function __construct($themePath,$themeUrl) |
9341
|
|
|
{ |
9342
|
|
|
$this->_themeUrl=$themeUrl; |
9343
|
|
|
$this->_themePath=realpath($themePath); |
9344
|
|
|
$this->_name=basename($themePath); |
9345
|
|
|
$cacheValid=false; |
9346
|
|
|
if(($cache=$this->getApplication()->getCache())!==null) |
9347
|
|
|
{ |
9348
|
|
|
$array=$cache->get(self::THEME_CACHE_PREFIX.$themePath); |
9349
|
|
|
if(is_array($array)) |
9350
|
|
|
{ |
9351
|
|
|
list($skins,$cssFiles,$jsFiles,$timestamp)=$array; |
9352
|
|
|
if($this->getApplication()->getMode()!==TApplicationMode::Performance) |
9353
|
|
|
{ |
9354
|
|
|
if(($dir=opendir($themePath))===false) |
9355
|
|
|
throw new TIOException('theme_path_inexistent',$themePath); |
9356
|
|
|
$cacheValid=true; |
9357
|
|
|
while(($file=readdir($dir))!==false) |
9358
|
|
|
{ |
9359
|
|
|
if($file==='.' || $file==='..') |
9360
|
|
|
continue; |
9361
|
|
|
else if(basename($file,'.css')!==$file) |
9362
|
|
|
$this->_cssFiles[]=$themeUrl.'/'.$file; |
9363
|
|
|
else if(basename($file,'.js')!==$file) |
9364
|
|
|
$this->_jsFiles[]=$themeUrl.'/'.$file; |
9365
|
|
|
else if(basename($file,self::SKIN_FILE_EXT)!==$file && filemtime($themePath.DIRECTORY_SEPARATOR.$file)>$timestamp) |
9366
|
|
|
{ |
9367
|
|
|
$cacheValid=false; |
9368
|
|
|
break; |
9369
|
|
|
} |
9370
|
|
|
} |
9371
|
|
|
closedir($dir); |
9372
|
|
|
if($cacheValid) |
9373
|
|
|
$this->_skins=$skins; |
9374
|
|
|
} |
9375
|
|
|
else |
9376
|
|
|
{ |
9377
|
|
|
$cacheValid=true; |
9378
|
|
|
$this->_cssFiles=$cssFiles; |
9379
|
|
|
$this->_jsFiles=$jsFiles; |
9380
|
|
|
$this->_skins=$skins; |
9381
|
|
|
} |
9382
|
|
|
} |
9383
|
|
|
} |
9384
|
|
|
if(!$cacheValid) |
9385
|
|
|
{ |
9386
|
|
|
$this->_cssFiles=array(); |
9387
|
|
|
$this->_jsFiles=array(); |
9388
|
|
|
$this->_skins=array(); |
9389
|
|
|
if(($dir=opendir($themePath))===false) |
9390
|
|
|
throw new TIOException('theme_path_inexistent',$themePath); |
9391
|
|
|
while(($file=readdir($dir))!==false) |
9392
|
|
|
{ |
9393
|
|
|
if($file==='.' || $file==='..') |
9394
|
|
|
continue; |
9395
|
|
|
else if(basename($file,'.css')!==$file) |
9396
|
|
|
$this->_cssFiles[]=$themeUrl.'/'.$file; |
9397
|
|
|
else if(basename($file,'.js')!==$file) |
9398
|
|
|
$this->_jsFiles[]=$themeUrl.'/'.$file; |
9399
|
|
|
else if(basename($file,self::SKIN_FILE_EXT)!==$file) |
9400
|
|
|
{ |
9401
|
|
|
$template=new TTemplate(file_get_contents($themePath.'/'.$file),$themePath,$themePath.'/'.$file); |
9402
|
|
|
foreach($template->getItems() as $skin) |
9403
|
|
|
{ |
9404
|
|
|
if(!isset($skin[2])) continue; |
9405
|
|
|
else if($skin[0]!==-1) |
9406
|
|
|
throw new TConfigurationException('theme_control_nested',$skin[1],dirname($themePath)); |
9407
|
|
|
$type=$skin[1]; |
9408
|
|
|
$id=isset($skin[2]['skinid'])?$skin[2]['skinid']:0; |
9409
|
|
|
unset($skin[2]['skinid']); |
9410
|
|
|
if(isset($this->_skins[$type][$id])) |
9411
|
|
|
throw new TConfigurationException('theme_skinid_duplicated',$type,$id,dirname($themePath)); |
9412
|
|
|
$this->_skins[$type][$id]=$skin[2]; |
9413
|
|
|
} |
9414
|
|
|
} |
9415
|
|
|
} |
9416
|
|
|
closedir($dir); |
9417
|
|
|
sort($this->_cssFiles); |
9418
|
|
|
sort($this->_jsFiles); |
9419
|
|
|
if($cache!==null) |
9420
|
|
|
$cache->set(self::THEME_CACHE_PREFIX.$themePath,array($this->_skins,$this->_cssFiles,$this->_jsFiles,time())); |
9421
|
|
|
} |
9422
|
|
|
} |
9423
|
|
|
public function getName() |
9424
|
|
|
{ |
9425
|
|
|
return $this->_name; |
9426
|
|
|
} |
9427
|
|
|
protected function setName($value) |
9428
|
|
|
{ |
9429
|
|
|
$this->_name = $value; |
9430
|
|
|
} |
9431
|
|
|
public function getBaseUrl() |
9432
|
|
|
{ |
9433
|
|
|
return $this->_themeUrl; |
9434
|
|
|
} |
9435
|
|
|
protected function setBaseUrl($value) |
9436
|
|
|
{ |
9437
|
|
|
$this->_themeUrl=rtrim($value,'/'); |
9438
|
|
|
} |
9439
|
|
|
public function getBasePath() |
9440
|
|
|
{ |
9441
|
|
|
return $this->_themePath; |
9442
|
|
|
} |
9443
|
|
|
protected function setBasePath($value) |
9444
|
|
|
{ |
9445
|
|
|
$this->_themePath=$value; |
9446
|
|
|
} |
9447
|
|
|
public function getSkins() |
9448
|
|
|
{ |
9449
|
|
|
return $this->_skins; |
9450
|
|
|
} |
9451
|
|
|
protected function setSkins($value) |
9452
|
|
|
{ |
9453
|
|
|
$this->_skins = $value; |
9454
|
|
|
} |
9455
|
|
|
public function applySkin($control) |
9456
|
|
|
{ |
9457
|
|
|
$type=get_class($control); |
9458
|
|
|
if(($id=$control->getSkinID())==='') |
9459
|
|
|
$id=0; |
9460
|
|
|
if(isset($this->_skins[$type][$id])) |
9461
|
|
|
{ |
9462
|
|
|
foreach($this->_skins[$type][$id] as $name=>$value) |
9463
|
|
|
{ |
9464
|
|
|
if(is_array($value)) |
9465
|
|
|
{ |
9466
|
|
|
switch($value[0]) |
9467
|
|
|
{ |
9468
|
|
|
case TTemplate::CONFIG_EXPRESSION: |
9469
|
|
|
$value=$this->evaluateExpression($value[1]); |
9470
|
|
|
break; |
9471
|
|
|
case TTemplate::CONFIG_ASSET: |
9472
|
|
|
$value=$this->_themeUrl.'/'.ltrim($value[1],'/'); |
9473
|
|
|
break; |
9474
|
|
|
case TTemplate::CONFIG_DATABIND: |
9475
|
|
|
$control->bindProperty($name,$value[1]); |
9476
|
|
|
break; |
9477
|
|
|
case TTemplate::CONFIG_PARAMETER: |
9478
|
|
|
$control->setSubProperty($name,$this->getApplication()->getParameters()->itemAt($value[1])); |
9479
|
|
|
break; |
9480
|
|
|
case TTemplate::CONFIG_TEMPLATE: |
9481
|
|
|
$control->setSubProperty($name,$value[1]); |
9482
|
|
|
break; |
9483
|
|
|
case TTemplate::CONFIG_LOCALIZATION: |
9484
|
|
|
$control->setSubProperty($name,Prado::localize($value[1])); |
9485
|
|
|
break; |
9486
|
|
|
default: |
9487
|
|
|
throw new TConfigurationException('theme_tag_unexpected',$name,$value[0]); |
9488
|
|
|
break; |
|
|
|
|
9489
|
|
|
} |
9490
|
|
|
} |
9491
|
|
|
if(!is_array($value)) |
9492
|
|
|
{ |
9493
|
|
|
if(strpos($name,'.')===false) { |
9494
|
|
|
if($control->hasProperty($name)) |
9495
|
|
|
{ |
9496
|
|
|
if($control->canSetProperty($name)) |
9497
|
|
|
{ |
9498
|
|
|
$setter='set'.$name; |
9499
|
|
|
$control->$setter($value); |
9500
|
|
|
} |
9501
|
|
|
else |
9502
|
|
|
throw new TConfigurationException('theme_property_readonly',$type,$name); |
9503
|
|
|
} |
9504
|
|
|
else |
9505
|
|
|
throw new TConfigurationException('theme_property_undefined',$type,$name); |
9506
|
|
|
} |
9507
|
|
|
else $control->setSubProperty($name,$value); |
9508
|
|
|
} |
9509
|
|
|
} |
9510
|
|
|
return true; |
9511
|
|
|
} |
9512
|
|
|
else |
9513
|
|
|
return false; |
9514
|
|
|
} |
9515
|
|
|
public function getStyleSheetFiles() |
9516
|
|
|
{ |
9517
|
|
|
return $this->_cssFiles; |
9518
|
|
|
} |
9519
|
|
|
protected function setStyleSheetFiles($value) |
9520
|
|
|
{ |
9521
|
|
|
$this->_cssFiles=$value; |
9522
|
|
|
} |
9523
|
|
|
public function getJavaScriptFiles() |
9524
|
|
|
{ |
9525
|
|
|
return $this->_jsFiles; |
9526
|
|
|
} |
9527
|
|
|
protected function setJavaScriptFiles($value) |
9528
|
|
|
{ |
9529
|
|
|
$this->_jsFiles=$value; |
9530
|
|
|
} |
9531
|
|
|
} |
9532
|
|
|
class TPageService extends TService |
9533
|
|
|
{ |
9534
|
|
|
const CONFIG_FILE_XML='config.xml'; |
9535
|
|
|
const CONFIG_FILE_PHP='config.php'; |
9536
|
|
|
const DEFAULT_BASEPATH='Pages'; |
9537
|
|
|
const FALLBACK_BASEPATH='pages'; |
9538
|
|
|
const CONFIG_CACHE_PREFIX='prado:pageservice:'; |
9539
|
|
|
const PAGE_FILE_EXT='.page'; |
9540
|
|
|
private $_basePath=null; |
9541
|
|
|
private $_basePageClass='TPage'; |
9542
|
|
|
private $_clientScriptManagerClass='System.Web.UI.TClientScriptManager'; |
9543
|
|
|
private $_defaultPage='Home'; |
9544
|
|
|
private $_pagePath=null; |
9545
|
|
|
private $_page=null; |
9546
|
|
|
private $_properties=array(); |
9547
|
|
|
private $_initialized=false; |
9548
|
|
|
private $_themeManager=null; |
9549
|
|
|
private $_templateManager=null; |
9550
|
|
|
public function init($config) |
9551
|
|
|
{ |
9552
|
|
|
$pageConfig=$this->loadPageConfig($config); |
9553
|
|
|
$this->initPageContext($pageConfig); |
9554
|
|
|
$this->_initialized=true; |
9555
|
|
|
} |
9556
|
|
|
protected function initPageContext($pageConfig) |
9557
|
|
|
{ |
9558
|
|
|
$application=$this->getApplication(); |
9559
|
|
|
foreach($pageConfig->getApplicationConfigurations() as $appConfig) |
9560
|
|
|
$application->applyConfiguration($appConfig); |
9561
|
|
|
$this->applyConfiguration($pageConfig); |
9562
|
|
|
} |
9563
|
|
|
protected function applyConfiguration($config) |
9564
|
|
|
{ |
9565
|
|
|
$this->_properties=array_merge($this->_properties, $config->getProperties()); |
9566
|
|
|
$this->getApplication()->getAuthorizationRules()->mergeWith($config->getRules()); |
9567
|
|
|
$pagePath=$this->getRequestedPagePath(); |
9568
|
|
|
foreach($config->getExternalConfigurations() as $filePath=>$params) |
9569
|
|
|
{ |
9570
|
|
|
list($configPagePath,$condition)=$params; |
9571
|
|
|
if($condition!==true) |
9572
|
|
|
$condition=$this->evaluateExpression($condition); |
9573
|
|
|
if($condition) |
9574
|
|
|
{ |
9575
|
|
|
if(($path=Prado::getPathOfNamespace($filePath,Prado::getApplication()->getConfigurationFileExt()))===null || !is_file($path)) |
9576
|
|
|
throw new TConfigurationException('pageservice_includefile_invalid',$filePath); |
9577
|
|
|
$c=new TPageConfiguration($pagePath); |
9578
|
|
|
$c->loadFromFile($path,$configPagePath); |
9579
|
|
|
$this->applyConfiguration($c); |
9580
|
|
|
} |
9581
|
|
|
} |
9582
|
|
|
} |
9583
|
|
|
protected function determineRequestedPagePath() |
9584
|
|
|
{ |
9585
|
|
|
$pagePath=$this->getRequest()->getServiceParameter(); |
9586
|
|
|
if(empty($pagePath)) |
9587
|
|
|
$pagePath=$this->getDefaultPage(); |
9588
|
|
|
return $pagePath; |
9589
|
|
|
} |
9590
|
|
|
protected function loadPageConfig($config) |
9591
|
|
|
{ |
9592
|
|
|
$application=$this->getApplication(); |
9593
|
|
|
$pagePath=$this->getRequestedPagePath(); |
9594
|
|
|
if(($cache=$application->getCache())===null) |
9595
|
|
|
{ |
9596
|
|
|
$pageConfig=new TPageConfiguration($pagePath); |
9597
|
|
|
if($config!==null) |
9598
|
|
|
{ |
9599
|
|
|
if($application->getConfigurationType()==TApplication::CONFIG_TYPE_PHP) |
9600
|
|
|
$pageConfig->loadPageConfigurationFromPhp($config,$application->getBasePath(),''); |
9601
|
|
|
else |
9602
|
|
|
$pageConfig->loadPageConfigurationFromXml($config,$application->getBasePath(),''); |
9603
|
|
|
} |
9604
|
|
|
$pageConfig->loadFromFiles($this->getBasePath()); |
9605
|
|
|
} |
9606
|
|
|
else |
9607
|
|
|
{ |
9608
|
|
|
$configCached=true; |
9609
|
|
|
$currentTimestamp=array(); |
9610
|
|
|
$arr=$cache->get(self::CONFIG_CACHE_PREFIX.$this->getID().$pagePath); |
9611
|
|
|
if(is_array($arr)) |
9612
|
|
|
{ |
9613
|
|
|
list($pageConfig,$timestamps)=$arr; |
9614
|
|
|
if($application->getMode()!==TApplicationMode::Performance) |
9615
|
|
|
{ |
9616
|
|
|
foreach($timestamps as $fileName=>$timestamp) |
9617
|
|
|
{ |
9618
|
|
|
if($fileName===0) { |
9619
|
|
|
$appConfigFile=$application->getConfigurationFile(); |
9620
|
|
|
$currentTimestamp[0]=$appConfigFile===null?0:@filemtime($appConfigFile); |
9621
|
|
|
if($currentTimestamp[0]>$timestamp || ($timestamp>0 && !$currentTimestamp[0])) |
9622
|
|
|
$configCached=false; |
9623
|
|
|
} |
9624
|
|
|
else |
9625
|
|
|
{ |
9626
|
|
|
$currentTimestamp[$fileName]=@filemtime($fileName); |
9627
|
|
|
if($currentTimestamp[$fileName]>$timestamp || ($timestamp>0 && !$currentTimestamp[$fileName])) |
9628
|
|
|
$configCached=false; |
9629
|
|
|
} |
9630
|
|
|
} |
9631
|
|
|
} |
9632
|
|
|
} |
9633
|
|
|
else |
9634
|
|
|
{ |
9635
|
|
|
$configCached=false; |
9636
|
|
|
$paths=explode('.',$pagePath); |
9637
|
|
|
$configPath=$this->getBasePath(); |
9638
|
|
|
$fileName = $this->getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP |
9639
|
|
|
? self::CONFIG_FILE_PHP |
9640
|
|
|
: self::CONFIG_FILE_XML; |
9641
|
|
|
foreach($paths as $path) |
9642
|
|
|
{ |
9643
|
|
|
$configFile=$configPath.DIRECTORY_SEPARATOR.$fileName; |
9644
|
|
|
$currentTimestamp[$configFile]=@filemtime($configFile); |
9645
|
|
|
$configPath.=DIRECTORY_SEPARATOR.$path; |
9646
|
|
|
} |
9647
|
|
|
$appConfigFile=$application->getConfigurationFile(); |
9648
|
|
|
$currentTimestamp[0]=$appConfigFile===null?0:@filemtime($appConfigFile); |
9649
|
|
|
} |
9650
|
|
|
if(!$configCached) |
9651
|
|
|
{ |
9652
|
|
|
$pageConfig=new TPageConfiguration($pagePath); |
9653
|
|
|
if($config!==null) |
9654
|
|
|
{ |
9655
|
|
|
if($application->getConfigurationType()==TApplication::CONFIG_TYPE_PHP) |
9656
|
|
|
$pageConfig->loadPageConfigurationFromPhp($config,$application->getBasePath(),''); |
9657
|
|
|
else |
9658
|
|
|
$pageConfig->loadPageConfigurationFromXml($config,$application->getBasePath(),''); |
9659
|
|
|
} |
9660
|
|
|
$pageConfig->loadFromFiles($this->getBasePath()); |
9661
|
|
|
$cache->set(self::CONFIG_CACHE_PREFIX.$this->getID().$pagePath,array($pageConfig,$currentTimestamp)); |
9662
|
|
|
} |
9663
|
|
|
} |
9664
|
|
|
return $pageConfig; |
|
|
|
|
9665
|
|
|
} |
9666
|
|
|
public function getTemplateManager() |
9667
|
|
|
{ |
9668
|
|
|
if(!$this->_templateManager) |
9669
|
|
|
{ |
9670
|
|
|
$this->_templateManager=new TTemplateManager; |
9671
|
|
|
$this->_templateManager->init(null); |
9672
|
|
|
} |
9673
|
|
|
return $this->_templateManager; |
9674
|
|
|
} |
9675
|
|
|
public function setTemplateManager(TTemplateManager $value) |
9676
|
|
|
{ |
9677
|
|
|
$this->_templateManager=$value; |
9678
|
|
|
} |
9679
|
|
|
public function getThemeManager() |
9680
|
|
|
{ |
9681
|
|
|
if(!$this->_themeManager) |
9682
|
|
|
{ |
9683
|
|
|
$this->_themeManager=new TThemeManager; |
9684
|
|
|
$this->_themeManager->init(null); |
9685
|
|
|
} |
9686
|
|
|
return $this->_themeManager; |
9687
|
|
|
} |
9688
|
|
|
public function setThemeManager(TThemeManager $value) |
9689
|
|
|
{ |
9690
|
|
|
$this->_themeManager=$value; |
9691
|
|
|
} |
9692
|
|
|
public function getRequestedPagePath() |
9693
|
|
|
{ |
9694
|
|
|
if($this->_pagePath===null) |
9695
|
|
|
{ |
9696
|
|
|
$this->_pagePath=strtr($this->determineRequestedPagePath(),'/\\','..'); |
9697
|
|
|
if(empty($this->_pagePath)) |
9698
|
|
|
throw new THttpException(404,'pageservice_page_required'); |
9699
|
|
|
} |
9700
|
|
|
return $this->_pagePath; |
9701
|
|
|
} |
9702
|
|
|
public function getRequestedPage() |
9703
|
|
|
{ |
9704
|
|
|
return $this->_page; |
9705
|
|
|
} |
9706
|
|
|
public function getDefaultPage() |
9707
|
|
|
{ |
9708
|
|
|
return $this->_defaultPage; |
9709
|
|
|
} |
9710
|
|
|
public function setDefaultPage($value) |
9711
|
|
|
{ |
9712
|
|
|
if($this->_initialized) |
9713
|
|
|
throw new TInvalidOperationException('pageservice_defaultpage_unchangeable'); |
9714
|
|
|
else |
9715
|
|
|
$this->_defaultPage=$value; |
9716
|
|
|
} |
9717
|
|
|
public function getDefaultPageUrl() |
9718
|
|
|
{ |
9719
|
|
|
return $this->constructUrl($this->getDefaultPage()); |
9720
|
|
|
} |
9721
|
|
|
public function getBasePath() |
9722
|
|
|
{ |
9723
|
|
|
if($this->_basePath===null) |
9724
|
|
|
{ |
9725
|
|
|
$basePath=$this->getApplication()->getBasePath().DIRECTORY_SEPARATOR.self::DEFAULT_BASEPATH; |
9726
|
|
|
if(($this->_basePath=realpath($basePath))===false || !is_dir($this->_basePath)) |
9727
|
|
|
{ |
9728
|
|
|
$basePath=$this->getApplication()->getBasePath().DIRECTORY_SEPARATOR.self::FALLBACK_BASEPATH; |
9729
|
|
|
if(($this->_basePath=realpath($basePath))===false || !is_dir($this->_basePath)) |
9730
|
|
|
throw new TConfigurationException('pageservice_basepath_invalid',$basePath); |
9731
|
|
|
} |
9732
|
|
|
} |
9733
|
|
|
return $this->_basePath; |
9734
|
|
|
} |
9735
|
|
|
public function setBasePath($value) |
9736
|
|
|
{ |
9737
|
|
|
if($this->_initialized) |
9738
|
|
|
throw new TInvalidOperationException('pageservice_basepath_unchangeable'); |
9739
|
|
|
else if(($path=Prado::getPathOfNamespace($value))===null || !is_dir($path)) |
9740
|
|
|
throw new TConfigurationException('pageservice_basepath_invalid',$value); |
9741
|
|
|
$this->_basePath=realpath($path); |
9742
|
|
|
} |
9743
|
|
|
public function setBasePageClass($value) |
9744
|
|
|
{ |
9745
|
|
|
$this->_basePageClass=$value; |
9746
|
|
|
} |
9747
|
|
|
public function getBasePageClass() |
9748
|
|
|
{ |
9749
|
|
|
return $this->_basePageClass; |
9750
|
|
|
} |
9751
|
|
|
public function setClientScriptManagerClass($value) |
9752
|
|
|
{ |
9753
|
|
|
$this->_clientScriptManagerClass=$value; |
9754
|
|
|
} |
9755
|
|
|
public function getClientScriptManagerClass() |
9756
|
|
|
{ |
9757
|
|
|
return $this->_clientScriptManagerClass; |
9758
|
|
|
} |
9759
|
|
|
public function run() |
9760
|
|
|
{ |
9761
|
|
|
$this->_page=$this->createPage($this->getRequestedPagePath()); |
9762
|
|
|
$this->runPage($this->_page,$this->_properties); |
9763
|
|
|
} |
9764
|
|
|
protected function createPage($pagePath) |
9765
|
|
|
{ |
9766
|
|
|
$path=$this->getBasePath().DIRECTORY_SEPARATOR.strtr($pagePath,'.',DIRECTORY_SEPARATOR); |
9767
|
|
|
$hasTemplateFile=is_file($path.self::PAGE_FILE_EXT); |
9768
|
|
|
$hasClassFile=is_file($path.Prado::CLASS_FILE_EXT); |
9769
|
|
|
if(!$hasTemplateFile && !$hasClassFile) |
9770
|
|
|
throw new THttpException(404,'pageservice_page_unknown',$pagePath); |
9771
|
|
|
if($hasClassFile) |
9772
|
|
|
{ |
9773
|
|
|
$className=basename($path); |
9774
|
|
|
if(!class_exists($className,false)) |
9775
|
|
|
include_once($path.Prado::CLASS_FILE_EXT); |
9776
|
|
|
} |
9777
|
|
|
else |
9778
|
|
|
{ |
9779
|
|
|
$className=$this->getBasePageClass(); |
9780
|
|
|
Prado::using($className); |
9781
|
|
|
if(($pos=strrpos($className,'.'))!==false) |
9782
|
|
|
$className=substr($className,$pos+1); |
9783
|
|
|
} |
9784
|
|
|
if(!class_exists($className,false) || ($className!=='TPage' && !is_subclass_of($className,'TPage'))) |
9785
|
|
|
throw new THttpException(404,'pageservice_page_unknown',$pagePath); |
9786
|
|
|
$page=Prado::createComponent($className); |
9787
|
|
|
$page->setPagePath($pagePath); |
9788
|
|
|
if($hasTemplateFile) |
9789
|
|
|
$page->setTemplate($this->getTemplateManager()->getTemplateByFileName($path.self::PAGE_FILE_EXT)); |
9790
|
|
|
return $page; |
9791
|
|
|
} |
9792
|
|
|
protected function runPage($page,$properties) |
9793
|
|
|
{ |
9794
|
|
|
foreach($properties as $name=>$value) |
9795
|
|
|
$page->setSubProperty($name,$value); |
9796
|
|
|
$page->run($this->getResponse()->createHtmlWriter()); |
9797
|
|
|
} |
9798
|
|
|
public function constructUrl($pagePath,$getParams=null,$encodeAmpersand=true,$encodeGetItems=true) |
9799
|
|
|
{ |
9800
|
|
|
return $this->getRequest()->constructUrl($this->getID(),$pagePath,$getParams,$encodeAmpersand,$encodeGetItems); |
9801
|
|
|
} |
9802
|
|
|
} |
9803
|
|
|
class TPageConfiguration extends TComponent |
9804
|
|
|
{ |
9805
|
|
|
private $_appConfigs=array(); |
9806
|
|
|
private $_properties=array(); |
9807
|
|
|
private $_rules=array(); |
9808
|
|
|
private $_includes=array(); |
9809
|
|
|
private $_pagePath=''; |
9810
|
|
|
public function __construct($pagePath) |
9811
|
|
|
{ |
9812
|
|
|
$this->_pagePath=$pagePath; |
9813
|
|
|
} |
9814
|
|
|
public function getExternalConfigurations() |
9815
|
|
|
{ |
9816
|
|
|
return $this->_includes; |
9817
|
|
|
} |
9818
|
|
|
public function getProperties() |
9819
|
|
|
{ |
9820
|
|
|
return $this->_properties; |
9821
|
|
|
} |
9822
|
|
|
public function getRules() |
9823
|
|
|
{ |
9824
|
|
|
return $this->_rules; |
9825
|
|
|
} |
9826
|
|
|
public function getApplicationConfigurations() |
9827
|
|
|
{ |
9828
|
|
|
return $this->_appConfigs; |
9829
|
|
|
} |
9830
|
|
|
public function loadFromFiles($basePath) |
9831
|
|
|
{ |
9832
|
|
|
$paths=explode('.',$this->_pagePath); |
9833
|
|
|
$page=array_pop($paths); |
|
|
|
|
9834
|
|
|
$path=$basePath; |
9835
|
|
|
$configPagePath=''; |
9836
|
|
|
$fileName = Prado::getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP |
9837
|
|
|
? TPageService::CONFIG_FILE_PHP |
9838
|
|
|
: TPageService::CONFIG_FILE_XML; |
9839
|
|
|
foreach($paths as $p) |
9840
|
|
|
{ |
9841
|
|
|
$this->loadFromFile($path.DIRECTORY_SEPARATOR.$fileName,$configPagePath); |
9842
|
|
|
$path.=DIRECTORY_SEPARATOR.$p; |
9843
|
|
|
if($configPagePath==='') |
9844
|
|
|
$configPagePath=$p; |
9845
|
|
|
else |
9846
|
|
|
$configPagePath.='.'.$p; |
9847
|
|
|
} |
9848
|
|
|
$this->loadFromFile($path.DIRECTORY_SEPARATOR.$fileName,$configPagePath); |
9849
|
|
|
$this->_rules=new TAuthorizationRuleCollection($this->_rules); |
|
|
|
|
9850
|
|
|
} |
9851
|
|
|
public function loadFromFile($fname,$configPagePath) |
9852
|
|
|
{ |
9853
|
|
|
if(empty($fname) || !is_file($fname)) |
9854
|
|
|
return; |
9855
|
|
|
if(Prado::getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP) |
9856
|
|
|
{ |
9857
|
|
|
$fcontent = include $fname; |
9858
|
|
|
$this->loadFromPhp($fcontent,dirname($fname),$configPagePath); |
9859
|
|
|
} |
9860
|
|
|
else |
9861
|
|
|
{ |
9862
|
|
|
$dom=new TXmlDocument; |
9863
|
|
|
if($dom->loadFromFile($fname)) |
9864
|
|
|
$this->loadFromXml($dom,dirname($fname),$configPagePath); |
9865
|
|
|
else |
9866
|
|
|
throw new TConfigurationException('pageserviceconf_file_invalid',$fname); |
9867
|
|
|
} |
9868
|
|
|
} |
9869
|
|
|
public function loadFromPhp($config,$configPath,$configPagePath) |
9870
|
|
|
{ |
9871
|
|
|
$this->loadApplicationConfigurationFromPhp($config,$configPath); |
9872
|
|
|
$this->loadPageConfigurationFromPhp($config,$configPath,$configPagePath); |
9873
|
|
|
} |
9874
|
|
|
public function loadFromXml($dom,$configPath,$configPagePath) |
9875
|
|
|
{ |
9876
|
|
|
$this->loadApplicationConfigurationFromXml($dom,$configPath); |
9877
|
|
|
$this->loadPageConfigurationFromXml($dom,$configPath,$configPagePath); |
9878
|
|
|
} |
9879
|
|
|
public function loadApplicationConfigurationFromPhp($config,$configPath) |
9880
|
|
|
{ |
9881
|
|
|
$appConfig=new TApplicationConfiguration; |
9882
|
|
|
$appConfig->loadFromPhp($config,$configPath); |
9883
|
|
|
$this->_appConfigs[]=$appConfig; |
9884
|
|
|
} |
9885
|
|
|
public function loadApplicationConfigurationFromXml($dom,$configPath) |
9886
|
|
|
{ |
9887
|
|
|
$appConfig=new TApplicationConfiguration; |
9888
|
|
|
$appConfig->loadFromXml($dom,$configPath); |
9889
|
|
|
$this->_appConfigs[]=$appConfig; |
9890
|
|
|
} |
9891
|
|
|
public function loadPageConfigurationFromPhp($config, $configPath, $configPagePath) |
9892
|
|
|
{ |
9893
|
|
|
if(isset($config['authorization']) && is_array($config['authorization'])) |
9894
|
|
|
{ |
9895
|
|
|
$rules = array(); |
9896
|
|
|
foreach($config['authorization'] as $authorization) |
9897
|
|
|
{ |
9898
|
|
|
$patterns=isset($authorization['pages'])?$authorization['pages']:''; |
9899
|
|
|
$ruleApplies=false; |
9900
|
|
|
if(empty($patterns) || trim($patterns)==='*') $ruleApplies=true; |
9901
|
|
|
else |
9902
|
|
|
{ |
9903
|
|
|
foreach(explode(',',$patterns) as $pattern) |
9904
|
|
|
{ |
9905
|
|
|
if(($pattern=trim($pattern))!=='') |
9906
|
|
|
{ |
9907
|
|
|
if($configPagePath!=='') $pattern=$configPagePath.'.'.$pattern; |
9908
|
|
|
if(strcasecmp($pattern,$this->_pagePath)===0) |
9909
|
|
|
{ |
9910
|
|
|
$ruleApplies=true; |
9911
|
|
|
break; |
9912
|
|
|
} |
9913
|
|
|
if($pattern[strlen($pattern)-1]==='*') { |
9914
|
|
|
if(strncasecmp($this->_pagePath,$pattern,strlen($pattern)-1)===0) |
9915
|
|
|
{ |
9916
|
|
|
$ruleApplies=true; |
9917
|
|
|
break; |
9918
|
|
|
} |
9919
|
|
|
} |
9920
|
|
|
} |
9921
|
|
|
} |
9922
|
|
|
} |
9923
|
|
|
if($ruleApplies) |
9924
|
|
|
{ |
9925
|
|
|
$action = isset($authorization['action'])?$authorization['action']:''; |
9926
|
|
|
$users = isset($authorization['users'])?$authorization['users']:''; |
9927
|
|
|
$roles = isset($authorization['roles'])?$authorization['roles']:''; |
9928
|
|
|
$verb = isset($authorization['verb'])?$authorization['verb']:''; |
9929
|
|
|
$ips = isset($authorization['ips'])?$authorization['ips']:''; |
9930
|
|
|
$rules[]=new TAuthorizationRule($action,$users,$roles,$verb,$ips); |
9931
|
|
|
} |
9932
|
|
|
} |
9933
|
|
|
$this->_rules=array_merge($rules,$this->_rules); |
9934
|
|
|
} |
9935
|
|
|
if(isset($config['pages']) && is_array($config['pages'])) |
9936
|
|
|
{ |
9937
|
|
|
if(isset($config['pages']['properties'])) |
9938
|
|
|
{ |
9939
|
|
|
$this->_properties = array_merge($this->_properties, $config['pages']['properties']); |
9940
|
|
|
unset($config['pages']['properties']); |
9941
|
|
|
} |
9942
|
|
|
foreach($config['pages'] as $id => $page) |
9943
|
|
|
{ |
9944
|
|
|
$properties = array(); |
9945
|
|
|
if(isset($page['properties'])) |
9946
|
|
|
{ |
9947
|
|
|
$properties=$page['properties']; |
9948
|
|
|
unset($page['properties']); |
9949
|
|
|
} |
9950
|
|
|
$matching=false; |
9951
|
|
|
$id=($configPagePath==='')?$id:$configPagePath.'.'.$id; |
9952
|
|
|
if(strcasecmp($id,$this->_pagePath)===0) |
9953
|
|
|
$matching=true; |
9954
|
|
|
else if($id[strlen($id)-1]==='*') $matching=strncasecmp($this->_pagePath,$id,strlen($id)-1)===0; |
9955
|
|
|
if($matching) |
9956
|
|
|
$this->_properties=array_merge($this->_properties,$properties); |
9957
|
|
|
} |
9958
|
|
|
} |
9959
|
|
|
if(isset($config['includes']) && is_array($config['includes'])) |
9960
|
|
|
{ |
9961
|
|
|
foreach($config['includes'] as $include) |
9962
|
|
|
{ |
9963
|
|
|
$when = isset($include['when'])?true:false; |
9964
|
|
|
if(!isset($include['file'])) |
9965
|
|
|
throw new TConfigurationException('pageserviceconf_includefile_required'); |
9966
|
|
|
$filePath = $include['file']; |
9967
|
|
|
if(isset($this->_includes[$filePath])) |
9968
|
|
|
$this->_includes[$filePath]=array($configPagePath,'('.$this->_includes[$filePath][1].') || ('.$when.')'); |
9969
|
|
|
else |
9970
|
|
|
$this->_includes[$filePath]=array($configPagePath,$when); |
9971
|
|
|
} |
9972
|
|
|
} |
9973
|
|
|
} |
9974
|
|
|
public function loadPageConfigurationFromXml($dom,$configPath,$configPagePath) |
9975
|
|
|
{ |
9976
|
|
|
if(($authorizationNode=$dom->getElementByTagName('authorization'))!==null) |
9977
|
|
|
{ |
9978
|
|
|
$rules=array(); |
9979
|
|
|
foreach($authorizationNode->getElements() as $node) |
9980
|
|
|
{ |
9981
|
|
|
$patterns=$node->getAttribute('pages'); |
9982
|
|
|
$ruleApplies=false; |
9983
|
|
|
if(empty($patterns) || trim($patterns)==='*') $ruleApplies=true; |
9984
|
|
|
else |
9985
|
|
|
{ |
9986
|
|
|
foreach(explode(',',$patterns) as $pattern) |
9987
|
|
|
{ |
9988
|
|
|
if(($pattern=trim($pattern))!=='') |
9989
|
|
|
{ |
9990
|
|
|
if($configPagePath!=='') $pattern=$configPagePath.'.'.$pattern; |
9991
|
|
|
if(strcasecmp($pattern,$this->_pagePath)===0) |
9992
|
|
|
{ |
9993
|
|
|
$ruleApplies=true; |
9994
|
|
|
break; |
9995
|
|
|
} |
9996
|
|
|
if($pattern[strlen($pattern)-1]==='*') { |
9997
|
|
|
if(strncasecmp($this->_pagePath,$pattern,strlen($pattern)-1)===0) |
9998
|
|
|
{ |
9999
|
|
|
$ruleApplies=true; |
10000
|
|
|
break; |
10001
|
|
|
} |
10002
|
|
|
} |
10003
|
|
|
} |
10004
|
|
|
} |
10005
|
|
|
} |
10006
|
|
|
if($ruleApplies) |
10007
|
|
|
$rules[]=new TAuthorizationRule($node->getTagName(),$node->getAttribute('users'),$node->getAttribute('roles'),$node->getAttribute('verb'),$node->getAttribute('ips')); |
10008
|
|
|
} |
10009
|
|
|
$this->_rules=array_merge($rules,$this->_rules); |
10010
|
|
|
} |
10011
|
|
|
if(($pagesNode=$dom->getElementByTagName('pages'))!==null) |
10012
|
|
|
{ |
10013
|
|
|
$this->_properties=array_merge($this->_properties,$pagesNode->getAttributes()->toArray()); |
10014
|
|
|
foreach($pagesNode->getElementsByTagName('page') as $node) |
10015
|
|
|
{ |
10016
|
|
|
$properties=$node->getAttributes(); |
10017
|
|
|
$id=$properties->remove('id'); |
10018
|
|
|
if(empty($id)) |
10019
|
|
|
throw new TConfigurationException('pageserviceconf_page_invalid',$configPath); |
10020
|
|
|
$matching=false; |
10021
|
|
|
$id=($configPagePath==='')?$id:$configPagePath.'.'.$id; |
10022
|
|
|
if(strcasecmp($id,$this->_pagePath)===0) |
10023
|
|
|
$matching=true; |
10024
|
|
|
else if($id[strlen($id)-1]==='*') $matching=strncasecmp($this->_pagePath,$id,strlen($id)-1)===0; |
10025
|
|
|
if($matching) |
10026
|
|
|
$this->_properties=array_merge($this->_properties,$properties->toArray()); |
10027
|
|
|
} |
10028
|
|
|
} |
10029
|
|
|
foreach($dom->getElementsByTagName('include') as $node) |
10030
|
|
|
{ |
10031
|
|
|
if(($when=$node->getAttribute('when'))===null) |
10032
|
|
|
$when=true; |
10033
|
|
|
if(($filePath=$node->getAttribute('file'))===null) |
10034
|
|
|
throw new TConfigurationException('pageserviceconf_includefile_required'); |
10035
|
|
|
if(isset($this->_includes[$filePath])) |
10036
|
|
|
$this->_includes[$filePath]=array($configPagePath,'('.$this->_includes[$filePath][1].') || ('.$when.')'); |
10037
|
|
|
else |
10038
|
|
|
$this->_includes[$filePath]=array($configPagePath,$when); |
10039
|
|
|
} |
10040
|
|
|
} |
10041
|
|
|
} |
10042
|
|
|
class TAssetManager extends TModule |
10043
|
|
|
{ |
10044
|
|
|
const DEFAULT_BASEPATH='assets'; |
10045
|
|
|
private $_basePath=null; |
10046
|
|
|
private $_baseUrl=null; |
10047
|
|
|
private $_checkTimestamp=false; |
|
|
|
|
10048
|
|
|
private $_application; |
|
|
|
|
10049
|
|
|
private $_published=array(); |
10050
|
|
|
private $_initialized=false; |
10051
|
|
|
public function init($config) |
10052
|
|
|
{ |
10053
|
|
|
$application=$this->getApplication(); |
10054
|
|
|
if($this->_basePath===null) |
10055
|
|
|
$this->_basePath=dirname($application->getRequest()->getApplicationFilePath()).DIRECTORY_SEPARATOR.self::DEFAULT_BASEPATH; |
10056
|
|
|
if(!is_writable($this->_basePath) || !is_dir($this->_basePath)) |
10057
|
|
|
throw new TConfigurationException('assetmanager_basepath_invalid',$this->_basePath); |
10058
|
|
|
if($this->_baseUrl===null) |
10059
|
|
|
$this->_baseUrl=rtrim(dirname($application->getRequest()->getApplicationUrl()),'/\\').'/'.self::DEFAULT_BASEPATH; |
10060
|
|
|
$application->setAssetManager($this); |
10061
|
|
|
$this->_initialized=true; |
10062
|
|
|
} |
10063
|
|
|
public function getBasePath() |
10064
|
|
|
{ |
10065
|
|
|
return $this->_basePath; |
10066
|
|
|
} |
10067
|
|
|
public function setBasePath($value) |
10068
|
|
|
{ |
10069
|
|
|
if($this->_initialized) |
10070
|
|
|
throw new TInvalidOperationException('assetmanager_basepath_unchangeable'); |
10071
|
|
|
else |
10072
|
|
|
{ |
10073
|
|
|
$this->_basePath=Prado::getPathOfNamespace($value); |
10074
|
|
|
if($this->_basePath===null || !is_dir($this->_basePath) || !is_writable($this->_basePath)) |
10075
|
|
|
throw new TInvalidDataValueException('assetmanager_basepath_invalid',$value); |
10076
|
|
|
} |
10077
|
|
|
} |
10078
|
|
|
public function getBaseUrl() |
10079
|
|
|
{ |
10080
|
|
|
return $this->_baseUrl; |
10081
|
|
|
} |
10082
|
|
|
public function setBaseUrl($value) |
10083
|
|
|
{ |
10084
|
|
|
if($this->_initialized) |
10085
|
|
|
throw new TInvalidOperationException('assetmanager_baseurl_unchangeable'); |
10086
|
|
|
else |
10087
|
|
|
$this->_baseUrl=rtrim($value,'/'); |
10088
|
|
|
} |
10089
|
|
|
public function publishFilePath($path,$checkTimestamp=false) |
10090
|
|
|
{ |
10091
|
|
|
if(isset($this->_published[$path])) |
10092
|
|
|
return $this->_published[$path]; |
10093
|
|
|
else if(empty($path) || ($fullpath=realpath($path))===false) |
10094
|
|
|
throw new TInvalidDataValueException('assetmanager_filepath_invalid',$path); |
10095
|
|
|
else if(is_file($fullpath)) |
10096
|
|
|
{ |
10097
|
|
|
$dir=$this->hash(dirname($fullpath)); |
10098
|
|
|
$fileName=basename($fullpath); |
10099
|
|
|
$dst=$this->_basePath.DIRECTORY_SEPARATOR.$dir; |
10100
|
|
|
if(!is_file($dst.DIRECTORY_SEPARATOR.$fileName) || $checkTimestamp || $this->getApplication()->getMode()!==TApplicationMode::Performance) |
10101
|
|
|
$this->copyFile($fullpath,$dst); |
10102
|
|
|
return $this->_published[$path]=$this->_baseUrl.'/'.$dir.'/'.$fileName; |
10103
|
|
|
} |
10104
|
|
|
else |
10105
|
|
|
{ |
10106
|
|
|
$dir=$this->hash($fullpath); |
10107
|
|
|
if(!is_dir($this->_basePath.DIRECTORY_SEPARATOR.$dir) || $checkTimestamp || $this->getApplication()->getMode()!==TApplicationMode::Performance) |
10108
|
|
|
{ |
10109
|
|
|
$this->copyDirectory($fullpath,$this->_basePath.DIRECTORY_SEPARATOR.$dir); |
10110
|
|
|
} |
10111
|
|
|
return $this->_published[$path]=$this->_baseUrl.'/'.$dir; |
10112
|
|
|
} |
10113
|
|
|
} |
10114
|
|
|
public function getPublished() |
10115
|
|
|
{ |
10116
|
|
|
return $this->_published; |
10117
|
|
|
} |
10118
|
|
|
protected function setPublished($values=array()) |
10119
|
|
|
{ |
10120
|
|
|
$this->_published = $values; |
10121
|
|
|
} |
10122
|
|
|
public function getPublishedPath($path) |
10123
|
|
|
{ |
10124
|
|
|
$path=realpath($path); |
10125
|
|
|
if(is_file($path)) |
10126
|
|
|
return $this->_basePath.DIRECTORY_SEPARATOR.$this->hash(dirname($path)).DIRECTORY_SEPARATOR.basename($path); |
10127
|
|
|
else |
10128
|
|
|
return $this->_basePath.DIRECTORY_SEPARATOR.$this->hash($path); |
10129
|
|
|
} |
10130
|
|
|
public function getPublishedUrl($path) |
10131
|
|
|
{ |
10132
|
|
|
$path=realpath($path); |
10133
|
|
|
if(is_file($path)) |
10134
|
|
|
return $this->_baseUrl.'/'.$this->hash(dirname($path)).'/'.basename($path); |
10135
|
|
|
else |
10136
|
|
|
return $this->_baseUrl.'/'.$this->hash($path); |
10137
|
|
|
} |
10138
|
|
|
protected function hash($dir) |
10139
|
|
|
{ |
10140
|
|
|
return sprintf('%x',crc32($dir.Prado::getVersion())); |
10141
|
|
|
} |
10142
|
|
|
protected function copyFile($src,$dst) |
10143
|
|
|
{ |
10144
|
|
|
if(!is_dir($dst)) |
10145
|
|
|
{ |
10146
|
|
|
@mkdir($dst); |
10147
|
|
|
@chmod($dst, PRADO_CHMOD); |
10148
|
|
|
} |
10149
|
|
|
$dstFile=$dst.DIRECTORY_SEPARATOR.basename($src); |
10150
|
|
|
if(@filemtime($dstFile)<@filemtime($src)) |
10151
|
|
|
{ |
10152
|
|
|
@copy($src,$dstFile); |
10153
|
|
|
} |
10154
|
|
|
} |
10155
|
|
|
public function copyDirectory($src,$dst) |
10156
|
|
|
{ |
10157
|
|
|
if(!is_dir($dst)) |
10158
|
|
|
{ |
10159
|
|
|
@mkdir($dst); |
10160
|
|
|
@chmod($dst, PRADO_CHMOD); |
10161
|
|
|
} |
10162
|
|
|
if($folder=@opendir($src)) |
10163
|
|
|
{ |
10164
|
|
|
while($file=@readdir($folder)) |
10165
|
|
|
{ |
10166
|
|
|
if($file==='.' || $file==='..' || $file==='.svn') |
10167
|
|
|
continue; |
10168
|
|
|
else if(is_file($src.DIRECTORY_SEPARATOR.$file)) |
10169
|
|
|
{ |
10170
|
|
|
if(@filemtime($dst.DIRECTORY_SEPARATOR.$file)<@filemtime($src.DIRECTORY_SEPARATOR.$file)) |
10171
|
|
|
{ |
10172
|
|
|
@copy($src.DIRECTORY_SEPARATOR.$file,$dst.DIRECTORY_SEPARATOR.$file); |
10173
|
|
|
@chmod($dst.DIRECTORY_SEPARATOR.$file, PRADO_CHMOD); |
10174
|
|
|
} |
10175
|
|
|
} |
10176
|
|
|
else |
10177
|
|
|
$this->copyDirectory($src.DIRECTORY_SEPARATOR.$file,$dst.DIRECTORY_SEPARATOR.$file); |
10178
|
|
|
} |
10179
|
|
|
closedir($folder); |
10180
|
|
|
} else { |
10181
|
|
|
throw new TInvalidDataValueException('assetmanager_source_directory_invalid', $src); |
10182
|
|
|
} |
10183
|
|
|
} |
10184
|
|
|
public function publishTarFile($tarfile, $md5sum, $checkTimestamp=false) |
10185
|
|
|
{ |
10186
|
|
|
if(isset($this->_published[$md5sum])) |
10187
|
|
|
return $this->_published[$md5sum]; |
10188
|
|
|
else if(($fullpath=realpath($md5sum))===false || !is_file($fullpath)) |
10189
|
|
|
throw new TInvalidDataValueException('assetmanager_tarchecksum_invalid',$md5sum); |
10190
|
|
|
else |
10191
|
|
|
{ |
10192
|
|
|
$dir=$this->hash(dirname($fullpath)); |
10193
|
|
|
$fileName=basename($fullpath); |
10194
|
|
|
$dst=$this->_basePath.DIRECTORY_SEPARATOR.$dir; |
10195
|
|
|
if(!is_file($dst.DIRECTORY_SEPARATOR.$fileName) || $checkTimestamp || $this->getApplication()->getMode()!==TApplicationMode::Performance) |
10196
|
|
|
{ |
10197
|
|
|
if(@filemtime($dst.DIRECTORY_SEPARATOR.$fileName)<@filemtime($fullpath)) |
10198
|
|
|
{ |
10199
|
|
|
$this->copyFile($fullpath,$dst); |
10200
|
|
|
$this->deployTarFile($tarfile,$dst); |
10201
|
|
|
} |
10202
|
|
|
} |
10203
|
|
|
return $this->_published[$md5sum]=$this->_baseUrl.'/'.$dir; |
10204
|
|
|
} |
10205
|
|
|
} |
10206
|
|
|
protected function deployTarFile($path,$destination) |
10207
|
|
|
{ |
10208
|
|
|
if(($fullpath=realpath($path))===false || !is_file($fullpath)) |
10209
|
|
|
throw new TIOException('assetmanager_tarfile_invalid',$path); |
10210
|
|
|
else |
10211
|
|
|
{ |
10212
|
|
|
Prado::using('System.IO.TTarFileExtractor'); |
10213
|
|
|
$tar = new TTarFileExtractor($fullpath); |
10214
|
|
|
return $tar->extract($destination); |
10215
|
|
|
} |
10216
|
|
|
} |
10217
|
|
|
} |
10218
|
|
|
class TGlobalization extends TModule |
10219
|
|
|
{ |
10220
|
|
|
private $_defaultCharset = 'UTF-8'; |
10221
|
|
|
private $_defaultCulture = 'en'; |
10222
|
|
|
private $_charset=null; |
10223
|
|
|
private $_culture=null; |
10224
|
|
|
private $_translation; |
10225
|
|
|
private $_translateDefaultCulture=true; |
10226
|
|
|
public function init($config) |
10227
|
|
|
{ |
10228
|
|
|
if($this->_charset===null) |
10229
|
|
|
$this->_charset=$this->getDefaultCharset(); |
10230
|
|
|
if($this->_culture===null) |
10231
|
|
|
$this->_culture=$this->getDefaultCulture(); |
10232
|
|
|
if($config!==null) |
10233
|
|
|
{ |
10234
|
|
|
if($this->getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP) |
10235
|
|
|
$translation = isset($config['translate'])?$config['translate']:null; |
10236
|
|
|
else |
10237
|
|
|
{ |
10238
|
|
|
$t = $config->getElementByTagName('translation'); |
10239
|
|
|
$translation = ($t)?$t->getAttributes():null; |
10240
|
|
|
} |
10241
|
|
|
if($translation) |
10242
|
|
|
$this->setTranslationConfiguration($translation); |
10243
|
|
|
} |
10244
|
|
|
$this->getApplication()->setGlobalization($this); |
10245
|
|
|
} |
10246
|
|
|
public function getTranslateDefaultCulture() |
10247
|
|
|
{ |
10248
|
|
|
return $this->_translateDefaultCulture; |
10249
|
|
|
} |
10250
|
|
|
public function setTranslateDefaultCulture($value) |
10251
|
|
|
{ |
10252
|
|
|
$this->_translateDefaultCulture = TPropertyValue::ensureBoolean($value); |
10253
|
|
|
} |
10254
|
|
|
public function getDefaultCulture() |
10255
|
|
|
{ |
10256
|
|
|
return $this->_defaultCulture; |
10257
|
|
|
} |
10258
|
|
|
public function setDefaultCulture($culture) |
10259
|
|
|
{ |
10260
|
|
|
$this->_defaultCulture = str_replace('-','_',$culture); |
10261
|
|
|
} |
10262
|
|
|
public function getDefaultCharset() |
10263
|
|
|
{ |
10264
|
|
|
return $this->_defaultCharset; |
10265
|
|
|
} |
10266
|
|
|
public function setDefaultCharset($charset) |
10267
|
|
|
{ |
10268
|
|
|
$this->_defaultCharset = $charset; |
10269
|
|
|
} |
10270
|
|
|
public function getCulture() |
10271
|
|
|
{ |
10272
|
|
|
return $this->_culture; |
10273
|
|
|
} |
10274
|
|
|
public function setCulture($culture) |
10275
|
|
|
{ |
10276
|
|
|
$this->_culture = str_replace('-','_',$culture); |
10277
|
|
|
} |
10278
|
|
|
public function getCharset() |
10279
|
|
|
{ |
10280
|
|
|
return $this->_charset; |
10281
|
|
|
} |
10282
|
|
|
public function setCharset($charset) |
10283
|
|
|
{ |
10284
|
|
|
$this->_charset = $charset; |
10285
|
|
|
} |
10286
|
|
|
public function getTranslationConfiguration() |
10287
|
|
|
{ |
10288
|
|
|
return (!$this->_translateDefaultCulture && ($this->getDefaultCulture() == $this->getCulture())) |
10289
|
|
|
? null |
10290
|
|
|
: $this->_translation; |
10291
|
|
|
} |
10292
|
|
|
protected function setTranslationConfiguration($config) |
10293
|
|
|
{ |
10294
|
|
|
if($config['type'] == 'XLIFF' || $config['type'] == 'gettext') |
10295
|
|
|
{ |
10296
|
|
|
if($config['source']) |
10297
|
|
|
{ |
10298
|
|
|
$config['source'] = Prado::getPathOfNamespace($config['source']); |
10299
|
|
|
if(!is_dir($config['source'])) |
10300
|
|
|
{ |
10301
|
|
|
if(@mkdir($config['source'])===false) |
10302
|
|
|
throw new TConfigurationException('globalization_source_path_failed', |
10303
|
|
|
$config['source']); |
10304
|
|
|
chmod($config['source'], PRADO_CHMOD); } |
10305
|
|
|
} |
10306
|
|
|
else |
10307
|
|
|
{ |
10308
|
|
|
throw new TConfigurationException("invalid source dir '{$config['source']}'"); |
10309
|
|
|
} |
10310
|
|
|
} |
10311
|
|
|
if(isset($config['cache']) && TPropertyValue::ensureBoolean($config['cache'])) |
10312
|
|
|
{ |
10313
|
|
|
$config['cache'] = $this->getApplication()->getRunTimePath().'/i18n'; |
10314
|
|
|
if(!is_dir($config['cache'])) |
10315
|
|
|
{ |
10316
|
|
|
if(@mkdir($config['cache'])===false) |
10317
|
|
|
throw new TConfigurationException('globalization_cache_path_failed', |
10318
|
|
|
$config['cache']); |
10319
|
|
|
chmod($config['cache'], PRADO_CHMOD); } |
10320
|
|
|
} |
10321
|
|
|
else |
10322
|
|
|
{ |
10323
|
|
|
unset($config['cache']); |
10324
|
|
|
} |
10325
|
|
|
$this->_translation = $config; |
10326
|
|
|
} |
10327
|
|
|
public function getTranslationCatalogue() |
10328
|
|
|
{ |
10329
|
|
|
return $this->_translation['catalogue']; |
10330
|
|
|
} |
10331
|
|
|
public function setTranslationCatalogue($value) |
10332
|
|
|
{ |
10333
|
|
|
$this->_translation['catalogue'] = $value; |
10334
|
|
|
} |
10335
|
|
|
public function getCultureVariants($culture=null) |
10336
|
|
|
{ |
10337
|
|
|
if($culture===null) $culture = $this->getCulture(); |
10338
|
|
|
$variants = explode('_', $culture); |
10339
|
|
|
$result = array(); |
10340
|
|
|
for(; count($variants) > 0; array_pop($variants)) |
|
|
|
|
10341
|
|
|
$result[] = implode('_', $variants); |
10342
|
|
|
return $result; |
10343
|
|
|
} |
10344
|
|
|
public function getLocalizedResource($file,$culture=null) |
10345
|
|
|
{ |
10346
|
|
|
$files = array(); |
10347
|
|
|
$variants = $this->getCultureVariants($culture); |
10348
|
|
|
$path = pathinfo($file); |
10349
|
|
|
foreach($variants as $variant) |
10350
|
|
|
$files[] = $path['dirname'].DIRECTORY_SEPARATOR.$variant.DIRECTORY_SEPARATOR.$path['basename']; |
10351
|
|
|
$filename = substr($path['basename'],0,strrpos($path['basename'],'.')); |
10352
|
|
|
foreach($variants as $variant) |
10353
|
|
|
$files[] = $path['dirname'].DIRECTORY_SEPARATOR.$filename.'.'.$variant.'.'.$path['extension']; |
10354
|
|
|
$files[] = $file; |
10355
|
|
|
return $files; |
10356
|
|
|
} |
10357
|
|
|
} |
10358
|
|
|
class TApplication extends TComponent |
10359
|
|
|
{ |
10360
|
|
|
const STATE_OFF='Off'; |
10361
|
|
|
const STATE_DEBUG='Debug'; |
10362
|
|
|
const STATE_NORMAL='Normal'; |
10363
|
|
|
const STATE_PERFORMANCE='Performance'; |
10364
|
|
|
const PAGE_SERVICE_ID='page'; |
10365
|
|
|
const CONFIG_FILE_XML='application.xml'; |
10366
|
|
|
const CONFIG_FILE_EXT_XML='.xml'; |
10367
|
|
|
const CONFIG_TYPE_XML = 'xml'; |
10368
|
|
|
const CONFIG_FILE_PHP='application.php'; |
10369
|
|
|
const CONFIG_FILE_EXT_PHP='.php'; |
10370
|
|
|
const CONFIG_TYPE_PHP = 'php'; |
10371
|
|
|
const RUNTIME_PATH='runtime'; |
10372
|
|
|
const CONFIGCACHE_FILE='config.cache'; |
10373
|
|
|
const GLOBAL_FILE='global.cache'; |
10374
|
|
|
private static $_steps=array( |
10375
|
|
|
'onBeginRequest', |
10376
|
|
|
'onLoadState', |
10377
|
|
|
'onLoadStateComplete', |
10378
|
|
|
'onAuthentication', |
10379
|
|
|
'onAuthenticationComplete', |
10380
|
|
|
'onAuthorization', |
10381
|
|
|
'onAuthorizationComplete', |
10382
|
|
|
'onPreRunService', |
10383
|
|
|
'runService', |
10384
|
|
|
'onSaveState', |
10385
|
|
|
'onSaveStateComplete', |
10386
|
|
|
'onPreFlushOutput', |
10387
|
|
|
'flushOutput' |
10388
|
|
|
); |
10389
|
|
|
private $_id; |
10390
|
|
|
private $_uniqueID; |
10391
|
|
|
private $_requestCompleted=false; |
10392
|
|
|
private $_step; |
10393
|
|
|
private $_services; |
10394
|
|
|
private $_service; |
10395
|
|
|
private $_modules=array(); |
10396
|
|
|
private $_lazyModules=array(); |
10397
|
|
|
private $_parameters; |
10398
|
|
|
private $_configFile; |
10399
|
|
|
private $_configFileExt; |
10400
|
|
|
private $_configType; |
10401
|
|
|
private $_basePath; |
10402
|
|
|
private $_runtimePath; |
10403
|
|
|
private $_stateChanged=false; |
10404
|
|
|
private $_globals=array(); |
10405
|
|
|
private $_cacheFile; |
10406
|
|
|
private $_errorHandler; |
10407
|
|
|
private $_request; |
10408
|
|
|
private $_response; |
10409
|
|
|
private $_session; |
10410
|
|
|
private $_cache; |
10411
|
|
|
private $_statePersister; |
10412
|
|
|
private $_user; |
10413
|
|
|
private $_globalization; |
10414
|
|
|
private $_security; |
10415
|
|
|
private $_assetManager; |
10416
|
|
|
private $_authRules; |
10417
|
|
|
private $_mode=TApplicationMode::Debug; |
10418
|
|
|
private $_pageServiceID = self::PAGE_SERVICE_ID; |
10419
|
|
|
public function __construct($basePath='protected',$cacheConfig=true, $configType=self::CONFIG_TYPE_XML) |
10420
|
|
|
{ |
10421
|
|
|
Prado::setApplication($this); |
10422
|
|
|
$this->setConfigurationType($configType); |
10423
|
|
|
$this->resolvePaths($basePath); |
10424
|
|
|
if($cacheConfig) |
10425
|
|
|
$this->_cacheFile=$this->_runtimePath.DIRECTORY_SEPARATOR.self::CONFIGCACHE_FILE; |
10426
|
|
|
$this->_uniqueID=md5($this->_runtimePath); |
10427
|
|
|
$this->_parameters=new TMap; |
10428
|
|
|
$this->_services=array($this->getPageServiceID()=>array('TPageService',array(),null)); |
10429
|
|
|
Prado::setPathOfAlias('Application',$this->_basePath); |
10430
|
|
|
} |
10431
|
|
|
protected function resolvePaths($basePath) |
10432
|
|
|
{ |
10433
|
|
|
if(empty($basePath) || ($basePath=realpath($basePath))===false) |
10434
|
|
|
throw new TConfigurationException('application_basepath_invalid',$basePath); |
10435
|
|
|
if(is_dir($basePath) && is_file($basePath.DIRECTORY_SEPARATOR.$this->getConfigurationFileName())) |
10436
|
|
|
$configFile=$basePath.DIRECTORY_SEPARATOR.$this->getConfigurationFileName(); |
10437
|
|
|
else if(is_file($basePath)) |
10438
|
|
|
{ |
10439
|
|
|
$configFile=$basePath; |
10440
|
|
|
$basePath=dirname($configFile); |
10441
|
|
|
} |
10442
|
|
|
else |
10443
|
|
|
$configFile=null; |
10444
|
|
|
$runtimePath=$basePath.DIRECTORY_SEPARATOR.self::RUNTIME_PATH; |
10445
|
|
|
if(is_writable($runtimePath)) |
10446
|
|
|
{ |
10447
|
|
|
if($configFile!==null) |
10448
|
|
|
{ |
10449
|
|
|
$runtimePath.=DIRECTORY_SEPARATOR.basename($configFile).'-'.Prado::getVersion(); |
10450
|
|
|
if(!is_dir($runtimePath)) |
10451
|
|
|
{ |
10452
|
|
|
if(@mkdir($runtimePath)===false) |
10453
|
|
|
throw new TConfigurationException('application_runtimepath_failed',$runtimePath); |
10454
|
|
|
@chmod($runtimePath, PRADO_CHMOD); } |
10455
|
|
|
$this->setConfigurationFile($configFile); |
10456
|
|
|
} |
10457
|
|
|
$this->setBasePath($basePath); |
10458
|
|
|
$this->setRuntimePath($runtimePath); |
10459
|
|
|
} |
10460
|
|
|
else |
10461
|
|
|
throw new TConfigurationException('application_runtimepath_invalid',$runtimePath); |
10462
|
|
|
} |
10463
|
|
|
public function run() |
10464
|
|
|
{ |
10465
|
|
|
try |
10466
|
|
|
{ |
10467
|
|
|
$this->initApplication(); |
10468
|
|
|
$n=count(self::$_steps); |
10469
|
|
|
$this->_step=0; |
10470
|
|
|
$this->_requestCompleted=false; |
10471
|
|
|
while($this->_step<$n) |
10472
|
|
|
{ |
10473
|
|
|
if($this->_mode===self::STATE_OFF) |
10474
|
|
|
throw new THttpException(503,'application_unavailable'); |
10475
|
|
|
if($this->_requestCompleted) |
10476
|
|
|
break; |
10477
|
|
|
$method=self::$_steps[$this->_step]; |
10478
|
|
|
$this->$method(); |
10479
|
|
|
$this->_step++; |
10480
|
|
|
} |
10481
|
|
|
} |
10482
|
|
|
catch(Exception $e) |
10483
|
|
|
{ |
10484
|
|
|
$this->onError($e); |
10485
|
|
|
} |
10486
|
|
|
$this->onEndRequest(); |
10487
|
|
|
} |
10488
|
|
|
public function completeRequest() |
10489
|
|
|
{ |
10490
|
|
|
$this->_requestCompleted=true; |
10491
|
|
|
} |
10492
|
|
|
public function getRequestCompleted() |
10493
|
|
|
{ |
10494
|
|
|
return $this->_requestCompleted; |
10495
|
|
|
} |
10496
|
|
|
public function getGlobalState($key,$defaultValue=null) |
10497
|
|
|
{ |
10498
|
|
|
return isset($this->_globals[$key])?$this->_globals[$key]:$defaultValue; |
10499
|
|
|
} |
10500
|
|
|
public function setGlobalState($key,$value,$defaultValue=null,$forceSave=false) |
10501
|
|
|
{ |
10502
|
|
|
$this->_stateChanged=true; |
10503
|
|
|
if($value===$defaultValue) |
10504
|
|
|
unset($this->_globals[$key]); |
10505
|
|
|
else |
10506
|
|
|
$this->_globals[$key]=$value; |
10507
|
|
|
if($forceSave) |
10508
|
|
|
$this->saveGlobals(); |
10509
|
|
|
} |
10510
|
|
|
public function clearGlobalState($key) |
10511
|
|
|
{ |
10512
|
|
|
$this->_stateChanged=true; |
10513
|
|
|
unset($this->_globals[$key]); |
10514
|
|
|
} |
10515
|
|
|
protected function loadGlobals() |
10516
|
|
|
{ |
10517
|
|
|
$this->_globals=$this->getApplicationStatePersister()->load(); |
10518
|
|
|
} |
10519
|
|
|
protected function saveGlobals() |
10520
|
|
|
{ |
10521
|
|
|
if($this->_stateChanged) |
10522
|
|
|
{ |
10523
|
|
|
$this->_stateChanged=false; |
10524
|
|
|
$this->getApplicationStatePersister()->save($this->_globals); |
10525
|
|
|
} |
10526
|
|
|
} |
10527
|
|
|
public function getID() |
10528
|
|
|
{ |
10529
|
|
|
return $this->_id; |
10530
|
|
|
} |
10531
|
|
|
public function setID($value) |
10532
|
|
|
{ |
10533
|
|
|
$this->_id=$value; |
10534
|
|
|
} |
10535
|
|
|
public function getPageServiceID() |
10536
|
|
|
{ |
10537
|
|
|
return $this->_pageServiceID; |
10538
|
|
|
} |
10539
|
|
|
public function setPageServiceID($value) |
10540
|
|
|
{ |
10541
|
|
|
$this->_pageServiceID=$value; |
10542
|
|
|
} |
10543
|
|
|
public function getUniqueID() |
10544
|
|
|
{ |
10545
|
|
|
return $this->_uniqueID; |
10546
|
|
|
} |
10547
|
|
|
public function getMode() |
10548
|
|
|
{ |
10549
|
|
|
return $this->_mode; |
10550
|
|
|
} |
10551
|
|
|
public function setMode($value) |
10552
|
|
|
{ |
10553
|
|
|
$this->_mode=TPropertyValue::ensureEnum($value,'TApplicationMode'); |
10554
|
|
|
} |
10555
|
|
|
public function getBasePath() |
10556
|
|
|
{ |
10557
|
|
|
return $this->_basePath; |
10558
|
|
|
} |
10559
|
|
|
public function setBasePath($value) |
10560
|
|
|
{ |
10561
|
|
|
$this->_basePath=$value; |
10562
|
|
|
} |
10563
|
|
|
public function getConfigurationFile() |
10564
|
|
|
{ |
10565
|
|
|
return $this->_configFile; |
10566
|
|
|
} |
10567
|
|
|
public function setConfigurationFile($value) |
10568
|
|
|
{ |
10569
|
|
|
$this->_configFile=$value; |
10570
|
|
|
} |
10571
|
|
|
public function getConfigurationType() |
10572
|
|
|
{ |
10573
|
|
|
return $this->_configType; |
10574
|
|
|
} |
10575
|
|
|
public function setConfigurationType($value) |
10576
|
|
|
{ |
10577
|
|
|
$this->_configType = $value; |
10578
|
|
|
} |
10579
|
|
|
public function getConfigurationFileExt() |
10580
|
|
|
{ |
10581
|
|
|
if($this->_configFileExt===null) |
10582
|
|
|
{ |
10583
|
|
|
switch($this->_configType) |
10584
|
|
|
{ |
10585
|
|
|
case TApplication::CONFIG_TYPE_PHP: |
|
|
|
|
10586
|
|
|
$this->_configFileExt = TApplication::CONFIG_FILE_EXT_PHP; |
|
|
|
|
10587
|
|
|
break; |
10588
|
|
|
default: |
10589
|
|
|
$this->_configFileExt = TApplication::CONFIG_FILE_EXT_XML; |
|
|
|
|
10590
|
|
|
} |
10591
|
|
|
} |
10592
|
|
|
return $this->_configFileExt; |
10593
|
|
|
} |
10594
|
|
|
public function getConfigurationFileName() |
10595
|
|
|
{ |
10596
|
|
|
static $fileName; |
10597
|
|
|
if($fileName == null) |
10598
|
|
|
{ |
10599
|
|
|
switch($this->_configType) |
10600
|
|
|
{ |
10601
|
|
|
case TApplication::CONFIG_TYPE_PHP: |
|
|
|
|
10602
|
|
|
$fileName = TApplication::CONFIG_FILE_PHP; |
|
|
|
|
10603
|
|
|
break; |
10604
|
|
|
default: |
10605
|
|
|
$fileName = TApplication::CONFIG_FILE_XML; |
|
|
|
|
10606
|
|
|
} |
10607
|
|
|
} |
10608
|
|
|
return $fileName; |
10609
|
|
|
} |
10610
|
|
|
public function getRuntimePath() |
10611
|
|
|
{ |
10612
|
|
|
return $this->_runtimePath; |
10613
|
|
|
} |
10614
|
|
|
public function setRuntimePath($value) |
10615
|
|
|
{ |
10616
|
|
|
$this->_runtimePath=$value; |
10617
|
|
|
if($this->_cacheFile) |
10618
|
|
|
$this->_cacheFile=$this->_runtimePath.DIRECTORY_SEPARATOR.self::CONFIGCACHE_FILE; |
10619
|
|
|
$this->_uniqueID=md5($this->_runtimePath); |
10620
|
|
|
} |
10621
|
|
|
public function getService() |
10622
|
|
|
{ |
10623
|
|
|
return $this->_service; |
10624
|
|
|
} |
10625
|
|
|
public function setService($value) |
10626
|
|
|
{ |
10627
|
|
|
$this->_service=$value; |
10628
|
|
|
} |
10629
|
|
|
public function setModule($id,IModule $module=null) |
10630
|
|
|
{ |
10631
|
|
|
if(isset($this->_modules[$id])) |
10632
|
|
|
throw new TConfigurationException('application_moduleid_duplicated',$id); |
10633
|
|
|
else |
10634
|
|
|
$this->_modules[$id]=$module; |
10635
|
|
|
} |
10636
|
|
|
public function getModule($id) |
10637
|
|
|
{ |
10638
|
|
|
if(!array_key_exists($id, $this->_modules)) |
10639
|
|
|
return null; |
10640
|
|
|
if($this->_modules[$id]===null) |
10641
|
|
|
{ |
10642
|
|
|
$module = $this->internalLoadModule($id, true); |
10643
|
|
|
$module[0]->init($module[1]); |
10644
|
|
|
} |
10645
|
|
|
return $this->_modules[$id]; |
10646
|
|
|
} |
10647
|
|
|
public function getModules() |
10648
|
|
|
{ |
10649
|
|
|
return $this->_modules; |
10650
|
|
|
} |
10651
|
|
|
public function getParameters() |
10652
|
|
|
{ |
10653
|
|
|
return $this->_parameters; |
10654
|
|
|
} |
10655
|
|
|
public function getRequest() |
10656
|
|
|
{ |
10657
|
|
|
if(!$this->_request) |
10658
|
|
|
{ |
10659
|
|
|
$this->_request=new THttpRequest; |
10660
|
|
|
$this->_request->init(null); |
10661
|
|
|
} |
10662
|
|
|
return $this->_request; |
10663
|
|
|
} |
10664
|
|
|
public function setRequest(THttpRequest $request) |
10665
|
|
|
{ |
10666
|
|
|
$this->_request=$request; |
10667
|
|
|
} |
10668
|
|
|
public function getResponse() |
10669
|
|
|
{ |
10670
|
|
|
if(!$this->_response) |
10671
|
|
|
{ |
10672
|
|
|
$this->_response=new THttpResponse; |
10673
|
|
|
$this->_response->init(null); |
10674
|
|
|
} |
10675
|
|
|
return $this->_response; |
10676
|
|
|
} |
10677
|
|
|
public function setResponse(THttpResponse $response) |
10678
|
|
|
{ |
10679
|
|
|
$this->_response=$response; |
10680
|
|
|
} |
10681
|
|
|
public function getSession() |
10682
|
|
|
{ |
10683
|
|
|
if(!$this->_session) |
10684
|
|
|
{ |
10685
|
|
|
$this->_session=new THttpSession; |
10686
|
|
|
$this->_session->init(null); |
10687
|
|
|
} |
10688
|
|
|
return $this->_session; |
10689
|
|
|
} |
10690
|
|
|
public function setSession(THttpSession $session) |
10691
|
|
|
{ |
10692
|
|
|
$this->_session=$session; |
10693
|
|
|
} |
10694
|
|
|
public function getErrorHandler() |
10695
|
|
|
{ |
10696
|
|
|
if(!$this->_errorHandler) |
10697
|
|
|
{ |
10698
|
|
|
$this->_errorHandler=new TErrorHandler; |
10699
|
|
|
$this->_errorHandler->init(null); |
10700
|
|
|
} |
10701
|
|
|
return $this->_errorHandler; |
10702
|
|
|
} |
10703
|
|
|
public function setErrorHandler(TErrorHandler $handler) |
10704
|
|
|
{ |
10705
|
|
|
$this->_errorHandler=$handler; |
10706
|
|
|
} |
10707
|
|
|
public function getSecurityManager() |
10708
|
|
|
{ |
10709
|
|
|
if(!$this->_security) |
10710
|
|
|
{ |
10711
|
|
|
$this->_security=new TSecurityManager; |
10712
|
|
|
$this->_security->init(null); |
10713
|
|
|
} |
10714
|
|
|
return $this->_security; |
10715
|
|
|
} |
10716
|
|
|
public function setSecurityManager(TSecurityManager $sm) |
10717
|
|
|
{ |
10718
|
|
|
$this->_security=$sm; |
10719
|
|
|
} |
10720
|
|
|
public function getAssetManager() |
10721
|
|
|
{ |
10722
|
|
|
if(!$this->_assetManager) |
10723
|
|
|
{ |
10724
|
|
|
$this->_assetManager=new TAssetManager; |
10725
|
|
|
$this->_assetManager->init(null); |
10726
|
|
|
} |
10727
|
|
|
return $this->_assetManager; |
10728
|
|
|
} |
10729
|
|
|
public function setAssetManager(TAssetManager $value) |
10730
|
|
|
{ |
10731
|
|
|
$this->_assetManager=$value; |
10732
|
|
|
} |
10733
|
|
|
public function getApplicationStatePersister() |
10734
|
|
|
{ |
10735
|
|
|
if(!$this->_statePersister) |
10736
|
|
|
{ |
10737
|
|
|
$this->_statePersister=new TApplicationStatePersister; |
10738
|
|
|
$this->_statePersister->init(null); |
10739
|
|
|
} |
10740
|
|
|
return $this->_statePersister; |
10741
|
|
|
} |
10742
|
|
|
public function setApplicationStatePersister(IStatePersister $persister) |
10743
|
|
|
{ |
10744
|
|
|
$this->_statePersister=$persister; |
10745
|
|
|
} |
10746
|
|
|
public function getCache() |
10747
|
|
|
{ |
10748
|
|
|
return $this->_cache; |
10749
|
|
|
} |
10750
|
|
|
public function setCache(ICache $cache) |
10751
|
|
|
{ |
10752
|
|
|
$this->_cache=$cache; |
10753
|
|
|
} |
10754
|
|
|
public function getUser() |
10755
|
|
|
{ |
10756
|
|
|
return $this->_user; |
10757
|
|
|
} |
10758
|
|
|
public function setUser(IUser $user) |
10759
|
|
|
{ |
10760
|
|
|
$this->_user=$user; |
10761
|
|
|
} |
10762
|
|
|
public function getGlobalization($createIfNotExists=true) |
10763
|
|
|
{ |
10764
|
|
|
if($this->_globalization===null && $createIfNotExists) |
10765
|
|
|
{ |
10766
|
|
|
$this->_globalization=new TGlobalization; |
10767
|
|
|
$this->_globalization->init(null); |
10768
|
|
|
} |
10769
|
|
|
return $this->_globalization; |
10770
|
|
|
} |
10771
|
|
|
public function setGlobalization(TGlobalization $glob) |
10772
|
|
|
{ |
10773
|
|
|
$this->_globalization=$glob; |
10774
|
|
|
} |
10775
|
|
|
public function getAuthorizationRules() |
10776
|
|
|
{ |
10777
|
|
|
if($this->_authRules===null) |
10778
|
|
|
$this->_authRules=new TAuthorizationRuleCollection; |
10779
|
|
|
return $this->_authRules; |
10780
|
|
|
} |
10781
|
|
|
protected function getApplicationConfigurationClass() |
10782
|
|
|
{ |
10783
|
|
|
return 'TApplicationConfiguration'; |
10784
|
|
|
} |
10785
|
|
|
protected function internalLoadModule($id, $force=false) |
10786
|
|
|
{ |
10787
|
|
|
list($moduleClass, $initProperties, $configElement)=$this->_lazyModules[$id]; |
10788
|
|
|
if(isset($initProperties['lazy']) && $initProperties['lazy'] && !$force) |
10789
|
|
|
{ |
10790
|
|
|
$this->setModule($id, null); |
10791
|
|
|
return null; |
10792
|
|
|
} |
10793
|
|
|
$module=Prado::createComponent($moduleClass); |
10794
|
|
|
foreach($initProperties as $name=>$value) |
10795
|
|
|
{ |
10796
|
|
|
if($name==='lazy') continue; |
10797
|
|
|
$module->setSubProperty($name,$value); |
10798
|
|
|
} |
10799
|
|
|
$this->setModule($id,$module); |
10800
|
|
|
$this->_lazyModules[$id]=null; |
10801
|
|
|
return array($module,$configElement); |
10802
|
|
|
} |
10803
|
|
|
public function applyConfiguration($config,$withinService=false) |
10804
|
|
|
{ |
10805
|
|
|
if($config->getIsEmpty()) |
10806
|
|
|
return; |
10807
|
|
|
foreach($config->getAliases() as $alias=>$path) |
10808
|
|
|
Prado::setPathOfAlias($alias,$path); |
10809
|
|
|
foreach($config->getUsings() as $using) |
10810
|
|
|
Prado::using($using); |
10811
|
|
|
if(!$withinService) |
10812
|
|
|
{ |
10813
|
|
|
foreach($config->getProperties() as $name=>$value) |
10814
|
|
|
$this->setSubProperty($name,$value); |
10815
|
|
|
} |
10816
|
|
|
if(empty($this->_services)) |
10817
|
|
|
$this->_services=array($this->getPageServiceID()=>array('TPageService',array(),null)); |
10818
|
|
|
foreach($config->getParameters() as $id=>$parameter) |
10819
|
|
|
{ |
10820
|
|
|
if(is_array($parameter)) |
10821
|
|
|
{ |
10822
|
|
|
$component=Prado::createComponent($parameter[0]); |
10823
|
|
|
foreach($parameter[1] as $name=>$value) |
10824
|
|
|
$component->setSubProperty($name,$value); |
10825
|
|
|
$this->_parameters->add($id,$component); |
10826
|
|
|
} |
10827
|
|
|
else |
10828
|
|
|
$this->_parameters->add($id,$parameter); |
10829
|
|
|
} |
10830
|
|
|
$modules=array(); |
10831
|
|
|
foreach($config->getModules() as $id=>$moduleConfig) |
10832
|
|
|
{ |
10833
|
|
|
if(!is_string($id)) |
10834
|
|
|
$id='_module'.count($this->_lazyModules); |
10835
|
|
|
$this->_lazyModules[$id]=$moduleConfig; |
10836
|
|
|
if($module = $this->internalLoadModule($id)) |
10837
|
|
|
$modules[]=$module; |
10838
|
|
|
} |
10839
|
|
|
foreach($modules as $module) |
10840
|
|
|
$module[0]->init($module[1]); |
10841
|
|
|
foreach($config->getServices() as $serviceID=>$serviceConfig) |
10842
|
|
|
$this->_services[$serviceID]=$serviceConfig; |
10843
|
|
|
foreach($config->getExternalConfigurations() as $filePath=>$condition) |
10844
|
|
|
{ |
10845
|
|
|
if($condition!==true) |
10846
|
|
|
$condition=$this->evaluateExpression($condition); |
10847
|
|
|
if($condition) |
10848
|
|
|
{ |
10849
|
|
|
if(($path=Prado::getPathOfNamespace($filePath,$this->getConfigurationFileExt()))===null || !is_file($path)) |
10850
|
|
|
throw new TConfigurationException('application_includefile_invalid',$filePath); |
10851
|
|
|
$cn=$this->getApplicationConfigurationClass(); |
10852
|
|
|
$c=new $cn; |
10853
|
|
|
$c->loadFromFile($path); |
10854
|
|
|
$this->applyConfiguration($c,$withinService); |
10855
|
|
|
} |
10856
|
|
|
} |
10857
|
|
|
} |
10858
|
|
|
protected function initApplication() |
10859
|
|
|
{ |
10860
|
|
|
if($this->_configFile!==null) |
10861
|
|
|
{ |
10862
|
|
|
if($this->_cacheFile===null || @filemtime($this->_cacheFile)<filemtime($this->_configFile)) |
10863
|
|
|
{ |
10864
|
|
|
$config=new TApplicationConfiguration; |
10865
|
|
|
$config->loadFromFile($this->_configFile); |
10866
|
|
|
if($this->_cacheFile!==null) |
10867
|
|
|
file_put_contents($this->_cacheFile,serialize($config),LOCK_EX); |
10868
|
|
|
} |
10869
|
|
|
else |
10870
|
|
|
$config=unserialize(file_get_contents($this->_cacheFile)); |
10871
|
|
|
$this->applyConfiguration($config,false); |
10872
|
|
|
} |
10873
|
|
|
if(($serviceID=$this->getRequest()->resolveRequest(array_keys($this->_services)))===null) |
10874
|
|
|
$serviceID=$this->getPageServiceID(); |
10875
|
|
|
$this->startService($serviceID); |
10876
|
|
|
} |
10877
|
|
|
public function startService($serviceID) |
10878
|
|
|
{ |
10879
|
|
|
if(isset($this->_services[$serviceID])) |
10880
|
|
|
{ |
10881
|
|
|
list($serviceClass,$initProperties,$configElement)=$this->_services[$serviceID]; |
10882
|
|
|
$service=Prado::createComponent($serviceClass); |
10883
|
|
|
if(!($service instanceof IService)) |
10884
|
|
|
throw new THttpException(500,'application_service_invalid',$serviceClass); |
10885
|
|
|
if(!$service->getEnabled()) |
10886
|
|
|
throw new THttpException(500,'application_service_unavailable',$serviceClass); |
10887
|
|
|
$service->setID($serviceID); |
10888
|
|
|
$this->setService($service); |
10889
|
|
|
foreach($initProperties as $name=>$value) |
10890
|
|
|
$service->setSubProperty($name,$value); |
10891
|
|
|
if($configElement!==null) |
10892
|
|
|
{ |
10893
|
|
|
$config=new TApplicationConfiguration; |
10894
|
|
|
if($this->getConfigurationType()==self::CONFIG_TYPE_PHP) |
10895
|
|
|
$config->loadFromPhp($configElement,$this->getBasePath()); |
10896
|
|
|
else |
10897
|
|
|
$config->loadFromXml($configElement,$this->getBasePath()); |
10898
|
|
|
$this->applyConfiguration($config,true); |
10899
|
|
|
} |
10900
|
|
|
$service->init($configElement); |
10901
|
|
|
} |
10902
|
|
|
else |
10903
|
|
|
throw new THttpException(500,'application_service_unknown',$serviceID); |
10904
|
|
|
} |
10905
|
|
|
public function onError($param) |
10906
|
|
|
{ |
10907
|
|
|
Prado::log($param->getMessage(),TLogger::ERROR,'System.TApplication'); |
10908
|
|
|
$this->raiseEvent('OnError',$this,$param); |
10909
|
|
|
$this->getErrorHandler()->handleError($this,$param); |
10910
|
|
|
} |
10911
|
|
|
public function onBeginRequest() |
10912
|
|
|
{ |
10913
|
|
|
$this->raiseEvent('OnBeginRequest',$this,null); |
10914
|
|
|
} |
10915
|
|
|
public function onAuthentication() |
10916
|
|
|
{ |
10917
|
|
|
$this->raiseEvent('OnAuthentication',$this,null); |
10918
|
|
|
} |
10919
|
|
|
public function onAuthenticationComplete() |
10920
|
|
|
{ |
10921
|
|
|
$this->raiseEvent('OnAuthenticationComplete',$this,null); |
10922
|
|
|
} |
10923
|
|
|
public function onAuthorization() |
10924
|
|
|
{ |
10925
|
|
|
$this->raiseEvent('OnAuthorization',$this,null); |
10926
|
|
|
} |
10927
|
|
|
public function onAuthorizationComplete() |
10928
|
|
|
{ |
10929
|
|
|
$this->raiseEvent('OnAuthorizationComplete',$this,null); |
10930
|
|
|
} |
10931
|
|
|
public function onLoadState() |
10932
|
|
|
{ |
10933
|
|
|
$this->loadGlobals(); |
10934
|
|
|
$this->raiseEvent('OnLoadState',$this,null); |
10935
|
|
|
} |
10936
|
|
|
public function onLoadStateComplete() |
10937
|
|
|
{ |
10938
|
|
|
$this->raiseEvent('OnLoadStateComplete',$this,null); |
10939
|
|
|
} |
10940
|
|
|
public function onPreRunService() |
10941
|
|
|
{ |
10942
|
|
|
$this->raiseEvent('OnPreRunService',$this,null); |
10943
|
|
|
} |
10944
|
|
|
public function runService() |
10945
|
|
|
{ |
10946
|
|
|
if($this->_service) |
10947
|
|
|
$this->_service->run(); |
10948
|
|
|
} |
10949
|
|
|
public function onSaveState() |
10950
|
|
|
{ |
10951
|
|
|
$this->raiseEvent('OnSaveState',$this,null); |
10952
|
|
|
$this->saveGlobals(); |
10953
|
|
|
} |
10954
|
|
|
public function onSaveStateComplete() |
10955
|
|
|
{ |
10956
|
|
|
$this->raiseEvent('OnSaveStateComplete',$this,null); |
10957
|
|
|
} |
10958
|
|
|
public function onPreFlushOutput() |
10959
|
|
|
{ |
10960
|
|
|
$this->raiseEvent('OnPreFlushOutput',$this,null); |
10961
|
|
|
} |
10962
|
|
|
public function flushOutput($continueBuffering = true) |
10963
|
|
|
{ |
10964
|
|
|
$this->getResponse()->flush($continueBuffering); |
10965
|
|
|
} |
10966
|
|
|
public function onEndRequest() |
10967
|
|
|
{ |
10968
|
|
|
$this->flushOutput(false); $this->saveGlobals(); $this->raiseEvent('OnEndRequest',$this,null); |
|
|
|
|
10969
|
|
|
} |
10970
|
|
|
} |
10971
|
|
|
class TApplicationMode extends TEnumerable |
10972
|
|
|
{ |
10973
|
|
|
const Off='Off'; |
10974
|
|
|
const Debug='Debug'; |
10975
|
|
|
const Normal='Normal'; |
10976
|
|
|
const Performance='Performance'; |
10977
|
|
|
} |
10978
|
|
|
class TApplicationConfiguration extends TComponent |
10979
|
|
|
{ |
10980
|
|
|
private $_properties=array(); |
10981
|
|
|
private $_usings=array(); |
10982
|
|
|
private $_aliases=array(); |
10983
|
|
|
private $_modules=array(); |
10984
|
|
|
private $_services=array(); |
10985
|
|
|
private $_parameters=array(); |
10986
|
|
|
private $_includes=array(); |
10987
|
|
|
private $_empty=true; |
10988
|
|
|
public function loadFromFile($fname) |
10989
|
|
|
{ |
10990
|
|
|
if(Prado::getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP) |
10991
|
|
|
{ |
10992
|
|
|
$fcontent = include $fname; |
10993
|
|
|
$this->loadFromPhp($fcontent,dirname($fname)); |
10994
|
|
|
} |
10995
|
|
|
else |
10996
|
|
|
{ |
10997
|
|
|
$dom=new TXmlDocument; |
10998
|
|
|
$dom->loadFromFile($fname); |
10999
|
|
|
$this->loadFromXml($dom,dirname($fname)); |
11000
|
|
|
} |
11001
|
|
|
} |
11002
|
|
|
public function getIsEmpty() |
11003
|
|
|
{ |
11004
|
|
|
return $this->_empty; |
11005
|
|
|
} |
11006
|
|
|
public function loadFromPhp($config, $configPath) |
11007
|
|
|
{ |
11008
|
|
|
if(isset($config['application'])) |
11009
|
|
|
{ |
11010
|
|
|
foreach($config['application'] as $name=>$value) |
11011
|
|
|
{ |
11012
|
|
|
$this->_properties[$name]=$value; |
11013
|
|
|
} |
11014
|
|
|
$this->_empty = false; |
11015
|
|
|
} |
11016
|
|
|
if(isset($config['paths']) && is_array($config['paths'])) |
11017
|
|
|
$this->loadPathsPhp($config['paths'],$configPath); |
11018
|
|
|
if(isset($config['modules']) && is_array($config['modules'])) |
11019
|
|
|
$this->loadModulesPhp($config['modules'],$configPath); |
11020
|
|
|
if(isset($config['services']) && is_array($config['services'])) |
11021
|
|
|
$this->loadServicesPhp($config['services'],$configPath); |
11022
|
|
|
if(isset($config['parameters']) && is_array($config['parameters'])) |
11023
|
|
|
$this->loadParametersPhp($config['parameters'], $configPath); |
11024
|
|
|
if(isset($config['includes']) && is_array($config['includes'])) |
11025
|
|
|
$this->loadExternalXml($config['includes'],$configPath); |
11026
|
|
|
} |
11027
|
|
|
public function loadFromXml($dom,$configPath) |
11028
|
|
|
{ |
11029
|
|
|
foreach($dom->getAttributes() as $name=>$value) |
11030
|
|
|
{ |
11031
|
|
|
$this->_properties[$name]=$value; |
11032
|
|
|
$this->_empty=false; |
11033
|
|
|
} |
11034
|
|
|
foreach($dom->getElements() as $element) |
11035
|
|
|
{ |
11036
|
|
|
switch($element->getTagName()) |
11037
|
|
|
{ |
11038
|
|
|
case 'paths': |
11039
|
|
|
$this->loadPathsXml($element,$configPath); |
11040
|
|
|
break; |
11041
|
|
|
case 'modules': |
11042
|
|
|
$this->loadModulesXml($element,$configPath); |
11043
|
|
|
break; |
11044
|
|
|
case 'services': |
11045
|
|
|
$this->loadServicesXml($element,$configPath); |
11046
|
|
|
break; |
11047
|
|
|
case 'parameters': |
11048
|
|
|
$this->loadParametersXml($element,$configPath); |
11049
|
|
|
break; |
11050
|
|
|
case 'include': |
11051
|
|
|
$this->loadExternalXml($element,$configPath); |
11052
|
|
|
break; |
11053
|
|
|
default: |
11054
|
|
|
break; |
11055
|
|
|
} |
11056
|
|
|
} |
11057
|
|
|
} |
11058
|
|
|
protected function loadPathsPhp($pathsNode, $configPath) |
11059
|
|
|
{ |
11060
|
|
|
if(isset($pathsNode['aliases']) && is_array($pathsNode['aliases'])) |
11061
|
|
|
{ |
11062
|
|
|
foreach($pathsNode['aliases'] as $id=>$path) |
11063
|
|
|
{ |
11064
|
|
|
$path=str_replace('\\','/',$path); |
11065
|
|
|
if(preg_match('/^\\/|.:\\/|.:\\\\/',$path)) $p=realpath($path); |
11066
|
|
|
else |
11067
|
|
|
$p=realpath($configPath.DIRECTORY_SEPARATOR.$path); |
11068
|
|
|
if($p===false || !is_dir($p)) |
11069
|
|
|
throw new TConfigurationException('appconfig_aliaspath_invalid',$id,$path); |
11070
|
|
|
if(isset($this->_aliases[$id])) |
11071
|
|
|
throw new TConfigurationException('appconfig_alias_redefined',$id); |
11072
|
|
|
$this->_aliases[$id]=$p; |
11073
|
|
|
} |
11074
|
|
|
} |
11075
|
|
|
if(isset($pathsNode['using']) && is_array($pathsNode['using'])) |
11076
|
|
|
{ |
11077
|
|
|
foreach($pathsNode['using'] as $namespace) |
11078
|
|
|
{ |
11079
|
|
|
$this->_usings[] = $namespace; |
11080
|
|
|
} |
11081
|
|
|
} |
11082
|
|
|
} |
11083
|
|
|
protected function loadPathsXml($pathsNode,$configPath) |
11084
|
|
|
{ |
11085
|
|
|
foreach($pathsNode->getElements() as $element) |
11086
|
|
|
{ |
11087
|
|
|
switch($element->getTagName()) |
11088
|
|
|
{ |
11089
|
|
|
case 'alias': |
|
|
|
|
11090
|
|
|
{ |
11091
|
|
|
if(($id=$element->getAttribute('id'))!==null && ($path=$element->getAttribute('path'))!==null) |
11092
|
|
|
{ |
11093
|
|
|
$path=str_replace('\\','/',$path); |
11094
|
|
|
if(preg_match('/^\\/|.:\\/|.:\\\\/',$path)) $p=realpath($path); |
11095
|
|
|
else |
11096
|
|
|
$p=realpath($configPath.DIRECTORY_SEPARATOR.$path); |
11097
|
|
|
if($p===false || !is_dir($p)) |
11098
|
|
|
throw new TConfigurationException('appconfig_aliaspath_invalid',$id,$path); |
11099
|
|
|
if(isset($this->_aliases[$id])) |
11100
|
|
|
throw new TConfigurationException('appconfig_alias_redefined',$id); |
11101
|
|
|
$this->_aliases[$id]=$p; |
11102
|
|
|
} |
11103
|
|
|
else |
11104
|
|
|
throw new TConfigurationException('appconfig_alias_invalid'); |
11105
|
|
|
$this->_empty=false; |
11106
|
|
|
break; |
11107
|
|
|
} |
11108
|
|
|
case 'using': |
|
|
|
|
11109
|
|
|
{ |
11110
|
|
|
if(($namespace=$element->getAttribute('namespace'))!==null) |
11111
|
|
|
$this->_usings[]=$namespace; |
11112
|
|
|
else |
11113
|
|
|
throw new TConfigurationException('appconfig_using_invalid'); |
11114
|
|
|
$this->_empty=false; |
11115
|
|
|
break; |
11116
|
|
|
} |
11117
|
|
|
default: |
11118
|
|
|
throw new TConfigurationException('appconfig_paths_invalid',$element->getTagName()); |
11119
|
|
|
} |
11120
|
|
|
} |
11121
|
|
|
} |
11122
|
|
|
protected function loadModulesPhp($modulesNode, $configPath) |
11123
|
|
|
{ |
11124
|
|
|
foreach($modulesNode as $id=>$module) |
11125
|
|
|
{ |
11126
|
|
|
if(!isset($module['class'])) |
11127
|
|
|
throw new TConfigurationException('appconfig_moduletype_required',$id); |
11128
|
|
|
$type = $module['class']; |
11129
|
|
|
unset($module['class']); |
11130
|
|
|
$properties = array(); |
11131
|
|
|
if(isset($module['properties'])) |
11132
|
|
|
{ |
11133
|
|
|
$properties = $module['properties']; |
11134
|
|
|
unset($module['properties']); |
11135
|
|
|
} |
11136
|
|
|
$properties['id'] = $id; |
11137
|
|
|
$this->_modules[$id]=array($type,$properties,$module); |
11138
|
|
|
$this->_empty=false; |
11139
|
|
|
} |
11140
|
|
|
} |
11141
|
|
|
protected function loadModulesXml($modulesNode,$configPath) |
11142
|
|
|
{ |
11143
|
|
|
foreach($modulesNode->getElements() as $element) |
11144
|
|
|
{ |
11145
|
|
|
if($element->getTagName()==='module') |
11146
|
|
|
{ |
11147
|
|
|
$properties=$element->getAttributes(); |
11148
|
|
|
$id=$properties->itemAt('id'); |
11149
|
|
|
$type=$properties->remove('class'); |
11150
|
|
|
if($type===null) |
11151
|
|
|
throw new TConfigurationException('appconfig_moduletype_required',$id); |
11152
|
|
|
$element->setParent(null); |
11153
|
|
|
if($id===null) |
11154
|
|
|
$this->_modules[]=array($type,$properties->toArray(),$element); |
11155
|
|
|
else |
11156
|
|
|
$this->_modules[$id]=array($type,$properties->toArray(),$element); |
11157
|
|
|
$this->_empty=false; |
11158
|
|
|
} |
11159
|
|
|
else |
11160
|
|
|
throw new TConfigurationException('appconfig_modules_invalid',$element->getTagName()); |
11161
|
|
|
} |
11162
|
|
|
} |
11163
|
|
|
protected function loadServicesPhp($servicesNode,$configPath) |
11164
|
|
|
{ |
11165
|
|
|
foreach($servicesNode as $id => $service) |
11166
|
|
|
{ |
11167
|
|
|
if(!isset($service['class'])) |
11168
|
|
|
throw new TConfigurationException('appconfig_servicetype_required'); |
11169
|
|
|
$type = $service['class']; |
11170
|
|
|
$properties = isset($service['properties']) ? $service['properties'] : array(); |
11171
|
|
|
unset($service['properties']); |
11172
|
|
|
$properties['id'] = $id; |
11173
|
|
|
$this->_services[$id] = array($type,$properties,$service); |
11174
|
|
|
$this->_empty = false; |
11175
|
|
|
} |
11176
|
|
|
} |
11177
|
|
|
protected function loadServicesXml($servicesNode,$configPath) |
11178
|
|
|
{ |
11179
|
|
|
foreach($servicesNode->getElements() as $element) |
11180
|
|
|
{ |
11181
|
|
|
if($element->getTagName()==='service') |
11182
|
|
|
{ |
11183
|
|
|
$properties=$element->getAttributes(); |
11184
|
|
|
if(($id=$properties->itemAt('id'))===null) |
11185
|
|
|
throw new TConfigurationException('appconfig_serviceid_required'); |
11186
|
|
|
if(($type=$properties->remove('class'))===null) |
11187
|
|
|
throw new TConfigurationException('appconfig_servicetype_required',$id); |
11188
|
|
|
$element->setParent(null); |
11189
|
|
|
$this->_services[$id]=array($type,$properties->toArray(),$element); |
11190
|
|
|
$this->_empty=false; |
11191
|
|
|
} |
11192
|
|
|
else |
11193
|
|
|
throw new TConfigurationException('appconfig_services_invalid',$element->getTagName()); |
11194
|
|
|
} |
11195
|
|
|
} |
11196
|
|
|
protected function loadParametersPhp($parametersNode,$configPath) |
11197
|
|
|
{ |
11198
|
|
|
foreach($parametersNode as $id => $parameter) |
11199
|
|
|
{ |
11200
|
|
|
if(is_array($parameter)) |
11201
|
|
|
{ |
11202
|
|
|
if(isset($parameter['class'])) |
11203
|
|
|
{ |
11204
|
|
|
$type = $parameter['class']; |
11205
|
|
|
unset($parameter['class']); |
11206
|
|
|
$properties = isset($service['properties']) ? $service['properties'] : array(); |
11207
|
|
|
$properties['id'] = $id; |
11208
|
|
|
$this->_parameters[$id] = array($type,$properties); |
11209
|
|
|
} |
11210
|
|
|
} |
11211
|
|
|
else |
11212
|
|
|
{ |
11213
|
|
|
$this->_parameters[$id] = $parameter; |
11214
|
|
|
} |
11215
|
|
|
} |
11216
|
|
|
} |
11217
|
|
|
protected function loadParametersXml($parametersNode,$configPath) |
11218
|
|
|
{ |
11219
|
|
|
foreach($parametersNode->getElements() as $element) |
11220
|
|
|
{ |
11221
|
|
|
if($element->getTagName()==='parameter') |
11222
|
|
|
{ |
11223
|
|
|
$properties=$element->getAttributes(); |
11224
|
|
|
if(($id=$properties->remove('id'))===null) |
11225
|
|
|
throw new TConfigurationException('appconfig_parameterid_required'); |
11226
|
|
|
if(($type=$properties->remove('class'))===null) |
11227
|
|
|
{ |
11228
|
|
|
if(($value=$properties->remove('value'))===null) |
11229
|
|
|
$this->_parameters[$id]=$element; |
11230
|
|
|
else |
11231
|
|
|
$this->_parameters[$id]=$value; |
11232
|
|
|
} |
11233
|
|
|
else |
11234
|
|
|
$this->_parameters[$id]=array($type,$properties->toArray()); |
11235
|
|
|
$this->_empty=false; |
11236
|
|
|
} |
11237
|
|
|
else |
11238
|
|
|
throw new TConfigurationException('appconfig_parameters_invalid',$element->getTagName()); |
11239
|
|
|
} |
11240
|
|
|
} |
11241
|
|
|
protected function loadExternalPhp($includeNode,$configPath) |
11242
|
|
|
{ |
11243
|
|
|
foreach($includeNode as $include) |
11244
|
|
|
{ |
11245
|
|
|
$when = isset($include['when'])?true:false; |
11246
|
|
|
if(!isset($include['file'])) |
11247
|
|
|
throw new TConfigurationException('appconfig_includefile_required'); |
11248
|
|
|
$filePath = $include['file']; |
11249
|
|
|
if(isset($this->_includes[$filePath])) |
11250
|
|
|
$this->_includes[$filePath]='('.$this->_includes[$filePath].') || ('.$when.')'; |
11251
|
|
|
else |
11252
|
|
|
$$this->_includes[$filePath]=$when; |
11253
|
|
|
$this->_empty=false; |
11254
|
|
|
} |
11255
|
|
|
} |
11256
|
|
|
protected function loadExternalXml($includeNode,$configPath) |
11257
|
|
|
{ |
11258
|
|
|
if(($when=$includeNode->getAttribute('when'))===null) |
11259
|
|
|
$when=true; |
11260
|
|
|
if(($filePath=$includeNode->getAttribute('file'))===null) |
11261
|
|
|
throw new TConfigurationException('appconfig_includefile_required'); |
11262
|
|
|
if(isset($this->_includes[$filePath])) |
11263
|
|
|
$this->_includes[$filePath]='('.$this->_includes[$filePath].') || ('.$when.')'; |
11264
|
|
|
else |
11265
|
|
|
$this->_includes[$filePath]=$when; |
11266
|
|
|
$this->_empty=false; |
11267
|
|
|
} |
11268
|
|
|
public function getProperties() |
11269
|
|
|
{ |
11270
|
|
|
return $this->_properties; |
11271
|
|
|
} |
11272
|
|
|
public function getAliases() |
11273
|
|
|
{ |
11274
|
|
|
return $this->_aliases; |
11275
|
|
|
} |
11276
|
|
|
public function getUsings() |
11277
|
|
|
{ |
11278
|
|
|
return $this->_usings; |
11279
|
|
|
} |
11280
|
|
|
public function getModules() |
11281
|
|
|
{ |
11282
|
|
|
return $this->_modules; |
11283
|
|
|
} |
11284
|
|
|
public function getServices() |
11285
|
|
|
{ |
11286
|
|
|
return $this->_services; |
11287
|
|
|
} |
11288
|
|
|
public function getParameters() |
11289
|
|
|
{ |
11290
|
|
|
return $this->_parameters; |
11291
|
|
|
} |
11292
|
|
|
public function getExternalConfigurations() |
11293
|
|
|
{ |
11294
|
|
|
return $this->_includes; |
11295
|
|
|
} |
11296
|
|
|
} |
11297
|
|
|
class TApplicationStatePersister extends TModule implements IStatePersister |
11298
|
|
|
{ |
11299
|
|
|
const CACHE_NAME='prado:appstate'; |
11300
|
|
|
public function init($config) |
11301
|
|
|
{ |
11302
|
|
|
$this->getApplication()->setApplicationStatePersister($this); |
11303
|
|
|
} |
11304
|
|
|
protected function getStateFilePath() |
11305
|
|
|
{ |
11306
|
|
|
return $this->getApplication()->getRuntimePath().'/global.cache'; |
11307
|
|
|
} |
11308
|
|
|
public function load() |
11309
|
|
|
{ |
11310
|
|
|
if(($cache=$this->getApplication()->getCache())!==null && ($value=$cache->get(self::CACHE_NAME))!==false) |
11311
|
|
|
return unserialize($value); |
11312
|
|
|
else |
11313
|
|
|
{ |
11314
|
|
|
if(($content=@file_get_contents($this->getStateFilePath()))!==false) |
11315
|
|
|
return unserialize($content); |
11316
|
|
|
else |
11317
|
|
|
return null; |
11318
|
|
|
} |
11319
|
|
|
} |
11320
|
|
|
public function save($state) |
11321
|
|
|
{ |
11322
|
|
|
$content=serialize($state); |
11323
|
|
|
$saveFile=true; |
11324
|
|
|
if(($cache=$this->getApplication()->getCache())!==null) |
11325
|
|
|
{ |
11326
|
|
|
if($cache->get(self::CACHE_NAME)===$content) |
11327
|
|
|
$saveFile=false; |
11328
|
|
|
else |
11329
|
|
|
$cache->set(self::CACHE_NAME,$content); |
11330
|
|
|
} |
11331
|
|
|
if($saveFile) |
11332
|
|
|
{ |
11333
|
|
|
$fileName=$this->getStateFilePath(); |
11334
|
|
|
file_put_contents($fileName,$content,LOCK_EX); |
11335
|
|
|
} |
11336
|
|
|
} |
11337
|
|
|
} |
11338
|
|
|
class TShellApplication extends TApplication |
11339
|
|
|
{ |
11340
|
|
|
public function run() |
11341
|
|
|
{ |
11342
|
|
|
$this->initApplication(); |
11343
|
|
|
} |
11344
|
|
|
} |
11345
|
|
|
?> |
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.