How to use ensureId method of Rule class

Best Cucumber Common Library code snippet using Rule.ensureId

pradolite.php

Source:pradolite.php Github

copy

Full Screen

1<?php2/**3 * File Name: pradolite.php4 * Last Update: 2017/01/23 17:32:515 * Generated By: buildscripts/phpbuilder/build.php6 *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 */13if(!defined('PRADO_DIR'))14 define('PRADO_DIR',dirname(__FILE__));15if(!defined('PRADO_CHMOD'))16 define('PRADO_CHMOD',0777);17class PradoBase18{19 const CLASS_FILE_EXT='.php';20 private static $_aliases=array('System'=>PRADO_DIR);21 private static $_usings=array();22 private static $_application=null;23 private static $_logger=null;24 protected static $classExists = array();25 public static function getVersion()26 {27 return '3.3.3';28 }29 public static function initErrorHandlers()30 {31 set_error_handler(array('PradoBase','phpErrorHandler'));32 register_shutdown_function(array('PradoBase','phpFatalErrorHandler'));33 set_exception_handler(array('PradoBase','exceptionHandler'));34 ini_set('display_errors', 0);35 }36 public static function autoload($className)37 {38 @include_once($className.self::CLASS_FILE_EXT);39 }40 public static function poweredByPrado($logoType=0)41 {42 $logoName=$logoType==1?'powered2':'powered';43 if(self::$_application!==null)44 {45 $am=self::$_application->getAssetManager();46 $url=$am->publishFilePath(self::getPathOfNamespace('System.'.$logoName,'.gif'));47 }48 else49 $url='http://pradosoft.github.io/docs/'.$logoName.'.gif';50 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>';51 }52 public static function phpErrorHandler($errno,$errstr,$errfile,$errline)53 {54 if(error_reporting() & $errno)55 throw new TPhpErrorException($errno,$errstr,$errfile,$errline);56 }57 public static function phpFatalErrorHandler()58 {59 $error = error_get_last();60 if($error && 61 TPhpErrorException::isFatalError($error) &&62 error_reporting() & $error['type'])63 {64 self::exceptionHandler(new TPhpErrorException($error['type'],$error['message'],$error['file'],$error['line']));65 }66 }67 public static function exceptionHandler($exception)68 {69 if(self::$_application!==null && ($errorHandler=self::$_application->getErrorHandler())!==null)70 {71 $errorHandler->handleError(null,$exception);72 }73 else74 {75 echo $exception;76 }77 exit(1);78 }79 public static function setApplication($application)80 {81 if(self::$_application!==null && !defined('PRADO_TEST_RUN'))82 throw new TInvalidOperationException('prado_application_singleton_required');83 self::$_application=$application;84 }85 public static function getApplication()86 {87 return self::$_application;88 }89 public static function getFrameworkPath()90 {91 return PRADO_DIR;92 }93 public static function createComponent($type)94 {95 if(!isset(self::$classExists[$type]))96 self::$classExists[$type] = class_exists($type, false);97 if( !isset(self::$_usings[$type]) && !self::$classExists[$type]) {98 self::using($type);99 self::$classExists[$type] = class_exists($type, false);100 }101 if( ($pos = strrpos($type, '.')) !== false)102 $type = substr($type,$pos+1);103 if(($n=func_num_args())>1)104 {105 $args = func_get_args();106 switch($n) {107 case 2:108 return new $type($args[1]);109 break;110 case 3:111 return new $type($args[1], $args[2]);112 break;113 case 4:114 return new $type($args[1], $args[2], $args[3]);115 break;116 case 5:117 return new $type($args[1], $args[2], $args[3], $args[4]);118 break;119 default:120 $s='$args[1]';121 for($i=2;$i<$n;++$i)122 $s.=",\$args[$i]";123 eval("\$component=new $type($s);");124 return $component;125 break;126 }127 }128 else129 return new $type;130 }131 public static function using($namespace,$checkClassExistence=true)132 {133 if(isset(self::$_usings[$namespace]) || class_exists($namespace,false))134 return;135 if(($pos=strrpos($namespace,'.'))===false) {136 try137 {138 include_once($namespace.self::CLASS_FILE_EXT);139 }140 catch(Exception $e)141 {142 if($checkClassExistence && !class_exists($namespace,false))143 throw new TInvalidOperationException('prado_component_unknown',$namespace,$e->getMessage());144 else145 throw $e;146 }147 }148 else if(($path=self::getPathOfNamespace($namespace,self::CLASS_FILE_EXT))!==null)149 {150 $className=substr($namespace,$pos+1);151 if($className==='*') {152 self::$_usings[$namespace]=$path;153 set_include_path(get_include_path().PATH_SEPARATOR.$path);154 }155 else {156 self::$_usings[$namespace]=$path;157 if(!$checkClassExistence || !class_exists($className,false))158 {159 try160 {161 include_once($path);162 }163 catch(Exception $e)164 {165 if($checkClassExistence && !class_exists($className,false))166 throw new TInvalidOperationException('prado_component_unknown',$className,$e->getMessage());167 else168 throw $e;169 }170 }171 }172 }173 else174 throw new TInvalidDataValueException('prado_using_invalid',$namespace);175 }176 public static function getPathOfNamespace($namespace, $ext='')177 {178 if(self::CLASS_FILE_EXT === $ext || empty($ext))179 {180 if(isset(self::$_usings[$namespace]))181 return self::$_usings[$namespace];182 if(isset(self::$_aliases[$namespace]))183 return self::$_aliases[$namespace];184 }185 $segs = explode('.',$namespace);186 $alias = array_shift($segs);187 if(null !== ($file = array_pop($segs)) && null !== ($root = self::getPathOfAlias($alias)))188 return rtrim($root.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR ,$segs),'/\\').(($file === '*') ? '' : DIRECTORY_SEPARATOR.$file.$ext);189 return null;190 }191 public static function getPathOfAlias($alias)192 {193 return isset(self::$_aliases[$alias])?self::$_aliases[$alias]:null;194 }195 protected static function getPathAliases()196 {197 return self::$_aliases;198 }199 public static function setPathOfAlias($alias,$path)200 {201 if(isset(self::$_aliases[$alias]) && !defined('PRADO_TEST_RUN'))202 throw new TInvalidOperationException('prado_alias_redefined',$alias);203 else if(($rp=realpath($path))!==false && is_dir($rp))204 {205 if(strpos($alias,'.')===false)206 self::$_aliases[$alias]=$rp;207 else208 throw new TInvalidDataValueException('prado_aliasname_invalid',$alias);209 }210 else211 throw new TInvalidDataValueException('prado_alias_invalid',$alias,$path);212 }213 public static function fatalError($msg)214 {215 echo '<h1>Fatal Error</h1>';216 echo '<p>'.$msg.'</p>';217 if(!function_exists('debug_backtrace'))218 return;219 echo '<h2>Debug Backtrace</h2>';220 echo '<pre>';221 $index=-1;222 foreach(debug_backtrace() as $t)223 {224 $index++;225 if($index==0) continue;226 echo '#'.$index.' ';227 if(isset($t['file']))228 echo basename($t['file']) . ':' . $t['line'];229 else230 echo '<PHP inner-code>';231 echo ' -- ';232 if(isset($t['class']))233 echo $t['class'] . $t['type'];234 echo $t['function'] . '(';235 if(isset($t['args']) && sizeof($t['args']) > 0)236 {237 $count=0;238 foreach($t['args'] as $item)239 {240 if(is_string($item))241 {242 $str=htmlentities(str_replace("\r\n", "", $item), ENT_QUOTES);243 if (strlen($item) > 70)244 echo "'". substr($str, 0, 70) . "...'";245 else246 echo "'" . $str . "'";247 }248 else if (is_int($item) || is_float($item))249 echo $item;250 else if (is_object($item))251 echo get_class($item);252 else if (is_array($item))253 echo 'array(' . count($item) . ')';254 else if (is_bool($item))255 echo $item ? 'true' : 'false';256 else if ($item === null)257 echo 'NULL';258 else if (is_resource($item))259 echo get_resource_type($item);260 $count++;261 if (count($t['args']) > $count)262 echo ', ';263 }264 }265 echo ")\n";266 }267 echo '</pre>';268 exit(1);269 }270 public static function getUserLanguages()271 {272 static $languages=null;273 if($languages===null)274 {275 if(!isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))276 $languages[0]='en';277 else278 {279 $languages=array();280 foreach(explode(',',$_SERVER['HTTP_ACCEPT_LANGUAGE']) as $language)281 {282 $array=explode(';q=',trim($language));283 $languages[trim($array[0])]=isset($array[1])?(float)$array[1]:1.0;284 }285 arsort($languages);286 $languages=array_keys($languages);287 if(empty($languages))288 $languages[0]='en';289 }290 }291 return $languages;292 }293 public static function getPreferredLanguage()294 {295 static $language=null;296 if($language===null)297 {298 $langs=Prado::getUserLanguages();299 $lang=explode('-',$langs[0]);300 if(empty($lang[0]) || !ctype_alpha($lang[0]))301 $language='en';302 else303 $language=$lang[0];304 }305 return $language;306 }307 public static function trace($msg,$category='Uncategorized',$ctl=null)308 {309 if(self::$_application && self::$_application->getMode()===TApplicationMode::Performance)310 return;311 if(!self::$_application || self::$_application->getMode()===TApplicationMode::Debug)312 {313 $trace=debug_backtrace();314 if(isset($trace[0]['file']) && isset($trace[0]['line']))315 $msg.=" (line {$trace[0]['line']}, {$trace[0]['file']})";316 $level=TLogger::DEBUG;317 }318 else319 $level=TLogger::INFO;320 self::log($msg,$level,$category,$ctl);321 }322 public static function log($msg,$level=TLogger::INFO,$category='Uncategorized',$ctl=null)323 {324 if(self::$_logger===null)325 self::$_logger=new TLogger;326 self::$_logger->log($msg,$level,$category,$ctl);327 }328 public static function getLogger()329 {330 if(self::$_logger===null)331 self::$_logger=new TLogger;332 return self::$_logger;333 }334 public static function varDump($var,$depth=10,$highlight=false)335 {336 Prado::using('System.Util.TVarDumper');337 return TVarDumper::dump($var,$depth,$highlight);338 }339 public static function localize($text, $parameters=array(), $catalogue=null, $charset=null)340 {341 Prado::using('System.I18N.Translation');342 $app = Prado::getApplication()->getGlobalization(false);343 $params = array();344 foreach($parameters as $key => $value)345 $params['{'.$key.'}'] = $value;346 if($app===null || ($config = $app->getTranslationConfiguration())===null)347 return strtr($text, $params);348 if ($catalogue===null)349 $catalogue=isset($config['catalogue'])?$config['catalogue']:'messages';350 Translation::init($catalogue);351 $appCharset = $app===null ? '' : $app->getCharset();352 $defaultCharset = ($app===null) ? 'UTF-8' : $app->getDefaultCharset();353 if(empty($charset)) $charset = $appCharset;354 if(empty($charset)) $charset = $defaultCharset;355 return Translation::formatter($catalogue)->format($text,$params,$catalogue,$charset);356 }357}358PradoBase::using('System.TComponent');359PradoBase::using('System.Exceptions.TException');360PradoBase::using('System.Util.TLogger');361if(!class_exists('Prado',false))362{363 class Prado extends PradoBase364 {365 }366}367spl_autoload_register(array('Prado','autoload'));368Prado::initErrorHandlers();369interface IModule370{371 public function init($config);372 public function getID();373 public function setID($id);374}375interface IService376{377 public function init($config);378 public function getID();379 public function setID($id);380 public function getEnabled();381 public function setEnabled($value);382 public function run();383}384interface ITextWriter385{386 public function write($str);387 public function flush();388}389interface IUser390{391 public function getName();392 public function setName($value);393 public function getIsGuest();394 public function setIsGuest($value);395 public function getRoles();396 public function setRoles($value);397 public function isInRole($role);398 public function saveToString();399 public function loadFromString($string);400}401interface IStatePersister402{403 public function load();404 public function save($state);405}406interface ICache407{408 public function get($id);409 public function set($id,$value,$expire=0,$dependency=null);410 public function add($id,$value,$expire=0,$dependency=null);411 public function delete($id);412 public function flush();413}414interface ICacheDependency415{416 public function getHasChanged();417}418interface IRenderable419{420 public function render($writer);421}422interface IBindable423{424 public function dataBind();425}426interface IStyleable427{428 public function getHasStyle();429 public function getStyle();430 public function clearStyle();431}432interface IActiveControl433{434 public function getActiveControl();435}436interface ICallbackEventHandler437{438 public function raiseCallbackEvent($eventArgument);439}440interface IDataRenderer441{442 public function getData();443 public function setData($value);444}445class TApplicationComponent extends TComponent446{447 public function getApplication()448 {449 return Prado::getApplication();450 }451 public function getService()452 {453 return Prado::getApplication()->getService();454 }455 public function getRequest()456 {457 return Prado::getApplication()->getRequest();458 }459 public function getResponse()460 {461 return Prado::getApplication()->getResponse();462 }463 public function getSession()464 {465 return Prado::getApplication()->getSession();466 }467 public function getUser()468 {469 return Prado::getApplication()->getUser();470 }471 public function publishAsset($assetPath,$className=null)472 {473 if($className===null)474 $className=get_class($this);475 $class=new ReflectionClass($className);476 $fullPath=dirname($class->getFileName()).DIRECTORY_SEPARATOR.$assetPath;477 return $this->publishFilePath($fullPath);478 }479 public function publishFilePath($fullPath, $checkTimestamp=false)480 {481 return Prado::getApplication()->getAssetManager()->publishFilePath($fullPath, $checkTimestamp);482 }483}484abstract class TModule extends TApplicationComponent implements IModule485{486 private $_id;487 public function init($config)488 {489 }490 public function getID()491 {492 return $this->_id;493 }494 public function setID($value)495 {496 $this->_id=$value;497 }498}499abstract class TService extends TApplicationComponent implements IService500{501 private $_id;502 private $_enabled=true;503 public function init($config)504 {505 }506 public function getID()507 {508 return $this->_id;509 }510 public function setID($value)511 {512 $this->_id=$value;513 }514 public function getEnabled()515 {516 return $this->_enabled;517 }518 public function setEnabled($value)519 {520 $this->_enabled=TPropertyValue::ensureBoolean($value);521 }522 public function run()523 {524 }525}526class TErrorHandler extends TModule527{528 const ERROR_FILE_NAME='error';529 const EXCEPTION_FILE_NAME='exception';530 const SOURCE_LINES=12;531 private $_templatePath=null;532 public function init($config)533 {534 $this->getApplication()->setErrorHandler($this);535 }536 public function getErrorTemplatePath()537 {538 if($this->_templatePath===null)539 $this->_templatePath=Prado::getFrameworkPath().'/Exceptions/templates';540 return $this->_templatePath;541 }542 public function setErrorTemplatePath($value)543 {544 if(($templatePath=Prado::getPathOfNamespace($value))!==null && is_dir($templatePath))545 $this->_templatePath=$templatePath;546 else547 throw new TConfigurationException('errorhandler_errortemplatepath_invalid',$value);548 }549 public function handleError($sender,$param)550 {551 static $handling=false;552 restore_error_handler();553 restore_exception_handler();554 if($handling)555 $this->handleRecursiveError($param);556 else557 {558 $handling=true;559 if(($response=$this->getResponse())!==null)560 $response->clear();561 if(!headers_sent())562 header('Content-Type: text/html; charset=UTF-8');563 if($param instanceof THttpException)564 $this->handleExternalError($param->getStatusCode(),$param);565 else if($this->getApplication()->getMode()===TApplicationMode::Debug)566 $this->displayException($param);567 else568 $this->handleExternalError(500,$param);569 }570 }571 protected static function hideSecurityRelated($value, $exception=null)572 {573 $aRpl = array();574 if($exception !== null && $exception instanceof Exception)575 {576 $aTrace = $exception->getTrace();577 foreach($aTrace as $item)578 {579 if(isset($item['file']))580 $aRpl[dirname($item['file']) . DIRECTORY_SEPARATOR] = '<hidden>' . DIRECTORY_SEPARATOR;581 }582 }583 $aRpl[$_SERVER['DOCUMENT_ROOT']] = '${DocumentRoot}';584 $aRpl[str_replace('/', DIRECTORY_SEPARATOR, $_SERVER['DOCUMENT_ROOT'])] = '${DocumentRoot}';585 $aRpl[PRADO_DIR . DIRECTORY_SEPARATOR] = '${PradoFramework}' . DIRECTORY_SEPARATOR;586 if(isset($aRpl[DIRECTORY_SEPARATOR])) unset($aRpl[DIRECTORY_SEPARATOR]);587 $aRpl = array_reverse($aRpl, true);588 return str_replace(array_keys($aRpl), $aRpl, $value);589 }590 protected function handleExternalError($statusCode,$exception)591 {592 if(!($exception instanceof THttpException))593 error_log($exception->__toString());594 $content=$this->getErrorTemplate($statusCode,$exception);595 $serverAdmin=isset($_SERVER['SERVER_ADMIN'])?$_SERVER['SERVER_ADMIN']:'';596 $isDebug = $this->getApplication()->getMode()===TApplicationMode::Debug;597 $errorMessage = $exception->getMessage();598 if($isDebug)599 $version=$_SERVER['SERVER_SOFTWARE'].' <a href="https://github.com/pradosoft/prado">PRADO</a>/'.Prado::getVersion();600 else601 {602 $version='';603 $errorMessage = self::hideSecurityRelated($errorMessage, $exception);604 }605 $tokens=array(606 '%%StatusCode%%' => "$statusCode",607 '%%ErrorMessage%%' => htmlspecialchars($errorMessage),608 '%%ServerAdmin%%' => $serverAdmin,609 '%%Version%%' => $version,610 '%%Time%%' => @strftime('%Y-%m-%d %H:%M',time())611 );612 $this->getApplication()->getResponse()->setStatusCode($statusCode, $isDebug ? $exception->getMessage() : null);613 echo strtr($content,$tokens);614 }615 protected function handleRecursiveError($exception)616 {617 if($this->getApplication()->getMode()===TApplicationMode::Debug)618 {619 echo "<html><head><title>Recursive Error</title></head>\n";620 echo "<body><h1>Recursive Error</h1>\n";621 echo "<pre>".$exception->__toString()."</pre>\n";622 echo "</body></html>";623 }624 else625 {626 error_log("Error happened while processing an existing error:\n".$exception->__toString());627 header('HTTP/1.0 500 Internal Error');628 }629 }630 protected function displayException($exception)631 {632 if(php_sapi_name()==='cli')633 {634 echo $exception->getMessage()."\n";635 echo $exception->getTraceAsString();636 return;637 }638 if($exception instanceof TTemplateException)639 {640 $fileName=$exception->getTemplateFile();641 $lines=empty($fileName)?explode("\n",$exception->getTemplateSource()):@file($fileName);642 $source=$this->getSourceCode($lines,$exception->getLineNumber());643 if($fileName==='')644 $fileName='---embedded template---';645 $errorLine=$exception->getLineNumber();646 }647 else648 {649 if(($trace=$this->getExactTrace($exception))!==null)650 {651 $fileName=$trace['file'];652 $errorLine=$trace['line'];653 }654 else655 {656 $fileName=$exception->getFile();657 $errorLine=$exception->getLine();658 }659 $source=$this->getSourceCode(@file($fileName),$errorLine);660 }661 if($this->getApplication()->getMode()===TApplicationMode::Debug)662 $version=$_SERVER['SERVER_SOFTWARE'].' <a href="https://github.com/pradosoft/prado">PRADO</a>/'.Prado::getVersion();663 else664 $version='';665 $tokens=array(666 '%%ErrorType%%' => get_class($exception),667 '%%ErrorMessage%%' => $this->addLink(htmlspecialchars($exception->getMessage())),668 '%%SourceFile%%' => htmlspecialchars($fileName).' ('.$errorLine.')',669 '%%SourceCode%%' => $source,670 '%%StackTrace%%' => htmlspecialchars($exception->getTraceAsString()),671 '%%Version%%' => $version,672 '%%Time%%' => @strftime('%Y-%m-%d %H:%M',time())673 );674 $content=$this->getExceptionTemplate($exception);675 echo strtr($content,$tokens);676 }677 protected function getExceptionTemplate($exception)678 {679 $lang=Prado::getPreferredLanguage();680 $exceptionFile=Prado::getFrameworkPath().'/Exceptions/templates/'.self::EXCEPTION_FILE_NAME.'-'.$lang.'.html';681 if(!is_file($exceptionFile))682 $exceptionFile=Prado::getFrameworkPath().'/Exceptions/templates/'.self::EXCEPTION_FILE_NAME.'.html';683 if(($content=@file_get_contents($exceptionFile))===false)684 die("Unable to open exception template file '$exceptionFile'.");685 return $content;686 }687 protected function getErrorTemplate($statusCode,$exception)688 {689 $base=$this->getErrorTemplatePath().DIRECTORY_SEPARATOR.self::ERROR_FILE_NAME;690 $lang=Prado::getPreferredLanguage();691 if(is_file("$base$statusCode-$lang.html"))692 $errorFile="$base$statusCode-$lang.html";693 else if(is_file("$base$statusCode.html"))694 $errorFile="$base$statusCode.html";695 else if(is_file("$base-$lang.html"))696 $errorFile="$base-$lang.html";697 else698 $errorFile="$base.html";699 if(($content=@file_get_contents($errorFile))===false)700 die("Unable to open error template file '$errorFile'.");701 return $content;702 }703 private function getExactTrace($exception)704 {705 $trace=$exception->getTrace();706 $result=null;707 if($exception instanceof TPhpErrorException)708 {709 if(isset($trace[0]['file']))710 $result=$trace[0];711 elseif(isset($trace[1]))712 $result=$trace[1];713 }714 else if($exception instanceof TInvalidOperationException)715 {716 if(($result=$this->getPropertyAccessTrace($trace,'__get'))===null)717 $result=$this->getPropertyAccessTrace($trace,'__set');718 }719 if($result!==null && strpos($result['file'],': eval()\'d code')!==false)720 return null;721 return $result;722 }723 private function getPropertyAccessTrace($trace,$pattern)724 {725 $result=null;726 foreach($trace as $t)727 {728 if(isset($t['function']) && $t['function']===$pattern)729 $result=$t;730 else731 break;732 }733 return $result;734 }735 private function getSourceCode($lines,$errorLine)736 {737 $beginLine=$errorLine-self::SOURCE_LINES>=0?$errorLine-self::SOURCE_LINES:0;738 $endLine=$errorLine+self::SOURCE_LINES<=count($lines)?$errorLine+self::SOURCE_LINES:count($lines);739 $source='';740 for($i=$beginLine;$i<$endLine;++$i)741 {742 if($i===$errorLine-1)743 {744 $line=htmlspecialchars(sprintf("%04d: %s",$i+1,str_replace("\t",' ',$lines[$i])));745 $source.="<div class=\"error\">".$line."</div>";746 }747 else748 $source.=htmlspecialchars(sprintf("%04d: %s",$i+1,str_replace("\t",' ',$lines[$i])));749 }750 return $source;751 }752 private function addLink($message)753 {754 $baseUrl='http://pradosoft.github.io/docs/manual/class-';755 return preg_replace('/\b(T[A-Z]\w+)\b/',"<a href=\"$baseUrl\${1}\" target=\"_blank\">\${1}</a>",$message);756 }757}758class TList extends TComponent implements IteratorAggregate,ArrayAccess,Countable759{760 private $_d=array();761 private $_c=0;762 private $_r=false;763 public function __construct($data=null,$readOnly=false)764 {765 if($data!==null)766 $this->copyFrom($data);767 $this->setReadOnly($readOnly);768 }769 public function getReadOnly()770 {771 return $this->_r;772 }773 protected function setReadOnly($value)774 {775 $this->_r=TPropertyValue::ensureBoolean($value);776 }777 public function getIterator()778 {779 return new ArrayIterator( $this->_d );780 }781 public function count()782 {783 return $this->getCount();784 }785 public function getCount()786 {787 return $this->_c;788 }789 public function itemAt($index)790 {791 if($index>=0 && $index<$this->_c)792 return $this->_d[$index];793 else794 throw new TInvalidDataValueException('list_index_invalid',$index);795 }796 public function add($item)797 {798 $this->insertAt($this->_c,$item);799 return $this->_c-1;800 }801 public function insertAt($index,$item)802 {803 if(!$this->_r)804 {805 if($index===$this->_c)806 $this->_d[$this->_c++]=$item;807 else if($index>=0 && $index<$this->_c)808 {809 array_splice($this->_d,$index,0,array($item));810 $this->_c++;811 }812 else813 throw new TInvalidDataValueException('list_index_invalid',$index);814 }815 else816 throw new TInvalidOperationException('list_readonly',get_class($this));817 }818 public function remove($item)819 {820 if(!$this->_r)821 {822 if(($index=$this->indexOf($item))>=0)823 {824 $this->removeAt($index);825 return $index;826 }827 else828 throw new TInvalidDataValueException('list_item_inexistent');829 }830 else831 throw new TInvalidOperationException('list_readonly',get_class($this));832 }833 public function removeAt($index)834 {835 if(!$this->_r)836 {837 if($index>=0 && $index<$this->_c)838 {839 $this->_c--;840 if($index===$this->_c)841 return array_pop($this->_d);842 else843 {844 $item=$this->_d[$index];845 array_splice($this->_d,$index,1);846 return $item;847 }848 }849 else850 throw new TInvalidDataValueException('list_index_invalid',$index);851 }852 else853 throw new TInvalidOperationException('list_readonly',get_class($this));854 }855 public function clear()856 {857 for($i=$this->_c-1;$i>=0;--$i)858 $this->removeAt($i);859 }860 public function contains($item)861 {862 return $this->indexOf($item)>=0;863 }864 public function indexOf($item)865 {866 if(($index=array_search($item,$this->_d,true))===false)867 return -1;868 else869 return $index;870 }871 public function insertBefore($baseitem, $item)872 {873 if(!$this->_r)874 {875 if(($index = $this->indexOf($baseitem)) == -1)876 throw new TInvalidDataValueException('list_item_inexistent');877 $this->insertAt($index, $item);878 return $index;879 }880 else881 throw new TInvalidOperationException('list_readonly',get_class($this));882 }883 public function insertAfter($baseitem, $item)884 {885 if(!$this->_r)886 {887 if(($index = $this->indexOf($baseitem)) == -1)888 throw new TInvalidDataValueException('list_item_inexistent');889 $this->insertAt($index + 1, $item);890 return $index + 1;891 }892 else893 throw new TInvalidOperationException('list_readonly',get_class($this));894 }895 public function toArray()896 {897 return $this->_d;898 }899 public function copyFrom($data)900 {901 if(is_array($data) || ($data instanceof Traversable))902 {903 if($this->_c>0)904 $this->clear();905 foreach($data as $item)906 $this->add($item);907 }908 else if($data!==null)909 throw new TInvalidDataTypeException('list_data_not_iterable');910 }911 public function mergeWith($data)912 {913 if(is_array($data) || ($data instanceof Traversable))914 {915 foreach($data as $item)916 $this->add($item);917 }918 else if($data!==null)919 throw new TInvalidDataTypeException('list_data_not_iterable');920 }921 public function offsetExists($offset)922 {923 return ($offset>=0 && $offset<$this->_c);924 }925 public function offsetGet($offset)926 {927 return $this->itemAt($offset);928 }929 public function offsetSet($offset,$item)930 {931 if($offset===null || $offset===$this->_c)932 $this->insertAt($this->_c,$item);933 else934 {935 $this->removeAt($offset);936 $this->insertAt($offset,$item);937 }938 }939 public function offsetUnset($offset)940 {941 $this->removeAt($offset);942 }943}944class TListIterator extends ArrayIterator945{946}947abstract class TCache extends TModule implements ICache, ArrayAccess948{949 private $_prefix=null;950 private $_primary=true;951 public function init($config)952 {953 if($this->_prefix===null)954 $this->_prefix=$this->getApplication()->getUniqueID();955 if($this->_primary)956 {957 if($this->getApplication()->getCache()===null)958 $this->getApplication()->setCache($this);959 else960 throw new TConfigurationException('cache_primary_duplicated',get_class($this));961 }962 }963 public function getPrimaryCache()964 {965 return $this->_primary;966 }967 public function setPrimaryCache($value)968 {969 $this->_primary=TPropertyValue::ensureBoolean($value);970 }971 public function getKeyPrefix()972 {973 return $this->_prefix;974 }975 public function setKeyPrefix($value)976 {977 $this->_prefix=$value;978 }979 protected function generateUniqueKey($key)980 {981 return md5($this->_prefix.$key);982 }983 public function get($id)984 {985 if(($data=$this->getValue($this->generateUniqueKey($id)))!==false)986 {987 if(!is_array($data))988 return false;989 if(!($data[1] instanceof ICacheDependency) || !$data[1]->getHasChanged())990 return $data[0];991 }992 return false;993 }994 public function set($id,$value,$expire=0,$dependency=null)995 {996 if(empty($value) && $expire === 0)997 $this->delete($id);998 else999 {1000 $data=array($value,$dependency);1001 return $this->setValue($this->generateUniqueKey($id),$data,$expire);1002 }1003 }1004 public function add($id,$value,$expire=0,$dependency=null)1005 {1006 if(empty($value) && $expire === 0)1007 return false;1008 $data=array($value,$dependency);1009 return $this->addValue($this->generateUniqueKey($id),$data,$expire);1010 }1011 public function delete($id)1012 {1013 return $this->deleteValue($this->generateUniqueKey($id));1014 }1015 public function flush()1016 {1017 throw new TNotSupportedException('cache_flush_unsupported');1018 }1019 abstract protected function getValue($key);1020 abstract protected function setValue($key,$value,$expire);1021 abstract protected function addValue($key,$value,$expire);1022 abstract protected function deleteValue($key);1023 public function offsetExists($id)1024 {1025 return $this->get($id) !== false;1026 }1027 public function offsetGet($id)1028 {1029 return $this->get($id);1030 }1031 public function offsetSet($id, $value)1032 {1033 $this->set($id, $value);1034 }1035 public function offsetUnset($id)1036 {1037 $this->delete($id);1038 }1039}1040abstract class TCacheDependency extends TComponent implements ICacheDependency1041{1042}1043class TFileCacheDependency extends TCacheDependency1044{1045 private $_fileName;1046 private $_timestamp;1047 public function __construct($fileName)1048 {1049 $this->setFileName($fileName);1050 }1051 public function getFileName()1052 {1053 return $this->_fileName;1054 }1055 public function setFileName($value)1056 {1057 $this->_fileName=$value;1058 $this->_timestamp=@filemtime($value);1059 }1060 public function getTimestamp()1061 {1062 return $this->_timestamp;1063 }1064 public function getHasChanged()1065 {1066 return @filemtime($this->_fileName)!==$this->_timestamp;1067 }1068}1069class TDirectoryCacheDependency extends TCacheDependency1070{1071 private $_recursiveCheck=true;1072 private $_recursiveLevel=-1;1073 private $_timestamps;1074 private $_directory;1075 public function __construct($directory)1076 {1077 $this->setDirectory($directory);1078 }1079 public function getDirectory()1080 {1081 return $this->_directory;1082 }1083 public function setDirectory($directory)1084 {1085 if(($path=realpath($directory))===false || !is_dir($path))1086 throw new TInvalidDataValueException('directorycachedependency_directory_invalid',$directory);1087 $this->_directory=$path;1088 $this->_timestamps=$this->generateTimestamps($path);1089 }1090 public function getRecursiveCheck()1091 {1092 return $this->_recursiveCheck;1093 }1094 public function setRecursiveCheck($value)1095 {1096 $this->_recursiveCheck=TPropertyValue::ensureBoolean($value);1097 }1098 public function getRecursiveLevel()1099 {1100 return $this->_recursiveLevel;1101 }1102 public function setRecursiveLevel($value)1103 {1104 $this->_recursiveLevel=TPropertyValue::ensureInteger($value);1105 }1106 public function getHasChanged()1107 {1108 return $this->generateTimestamps($this->_directory)!=$this->_timestamps;1109 }1110 protected function validateFile($fileName)1111 {1112 return true;1113 }1114 protected function validateDirectory($directory)1115 {1116 return true;1117 }1118 protected function generateTimestamps($directory,$level=0)1119 {1120 if(($dir=opendir($directory))===false)1121 throw new TIOException('directorycachedependency_directory_invalid',$directory);1122 $timestamps=array();1123 while(($file=readdir($dir))!==false)1124 {1125 $path=$directory.DIRECTORY_SEPARATOR.$file;1126 if($file==='.' || $file==='..')1127 continue;1128 else if(is_dir($path))1129 {1130 if(($this->_recursiveLevel<0 || $level<$this->_recursiveLevel) && $this->validateDirectory($path))1131 $timestamps=array_merge($this->generateTimestamps($path,$level+1));1132 }1133 else if($this->validateFile($path))1134 $timestamps[$path]=filemtime($path);1135 }1136 closedir($dir);1137 return $timestamps;1138 }1139}1140class TGlobalStateCacheDependency extends TCacheDependency1141{1142 private $_stateName;1143 private $_stateValue;1144 public function __construct($name)1145 {1146 $this->setStateName($name);1147 }1148 public function getStateName()1149 {1150 return $this->_stateName;1151 }1152 public function setStateName($value)1153 {1154 $this->_stateName=$value;1155 $this->_stateValue=Prado::getApplication()->getGlobalState($value);1156 }1157 public function getHasChanged()1158 {1159 return $this->_stateValue!==Prado::getApplication()->getGlobalState($this->_stateName);1160 }1161}1162class TChainedCacheDependency extends TCacheDependency1163{1164 private $_dependencies=null;1165 public function getDependencies()1166 {1167 if($this->_dependencies===null)1168 $this->_dependencies=new TCacheDependencyList;1169 return $this->_dependencies;1170 }1171 public function getHasChanged()1172 {1173 if($this->_dependencies!==null)1174 {1175 foreach($this->_dependencies as $dependency)1176 if($dependency->getHasChanged())1177 return true;1178 }1179 return false;1180 }1181}1182class TApplicationStateCacheDependency extends TCacheDependency1183{1184 public function getHasChanged()1185 {1186 return Prado::getApplication()->getMode()!==TApplicationMode::Performance;1187 }1188}1189class TCacheDependencyList extends TList1190{1191 public function insertAt($index,$item)1192 {1193 if($item instanceof ICacheDependency)1194 parent::insertAt($index,$item);1195 else1196 throw new TInvalidDataTypeException('cachedependencylist_cachedependency_required');1197 }1198}1199class TTextWriter extends TComponent implements ITextWriter1200{1201 private $_str='';1202 public function flush()1203 {1204 $str=$this->_str;1205 $this->_str='';1206 return $str;1207 }1208 public function write($str)1209 {1210 $this->_str.=$str;1211 }1212 public function writeLine($str='')1213 {1214 $this->write($str."\n");1215 }1216}1217class TPriorityList extends TList1218{1219 private $_d=array();1220 private $_o=false;1221 private $_fd=null;1222 private $_c=0;1223 private $_dp=10;1224 private $_p=8;1225 public function __construct($data=null,$readOnly=false,$defaultPriority=10,$precision=8)1226 {1227 parent::__construct();1228 if($data!==null)1229 $this->copyFrom($data);1230 $this->setReadOnly($readOnly);1231 $this->setPrecision($precision);1232 $this->setDefaultPriority($defaultPriority);1233 }1234 public function count()1235 {1236 return $this->getCount();1237 }1238 public function getCount()1239 {1240 return $this->_c;1241 }1242 public function getPriorityCount($priority=null)1243 {1244 if($priority===null)1245 $priority=$this->getDefaultPriority();1246 $priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p);1247 if(!isset($this->_d[$priority]) || !is_array($this->_d[$priority]))1248 return false;1249 return count($this->_d[$priority]);1250 }1251 public function getDefaultPriority()1252 {1253 return $this->_dp;1254 }1255 protected function setDefaultPriority($value)1256 {1257 $this->_dp=(string)round(TPropertyValue::ensureFloat($value),$this->_p);1258 }1259 public function getPrecision()1260 {1261 return $this->_p;1262 }1263 protected function setPrecision($value)1264 {1265 $this->_p=TPropertyValue::ensureInteger($value);1266 }1267 public function getIterator()1268 {1269 return new ArrayIterator($this->flattenPriorities());1270 }1271 public function getPriorities()1272 {1273 $this->sortPriorities();1274 return array_keys($this->_d);1275 }1276 protected function sortPriorities() {1277 if(!$this->_o) {1278 ksort($this->_d,SORT_NUMERIC);1279 $this->_o=true;1280 }1281 }1282 protected function flattenPriorities() {1283 if(is_array($this->_fd))1284 return $this->_fd;1285 $this->sortPriorities();1286 $this->_fd=array();1287 foreach($this->_d as $priority => $itemsatpriority)1288 $this->_fd=array_merge($this->_fd,$itemsatpriority);1289 return $this->_fd;1290 }1291 public function itemAt($index)1292 {1293 if($index>=0&&$index<$this->getCount()) {1294 $arr=$this->flattenPriorities();1295 return $arr[$index];1296 } else1297 throw new TInvalidDataValueException('list_index_invalid',$index);1298 }1299 public function itemsAtPriority($priority=null)1300 {1301 if($priority===null)1302 $priority=$this->getDefaultPriority();1303 $priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p);1304 return isset($this->_d[$priority])?$this->_d[$priority]:null;1305 }1306 public function itemAtIndexInPriority($index,$priority=null)1307 {1308 if($priority===null)1309 $priority=$this->getDefaultPriority();1310 $priority=(string)round(TPropertyValue::ensureFloat($priority), $this->_p);1311 return !isset($this->_d[$priority])?false:(1312 isset($this->_d[$priority][$index])?$this->_d[$priority][$index]:false1313 );1314 }1315 public function add($item,$priority=null)1316 {1317 if($this->getReadOnly())1318 throw new TInvalidOperationException('list_readonly',get_class($this));1319 return $this->insertAtIndexInPriority($item,false,$priority,true);1320 }1321 public function insertAt($index,$item)1322 {1323 if($this->getReadOnly())1324 throw new TInvalidOperationException('list_readonly',get_class($this));1325 if(($priority=$this->priorityAt($index,true))!==false)1326 $this->insertAtIndexInPriority($item,$priority[1],$priority[0]);1327 else1328 throw new TInvalidDataValueException('list_index_invalid',$index);1329 }1330 public function insertAtIndexInPriority($item,$index=false,$priority=null,$preserveCache=false)1331 {1332 if($this->getReadOnly())1333 throw new TInvalidOperationException('list_readonly',get_class($this));1334 if($priority===null)1335 $priority=$this->getDefaultPriority();1336 $priority=(string)round(TPropertyValue::ensureFloat($priority), $this->_p);1337 if($preserveCache) {1338 $this->sortPriorities();1339 $cc=0;1340 foreach($this->_d as $prioritykey=>$items)1341 if($prioritykey>=$priority)1342 break;1343 else1344 $cc+=count($items);1345 if($index===false&&isset($this->_d[$priority])) {1346 $c=count($this->_d[$priority]);1347 $c+=$cc;1348 $this->_d[$priority][]=$item;1349 } else if(isset($this->_d[$priority])) {1350 $c=$index+$cc;1351 array_splice($this->_d[$priority],$index,0,array($item));1352 } else {1353 $c = $cc;1354 $this->_o = false;1355 $this->_d[$priority]=array($item);1356 }1357 if($this->_fd&&is_array($this->_fd)) array_splice($this->_fd,$c,0,array($item));1358 } else {1359 $c=null;1360 if($index===false&&isset($this->_d[$priority])) {1361 $cc=count($this->_d[$priority]);1362 $this->_d[$priority][]=$item;1363 } else if(isset($this->_d[$priority])) {1364 $cc=$index;1365 array_splice($this->_d[$priority],$index,0,array($item));1366 } else {1367 $cc=0;1368 $this->_o=false;1369 $this->_d[$priority]=array($item);1370 }1371 if($this->_fd&&is_array($this->_fd)&&count($this->_d)==1)1372 array_splice($this->_fd,$cc,0,array($item));1373 else1374 $this->_fd=null;1375 }1376 $this->_c++;1377 return $c;1378 }1379 public function remove($item,$priority=false)1380 {1381 if($this->getReadOnly())1382 throw new TInvalidOperationException('list_readonly',get_class($this));1383 if(($p=$this->priorityOf($item,true))!==false)1384 {1385 if($priority!==false) {1386 if($priority===null)1387 $priority=$this->getDefaultPriority();1388 $priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p);1389 if($p[0]!=$priority)1390 throw new TInvalidDataValueException('list_item_inexistent');1391 }1392 $this->removeAtIndexInPriority($p[1],$p[0]);1393 return $p[2];1394 }1395 else1396 throw new TInvalidDataValueException('list_item_inexistent');1397 }1398 public function removeAt($index)1399 {1400 if($this->getReadOnly())1401 throw new TInvalidOperationException('list_readonly',get_class($this));1402 if(($priority=$this->priorityAt($index, true))!==false)1403 return $this->removeAtIndexInPriority($priority[1],$priority[0]);1404 throw new TInvalidDataValueException('list_index_invalid',$index);1405 }1406 public function removeAtIndexInPriority($index, $priority=null)1407 {1408 if($this->getReadOnly())1409 throw new TInvalidOperationException('list_readonly',get_class($this));1410 if($priority===null)1411 $priority=$this->getDefaultPriority();1412 $priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p);1413 if(!isset($this->_d[$priority])||$index<0||$index>=count($this->_d[$priority]))1414 throw new TInvalidDataValueException('list_item_inexistent');1415 $value=array_splice($this->_d[$priority],$index,1);1416 $value=$value[0];1417 if(!count($this->_d[$priority]))1418 unset($this->_d[$priority]);1419 $this->_c--;1420 $this->_fd=null;1421 return $value;1422 }1423 public function clear()1424 {1425 if($this->getReadOnly())1426 throw new TInvalidOperationException('list_readonly',get_class($this));1427 $d=array_reverse($this->_d,true);1428 foreach($this->_d as $priority=>$items) {1429 for($index=count($items)-1;$index>=0;$index--)1430 $this->removeAtIndexInPriority($index,$priority);1431 unset($this->_d[$priority]);1432 }1433 }1434 public function contains($item)1435 {1436 return $this->indexOf($item)>=0;1437 }1438 public function indexOf($item)1439 {1440 if(($index=array_search($item,$this->flattenPriorities(),true))===false)1441 return -1;1442 else1443 return $index;1444 }1445 public function priorityOf($item,$withindex = false)1446 {1447 $this->sortPriorities();1448 $absindex = 0;1449 foreach($this->_d as $priority=>$items) {1450 if(($index=array_search($item,$items,true))!==false) {1451 $absindex+=$index;1452 return $withindex?array($priority,$index,$absindex,1453 'priority'=>$priority,'index'=>$index,'absindex'=>$absindex):$priority;1454 } else1455 $absindex+=count($items);1456 }1457 return false;1458 }1459 public function priorityAt($index,$withindex = false)1460 {1461 if($index<0||$index>=$this->getCount())1462 throw new TInvalidDataValueException('list_index_invalid',$index);1463 $absindex=$index;1464 $this->sortPriorities();1465 foreach($this->_d as $priority=>$items) {1466 if($index>=($c=count($items)))1467 $index-=$c;1468 else1469 return $withindex?array($priority,$index,$absindex,1470 'priority'=>$priority,'index'=>$index,'absindex'=>$absindex):$priority;1471 }1472 return false;1473 }1474 public function insertBefore($indexitem, $item)1475 {1476 if($this->getReadOnly())1477 throw new TInvalidOperationException('list_readonly',get_class($this));1478 if(($priority=$this->priorityOf($indexitem,true))===false)1479 throw new TInvalidDataValueException('list_item_inexistent');1480 $this->insertAtIndexInPriority($item,$priority[1],$priority[0]);1481 return $priority[2];1482 }1483 public function insertAfter($indexitem, $item)1484 {1485 if($this->getReadOnly())1486 throw new TInvalidOperationException('list_readonly',get_class($this));1487 if(($priority=$this->priorityOf($indexitem,true))===false)1488 throw new TInvalidDataValueException('list_item_inexistent');1489 $this->insertAtIndexInPriority($item,$priority[1]+1,$priority[0]);1490 return $priority[2]+1;1491 }1492 public function toArray()1493 {1494 return $this->flattenPriorities();1495 }1496 public function toPriorityArray()1497 {1498 $this->sortPriorities();1499 return $this->_d;1500 }1501 public function toArrayBelowPriority($priority,$inclusive=false)1502 {1503 $this->sortPriorities();1504 $items=array();1505 foreach($this->_d as $itemspriority=>$itemsatpriority)1506 {1507 if((!$inclusive&&$itemspriority>=$priority)||$itemspriority>$priority)1508 break;1509 $items=array_merge($items,$itemsatpriority);1510 }1511 return $items;1512 }1513 public function toArrayAbovePriority($priority,$inclusive=true)1514 {1515 $this->sortPriorities();1516 $items=array();1517 foreach($this->_d as $itemspriority=>$itemsatpriority)1518 {1519 if((!$inclusive&&$itemspriority<=$priority)||$itemspriority<$priority)1520 continue;1521 $items=array_merge($items,$itemsatpriority);1522 }1523 return $items;1524 }1525 public function copyFrom($data)1526 {1527 if($data instanceof TPriorityList)1528 {1529 if($this->getCount()>0)1530 $this->clear();1531 foreach($data->getPriorities() as $priority)1532 {1533 foreach($data->itemsAtPriority($priority) as $index=>$item)1534 $this->insertAtIndexInPriority($item,$index,$priority);1535 }1536 } else if(is_array($data)||$data instanceof Traversable) {1537 if($this->getCount()>0)1538 $this->clear();1539 foreach($data as $key=>$item)1540 $this->add($item);1541 } else if($data!==null)1542 throw new TInvalidDataTypeException('map_data_not_iterable');1543 }1544 public function mergeWith($data)1545 {1546 if($data instanceof TPriorityList)1547 {1548 foreach($data->getPriorities() as $priority)1549 {1550 foreach($data->itemsAtPriority($priority) as $index=>$item)1551 $this->insertAtIndexInPriority($item,false,$priority);1552 }1553 }1554 else if(is_array($data)||$data instanceof Traversable)1555 {1556 foreach($data as $priority=>$item)1557 $this->add($item);1558 }1559 else if($data!==null)1560 throw new TInvalidDataTypeException('map_data_not_iterable');1561 }1562 public function offsetExists($offset)1563 {1564 return ($offset>=0&&$offset<$this->getCount());1565 }1566 public function offsetGet($offset)1567 {1568 return $this->itemAt($offset);1569 }1570 public function offsetSet($offset,$item)1571 {1572 if($offset===null)1573 return $this->add($item);1574 if($offset===$this->getCount()) {1575 $priority=$this->priorityAt($offset-1,true);1576 $priority[1]++;1577 } else {1578 $priority=$this->priorityAt($offset,true);1579 $this->removeAtIndexInPriority($priority[1],$priority[0]);1580 }1581 $this->insertAtIndexInPriority($item,$priority[1],$priority[0]);1582 }1583 public function offsetUnset($offset)1584 {1585 $this->removeAt($offset);1586 }1587}1588class TMap extends TComponent implements IteratorAggregate,ArrayAccess,Countable1589{1590 private $_d=array();1591 private $_r=false;1592 protected function _getZappableSleepProps(&$exprops)1593 {1594 parent::_getZappableSleepProps($exprops);1595 if ($this->_d===array())1596 $exprops[] = "\0TMap\0_d";1597 if ($this->_r===false)1598 $exprops[] = "\0TMap\0_r";1599 }1600 public function __construct($data=null,$readOnly=false)1601 {1602 if($data!==null)1603 $this->copyFrom($data);1604 $this->setReadOnly($readOnly);1605 }1606 public function getReadOnly()1607 {1608 return $this->_r;1609 }1610 protected function setReadOnly($value)1611 {1612 $this->_r=TPropertyValue::ensureBoolean($value);1613 }1614 public function getIterator()1615 {1616 return new ArrayIterator( $this->_d );1617 }1618 public function count()1619 {1620 return $this->getCount();1621 }1622 public function getCount()1623 {1624 return count($this->_d);1625 }1626 public function getKeys()1627 {1628 return array_keys($this->_d);1629 }1630 public function itemAt($key)1631 {1632 return isset($this->_d[$key]) ? $this->_d[$key] : null;1633 }1634 public function add($key,$value)1635 {1636 if(!$this->_r)1637 $this->_d[$key]=$value;1638 else1639 throw new TInvalidOperationException('map_readonly',get_class($this));1640 }1641 public function remove($key)1642 {1643 if(!$this->_r)1644 {1645 if(isset($this->_d[$key]) || array_key_exists($key,$this->_d))1646 {1647 $value=$this->_d[$key];1648 unset($this->_d[$key]);1649 return $value;1650 }1651 else1652 return null;1653 }1654 else1655 throw new TInvalidOperationException('map_readonly',get_class($this));1656 }1657 public function clear()1658 {1659 foreach(array_keys($this->_d) as $key)1660 $this->remove($key);1661 }1662 public function contains($key)1663 {1664 return isset($this->_d[$key]) || array_key_exists($key,$this->_d);1665 }1666 public function toArray()1667 {1668 return $this->_d;1669 }1670 public function copyFrom($data)1671 {1672 if(is_array($data) || $data instanceof Traversable)1673 {1674 if($this->getCount()>0)1675 $this->clear();1676 foreach($data as $key=>$value)1677 $this->add($key,$value);1678 }1679 else if($data!==null)1680 throw new TInvalidDataTypeException('map_data_not_iterable');1681 }1682 public function mergeWith($data)1683 {1684 if(is_array($data) || $data instanceof Traversable)1685 {1686 foreach($data as $key=>$value)1687 $this->add($key,$value);1688 }1689 else if($data!==null)1690 throw new TInvalidDataTypeException('map_data_not_iterable');1691 }1692 public function offsetExists($offset)1693 {1694 return $this->contains($offset);1695 }1696 public function offsetGet($offset)1697 {1698 return $this->itemAt($offset);1699 }1700 public function offsetSet($offset,$item)1701 {1702 $this->add($offset,$item);1703 }1704 public function offsetUnset($offset)1705 {1706 $this->remove($offset);1707 }1708}1709class TMapIterator extends ArrayIterator1710{1711}1712class TPriorityMap extends TMap1713{1714 private $_d=array();1715 private $_r=false;1716 private $_o=false;1717 private $_fd=null;1718 private $_c=0;1719 private $_dp=10;1720 private $_p=8;1721 public function __construct($data=null,$readOnly=false,$defaultPriority=10,$precision=8)1722 {1723 if($data!==null)1724 $this->copyFrom($data);1725 $this->setReadOnly($readOnly);1726 $this->setPrecision($precision);1727 $this->setDefaultPriority($defaultPriority);1728 }1729 public function getReadOnly()1730 {1731 return $this->_r;1732 }1733 protected function setReadOnly($value)1734 {1735 $this->_r=TPropertyValue::ensureBoolean($value);1736 }1737 public function getDefaultPriority()1738 {1739 return $this->_dp;1740 }1741 protected function setDefaultPriority($value)1742 {1743 $this->_dp = (string)round(TPropertyValue::ensureFloat($value), $this->_p);1744 }1745 public function getPrecision()1746 {1747 return $this->_p;1748 }1749 protected function setPrecision($value)1750 {1751 $this->_p=TPropertyValue::ensureInteger($value);1752 }1753 public function getIterator()1754 {1755 return new ArrayIterator($this->flattenPriorities());1756 }1757 protected function sortPriorities() {1758 if(!$this->_o) {1759 ksort($this->_d, SORT_NUMERIC);1760 $this->_o=true;1761 }1762 }1763 protected function flattenPriorities() {1764 if(is_array($this->_fd))1765 return $this->_fd;1766 $this->sortPriorities();1767 $this->_fd = array();1768 foreach($this->_d as $priority => $itemsatpriority)1769 $this->_fd = array_merge($this->_fd, $itemsatpriority);1770 return $this->_fd;1771 }1772 public function count()1773 {1774 return $this->getCount();1775 }1776 public function getCount()1777 {1778 return $this->_c;1779 }1780 public function getPriorityCount($priority=null)1781 {1782 if($priority===null)1783 $priority=$this->getDefaultPriority();1784 $priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p);1785 if(!isset($this->_d[$priority])||!is_array($this->_d[$priority]))1786 return false;1787 return count($this->_d[$priority]);1788 }1789 public function getPriorities()1790 {1791 $this->sortPriorities();1792 return array_keys($this->_d);1793 }1794 public function getKeys()1795 {1796 return array_keys($this->flattenPriorities());1797 }1798 public function itemAt($key,$priority=false)1799 {1800 if($priority===false){1801 $map=$this->flattenPriorities();1802 return isset($map[$key])?$map[$key]:null;1803 } else {1804 if($priority===null)1805 $priority=$this->getDefaultPriority();1806 $priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p);1807 return (isset($this->_d[$priority])&&isset($this->_d[$priority][$key]))?$this->_d[$priority][$key]:null;1808 }1809 }1810 public function setPriorityAt($key,$priority=null)1811 {1812 if($priority===null)1813 $priority=$this->getDefaultPriority();1814 $priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p);1815 $oldpriority=$this->priorityAt($key);1816 if($oldpriority!==false&&$oldpriority!=$priority) {1817 $value=$this->remove($key,$oldpriority);1818 $this->add($key,$value,$priority);1819 }1820 return $oldpriority;1821 }1822 public function itemsAtPriority($priority=null)1823 {1824 if($priority===null)1825 $priority=$this->getDefaultPriority();1826 $priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p);1827 return isset($this->_d[$priority])?$this->_d[$priority]:null;1828 }1829 public function priorityOf($item)1830 {1831 $this->sortPriorities();1832 foreach($this->_d as $priority=>$items)1833 if(($index=array_search($item,$items,true))!==false)1834 return $priority;1835 return false;1836 }1837 public function priorityAt($key)1838 {1839 $this->sortPriorities();1840 foreach($this->_d as $priority=>$items)1841 if(array_key_exists($key,$items))1842 return $priority;1843 return false;1844 }1845 public function add($key,$value,$priority=null)1846 {1847 if($priority===null)1848 $priority=$this->getDefaultPriority();1849 $priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p);1850 if(!$this->_r)1851 {1852 foreach($this->_d as $innerpriority=>$items)1853 if(array_key_exists($key,$items))1854 {1855 unset($this->_d[$innerpriority][$key]);1856 $this->_c--;1857 if(count($this->_d[$innerpriority])===0)1858 unset($this->_d[$innerpriority]);1859 }1860 if(!isset($this->_d[$priority])) {1861 $this->_d[$priority]=array($key=>$value);1862 $this->_o=false;1863 }1864 else1865 $this->_d[$priority][$key]=$value;1866 $this->_c++;1867 $this->_fd=null;1868 }1869 else1870 throw new TInvalidOperationException('map_readonly',get_class($this));1871 return $priority;1872 }1873 public function remove($key,$priority=false)1874 {1875 if(!$this->_r)1876 {1877 if($priority===null)1878 $priority=$this->getDefaultPriority();1879 if($priority===false)1880 {1881 $this->sortPriorities();1882 foreach($this->_d as $priority=>$items)1883 if(array_key_exists($key,$items))1884 {1885 $value=$this->_d[$priority][$key];1886 unset($this->_d[$priority][$key]);1887 $this->_c--;1888 if(count($this->_d[$priority])===0)1889 {1890 unset($this->_d[$priority]);1891 $this->_o=false;1892 }1893 $this->_fd=null;1894 return $value;1895 }1896 return null;1897 }1898 else1899 {1900 $priority=(string)round(TPropertyValue::ensureFloat($priority),$this->_p);1901 if(isset($this->_d[$priority])&&(isset($this->_d[$priority][$key])||array_key_exists($key,$this->_d[$priority])))1902 {1903 $value=$this->_d[$priority][$key];1904 unset($this->_d[$priority][$key]);1905 $this->_c--;1906 if(count($this->_d[$priority])===0) {1907 unset($this->_d[$priority]);1908 $this->_o=false;1909 }1910 $this->_fd=null;1911 return $value;1912 }1913 else1914 return null;1915 }1916 }1917 else1918 throw new TInvalidOperationException('map_readonly',get_class($this));1919 }1920 public function clear()1921 {1922 foreach($this->_d as $priority=>$items)1923 foreach(array_keys($items) as $key)1924 $this->remove($key);1925 }1926 public function contains($key)1927 {1928 $map=$this->flattenPriorities();1929 return isset($map[$key])||array_key_exists($key,$map);1930 }1931 public function toArray()1932 {1933 return $this->flattenPriorities();1934 }1935 public function toArrayBelowPriority($priority,$inclusive=false)1936 {1937 $this->sortPriorities();1938 $items=array();1939 foreach($this->_d as $itemspriority=>$itemsatpriority)1940 {1941 if((!$inclusive&&$itemspriority>=$priority)||$itemspriority>$priority)1942 break;1943 $items=array_merge($items,$itemsatpriority);1944 }1945 return $items;1946 }1947 public function toArrayAbovePriority($priority,$inclusive=true)1948 {1949 $this->sortPriorities();1950 $items=array();1951 foreach($this->_d as $itemspriority=>$itemsatpriority)1952 {1953 if((!$inclusive&&$itemspriority<=$priority)||$itemspriority<$priority)1954 continue;1955 $items=array_merge($items,$itemsatpriority);1956 }1957 return $items;1958 }1959 public function copyFrom($data)1960 {1961 if($data instanceof TPriorityMap)1962 {1963 if($this->getCount()>0)1964 $this->clear();1965 foreach($data->getPriorities() as $priority) {1966 foreach($data->itemsAtPriority($priority) as $key => $value) {1967 $this->add($key,$value,$priority);1968 }1969 }1970 }1971 else if(is_array($data)||$data instanceof Traversable)1972 {1973 if($this->getCount()>0)1974 $this->clear();1975 foreach($data as $key=>$value)1976 $this->add($key,$value);1977 }1978 else if($data!==null)1979 throw new TInvalidDataTypeException('map_data_not_iterable');1980 }1981 public function mergeWith($data)1982 {1983 if($data instanceof TPriorityMap)1984 {1985 foreach($data->getPriorities() as $priority)1986 {1987 foreach($data->itemsAtPriority($priority) as $key => $value)1988 $this->add($key,$value,$priority);1989 }1990 }1991 else if(is_array($data)||$data instanceof Traversable)1992 {1993 foreach($data as $key=>$value)1994 $this->add($key,$value);1995 }1996 else if($data!==null)1997 throw new TInvalidDataTypeException('map_data_not_iterable');1998 }1999 public function offsetExists($offset)2000 {2001 return $this->contains($offset);2002 }2003 public function offsetGet($offset)2004 {2005 return $this->itemAt($offset);2006 }2007 public function offsetSet($offset,$item)2008 {2009 $this->add($offset,$item);2010 }2011 public function offsetUnset($offset)2012 {2013 $this->remove($offset);2014 }2015}2016class TStack extends TComponent implements IteratorAggregate,Countable2017{2018 private $_d=array();2019 private $_c=0;2020 public function __construct($data=null)2021 {2022 if($data!==null)2023 $this->copyFrom($data);2024 }2025 public function toArray()2026 {2027 return $this->_d;2028 }2029 public function copyFrom($data)2030 {2031 if(is_array($data) || ($data instanceof Traversable))2032 {2033 $this->clear();2034 foreach($data as $item)2035 {2036 $this->_d[]=$item;2037 ++$this->_c;2038 }2039 }2040 else if($data!==null)2041 throw new TInvalidDataTypeException('stack_data_not_iterable');2042 }2043 public function clear()2044 {2045 $this->_c=0;2046 $this->_d=array();2047 }2048 public function contains($item)2049 {2050 return array_search($item,$this->_d,true)!==false;2051 }2052 public function peek()2053 {2054 if($this->_c===0)2055 throw new TInvalidOperationException('stack_empty');2056 else2057 return $this->_d[$this->_c-1];2058 }2059 public function pop()2060 {2061 if($this->_c===0)2062 throw new TInvalidOperationException('stack_empty');2063 else2064 {2065 --$this->_c;2066 return array_pop($this->_d);2067 }2068 }2069 public function push($item)2070 {2071 ++$this->_c;2072 $this->_d[] = $item;2073 }2074 public function getIterator()2075 {2076 return new ArrayIterator( $this->_d );2077 }2078 public function getCount()2079 {2080 return $this->_c;2081 }2082 public function count()2083 {2084 return $this->getCount();2085 }2086}2087class TStackIterator implements Iterator2088{2089 private $_d;2090 private $_i;2091 private $_c;2092 public function __construct(&$data)2093 {2094 $this->_d=&$data;2095 $this->_i=0;2096 $this->_c=count($this->_d);2097 }2098 public function rewind()2099 {2100 $this->_i=0;2101 }2102 public function key()2103 {2104 return $this->_i;2105 }2106 public function current()2107 {2108 return $this->_d[$this->_i];2109 }2110 public function next()2111 {2112 $this->_i++;2113 }2114 public function valid()2115 {2116 return $this->_i<$this->_c;2117 }2118}2119class TXmlElement extends TComponent2120{2121 private $_parent=null;2122 private $_tagName='unknown';2123 private $_value='';2124 private $_elements=null;2125 private $_attributes=null;2126 public function __construct($tagName)2127 {2128 $this->setTagName($tagName);2129 }2130 public function getParent()2131 {2132 return $this->_parent;2133 }2134 public function setParent($parent)2135 {2136 $this->_parent=$parent;2137 }2138 public function getTagName()2139 {2140 return $this->_tagName;2141 }2142 public function setTagName($tagName)2143 {2144 $this->_tagName=$tagName;2145 }2146 public function getValue()2147 {2148 return $this->_value;2149 }2150 public function setValue($value)2151 {2152 $this->_value=TPropertyValue::ensureString($value);2153 }2154 public function getHasElement()2155 {2156 return $this->_elements!==null && $this->_elements->getCount()>0;2157 }2158 public function getHasAttribute()2159 {2160 return $this->_attributes!==null && $this->_attributes->getCount()>0;2161 }2162 public function getAttribute($name)2163 {2164 if($this->_attributes!==null)2165 return $this->_attributes->itemAt($name);2166 else2167 return null;2168 }2169 public function setAttribute($name,$value)2170 {2171 $this->getAttributes()->add($name,TPropertyValue::ensureString($value));2172 }2173 public function getElements()2174 {2175 if(!$this->_elements)2176 $this->_elements=new TXmlElementList($this);2177 return $this->_elements;2178 }2179 public function getAttributes()2180 {2181 if(!$this->_attributes)2182 $this->_attributes=new TMap;2183 return $this->_attributes;2184 }2185 public function getElementByTagName($tagName)2186 {2187 if($this->_elements)2188 {2189 foreach($this->_elements as $element)2190 if($element->_tagName===$tagName)2191 return $element;2192 }2193 return null;2194 }2195 public function getElementsByTagName($tagName)2196 {2197 $list=new TList;2198 if($this->_elements)2199 {2200 foreach($this->_elements as $element)2201 if($element->_tagName===$tagName)2202 $list->add($element);2203 }2204 return $list;2205 }2206 public function toString($indent=0)2207 {2208 $attr='';2209 if($this->_attributes!==null)2210 {2211 foreach($this->_attributes as $name=>$value)2212 {2213 $value=$this->xmlEncode($value);2214 $attr.=" $name=\"$value\"";2215 }2216 }2217 $prefix=str_repeat(' ',$indent*4);2218 if($this->getHasElement())2219 {2220 $str=$prefix."<{$this->_tagName}$attr>\n";2221 foreach($this->getElements() as $element)2222 $str.=$element->toString($indent+1)."\n";2223 $str.=$prefix."</{$this->_tagName}>";2224 return $str;2225 }2226 else if(($value=$this->getValue())!=='')2227 {2228 $value=$this->xmlEncode($value);2229 return $prefix."<{$this->_tagName}$attr>$value</{$this->_tagName}>";2230 }2231 else2232 return $prefix."<{$this->_tagName}$attr />";2233 }2234 public function __toString()2235 {2236 return $this->toString();2237 }2238 private function xmlEncode($str)2239 {2240 return strtr($str,array(2241 '>'=>'&gt;',2242 '<'=>'&lt;',2243 '&'=>'&amp;',2244 '"'=>'&quot;',2245 "\r"=>'&#xD;',2246 "\t"=>'&#x9;',2247 "\n"=>'&#xA;'));2248 }2249}2250class TXmlDocument extends TXmlElement2251{2252 private $_version;2253 private $_encoding;2254 public function __construct($version='1.0',$encoding='')2255 {2256 parent::__construct('');2257 $this->setVersion($version);2258 $this->setEncoding($encoding);2259 }2260 public function getVersion()2261 {2262 return $this->_version;2263 }2264 public function setVersion($version)2265 {2266 $this->_version=$version;2267 }2268 public function getEncoding()2269 {2270 return $this->_encoding;2271 }2272 public function setEncoding($encoding)2273 {2274 $this->_encoding=$encoding;2275 }2276 public function loadFromFile($file)2277 {2278 if(($str=@file_get_contents($file))!==false)2279 return $this->loadFromString($str);2280 else2281 throw new TIOException('xmldocument_file_read_failed',$file);2282 }2283 public function loadFromString($string)2284 {2285 $doc=new DOMDocument();2286 if($doc->loadXML($string)===false)2287 return false;2288 $this->setEncoding($doc->encoding);2289 $this->setVersion($doc->xmlVersion);2290 $element=$doc->documentElement;2291 $this->setTagName($element->tagName);2292 $this->setValue($element->nodeValue);2293 $elements=$this->getElements();2294 $attributes=$this->getAttributes();2295 $elements->clear();2296 $attributes->clear();2297 static $bSimpleXml;2298 if($bSimpleXml === null)2299 $bSimpleXml = (boolean)function_exists('simplexml_load_string');2300 if($bSimpleXml)2301 {2302 $simpleDoc = simplexml_load_string($string);2303 $docNamespaces = $simpleDoc->getDocNamespaces(false);2304 $simpleDoc = null;2305 foreach($docNamespaces as $prefix => $uri)2306 {2307 if($prefix === '')2308 $attributes->add('xmlns', $uri);2309 else2310 $attributes->add('xmlns:'.$prefix, $uri);2311 }2312 }2313 foreach($element->attributes as $name=>$attr)2314 $attributes->add(($attr->prefix === '' ? '' : $attr->prefix . ':') .$name,$attr->value);2315 foreach($element->childNodes as $child)2316 {2317 if($child instanceof DOMElement)2318 $elements->add($this->buildElement($child));2319 }2320 return true;2321 }2322 public function saveToFile($file)2323 {2324 if(($fw=fopen($file,'w'))!==false)2325 {2326 fwrite($fw,$this->saveToString());2327 fclose($fw);2328 }2329 else2330 throw new TIOException('xmldocument_file_write_failed',$file);2331 }2332 public function saveToString()2333 {2334 $version=empty($this->_version)?' version="1.0"':' version="'.$this->_version.'"';2335 $encoding=empty($this->_encoding)?'':' encoding="'.$this->_encoding.'"';2336 return "<?xml{$version}{$encoding}?>\n".$this->toString(0);2337 }2338 public function __toString()2339 {2340 return $this->saveToString();2341 }2342 protected function buildElement($node)2343 {2344 $element=new TXmlElement($node->tagName);2345 $element->setValue($node->nodeValue);2346 foreach($node->attributes as $name=>$attr)2347 $element->getAttributes()->add(($attr->prefix === '' ? '' : $attr->prefix . ':') . $name,$attr->value);2348 foreach($node->childNodes as $child)2349 {2350 if($child instanceof DOMElement)2351 $element->getElements()->add($this->buildElement($child));2352 }2353 return $element;2354 }2355}2356class TXmlElementList extends TList2357{2358 private $_o;2359 public function __construct(TXmlElement $owner)2360 {2361 $this->_o=$owner;2362 }2363 protected function getOwner()2364 {2365 return $this->_o;2366 }2367 public function insertAt($index,$item)2368 {2369 if($item instanceof TXmlElement)2370 {2371 parent::insertAt($index,$item);2372 if($item->getParent()!==null)2373 $item->getParent()->getElements()->remove($item);2374 $item->setParent($this->_o);2375 }2376 else2377 throw new TInvalidDataTypeException('xmlelementlist_xmlelement_required');2378 }2379 public function removeAt($index)2380 {2381 $item=parent::removeAt($index);2382 if($item instanceof TXmlElement)2383 $item->setParent(null);2384 return $item;2385 }2386}2387class TAuthorizationRule extends TComponent2388{2389 private $_action;2390 private $_users;2391 private $_roles;2392 private $_verb;2393 private $_ipRules;2394 private $_everyone;2395 private $_guest;2396 private $_authenticated;2397 public function __construct($action,$users,$roles,$verb='',$ipRules='')2398 {2399 $action=strtolower(trim($action));2400 if($action==='allow' || $action==='deny')2401 $this->_action=$action;2402 else2403 throw new TInvalidDataValueException('authorizationrule_action_invalid',$action);2404 $this->_users=array();2405 $this->_roles=array();2406 $this->_ipRules=array();2407 $this->_everyone=false;2408 $this->_guest=false;2409 $this->_authenticated=false;2410 if(trim($users)==='')2411 $users='*';2412 foreach(explode(',',$users) as $user)2413 {2414 if(($user=trim(strtolower($user)))!=='')2415 {2416 if($user==='*')2417 {2418 $this->_everyone=true;2419 break;2420 }2421 else if($user==='?')2422 $this->_guest=true;2423 else if($user==='@')2424 $this->_authenticated=true;2425 else2426 $this->_users[]=$user;2427 }2428 }2429 if(trim($roles)==='')2430 $roles='*';2431 foreach(explode(',',$roles) as $role)2432 {2433 if(($role=trim(strtolower($role)))!=='')2434 $this->_roles[]=$role;2435 }2436 if(($verb=trim(strtolower($verb)))==='')2437 $verb='*';2438 if($verb==='*' || $verb==='get' || $verb==='post')2439 $this->_verb=$verb;2440 else2441 throw new TInvalidDataValueException('authorizationrule_verb_invalid',$verb);2442 if(trim($ipRules)==='')2443 $ipRules='*';2444 foreach(explode(',',$ipRules) as $ipRule)2445 {2446 if(($ipRule=trim($ipRule))!=='')2447 $this->_ipRules[]=$ipRule;2448 }2449 }2450 public function getAction()2451 {2452 return $this->_action;2453 }2454 public function getUsers()2455 {2456 return $this->_users;2457 }2458 public function getRoles()2459 {2460 return $this->_roles;2461 }2462 public function getVerb()2463 {2464 return $this->_verb;2465 }2466 public function getIPRules()2467 {2468 return $this->_ipRules;2469 }2470 public function getGuestApplied()2471 {2472 return $this->_guest || $this->_everyone;2473 }2474 public function getEveryoneApplied()2475 {2476 return $this->_everyone;2477 }2478 public function getAuthenticatedApplied()2479 {2480 return $this->_authenticated || $this->_everyone;2481 }2482 public function isUserAllowed(IUser $user,$verb,$ip)2483 {2484 if($this->isVerbMatched($verb) && $this->isIpMatched($ip) && $this->isUserMatched($user) && $this->isRoleMatched($user))2485 return ($this->_action==='allow')?1:-1;2486 else2487 return 0;2488 }2489 private function isIpMatched($ip)2490 {2491 if(empty($this->_ipRules))2492 return 1;2493 foreach($this->_ipRules as $rule)2494 {2495 if($rule==='*' || $rule===$ip || (($pos=strpos($rule,'*'))!==false && strncmp($ip,$rule,$pos)===0))2496 return 1;2497 }2498 return 0;2499 }2500 private function isUserMatched($user)2501 {2502 return ($this->_everyone || ($this->_guest && $user->getIsGuest()) || ($this->_authenticated && !$user->getIsGuest()) || in_array(strtolower($user->getName()),$this->_users));2503 }2504 private function isRoleMatched($user)2505 {2506 foreach($this->_roles as $role)2507 {2508 if($role==='*' || $user->isInRole($role))2509 return true;2510 }2511 return false;2512 }2513 private function isVerbMatched($verb)2514 {2515 return ($this->_verb==='*' || strcasecmp($verb,$this->_verb)===0);2516 }2517}2518class TAuthorizationRuleCollection extends TList2519{2520 public function isUserAllowed($user,$verb,$ip)2521 {2522 if($user instanceof IUser)2523 {2524 $verb=strtolower(trim($verb));2525 foreach($this as $rule)2526 {2527 if(($decision=$rule->isUserAllowed($user,$verb,$ip))!==0)2528 return ($decision>0);2529 }2530 return true;2531 }2532 else2533 return false;2534 }2535 public function insertAt($index,$item)2536 {2537 if($item instanceof TAuthorizationRule)2538 parent::insertAt($index,$item);2539 else2540 throw new TInvalidDataTypeException('authorizationrulecollection_authorizationrule_required');2541 }2542}2543class TSecurityManager extends TModule2544{2545 const STATE_VALIDATION_KEY = 'prado:securitymanager:validationkey';2546 const STATE_ENCRYPTION_KEY = 'prado:securitymanager:encryptionkey';2547 private $_validationKey = null;2548 private $_encryptionKey = null;2549 private $_hashAlgorithm = 'sha1';2550 private $_cryptAlgorithm = 'rijndael-256';2551 private $_mbstring;2552 public function init($config)2553 {2554 $this->_mbstring=extension_loaded('mbstring');2555 $this->getApplication()->setSecurityManager($this);2556 }2557 protected function generateRandomKey()2558 {2559 return sprintf('%08x%08x%08x%08x',mt_rand(),mt_rand(),mt_rand(),mt_rand());2560 }2561 public function getValidationKey()2562 {2563 if(null === $this->_validationKey) {2564 if(null === ($this->_validationKey = $this->getApplication()->getGlobalState(self::STATE_VALIDATION_KEY))) {2565 $this->_validationKey = $this->generateRandomKey();2566 $this->getApplication()->setGlobalState(self::STATE_VALIDATION_KEY, $this->_validationKey, null, true);2567 }2568 }2569 return $this->_validationKey;2570 }2571 public function setValidationKey($value)2572 {2573 if('' === $value)2574 throw new TInvalidDataValueException('securitymanager_validationkey_invalid');2575 $this->_validationKey = $value;2576 }2577 public function getEncryptionKey()2578 {2579 if(null === $this->_encryptionKey) {2580 if(null === ($this->_encryptionKey = $this->getApplication()->getGlobalState(self::STATE_ENCRYPTION_KEY))) {2581 $this->_encryptionKey = $this->generateRandomKey();2582 $this->getApplication()->setGlobalState(self::STATE_ENCRYPTION_KEY, $this->_encryptionKey, null, true);2583 }2584 }2585 return $this->_encryptionKey;2586 }2587 public function setEncryptionKey($value)2588 {2589 if('' === $value)2590 throw new TInvalidDataValueException('securitymanager_encryptionkey_invalid');2591 $this->_encryptionKey = $value;2592 }2593 public function getValidation()2594 {2595 return $this->_hashAlgorithm;2596 }2597 public function getHashAlgorithm()2598 {2599 return $this->_hashAlgorithm;2600 }2601 public function setValidation($value)2602 {2603 $this->_hashAlgorithm = TPropertyValue::ensureEnum($value, 'TSecurityManagerValidationMode');2604 }2605 public function setHashAlgorithm($value)2606 {2607 $this->_hashAlgorithm = TPropertyValue::ensureString($value);2608 }2609 public function getEncryption()2610 {2611 if(is_string($this->_cryptAlgorithm))2612 return $this->_cryptAlgorithm;2613 return "3DES";2614 }2615 public function setEncryption($value)2616 {2617 $this->_cryptAlgorithm = $value;2618 }2619 public function getCryptAlgorithm()2620 {2621 return $this->_cryptAlgorithm;2622 }2623 public function setCryptAlgorithm($value)2624 {2625 $this->_cryptAlgorithm = $value;2626 }2627 public function encrypt($data)2628 {2629 $module=$this->openCryptModule();2630 $key = $this->substr(md5($this->getEncryptionKey()), 0, mcrypt_enc_get_key_size($module));2631 srand();2632 $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($module), MCRYPT_RAND);2633 mcrypt_generic_init($module, $key, $iv);2634 $encrypted = $iv.mcrypt_generic($module, $data);2635 mcrypt_generic_deinit($module);2636 mcrypt_module_close($module);2637 return $encrypted;2638 }2639 public function decrypt($data)2640 {2641 $module=$this->openCryptModule();2642 $key = $this->substr(md5($this->getEncryptionKey()), 0, mcrypt_enc_get_key_size($module));2643 $ivSize = mcrypt_enc_get_iv_size($module);2644 $iv = $this->substr($data, 0, $ivSize);2645 mcrypt_generic_init($module, $key, $iv);2646 $decrypted = mdecrypt_generic($module, $this->substr($data, $ivSize, $this->strlen($data)));2647 mcrypt_generic_deinit($module);2648 mcrypt_module_close($module);2649 return $decrypted;2650 }2651 protected function openCryptModule()2652 {2653 if(extension_loaded('mcrypt'))2654 {2655 if(is_array($this->_cryptAlgorithm))2656 $module=@call_user_func_array('mcrypt_module_open',$this->_cryptAlgorithm);2657 else2658 $module=@mcrypt_module_open($this->_cryptAlgorithm,'', MCRYPT_MODE_CBC,'');2659 if($module===false)2660 throw new TNotSupportedException('securitymanager_mcryptextension_initfailed');2661 return $module;2662 }2663 else2664 throw new TNotSupportedException('securitymanager_mcryptextension_required');2665 }2666 public function hashData($data)2667 {2668 $hmac = $this->computeHMAC($data);2669 return $hmac.$data;2670 }2671 public function validateData($data)2672 {2673 $len=$this->strlen($this->computeHMAC('test'));2674 if($this->strlen($data) < $len)2675 return false;2676 $hmac = $this->substr($data, 0, $len);2677 $data2=$this->substr($data, $len, $this->strlen($data));2678 return $hmac === $this->computeHMAC($data2) ? $data2 : false;2679 }2680 protected function computeHMAC($data)2681 {2682 $key = $this->getValidationKey();2683 if(function_exists('hash_hmac'))2684 return hash_hmac($this->_hashAlgorithm, $data, $key);2685 if(!strcasecmp($this->_hashAlgorithm,'sha1'))2686 {2687 $pack = 'H40';2688 $func = 'sha1';2689 } else {2690 $pack = 'H32';2691 $func = 'md5';2692 }2693 $key = str_pad($func($key), 64, chr(0));2694 return $func((str_repeat(chr(0x5C), 64) ^ substr($key, 0, 64)) . pack($pack, $func((str_repeat(chr(0x36), 64) ^ substr($key, 0, 64)) . $data)));2695 }2696 private function strlen($string)2697 {2698 return $this->_mbstring ? mb_strlen($string,'8bit') : strlen($string);2699 }2700 private function substr($string,$start,$length)2701 {2702 return $this->_mbstring ? mb_substr($string,$start,$length,'8bit') : substr($string,$start,$length);2703 }2704}2705class TSecurityManagerValidationMode extends TEnumerable2706{2707 const MD5 = 'MD5';2708 const SHA1 = 'SHA1';2709}2710class THttpUtility2711{2712 private static $_encodeTable=array('<'=>'&lt;','>'=>'&gt;','"'=>'&quot;');2713 private static $_decodeTable=array('&lt;'=>'<','&gt;'=>'>','&quot;'=>'"');2714 private static $_stripTable=array('&lt;'=>'','&gt;'=>'','&quot;'=>'');2715 public static function htmlEncode($s)2716 {2717 return strtr($s,self::$_encodeTable);2718 }2719 public static function htmlDecode($s)2720 {2721 return strtr($s,self::$_decodeTable);2722 }2723 public static function htmlStrip($s)2724 {2725 return strtr($s,self::$_stripTable);2726 }2727}2728class TJavaScript2729{2730 public static function renderScriptFiles($files)2731 {2732 $str='';2733 foreach($files as $file)2734 $str.= self::renderScriptFile($file);2735 return $str;2736 }2737 public static function renderScriptFile($file)2738 {2739 return '<script type="text/javascript" src="'.THttpUtility::htmlEncode($file)."\"></script>\n";2740 }2741 public static function renderScriptBlocks($scripts)2742 {2743 if(count($scripts))2744 return "<script type=\"text/javascript\">\n/*<![CDATA[*/\n".implode("\n",$scripts)."\n/*]]>*/\n</script>\n";2745 else2746 return '';2747 }2748 public static function renderScriptBlocksCallback($scripts)2749 {2750 if(count($scripts))2751 return implode("\n",$scripts)."\n";2752 else2753 return '';2754 }2755 public static function renderScriptBlock($script)2756 {2757 return "<script type=\"text/javascript\">\n/*<![CDATA[*/\n{$script}\n/*]]>*/\n</script>\n";2758 }2759 public static function quoteString($js)2760 {2761 return self::jsonEncode($js,JSON_HEX_QUOT | JSON_HEX_APOS | JSON_HEX_TAG);2762 }2763 public static function quoteJsLiteral($js)2764 {2765 if($js instanceof TJavaScriptLiteral)2766 return $js;2767 else2768 return new TJavaScriptLiteral($js);2769 }2770 public static function quoteFunction($js)2771 {2772 return self::quoteJsLiteral($js);2773 }2774 public static function isJsLiteral($js)2775 {2776 return ($js instanceof TJavaScriptLiteral);2777 }2778 public static function isFunction($js)2779 {2780 return self::isJsLiteral($js);2781 }2782 public static function encode($value,$toMap=true,$encodeEmptyStrings=false)2783 {2784 if(is_string($value))2785 return self::quoteString($value);2786 else if(is_bool($value))2787 return $value?'true':'false';2788 else if(is_array($value))2789 {2790 $results='';2791 if(($n=count($value))>0 && array_keys($value)!==range(0,$n-1))2792 {2793 foreach($value as $k=>$v)2794 {2795 if($v!=='' || $encodeEmptyStrings)2796 {2797 if($results!=='')2798 $results.=',';2799 $results.="'$k':".self::encode($v,$toMap,$encodeEmptyStrings);2800 }2801 }2802 return '{'.$results.'}';2803 }2804 else2805 {2806 foreach($value as $v)2807 {2808 if($v!=='' || $encodeEmptyStrings)2809 {2810 if($results!=='')2811 $results.=',';2812 $results.=self::encode($v,$toMap, $encodeEmptyStrings);2813 }2814 }2815 return '['.$results.']';2816 }2817 }2818 else if(is_integer($value))2819 return "$value";2820 else if(is_float($value))2821 {2822 switch($value)2823 {2824 case -INF:2825 return 'Number.NEGATIVE_INFINITY';2826 break;2827 case INF:2828 return 'Number.POSITIVE_INFINITY';2829 break;2830 default:2831 $locale=localeConv();2832 if($locale['decimal_point']=='.')2833 return "$value";2834 else2835 return str_replace($locale['decimal_point'], '.', "$value");2836 break;2837 }2838 }2839 else if(is_object($value))2840 if ($value instanceof TJavaScriptLiteral)2841 return $value->toJavaScriptLiteral();2842 else2843 return self::encode(get_object_vars($value),$toMap);2844 else if($value===null)2845 return 'null';2846 else2847 return '';2848 }2849 public static function jsonEncode($value, $options = 0)2850 {2851 if (($g=Prado::getApplication()->getGlobalization(false))!==null &&2852 strtoupper($enc=$g->getCharset())!='UTF-8') {2853 self::convertToUtf8($value, $enc);2854 }2855 $s = @json_encode($value,$options);2856 self::checkJsonError();2857 return $s;2858 }2859 private static function convertToUtf8(&$value, $sourceEncoding) {2860 if(is_string($value))2861 $value=iconv($sourceEncoding, 'UTF-8', $value);2862 else if (is_array($value))2863 {2864 foreach($value as &$element)2865 self::convertToUtf8($element, $sourceEncoding);2866 }2867 }2868 public static function jsonDecode($value, $assoc = false, $depth = 512)2869 {2870 $s= @json_decode($value, $assoc, $depth);2871 self::checkJsonError();2872 return $s;2873 }2874 private static function checkJsonError()2875 {2876 switch ($err = json_last_error())2877 {2878 case JSON_ERROR_NONE:2879 return;2880 break;2881 case JSON_ERROR_DEPTH:2882 $msg = 'Maximum stack depth exceeded';2883 break;2884 case JSON_ERROR_STATE_MISMATCH:2885 $msg = 'Underflow or the modes mismatch';2886 break;2887 case JSON_ERROR_CTRL_CHAR:2888 $msg = 'Unexpected control character found';2889 break;2890 case JSON_ERROR_SYNTAX:2891 $msg = 'Syntax error, malformed JSON';2892 break;2893 case JSON_ERROR_UTF8:2894 $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';2895 break;2896 default:2897 $msg = 'Unknown error';2898 break;2899 }2900 throw new Exception("JSON error ($err): $msg");2901 }2902 public static function JSMin($code)2903 {2904 Prado::using('System.Web.Javascripts.JSMin');2905 return JSMin::minify($code);2906 }2907}2908class TUrlManager extends TModule2909{2910 public function constructUrl($serviceID,$serviceParam,$getItems,$encodeAmpersand,$encodeGetItems)2911 {2912 $url=$serviceID.'='.urlencode($serviceParam);2913 $amp=$encodeAmpersand?'&amp;':'&';2914 $request=$this->getRequest();2915 if(is_array($getItems) || $getItems instanceof Traversable)2916 {2917 if($encodeGetItems)2918 {2919 foreach($getItems as $name=>$value)2920 {2921 if(is_array($value))2922 {2923 $name=urlencode($name.'[]');2924 foreach($value as $v)2925 $url.=$amp.$name.'='.urlencode($v);2926 }2927 else2928 $url.=$amp.urlencode($name).'='.urlencode($value);2929 }2930 }2931 else2932 {2933 foreach($getItems as $name=>$value)2934 {2935 if(is_array($value))2936 {2937 foreach($value as $v)2938 $url.=$amp.$name.'[]='.$v;2939 }2940 else2941 $url.=$amp.$name.'='.$value;2942 }2943 }2944 }2945 switch($request->getUrlFormat())2946 {2947 case THttpRequestUrlFormat::Path:2948 return $request->getApplicationUrl().'/'.strtr($url,array($amp=>'/','?'=>'/','='=>$request->getUrlParamSeparator()));2949 case THttpRequestUrlFormat::HiddenPath:2950 return rtrim(dirname($request->getApplicationUrl()), '/').'/'.strtr($url,array($amp=>'/','?'=>'/','='=>$request->getUrlParamSeparator()));2951 default:2952 return $request->getApplicationUrl().'?'.$url;2953 }2954 }2955 public function parseUrl()2956 {2957 $request=$this->getRequest();2958 $pathInfo=trim($request->getPathInfo(),'/');2959 if(($request->getUrlFormat()===THttpRequestUrlFormat::Path ||2960 $request->getUrlFormat()===THttpRequestUrlFormat::HiddenPath) &&2961 $pathInfo!=='')2962 {2963 $separator=$request->getUrlParamSeparator();2964 $paths=explode('/',$pathInfo);2965 $getVariables=array();2966 foreach($paths as $path)2967 {2968 if(($path=trim($path))!=='')2969 {2970 if(($pos=strpos($path,$separator))!==false)2971 {2972 $name=substr($path,0,$pos);2973 $value=substr($path,$pos+1);2974 if(($pos=strpos($name,'[]'))!==false)2975 $getVariables[substr($name,0,$pos)][]=$value;2976 else2977 $getVariables[$name]=$value;2978 }2979 else2980 $getVariables[$path]='';2981 }2982 }2983 return $getVariables;2984 }2985 else2986 return array();2987 }2988}2989class THttpRequest extends TApplicationComponent implements IteratorAggregate,ArrayAccess,Countable,IModule2990{2991 const CGIFIX__PATH_INFO = 1;2992 const CGIFIX__SCRIPT_NAME = 2;2993 private $_urlManager=null;2994 private $_urlManagerID='';2995 private $_separator=',';2996 private $_serviceID=null;2997 private $_serviceParam=null;2998 private $_cookies=null;2999 private $_requestUri;3000 private $_pathInfo;3001 private $_cookieOnly=null;3002 private $_urlFormat=THttpRequestUrlFormat::Get;3003 private $_services;3004 private $_requestResolved=false;3005 private $_enableCookieValidation=false;3006 private $_cgiFix=0;3007 private $_enableCache=false;3008 private $_url=null;3009 private $_id;3010 private $_items=array();3011 public function getID()3012 {3013 return $this->_id;3014 }3015 public function setID($value)3016 {3017 $this->_id=$value;3018 }3019 public function init($config)3020 {3021 if(php_sapi_name()==='cli')3022 {3023 $_SERVER['REMOTE_ADDR']='127.0.0.1';3024 $_SERVER['REQUEST_METHOD']='GET';3025 $_SERVER['SERVER_NAME']='localhost';3026 $_SERVER['SERVER_PORT']=80;3027 $_SERVER['HTTP_USER_AGENT']='';3028 }3029 if(isset($_SERVER['REQUEST_URI']))3030 $this->_requestUri=$_SERVER['REQUEST_URI'];3031 else $this->_requestUri=$_SERVER['SCRIPT_NAME'].(empty($_SERVER['QUERY_STRING'])?'':'?'.$_SERVER['QUERY_STRING']);3032 if($this->_cgiFix&self::CGIFIX__PATH_INFO && isset($_SERVER['ORIG_PATH_INFO']))3033 $this->_pathInfo=substr($_SERVER['ORIG_PATH_INFO'], strlen($_SERVER['SCRIPT_NAME']));3034 elseif(isset($_SERVER['PATH_INFO']))3035 $this->_pathInfo=$_SERVER['PATH_INFO'];3036 else if(strpos($_SERVER['PHP_SELF'],$_SERVER['SCRIPT_NAME'])===0 && $_SERVER['PHP_SELF']!==$_SERVER['SCRIPT_NAME'])3037 $this->_pathInfo=substr($_SERVER['PHP_SELF'],strlen($_SERVER['SCRIPT_NAME']));3038 else3039 $this->_pathInfo='';3040 if(get_magic_quotes_gpc())3041 {3042 if(isset($_GET))3043 $_GET=$this->stripSlashes($_GET);3044 if(isset($_POST))3045 $_POST=$this->stripSlashes($_POST);3046 if(isset($_REQUEST))3047 $_REQUEST=$this->stripSlashes($_REQUEST);3048 if(isset($_COOKIE))3049 $_COOKIE=$this->stripSlashes($_COOKIE);3050 }3051 $this->getApplication()->setRequest($this);3052 }3053 public function stripSlashes(&$data)3054 {3055 return is_array($data)?array_map(array($this,'stripSlashes'),$data):stripslashes($data);3056 }3057 public function getUrl()3058 {3059 if($this->_url===null)3060 {3061 $secure=$this->getIsSecureConnection();3062 $url=$secure?'https://':'http://';3063 if(empty($_SERVER['HTTP_HOST']))3064 {3065 $url.=$_SERVER['SERVER_NAME'];3066 $port=$_SERVER['SERVER_PORT'];3067 if(($port!=80 && !$secure) || ($port!=443 && $secure))3068 $url.=':'.$port;3069 }3070 else3071 $url.=$_SERVER['HTTP_HOST'];3072 $url.=$this->getRequestUri();3073 $this->_url=new TUri($url);3074 }3075 return $this->_url;3076 }3077 public function setEnableCache($value)3078 {3079 $this->_enableCache = TPropertyValue::ensureBoolean($value);3080 }3081 public function getEnableCache()3082 {3083 return $this->_enableCache;3084 }3085 protected function getCacheKey()3086 {3087 return $this->getID();3088 }3089 protected function cacheUrlManager($manager)3090 {3091 if($this->getEnableCache())3092 {3093 $cache = $this->getApplication()->getCache();3094 if($cache !== null)3095 {3096 $dependencies = null;3097 if($this->getApplication()->getMode() !== TApplicationMode::Performance)3098 if ($manager instanceof TUrlMapping && $fn = $manager->getConfigFile())3099 {3100 $fn = Prado::getPathOfNamespace($fn,$this->getApplication()->getConfigurationFileExt());3101 $dependencies = new TFileCacheDependency($fn);3102 }3103 return $cache->set($this->getCacheKey(), $manager, 0, $dependencies);3104 }3105 }3106 return false;3107 }3108 protected function loadCachedUrlManager()3109 {3110 if($this->getEnableCache())3111 {3112 $cache = $this->getApplication()->getCache();3113 if($cache !== null)3114 {3115 $manager = $cache->get($this->getCacheKey());3116 if($manager instanceof TUrlManager)3117 return $manager;3118 }3119 }3120 return null;3121 }3122 public function getUrlManager()3123 {3124 return $this->_urlManagerID;3125 }3126 public function setUrlManager($value)3127 {3128 $this->_urlManagerID=$value;3129 }3130 public function getUrlManagerModule()3131 {3132 if($this->_urlManager===null)3133 {3134 if(($this->_urlManager = $this->loadCachedUrlManager())===null)3135 {3136 if(empty($this->_urlManagerID))3137 {3138 $this->_urlManager=new TUrlManager;3139 $this->_urlManager->init(null);3140 }3141 else3142 {3143 $this->_urlManager=$this->getApplication()->getModule($this->_urlManagerID);3144 if($this->_urlManager===null)3145 throw new TConfigurationException('httprequest_urlmanager_inexist',$this->_urlManagerID);3146 if(!($this->_urlManager instanceof TUrlManager))3147 throw new TConfigurationException('httprequest_urlmanager_invalid',$this->_urlManagerID);3148 }3149 $this->cacheUrlManager($this->_urlManager);3150 }3151 }3152 return $this->_urlManager;3153 }3154 public function getUrlFormat()3155 {3156 return $this->_urlFormat;3157 }3158 public function setUrlFormat($value)3159 {3160 $this->_urlFormat=TPropertyValue::ensureEnum($value,'THttpRequestUrlFormat');3161 }3162 public function getUrlParamSeparator()3163 {3164 return $this->_separator;3165 }3166 public function setUrlParamSeparator($value)3167 {3168 if(strlen($value)===1)3169 $this->_separator=$value;3170 else3171 throw new TInvalidDataValueException('httprequest_separator_invalid');3172 }3173 public function getRequestType()3174 {3175 return isset($_SERVER['REQUEST_METHOD'])?$_SERVER['REQUEST_METHOD']:null;3176 }3177 public function getContentType($mimetypeOnly = true)3178 {3179 if(!isset($_SERVER['CONTENT_TYPE']))3180 return null;3181 if($mimetypeOnly === true && ($_pos = strpos(';', $_SERVER['CONTENT_TYPE'])) !== false)3182 return substr($_SERVER['CONTENT_TYPE'], 0, $_pos);3183 return $_SERVER['CONTENT_TYPE'];3184 }3185 public function getIsSecureConnection()3186 {3187 return isset($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'],'off');3188 }3189 public function getPathInfo()3190 {3191 return $this->_pathInfo;3192 }3193 public function getQueryString()3194 {3195 return isset($_SERVER['QUERY_STRING'])?$_SERVER['QUERY_STRING']:null;3196 }3197 public function getHttpProtocolVersion()3198 {3199 return isset($_SERVER['SERVER_PROTOCOL'])?$_SERVER['SERVER_PROTOCOL']:null;3200 }3201 public function getHeaders($case=null)3202 {3203 static $result;3204 if($result === null && function_exists('apache_request_headers')) {3205 $result = apache_request_headers();3206 }3207 elseif($result === null) {3208 $result = array();3209 foreach($_SERVER as $key=>$value) {3210 if(strncasecmp($key, 'HTTP_', 5) !== 0) continue;3211 $key = str_replace(' ','-', ucwords(strtolower(str_replace('_',' ', substr($key, 5)))));3212 $result[$key] = $value;3213 }3214 }3215 if($case !== null)3216 return array_change_key_case($result, $case);3217 return $result;3218 }3219 public function getRequestUri()3220 {3221 return $this->_requestUri;3222 }3223 public function getBaseUrl($forceSecureConnection=null)3224 {3225 $url=$this->getUrl();3226 $scheme=($forceSecureConnection)?"https": (($forceSecureConnection === null)?$url->getScheme():'http');3227 $host=$url->getHost();3228 if (($port=$url->getPort())) $host.=':'.$port;3229 return $scheme.'://'.$host;3230 }3231 public function getApplicationUrl()3232 {3233 if($this->_cgiFix&self::CGIFIX__SCRIPT_NAME && isset($_SERVER['ORIG_SCRIPT_NAME']))3234 return $_SERVER['ORIG_SCRIPT_NAME'];3235 return isset($_SERVER['SCRIPT_NAME'])?$_SERVER['SCRIPT_NAME']:null;3236 }3237 public function getAbsoluteApplicationUrl($forceSecureConnection=null)3238 {3239 return $this->getBaseUrl($forceSecureConnection) . $this->getApplicationUrl();3240 }3241 public function getApplicationFilePath()3242 {3243 return realpath(isset($_SERVER['SCRIPT_FILENAME'])?$_SERVER['SCRIPT_FILENAME']:null);3244 }3245 public function getServerName()3246 {3247 return isset($_SERVER['SERVER_NAME'])?$_SERVER['SERVER_NAME']:null;3248 }3249 public function getServerSoftware()3250 {3251 return isset($_SERVER['SERVER_SOFTWARE'])?$_SERVER['SERVER_SOFTWARE']:null;3252 }3253 public function getServerPort()3254 {3255 return isset($_SERVER['SERVER_PORT'])?$_SERVER['SERVER_PORT']:null;3256 }3257 public function getUrlReferrer()3258 {3259 return isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:null;3260 }3261 public function getBrowser()3262 {3263 try3264 {3265 return get_browser();3266 }3267 catch(TPhpErrorException $e)3268 {3269 throw new TConfigurationException('httprequest_browscap_required');3270 }3271 }3272 public function getUserAgent()3273 {3274 return isset($_SERVER['HTTP_USER_AGENT'])?$_SERVER['HTTP_USER_AGENT']:null;3275 }3276 public function getUserHostAddress()3277 {3278 return isset($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:null;3279 }3280 public function getUserHost()3281 {3282 return isset($_SERVER['REMOTE_HOST'])?$_SERVER['REMOTE_HOST']:null;3283 }3284 public function getAcceptTypes()3285 {3286 return isset($_SERVER['HTTP_ACCEPT'])?$_SERVER['HTTP_ACCEPT']:null;3287 }3288 public function getUserLanguages()3289 {3290 return Prado::getUserLanguages();3291 }3292 public function getEnableCookieValidation()3293 {3294 return $this->_enableCookieValidation;3295 }3296 public function setEnableCookieValidation($value)3297 {3298 $this->_enableCookieValidation=TPropertyValue::ensureBoolean($value);3299 }3300 public function getCgiFix()3301 {3302 return $this->_cgiFix;3303 }3304 public function setCgiFix($value)3305 {3306 $this->_cgiFix=TPropertyValue::ensureInteger($value);3307 }3308 public function getCookies()3309 {3310 if($this->_cookies===null)3311 {3312 $this->_cookies=new THttpCookieCollection;3313 if($this->getEnableCookieValidation())3314 {3315 $sm=$this->getApplication()->getSecurityManager();3316 foreach($_COOKIE as $key=>$value)3317 {3318 if(($value=$sm->validateData($value))!==false)3319 $this->_cookies->add(new THttpCookie($key,$value));3320 }3321 }3322 else3323 {3324 foreach($_COOKIE as $key=>$value)3325 $this->_cookies->add(new THttpCookie($key,$value));3326 }3327 }3328 return $this->_cookies;3329 }3330 public function getUploadedFiles()3331 {3332 return $_FILES;3333 }3334 public function getServerVariables()3335 {3336 return $_SERVER;3337 }3338 public function getEnvironmentVariables()3339 {3340 return $_ENV;3341 }3342 public function constructUrl($serviceID,$serviceParam,$getItems=null,$encodeAmpersand=true,$encodeGetItems=true)3343 {3344 if ($this->_cookieOnly===null)3345 $this->_cookieOnly=(int)ini_get('session.use_cookies') && (int)ini_get('session.use_only_cookies');3346 $url=$this->getUrlManagerModule()->constructUrl($serviceID,$serviceParam,$getItems,$encodeAmpersand,$encodeGetItems);3347 if(defined('SID') && SID != '' && !$this->_cookieOnly)3348 return $url . (strpos($url,'?')===false? '?' : ($encodeAmpersand?'&amp;':'&')) . SID;3349 else3350 return $url;3351 }3352 protected function parseUrl()3353 {3354 return $this->getUrlManagerModule()->parseUrl();3355 }3356 public function resolveRequest($serviceIDs)3357 {3358 $getParams=$this->parseUrl();3359 foreach($getParams as $name=>$value)3360 $_GET[$name]=$value;3361 $this->_items=array_merge($_GET,$_POST);3362 $this->_requestResolved=true;3363 foreach($serviceIDs as $serviceID)3364 {3365 if($this->contains($serviceID))3366 {3367 $this->setServiceID($serviceID);3368 $this->setServiceParameter($this->itemAt($serviceID));3369 return $serviceID;3370 }3371 }3372 return null;3373 }3374 public function getRequestResolved()3375 {3376 return $this->_requestResolved;3377 }3378 public function getServiceID()3379 {3380 return $this->_serviceID;3381 }3382 public function setServiceID($value)3383 {3384 $this->_serviceID=$value;3385 }3386 public function getServiceParameter()3387 {3388 return $this->_serviceParam;3389 }3390 public function setServiceParameter($value)3391 {3392 $this->_serviceParam=$value;3393 }3394 public function getIterator()3395 {3396 return new ArrayIterator($this->_items);3397 }3398 public function getCount()3399 {3400 return count($this->_items);3401 }3402 public function count()3403 {3404 return $this->getCount();3405 }3406 public function getKeys()3407 {3408 return array_keys($this->_items);3409 }3410 public function itemAt($key)3411 {3412 return isset($this->_items[$key]) ? $this->_items[$key] : null;3413 }3414 public function add($key,$value)3415 {3416 $this->_items[$key]=$value;3417 }3418 public function remove($key)3419 {3420 if(isset($this->_items[$key]) || array_key_exists($key,$this->_items))3421 {3422 $value=$this->_items[$key];3423 unset($this->_items[$key]);3424 return $value;3425 }3426 else3427 return null;3428 }3429 public function clear()3430 {3431 foreach(array_keys($this->_items) as $key)3432 $this->remove($key);3433 }3434 public function contains($key)3435 {3436 return isset($this->_items[$key]) || array_key_exists($key,$this->_items);3437 }3438 public function toArray()3439 {3440 return $this->_items;3441 }3442 public function offsetExists($offset)3443 {3444 return $this->contains($offset);3445 }3446 public function offsetGet($offset)3447 {3448 return $this->itemAt($offset);3449 }3450 public function offsetSet($offset,$item)3451 {3452 $this->add($offset,$item);3453 }3454 public function offsetUnset($offset)3455 {3456 $this->remove($offset);3457 }3458}3459class THttpCookieCollection extends TList3460{3461 private $_o;3462 public function __construct($owner=null)3463 {3464 $this->_o=$owner;3465 }3466 public function insertAt($index,$item)3467 {3468 if($item instanceof THttpCookie)3469 {3470 parent::insertAt($index,$item);3471 if($this->_o instanceof THttpResponse)3472 $this->_o->addCookie($item);3473 }3474 else3475 throw new TInvalidDataTypeException('httpcookiecollection_httpcookie_required');3476 }3477 public function removeAt($index)3478 {3479 $item=parent::removeAt($index);3480 if($this->_o instanceof THttpResponse)3481 $this->_o->removeCookie($item);3482 return $item;3483 }3484 public function itemAt($index)3485 {3486 if(is_integer($index))3487 return parent::itemAt($index);3488 else3489 return $this->findCookieByName($index);3490 }3491 public function findCookieByName($name)3492 {3493 foreach($this as $cookie)3494 if($cookie->getName()===$name)3495 return $cookie;3496 return null;3497 }3498}3499class THttpCookie extends TComponent3500{3501 private $_domain='';3502 private $_name;3503 private $_value='';3504 private $_expire=0;3505 private $_path='/';3506 private $_secure=false;3507 private $_httpOnly=false;3508 public function __construct($name,$value)3509 {3510 $this->_name=$name;3511 $this->_value=$value;3512 }3513 public function getDomain()3514 {3515 return $this->_domain;3516 }3517 public function setDomain($value)3518 {3519 $this->_domain=$value;3520 }3521 public function getExpire()3522 {3523 return $this->_expire;3524 }3525 public function setExpire($value)3526 {3527 $this->_expire=TPropertyValue::ensureInteger($value);3528 }3529 public function getHttpOnly()3530 {3531 return $this->_httpOnly;3532 }3533 public function setHttpOnly($value)3534 {3535 $this->_httpOnly = TPropertyValue::ensureBoolean($value);3536 }3537 public function getName()3538 {3539 return $this->_name;3540 }3541 public function setName($value)3542 {3543 $this->_name=$value;3544 }3545 public function getValue()3546 {3547 return $this->_value;3548 }3549 public function setValue($value)3550 {3551 $this->_value=$value;3552 }3553 public function getPath()3554 {3555 return $this->_path;3556 }3557 public function setPath($value)3558 {3559 $this->_path=$value;3560 }3561 public function getSecure()3562 {3563 return $this->_secure;3564 }3565 public function setSecure($value)3566 {3567 $this->_secure=TPropertyValue::ensureBoolean($value);3568 }3569}3570class TUri extends TComponent3571{3572 private static $_defaultPort=array(3573 'ftp'=>21,3574 'gopher'=>70,3575 'http'=>80,3576 'https'=>443,3577 'news'=>119,3578 'nntp'=>119,3579 'wais'=>210,3580 'telnet'=>233581 );3582 private $_scheme;3583 private $_host;3584 private $_port;3585 private $_user;3586 private $_pass;3587 private $_path;3588 private $_query;3589 private $_fragment;3590 private $_uri;3591 public function __construct($uri)3592 {3593 if(($ret=@parse_url($uri))!==false)3594 {3595 $this->_scheme=isset($ret['scheme'])?$ret['scheme']:'';3596 $this->_host=isset($ret['host'])?$ret['host']:'';3597 $this->_port=isset($ret['port'])?$ret['port']:'';3598 $this->_user=isset($ret['user'])?$ret['user']:'';3599 $this->_pass=isset($ret['pass'])?$ret['pass']:'';3600 $this->_path=isset($ret['path'])?$ret['path']:'';3601 $this->_query=isset($ret['query'])?$ret['query']:'';3602 $this->_fragment=isset($ret['fragment'])?$ret['fragment']:'';3603 $this->_uri=$uri;3604 }3605 else3606 {3607 throw new TInvalidDataValueException('uri_format_invalid',$uri);3608 }3609 }3610 public function getUri()3611 {3612 return $this->_uri;3613 }3614 public function getScheme()3615 {3616 return $this->_scheme;3617 }3618 public function getHost()3619 {3620 return $this->_host;3621 }3622 public function getPort()3623 {3624 return $this->_port;3625 }3626 public function getUser()3627 {3628 return $this->_user;3629 }3630 public function getPassword()3631 {3632 return $this->_pass;3633 }3634 public function getPath()3635 {3636 return $this->_path;3637 }3638 public function getQuery()3639 {3640 return $this->_query;3641 }3642 public function getFragment()3643 {3644 return $this->_fragment;3645 }3646}3647class THttpRequestUrlFormat extends TEnumerable3648{3649 const Get='Get';3650 const Path='Path';3651 const HiddenPath='HiddenPath';3652}3653class THttpResponseAdapter extends TApplicationComponent3654{3655 private $_response;3656 public function __construct($response)3657 {3658 $this->_response=$response;3659 }3660 public function getResponse()3661 {3662 return $this->_response;3663 }3664 public function flushContent()3665 {3666 $this->_response->flushContent();3667 }3668 public function httpRedirect($url)3669 {3670 $this->_response->httpRedirect($url);3671 }3672 public function createNewHtmlWriter($type, $writer)3673 {3674 return $this->_response->createNewHtmlWriter($type,$writer);3675 }3676}3677class THttpResponse extends TModule implements ITextWriter3678{3679 const DEFAULT_CONTENTTYPE = 'text/html';3680 const DEFAULT_CHARSET = 'UTF-8';3681 private static $HTTP_STATUS_CODES = array(3682 100 => 'Continue', 101 => 'Switching Protocols',3683 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content',3684 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect',3685 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',3686 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported'3687 );3688 private $_bufferOutput=true;3689 private $_initialized=false;3690 private $_cookies=null;3691 private $_status=200;3692 private $_reason='OK';3693 private $_htmlWriterType='System.Web.UI.THtmlWriter';3694 private $_contentType=null;3695 private $_charset='';3696 private $_adapter;3697 private $_httpHeaderSent;3698 private $_contentTypeHeaderSent;3699 public function __destruct()3700 {3701 }3702 public function setAdapter(THttpResponseAdapter $adapter)3703 {3704 $this->_adapter=$adapter;3705 }3706 public function getAdapter()3707 {3708 return $this->_adapter;3709 }3710 public function getHasAdapter()3711 {3712 return $this->_adapter!==null;3713 }3714 public function init($config)3715 {3716 if($this->_bufferOutput)3717 ob_start();3718 $this->_initialized=true;3719 $this->getApplication()->setResponse($this);3720 }3721 public function getCacheExpire()3722 {3723 return session_cache_expire();3724 }3725 public function setCacheExpire($value)3726 {3727 session_cache_expire(TPropertyValue::ensureInteger($value));3728 }3729 public function getCacheControl()3730 {3731 return session_cache_limiter();3732 }3733 public function setCacheControl($value)3734 {3735 session_cache_limiter(TPropertyValue::ensureEnum($value,array('none','nocache','private','private_no_expire','public')));3736 }3737 public function setContentType($type)3738 {3739 if ($this->_contentTypeHeaderSent)3740 throw new Exception('Unable to alter content-type as it has been already sent');3741 $this->_contentType = $type;3742 }3743 public function getContentType()3744 {3745 return $this->_contentType;3746 }3747 public function getCharset()3748 {3749 return $this->_charset;3750 }3751 public function setCharset($charset)3752 {3753 $this->_charset = (strToLower($charset) === 'false') ? false : (string)$charset;3754 }3755 public function getBufferOutput()3756 {3757 return $this->_bufferOutput;3758 }3759 public function setBufferOutput($value)3760 {3761 if($this->_initialized)3762 throw new TInvalidOperationException('httpresponse_bufferoutput_unchangeable');3763 else3764 $this->_bufferOutput=TPropertyValue::ensureBoolean($value);3765 }3766 public function getStatusCode()3767 {3768 return $this->_status;3769 }3770 public function setStatusCode($status, $reason=null)3771 {3772 if ($this->_httpHeaderSent)3773 throw new Exception('Unable to alter response as HTTP header already sent');3774 $status=TPropertyValue::ensureInteger($status);3775 if(isset(self::$HTTP_STATUS_CODES[$status])) {3776 $this->_reason=self::$HTTP_STATUS_CODES[$status];3777 }else{3778 if($reason===null || $reason==='') {3779 throw new TInvalidDataValueException("response_status_reason_missing");3780 }3781 $reason=TPropertyValue::ensureString($reason);3782 if(strpos($reason, "\r")!=false || strpos($reason, "\n")!=false) {3783 throw new TInvalidDataValueException("response_status_reason_barchars");3784 }3785 $this->_reason=$reason;3786 }3787 $this->_status=$status;3788 }3789 public function getStatusReason() {3790 return $this->_reason;3791 }3792 public function getCookies()3793 {3794 if($this->_cookies===null)3795 $this->_cookies=new THttpCookieCollection($this);3796 return $this->_cookies;3797 }3798 public function write($str)3799 {3800 if (!$this->_bufferOutput and !$this->_httpHeaderSent)3801 $this->ensureHeadersSent();3802 echo $str;3803 }3804 public function writeFile($fileName,$content=null,$mimeType=null,$headers=null,$forceDownload=true,$clientFileName=null,$fileSize=null)3805 {3806 static $defaultMimeTypes=array(3807 'css'=>'text/css',3808 'gif'=>'image/gif',3809 'png'=>'image/png',3810 'jpg'=>'image/jpeg',3811 'jpeg'=>'image/jpeg',3812 'htm'=>'text/html',3813 'html'=>'text/html',3814 'js'=>'javascript/js',3815 'pdf'=>'application/pdf',3816 'xls'=>'application/vnd.ms-excel',3817 );3818 if($mimeType===null)3819 {3820 $mimeType='text/plain';3821 if(function_exists('mime_content_type'))3822 $mimeType=mime_content_type($fileName);3823 else if(($ext=strrchr($fileName,'.'))!==false)3824 {3825 $ext=substr($ext,1);3826 if(isset($defaultMimeTypes[$ext]))3827 $mimeType=$defaultMimeTypes[$ext];3828 }3829 }3830 if($clientFileName===null)3831 $clientFileName=basename($fileName);3832 else3833 $clientFileName=basename($clientFileName);3834 if($fileSize===null || $fileSize < 0)3835 $fileSize = ($content===null?filesize($fileName):strlen($content));3836 $this->sendHttpHeader();3837 if(is_array($headers))3838 {3839 foreach($headers as $h)3840 header($h);3841 }3842 else3843 {3844 header('Pragma: public');3845 header('Expires: 0');3846 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');3847 header("Content-Type: $mimeType");3848 $this->_contentTypeHeaderSent = true;3849 }3850 header('Content-Length: '.$fileSize);3851 header("Content-Disposition: " . ($forceDownload ? 'attachment' : 'inline') . "; filename=\"$clientFileName\"");3852 header('Content-Transfer-Encoding: binary');3853 if($content===null)3854 readfile($fileName);3855 else3856 echo $content;3857 }3858 public function redirect($url)3859 {3860 if($this->getHasAdapter())3861 $this->_adapter->httpRedirect($url);3862 else3863 $this->httpRedirect($url);3864 }3865 public function httpRedirect($url)3866 {3867 $this->ensureHeadersSent();3868 $isIIS = (stripos($this->getRequest()->getServerSoftware(), "microsoft-iis") !== false);3869 if($url[0]==='/')3870 $url=$this->getRequest()->getBaseUrl().$url;3871 if ($this->_status >= 300 && $this->_status < 400)3872 {3873 if($isIIS)3874 {3875 header('HTTP/1.1 ' . $this->_status . ' ' . self::$HTTP_STATUS_CODES[3876 array_key_exists($this->_status, self::$HTTP_STATUS_CODES)3877 ? $this->_status3878 : 3023879 ]);3880 }3881 header('Location: '.str_replace('&amp;','&',$url), true, $this->_status);3882 } else {3883 if($isIIS)3884 header('HTTP/1.1 302 '.self::$HTTP_STATUS_CODES[302]);3885 header('Location: '.str_replace('&amp;','&',$url));3886 }3887 if(!$this->getApplication()->getRequestCompleted())3888 $this->getApplication()->onEndRequest();3889 exit();3890 }3891 public function reload()3892 {3893 $this->redirect($this->getRequest()->getRequestUri());3894 }3895 public function flush($continueBuffering = true)3896 {3897 if($this->getHasAdapter())3898 $this->_adapter->flushContent($continueBuffering);3899 else3900 $this->flushContent($continueBuffering);3901 }3902 public function ensureHeadersSent()3903 {3904 $this->ensureHttpHeaderSent();3905 $this->ensureContentTypeHeaderSent();3906 }3907 public function flushContent($continueBuffering = true)3908 {3909 $this->ensureHeadersSent();3910 if($this->_bufferOutput)3911 {3912 if (ob_get_length()>0)3913 {3914 if (!$continueBuffering)3915 {3916 $this->_bufferOutput = false;3917 ob_end_flush();3918 }3919 else3920 ob_flush();3921 flush();3922 }3923 }3924 else3925 flush();3926 }3927 protected function ensureHttpHeaderSent()3928 {3929 if (!$this->_httpHeaderSent)3930 $this->sendHttpHeader();3931 }3932 protected function sendHttpHeader()3933 {3934 $protocol=$this->getRequest()->getHttpProtocolVersion();3935 if($this->getRequest()->getHttpProtocolVersion() === null)3936 $protocol='HTTP/1.1';3937 $phpSapiName = substr(php_sapi_name(), 0, 3);3938 $cgi = $phpSapiName == 'cgi' || $phpSapiName == 'fpm';3939 header(($cgi ? 'Status:' : $protocol).' '.$this->_status.' '.$this->_reason, true, TPropertyValue::ensureInteger($this->_status));3940 $this->_httpHeaderSent = true;3941 }3942 protected function ensureContentTypeHeaderSent()3943 {3944 if (!$this->_contentTypeHeaderSent)3945 $this->sendContentTypeHeader();3946 }3947 protected function sendContentTypeHeader()3948 {3949 $contentType=$this->_contentType===null?self::DEFAULT_CONTENTTYPE:$this->_contentType;3950 $charset=$this->getCharset();3951 if($charset === false) {3952 $this->appendHeader('Content-Type: '.$contentType);3953 return;3954 }3955 if($charset==='' && ($globalization=$this->getApplication()->getGlobalization(false))!==null)3956 $charset=$globalization->getCharset();3957 if($charset==='') $charset = self::DEFAULT_CHARSET;3958 $this->appendHeader('Content-Type: '.$contentType.';charset='.$charset);3959 $this->_contentTypeHeaderSent = true;3960 }3961 public function getContents()3962 {3963 return $this->_bufferOutput?ob_get_contents():'';3964 }3965 public function clear()3966 {3967 if($this->_bufferOutput)3968 ob_clean();3969 }3970 public function getHeaders($case=null)3971 {3972 $result = array();3973 $headers = headers_list();3974 foreach($headers as $header) {3975 $tmp = explode(':', $header);3976 $key = trim(array_shift($tmp));3977 $value = trim(implode(':', $tmp));3978 if(isset($result[$key]))3979 $result[$key] .= ', ' . $value;3980 else3981 $result[$key] = $value;3982 }3983 if($case !== null)3984 return array_change_key_case($result, $case);3985 return $result;3986 }3987 public function appendHeader($value, $replace=true)3988 {3989 header($value, $replace);3990 }3991 public function appendLog($message,$messageType=0,$destination='',$extraHeaders='')3992 {3993 error_log($message,$messageType,$destination,$extraHeaders);3994 }3995 public function addCookie($cookie)3996 {3997 $request=$this->getRequest();3998 if($request->getEnableCookieValidation())3999 {4000 $value=$this->getApplication()->getSecurityManager()->hashData($cookie->getValue());4001 setcookie(4002 $cookie->getName(),4003 $value,4004 $cookie->getExpire(),4005 $cookie->getPath(),4006 $cookie->getDomain(),4007 $cookie->getSecure(),4008 $cookie->getHttpOnly()4009 );4010 }4011 else {4012 setcookie(4013 $cookie->getName(),4014 $cookie->getValue(),4015 $cookie->getExpire(),4016 $cookie->getPath(),4017 $cookie->getDomain(),4018 $cookie->getSecure(),4019 $cookie->getHttpOnly()4020 );4021 }4022 }4023 public function removeCookie($cookie)4024 {4025 setcookie(4026 $cookie->getName(),4027 null,4028 0,4029 $cookie->getPath(),4030 $cookie->getDomain(),4031 $cookie->getSecure(),4032 $cookie->getHttpOnly()4033 );4034 }4035 public function getHtmlWriterType()4036 {4037 return $this->_htmlWriterType;4038 }4039 public function setHtmlWriterType($value)4040 {4041 $this->_htmlWriterType=$value;4042 }4043 public function createHtmlWriter($type=null)4044 {4045 if($type===null)4046 $type=$this->getHtmlWriterType();4047 if($this->getHasAdapter())4048 return $this->_adapter->createNewHtmlWriter($type, $this);4049 else4050 return $this->createNewHtmlWriter($type, $this);4051 }4052 public function createNewHtmlWriter($type, $writer)4053 {4054 return Prado::createComponent($type, $writer);4055 }4056}4057class THttpSession extends TApplicationComponent implements IteratorAggregate,ArrayAccess,Countable,IModule4058{4059 private $_initialized=false;4060 private $_started=false;4061 private $_autoStart=false;4062 private $_cookie=null;4063 private $_id;4064 private $_customStorage=false;4065 public function getID()4066 {4067 return $this->_id;4068 }4069 public function setID($value)4070 {4071 $this->_id=$value;4072 }4073 public function init($config)4074 {4075 if($this->_autoStart)4076 $this->open();4077 $this->_initialized=true;4078 $this->getApplication()->setSession($this);4079 register_shutdown_function(array($this, "close"));4080 }4081 public function open()4082 {4083 if(!$this->_started)4084 {4085 if($this->_customStorage)4086 session_set_save_handler(array($this,'_open'),array($this,'_close'),array($this,'_read'),array($this,'_write'),array($this,'_destroy'),array($this,'_gc'));4087 if($this->_cookie!==null)4088 session_set_cookie_params($this->_cookie->getExpire(),$this->_cookie->getPath(),$this->_cookie->getDomain(),$this->_cookie->getSecure(),$this->_cookie->getHttpOnly());4089 if(ini_get('session.auto_start')!=='1')4090 session_start();4091 $this->_started=true;4092 }4093 }4094 public function close()4095 {4096 if($this->_started)4097 {4098 session_write_close();4099 $this->_started=false;4100 }4101 }4102 public function destroy()4103 {4104 if($this->_started)4105 {4106 session_destroy();4107 $this->_started=false;4108 }4109 }4110 public function regenerate($deleteOld=false)4111 {4112 $old = $this->getSessionID();4113 session_regenerate_id($deleteOld);4114 return $old;4115 }4116 public function getIsStarted()4117 {4118 return $this->_started;4119 }4120 public function getSessionID()4121 {4122 return session_id();4123 }4124 public function setSessionID($value)4125 {4126 if($this->_started)4127 throw new TInvalidOperationException('httpsession_sessionid_unchangeable');4128 else4129 session_id($value);4130 }4131 public function getSessionName()4132 {4133 return session_name();4134 }4135 public function setSessionName($value)4136 {4137 if($this->_started)4138 throw new TInvalidOperationException('httpsession_sessionname_unchangeable');4139 else if(ctype_alnum($value))4140 session_name($value);4141 else4142 throw new TInvalidDataValueException('httpsession_sessionname_invalid',$value);4143 }4144 public function getSavePath()4145 {4146 return session_save_path();4147 }4148 public function setSavePath($value)4149 {4150 if($this->_started)4151 throw new TInvalidOperationException('httpsession_savepath_unchangeable');4152 else if(is_dir($value))4153 session_save_path($value);4154 else4155 throw new TInvalidDataValueException('httpsession_savepath_invalid',$value);4156 }4157 public function getUseCustomStorage()4158 {4159 return $this->_customStorage;4160 }4161 public function setUseCustomStorage($value)4162 {4163 $this->_customStorage=TPropertyValue::ensureBoolean($value);4164 }4165 public function getCookie()4166 {4167 if($this->_cookie===null)4168 $this->_cookie=new THttpCookie($this->getSessionName(),$this->getSessionID());4169 return $this->_cookie;4170 }4171 public function getCookieMode()4172 {4173 if(ini_get('session.use_cookies')==='0')4174 return THttpSessionCookieMode::None;4175 else if(ini_get('session.use_only_cookies')==='0')4176 return THttpSessionCookieMode::Allow;4177 else4178 return THttpSessionCookieMode::Only;4179 }4180 public function setCookieMode($value)4181 {4182 if($this->_started)4183 throw new TInvalidOperationException('httpsession_cookiemode_unchangeable');4184 else4185 {4186 $value=TPropertyValue::ensureEnum($value,'THttpSessionCookieMode');4187 if($value===THttpSessionCookieMode::None) 4188 {4189 ini_set('session.use_cookies','0');4190 ini_set('session.use_only_cookies','0');4191 }4192 else if($value===THttpSessionCookieMode::Allow)4193 {4194 ini_set('session.use_cookies','1');4195 ini_set('session.use_only_cookies','0');4196 }4197 else4198 {4199 ini_set('session.use_cookies','1');4200 ini_set('session.use_only_cookies','1');4201 ini_set('session.use_trans_sid', 0);4202 }4203 }4204 }4205 public function getAutoStart()4206 {4207 return $this->_autoStart;4208 }4209 public function setAutoStart($value)4210 {4211 if($this->_initialized)4212 throw new TInvalidOperationException('httpsession_autostart_unchangeable');4213 else4214 $this->_autoStart=TPropertyValue::ensureBoolean($value);4215 }4216 public function getGCProbability()4217 {4218 return TPropertyValue::ensureInteger(ini_get('session.gc_probability'));4219 }4220 public function setGCProbability($value)4221 {4222 if($this->_started)4223 throw new TInvalidOperationException('httpsession_gcprobability_unchangeable');4224 else4225 {4226 $value=TPropertyValue::ensureInteger($value);4227 if($value>=0 && $value<=100)4228 {4229 ini_set('session.gc_probability',$value);4230 ini_set('session.gc_divisor','100');4231 }4232 else4233 throw new TInvalidDataValueException('httpsession_gcprobability_invalid',$value);4234 }4235 }4236 public function getUseTransparentSessionID()4237 {4238 return ini_get('session.use_trans_sid')==='1';4239 }4240 public function setUseTransparentSessionID($value)4241 {4242 if($this->_started)4243 throw new TInvalidOperationException('httpsession_transid_unchangeable');4244 else4245 {4246 $value=TPropertyValue::ensureBoolean($value);4247 if ($value && $this->getCookieMode()==THttpSessionCookieMode::Only)4248 throw new TInvalidOperationException('httpsession_transid_cookieonly');4249 ini_set('session.use_trans_sid',$value?'1':'0');4250 }4251 }4252 public function getTimeout()4253 {4254 return TPropertyValue::ensureInteger(ini_get('session.gc_maxlifetime'));4255 }4256 public function setTimeout($value)4257 {4258 if($this->_started)4259 throw new TInvalidOperationException('httpsession_maxlifetime_unchangeable');4260 else4261 ini_set('session.gc_maxlifetime',$value);4262 }4263 public function _open($savePath,$sessionName)4264 {4265 return true;4266 }4267 public function _close()4268 {4269 return true;4270 }4271 public function _read($id)4272 {4273 return '';4274 }4275 public function _write($id,$data)4276 {4277 return true;4278 }4279 public function _destroy($id)4280 {4281 return true;4282 }4283 public function _gc($maxLifetime)4284 {4285 return true;4286 }4287 public function getIterator()4288 {4289 return new TSessionIterator;4290 }4291 public function getCount()4292 {4293 return count($_SESSION);4294 }4295 public function count()4296 {4297 return $this->getCount();4298 }4299 public function getKeys()4300 {4301 return array_keys($_SESSION);4302 }4303 public function itemAt($key)4304 {4305 return isset($_SESSION[$key]) ? $_SESSION[$key] : null;4306 }4307 public function add($key,$value)4308 {4309 $_SESSION[$key]=$value;4310 }4311 public function remove($key)4312 {4313 if(isset($_SESSION[$key]))4314 {4315 $value=$_SESSION[$key];4316 unset($_SESSION[$key]);4317 return $value;4318 }4319 else4320 return null;4321 }4322 public function clear()4323 {4324 foreach(array_keys($_SESSION) as $key)4325 unset($_SESSION[$key]);4326 }4327 public function contains($key)4328 {4329 return isset($_SESSION[$key]);4330 }4331 public function toArray()4332 {4333 return $_SESSION;4334 }4335 public function offsetExists($offset)4336 {4337 return isset($_SESSION[$offset]);4338 }4339 public function offsetGet($offset)4340 {4341 return isset($_SESSION[$offset]) ? $_SESSION[$offset] : null;4342 }4343 public function offsetSet($offset,$item)4344 {4345 $_SESSION[$offset]=$item;4346 }4347 public function offsetUnset($offset)4348 {4349 unset($_SESSION[$offset]);4350 }4351}4352class TSessionIterator implements Iterator4353{4354 private $_keys;4355 private $_key;4356 public function __construct()4357 {4358 $this->_keys=array_keys($_SESSION);4359 }4360 public function rewind()4361 {4362 $this->_key=reset($this->_keys);4363 }4364 public function key()4365 {4366 return $this->_key;4367 }4368 public function current()4369 {4370 return isset($_SESSION[$this->_key])?$_SESSION[$this->_key]:null;4371 }4372 public function next()4373 {4374 do4375 {4376 $this->_key=next($this->_keys);4377 }4378 while(!isset($_SESSION[$this->_key]) && $this->_key!==false);4379 }4380 public function valid()4381 {4382 return $this->_key!==false;4383 }4384}4385class THttpSessionCookieMode extends TEnumerable4386{4387 const None='None';4388 const Allow='Allow';4389 const Only='Only';4390}4391Prado::using('System.Web.UI.WebControls.*');4392class TAttributeCollection extends TMap4393{4394 private $_caseSensitive=false;4395 protected function _getZappableSleepProps(&$exprops)4396 {4397 parent::_getZappableSleepProps($exprops);4398 if ($this->_caseSensitive===false)4399 $exprops[] = "\0TAttributeCollection\0_caseSensitive";4400 }4401 public function __get($name)4402 {4403 return $this->contains($name)?$this->itemAt($name):parent::__get($name);4404 }4405 public function __set($name,$value)4406 {4407 $this->add($name,$value);4408 }4409 public function getCaseSensitive()4410 {4411 return $this->_caseSensitive;4412 }4413 public function setCaseSensitive($value)4414 {4415 $this->_caseSensitive=TPropertyValue::ensureBoolean($value);4416 }4417 public function itemAt($key)4418 {4419 return parent::itemAt($this->_caseSensitive?$key:strtolower($key));4420 }4421 public function add($key,$value)4422 {4423 parent::add($this->_caseSensitive?$key:strtolower($key),$value);4424 }4425 public function remove($key)4426 {4427 return parent::remove($this->_caseSensitive?$key:strtolower($key));4428 }4429 public function contains($key)4430 {4431 return parent::contains($this->_caseSensitive?$key:strtolower($key));4432 }4433 public function hasProperty($name)4434 {4435 return $this->contains($name) || parent::canGetProperty($name) || parent::canSetProperty($name);4436 }4437 public function canGetProperty($name)4438 {4439 return $this->contains($name) || parent::canGetProperty($name);4440 }4441 public function canSetProperty($name)4442 {4443 return true;4444 }4445}4446class TControlAdapter extends TApplicationComponent4447{4448 protected $_control;4449 public function __construct($control)4450 {4451 $this->_control=$control;4452 }4453 public function getControl()4454 {4455 return $this->_control;4456 }4457 public function getPage()4458 {4459 return $this->_control?$this->_control->getPage():null;4460 }4461 public function createChildControls()4462 {4463 $this->_control->createChildControls();4464 }4465 public function loadState()4466 {4467 $this->_control->loadState();4468 }4469 public function saveState()4470 {4471 $this->_control->saveState();4472 }4473 public function onInit($param)4474 {4475 $this->_control->onInit($param);4476 }4477 public function onLoad($param)4478 {4479 $this->_control->onLoad($param);4480 }4481 public function onPreRender($param)4482 {4483 $this->_control->onPreRender($param);4484 }4485 public function onUnload($param)4486 {4487 $this->_control->onUnload($param);4488 }4489 public function render($writer)4490 {4491 $this->_control->render($writer);4492 }4493 public function renderChildren($writer)4494 {4495 $this->_control->renderChildren($writer);4496 }4497}4498class TControl extends TApplicationComponent implements IRenderable, IBindable4499{4500 const ID_FORMAT='/^[a-zA-Z_]\\w*$/';4501 const ID_SEPARATOR='$';4502 const CLIENT_ID_SEPARATOR='_';4503 const AUTOMATIC_ID_PREFIX='ctl';4504 const CS_CONSTRUCTED=0;4505 const CS_CHILD_INITIALIZED=1;4506 const CS_INITIALIZED=2;4507 const CS_STATE_LOADED=3;4508 const CS_LOADED=4;4509 const CS_PRERENDERED=5;4510 const IS_ID_SET=0x01;4511 const IS_DISABLE_VIEWSTATE=0x02;4512 const IS_SKIN_APPLIED=0x04;4513 const IS_STYLESHEET_APPLIED=0x08;4514 const IS_DISABLE_THEMING=0x10;4515 const IS_CHILD_CREATED=0x20;4516 const IS_CREATING_CHILD=0x40;4517 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; 4518 private $_id='';4519 private $_uid;4520 private $_parent;4521 private $_page;4522 private $_namingContainer;4523 private $_tplControl;4524 private $_viewState=array();4525 private $_tempState=array();4526 private $_trackViewState=true;4527 private $_stage=0;4528 private $_flags=0;4529 private $_rf=array();4530 public function __get($name)4531 {4532 if(isset($this->_rf[self::RF_NAMED_OBJECTS][$name]))4533 return $this->_rf[self::RF_NAMED_OBJECTS][$name];4534 else4535 return parent::__get($name);4536 }4537 public function __isset($name) {4538 if(isset($this->_rf[self::RF_NAMED_OBJECTS][$name])) {4539 return true;4540 } else {4541 return parent::__isset($name);4542 }4543 }4544 public function getHasAdapter()4545 {4546 return isset($this->_rf[self::RF_ADAPTER]);4547 }4548 public function getAdapter()4549 {4550 return isset($this->_rf[self::RF_ADAPTER])?$this->_rf[self::RF_ADAPTER]:null;4551 }4552 public function setAdapter(TControlAdapter $adapter)4553 {4554 $this->_rf[self::RF_ADAPTER]=$adapter;4555 }4556 public function getParent()4557 {4558 return $this->_parent;4559 }4560 public function getNamingContainer()4561 {4562 if(!$this->_namingContainer && $this->_parent)4563 {4564 if($this->_parent instanceof INamingContainer)4565 $this->_namingContainer=$this->_parent;4566 else4567 $this->_namingContainer=$this->_parent->getNamingContainer();4568 }4569 return $this->_namingContainer;4570 }4571 public function getPage()4572 {4573 if(!$this->_page)4574 {4575 if($this->_parent)4576 $this->_page=$this->_parent->getPage();4577 else if($this->_tplControl)4578 $this->_page=$this->_tplControl->getPage();4579 }4580 return $this->_page;4581 }4582 public function setPage($page)4583 {4584 $this->_page=$page;4585 }4586 public function setTemplateControl($control)4587 {4588 $this->_tplControl=$control;4589 }4590 public function getTemplateControl()4591 {4592 if(!$this->_tplControl && $this->_parent)4593 $this->_tplControl=$this->_parent->getTemplateControl();4594 return $this->_tplControl;4595 }4596 public function getSourceTemplateControl()4597 {4598 $control=$this;4599 while(($control instanceof TControl) && ($control=$control->getTemplateControl())!==null)4600 {4601 if(($control instanceof TTemplateControl) && $control->getIsSourceTemplateControl())4602 return $control;4603 }4604 return $this->getPage();4605 }4606 protected function getControlStage()4607 {4608 return $this->_stage;4609 }4610 protected function setControlStage($value)4611 {4612 $this->_stage=$value;4613 }4614 public function getID($hideAutoID=true)4615 {4616 if($hideAutoID)4617 return ($this->_flags & self::IS_ID_SET) ? $this->_id : '';4618 else4619 return $this->_id;4620 }4621 public function setID($id)4622 {4623 if(!preg_match(self::ID_FORMAT,$id))4624 throw new TInvalidDataValueException('control_id_invalid',get_class($this),$id);4625 $this->_id=$id;4626 $this->_flags |= self::IS_ID_SET;4627 $this->clearCachedUniqueID($this instanceof INamingContainer);4628 if($this->_namingContainer)4629 $this->_namingContainer->clearNameTable();4630 }4631 public function getUniqueID()4632 {4633 if($this->_uid==='' || $this->_uid===null) {4634 $this->_uid=''; if($namingContainer=$this->getNamingContainer())4635 {4636 if($this->getPage()===$namingContainer)4637 return ($this->_uid=$this->_id);4638 else if(($prefix=$namingContainer->getUniqueID())==='')4639 return $this->_id;4640 else4641 return ($this->_uid=$prefix.self::ID_SEPARATOR.$this->_id);4642 }4643 else return $this->_id;4644 }4645 else4646 return $this->_uid;4647 }4648 public function focus()4649 {4650 $this->getPage()->setFocus($this);4651 }4652 public function getClientID()4653 {4654 return strtr($this->getUniqueID(),self::ID_SEPARATOR,self::CLIENT_ID_SEPARATOR);4655 }4656 public static function convertUniqueIdToClientId($uniqueID)4657 {4658 return strtr($uniqueID,self::ID_SEPARATOR,self::CLIENT_ID_SEPARATOR);4659 }4660 public function getSkinID()4661 {4662 return isset($this->_rf[self::RF_SKIN_ID])?$this->_rf[self::RF_SKIN_ID]:'';4663 }4664 public function setSkinID($value)4665 {4666 if(($this->_flags & self::IS_SKIN_APPLIED) || $this->_stage>=self::CS_CHILD_INITIALIZED)4667 throw new TInvalidOperationException('control_skinid_unchangeable',get_class($this));4668 else4669 $this->_rf[self::RF_SKIN_ID]=$value;4670 }4671 public function getIsSkinApplied()4672 {4673 return ($this->_flags & self::IS_SKIN_APPLIED);4674 }4675 public function getEnableTheming()4676 {4677 if($this->_flags & self::IS_DISABLE_THEMING)4678 return false;4679 else4680 return $this->_parent?$this->_parent->getEnableTheming():true;4681 }4682 public function setEnableTheming($value)4683 {4684 if($this->_stage>=self::CS_CHILD_INITIALIZED)4685 throw new TInvalidOperationException('control_enabletheming_unchangeable',get_class($this),$this->getUniqueID());4686 else if(TPropertyValue::ensureBoolean($value))4687 $this->_flags &= ~self::IS_DISABLE_THEMING;4688 else4689 $this->_flags |= self::IS_DISABLE_THEMING;4690 }4691 public function getCustomData()4692 {4693 return $this->getViewState('CustomData',null);4694 }4695 public function setCustomData($value)4696 {4697 $this->setViewState('CustomData',$value,null);4698 }4699 public function getHasControls()4700 {4701 return isset($this->_rf[self::RF_CONTROLS]) && $this->_rf[self::RF_CONTROLS]->getCount()>0;4702 }4703 public function getControls()4704 {4705 if(!isset($this->_rf[self::RF_CONTROLS]))4706 $this->_rf[self::RF_CONTROLS]=$this->createControlCollection();4707 return $this->_rf[self::RF_CONTROLS];4708 }4709 protected function createControlCollection()4710 {4711 return $this->getAllowChildControls()?new TControlCollection($this):new TEmptyControlCollection($this);4712 }4713 public function getVisible($checkParents=true)4714 {4715 if($checkParents)4716 {4717 for($control=$this;$control;$control=$control->_parent)4718 if(!$control->getVisible(false))4719 return false;4720 return true;4721 }4722 else4723 return $this->getViewState('Visible',true);4724 }4725 public function setVisible($value)4726 {4727 $this->setViewState('Visible',TPropertyValue::ensureBoolean($value),true);4728 }4729 public function getEnabled($checkParents=false)4730 {4731 if($checkParents)4732 {4733 for($control=$this;$control;$control=$control->_parent)4734 if(!$control->getViewState('Enabled',true))4735 return false;4736 return true;4737 }4738 else4739 return $this->getViewState('Enabled',true);4740 }4741 public function setEnabled($value)4742 {4743 $this->setViewState('Enabled',TPropertyValue::ensureBoolean($value),true);4744 }4745 public function getHasAttributes()4746 {4747 if($attributes=$this->getViewState('Attributes',null))4748 return $attributes->getCount()>0;4749 else4750 return false;4751 }4752 public function getAttributes()4753 {4754 if($attributes=$this->getViewState('Attributes',null))4755 return $attributes;4756 else4757 {4758 $attributes=new TAttributeCollection;4759 $this->setViewState('Attributes',$attributes,null);4760 return $attributes;4761 }4762 }4763 public function hasAttribute($name)4764 {4765 if($attributes=$this->getViewState('Attributes',null))4766 return $attributes->contains($name);4767 else4768 return false;4769 }4770 public function getAttribute($name)4771 {4772 if($attributes=$this->getViewState('Attributes',null))4773 return $attributes->itemAt($name);4774 else4775 return null;4776 }4777 public function setAttribute($name,$value)4778 {4779 $this->getAttributes()->add($name,$value);4780 }4781 public function removeAttribute($name)4782 {4783 if($attributes=$this->getViewState('Attributes',null))4784 return $attributes->remove($name);4785 else4786 return null;4787 }4788 public function getEnableViewState($checkParents=false)4789 {4790 if($checkParents)4791 {4792 for($control=$this;$control!==null;$control=$control->getParent())4793 if($control->_flags & self::IS_DISABLE_VIEWSTATE)4794 return false;4795 return true;4796 }4797 else4798 return !($this->_flags & self::IS_DISABLE_VIEWSTATE);4799 }4800 public function setEnableViewState($value)4801 {4802 if(TPropertyValue::ensureBoolean($value))4803 $this->_flags &= ~self::IS_DISABLE_VIEWSTATE;4804 else4805 $this->_flags |= self::IS_DISABLE_VIEWSTATE;4806 }4807 protected function getControlState($key,$defaultValue=null)4808 {4809 return isset($this->_rf[self::RF_CONTROLSTATE][$key])?$this->_rf[self::RF_CONTROLSTATE][$key]:$defaultValue;4810 }4811 protected function setControlState($key,$value,$defaultValue=null)4812 {4813 if($value===$defaultValue)4814 unset($this->_rf[self::RF_CONTROLSTATE][$key]);4815 else4816 $this->_rf[self::RF_CONTROLSTATE][$key]=$value;4817 }4818 protected function clearControlState($key)4819 {4820 unset($this->_rf[self::RF_CONTROLSTATE][$key]);4821 }4822 public function trackViewState($enabled)4823 {4824 $this->_trackViewState=TPropertyValue::ensureBoolean($enabled);4825 }4826 public function getViewState($key,$defaultValue=null)4827 {4828 if(isset($this->_viewState[$key]))4829 return $this->_viewState[$key]!==null?$this->_viewState[$key]:$defaultValue;4830 else if(isset($this->_tempState[$key]))4831 {4832 if(is_object($this->_tempState[$key]) && $this->_trackViewState)4833 $this->_viewState[$key]=$this->_tempState[$key];4834 return $this->_tempState[$key];4835 }4836 else4837 return $defaultValue;4838 }4839 public function setViewState($key,$value,$defaultValue=null)4840 {4841 if($this->_trackViewState)4842 {4843 unset($this->_tempState[$key]);4844 $this->_viewState[$key]=$value;4845 }4846 else4847 {4848 unset($this->_viewState[$key]);4849 if($value===$defaultValue)4850 unset($this->_tempState[$key]);4851 else4852 $this->_tempState[$key]=$value;4853 }4854 }4855 public function clearViewState($key)4856 {4857 unset($this->_viewState[$key]);4858 unset($this->_tempState[$key]);4859 }4860 public function bindProperty($name,$expression)4861 {4862 $this->_rf[self::RF_DATA_BINDINGS][$name]=$expression;4863 }4864 public function unbindProperty($name)4865 {4866 unset($this->_rf[self::RF_DATA_BINDINGS][$name]);4867 }4868 public function autoBindProperty($name,$expression)4869 {4870 $this->_rf[self::RF_AUTO_BINDINGS][$name]=$expression;4871 }4872 public function dataBind()4873 {4874 $this->dataBindProperties();4875 $this->onDataBinding(null);4876 $this->dataBindChildren();4877 }4878 protected function dataBindProperties()4879 {4880 if(isset($this->_rf[self::RF_DATA_BINDINGS]))4881 {4882 if(($context=$this->getTemplateControl())===null)4883 $context=$this;4884 foreach($this->_rf[self::RF_DATA_BINDINGS] as $property=>$expression)4885 $this->setSubProperty($property,$context->evaluateExpression($expression));4886 }4887 }4888 protected function autoDataBindProperties()4889 {4890 if(isset($this->_rf[self::RF_AUTO_BINDINGS]))4891 {4892 if(($context=$this->getTemplateControl())===null)4893 $context=$this;4894 foreach($this->_rf[self::RF_AUTO_BINDINGS] as $property=>$expression)4895 $this->setSubProperty($property,$context->evaluateExpression($expression));4896 }4897 }4898 protected function dataBindChildren()4899 {4900 if(isset($this->_rf[self::RF_CONTROLS]))4901 {4902 foreach($this->_rf[self::RF_CONTROLS] as $control)4903 if($control instanceof IBindable)4904 $control->dataBind();4905 }4906 }4907 final protected function getChildControlsCreated()4908 {4909 return ($this->_flags & self::IS_CHILD_CREATED)!==0;4910 }4911 final protected function setChildControlsCreated($value)4912 {4913 if($value)4914 $this->_flags |= self::IS_CHILD_CREATED;4915 else4916 {4917 if($this->getHasControls() && ($this->_flags & self::IS_CHILD_CREATED))4918 $this->getControls()->clear();4919 $this->_flags &= ~self::IS_CHILD_CREATED;4920 }4921 }4922 public function ensureChildControls()4923 {4924 if(!($this->_flags & self::IS_CHILD_CREATED) && !($this->_flags & self::IS_CREATING_CHILD))4925 {4926 try4927 {4928 $this->_flags |= self::IS_CREATING_CHILD;4929 if(isset($this->_rf[self::RF_ADAPTER]))4930 $this->_rf[self::RF_ADAPTER]->createChildControls();4931 else4932 $this->createChildControls();4933 $this->_flags &= ~self::IS_CREATING_CHILD;4934 $this->_flags |= self::IS_CHILD_CREATED;4935 }4936 catch(Exception $e)4937 {4938 $this->_flags &= ~self::IS_CREATING_CHILD;4939 $this->_flags |= self::IS_CHILD_CREATED;4940 throw $e;4941 }4942 }4943 }4944 public function createChildControls()4945 {4946 }4947 public function findControl($id)4948 {4949 $id=strtr($id,'.',self::ID_SEPARATOR);4950 $container=($this instanceof INamingContainer)?$this:$this->getNamingContainer();4951 if(!$container || !$container->getHasControls())4952 return null;4953 if(!isset($container->_rf[self::RF_NAMED_CONTROLS]))4954 {4955 $container->_rf[self::RF_NAMED_CONTROLS]=array();4956 $container->fillNameTable($container,$container->_rf[self::RF_CONTROLS]);4957 }4958 if(($pos=strpos($id,self::ID_SEPARATOR))===false)4959 return isset($container->_rf[self::RF_NAMED_CONTROLS][$id])?$container->_rf[self::RF_NAMED_CONTROLS][$id]:null;4960 else4961 {4962 $cid=substr($id,0,$pos);4963 $sid=substr($id,$pos+1);4964 if(isset($container->_rf[self::RF_NAMED_CONTROLS][$cid]))4965 return $container->_rf[self::RF_NAMED_CONTROLS][$cid]->findControl($sid);4966 else4967 return null;4968 }4969 }4970 public function findControlsByType($type,$strict=true)4971 {4972 $controls=array();4973 if($this->getHasControls())4974 {4975 foreach($this->_rf[self::RF_CONTROLS] as $control)4976 {4977 if(is_object($control) && (get_class($control)===$type || (!$strict && ($control instanceof $type))))4978 $controls[]=$control;4979 if(($control instanceof TControl) && $control->getHasControls())4980 $controls=array_merge($controls,$control->findControlsByType($type,$strict));4981 }4982 }4983 return $controls;4984 }4985 public function findControlsByID($id)4986 {4987 $controls=array();4988 if($this->getHasControls())4989 {4990 foreach($this->_rf[self::RF_CONTROLS] as $control)4991 {4992 if($control instanceof TControl)4993 {4994 if($control->_id===$id)4995 $controls[]=$control;4996 $controls=array_merge($controls,$control->findControlsByID($id));4997 }4998 }4999 }5000 return $controls;5001 }5002 public function clearNamingContainer()5003 {5004 unset($this->_rf[self::RF_NAMED_CONTROLS_ID]);5005 $this->clearNameTable();5006 }5007 public function registerObject($name,$object)5008 {5009 if(isset($this->_rf[self::RF_NAMED_OBJECTS][$name]))5010 throw new TInvalidOperationException('control_object_reregistered',$name);5011 $this->_rf[self::RF_NAMED_OBJECTS][$name]=$object;5012 }5013 public function unregisterObject($name)5014 {5015 unset($this->_rf[self::RF_NAMED_OBJECTS][$name]);5016 }5017 public function isObjectRegistered($name)5018 {5019 return isset($this->_rf[self::RF_NAMED_OBJECTS][$name]);5020 }5021 public function getHasChildInitialized()5022 {5023 return $this->getControlStage() >= self::CS_CHILD_INITIALIZED;5024 }5025 public function getHasInitialized()5026 {5027 return $this->getControlStage() >= self::CS_INITIALIZED;5028 }5029 public function getHasLoadedPostData()5030 {5031 return $this->getControlStage() >= self::CS_STATE_LOADED;5032 }5033 public function getHasLoaded()5034 {5035 return $this->getControlStage() >= self::CS_LOADED;5036 }5037 public function getHasPreRendered()5038 {5039 return $this->getControlStage() >= self::CS_PRERENDERED;5040 }5041 public function getRegisteredObject($name)5042 {5043 return isset($this->_rf[self::RF_NAMED_OBJECTS][$name])?$this->_rf[self::RF_NAMED_OBJECTS][$name]:null;5044 }5045 public function getAllowChildControls()5046 {5047 return true;5048 }5049 public function addParsedObject($object)5050 {5051 $this->getControls()->add($object);5052 }5053 final protected function clearChildState()5054 {5055 unset($this->_rf[self::RF_CHILD_STATE]);5056 }5057 final protected function isDescendentOf($ancestor)5058 {5059 $control=$this;5060 while($control!==$ancestor && $control->_parent)5061 $control=$control->_parent;5062 return $control===$ancestor;5063 }5064 public function addedControl($control)5065 {5066 if($control->_parent)5067 $control->_parent->getControls()->remove($control);5068 $control->_parent=$this;5069 $control->_page=$this->getPage();5070 $namingContainer=($this instanceof INamingContainer)?$this:$this->_namingContainer;5071 if($namingContainer)5072 {5073 $control->_namingContainer=$namingContainer;5074 if($control->_id==='')5075 $control->generateAutomaticID();5076 else5077 $namingContainer->clearNameTable();5078 $control->clearCachedUniqueID($control instanceof INamingContainer);5079 }5080 if($this->_stage>=self::CS_CHILD_INITIALIZED)5081 {5082 $control->initRecursive($namingContainer);5083 if($this->_stage>=self::CS_STATE_LOADED)5084 {5085 if(isset($this->_rf[self::RF_CHILD_STATE][$control->_id]))5086 {5087 $state=$this->_rf[self::RF_CHILD_STATE][$control->_id];5088 unset($this->_rf[self::RF_CHILD_STATE][$control->_id]);5089 }5090 else5091 $state=null;5092 $control->loadStateRecursive($state,!($this->_flags & self::IS_DISABLE_VIEWSTATE));5093 if($this->_stage>=self::CS_LOADED)5094 {5095 $control->loadRecursive();5096 if($this->_stage>=self::CS_PRERENDERED)5097 $control->preRenderRecursive();5098 }5099 }5100 }5101 }5102 public function removedControl($control)5103 {5104 if($this->_namingContainer)5105 $this->_namingContainer->clearNameTable();5106 $control->unloadRecursive();5107 $control->_parent=null;5108 $control->_page=null;5109 $control->_namingContainer=null;5110 $control->_tplControl=null;5111 if(!($control->_flags & self::IS_ID_SET))5112 $control->_id='';5113 else5114 unset($this->_rf[self::RF_NAMED_OBJECTS][$control->_id]);5115 $control->clearCachedUniqueID(true);5116 }5117 protected function initRecursive($namingContainer=null)5118 {5119 $this->ensureChildControls();5120 if($this->getHasControls())5121 {5122 if($this instanceof INamingContainer)5123 $namingContainer=$this;5124 $page=$this->getPage();5125 foreach($this->_rf[self::RF_CONTROLS] as $control)5126 {5127 if($control instanceof TControl)5128 {5129 $control->_namingContainer=$namingContainer;5130 $control->_page=$page;5131 if($control->_id==='' && $namingContainer)5132 $control->generateAutomaticID();5133 $control->initRecursive($namingContainer);5134 }5135 }5136 }5137 if($this->_stage<self::CS_INITIALIZED)5138 {5139 $this->_stage=self::CS_CHILD_INITIALIZED;5140 if(($page=$this->getPage()) && $this->getEnableTheming() && !($this->_flags & self::IS_SKIN_APPLIED))5141 {5142 $page->applyControlSkin($this);5143 $this->_flags |= self::IS_SKIN_APPLIED;5144 }5145 if(isset($this->_rf[self::RF_ADAPTER]))5146 $this->_rf[self::RF_ADAPTER]->onInit(null);5147 else5148 $this->onInit(null);5149 $this->_stage=self::CS_INITIALIZED;5150 }5151 }5152 protected function loadRecursive()5153 {5154 if($this->_stage<self::CS_LOADED)5155 {5156 if(isset($this->_rf[self::RF_ADAPTER]))5157 $this->_rf[self::RF_ADAPTER]->onLoad(null);5158 else5159 $this->onLoad(null);5160 }5161 if($this->getHasControls())5162 {5163 foreach($this->_rf[self::RF_CONTROLS] as $control)5164 {5165 if($control instanceof TControl)5166 $control->loadRecursive();5167 }5168 }5169 if($this->_stage<self::CS_LOADED)5170 $this->_stage=self::CS_LOADED;5171 }5172 protected function preRenderRecursive()5173 {5174 $this->autoDataBindProperties();5175 if($this->getVisible(false))5176 {5177 if(isset($this->_rf[self::RF_ADAPTER]))5178 $this->_rf[self::RF_ADAPTER]->onPreRender(null);5179 else5180 $this->onPreRender(null);5181 if($this->getHasControls())5182 {5183 foreach($this->_rf[self::RF_CONTROLS] as $control)5184 {5185 if($control instanceof TControl)5186 $control->preRenderRecursive();5187 else if($control instanceof TCompositeLiteral)5188 $control->evaluateDynamicContent();5189 }5190 }5191 }5192 $this->_stage=self::CS_PRERENDERED;5193 }5194 protected function unloadRecursive()5195 {5196 if(!($this->_flags & self::IS_ID_SET))5197 $this->_id='';5198 if($this->getHasControls())5199 {5200 foreach($this->_rf[self::RF_CONTROLS] as $control)5201 if($control instanceof TControl)5202 $control->unloadRecursive();5203 }5204 if(isset($this->_rf[self::RF_ADAPTER]))5205 $this->_rf[self::RF_ADAPTER]->onUnload(null);5206 else5207 $this->onUnload(null);5208 }5209 public function onInit($param)5210 {5211 $this->raiseEvent('OnInit',$this,$param);5212 }5213 public function onLoad($param)5214 {5215 $this->raiseEvent('OnLoad',$this,$param);5216 }5217 public function onDataBinding($param)5218 {5219 $this->raiseEvent('OnDataBinding',$this,$param);5220 }5221 public function onUnload($param)5222 {5223 $this->raiseEvent('OnUnload',$this,$param);5224 }5225 public function onPreRender($param)5226 {5227 $this->raiseEvent('OnPreRender',$this,$param);5228 }5229 protected function raiseBubbleEvent($sender,$param)5230 {5231 $control=$this;5232 while($control=$control->_parent)5233 {5234 if($control->bubbleEvent($sender,$param))5235 break;5236 }5237 }5238 public function bubbleEvent($sender,$param)5239 {5240 return false;5241 }5242 public function broadcastEvent($name,$sender,$param)5243 {5244 $rootControl=(($page=$this->getPage())===null)?$this:$page;5245 $rootControl->broadcastEventInternal($name,$sender,new TBroadcastEventParameter($name,$param));5246 }5247 private function broadcastEventInternal($name,$sender,$param)5248 {5249 if($this->hasEvent($name))5250 $this->raiseEvent($name,$sender,$param->getParameter());5251 if($this instanceof IBroadcastEventReceiver)5252 $this->broadcastEventReceived($sender,$param);5253 if($this->getHasControls())5254 {5255 foreach($this->_rf[self::RF_CONTROLS] as $control)5256 {5257 if($control instanceof TControl)5258 $control->broadcastEventInternal($name,$sender,$param);5259 }5260 }5261 }5262 protected function traverseChildControls($param,$preCallback=null,$postCallback=null)5263 {5264 if($preCallback!==null)5265 call_user_func($preCallback,$this,$param);5266 if($this->getHasControls())5267 {5268 foreach($this->_rf[self::RF_CONTROLS] as $control)5269 {5270 if($control instanceof TControl)5271 {5272 $control->traverseChildControls($param,$preCallback,$postCallback);5273 }5274 }5275 }5276 if($postCallback!==null)5277 call_user_func($postCallback,$this,$param);5278 }5279 public function renderControl($writer)5280 {5281 if($this instanceof IActiveControl || $this->getVisible(false))5282 {5283 if(isset($this->_rf[self::RF_ADAPTER]))5284 $this->_rf[self::RF_ADAPTER]->render($writer);5285 else5286 $this->render($writer);5287 }5288 }5289 public function render($writer)5290 {5291 $this->renderChildren($writer);5292 }5293 public function renderChildren($writer)5294 {5295 if($this->getHasControls())5296 {5297 foreach($this->_rf[self::RF_CONTROLS] as $control)5298 {5299 if(is_string($control))5300 $writer->write($control);5301 else if($control instanceof TControl)5302 $control->renderControl($writer);5303 else if($control instanceof IRenderable)5304 $control->render($writer);5305 }5306 }5307 }5308 public function saveState()5309 {5310 }5311 public function loadState()5312 {5313 }5314 protected function loadStateRecursive(&$state,$needViewState=true)5315 {5316 if(is_array($state))5317 {5318 $needViewState=($needViewState && !($this->_flags & self::IS_DISABLE_VIEWSTATE));5319 if(isset($state[1]))5320 {5321 $this->_rf[self::RF_CONTROLSTATE]=&$state[1];5322 unset($state[1]);5323 }5324 else5325 unset($this->_rf[self::RF_CONTROLSTATE]);5326 if($needViewState)5327 {5328 if(isset($state[0]))5329 $this->_viewState=&$state[0];5330 else5331 $this->_viewState=array();5332 }5333 unset($state[0]);5334 if($this->getHasControls())5335 {5336 foreach($this->_rf[self::RF_CONTROLS] as $control)5337 {5338 if($control instanceof TControl)5339 {5340 if(isset($state[$control->_id]))5341 {5342 $control->loadStateRecursive($state[$control->_id],$needViewState);5343 unset($state[$control->_id]);5344 }5345 }5346 }5347 }5348 if(!empty($state))5349 $this->_rf[self::RF_CHILD_STATE]=&$state;5350 }5351 $this->_stage=self::CS_STATE_LOADED;5352 if(isset($this->_rf[self::RF_ADAPTER]))5353 $this->_rf[self::RF_ADAPTER]->loadState();5354 else5355 $this->loadState();5356 }5357 protected function &saveStateRecursive($needViewState=true)5358 {5359 if(isset($this->_rf[self::RF_ADAPTER]))5360 $this->_rf[self::RF_ADAPTER]->saveState();5361 else5362 $this->saveState();5363 $needViewState=($needViewState && !($this->_flags & self::IS_DISABLE_VIEWSTATE));5364 $state=array();5365 if($this->getHasControls())5366 {5367 foreach($this->_rf[self::RF_CONTROLS] as $control)5368 {5369 if($control instanceof TControl)5370 {5371 if(count($tmp = &$control->saveStateRecursive($needViewState)))5372 $state[$control->_id]=$tmp;5373 }5374 }5375 }5376 if($needViewState && !empty($this->_viewState))5377 $state[0]=&$this->_viewState;5378 if(isset($this->_rf[self::RF_CONTROLSTATE]))5379 $state[1]=&$this->_rf[self::RF_CONTROLSTATE];5380 return $state;5381 }5382 public function applyStyleSheetSkin($page)5383 {5384 if($page && !($this->_flags & self::IS_STYLESHEET_APPLIED))5385 {5386 $page->applyControlStyleSheet($this);5387 $this->_flags |= self::IS_STYLESHEET_APPLIED;5388 }5389 else if($this->_flags & self::IS_STYLESHEET_APPLIED)5390 throw new TInvalidOperationException('control_stylesheet_applied',get_class($this));5391 }5392 private function clearCachedUniqueID($recursive)5393 {5394 if($recursive && $this->_uid!==null && isset($this->_rf[self::RF_CONTROLS]))5395 {5396 foreach($this->_rf[self::RF_CONTROLS] as $control)5397 if($control instanceof TControl)5398 $control->clearCachedUniqueID($recursive);5399 }5400 $this->_uid=null;5401 }5402 private function generateAutomaticID()5403 {5404 $this->_flags &= ~self::IS_ID_SET;5405 if(!isset($this->_namingContainer->_rf[self::RF_NAMED_CONTROLS_ID]))5406 $this->_namingContainer->_rf[self::RF_NAMED_CONTROLS_ID]=0;5407 $id=$this->_namingContainer->_rf[self::RF_NAMED_CONTROLS_ID]++;5408 $this->_id=self::AUTOMATIC_ID_PREFIX . $id;5409 $this->_namingContainer->clearNameTable();5410 }5411 private function clearNameTable()5412 {5413 unset($this->_rf[self::RF_NAMED_CONTROLS]);5414 }5415 private function fillNameTable($container,$controls)5416 {5417 foreach($controls as $control)5418 {5419 if($control instanceof TControl)5420 {5421 if($control->_id!=='')5422 {5423 if(isset($container->_rf[self::RF_NAMED_CONTROLS][$control->_id]))5424 throw new TInvalidDataValueException('control_id_nonunique',get_class($control),$control->_id);5425 else5426 $container->_rf[self::RF_NAMED_CONTROLS][$control->_id]=$control;5427 }5428 if(!($control instanceof INamingContainer) && $control->getHasControls())5429 $this->fillNameTable($container,$control->_rf[self::RF_CONTROLS]);5430 }5431 }5432 }5433}5434class TControlCollection extends TList5435{5436 private $_o;5437 public function __construct(TControl $owner,$readOnly=false)5438 {5439 $this->_o=$owner;5440 parent::__construct(null,$readOnly);5441 }5442 protected function getOwner()5443 {5444 return $this->_o;5445 }5446 public function insertAt($index,$item)5447 {5448 if($item instanceof TControl)5449 {5450 parent::insertAt($index,$item);5451 $this->_o->addedControl($item);5452 }5453 else if(is_string($item) || ($item instanceof IRenderable))5454 parent::insertAt($index,$item);5455 else5456 throw new TInvalidDataTypeException('controlcollection_control_required');5457 }5458 public function removeAt($index)5459 {5460 $item=parent::removeAt($index);5461 if($item instanceof TControl)5462 $this->_o->removedControl($item);5463 return $item;5464 }5465 public function clear()5466 {5467 parent::clear();5468 if($this->_o instanceof INamingContainer)5469 $this->_o->clearNamingContainer();5470 }5471}5472class TEmptyControlCollection extends TControlCollection5473{5474 public function __construct(TControl $owner)5475 {5476 parent::__construct($owner,true);5477 }5478 public function insertAt($index,$item)5479 {5480 if(!is_string($item)) parent::insertAt($index,$item); }5481}5482interface INamingContainer5483{5484}5485interface IPostBackEventHandler5486{5487 public function raisePostBackEvent($param);5488}5489interface IPostBackDataHandler5490{5491 public function loadPostData($key,$values);5492 public function raisePostDataChangedEvent();5493 public function getDataChanged();5494}5495interface IValidator5496{5497 public function validate();5498 public function getIsValid();5499 public function setIsValid($value);5500 public function getErrorMessage();5501 public function setErrorMessage($value);5502}5503interface IValidatable5504{5505 public function getValidationPropertyValue();5506 public function getIsValid();5507 public function setIsValid($value);5508}5509interface IBroadcastEventReceiver5510{5511 public function broadcastEventReceived($sender,$param);5512}5513interface ITheme5514{5515 public function applySkin($control);5516}5517interface ITemplate5518{5519 public function instantiateIn($parent);5520}5521interface IButtonControl5522{5523 public function getText();5524 public function setText($value);5525 public function getCausesValidation();5526 public function setCausesValidation($value);5527 public function getCommandName();5528 public function setCommandName($value);5529 public function getCommandParameter();5530 public function setCommandParameter($value);5531 public function getValidationGroup();5532 public function setValidationGroup($value);5533 public function onClick($param);5534 public function onCommand($param);5535 public function setIsDefaultButton($value);5536 public function getIsDefaultButton();5537}5538interface ISurroundable5539{5540 public function getSurroundingTag();5541 public function getSurroundingTagID();5542}5543class TBroadcastEventParameter extends TEventParameter5544{5545 private $_name;5546 private $_param;5547 public function __construct($name='',$parameter=null)5548 {5549 $this->_name=$name;5550 $this->_param=$parameter;5551 }5552 public function getName()5553 {5554 return $this->_name;5555 }5556 public function setName($value)5557 {5558 $this->_name=$value;5559 }5560 public function getParameter()5561 {5562 return $this->_param;5563 }5564 public function setParameter($value)5565 {5566 $this->_param=$value;5567 }5568}5569class TCommandEventParameter extends TEventParameter5570{5571 private $_name;5572 private $_param;5573 public function __construct($name='',$parameter='')5574 {5575 $this->_name=$name;5576 $this->_param=$parameter;5577 }5578 public function getCommandName()5579 {5580 return $this->_name;5581 }5582 public function getCommandParameter()5583 {5584 return $this->_param;5585 }5586}5587class TCompositeLiteral extends TComponent implements IRenderable, IBindable5588{5589 const TYPE_EXPRESSION=0;5590 const TYPE_STATEMENTS=1;5591 const TYPE_DATABINDING=2;5592 private $_container=null;5593 private $_items=array();5594 private $_expressions=array();5595 private $_statements=array();5596 private $_bindings=array();5597 public function __construct($items)5598 {5599 $this->_items=array();5600 $this->_expressions=array();5601 $this->_statements=array();5602 foreach($items as $id=>$item)5603 {5604 if(is_array($item))5605 {5606 if($item[0]===self::TYPE_EXPRESSION)5607 $this->_expressions[$id]=$item[1];5608 else if($item[0]===self::TYPE_STATEMENTS)5609 $this->_statements[$id]=$item[1];5610 else if($item[0]===self::TYPE_DATABINDING)5611 $this->_bindings[$id]=$item[1];5612 $this->_items[$id]='';5613 }5614 else5615 $this->_items[$id]=$item;5616 }5617 }5618 public function getContainer()5619 {5620 return $this->_container;5621 }5622 public function setContainer(TComponent $value)5623 {5624 $this->_container=$value;5625 }5626 public function evaluateDynamicContent()5627 {5628 $context=$this->_container===null?$this:$this->_container;5629 foreach($this->_expressions as $id=>$expression)5630 $this->_items[$id]=$context->evaluateExpression($expression);5631 foreach($this->_statements as $id=>$statement)5632 $this->_items[$id]=$context->evaluateStatements($statement);5633 }5634 public function dataBind()5635 {5636 $context=$this->_container===null?$this:$this->_container;5637 foreach($this->_bindings as $id=>$binding)5638 $this->_items[$id]=$context->evaluateExpression($binding);5639 }5640 public function render($writer)5641 {5642 $writer->write(implode('',$this->_items));5643 }5644}5645class TFont extends TComponent5646{5647 const IS_BOLD=0x01;5648 const IS_ITALIC=0x02;5649 const IS_OVERLINE=0x04;5650 const IS_STRIKEOUT=0x08;5651 const IS_UNDERLINE=0x10;5652 const IS_SET_BOLD=0x01000;5653 const IS_SET_ITALIC=0x02000;5654 const IS_SET_OVERLINE=0x04000;5655 const IS_SET_STRIKEOUT=0x08000;5656 const IS_SET_UNDERLINE=0x10000;5657 const IS_SET_SIZE=0x20000;5658 const IS_SET_NAME=0x40000;5659 private $_flags=0;5660 private $_name='';5661 private $_size='';5662 protected function _getZappableSleepProps(&$exprops)5663 {5664 parent::_getZappableSleepProps($exprops);5665 if ($this->_flags===0)5666 $exprops[] = "\0TFont\0_flags";5667 if ($this->_name==='')5668 $exprops[] = "\0TFont\0_name";5669 if ($this->_size==='')5670 $exprops[] = "\0TFont\0_size";5671 }5672 public function getBold()5673 {5674 return ($this->_flags & self::IS_BOLD)!==0;5675 }5676 public function setBold($value)5677 {5678 $this->_flags |= self::IS_SET_BOLD;5679 if(TPropertyValue::ensureBoolean($value))5680 $this->_flags |= self::IS_BOLD;5681 else5682 $this->_flags &= ~self::IS_BOLD;5683 }5684 public function getItalic()5685 {5686 return ($this->_flags & self::IS_ITALIC)!==0;5687 }5688 public function setItalic($value)5689 {5690 $this->_flags |= self::IS_SET_ITALIC;5691 if(TPropertyValue::ensureBoolean($value))5692 $this->_flags |= self::IS_ITALIC;5693 else5694 $this->_flags &= ~self::IS_ITALIC;5695 }5696 public function getOverline()5697 {5698 return ($this->_flags & self::IS_OVERLINE)!==0;5699 }5700 public function setOverline($value)5701 {5702 $this->_flags |= self::IS_SET_OVERLINE;5703 if(TPropertyValue::ensureBoolean($value))5704 $this->_flags |= self::IS_OVERLINE;5705 else5706 $this->_flags &= ~self::IS_OVERLINE;5707 }5708 public function getSize()5709 {5710 return $this->_size;5711 }5712 public function setSize($value)5713 {5714 $this->_flags |= self::IS_SET_SIZE;5715 $this->_size=$value;5716 }5717 public function getStrikeout()5718 {5719 return ($this->_flags & self::IS_STRIKEOUT)!==0;5720 }5721 public function setStrikeout($value)5722 {5723 $this->_flags |= self::IS_SET_STRIKEOUT;5724 if(TPropertyValue::ensureBoolean($value))5725 $this->_flags |= self::IS_STRIKEOUT;5726 else5727 $this->_flags &= ~self::IS_STRIKEOUT;5728 }5729 public function getUnderline()5730 {5731 return ($this->_flags & self::IS_UNDERLINE)!==0;5732 }5733 public function setUnderline($value)5734 {5735 $this->_flags |= self::IS_SET_UNDERLINE;5736 if(TPropertyValue::ensureBoolean($value))5737 $this->_flags |= self::IS_UNDERLINE;5738 else5739 $this->_flags &= ~self::IS_UNDERLINE;5740 }5741 public function getName()5742 {5743 return $this->_name;5744 }5745 public function setName($value)5746 {5747 $this->_flags |= self::IS_SET_NAME;5748 $this->_name=$value;5749 }5750 public function getIsEmpty()5751 {5752 return !$this->_flags;5753 }5754 public function reset()5755 {5756 $this->_flags=0;5757 $this->_name='';5758 $this->_size='';5759 }5760 public function mergeWith($font)5761 {5762 if($font===null || $font->_flags===0)5763 return;5764 if(!($this->_flags & self::IS_SET_BOLD) && ($font->_flags & self::IS_SET_BOLD))5765 $this->setBold($font->getBold());5766 if(!($this->_flags & self::IS_SET_ITALIC) && ($font->_flags & self::IS_SET_ITALIC))5767 $this->setItalic($font->getItalic());5768 if(!($this->_flags & self::IS_SET_OVERLINE) && ($font->_flags & self::IS_SET_OVERLINE))5769 $this->setOverline($font->getOverline());5770 if(!($this->_flags & self::IS_SET_STRIKEOUT) && ($font->_flags & self::IS_SET_STRIKEOUT))5771 $this->setStrikeout($font->getStrikeout());5772 if(!($this->_flags & self::IS_SET_UNDERLINE) && ($font->_flags & self::IS_SET_UNDERLINE))5773 $this->setUnderline($font->getUnderline());5774 if(!($this->_flags & self::IS_SET_SIZE) && ($font->_flags & self::IS_SET_SIZE))5775 $this->setSize($font->getSize());5776 if(!($this->_flags & self::IS_SET_NAME) && ($font->_flags & self::IS_SET_NAME))5777 $this->setName($font->getName());5778 }5779 public function copyFrom($font)5780 {5781 if($font===null || $font->_flags===0)5782 return;5783 if($font->_flags & self::IS_SET_BOLD)5784 $this->setBold($font->getBold());5785 if($font->_flags & self::IS_SET_ITALIC)5786 $this->setItalic($font->getItalic());5787 if($font->_flags & self::IS_SET_OVERLINE)5788 $this->setOverline($font->getOverline());5789 if($font->_flags & self::IS_SET_STRIKEOUT)5790 $this->setStrikeout($font->getStrikeout());5791 if($font->_flags & self::IS_SET_UNDERLINE)5792 $this->setUnderline($font->getUnderline());5793 if($font->_flags & self::IS_SET_SIZE)5794 $this->setSize($font->getSize());5795 if($font->_flags & self::IS_SET_NAME)5796 $this->setName($font->getName());5797 }5798 public function toString()5799 {5800 if($this->_flags===0)5801 return '';5802 $str='';5803 if($this->_flags & self::IS_SET_BOLD)5804 $str.='font-weight:'.(($this->_flags & self::IS_BOLD)?'bold;':'normal;');5805 if($this->_flags & self::IS_SET_ITALIC)5806 $str.='font-style:'.(($this->_flags & self::IS_ITALIC)?'italic;':'normal;');5807 $textDec='';5808 if($this->_flags & self::IS_UNDERLINE)5809 $textDec.='underline';5810 if($this->_flags & self::IS_OVERLINE)5811 $textDec.=' overline';5812 if($this->_flags & self::IS_STRIKEOUT)5813 $textDec.=' line-through';5814 $textDec=ltrim($textDec);5815 if($textDec!=='')5816 $str.='text-decoration:'.$textDec.';';5817 if($this->_size!=='')5818 $str.='font-size:'.$this->_size.';';5819 if($this->_name!=='')5820 $str.='font-family:'.$this->_name.';';5821 return $str;5822 }5823 public function addAttributesToRender($writer)5824 {5825 if($this->_flags===0)5826 return;5827 if($this->_flags & self::IS_SET_BOLD)5828 $writer->addStyleAttribute('font-weight',(($this->_flags & self::IS_BOLD)?'bold':'normal'));5829 if($this->_flags & self::IS_SET_ITALIC)5830 $writer->addStyleAttribute('font-style',(($this->_flags & self::IS_ITALIC)?'italic':'normal'));5831 $textDec='';5832 if($this->_flags & self::IS_UNDERLINE)5833 $textDec.='underline';5834 if($this->_flags & self::IS_OVERLINE)5835 $textDec.=' overline';5836 if($this->_flags & self::IS_STRIKEOUT)5837 $textDec.=' line-through';5838 $textDec=ltrim($textDec);5839 if($textDec!=='')5840 $writer->addStyleAttribute('text-decoration',$textDec);5841 if($this->_size!=='')5842 $writer->addStyleAttribute('font-size',$this->_size);5843 if($this->_name!=='')5844 $writer->addStyleAttribute('font-family',$this->_name);5845 }5846}5847class TStyle extends TComponent5848{5849 private $_fields=array();5850 private $_font=null;5851 private $_class=null;5852 private $_customStyle=null;5853 private $_displayStyle='Fixed';5854 protected function _getZappableSleepProps(&$exprops)5855 {5856 parent::_getZappableSleepProps($exprops);5857 if ($this->_fields===array())5858 $exprops[] = "\0TStyle\0_fields";5859 if($this->_font===null)5860 $exprops[] = "\0TStyle\0_font";5861 if($this->_class===null)5862 $exprops[] = "\0TStyle\0_class";5863 if ($this->_customStyle===null)5864 $exprops[] = "\0TStyle\0_customStyle";5865 if ($this->_displayStyle==='Fixed')5866 $exprops[] = "\0TStyle\0_displayStyle";5867 }5868 public function __construct($style=null)5869 {5870 parent::__construct();5871 if($style!==null)5872 $this->copyFrom($style);5873 }5874 public function __clone()5875 {5876 if($this->_font!==null)5877 $this->_font = clone($this->_font);5878 }5879 public function getBackColor()5880 {5881 return isset($this->_fields['background-color'])?$this->_fields['background-color']:'';5882 }5883 public function setBackColor($value)5884 {5885 if(trim($value)==='')5886 unset($this->_fields['background-color']);5887 else5888 $this->_fields['background-color']=$value;5889 }5890 public function getBorderColor()5891 {5892 return isset($this->_fields['border-color'])?$this->_fields['border-color']:'';5893 }5894 public function setBorderColor($value)5895 {5896 if(trim($value)==='')5897 unset($this->_fields['border-color']);5898 else5899 $this->_fields['border-color']=$value;5900 }5901 public function getBorderStyle()5902 {5903 return isset($this->_fields['border-style'])?$this->_fields['border-style']:'';5904 }5905 public function setBorderStyle($value)5906 {5907 if(trim($value)==='')5908 unset($this->_fields['border-style']);5909 else5910 $this->_fields['border-style']=$value;5911 }5912 public function getBorderWidth()5913 {5914 return isset($this->_fields['border-width'])?$this->_fields['border-width']:'';5915 }5916 public function setBorderWidth($value)5917 {5918 if(trim($value)==='')5919 unset($this->_fields['border-width']);5920 else5921 $this->_fields['border-width']=$value;5922 }5923 public function getCssClass()5924 {5925 return $this->_class===null?'':$this->_class;5926 }5927 public function hasCssClass()5928 {5929 return ($this->_class!==null);5930 }5931 public function setCssClass($value)5932 {5933 $this->_class=$value;5934 }5935 public function getFont()5936 {5937 if($this->_font===null)5938 $this->_font=new TFont;5939 return $this->_font;5940 }5941 public function hasFont()5942 {5943 return $this->_font !== null;5944 }5945 public function setDisplayStyle($value)5946 {5947 $this->_displayStyle = TPropertyValue::ensureEnum($value, 'TDisplayStyle');5948 switch($this->_displayStyle)5949 {5950 case TDisplayStyle::None:5951 $this->_fields['display'] = 'none';5952 break;5953 case TDisplayStyle::Dynamic:5954 $this->_fields['display'] = ''; break;5955 case TDisplayStyle::Fixed:5956 $this->_fields['visibility'] = 'visible';5957 break;5958 case TDisplayStyle::Hidden:5959 $this->_fields['visibility'] = 'hidden';5960 break;5961 }5962 }5963 public function getDisplayStyle()5964 {5965 return $this->_displayStyle;5966 }5967 public function getForeColor()5968 {5969 return isset($this->_fields['color'])?$this->_fields['color']:'';5970 }5971 public function setForeColor($value)5972 {5973 if(trim($value)==='')5974 unset($this->_fields['color']);5975 else5976 $this->_fields['color']=$value;5977 }5978 public function getHeight()5979 {5980 return isset($this->_fields['height'])?$this->_fields['height']:'';5981 }5982 public function setHeight($value)5983 {5984 if(trim($value)==='')5985 unset($this->_fields['height']);5986 else5987 $this->_fields['height']=$value;5988 }5989 public function getCustomStyle()5990 {5991 return $this->_customStyle===null?'':$this->_customStyle;5992 }5993 public function setCustomStyle($value)5994 {5995 $this->_customStyle=$value;5996 }5997 public function getStyleField($name)5998 {5999 return isset($this->_fields[$name])?$this->_fields[$name]:'';6000 }6001 public function setStyleField($name,$value)6002 {6003 $this->_fields[$name]=$value;6004 }6005 public function clearStyleField($name)6006 {6007 unset($this->_fields[$name]);6008 }6009 public function hasStyleField($name)6010 {6011 return isset($this->_fields[$name]);6012 }6013 public function getWidth()6014 {6015 return isset($this->_fields['width'])?$this->_fields['width']:'';6016 }6017 public function setWidth($value)6018 {6019 $this->_fields['width']=$value;6020 }6021 public function reset()6022 {6023 $this->_fields=array();6024 $this->_font=null;6025 $this->_class=null;6026 $this->_customStyle=null;6027 }6028 public function copyFrom($style)6029 {6030 if($style instanceof TStyle)6031 {6032 $this->_fields=array_merge($this->_fields,$style->_fields);6033 if($style->_class!==null)6034 $this->_class=$style->_class;6035 if($style->_customStyle!==null)6036 $this->_customStyle=$style->_customStyle;6037 if($style->_font!==null)6038 $this->getFont()->copyFrom($style->_font);6039 }6040 }6041 public function mergeWith($style)6042 {6043 if($style instanceof TStyle)6044 {6045 $this->_fields=array_merge($style->_fields,$this->_fields);6046 if($this->_class===null)6047 $this->_class=$style->_class;6048 if($this->_customStyle===null)6049 $this->_customStyle=$style->_customStyle;6050 if($style->_font!==null)6051 $this->getFont()->mergeWith($style->_font);6052 }6053 }6054 public function addAttributesToRender($writer)6055 {6056 if($this->_customStyle!==null)6057 {6058 foreach(explode(';',$this->_customStyle) as $style)6059 {6060 $arr=explode(':',$style,2);6061 if(isset($arr[1]) && trim($arr[0])!=='')6062 $writer->addStyleAttribute(trim($arr[0]),trim($arr[1]));6063 }6064 }6065 $writer->addStyleAttributes($this->_fields);6066 if($this->_font!==null)6067 $this->_font->addAttributesToRender($writer);6068 if($this->_class!==null)6069 $writer->addAttribute('class',$this->_class);6070 }6071 public function getStyleFields()6072 {6073 return $this->_fields;6074 }6075}6076class TDisplayStyle extends TEnumerable6077{6078 const None='None';6079 const Dynamic='Dynamic';6080 const Fixed='Fixed';6081 const Hidden='Hidden';6082}6083class TTableStyle extends TStyle6084{6085 private $_backImageUrl=null;6086 private $_horizontalAlign=null;6087 private $_cellPadding=null;6088 private $_cellSpacing=null;6089 private $_gridLines=null;6090 private $_borderCollapse=null;6091 protected function _getZappableSleepProps(&$exprops)6092 {6093 parent::_getZappableSleepProps($exprops);6094 if ($this->_backImageUrl===null)6095 $exprops[] = "\0TTableStyle\0_backImageUrl";6096 if ($this->_horizontalAlign===null)6097 $exprops[] = "\0TTableStyle\0_horizontalAlign";6098 if ($this->_cellPadding===null)6099 $exprops[] = "\0TTableStyle\0_cellPadding";6100 if ($this->_cellSpacing===null)6101 $exprops[] = "\0TTableStyle\0_cellSpacing";6102 if ($this->_gridLines===null)6103 $exprops[] = "\0TTableStyle\0_gridLines";6104 if ($this->_borderCollapse===null)6105 $exprops[] = "\0TTableStyle\0_borderCollapse";6106 }6107 public function reset()6108 {6109 $this->_backImageUrl=null;6110 $this->_horizontalAlign=null;6111 $this->_cellPadding=null;6112 $this->_cellSpacing=null;6113 $this->_gridLines=null;6114 $this->_borderCollapse=null;6115 }6116 public function copyFrom($style)6117 {6118 parent::copyFrom($style);6119 if($style instanceof TTableStyle)6120 {6121 if($style->_backImageUrl!==null)6122 $this->_backImageUrl=$style->_backImageUrl;6123 if($style->_horizontalAlign!==null)6124 $this->_horizontalAlign=$style->_horizontalAlign;6125 if($style->_cellPadding!==null)6126 $this->_cellPadding=$style->_cellPadding;6127 if($style->_cellSpacing!==null)6128 $this->_cellSpacing=$style->_cellSpacing;6129 if($style->_gridLines!==null)6130 $this->_gridLines=$style->_gridLines;6131 if($style->_borderCollapse!==null)6132 $this->_borderCollapse=$style->_borderCollapse;6133 }6134 }6135 public function mergeWith($style)6136 {6137 parent::mergeWith($style);6138 if($style instanceof TTableStyle)6139 {6140 if($this->_backImageUrl===null && $style->_backImageUrl!==null)6141 $this->_backImageUrl=$style->_backImageUrl;6142 if($this->_horizontalAlign===null && $style->_horizontalAlign!==null)6143 $this->_horizontalAlign=$style->_horizontalAlign;6144 if($this->_cellPadding===null && $style->_cellPadding!==null)6145 $this->_cellPadding=$style->_cellPadding;6146 if($this->_cellSpacing===null && $style->_cellSpacing!==null)6147 $this->_cellSpacing=$style->_cellSpacing;6148 if($this->_gridLines===null && $style->_gridLines!==null)6149 $this->_gridLines=$style->_gridLines;6150 if($this->_borderCollapse===null && $style->_borderCollapse!==null)6151 $this->_borderCollapse=$style->_borderCollapse;6152 }6153 }6154 public function addAttributesToRender($writer)6155 {6156 if(($url=trim($this->getBackImageUrl()))!=='')6157 $writer->addStyleAttribute('background-image','url('.$url.')');6158 if(($horizontalAlign=$this->getHorizontalAlign())!==THorizontalAlign::NotSet)6159 $writer->addStyleAttribute('text-align',strtolower($horizontalAlign));6160 if(($cellPadding=$this->getCellPadding())>=0)6161 $writer->addAttribute('cellpadding',"$cellPadding");6162 if(($cellSpacing=$this->getCellSpacing())>=0)6163 $writer->addAttribute('cellspacing',"$cellSpacing");6164 if($this->getBorderCollapse())6165 $writer->addStyleAttribute('border-collapse','collapse');6166 switch($this->getGridLines())6167 {6168 case TTableGridLines::Horizontal : $writer->addAttribute('rules','rows'); break;6169 case TTableGridLines::Vertical : $writer->addAttribute('rules','cols'); break;6170 case TTableGridLines::Both : $writer->addAttribute('rules','all'); break;6171 }6172 parent::addAttributesToRender($writer);6173 }6174 public function getBackImageUrl()6175 {6176 return $this->_backImageUrl===null?'':$this->_backImageUrl;6177 }6178 public function setBackImageUrl($value)6179 {6180 $this->_backImageUrl=$value;6181 }6182 public function getHorizontalAlign()6183 {6184 return $this->_horizontalAlign===null?THorizontalAlign::NotSet:$this->_horizontalAlign;6185 }6186 public function setHorizontalAlign($value)6187 {6188 $this->_horizontalAlign=TPropertyValue::ensureEnum($value,'THorizontalAlign');6189 }6190 public function getCellPadding()6191 {6192 return $this->_cellPadding===null?-1:$this->_cellPadding;6193 }6194 public function setCellPadding($value)6195 {6196 if(($this->_cellPadding=TPropertyValue::ensureInteger($value))<-1)6197 throw new TInvalidDataValueException('tablestyle_cellpadding_invalid');6198 }6199 public function getCellSpacing()6200 {6201 return $this->_cellSpacing===null?-1:$this->_cellSpacing;6202 }6203 public function setCellSpacing($value)6204 {6205 if(($this->_cellSpacing=TPropertyValue::ensureInteger($value))<-1)6206 throw new TInvalidDataValueException('tablestyle_cellspacing_invalid');6207 }6208 public function getGridLines()6209 {6210 return $this->_gridLines===null?TTableGridLines::None:$this->_gridLines;6211 }6212 public function setGridLines($value)6213 {6214 $this->_gridLines=TPropertyValue::ensureEnum($value,'TTableGridLines');6215 }6216 public function getBorderCollapse()6217 {6218 return $this->_borderCollapse===null?false:$this->_borderCollapse;6219 }6220 public function setBorderCollapse($value)6221 {6222 $this->_borderCollapse=TPropertyValue::ensureBoolean($value);6223 }6224}6225class TTableItemStyle extends TStyle6226{6227 private $_horizontalAlign=null;6228 private $_verticalAlign=null;6229 private $_wrap=null;6230 protected function _getZappableSleepProps(&$exprops)6231 {6232 parent::_getZappableSleepProps($exprops);6233 if ($this->_horizontalAlign===null)6234 $exprops[] = "\0TTableItemStyle\0_horizontalAlign";6235 if ($this->_verticalAlign===null)6236 $exprops[] = "\0TTableItemStyle\0_verticalAlign";6237 if ($this->_wrap===null)6238 $exprops[] = "\0TTableItemStyle\0_wrap";6239 }6240 public function reset()6241 {6242 parent::reset();6243 $this->_verticalAlign=null;6244 $this->_horizontalAlign=null;6245 $this->_wrap=null;6246 }6247 public function copyFrom($style)6248 {6249 parent::copyFrom($style);6250 if($style instanceof TTableItemStyle)6251 {6252 if($this->_verticalAlign===null && $style->_verticalAlign!==null)6253 $this->_verticalAlign=$style->_verticalAlign;6254 if($this->_horizontalAlign===null && $style->_horizontalAlign!==null)6255 $this->_horizontalAlign=$style->_horizontalAlign;6256 if($this->_wrap===null && $style->_wrap!==null)6257 $this->_wrap=$style->_wrap;6258 }6259 }6260 public function mergeWith($style)6261 {6262 parent::mergeWith($style);6263 if($style instanceof TTableItemStyle)6264 {6265 if($style->_verticalAlign!==null)6266 $this->_verticalAlign=$style->_verticalAlign;6267 if($style->_horizontalAlign!==null)6268 $this->_horizontalAlign=$style->_horizontalAlign;6269 if($style->_wrap!==null)6270 $this->_wrap=$style->_wrap;6271 }6272 }6273 public function addAttributesToRender($writer)6274 {6275 if(!$this->getWrap())6276 $writer->addStyleAttribute('white-space','nowrap');6277 if(($horizontalAlign=$this->getHorizontalAlign())!==THorizontalAlign::NotSet)6278 $writer->addAttribute('align',strtolower($horizontalAlign));6279 if(($verticalAlign=$this->getVerticalAlign())!==TVerticalAlign::NotSet)6280 $writer->addAttribute('valign',strtolower($verticalAlign));6281 parent::addAttributesToRender($writer);6282 }6283 public function getHorizontalAlign()6284 {6285 return $this->_horizontalAlign===null?THorizontalAlign::NotSet:$this->_horizontalAlign;6286 }6287 public function setHorizontalAlign($value)6288 {6289 $this->_horizontalAlign=TPropertyValue::ensureEnum($value,'THorizontalAlign');6290 }6291 public function getVerticalAlign()6292 {6293 return $this->_verticalAlign===null?TVerticalAlign::NotSet:$this->_verticalAlign;6294 }6295 public function setVerticalAlign($value)6296 {6297 $this->_verticalAlign=TPropertyValue::ensureEnum($value,'TVerticalAlign');6298 }6299 public function getWrap()6300 {6301 return $this->_wrap===null?true:$this->_wrap;6302 }6303 public function setWrap($value)6304 {6305 $this->_wrap=TPropertyValue::ensureBoolean($value);6306 }6307}6308class THorizontalAlign extends TEnumerable6309{6310 const NotSet='NotSet';6311 const Left='Left';6312 const Right='Right';6313 const Center='Center';6314 const Justify='Justify';6315}6316class TVerticalAlign extends TEnumerable6317{6318 const NotSet='NotSet';6319 const Top='Top';6320 const Bottom='Bottom';6321 const Middle='Middle';6322}6323class TTableGridLines extends TEnumerable6324{6325 const None='None';6326 const Horizontal='Horizontal';6327 const Vertical='Vertical';6328 const Both='Both';6329}6330class TWebControlAdapter extends TControlAdapter6331{6332 public function render($writer)6333 {6334 $this->renderBeginTag($writer);6335 $this->renderContents($writer);6336 $this->renderEndTag($writer);6337 }6338 public function renderBeginTag($writer)6339 {6340 $this->getControl()->renderBeginTag($writer);6341 }6342 public function renderContents($writer)6343 {6344 $this->getControl()->renderContents($writer);6345 }6346 public function renderEndTag($writer)6347 {6348 $this->getControl()->renderEndTag($writer);6349 }6350}6351class TWebControlDecorator extends TComponent {6352 private $_internalonly;6353 private $_usestate = false;6354 private $_control;6355 private $_outercontrol;6356 private $_addedTemplateDecoration=false;6357 private $_pretagtext = '';6358 private $_precontentstext = '';6359 private $_postcontentstext = '';6360 private $_posttagtext = '';6361 private $_pretagtemplate;6362 private $_precontentstemplate;6363 private $_postcontentstemplate;6364 private $_posttagtemplate;6365 public function __construct($control, $onlyinternal = false) {6366 $this->_control = $control;6367 $this->_internalonly = $onlyinternal;6368 }6369 public function getUseState()6370 {6371 return $this->_usestate;6372 }6373 public function setUseState($value)6374 {6375 $this->_usestate = TPropertyValue::ensureBoolean($value);6376 }6377 public function getPreTagText() {6378 return $this->_pretagtext;6379 }6380 public function setPreTagText($value) {6381 if(!$this->_internalonly && !$this->_control->getIsSkinApplied())6382 $this->_pretagtext = TPropertyValue::ensureString($value);6383 }6384 public function getPreContentsText() {6385 return $this->_precontentstext;6386 }6387 public function setPreContentsText($value) {6388 if(!$this->_control->getIsSkinApplied())6389 $this->_precontentstext = TPropertyValue::ensureString($value);6390 }6391 public function getPostContentsText() {6392 return $this->_postcontentstext;6393 }6394 public function setPostContentsText($value) {6395 if(!$this->_control->getIsSkinApplied())6396 $this->_postcontentstext = TPropertyValue::ensureString($value);6397 }6398 public function getPostTagText() {6399 return $this->_posttagtext;6400 }6401 public function setPostTagText($value) {6402 if(!$this->_internalonly && !$this->_control->getIsSkinApplied())6403 $this->_posttagtext = TPropertyValue::ensureString($value);6404 }6405 public function getPreTagTemplate() {6406 return $this->_pretagtemplate;6407 }6408 public function setPreTagTemplate($value) {6409 if(!$this->_internalonly && !$this->_control->getIsSkinApplied())6410 $this->_pretagtemplate = $value;6411 }6412 public function getPreContentsTemplate() {6413 return $this->_precontentstemplate;6414 }6415 public function setPreContentsTemplate($value) {6416 if(!$this->_control->getIsSkinApplied())6417 $this->_precontentstemplate = $value;6418 }6419 public function getPostContentsTemplate() {6420 return $this->_postcontentstemplate;6421 }6422 public function setPostContentsTemplate($value) {6423 if(!$this->_control->getIsSkinApplied())6424 $this->_postcontentstemplate = $value;6425 }6426 public function getPostTagTemplate() {6427 return $this->_posttagtemplate;6428 }6429 public function setPostTagTemplate($value) {6430 if(!$this->_internalonly && !$this->_control->getIsSkinApplied())6431 $this->_posttagtemplate = $value;6432 }6433 public function instantiate($outercontrol = null) {6434 if($this->getPreTagTemplate() || $this->getPreContentsTemplate() ||6435 $this->getPostContentsTemplate() || $this->getPostTagTemplate()) {6436 $this->_outercontrol = $outercontrol;6437 if($this->getUseState())6438 $this->ensureTemplateDecoration();6439 else6440 $this->_control->getPage()->onSaveStateComplete[] = array($this, 'ensureTemplateDecoration');6441 }6442 }6443 public function ensureTemplateDecoration($sender=null, $param=null) {6444 $control = $this->_control;6445 $outercontrol = $this->_outercontrol;6446 if($outercontrol === null)6447 $outercontrol = $control;6448 if($this->_addedTemplateDecoration)6449 return $this->_addedTemplateDecoration;6450 $this->_addedTemplateDecoration = true;6451 if($this->getPreContentsTemplate())6452 {6453 $precontents = Prado::createComponent('TCompositeControl');6454 $this->getPreContentsTemplate()->instantiateIn($precontents);6455 $control->getControls()->insertAt(0, $precontents);6456 }6457 if($this->getPostContentsTemplate())6458 {6459 $postcontents = Prado::createComponent('TCompositeControl');6460 $this->getPostContentsTemplate()->instantiateIn($postcontents);6461 $control->getControls()->add($postcontents);6462 }6463 if(!$outercontrol->getParent())6464 return $this->_addedTemplateDecoration;6465 if($this->getPreTagTemplate())6466 {6467 $pretag = Prado::createComponent('TCompositeControl');6468 $this->getPreTagTemplate()->instantiateIn($pretag);6469 $outercontrol->getParent()->getControls()->insertBefore($outercontrol, $pretag);6470 }6471 if($this->getPostTagTemplate())6472 {6473 $posttag = Prado::createComponent('TCompositeControl');6474 $this->getPostTagTemplate()->instantiateIn($posttag);6475 $outercontrol->getParent()->getControls()->insertAfter($outercontrol, $posttag);6476 }6477 return true;6478 }6479 public function renderPreTagText($writer) {6480 $writer->write($this->getPreTagText());6481 }6482 public function renderPreContentsText($writer) {6483 $writer->write($this->getPreContentsText());6484 }6485 public function renderPostContentsText($writer) {6486 $writer->write($this->getPostContentsText());6487 }6488 public function renderPostTagText($writer) {6489 $writer->write($this->getPostTagText());6490 }6491}6492class TWebControl extends TControl implements IStyleable6493{6494 private $_ensureid=false;6495 protected $_decorator;6496 public function setEnsureId($value)6497 {6498 $this->_ensureid |= TPropertyValue::ensureBoolean($value);6499 }6500 public function getEnsureId()6501 {6502 return $this->_ensureid;6503 }6504 public function getDecorator($create=true)6505 {6506 if($create && !$this->_decorator)6507 $this->_decorator = Prado::createComponent('TWebControlDecorator', $this);6508 return $this->_decorator;6509 }6510 public function copyBaseAttributes(TWebControl $control)6511 {6512 $this->setAccessKey($control->getAccessKey());6513 $this->setToolTip($control->getToolTip());6514 $this->setTabIndex($control->getTabIndex());6515 if(!$control->getEnabled())6516 $this->setEnabled(false);6517 if($control->getHasAttributes())6518 $this->getAttributes()->copyFrom($control->getAttributes());6519 }6520 public function getAccessKey()6521 {6522 return $this->getViewState('AccessKey','');6523 }6524 public function setAccessKey($value)6525 {6526 if(strlen($value)>1)6527 throw new TInvalidDataValueException('webcontrol_accesskey_invalid',get_class($this),$value);6528 $this->setViewState('AccessKey',$value,'');6529 }6530 public function getBackColor()6531 {6532 if($style=$this->getViewState('Style',null))6533 return $style->getBackColor();6534 else6535 return '';6536 }6537 public function setBackColor($value)6538 {6539 $this->getStyle()->setBackColor($value);6540 }6541 public function getBorderColor()6542 {6543 if($style=$this->getViewState('Style',null))6544 return $style->getBorderColor();6545 else6546 return '';6547 }6548 public function setBorderColor($value)6549 {6550 $this->getStyle()->setBorderColor($value);6551 }6552 public function getBorderStyle()6553 {6554 if($style=$this->getViewState('Style',null))6555 return $style->getBorderStyle();6556 else6557 return '';6558 }6559 public function setBorderStyle($value)6560 {6561 $this->getStyle()->setBorderStyle($value);6562 }6563 public function getBorderWidth()6564 {6565 if($style=$this->getViewState('Style',null))6566 return $style->getBorderWidth();6567 else6568 return '';6569 }6570 public function setBorderWidth($value)6571 {6572 $this->getStyle()->setBorderWidth($value);6573 }6574 public function getFont()6575 {6576 return $this->getStyle()->getFont();6577 }6578 public function getForeColor()6579 {6580 if($style=$this->getViewState('Style',null))6581 return $style->getForeColor();6582 else6583 return '';6584 }6585 public function setForeColor($value)6586 {6587 $this->getStyle()->setForeColor($value);6588 }6589 public function getHeight()6590 {6591 if($style=$this->getViewState('Style',null))6592 return $style->getHeight();6593 else6594 return '';6595 }6596 public function setDisplay($value)6597 {6598 $this->getStyle()->setDisplayStyle($value);6599 }6600 public function getDisplay()6601 {6602 return $this->getStyle()->getDisplayStyle();6603 }6604 public function setCssClass($value)6605 {6606 $this->getStyle()->setCssClass($value);6607 }6608 public function getCssClass()6609 {6610 if($style=$this->getViewState('Style',null))6611 return $style->getCssClass();6612 else6613 return '';6614 }6615 public function setHeight($value)6616 {6617 $this->getStyle()->setHeight($value);6618 }6619 public function getHasStyle()6620 {6621 return $this->getViewState('Style',null)!==null;6622 }6623 protected function createStyle()6624 {6625 return new TStyle;6626 }6627 public function getStyle()6628 {6629 if($style=$this->getViewState('Style',null))6630 return $style;6631 else6632 {6633 $style=$this->createStyle();6634 $this->setViewState('Style',$style,null);6635 return $style;6636 }6637 }6638 public function setStyle($value)6639 {6640 if(is_string($value))6641 $this->getStyle()->setCustomStyle($value);6642 else6643 throw new TInvalidDataValueException('webcontrol_style_invalid',get_class($this));6644 }6645 public function clearStyle()6646 {6647 $this->clearViewState('Style');6648 }6649 public function getTabIndex()6650 {6651 return $this->getViewState('TabIndex',0);6652 }6653 public function setTabIndex($value)6654 {6655 $this->setViewState('TabIndex',TPropertyValue::ensureInteger($value),0);6656 }6657 protected function getTagName()6658 {6659 return 'span';6660 }6661 public function getToolTip()6662 {6663 return $this->getViewState('ToolTip','');6664 }6665 public function setToolTip($value)6666 {6667 $this->setViewState('ToolTip',$value,'');6668 }6669 public function getWidth()6670 {6671 if($style=$this->getViewState('Style',null))6672 return $style->getWidth();6673 else6674 return '';6675 }6676 public function setWidth($value)6677 {6678 $this->getStyle()->setWidth($value);6679 }6680 public function onPreRender($param) {6681 if($decorator = $this->getDecorator(false))6682 $decorator->instantiate();6683 parent::onPreRender($param);6684 }6685 protected function addAttributesToRender($writer)6686 {6687 if($this->getID()!=='' || $this->getEnsureId())6688 $writer->addAttribute('id',$this->getClientID());6689 if(($accessKey=$this->getAccessKey())!=='')6690 $writer->addAttribute('accesskey',$accessKey);6691 if(!$this->getEnabled())6692 $writer->addAttribute('disabled','disabled');6693 if(($tabIndex=$this->getTabIndex())>0)6694 $writer->addAttribute('tabindex',"$tabIndex");6695 if(($toolTip=$this->getToolTip())!=='')6696 $writer->addAttribute('title',$toolTip);6697 if($style=$this->getViewState('Style',null))6698 $style->addAttributesToRender($writer);6699 if($this->getHasAttributes())6700 {6701 foreach($this->getAttributes() as $name=>$value)6702 $writer->addAttribute($name,$value);6703 }6704 }6705 public function render($writer)6706 {6707 $this->renderBeginTag($writer);6708 $this->renderContents($writer);6709 $this->renderEndTag($writer);6710 }6711 public function renderBeginTag($writer)6712 {6713 if($decorator = $this->getDecorator(false)) {6714 $decorator->renderPreTagText($writer);6715 $this->addAttributesToRender($writer);6716 $writer->renderBeginTag($this->getTagName());6717 $decorator->renderPreContentsText($writer);6718 } else {6719 $this->addAttributesToRender($writer);6720 $writer->renderBeginTag($this->getTagName());6721 }6722 }6723 public function renderContents($writer)6724 {6725 parent::renderChildren($writer);6726 }6727 public function renderEndTag($writer)6728 {6729 if($decorator = $this->getDecorator(false)) {6730 $decorator->renderPostContentsText($writer);6731 $writer->renderEndTag();6732 $decorator->renderPostTagText($writer);6733 } else6734 $writer->renderEndTag($writer);6735 }6736}6737class TCompositeControl extends TControl implements INamingContainer6738{6739 protected function initRecursive($namingContainer=null)6740 {6741 $this->ensureChildControls();6742 parent::initRecursive($namingContainer);6743 }6744}6745class TTemplateControl extends TCompositeControl6746{6747 const EXT_TEMPLATE='.tpl';6748 private static $_template=array();6749 private $_localTemplate=null;6750 private $_master=null;6751 private $_masterClass='';6752 private $_contents=array();6753 private $_placeholders=array();6754 public function getTemplate()6755 {6756 if($this->_localTemplate===null)6757 {6758 $class=get_class($this);6759 if(!isset(self::$_template[$class]))6760 self::$_template[$class]=$this->loadTemplate();6761 return self::$_template[$class];6762 }6763 else6764 return $this->_localTemplate;6765 }6766 public function setTemplate($value)6767 {6768 $this->_localTemplate=$value;6769 }6770 public function getIsSourceTemplateControl()6771 {6772 if(($template=$this->getTemplate())!==null)6773 return $template->getIsSourceTemplate();6774 else6775 return false;6776 }6777 public function getTemplateDirectory()6778 {6779 if(($template=$this->getTemplate())!==null)6780 return $template->getContextPath();6781 else6782 return '';6783 }6784 protected function loadTemplate()6785 {6786 $template=$this->getService()->getTemplateManager()->getTemplateByClassName(get_class($this));6787 return $template;6788 }6789 public function createChildControls()6790 {6791 if($tpl=$this->getTemplate())6792 {6793 foreach($tpl->getDirective() as $name=>$value)6794 {6795 if(is_string($value))6796 $this->setSubProperty($name,$value);6797 else6798 throw new TConfigurationException('templatecontrol_directive_invalid',get_class($this),$name);6799 }6800 $tpl->instantiateIn($this);6801 }6802 }6803 public function registerContent($id,TContent $object)6804 {6805 if(isset($this->_contents[$id]))6806 throw new TConfigurationException('templatecontrol_contentid_duplicated',$id);6807 else6808 $this->_contents[$id]=$object;6809 }6810 public function registerContentPlaceHolder($id,TContentPlaceHolder $object)6811 {6812 if(isset($this->_placeholders[$id]))6813 throw new TConfigurationException('templatecontrol_placeholderid_duplicated',$id);6814 else6815 $this->_placeholders[$id]=$object;6816 }6817 public function getMasterClass()6818 {6819 return $this->_masterClass;6820 }6821 public function setMasterClass($value)6822 {6823 $this->_masterClass=$value;6824 }6825 public function getMaster()6826 {6827 return $this->_master;6828 }6829 public function injectContent($id,$content)6830 {6831 if(isset($this->_placeholders[$id]))6832 {6833 $placeholder=$this->_placeholders[$id];6834 $controls=$placeholder->getParent()->getControls();6835 $loc=$controls->remove($placeholder);6836 $controls->insertAt($loc,$content);6837 }6838 else6839 throw new TConfigurationException('templatecontrol_placeholder_inexistent',$id);6840 }6841 protected function initRecursive($namingContainer=null)6842 {6843 $this->ensureChildControls();6844 if($this->_masterClass!=='')6845 {6846 $master=Prado::createComponent($this->_masterClass);6847 if(!($master instanceof TTemplateControl))6848 throw new TInvalidDataValueException('templatecontrol_mastercontrol_invalid');6849 $this->_master=$master;6850 $this->getControls()->clear();6851 $this->getControls()->add($master);6852 $master->ensureChildControls();6853 foreach($this->_contents as $id=>$content)6854 $master->injectContent($id,$content);6855 }6856 else if(!empty($this->_contents))6857 throw new TConfigurationException('templatecontrol_mastercontrol_required',get_class($this));6858 parent::initRecursive($namingContainer);6859 }6860 public function tryToUpdateView($arObj, $throwExceptions = false)6861 {6862 $objAttrs = get_class_vars(get_class($arObj));6863 foreach (array_keys($objAttrs) as $key)6864 {6865 try6866 {6867 if ($key != "RELATIONS")6868 {6869 $control = $this->{$key};6870 if ($control instanceof TTextBox)6871 $control->Text = $arObj->{$key};6872 elseif ($control instanceof TCheckBox)6873 $control->Checked = (boolean) $arObj->{$key};6874 elseif ($control instanceof TDatePicker)6875 $control->Date = $arObj->{$key};6876 }6877 else6878 {6879 foreach ($objAttrs["RELATIONS"] as $relKey => $relValues)6880 {6881 $relControl = $this->{$relKey};6882 switch ($relValues[0])6883 {6884 case TActiveRecord::BELONGS_TO:6885 case TActiveRecord::HAS_ONE:6886 $relControl->Text = $arObj->{$relKey};6887 break;6888 case TActiveRecord::HAS_MANY:6889 if ($relControl instanceof TListControl)6890 {6891 $relControl->DataSource = $arObj->{$relKey};6892 $relControl->dataBind();6893 }6894 break;6895 }6896 }6897 break;6898 }6899 } 6900 catch (Exception $ex)6901 {6902 if ($throwExceptions)6903 throw $ex;6904 }6905 }6906 }6907 public function tryToUpdateAR($arObj, $throwExceptions = false)6908 {6909 $objAttrs = get_class_vars(get_class($arObj));6910 foreach (array_keys($objAttrs) as $key)6911 {6912 try6913 {6914 if ($key == "RELATIONS")6915 break;6916 $control = $this->{$key};6917 if ($control instanceof TTextBox)6918 $arObj->{$key} = $control->Text;6919 elseif ($control instanceof TCheckBox)6920 $arObj->{$key} = $control->Checked;6921 elseif ($control instanceof TDatePicker)6922 $arObj->{$key} = $control->Date;6923 } 6924 catch (Exception $ex)6925 {6926 if ($throwExceptions)6927 throw $ex;6928 }6929 }6930 }6931}6932class TForm extends TControl6933{6934 public function onInit($param)6935 {6936 parent::onInit($param);6937 $this->getPage()->setForm($this);6938 }6939 protected function addAttributesToRender($writer)6940 {6941 $writer->addAttribute('id',$this->getClientID());6942 $writer->addAttribute('method',$this->getMethod());6943 $uri=$this->getRequest()->getRequestURI();6944 $writer->addAttribute('action',str_replace('&','&amp;',str_replace('&amp;','&',$uri)));6945 if(($enctype=$this->getEnctype())!=='')6946 $writer->addAttribute('enctype',$enctype);6947 $attributes=$this->getAttributes();6948 $attributes->remove('action');6949 $writer->addAttributes($attributes);6950 if(($butt=$this->getDefaultButton())!=='')6951 {6952 if(($button=$this->findControl($butt))!==null)6953 $this->getPage()->getClientScript()->registerDefaultButton($this, $button);6954 else6955 throw new TInvalidDataValueException('form_defaultbutton_invalid',$butt);6956 }6957 }6958 public function render($writer)6959 {6960 $page=$this->getPage();6961 $this->addAttributesToRender($writer);6962 $writer->renderBeginTag('form');6963 $cs=$page->getClientScript();6964 if($page->getClientSupportsJavaScript())6965 {6966 $cs->renderHiddenFieldsBegin($writer);6967 $cs->renderScriptFilesBegin($writer);6968 $cs->renderBeginScripts($writer);6969 $page->beginFormRender($writer);6970 $this->renderChildren($writer);6971 $cs->renderHiddenFieldsEnd($writer);6972 $page->endFormRender($writer);6973 $cs->renderScriptFilesEnd($writer);6974 $cs->renderEndScripts($writer);6975 }6976 else6977 {6978 $cs->renderHiddenFieldsBegin($writer);6979 $page->beginFormRender($writer);6980 $this->renderChildren($writer);6981 $page->endFormRender($writer);6982 $cs->renderHiddenFieldsEnd($writer);6983 }6984 $writer->renderEndTag();6985 }6986 public function getDefaultButton()6987 {6988 return $this->getViewState('DefaultButton','');6989 }6990 public function setDefaultButton($value)6991 {6992 $this->setViewState('DefaultButton',$value,'');6993 }6994 public function getMethod()6995 {6996 return $this->getViewState('Method','post');6997 }6998 public function setMethod($value)6999 {7000 $this->setViewState('Method',TPropertyValue::ensureEnum($value,'post','get'),'post');7001 }7002 public function getEnctype()7003 {7004 return $this->getViewState('Enctype','');7005 }7006 public function setEnctype($value)7007 {7008 $this->setViewState('Enctype',$value,'');7009 }7010 public function getName()7011 {7012 return $this->getUniqueID();7013 }7014}7015class TClientScriptManager extends TApplicationComponent7016{7017 const SCRIPT_PATH='Web/Javascripts/source';7018 const PACKAGES_FILE='Web/Javascripts/packages.php';7019 const CSS_PACKAGES_FILE='Web/Javascripts/css-packages.php';7020 private $_page;7021 private $_hiddenFields=array();7022 private $_beginScripts=array();7023 private $_endScripts=array();7024 private $_scriptFiles=array();7025 private $_headScriptFiles=array();7026 private $_headScripts=array();7027 private $_styleSheetFiles=array();7028 private $_styleSheets=array();7029 private $_registeredPradoScripts=array();7030 private static $_pradoScripts;7031 private static $_pradoPackages;7032 private $_registeredPradoStyles=array();7033 private static $_pradoStyles;7034 private static $_pradoStylePackages;7035 private $_renderedHiddenFields;7036 private $_renderedScriptFiles=array();7037 private $_expandedPradoScripts;7038 private $_expandedPradoStyles;7039 public function __construct(TPage $owner)7040 {7041 $this->_page=$owner;7042 }7043 public function getRequiresHead()7044 {7045 return count($this->_styleSheetFiles) || count($this->_styleSheets)7046 || count($this->_headScriptFiles) || count($this->_headScripts);7047 }7048 public static function getPradoPackages()7049 {7050 return self::$_pradoPackages;7051 }7052 public static function getPradoScripts()7053 {7054 return self::$_pradoScripts;7055 }7056 public function registerPradoScript($name)7057 {7058 $this->registerPradoScriptInternal($name);7059 $params=func_get_args();7060 $this->_page->registerCachingAction('Page.ClientScript','registerPradoScript',$params);7061 }7062 protected function registerPradoScriptInternal($name)7063 {7064 if(!isset($this->_registeredPradoScripts[$name]))7065 {7066 if(self::$_pradoScripts === null)7067 {7068 $packageFile = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::PACKAGES_FILE;7069 list($packages,$deps)= include($packageFile);7070 self::$_pradoScripts = $deps;7071 self::$_pradoPackages = $packages;7072 }7073 if (isset(self::$_pradoScripts[$name]))7074 $this->_registeredPradoScripts[$name]=true;7075 else7076 throw new TInvalidOperationException('csmanager_pradoscript_invalid',$name);7077 if(($packages=array_keys($this->_registeredPradoScripts))!==array())7078 {7079 $base = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::SCRIPT_PATH;7080 list($path,$baseUrl)=$this->getPackagePathUrl($base);7081 $packagesUrl=array();7082 $isDebug=$this->getApplication()->getMode()===TApplicationMode::Debug;7083 foreach ($packages as $p)7084 {7085 foreach (self::$_pradoScripts[$p] as $dep)7086 {7087 foreach (self::$_pradoPackages[$dep] as $script)7088 if (!isset($this->_expandedPradoScripts[$script]))7089 {7090 $this->_expandedPradoScripts[$script] = true;7091 if($isDebug)7092 {7093 if (!in_array($url=$baseUrl.'/'.$script,$packagesUrl))7094 $packagesUrl[]=$url;7095 } else {7096 if (!in_array($url=$baseUrl.'/min/'.$script,$packagesUrl))7097 {7098 if(!is_file($filePath=$path.'/min/'.$script))7099 {7100 $dirPath=dirname($filePath);7101 if(!is_dir($dirPath))7102 mkdir($dirPath, PRADO_CHMOD, true);7103 file_put_contents($filePath, TJavaScript::JSMin(file_get_contents($base.'/'.$script)));7104 chmod($filePath, PRADO_CHMOD);7105 }7106 $packagesUrl[]=$url;7107 }7108 }7109 }7110 }7111 }7112 foreach($packagesUrl as $url)7113 $this->registerScriptFile($url,$url);7114 }7115 }7116 }7117 public function getPradoScriptAssetUrl()7118 {7119 $base = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::SCRIPT_PATH;7120 $assets = Prado::getApplication()->getAssetManager();7121 return $assets->getPublishedUrl($base);7122 }7123 public function getScriptUrls()7124 {7125 $scripts = array_values($this->_headScriptFiles);7126 $scripts = array_merge($scripts, array_values($this->_scriptFiles));7127 $scripts = array_unique($scripts);7128 return $scripts;7129 }7130 protected function getPackagePathUrl($base)7131 {7132 $assets = Prado::getApplication()->getAssetManager();7133 if(strpos($base, $assets->getBaseUrl())===false)7134 {7135 if(($dir = Prado::getPathOfNameSpace($base)) !== null) {7136 $base = $dir;7137 }7138 return array($assets->getPublishedPath($base), $assets->publishFilePath($base));7139 }7140 else7141 {7142 return array($assets->getBasePath().str_replace($assets->getBaseUrl(),'',$base), $base);7143 }7144 }7145 public function getCallbackReference(ICallbackEventHandler $callbackHandler, $options=null)7146 {7147 $options = !is_array($options) ? array() : $options;7148 $class = new ReflectionClass($callbackHandler);7149 $clientSide = $callbackHandler->getActiveControl()->getClientSide();7150 $options = array_merge($options, $clientSide->getOptions()->toArray());7151 $optionString = TJavaScript::encode($options);7152 $this->registerPradoScriptInternal('ajax');7153 $id = $callbackHandler->getUniqueID();7154 return "new Prado.CallbackRequest('{$id}',{$optionString})";7155 }7156 public function registerCallbackControl($class, $options)7157 {7158 $optionString=TJavaScript::encode($options);7159 $code="new {$class}({$optionString});";7160 $this->_endScripts[sprintf('%08X', crc32($code))]=$code;7161 $this->registerPradoScriptInternal('ajax');7162 $params=func_get_args();7163 $this->_page->registerCachingAction('Page.ClientScript','registerCallbackControl',$params);7164 }7165 public function registerPostBackControl($class,$options)7166 {7167 if($class === null) {7168 return;7169 }7170 if(!isset($options['FormID']) && ($form=$this->_page->getForm())!==null)7171 $options['FormID']=$form->getClientID();7172 $optionString=TJavaScript::encode($options);7173 $code="new {$class}({$optionString});";7174 $this->_endScripts[sprintf('%08X', crc32($code))]=$code;7175 $this->registerPradoScriptInternal('prado');7176 $params=func_get_args();7177 $this->_page->registerCachingAction('Page.ClientScript','registerPostBackControl',$params);7178 }7179 public function registerDefaultButton($panel, $button)7180 {7181 $panelID=is_string($panel)?$panel:$panel->getUniqueID();7182 if(is_string($button))7183 $buttonID=$button;7184 else7185 {7186 $button->setIsDefaultButton(true);7187 $buttonID=$button->getUniqueID();7188 }7189 $options = TJavaScript::encode($this->getDefaultButtonOptions($panelID, $buttonID));7190 $code = "new Prado.WebUI.DefaultButton($options);";7191 $this->_endScripts['prado:'.$panelID]=$code;7192 $this->registerPradoScriptInternal('prado');7193 $params=array($panelID,$buttonID);7194 $this->_page->registerCachingAction('Page.ClientScript','registerDefaultButton',$params);7195 }7196 protected function getDefaultButtonOptions($panelID, $buttonID)7197 {7198 $options['ID'] = TControl::convertUniqueIdToClientId($panelID);7199 $options['Panel'] = TControl::convertUniqueIdToClientId($panelID);7200 $options['Target'] = TControl::convertUniqueIdToClientId($buttonID);7201 $options['EventTarget'] = $buttonID;7202 $options['Event'] = 'click';7203 return $options;7204 }7205 public function registerFocusControl($target)7206 {7207 $this->registerPradoScriptInternal('jquery');7208 if($target instanceof TControl)7209 $target=$target->getClientID();7210 $this->_endScripts['prado:focus'] = 'jQuery(\'#'.$target.'\').focus();';7211 $params=func_get_args();7212 $this->_page->registerCachingAction('Page.ClientScript','registerFocusControl',$params);7213 }7214 public function registerPradoStyle($name)7215 {7216 $this->registerPradoStyleInternal($name);7217 $params=func_get_args();7218 $this->_page->registerCachingAction('Page.ClientScript','registerPradoStyle',$params);7219 }7220 protected function registerPradoStyleInternal($name)7221 {7222 if(!isset($this->_registeredPradoStyles[$name]))7223 {7224 $base = $this->getPradoScriptAssetUrl();7225 if(self::$_pradoStyles === null)7226 {7227 $packageFile = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::CSS_PACKAGES_FILE;7228 list($packages,$deps)= include($packageFile);7229 self::$_pradoStyles = $deps;7230 self::$_pradoStylePackages = $packages;7231 }7232 if (isset(self::$_pradoStyles[$name]))7233 $this->_registeredPradoStyles[$name]=true;7234 else7235 throw new TInvalidOperationException('csmanager_pradostyle_invalid',$name);7236 if(($packages=array_keys($this->_registeredPradoStyles))!==array())7237 {7238 $base = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::SCRIPT_PATH;7239 list($path,$baseUrl)=$this->getPackagePathUrl($base);7240 $packagesUrl=array();7241 $isDebug=$this->getApplication()->getMode()===TApplicationMode::Debug;7242 foreach ($packages as $p)7243 {7244 foreach (self::$_pradoStyles[$p] as $dep)7245 {7246 foreach (self::$_pradoStylePackages[$dep] as $style)7247 if (!isset($this->_expandedPradoStyles[$style]))7248 {7249 $this->_expandedPradoStyles[$style] = true;7250 if (!in_array($url=$baseUrl.'/'.$style,$packagesUrl))7251 $packagesUrl[]=$url;7252 }7253 }7254 }7255 foreach($packagesUrl as $url)7256 $this->registerStyleSheetFile($url,$url);7257 }7258 }7259 }7260 public function registerStyleSheetFile($key,$url,$media='')7261 {7262 if($media==='')7263 $this->_styleSheetFiles[$key]=$url;7264 else7265 $this->_styleSheetFiles[$key]=array($url,$media);7266 $params=func_get_args();7267 $this->_page->registerCachingAction('Page.ClientScript','registerStyleSheetFile',$params);7268 }7269 public function registerStyleSheet($key,$css,$media='')7270 {7271 $this->_styleSheets[$key]=$css;7272 $params=func_get_args();7273 $this->_page->registerCachingAction('Page.ClientScript','registerStyleSheet',$params);7274 }7275 public function getStyleSheetUrls()7276 {7277 $stylesheets = array_values(7278 array_map(function($e) {7279 return is_array($e) ? $e[0] : $e;7280 }, $this->_styleSheetFiles)7281 );7282 foreach(Prado::getApplication()->getAssetManager()->getPublished() as $path=>$url)7283 if (substr($url,strlen($url)-4)=='.css')7284 $stylesheets[] = $url;7285 $stylesheets = array_unique($stylesheets);7286 return $stylesheets;7287 }7288 public function getStyleSheetCodes()7289 {7290 return array_unique(array_values($this->_styleSheets));7291 }7292 public function registerHeadScriptFile($key,$url)7293 {7294 $this->checkIfNotInRender();7295 $this->_headScriptFiles[$key]=$url;7296 $params=func_get_args();7297 $this->_page->registerCachingAction('Page.ClientScript','registerHeadScriptFile',$params);7298 }7299 public function registerHeadScript($key,$script)7300 {7301 $this->checkIfNotInRender();7302 $this->_headScripts[$key]=$script;7303 $params=func_get_args();7304 $this->_page->registerCachingAction('Page.ClientScript','registerHeadScript',$params);7305 }7306 public function registerScriptFile($key, $url)7307 {7308 $this->_scriptFiles[$key]=$url;7309 $params=func_get_args();7310 $this->_page->registerCachingAction('Page.ClientScript','registerScriptFile',$params);7311 }7312 public function registerBeginScript($key,$script)7313 {7314 $this->checkIfNotInRender();7315 $this->_beginScripts[$key]=$script;7316 $params=func_get_args();7317 $this->_page->registerCachingAction('Page.ClientScript','registerBeginScript',$params);7318 }7319 public function registerEndScript($key,$script)7320 {7321 $this->_endScripts[$key]=$script;7322 $params=func_get_args();7323 $this->_page->registerCachingAction('Page.ClientScript','registerEndScript',$params);7324 }7325 public function registerHiddenField($name,$value)7326 {7327 $this->_hiddenFields[$name]=$value;7328 $params=func_get_args();7329 $this->_page->registerCachingAction('Page.ClientScript','registerHiddenField',$params);7330 }7331 public function isStyleSheetFileRegistered($key)7332 {7333 return isset($this->_styleSheetFiles[$key]);7334 }7335 public function isStyleSheetRegistered($key)7336 {7337 return isset($this->_styleSheets[$key]);7338 }7339 public function isHeadScriptFileRegistered($key)7340 {7341 return isset($this->_headScriptFiles[$key]);7342 }7343 public function isHeadScriptRegistered($key)7344 {7345 return isset($this->_headScripts[$key]);7346 }7347 public function isScriptFileRegistered($key)7348 {7349 return isset($this->_scriptFiles[$key]);7350 }7351 public function isBeginScriptRegistered($key)7352 {7353 return isset($this->_beginScripts[$key]);7354 }7355 public function isEndScriptRegistered($key)7356 {7357 return isset($this->_endScripts[$key]);7358 }7359 public function hasEndScripts()7360 {7361 return count($this->_endScripts) > 0;7362 }7363 public function hasBeginScripts()7364 {7365 return count($this->_beginScripts) > 0;7366 }7367 public function isHiddenFieldRegistered($key)7368 {7369 return isset($this->_hiddenFields[$key]);7370 }7371 public function renderStyleSheetFiles($writer)7372 {7373 $str='';7374 foreach($this->_styleSheetFiles as $url)7375 {7376 if(is_array($url))7377 $str.="<link rel=\"stylesheet\" type=\"text/css\" media=\"{$url[1]}\" href=\"".THttpUtility::htmlEncode($url[0])."\" />\n";7378 else7379 $str.="<link rel=\"stylesheet\" type=\"text/css\" href=\"".THttpUtility::htmlEncode($url)."\" />\n";7380 }7381 $writer->write($str);7382 }7383 public function renderStyleSheets($writer)7384 {7385 if(count($this->_styleSheets))7386 $writer->write("<style type=\"text/css\">\n/*<![CDATA[*/\n".implode("\n",$this->_styleSheets)."\n/*]]>*/\n</style>\n");7387 }7388 public function renderHeadScriptFiles($writer)7389 {7390 $this->renderScriptFiles($writer,$this->_headScriptFiles);7391 }7392 public function renderHeadScripts($writer)7393 {7394 $writer->write(TJavaScript::renderScriptBlocks($this->_headScripts));7395 }7396 public function renderScriptFilesBegin($writer)7397 {7398 $this->renderAllPendingScriptFiles($writer);7399 }7400 public function renderScriptFilesEnd($writer)7401 {7402 $this->renderAllPendingScriptFiles($writer);7403 }7404 public function markScriptFileAsRendered($url)7405 {7406 $this->_renderedScriptFiles[$url] = $url;7407 $params=func_get_args();7408 $this->_page->registerCachingAction('Page.ClientScript','markScriptFileAsRendered',$params);7409 }7410 protected function renderScriptFiles($writer, Array $scripts)7411 {7412 foreach($scripts as $script)7413 {7414 $writer->write(TJavaScript::renderScriptFile($script));7415 $this->markScriptFileAsRendered($script);7416 }7417 }7418 protected function getRenderedScriptFiles()7419 {7420 return $this->_renderedScriptFiles;7421 }7422 public function renderAllPendingScriptFiles($writer)7423 {7424 if(!empty($this->_scriptFiles))7425 {7426 $addedScripts = array_diff($this->_scriptFiles,$this->getRenderedScriptFiles());7427 $this->renderScriptFiles($writer,$addedScripts);7428 }7429 }7430 public function renderBeginScripts($writer)7431 {7432 $writer->write(TJavaScript::renderScriptBlocks($this->_beginScripts));7433 }7434 public function renderEndScripts($writer)7435 {7436 $writer->write(TJavaScript::renderScriptBlocks($this->_endScripts));7437 }7438 public function renderBeginScriptsCallback($writer)7439 {7440 $writer->write(TJavaScript::renderScriptBlocksCallback($this->_beginScripts));7441 }7442 public function renderEndScriptsCallback($writer)7443 {7444 $writer->write(TJavaScript::renderScriptBlocksCallback($this->_endScripts));7445 }7446 public function renderHiddenFieldsBegin($writer)7447 {7448 $this->renderHiddenFieldsInt($writer,true);7449 }7450 public function renderHiddenFieldsEnd($writer)7451 {7452 $this->renderHiddenFieldsInt($writer,false);7453 }7454 public function flushScriptFiles($writer, $control=null)7455 {7456 if(!$this->_page->getIsCallback())7457 {7458 $this->_page->ensureRenderInForm($control);7459 $this->renderAllPendingScriptFiles($writer);7460 }7461 }7462 protected function renderHiddenFieldsInt($writer, $initial)7463 {7464 if ($initial) $this->_renderedHiddenFields = array();7465 $str='';7466 foreach($this->_hiddenFields as $name=>$value)7467 {7468 if (in_array($name,$this->_renderedHiddenFields)) continue;7469 $id=strtr($name,':','_');7470 if(is_array($value))7471 {7472 foreach($value as $v)7473 $str.='<input type="hidden" name="'.$name.'[]" id="'.$id.'" value="'.THttpUtility::htmlEncode($value)."\" />\n";7474 }7475 else7476 {7477 $str.='<input type="hidden" name="'.$name.'" id="'.$id.'" value="'.THttpUtility::htmlEncode($value)."\" />\n";7478 }7479 $this->_renderedHiddenFields[] = $name;7480 }7481 if($str!=='')7482 $writer->write("<div style=\"visibility:hidden;\">\n".$str."</div>\n");7483 }7484 public function getHiddenFields()7485 {7486 return $this->_hiddenFields;7487 }7488 protected function checkIfNotInRender()7489 {7490 if ($form = $this->_page->InFormRender)7491 throw new Exception('Operation invalid when page is already rendering');7492 }7493}7494abstract class TClientSideOptions extends TComponent7495{7496 private $_options;7497 protected function setFunction($name, $code)7498 {7499 if(!TJavaScript::isJsLiteral($code))7500 $code = TJavaScript::quoteJsLiteral($this->ensureFunction($code));7501 $this->setOption($name, $code);7502 }7503 protected function getOption($name)7504 {7505 if ($this->_options)7506 return $this->_options->itemAt($name);7507 else7508 return null;7509 }7510 protected function setOption($name, $value)7511 {7512 $this->getOptions()->add($name, $value);7513 }7514 public function getOptions()7515 {7516 if (!$this->_options)7517 $this->_options = Prado::createComponent('System.Collections.TMap');7518 return $this->_options;7519 }7520 protected function ensureFunction($javascript)7521 {7522 return "function(sender, parameter){ {$javascript} }";7523 }7524}7525class TPage extends TTemplateControl7526{7527 const FIELD_POSTBACK_TARGET='PRADO_POSTBACK_TARGET';7528 const FIELD_POSTBACK_PARAMETER='PRADO_POSTBACK_PARAMETER';7529 const FIELD_LASTFOCUS='PRADO_LASTFOCUS';7530 const FIELD_PAGESTATE='PRADO_PAGESTATE';7531 const FIELD_CALLBACK_TARGET='PRADO_CALLBACK_TARGET';7532 const FIELD_CALLBACK_PARAMETER='PRADO_CALLBACK_PARAMETER';7533 private static $_systemPostFields=array(7534 'PRADO_POSTBACK_TARGET'=>true,7535 'PRADO_POSTBACK_PARAMETER'=>true,7536 'PRADO_LASTFOCUS'=>true,7537 'PRADO_PAGESTATE'=>true,7538 'PRADO_CALLBACK_TARGET'=>true,7539 'PRADO_CALLBACK_PARAMETER'=>true7540 );7541 private $_form;7542 private $_head;7543 private $_validators=array();7544 private $_validated=false;7545 private $_theme;7546 private $_title;7547 private $_styleSheet;7548 private $_clientScript;7549 protected $_postData;7550 protected $_restPostData;7551 protected $_controlsPostDataChanged=array();7552 protected $_controlsRequiringPostData=array();7553 protected $_controlsRegisteredForPostData=array();7554 private $_postBackEventTarget;7555 private $_postBackEventParameter;7556 protected $_formRendered=false;7557 protected $_inFormRender=false;7558 private $_focus;7559 private $_pagePath='';7560 private $_enableStateValidation=true;7561 private $_enableStateEncryption=false;7562 private $_enableStateCompression=true;7563 private $_statePersisterClass='System.Web.UI.TPageStatePersister';7564 private $_statePersister;7565 private $_cachingStack;7566 private $_clientState='';7567 protected $_isLoadingPostData=false;7568 private $_enableJavaScript=true;7569 private $_writer;7570 public function __construct()7571 {7572 $this->setPage($this);7573 }7574 public function run($writer)7575 {7576 $this->_writer = $writer;7577 $this->determinePostBackMode();7578 if($this->getIsPostBack())7579 {7580 if($this->getIsCallback())7581 $this->processCallbackRequest($writer);7582 else7583 $this->processPostBackRequest($writer);7584 }7585 else7586 $this->processNormalRequest($writer);7587 $this->_writer = null;7588 }7589 protected function processNormalRequest($writer)7590 {7591 $this->onPreInit(null);7592 $this->initRecursive();7593 $this->onInitComplete(null);7594 $this->onPreLoad(null);7595 $this->loadRecursive();7596 $this->onLoadComplete(null);7597 $this->preRenderRecursive();7598 $this->onPreRenderComplete(null);7599 $this->savePageState();7600 $this->onSaveStateComplete(null);7601 $this->renderControl($writer);7602 $this->unloadRecursive();7603 }7604 protected function processPostBackRequest($writer)7605 {7606 $this->onPreInit(null);7607 $this->initRecursive();7608 $this->onInitComplete(null);7609 $this->_restPostData=new TMap;7610 $this->loadPageState();7611 $this->processPostData($this->_postData,true);7612 $this->onPreLoad(null);7613 $this->loadRecursive();7614 $this->processPostData($this->_restPostData,false);7615 $this->raiseChangedEvents();7616 $this->raisePostBackEvent();7617 $this->onLoadComplete(null);7618 $this->preRenderRecursive();7619 $this->onPreRenderComplete(null);7620 $this->savePageState();7621 $this->onSaveStateComplete(null);7622 $this->renderControl($writer);7623 $this->unloadRecursive();7624 }7625 protected static function decodeUTF8($data, $enc)7626 {7627 if(is_array($data))7628 {7629 foreach($data as $k=>$v)7630 $data[$k]=self::decodeUTF8($v, $enc);7631 return $data;7632 } elseif(is_string($data)) {7633 return iconv('UTF-8',$enc.'//IGNORE',$data);7634 } else {7635 return $data;7636 }7637 }7638 protected function processCallbackRequest($writer)7639 {7640 Prado::using('System.Web.UI.ActiveControls.TActivePageAdapter');7641 Prado::using('System.Web.UI.JuiControls.TJuiControlOptions');7642 $this->setAdapter(new TActivePageAdapter($this));7643 $callbackEventParameter = $this->getRequest()->itemAt(TPage::FIELD_CALLBACK_PARAMETER);7644 if(strlen($callbackEventParameter) > 0)7645 $this->_postData[TPage::FIELD_CALLBACK_PARAMETER]=TJavaScript::jsonDecode((string)$callbackEventParameter);7646 if (($g=$this->getApplication()->getGlobalization(false))!==null &&7647 strtoupper($enc=$g->getCharset())!='UTF-8')7648 foreach ($this->_postData as $k=>$v)7649 $this->_postData[$k]=self::decodeUTF8($v, $enc);7650 $this->onPreInit(null);7651 $this->initRecursive();7652 $this->onInitComplete(null);7653 $this->_restPostData=new TMap;7654 $this->loadPageState();7655 $this->processPostData($this->_postData,true);7656 $this->onPreLoad(null);7657 $this->loadRecursive();7658 $this->processPostData($this->_restPostData,false);7659 $this->raiseChangedEvents();7660 $this->getAdapter()->processCallbackEvent($writer);7661 $this->onLoadComplete(null);7662 $this->preRenderRecursive();7663 $this->onPreRenderComplete(null);7664 $this->savePageState();7665 $this->onSaveStateComplete(null);7666 $this->getAdapter()->renderCallbackResponse($writer);7667 $this->unloadRecursive();7668 }7669 public function getCallbackClient()7670 {7671 if($this->getAdapter() !== null)7672 return $this->getAdapter()->getCallbackClientHandler();7673 else7674 return new TCallbackClientScript();7675 }7676 public function setCallbackClient($client)7677 {7678 $this->getAdapter()->setCallbackClientHandler($client);7679 }7680 public function getCallbackEventTarget()7681 {7682 return $this->getAdapter()->getCallbackEventTarget();7683 }7684 public function setCallbackEventTarget(TControl $control)7685 {7686 $this->getAdapter()->setCallbackEventTarget($control);7687 }7688 public function getCallbackEventParameter()7689 {7690 return $this->getAdapter()->getCallbackEventParameter();7691 }7692 public function setCallbackEventParameter($value)7693 {7694 $this->getAdapter()->setCallbackEventParameter($value);7695 }7696 public function getForm()7697 {7698 return $this->_form;7699 }7700 public function setForm(TForm $form)7701 {7702 if($this->_form===null)7703 $this->_form=$form;7704 else7705 throw new TInvalidOperationException('page_form_duplicated');7706 }7707 public function getValidators($validationGroup=null)7708 {7709 if(!$this->_validators)7710 $this->_validators=new TList;7711 if(empty($validationGroup) === true)7712 return $this->_validators;7713 else7714 {7715 $list=new TList;7716 foreach($this->_validators as $validator)7717 if($validator->getValidationGroup()===$validationGroup)7718 $list->add($validator);7719 return $list;7720 }7721 }7722 public function validate($validationGroup=null)7723 {7724 $this->_validated=true;7725 if($this->_validators && $this->_validators->getCount())7726 {7727 if($validationGroup===null)7728 {7729 foreach($this->_validators as $validator)7730 $validator->validate();7731 }7732 else7733 {7734 foreach($this->_validators as $validator)7735 {7736 if($validator->getValidationGroup()===$validationGroup)7737 $validator->validate();7738 }7739 }7740 }7741 }7742 public function getIsValid()7743 {7744 if($this->_validated)7745 {7746 if($this->_validators && $this->_validators->getCount())7747 {7748 foreach($this->_validators as $validator)7749 if(!$validator->getIsValid())7750 return false;7751 }7752 return true;7753 }7754 else7755 throw new TInvalidOperationException('page_isvalid_unknown');7756 }7757 public function getTheme()7758 {7759 if(is_string($this->_theme))7760 $this->_theme=$this->getService()->getThemeManager()->getTheme($this->_theme);7761 return $this->_theme;7762 }7763 public function setTheme($value)7764 {7765 $this->_theme=empty($value)?null:$value;7766 }7767 public function getStyleSheetTheme()7768 {7769 if(is_string($this->_styleSheet))7770 $this->_styleSheet=$this->getService()->getThemeManager()->getTheme($this->_styleSheet);7771 return $this->_styleSheet;7772 }7773 public function setStyleSheetTheme($value)7774 {7775 $this->_styleSheet=empty($value)?null:$value;7776 }7777 public function applyControlSkin($control)7778 {7779 if(($theme=$this->getTheme())!==null)7780 $theme->applySkin($control);7781 }7782 public function applyControlStyleSheet($control)7783 {7784 if(($theme=$this->getStyleSheetTheme())!==null)7785 $theme->applySkin($control);7786 }7787 public function getClientScript()7788 {7789 if(!$this->_clientScript) {7790 $className = $classPath = $this->getService()->getClientScriptManagerClass();7791 Prado::using($className);7792 if(($pos=strrpos($className,'.'))!==false)7793 $className=substr($className,$pos+1);7794 if(!class_exists($className,false) || ($className!=='TClientScriptManager' && !is_subclass_of($className,'TClientScriptManager')))7795 throw new THttpException(404,'page_csmanagerclass_invalid',$classPath);7796 $this->_clientScript=new $className($this);7797 }7798 return $this->_clientScript;7799 }7800 public function onPreInit($param)7801 {7802 $this->raiseEvent('OnPreInit',$this,$param);7803 }7804 public function onInitComplete($param)7805 {7806 $this->raiseEvent('OnInitComplete',$this,$param);7807 }7808 public function onPreLoad($param)7809 {7810 $this->raiseEvent('OnPreLoad',$this,$param);7811 }7812 public function onLoadComplete($param)7813 {7814 $this->raiseEvent('OnLoadComplete',$this,$param);7815 }7816 public function onPreRenderComplete($param)7817 {7818 $this->raiseEvent('OnPreRenderComplete',$this,$param);7819 $cs=$this->getClientScript();7820 $theme=$this->getTheme();7821 if($theme instanceof ITheme)7822 {7823 foreach($theme->getStyleSheetFiles() as $url)7824 $cs->registerStyleSheetFile($url,$url,$this->getCssMediaType($url));7825 foreach($theme->getJavaScriptFiles() as $url)7826 $cs->registerHeadScriptFile($url,$url);7827 }7828 $styleSheet=$this->getStyleSheetTheme();7829 if($styleSheet instanceof ITheme)7830 {7831 foreach($styleSheet->getStyleSheetFiles() as $url)7832 $cs->registerStyleSheetFile($url,$url,$this->getCssMediaType($url));7833 foreach($styleSheet->getJavaScriptFiles() as $url)7834 $cs->registerHeadScriptFile($url,$url);7835 }7836 if($cs->getRequiresHead() && $this->getHead()===null)7837 throw new TConfigurationException('page_head_required');7838 }7839 private function getCssMediaType($url)7840 {7841 $segs=explode('.',basename($url));7842 if(isset($segs[2]))7843 return $segs[count($segs)-2];7844 else7845 return '';7846 }7847 public function onSaveStateComplete($param)7848 {7849 $this->raiseEvent('OnSaveStateComplete',$this,$param);7850 }7851 private function determinePostBackMode()7852 {7853 $postData=$this->getRequest();7854 if($postData->contains(self::FIELD_PAGESTATE) || $postData->contains(self::FIELD_POSTBACK_TARGET))7855 $this->_postData=$postData;7856 }7857 public function getIsPostBack()7858 {7859 return $this->_postData!==null;7860 }7861 public function getIsCallback()7862 {7863 return $this->getIsPostBack() && $this->getRequest()->contains(self::FIELD_CALLBACK_TARGET);7864 }7865 public function saveState()7866 {7867 parent::saveState();7868 $this->setViewState('ControlsRequiringPostBack',$this->_controlsRegisteredForPostData,array());7869 }7870 public function loadState()7871 {7872 parent::loadState();7873 $this->_controlsRequiringPostData=$this->getViewState('ControlsRequiringPostBack',array());7874 }7875 protected function loadPageState()7876 {7877 $state=$this->getStatePersister()->load();7878 $this->loadStateRecursive($state,$this->getEnableViewState());7879 }7880 protected function savePageState()7881 {7882 $state=&$this->saveStateRecursive($this->getEnableViewState());7883 $this->getStatePersister()->save($state);7884 }7885 protected function isSystemPostField($field)7886 {7887 return isset(self::$_systemPostFields[$field]);7888 }7889 public function registerRequiresPostData($control)7890 {7891 $id=is_string($control)?$control:$control->getUniqueID();7892 $this->_controlsRegisteredForPostData[$id]=true;7893 $params=func_get_args();7894 foreach($this->getCachingStack() as $item)7895 $item->registerAction('Page','registerRequiresPostData',array($id));7896 }7897 public function getPostBackEventTarget()7898 {7899 if($this->_postBackEventTarget===null && $this->_postData!==null)7900 {7901 $eventTarget=$this->_postData->itemAt(self::FIELD_POSTBACK_TARGET);7902 if(!empty($eventTarget))7903 $this->_postBackEventTarget=$this->findControl($eventTarget);7904 }7905 return $this->_postBackEventTarget;7906 }7907 public function setPostBackEventTarget(TControl $control)7908 {7909 $this->_postBackEventTarget=$control;7910 }7911 public function getPostBackEventParameter()7912 {7913 if($this->_postBackEventParameter===null && $this->_postData!==null)7914 {7915 if(($this->_postBackEventParameter=$this->_postData->itemAt(self::FIELD_POSTBACK_PARAMETER))===null)7916 $this->_postBackEventParameter='';7917 }7918 return $this->_postBackEventParameter;7919 }7920 public function setPostBackEventParameter($value)7921 {7922 $this->_postBackEventParameter=$value;7923 }7924 protected function processPostData($postData,$beforeLoad)7925 {7926 $this->_isLoadingPostData=true;7927 if($beforeLoad)7928 $this->_restPostData=new TMap;7929 foreach($postData as $key=>$value)7930 {7931 if($this->isSystemPostField($key))7932 continue;7933 else if($control=$this->findControl($key))7934 {7935 if($control instanceof IPostBackDataHandler)7936 {7937 if($control->loadPostData($key,$postData))7938 $this->_controlsPostDataChanged[]=$control;7939 }7940 else if($control instanceof IPostBackEventHandler &&7941 empty($this->_postData[self::FIELD_POSTBACK_TARGET]))7942 {7943 $this->_postData->add(self::FIELD_POSTBACK_TARGET,$key); }7944 unset($this->_controlsRequiringPostData[$key]);7945 }7946 else if($beforeLoad)7947 $this->_restPostData->add($key,$value);7948 }7949 foreach($this->_controlsRequiringPostData as $key=>$value)7950 {7951 if($control=$this->findControl($key))7952 {7953 if($control instanceof IPostBackDataHandler)7954 {7955 if($control->loadPostData($key,$this->_postData))7956 $this->_controlsPostDataChanged[]=$control;7957 }7958 else7959 throw new TInvalidDataValueException('page_postbackcontrol_invalid',$key);7960 unset($this->_controlsRequiringPostData[$key]);7961 }7962 }7963 $this->_isLoadingPostData=false;7964 }7965 public function getIsLoadingPostData()7966 {7967 return $this->_isLoadingPostData;7968 }7969 protected function raiseChangedEvents()7970 {7971 foreach($this->_controlsPostDataChanged as $control)7972 $control->raisePostDataChangedEvent();7973 }7974 protected function raisePostBackEvent()7975 {7976 if(($postBackHandler=$this->getPostBackEventTarget())===null)7977 $this->validate();7978 else if($postBackHandler instanceof IPostBackEventHandler)7979 $postBackHandler->raisePostBackEvent($this->getPostBackEventParameter());7980 }7981 public function getInFormRender()7982 {7983 return $this->_inFormRender;7984 }7985 public function ensureRenderInForm($control)7986 {7987 if(!$this->getIsCallback() && !$this->_inFormRender)7988 throw new TConfigurationException('page_control_outofform',get_class($control), $control ? $control->getUniqueID() : null);7989 }7990 public function beginFormRender($writer)7991 {7992 if($this->_formRendered)7993 throw new TConfigurationException('page_form_duplicated');7994 $this->_formRendered=true;7995 $this->getClientScript()->registerHiddenField(self::FIELD_PAGESTATE,$this->getClientState());7996 $this->_inFormRender=true;7997 }7998 public function endFormRender($writer)7999 {8000 if($this->_focus)8001 {8002 if(($this->_focus instanceof TControl) && $this->_focus->getVisible(true))8003 $focus=$this->_focus->getClientID();8004 else8005 $focus=$this->_focus;8006 $this->getClientScript()->registerFocusControl($focus);8007 }8008 else if($this->_postData && ($lastFocus=$this->_postData->itemAt(self::FIELD_LASTFOCUS))!==null)8009 $this->getClientScript()->registerFocusControl($lastFocus);8010 $this->_inFormRender=false;8011 }8012 public function setFocus($value)8013 {8014 $this->_focus=$value;8015 }8016 public function getClientSupportsJavaScript()8017 {8018 return $this->_enableJavaScript;8019 }8020 public function setClientSupportsJavaScript($value)8021 {8022 $this->_enableJavaScript=TPropertyValue::ensureBoolean($value);8023 }8024 public function getHead()8025 {8026 return $this->_head;8027 }8028 public function setHead(THead $value)8029 {8030 if($this->_head)8031 throw new TInvalidOperationException('page_head_duplicated');8032 $this->_head=$value;8033 if($this->_title!==null)8034 {8035 $this->_head->setTitle($this->_title);8036 $this->_title=null;8037 }8038 }8039 public function getTitle()8040 {8041 if($this->_head)8042 return $this->_head->getTitle();8043 else8044 return $this->_title===null ? '' : $this->_title;8045 }8046 public function setTitle($value)8047 {8048 if($this->_head)8049 $this->_head->setTitle($value);8050 else8051 $this->_title=$value;8052 }8053 public function getClientState()8054 {8055 return $this->_clientState;8056 }8057 public function setClientState($state)8058 {8059 $this->_clientState=$state;8060 }8061 public function getRequestClientState()8062 {8063 return $this->getRequest()->itemAt(self::FIELD_PAGESTATE);8064 }8065 public function getStatePersisterClass()8066 {8067 return $this->_statePersisterClass;8068 }8069 public function setStatePersisterClass($value)8070 {8071 $this->_statePersisterClass=$value;8072 }8073 public function getStatePersister()8074 {8075 if($this->_statePersister===null)8076 {8077 $this->_statePersister=Prado::createComponent($this->_statePersisterClass);8078 if(!($this->_statePersister instanceof IPageStatePersister))8079 throw new TInvalidDataTypeException('page_statepersister_invalid');8080 $this->_statePersister->setPage($this);8081 }8082 return $this->_statePersister;8083 }8084 public function getEnableStateValidation()8085 {8086 return $this->_enableStateValidation;8087 }8088 public function setEnableStateValidation($value)8089 {8090 $this->_enableStateValidation=TPropertyValue::ensureBoolean($value);8091 }8092 public function getEnableStateEncryption()8093 {8094 return $this->_enableStateEncryption;8095 }8096 public function setEnableStateEncryption($value)8097 {8098 $this->_enableStateEncryption=TPropertyValue::ensureBoolean($value);8099 }8100 public function getEnableStateCompression()8101 {8102 return $this->_enableStateCompression;8103 }8104 public function setEnableStateCompression($value)8105 {8106 $this->_enableStateCompression=TPropertyValue::ensureBoolean($value);8107 }8108 public function getPagePath()8109 {8110 return $this->_pagePath;8111 }8112 public function setPagePath($value)8113 {8114 $this->_pagePath=$value;8115 }8116 public function registerCachingAction($context,$funcName,$funcParams)8117 {8118 if($this->_cachingStack)8119 {8120 foreach($this->_cachingStack as $cache)8121 $cache->registerAction($context,$funcName,$funcParams);8122 }8123 }8124 public function getCachingStack()8125 {8126 if(!$this->_cachingStack)8127 $this->_cachingStack=new TStack;8128 return $this->_cachingStack;8129 }8130 public function flushWriter()8131 {8132 if ($this->_writer)8133 $this->Response->write($this->_writer->flush());8134 }8135}8136interface IPageStatePersister8137{8138 public function getPage();8139 public function setPage(TPage $page);8140 public function save($state);8141 public function load();8142}8143class TPageStateFormatter8144{8145 public static function serialize($page,$data)8146 {8147 $sm=$page->getApplication()->getSecurityManager();8148 if($page->getEnableStateValidation())8149 $str=$sm->hashData(serialize($data));8150 else8151 $str=serialize($data);8152 if($page->getEnableStateCompression() && extension_loaded('zlib'))8153 $str=gzcompress($str);8154 if($page->getEnableStateEncryption())8155 $str=$sm->encrypt($str);8156 return base64_encode($str);8157 }8158 public static function unserialize($page,$data)8159 {8160 $str=base64_decode($data);8161 if($str==='')8162 return null;8163 if($str!==false)8164 {8165 $sm=$page->getApplication()->getSecurityManager();8166 if($page->getEnableStateEncryption())8167 $str=$sm->decrypt($str);8168 if($page->getEnableStateCompression() && extension_loaded('zlib'))8169 $str=@gzuncompress($str);8170 if($page->getEnableStateValidation())8171 {8172 if(($str=$sm->validateData($str))!==false)8173 return unserialize($str);8174 }8175 else8176 return unserialize($str);8177 }8178 return null;8179 }8180}8181class TOutputCache extends TControl implements INamingContainer8182{8183 const CACHE_ID_PREFIX='prado:outputcache';8184 private $_cacheModuleID='';8185 private $_dataCached=false;8186 private $_cacheAvailable=false;8187 private $_cacheChecked=false;8188 private $_cacheKey=null;8189 private $_duration=60;8190 private $_cache=null;8191 private $_contents;8192 private $_state;8193 private $_actions=array();8194 private $_varyByParam='';8195 private $_keyPrefix='';8196 private $_varyBySession=false;8197 private $_cachePostBack=false;8198 private $_cacheTime=0;8199 public function getAllowChildControls()8200 {8201 $this->determineCacheability();8202 return !$this->_dataCached;8203 }8204 private function determineCacheability()8205 {8206 if(!$this->_cacheChecked)8207 {8208 $this->_cacheChecked=true;8209 if($this->_duration>0 && ($this->_cachePostBack || !$this->getPage()->getIsPostBack()))8210 {8211 if($this->_cacheModuleID!=='')8212 {8213 $this->_cache=$this->getApplication()->getModule($this->_cacheModuleID);8214 if(!($this->_cache instanceof ICache))8215 throw new TConfigurationException('outputcache_cachemoduleid_invalid',$this->_cacheModuleID);8216 }8217 else8218 $this->_cache=$this->getApplication()->getCache();8219 if($this->_cache!==null)8220 {8221 $this->_cacheAvailable=true;8222 $data=$this->_cache->get($this->getCacheKey());8223 if(is_array($data))8224 {8225 $param=new TOutputCacheCheckDependencyEventParameter;8226 $param->setCacheTime(isset($data[3])?$data[3]:0);8227 $this->onCheckDependency($param);8228 $this->_dataCached=$param->getIsValid();8229 }8230 else8231 $this->_dataCached=false;8232 if($this->_dataCached)8233 list($this->_contents,$this->_state,$this->_actions,$this->_cacheTime)=$data;8234 }8235 }8236 }8237 }8238 protected function initRecursive($namingContainer=null)8239 {8240 if($this->_cacheAvailable && !$this->_dataCached)8241 {8242 $stack=$this->getPage()->getCachingStack();8243 $stack->push($this);8244 parent::initRecursive($namingContainer);8245 $stack->pop();8246 }8247 else8248 parent::initRecursive($namingContainer);8249 }8250 protected function loadRecursive()8251 {8252 if($this->_cacheAvailable && !$this->_dataCached)8253 {8254 $stack=$this->getPage()->getCachingStack();8255 $stack->push($this);8256 parent::loadRecursive();8257 $stack->pop();8258 }8259 else8260 {8261 if($this->_dataCached)8262 $this->performActions();8263 parent::loadRecursive();8264 }8265 }8266 private function performActions()8267 {8268 $page=$this->getPage();8269 $cs=$page->getClientScript();8270 foreach($this->_actions as $action)8271 {8272 if($action[0]==='Page.ClientScript')8273 call_user_func_array(array($cs,$action[1]),$action[2]);8274 else if($action[0]==='Page')8275 call_user_func_array(array($page,$action[1]),$action[2]);8276 else8277 call_user_func_array(array($this->getSubProperty($action[0]),$action[1]),$action[2]);8278 }8279 }8280 protected function preRenderRecursive()8281 {8282 if($this->_cacheAvailable && !$this->_dataCached)8283 {8284 $stack=$this->getPage()->getCachingStack();8285 $stack->push($this);8286 parent::preRenderRecursive();8287 $stack->pop();8288 }8289 else8290 parent::preRenderRecursive();8291 }8292 protected function loadStateRecursive(&$state,$needViewState=true)8293 {8294 $st=unserialize($state);8295 parent::loadStateRecursive($st,$needViewState);8296 }8297 protected function &saveStateRecursive($needViewState=true)8298 {8299 if($this->_dataCached)8300 return $this->_state;8301 else8302 {8303 $st=parent::saveStateRecursive($needViewState);8304 $this->_state=serialize($st);8305 return $this->_state;8306 }8307 }8308 public function registerAction($context,$funcName,$funcParams)8309 {8310 $this->_actions[]=array($context,$funcName,$funcParams);8311 }8312 public function getCacheKey()8313 {8314 if($this->_cacheKey===null)8315 $this->_cacheKey=$this->calculateCacheKey();8316 return $this->_cacheKey;8317 }8318 protected function calculateCacheKey()8319 {8320 $key=$this->getBaseCacheKey();8321 if($this->_varyBySession)8322 $key.=$this->getSession()->getSessionID();8323 if($this->_varyByParam!=='')8324 {8325 $params=array();8326 $request=$this->getRequest();8327 foreach(explode(',',$this->_varyByParam) as $name)8328 {8329 $name=trim($name);8330 $params[$name]=$request->itemAt($name);8331 }8332 $key.=serialize($params);8333 }8334 $param=new TOutputCacheCalculateKeyEventParameter;8335 $this->onCalculateKey($param);8336 $key.=$param->getCacheKey();8337 return $key;8338 }8339 protected function getBaseCacheKey()8340 {8341 return self::CACHE_ID_PREFIX.$this->_keyPrefix.$this->getPage()->getPagePath().$this->getUniqueID();8342 }8343 public function getCacheModuleID()8344 {8345 return $this->_cacheModuleID;8346 }8347 public function setCacheModuleID($value)8348 {8349 $this->_cacheModuleID=$value;8350 }8351 public function setCacheKeyPrefix($value)8352 {8353 $this->_keyPrefix=$value;8354 }8355 public function getCacheTime()8356 {8357 return $this->_cacheTime;8358 }8359 protected function getCacheDependency()8360 {8361 return null;8362 }8363 public function getContentCached()8364 {8365 return $this->_dataCached;8366 }8367 public function getDuration()8368 {8369 return $this->_duration;8370 }8371 public function setDuration($value)8372 {8373 if(($value=TPropertyValue::ensureInteger($value))<0)8374 throw new TInvalidDataValueException('outputcache_duration_invalid',get_class($this));8375 $this->_duration=$value;8376 }8377 public function getVaryByParam()8378 {8379 return $this->_varyByParam;8380 }8381 public function setVaryByParam($value)8382 {8383 $this->_varyByParam=trim($value);8384 }8385 public function getVaryBySession()8386 {8387 return $this->_varyBySession;8388 }8389 public function setVaryBySession($value)8390 {8391 $this->_varyBySession=TPropertyValue::ensureBoolean($value);8392 }8393 public function getCachingPostBack()8394 {8395 return $this->_cachePostBack;8396 }8397 public function setCachingPostBack($value)8398 {8399 $this->_cachePostBack=TPropertyValue::ensureBoolean($value);8400 }8401 public function onCheckDependency($param)8402 {8403 $this->raiseEvent('OnCheckDependency',$this,$param);8404 }8405 public function onCalculateKey($param)8406 {8407 $this->raiseEvent('OnCalculateKey',$this,$param);8408 }8409 public function render($writer)8410 {8411 if($this->_dataCached)8412 $writer->write($this->_contents);8413 else if($this->_cacheAvailable)8414 {8415 $textwriter = new TTextWriter();8416 $multiwriter = new TOutputCacheTextWriterMulti(array($writer->getWriter(),$textwriter));8417 $htmlWriter = Prado::createComponent($this->GetResponse()->getHtmlWriterType(), $multiwriter);8418 $stack=$this->getPage()->getCachingStack();8419 $stack->push($this);8420 parent::render($htmlWriter);8421 $stack->pop();8422 $content=$textwriter->flush();8423 $data=array($content,$this->_state,$this->_actions,time());8424 $this->_cache->set($this->getCacheKey(),$data,$this->getDuration(),$this->getCacheDependency());8425 }8426 else8427 parent::render($writer);8428 }8429}8430class TOutputCacheCheckDependencyEventParameter extends TEventParameter8431{8432 private $_isValid=true;8433 private $_cacheTime=0;8434 public function getIsValid()8435 {8436 return $this->_isValid;8437 }8438 public function setIsValid($value)8439 {8440 $this->_isValid=TPropertyValue::ensureBoolean($value);8441 }8442 public function getCacheTime()8443 {8444 return $this->_cacheTime;8445 }8446 public function setCacheTime($value)8447 {8448 $this->_cacheTime=TPropertyValue::ensureInteger($value);8449 }8450}8451class TOutputCacheCalculateKeyEventParameter extends TEventParameter8452{8453 private $_cacheKey='';8454 public function getCacheKey()8455 {8456 return $this->_cacheKey;8457 }8458 public function setCacheKey($value)8459 {8460 $this->_cacheKey=TPropertyValue::ensureString($value);8461 }8462}8463class TOutputCacheTextWriterMulti extends TTextWriter8464{8465 protected $_writers;8466 public function __construct(Array $writers)8467 {8468 $this->_writers = $writers;8469 }8470 public function write($s)8471 {8472 foreach($this->_writers as $writer)8473 $writer->write($s);8474 }8475 public function flush()8476 {8477 foreach($this->_writers as $writer)8478 $s = $writer->flush();8479 return $s;8480 }8481}8482class TTemplateManager extends TModule8483{8484 const TEMPLATE_FILE_EXT='.tpl';8485 const TEMPLATE_CACHE_PREFIX='prado:template:';8486 public function init($config)8487 {8488 $this->getService()->setTemplateManager($this);8489 }8490 public function getTemplateByClassName($className)8491 {8492 $class=new ReflectionClass($className);8493 $tplFile=dirname($class->getFileName()).DIRECTORY_SEPARATOR.$className.self::TEMPLATE_FILE_EXT;8494 return $this->getTemplateByFileName($tplFile);8495 }8496 public function getTemplateByFileName($fileName)8497 {8498 if(($fileName=$this->getLocalizedTemplate($fileName))!==null)8499 {8500 if(($cache=$this->getApplication()->getCache())===null)8501 return new TTemplate(file_get_contents($fileName),dirname($fileName),$fileName);8502 else8503 {8504 $array=$cache->get(self::TEMPLATE_CACHE_PREFIX.$fileName);8505 if(is_array($array))8506 {8507 list($template,$timestamps)=$array;8508 if($this->getApplication()->getMode()===TApplicationMode::Performance)8509 return $template;8510 $cacheValid=true;8511 foreach($timestamps as $tplFile=>$timestamp)8512 {8513 if(!is_file($tplFile) || filemtime($tplFile)>$timestamp)8514 {8515 $cacheValid=false;8516 break;8517 }8518 }8519 if($cacheValid)8520 return $template;8521 }8522 $template=new TTemplate(file_get_contents($fileName),dirname($fileName),$fileName);8523 $includedFiles=$template->getIncludedFiles();8524 $timestamps=array();8525 $timestamps[$fileName]=filemtime($fileName);8526 foreach($includedFiles as $includedFile)8527 $timestamps[$includedFile]=filemtime($includedFile);8528 $cache->set(self::TEMPLATE_CACHE_PREFIX.$fileName,array($template,$timestamps));8529 return $template;8530 }8531 }8532 else8533 return null;8534 }8535 protected function getLocalizedTemplate($filename)8536 {8537 if(($app=$this->getApplication()->getGlobalization(false))===null)8538 return is_file($filename)?$filename:null;8539 foreach($app->getLocalizedResource($filename) as $file)8540 {8541 if(($file=realpath($file))!==false && is_file($file))8542 return $file;8543 }8544 return null;8545 }8546}8547class TTemplate extends TApplicationComponent implements ITemplate8548{8549 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';8550 const CONFIG_DATABIND=0;8551 const CONFIG_EXPRESSION=1;8552 const CONFIG_ASSET=2;8553 const CONFIG_PARAMETER=3;8554 const CONFIG_LOCALIZATION=4;8555 const CONFIG_TEMPLATE=5;8556 private $_tpl=array();8557 private $_directive=array();8558 private $_contextPath;8559 private $_tplFile=null;8560 private $_startingLine=0;8561 private $_content;8562 private $_sourceTemplate=true;8563 private $_hashCode='';8564 private $_tplControl=null;8565 private $_includedFiles=array();8566 private $_includeAtLine=array();8567 private $_includeLines=array();8568 public function __construct($template,$contextPath,$tplFile=null,$startingLine=0,$sourceTemplate=true)8569 {8570 $this->_sourceTemplate=$sourceTemplate;8571 $this->_contextPath=$contextPath;8572 $this->_tplFile=$tplFile;8573 $this->_startingLine=$startingLine;8574 $this->_content=$template;8575 $this->_hashCode=md5($template);8576 $this->parse($template);8577 $this->_content=null; }8578 public function getTemplateFile()8579 {8580 return $this->_tplFile;8581 }8582 public function getIsSourceTemplate()8583 {8584 return $this->_sourceTemplate;8585 }8586 public function getContextPath()8587 {8588 return $this->_contextPath;8589 }8590 public function getDirective()8591 {8592 return $this->_directive;8593 }8594 public function getHashCode()8595 {8596 return $this->_hashCode;8597 }8598 public function &getItems()8599 {8600 return $this->_tpl;8601 }8602 public function instantiateIn($tplControl,$parentControl=null)8603 {8604 $this->_tplControl=$tplControl;8605 if($parentControl===null)8606 $parentControl=$tplControl;8607 if(($page=$tplControl->getPage())===null)8608 $page=$this->getService()->getRequestedPage();8609 $controls=array();8610 $directChildren=array();8611 foreach($this->_tpl as $key=>$object)8612 {8613 if($object[0]===-1)8614 $parent=$parentControl;8615 else if(isset($controls[$object[0]]))8616 $parent=$controls[$object[0]];8617 else8618 continue;8619 if(isset($object[2])) {8620 $component=Prado::createComponent($object[1]);8621 $properties=&$object[2];8622 if($component instanceof TControl)8623 {8624 if($component instanceof TOutputCache)8625 $component->setCacheKeyPrefix($this->_hashCode.$key);8626 $component->setTemplateControl($tplControl);8627 if(isset($properties['id']))8628 {8629 if(is_array($properties['id']))8630 $properties['id']=$component->evaluateExpression($properties['id'][1]);8631 $tplControl->registerObject($properties['id'],$component);8632 }8633 if(isset($properties['skinid']))8634 {8635 if(is_array($properties['skinid']))8636 $component->setSkinID($component->evaluateExpression($properties['skinid'][1]));8637 else8638 $component->setSkinID($properties['skinid']);8639 unset($properties['skinid']);8640 }8641 $component->trackViewState(false);8642 $component->applyStyleSheetSkin($page);8643 foreach($properties as $name=>$value)8644 $this->configureControl($component,$name,$value);8645 $component->trackViewState(true);8646 if($parent===$parentControl)8647 $directChildren[]=$component;8648 else8649 $component->createdOnTemplate($parent);8650 if($component->getAllowChildControls())8651 $controls[$key]=$component;8652 }8653 else if($component instanceof TComponent)8654 {8655 $controls[$key]=$component;8656 if(isset($properties['id']))8657 {8658 if(is_array($properties['id']))8659 $properties['id']=$component->evaluateExpression($properties['id'][1]);8660 $tplControl->registerObject($properties['id'],$component);8661 if(!$component->hasProperty('id'))8662 unset($properties['id']);8663 }8664 foreach($properties as $name=>$value)8665 $this->configureComponent($component,$name,$value);8666 if($parent===$parentControl)8667 $directChildren[]=$component;8668 else8669 $component->createdOnTemplate($parent);8670 }8671 }8672 else8673 {8674 if($object[1] instanceof TCompositeLiteral)8675 {8676 $o=clone $object[1];8677 $o->setContainer($tplControl);8678 if($parent===$parentControl)8679 $directChildren[]=$o;8680 else8681 $parent->addParsedObject($o);8682 }8683 else8684 {8685 if($parent===$parentControl)8686 $directChildren[]=$object[1];8687 else8688 $parent->addParsedObject($object[1]);8689 }8690 }8691 }8692 foreach($directChildren as $control)8693 {8694 if($control instanceof TComponent)8695 $control->createdOnTemplate($parentControl);8696 else8697 $parentControl->addParsedObject($control);8698 }8699 }8700 protected function configureControl($control,$name,$value)8701 {8702 if(strncasecmp($name,'on',2)===0) $this->configureEvent($control,$name,$value,$control);8703 else if(($pos=strrpos($name,'.'))===false) $this->configureProperty($control,$name,$value);8704 else $this->configureSubProperty($control,$name,$value);8705 }8706 protected function configureComponent($component,$name,$value)8707 {8708 if(strpos($name,'.')===false) $this->configureProperty($component,$name,$value);8709 else $this->configureSubProperty($component,$name,$value);8710 }8711 protected function configureEvent($control,$name,$value,$contextControl)8712 {8713 if(strpos($value,'.')===false)8714 $control->attachEventHandler($name,array($contextControl,'TemplateControl.'.$value));8715 else8716 $control->attachEventHandler($name,array($contextControl,$value));8717 }8718 protected function configureProperty($component,$name,$value)8719 {8720 if(is_array($value))8721 {8722 switch($value[0])8723 {8724 case self::CONFIG_DATABIND:8725 $component->bindProperty($name,$value[1]);8726 break;8727 case self::CONFIG_EXPRESSION:8728 if($component instanceof TControl)8729 $component->autoBindProperty($name,$value[1]);8730 else8731 {8732 $setter='set'.$name;8733 $component->$setter($this->_tplControl->evaluateExpression($value[1]));8734 }8735 break;8736 case self::CONFIG_TEMPLATE:8737 $setter='set'.$name;8738 $component->$setter($value[1]);8739 break;8740 case self::CONFIG_ASSET: $setter='set'.$name;8741 $url=$this->publishFilePath($this->_contextPath.DIRECTORY_SEPARATOR.$value[1]);8742 $component->$setter($url);8743 break;8744 case self::CONFIG_PARAMETER: $setter='set'.$name;8745 $component->$setter($this->getApplication()->getParameters()->itemAt($value[1]));8746 break;8747 case self::CONFIG_LOCALIZATION:8748 $setter='set'.$name;8749 $component->$setter(Prado::localize($value[1]));8750 break;8751 default: throw new TConfigurationException('template_tag_unexpected',$name,$value[1]);8752 break;8753 }8754 }8755 else8756 {8757 if (substr($name,0,2)=='js')8758 if ($value and !($value instanceof TJavaScriptLiteral))8759 $value = new TJavaScriptLiteral($value);8760 $setter='set'.$name;8761 $component->$setter($value);8762 }8763 }8764 protected function configureSubProperty($component,$name,$value)8765 {8766 if(is_array($value))8767 {8768 switch($value[0])8769 {8770 case self::CONFIG_DATABIND: $component->bindProperty($name,$value[1]);8771 break;8772 case self::CONFIG_EXPRESSION: if($component instanceof TControl)8773 $component->autoBindProperty($name,$value[1]);8774 else8775 $component->setSubProperty($name,$this->_tplControl->evaluateExpression($value[1]));8776 break;8777 case self::CONFIG_TEMPLATE:8778 $component->setSubProperty($name,$value[1]);8779 break;8780 case self::CONFIG_ASSET: $url=$this->publishFilePath($this->_contextPath.DIRECTORY_SEPARATOR.$value[1]);8781 $component->setSubProperty($name,$url);8782 break;8783 case self::CONFIG_PARAMETER: $component->setSubProperty($name,$this->getApplication()->getParameters()->itemAt($value[1]));8784 break;8785 case self::CONFIG_LOCALIZATION:8786 $component->setSubProperty($name,Prado::localize($value[1]));8787 break;8788 default: throw new TConfigurationException('template_tag_unexpected',$name,$value[1]);8789 break;8790 }8791 }8792 else8793 $component->setSubProperty($name,$value);8794 }8795 protected function parse($input)8796 {8797 $input=$this->preprocess($input);8798 $tpl=&$this->_tpl;8799 $n=preg_match_all(self::REGEX_RULES,$input,$matches,PREG_SET_ORDER|PREG_OFFSET_CAPTURE);8800 $expectPropEnd=false;8801 $textStart=0;8802 $stack=array();8803 $container=-1;8804 $matchEnd=0;8805 $c=0;8806 $this->_directive=null;8807 try8808 {8809 for($i=0;$i<$n;++$i)8810 {8811 $match=&$matches[$i];8812 $str=$match[0][0];8813 $matchStart=$match[0][1];8814 $matchEnd=$matchStart+strlen($str)-1;8815 if(strpos($str,'<com:')===0) {8816 if($expectPropEnd)8817 continue;8818 if($matchStart>$textStart)8819 $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));8820 $textStart=$matchEnd+1;8821 $type=$match[1][0];8822 $attributes=$this->parseAttributes($match[2][0],$match[2][1]);8823 $this->validateAttributes($type,$attributes);8824 $tpl[$c++]=array($container,$type,$attributes);8825 if($str[strlen($str)-2]!=='/') {8826 $stack[] = $type;8827 $container=$c-1;8828 }8829 }8830 else if(strpos($str,'</com:')===0) {8831 if($expectPropEnd)8832 continue;8833 if($matchStart>$textStart)8834 $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));8835 $textStart=$matchEnd+1;8836 $type=$match[1][0];8837 if(empty($stack))8838 throw new TConfigurationException('template_closingtag_unexpected',"</com:$type>");8839 $name=array_pop($stack);8840 if($name!==$type)8841 {8842 $tag=$name[0]==='@' ? '</prop:'.substr($name,1).'>' : "</com:$name>";8843 throw new TConfigurationException('template_closingtag_expected',$tag);8844 }8845 $container=$tpl[$container][0];8846 }8847 else if(strpos($str,'<%@')===0) {8848 if($expectPropEnd)8849 continue;8850 if($matchStart>$textStart)8851 $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));8852 $textStart=$matchEnd+1;8853 if(isset($tpl[0]) || $this->_directive!==null)8854 throw new TConfigurationException('template_directive_nonunique');8855 $this->_directive=$this->parseAttributes($match[4][0],$match[4][1]);8856 }8857 else if(strpos($str,'<%')===0) {8858 if($expectPropEnd)8859 continue;8860 if($matchStart>$textStart)8861 $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));8862 $textStart=$matchEnd+1;8863 $literal=trim($match[5][0]);8864 if($str[2]==='=') $tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_EXPRESSION,$literal));8865 else if($str[2]==='%') $tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_STATEMENTS,$literal));8866 else if($str[2]==='#')8867 $tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_DATABINDING,$literal));8868 else if($str[2]==='$')8869 $tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_EXPRESSION,"\$this->getApplication()->getParameters()->itemAt('$literal')"));8870 else if($str[2]==='~')8871 $tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_EXPRESSION,"\$this->publishFilePath('$this->_contextPath/$literal')"));8872 else if($str[2]==='/')8873 $tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_EXPRESSION,"rtrim(dirname(\$this->getApplication()->getRequest()->getApplicationUrl()), '\/').'/$literal'"));8874 else if($str[2]==='[')8875 {8876 $literal=strtr(trim(substr($literal,0,strlen($literal)-1)),array("'"=>"\'","\\"=>"\\\\"));8877 $tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_EXPRESSION,"Prado::localize('$literal')"));8878 }8879 }8880 else if(strpos($str,'<prop:')===0) {8881 if(strrpos($str,'/>')===strlen($str)-2) {8882 if($expectPropEnd)8883 continue;8884 if($matchStart>$textStart)8885 $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));8886 $textStart=$matchEnd+1;8887 $prop=strtolower($match[6][0]);8888 $attrs=$this->parseAttributes($match[7][0],$match[7][1]);8889 $attributes=array();8890 foreach($attrs as $name=>$value)8891 $attributes[$prop.'.'.$name]=$value;8892 $type=$tpl[$container][1];8893 $this->validateAttributes($type,$attributes);8894 foreach($attributes as $name=>$value)8895 {8896 if(isset($tpl[$container][2][$name]))8897 throw new TConfigurationException('template_property_duplicated',$name);8898 $tpl[$container][2][$name]=$value;8899 }8900 }8901 else {8902 $prop=strtolower($match[3][0]);8903 $stack[] = '@'.$prop;8904 if(!$expectPropEnd)8905 {8906 if($matchStart>$textStart)8907 $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));8908 $textStart=$matchEnd+1;8909 $expectPropEnd=true;8910 }8911 }8912 }8913 else if(strpos($str,'</prop:')===0) {8914 $prop=strtolower($match[3][0]);8915 if(empty($stack))8916 throw new TConfigurationException('template_closingtag_unexpected',"</prop:$prop>");8917 $name=array_pop($stack);8918 if($name!=='@'.$prop)8919 {8920 $tag=$name[0]==='@' ? '</prop:'.substr($name,1).'>' : "</com:$name>";8921 throw new TConfigurationException('template_closingtag_expected',$tag);8922 }8923 if(($last=count($stack))<1 || $stack[$last-1][0]!=='@')8924 {8925 if($matchStart>$textStart)8926 {8927 $value=substr($input,$textStart,$matchStart-$textStart);8928 if(substr($prop,-8,8)==='template')8929 $value=$this->parseTemplateProperty($value,$textStart);8930 else8931 $value=$this->parseAttribute($value);8932 if($container>=0)8933 {8934 $type=$tpl[$container][1];8935 $this->validateAttributes($type,array($prop=>$value));8936 if(isset($tpl[$container][2][$prop]))8937 throw new TConfigurationException('template_property_duplicated',$prop);8938 $tpl[$container][2][$prop]=$value;8939 }8940 else $this->_directive[$prop]=$value;8941 $textStart=$matchEnd+1;8942 }8943 $expectPropEnd=false;8944 }8945 }8946 else if(strpos($str,'<!--')===0) {8947 if($expectPropEnd)8948 throw new TConfigurationException('template_comments_forbidden');8949 if($matchStart>$textStart)8950 $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));8951 $textStart=$matchEnd+1;8952 }8953 else8954 throw new TConfigurationException('template_matching_unexpected',$match);8955 }8956 if(!empty($stack))8957 {8958 $name=array_pop($stack);8959 $tag=$name[0]==='@' ? '</prop:'.substr($name,1).'>' : "</com:$name>";8960 throw new TConfigurationException('template_closingtag_expected',$tag);8961 }8962 if($textStart<strlen($input))8963 $tpl[$c++]=array($container,substr($input,$textStart));8964 }8965 catch(Exception $e)8966 {8967 if(($e instanceof TException) && ($e instanceof TTemplateException))8968 throw $e;8969 if($matchEnd===0)8970 $line=$this->_startingLine+1;8971 else8972 $line=$this->_startingLine+count(explode("\n",substr($input,0,$matchEnd+1)));8973 $this->handleException($e,$line,$input);8974 }8975 if($this->_directive===null)8976 $this->_directive=array();8977 $objects=array();8978 $parent=null;8979 $merged=array();8980 foreach($tpl as $id=>$object)8981 {8982 if(isset($object[2]) || $object[0]!==$parent)8983 {8984 if($parent!==null)8985 {8986 if(count($merged[1])===1 && is_string($merged[1][0]))8987 $objects[$id-1]=array($merged[0],$merged[1][0]);8988 else8989 $objects[$id-1]=array($merged[0],new TCompositeLiteral($merged[1]));8990 }8991 if(isset($object[2]))8992 {8993 $parent=null;8994 $objects[$id]=$object;8995 }8996 else8997 {8998 $parent=$object[0];8999 $merged=array($parent,array($object[1]));9000 }9001 }9002 else9003 $merged[1][]=$object[1];9004 }9005 if($parent!==null)9006 {9007 if(count($merged[1])===1 && is_string($merged[1][0]))9008 $objects[$id]=array($merged[0],$merged[1][0]);9009 else9010 $objects[$id]=array($merged[0],new TCompositeLiteral($merged[1]));9011 }9012 $tpl=$objects;9013 return $objects;9014 }9015 protected function parseAttributes($str,$offset)9016 {9017 if($str==='')9018 return array();9019 $pattern='/([\w\.\-]+)\s*=\s*(\'.*?\'|".*?"|<%.*?%>)/msS';9020 $attributes=array();9021 $n=preg_match_all($pattern,$str,$matches,PREG_SET_ORDER|PREG_OFFSET_CAPTURE);9022 for($i=0;$i<$n;++$i)9023 {9024 $match=&$matches[$i];9025 $name=strtolower($match[1][0]);9026 if(isset($attributes[$name]))9027 throw new TConfigurationException('template_property_duplicated',$name);9028 $value=$match[2][0];9029 if(substr($name,-8,8)==='template')9030 {9031 if($value[0]==='\'' || $value[0]==='"')9032 $attributes[$name]=$this->parseTemplateProperty(substr($value,1,strlen($value)-2),$match[2][1]+1);9033 else9034 $attributes[$name]=$this->parseTemplateProperty($value,$match[2][1]);9035 }9036 else9037 {9038 if($value[0]==='\'' || $value[0]==='"')9039 $attributes[$name]=$this->parseAttribute(substr($value,1,strlen($value)-2));9040 else9041 $attributes[$name]=$this->parseAttribute($value);9042 }9043 }9044 return $attributes;9045 }9046 protected function parseTemplateProperty($content,$offset)9047 {9048 $line=$this->_startingLine+count(explode("\n",substr($this->_content,0,$offset)))-1;9049 return array(self::CONFIG_TEMPLATE,new TTemplate($content,$this->_contextPath,$this->_tplFile,$line,false));9050 }9051 protected function parseAttribute($value)9052 {9053 if(($n=preg_match_all('/<%[#=].*?%>/msS',$value,$matches,PREG_OFFSET_CAPTURE))>0)9054 {9055 $isDataBind=false;9056 $textStart=0;9057 $expr='';9058 for($i=0;$i<$n;++$i)9059 {9060 $match=$matches[0][$i];9061 $token=$match[0];9062 $offset=$match[1];9063 $length=strlen($token);9064 if($token[2]==='#')9065 $isDataBind=true;9066 if($offset>$textStart)9067 $expr.=".'".strtr(substr($value,$textStart,$offset-$textStart),array("'"=>"\\'","\\"=>"\\\\"))."'";9068 $expr.='.('.substr($token,3,$length-5).')';9069 $textStart=$offset+$length;9070 }9071 $length=strlen($value);9072 if($length>$textStart)9073 $expr.=".'".strtr(substr($value,$textStart,$length-$textStart),array("'"=>"\\'","\\"=>"\\\\"))."'";9074 if($isDataBind)9075 return array(self::CONFIG_DATABIND,ltrim($expr,'.'));9076 else9077 return array(self::CONFIG_EXPRESSION,ltrim($expr,'.'));9078 }9079 else if(preg_match('/\\s*(<%~.*?%>|<%\\$.*?%>|<%\\[.*?\\]%>|<%\/.*?%>)\\s*/msS',$value,$matches) && $matches[0]===$value)9080 {9081 $value=$matches[1];9082 if($value[2]==='~')9083 return array(self::CONFIG_ASSET,trim(substr($value,3,strlen($value)-5)));9084 elseif($value[2]==='[')9085 return array(self::CONFIG_LOCALIZATION,trim(substr($value,3,strlen($value)-6)));9086 elseif($value[2]==='$')9087 return array(self::CONFIG_PARAMETER,trim(substr($value,3,strlen($value)-5)));9088 elseif($value[2]==='/') {9089 $literal = trim(substr($value,3,strlen($value)-5));9090 return array(self::CONFIG_EXPRESSION,"rtrim(dirname(\$this->getApplication()->getRequest()->getApplicationUrl()), '\/').'/$literal'");9091 }9092 }9093 else9094 return $value;9095 }9096 protected function validateAttributes($type,$attributes)9097 {9098 Prado::using($type);9099 if(($pos=strrpos($type,'.'))!==false)9100 $className=substr($type,$pos+1);9101 else9102 $className=$type;9103 $class=new ReflectionClass($className);9104 if(is_subclass_of($className,'TControl') || $className==='TControl')9105 {9106 foreach($attributes as $name=>$att)9107 {9108 if(($pos=strpos($name,'.'))!==false)9109 {9110 $subname=substr($name,0,$pos);9111 if(!$class->hasMethod('get'.$subname))9112 throw new TConfigurationException('template_property_unknown',$type,$subname);9113 }9114 else if(strncasecmp($name,'on',2)===0)9115 {9116 if(!$class->hasMethod($name))9117 throw new TConfigurationException('template_event_unknown',$type,$name);9118 else if(!is_string($att))9119 throw new TConfigurationException('template_eventhandler_invalid',$type,$name);9120 }9121 else9122 {9123 if (! ($class->hasMethod('set'.$name) || $class->hasMethod('setjs'.$name) || $this->isClassBehaviorMethod($class,'set'.$name)) )9124 {9125 if ($class->hasMethod('get'.$name) || $class->hasMethod('getjs'.$name))9126 throw new TConfigurationException('template_property_readonly',$type,$name);9127 else9128 throw new TConfigurationException('template_property_unknown',$type,$name);9129 }9130 else if(is_array($att) && $att[0]!==self::CONFIG_EXPRESSION)9131 {9132 if(strcasecmp($name,'id')===0)9133 throw new TConfigurationException('template_controlid_invalid',$type);9134 else if(strcasecmp($name,'skinid')===0)9135 throw new TConfigurationException('template_controlskinid_invalid',$type);9136 }9137 }9138 }9139 }9140 else if(is_subclass_of($className,'TComponent') || $className==='TComponent')9141 {9142 foreach($attributes as $name=>$att)9143 {9144 if(is_array($att) && ($att[0]===self::CONFIG_DATABIND))9145 throw new TConfigurationException('template_databind_forbidden',$type,$name);9146 if(($pos=strpos($name,'.'))!==false)9147 {9148 $subname=substr($name,0,$pos);9149 if(!$class->hasMethod('get'.$subname))9150 throw new TConfigurationException('template_property_unknown',$type,$subname);9151 }9152 else if(strncasecmp($name,'on',2)===0)9153 throw new TConfigurationException('template_event_forbidden',$type,$name);9154 else9155 {9156 if(strcasecmp($name,'id')!==0 && !($class->hasMethod('set'.$name) || $this->isClassBehaviorMethod($class,'set'.$name)))9157 {9158 if($class->hasMethod('get'.$name))9159 throw new TConfigurationException('template_property_readonly',$type,$name);9160 else9161 throw new TConfigurationException('template_property_unknown',$type,$name);9162 }9163 }9164 }9165 }9166 else9167 throw new TConfigurationException('template_component_required',$type);9168 }9169 public function getIncludedFiles()9170 {9171 return $this->_includedFiles;9172 }9173 protected function handleException($e,$line,$input=null)9174 {9175 $srcFile=$this->_tplFile;9176 if(($n=count($this->_includedFiles))>0) {9177 for($i=$n-1;$i>=0;--$i)9178 {9179 if($this->_includeAtLine[$i]<=$line)9180 {9181 if($line<$this->_includeAtLine[$i]+$this->_includeLines[$i])9182 {9183 $line=$line-$this->_includeAtLine[$i]+1;9184 $srcFile=$this->_includedFiles[$i];9185 break;9186 }9187 else9188 $line=$line-$this->_includeLines[$i]+1;9189 }9190 }9191 }9192 $exception=new TTemplateException('template_format_invalid',$e->getMessage());9193 $exception->setLineNumber($line);9194 if(!empty($srcFile))9195 $exception->setTemplateFile($srcFile);9196 else9197 $exception->setTemplateSource($input);9198 throw $exception;9199 }9200 protected function preprocess($input)9201 {9202 if($n=preg_match_all('/<%include(.*?)%>/',$input,$matches,PREG_SET_ORDER|PREG_OFFSET_CAPTURE))9203 {9204 for($i=0;$i<$n;++$i)9205 {9206 $filePath=Prado::getPathOfNamespace(trim($matches[$i][1][0]),TTemplateManager::TEMPLATE_FILE_EXT);9207 if($filePath!==null && is_file($filePath))9208 $this->_includedFiles[]=$filePath;9209 else9210 {9211 $errorLine=count(explode("\n",substr($input,0,$matches[$i][0][1]+1)));9212 $this->handleException(new TConfigurationException('template_include_invalid',trim($matches[$i][1][0])),$errorLine,$input);9213 }9214 }9215 $base=0;9216 for($i=0;$i<$n;++$i)9217 {9218 $ext=file_get_contents($this->_includedFiles[$i]);9219 $length=strlen($matches[$i][0][0]);9220 $offset=$base+$matches[$i][0][1];9221 $this->_includeAtLine[$i]=count(explode("\n",substr($input,0,$offset)));9222 $this->_includeLines[$i]=count(explode("\n",$ext));9223 $input=substr_replace($input,$ext,$offset,$length);9224 $base+=strlen($ext)-$length;9225 }9226 }9227 return $input;9228 }9229 protected function isClassBehaviorMethod(ReflectionClass $class,$method)9230 {9231 $component=new ReflectionClass('TComponent');9232 $behaviors=$component->getStaticProperties();9233 if(!isset($behaviors['_um']))9234 return false;9235 foreach($behaviors['_um'] as $name=>$list)9236 {9237 if(strtolower($class->getShortName())!==$name && !$class->isSubclassOf($name)) continue;9238 foreach($list as $param)9239 {9240 if(method_exists($param->getBehavior(),$method))9241 return true;9242 }9243 }9244 return false;9245 }9246}9247class TThemeManager extends TModule9248{9249 const DEFAULT_BASEPATH='themes';9250 const DEFAULT_THEMECLASS = 'TTheme';9251 private $_themeClass=self::DEFAULT_THEMECLASS;9252 private $_initialized=false;9253 private $_basePath=null;9254 private $_baseUrl=null;9255 public function init($config)9256 {9257 $this->_initialized=true;9258 $service=$this->getService();9259 if($service instanceof TPageService)9260 $service->setThemeManager($this);9261 else9262 throw new TConfigurationException('thememanager_service_unavailable');9263 }9264 public function getTheme($name)9265 {9266 $themePath=$this->getBasePath().DIRECTORY_SEPARATOR.$name;9267 $themeUrl=rtrim($this->getBaseUrl(),'/').'/'.$name;9268 return Prado::createComponent($this->getThemeClass(), $themePath, $themeUrl);9269 }9270 public function setThemeClass($class) {9271 $this->_themeClass = $class===null ? self::DEFAULT_THEMECLASS : (string)$class;9272 }9273 public function getThemeClass() {9274 return $this->_themeClass;9275 }9276 public function getAvailableThemes()9277 {9278 $themes=array();9279 $basePath=$this->getBasePath();9280 $folder=@opendir($basePath);9281 while($file=@readdir($folder))9282 {9283 if($file!=='.' && $file!=='..' && $file!=='.svn' && is_dir($basePath.DIRECTORY_SEPARATOR.$file))9284 $themes[]=$file;9285 }9286 closedir($folder);9287 return $themes;9288 }9289 public function getBasePath()9290 {9291 if($this->_basePath===null)9292 {9293 $this->_basePath=dirname($this->getRequest()->getApplicationFilePath()).DIRECTORY_SEPARATOR.self::DEFAULT_BASEPATH;9294 if(($basePath=realpath($this->_basePath))===false || !is_dir($basePath))9295 throw new TConfigurationException('thememanager_basepath_invalid2',$this->_basePath);9296 $this->_basePath=$basePath;9297 }9298 return $this->_basePath;9299 }9300 public function setBasePath($value)9301 {9302 if($this->_initialized)9303 throw new TInvalidOperationException('thememanager_basepath_unchangeable');9304 else9305 {9306 $this->_basePath=Prado::getPathOfNamespace($value);9307 if($this->_basePath===null || !is_dir($this->_basePath))9308 throw new TInvalidDataValueException('thememanager_basepath_invalid',$value);9309 }9310 }9311 public function getBaseUrl()9312 {9313 if($this->_baseUrl===null)9314 {9315 $appPath=dirname($this->getRequest()->getApplicationFilePath());9316 $basePath=$this->getBasePath();9317 if(strpos($basePath,$appPath)===false)9318 throw new TConfigurationException('thememanager_baseurl_required');9319 $appUrl=rtrim(dirname($this->getRequest()->getApplicationUrl()),'/\\');9320 $this->_baseUrl=$appUrl.strtr(substr($basePath,strlen($appPath)),'\\','/');9321 }9322 return $this->_baseUrl;9323 }9324 public function setBaseUrl($value)9325 {9326 $this->_baseUrl=rtrim($value,'/');9327 }9328}9329class TTheme extends TApplicationComponent implements ITheme9330{9331 const THEME_CACHE_PREFIX='prado:theme:';9332 const SKIN_FILE_EXT='.skin';9333 private $_themePath;9334 private $_themeUrl;9335 private $_skins=null;9336 private $_name='';9337 private $_cssFiles=array();9338 private $_jsFiles=array();9339 public function __construct($themePath,$themeUrl)9340 {9341 $this->_themeUrl=$themeUrl;9342 $this->_themePath=realpath($themePath);9343 $this->_name=basename($themePath);9344 $cacheValid=false;9345 if(($cache=$this->getApplication()->getCache())!==null)9346 {9347 $array=$cache->get(self::THEME_CACHE_PREFIX.$themePath);9348 if(is_array($array))9349 {9350 list($skins,$cssFiles,$jsFiles,$timestamp)=$array;9351 if($this->getApplication()->getMode()!==TApplicationMode::Performance)9352 {9353 if(($dir=opendir($themePath))===false)9354 throw new TIOException('theme_path_inexistent',$themePath);9355 $cacheValid=true;9356 while(($file=readdir($dir))!==false)9357 {9358 if($file==='.' || $file==='..')9359 continue;9360 else if(basename($file,'.css')!==$file)9361 $this->_cssFiles[]=$themeUrl.'/'.$file;9362 else if(basename($file,'.js')!==$file)9363 $this->_jsFiles[]=$themeUrl.'/'.$file;9364 else if(basename($file,self::SKIN_FILE_EXT)!==$file && filemtime($themePath.DIRECTORY_SEPARATOR.$file)>$timestamp)9365 {9366 $cacheValid=false;9367 break;9368 }9369 }9370 closedir($dir);9371 if($cacheValid)9372 $this->_skins=$skins;9373 }9374 else9375 {9376 $cacheValid=true;9377 $this->_cssFiles=$cssFiles;9378 $this->_jsFiles=$jsFiles;9379 $this->_skins=$skins;9380 }9381 }9382 }9383 if(!$cacheValid)9384 {9385 $this->_cssFiles=array();9386 $this->_jsFiles=array();9387 $this->_skins=array();9388 if(($dir=opendir($themePath))===false)9389 throw new TIOException('theme_path_inexistent',$themePath);9390 while(($file=readdir($dir))!==false)9391 {9392 if($file==='.' || $file==='..')9393 continue;9394 else if(basename($file,'.css')!==$file)9395 $this->_cssFiles[]=$themeUrl.'/'.$file;9396 else if(basename($file,'.js')!==$file)9397 $this->_jsFiles[]=$themeUrl.'/'.$file;9398 else if(basename($file,self::SKIN_FILE_EXT)!==$file)9399 {9400 $template=new TTemplate(file_get_contents($themePath.'/'.$file),$themePath,$themePath.'/'.$file);9401 foreach($template->getItems() as $skin)9402 {9403 if(!isset($skin[2])) continue;9404 else if($skin[0]!==-1)9405 throw new TConfigurationException('theme_control_nested',$skin[1],dirname($themePath));9406 $type=$skin[1];9407 $id=isset($skin[2]['skinid'])?$skin[2]['skinid']:0;9408 unset($skin[2]['skinid']);9409 if(isset($this->_skins[$type][$id]))9410 throw new TConfigurationException('theme_skinid_duplicated',$type,$id,dirname($themePath));9411 $this->_skins[$type][$id]=$skin[2];9412 }9413 }9414 }9415 closedir($dir);9416 sort($this->_cssFiles);9417 sort($this->_jsFiles);9418 if($cache!==null)9419 $cache->set(self::THEME_CACHE_PREFIX.$themePath,array($this->_skins,$this->_cssFiles,$this->_jsFiles,time()));9420 }9421 }9422 public function getName()9423 {9424 return $this->_name;9425 }9426 protected function setName($value)9427 {9428 $this->_name = $value;9429 }9430 public function getBaseUrl()9431 {9432 return $this->_themeUrl;9433 }9434 protected function setBaseUrl($value)9435 {9436 $this->_themeUrl=rtrim($value,'/');9437 }9438 public function getBasePath()9439 {9440 return $this->_themePath;9441 }9442 protected function setBasePath($value)9443 {9444 $this->_themePath=$value;9445 }9446 public function getSkins()9447 {9448 return $this->_skins;9449 }9450 protected function setSkins($value)9451 {9452 $this->_skins = $value;9453 }9454 public function applySkin($control)9455 {9456 $type=get_class($control);9457 if(($id=$control->getSkinID())==='')9458 $id=0;9459 if(isset($this->_skins[$type][$id]))9460 {9461 foreach($this->_skins[$type][$id] as $name=>$value)9462 {9463 if(is_array($value))9464 {9465 switch($value[0])9466 {9467 case TTemplate::CONFIG_EXPRESSION:9468 $value=$this->evaluateExpression($value[1]);9469 break;9470 case TTemplate::CONFIG_ASSET:9471 $value=$this->_themeUrl.'/'.ltrim($value[1],'/');9472 break;9473 case TTemplate::CONFIG_DATABIND:9474 $control->bindProperty($name,$value[1]);9475 break;9476 case TTemplate::CONFIG_PARAMETER:9477 $control->setSubProperty($name,$this->getApplication()->getParameters()->itemAt($value[1]));9478 break;9479 case TTemplate::CONFIG_TEMPLATE:9480 $control->setSubProperty($name,$value[1]);9481 break;9482 case TTemplate::CONFIG_LOCALIZATION:9483 $control->setSubProperty($name,Prado::localize($value[1]));9484 break;9485 default:9486 throw new TConfigurationException('theme_tag_unexpected',$name,$value[0]);9487 break;9488 }9489 }9490 if(!is_array($value))9491 {9492 if(strpos($name,'.')===false) {9493 if($control->hasProperty($name))9494 {9495 if($control->canSetProperty($name))9496 {9497 $setter='set'.$name;9498 $control->$setter($value);9499 }9500 else9501 throw new TConfigurationException('theme_property_readonly',$type,$name);9502 }9503 else9504 throw new TConfigurationException('theme_property_undefined',$type,$name);9505 }9506 else $control->setSubProperty($name,$value);9507 }9508 }9509 return true;9510 }9511 else9512 return false;9513 }9514 public function getStyleSheetFiles()9515 {9516 return $this->_cssFiles;9517 }9518 protected function setStyleSheetFiles($value)9519 {9520 $this->_cssFiles=$value;9521 }9522 public function getJavaScriptFiles()9523 {9524 return $this->_jsFiles;9525 }9526 protected function setJavaScriptFiles($value)9527 {9528 $this->_jsFiles=$value;9529 }9530}9531class TPageService extends TService9532{9533 const CONFIG_FILE_XML='config.xml';9534 const CONFIG_FILE_PHP='config.php';9535 const DEFAULT_BASEPATH='Pages';9536 const FALLBACK_BASEPATH='pages';9537 const CONFIG_CACHE_PREFIX='prado:pageservice:';9538 const PAGE_FILE_EXT='.page';9539 private $_basePath=null;9540 private $_basePageClass='TPage';9541 private $_clientScriptManagerClass='System.Web.UI.TClientScriptManager';9542 private $_defaultPage='Home';9543 private $_pagePath=null;9544 private $_page=null;9545 private $_properties=array();9546 private $_initialized=false;9547 private $_themeManager=null;9548 private $_templateManager=null;9549 public function init($config)9550 {9551 $pageConfig=$this->loadPageConfig($config);9552 $this->initPageContext($pageConfig);9553 $this->_initialized=true;9554 }9555 protected function initPageContext($pageConfig)9556 {9557 $application=$this->getApplication();9558 foreach($pageConfig->getApplicationConfigurations() as $appConfig)9559 $application->applyConfiguration($appConfig);9560 $this->applyConfiguration($pageConfig);9561 }9562 protected function applyConfiguration($config)9563 {9564 $this->_properties=array_merge($this->_properties, $config->getProperties());9565 $this->getApplication()->getAuthorizationRules()->mergeWith($config->getRules());9566 $pagePath=$this->getRequestedPagePath();9567 foreach($config->getExternalConfigurations() as $filePath=>$params)9568 {9569 list($configPagePath,$condition)=$params;9570 if($condition!==true)9571 $condition=$this->evaluateExpression($condition);9572 if($condition)9573 {9574 if(($path=Prado::getPathOfNamespace($filePath,Prado::getApplication()->getConfigurationFileExt()))===null || !is_file($path))9575 throw new TConfigurationException('pageservice_includefile_invalid',$filePath);9576 $c=new TPageConfiguration($pagePath);9577 $c->loadFromFile($path,$configPagePath);9578 $this->applyConfiguration($c);9579 }9580 }9581 }9582 protected function determineRequestedPagePath()9583 {9584 $pagePath=$this->getRequest()->getServiceParameter();9585 if(empty($pagePath))9586 $pagePath=$this->getDefaultPage();9587 return $pagePath;9588 }9589 protected function loadPageConfig($config)9590 {9591 $application=$this->getApplication();9592 $pagePath=$this->getRequestedPagePath();9593 if(($cache=$application->getCache())===null)9594 {9595 $pageConfig=new TPageConfiguration($pagePath);9596 if($config!==null)9597 {9598 if($application->getConfigurationType()==TApplication::CONFIG_TYPE_PHP)9599 $pageConfig->loadPageConfigurationFromPhp($config,$application->getBasePath(),'');9600 else9601 $pageConfig->loadPageConfigurationFromXml($config,$application->getBasePath(),'');9602 }9603 $pageConfig->loadFromFiles($this->getBasePath());9604 }9605 else9606 {9607 $configCached=true;9608 $currentTimestamp=array();9609 $arr=$cache->get(self::CONFIG_CACHE_PREFIX.$this->getID().$pagePath);9610 if(is_array($arr))9611 {9612 list($pageConfig,$timestamps)=$arr;9613 if($application->getMode()!==TApplicationMode::Performance)9614 {9615 foreach($timestamps as $fileName=>$timestamp)9616 {9617 if($fileName===0) {9618 $appConfigFile=$application->getConfigurationFile();9619 $currentTimestamp[0]=$appConfigFile===null?0:@filemtime($appConfigFile);9620 if($currentTimestamp[0]>$timestamp || ($timestamp>0 && !$currentTimestamp[0]))9621 $configCached=false;9622 }9623 else9624 {9625 $currentTimestamp[$fileName]=@filemtime($fileName);9626 if($currentTimestamp[$fileName]>$timestamp || ($timestamp>0 && !$currentTimestamp[$fileName]))9627 $configCached=false;9628 }9629 }9630 }9631 }9632 else9633 {9634 $configCached=false;9635 $paths=explode('.',$pagePath);9636 $configPath=$this->getBasePath();9637 $fileName = $this->getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP9638 ? self::CONFIG_FILE_PHP9639 : self::CONFIG_FILE_XML;9640 foreach($paths as $path)9641 {9642 $configFile=$configPath.DIRECTORY_SEPARATOR.$fileName;9643 $currentTimestamp[$configFile]=@filemtime($configFile);9644 $configPath.=DIRECTORY_SEPARATOR.$path;9645 }9646 $appConfigFile=$application->getConfigurationFile();9647 $currentTimestamp[0]=$appConfigFile===null?0:@filemtime($appConfigFile);9648 }9649 if(!$configCached)9650 {9651 $pageConfig=new TPageConfiguration($pagePath);9652 if($config!==null)9653 {9654 if($application->getConfigurationType()==TApplication::CONFIG_TYPE_PHP)9655 $pageConfig->loadPageConfigurationFromPhp($config,$application->getBasePath(),'');9656 else9657 $pageConfig->loadPageConfigurationFromXml($config,$application->getBasePath(),'');9658 }9659 $pageConfig->loadFromFiles($this->getBasePath());9660 $cache->set(self::CONFIG_CACHE_PREFIX.$this->getID().$pagePath,array($pageConfig,$currentTimestamp));9661 }9662 }9663 return $pageConfig;9664 }9665 public function getTemplateManager()9666 {9667 if(!$this->_templateManager)9668 {9669 $this->_templateManager=new TTemplateManager;9670 $this->_templateManager->init(null);9671 }9672 return $this->_templateManager;9673 }9674 public function setTemplateManager(TTemplateManager $value)9675 {9676 $this->_templateManager=$value;9677 }9678 public function getThemeManager()9679 {9680 if(!$this->_themeManager)9681 {9682 $this->_themeManager=new TThemeManager;9683 $this->_themeManager->init(null);9684 }9685 return $this->_themeManager;9686 }9687 public function setThemeManager(TThemeManager $value)9688 {9689 $this->_themeManager=$value;9690 }9691 public function getRequestedPagePath()9692 {9693 if($this->_pagePath===null)9694 {9695 $this->_pagePath=strtr($this->determineRequestedPagePath(),'/\\','..');9696 if(empty($this->_pagePath))9697 throw new THttpException(404,'pageservice_page_required');9698 }9699 return $this->_pagePath;9700 }9701 public function getRequestedPage()9702 {9703 return $this->_page;9704 }9705 public function getDefaultPage()9706 {9707 return $this->_defaultPage;9708 }9709 public function setDefaultPage($value)9710 {9711 if($this->_initialized)9712 throw new TInvalidOperationException('pageservice_defaultpage_unchangeable');9713 else9714 $this->_defaultPage=$value;9715 }9716 public function getDefaultPageUrl()9717 {9718 return $this->constructUrl($this->getDefaultPage());9719 }9720 public function getBasePath()9721 {9722 if($this->_basePath===null)9723 {9724 $basePath=$this->getApplication()->getBasePath().DIRECTORY_SEPARATOR.self::DEFAULT_BASEPATH;9725 if(($this->_basePath=realpath($basePath))===false || !is_dir($this->_basePath))9726 {9727 $basePath=$this->getApplication()->getBasePath().DIRECTORY_SEPARATOR.self::FALLBACK_BASEPATH;9728 if(($this->_basePath=realpath($basePath))===false || !is_dir($this->_basePath))9729 throw new TConfigurationException('pageservice_basepath_invalid',$basePath);9730 }9731 }9732 return $this->_basePath;9733 }9734 public function setBasePath($value)9735 {9736 if($this->_initialized)9737 throw new TInvalidOperationException('pageservice_basepath_unchangeable');9738 else if(($path=Prado::getPathOfNamespace($value))===null || !is_dir($path))9739 throw new TConfigurationException('pageservice_basepath_invalid',$value);9740 $this->_basePath=realpath($path);9741 }9742 public function setBasePageClass($value)9743 {9744 $this->_basePageClass=$value;9745 }9746 public function getBasePageClass()9747 {9748 return $this->_basePageClass;9749 }9750 public function setClientScriptManagerClass($value)9751 {9752 $this->_clientScriptManagerClass=$value;9753 }9754 public function getClientScriptManagerClass()9755 {9756 return $this->_clientScriptManagerClass;9757 }9758 public function run()9759 {9760 $this->_page=$this->createPage($this->getRequestedPagePath());9761 $this->runPage($this->_page,$this->_properties);9762 }9763 protected function createPage($pagePath)9764 {9765 $path=$this->getBasePath().DIRECTORY_SEPARATOR.strtr($pagePath,'.',DIRECTORY_SEPARATOR);9766 $hasTemplateFile=is_file($path.self::PAGE_FILE_EXT);9767 $hasClassFile=is_file($path.Prado::CLASS_FILE_EXT);9768 if(!$hasTemplateFile && !$hasClassFile)9769 throw new THttpException(404,'pageservice_page_unknown',$pagePath);9770 if($hasClassFile)9771 {9772 $className=basename($path);9773 if(!class_exists($className,false))9774 include_once($path.Prado::CLASS_FILE_EXT);9775 }9776 else9777 {9778 $className=$this->getBasePageClass();9779 Prado::using($className);9780 if(($pos=strrpos($className,'.'))!==false)9781 $className=substr($className,$pos+1);9782 }9783 if(!class_exists($className,false) || ($className!=='TPage' && !is_subclass_of($className,'TPage')))9784 throw new THttpException(404,'pageservice_page_unknown',$pagePath);9785 $page=Prado::createComponent($className);9786 $page->setPagePath($pagePath);9787 if($hasTemplateFile)9788 $page->setTemplate($this->getTemplateManager()->getTemplateByFileName($path.self::PAGE_FILE_EXT));9789 return $page;9790 }9791 protected function runPage($page,$properties)9792 {9793 foreach($properties as $name=>$value)9794 $page->setSubProperty($name,$value);9795 $page->run($this->getResponse()->createHtmlWriter());9796 }9797 public function constructUrl($pagePath,$getParams=null,$encodeAmpersand=true,$encodeGetItems=true)9798 {9799 return $this->getRequest()->constructUrl($this->getID(),$pagePath,$getParams,$encodeAmpersand,$encodeGetItems);9800 }9801}9802class TPageConfiguration extends TComponent9803{9804 private $_appConfigs=array();9805 private $_properties=array();9806 private $_rules=array();9807 private $_includes=array();9808 private $_pagePath='';9809 public function __construct($pagePath)9810 {9811 $this->_pagePath=$pagePath;9812 }9813 public function getExternalConfigurations()9814 {9815 return $this->_includes;9816 }9817 public function getProperties()9818 {9819 return $this->_properties;9820 }9821 public function getRules()9822 {9823 return $this->_rules;9824 }9825 public function getApplicationConfigurations()9826 {9827 return $this->_appConfigs;9828 }9829 public function loadFromFiles($basePath)9830 {9831 $paths=explode('.',$this->_pagePath);9832 $page=array_pop($paths);9833 $path=$basePath;9834 $configPagePath='';9835 $fileName = Prado::getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP9836 ? TPageService::CONFIG_FILE_PHP9837 : TPageService::CONFIG_FILE_XML;9838 foreach($paths as $p)9839 {9840 $this->loadFromFile($path.DIRECTORY_SEPARATOR.$fileName,$configPagePath);9841 $path.=DIRECTORY_SEPARATOR.$p;9842 if($configPagePath==='')9843 $configPagePath=$p;9844 else9845 $configPagePath.='.'.$p;9846 }9847 $this->loadFromFile($path.DIRECTORY_SEPARATOR.$fileName,$configPagePath);9848 $this->_rules=new TAuthorizationRuleCollection($this->_rules);9849 }9850 public function loadFromFile($fname,$configPagePath)9851 {9852 if(empty($fname) || !is_file($fname))9853 return;9854 if(Prado::getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP)9855 {9856 $fcontent = include $fname;9857 $this->loadFromPhp($fcontent,dirname($fname),$configPagePath);9858 }9859 else9860 {9861 $dom=new TXmlDocument;9862 if($dom->loadFromFile($fname))9863 $this->loadFromXml($dom,dirname($fname),$configPagePath);9864 else9865 throw new TConfigurationException('pageserviceconf_file_invalid',$fname);9866 }9867 }9868 public function loadFromPhp($config,$configPath,$configPagePath)9869 {9870 $this->loadApplicationConfigurationFromPhp($config,$configPath);9871 $this->loadPageConfigurationFromPhp($config,$configPath,$configPagePath);9872 }9873 public function loadFromXml($dom,$configPath,$configPagePath)9874 {9875 $this->loadApplicationConfigurationFromXml($dom,$configPath);9876 $this->loadPageConfigurationFromXml($dom,$configPath,$configPagePath);9877 }9878 public function loadApplicationConfigurationFromPhp($config,$configPath)9879 {9880 $appConfig=new TApplicationConfiguration;9881 $appConfig->loadFromPhp($config,$configPath);9882 $this->_appConfigs[]=$appConfig;9883 }9884 public function loadApplicationConfigurationFromXml($dom,$configPath)9885 {9886 $appConfig=new TApplicationConfiguration;9887 $appConfig->loadFromXml($dom,$configPath);9888 $this->_appConfigs[]=$appConfig;9889 }9890 public function loadPageConfigurationFromPhp($config, $configPath, $configPagePath)9891 {9892 if(isset($config['authorization']) && is_array($config['authorization']))9893 {9894 $rules = array();9895 foreach($config['authorization'] as $authorization)9896 {9897 $patterns=isset($authorization['pages'])?$authorization['pages']:'';9898 $ruleApplies=false;9899 if(empty($patterns) || trim($patterns)==='*') $ruleApplies=true;9900 else9901 {9902 foreach(explode(',',$patterns) as $pattern)9903 {9904 if(($pattern=trim($pattern))!=='')9905 {9906 if($configPagePath!=='') $pattern=$configPagePath.'.'.$pattern;9907 if(strcasecmp($pattern,$this->_pagePath)===0)9908 {9909 $ruleApplies=true;9910 break;9911 }9912 if($pattern[strlen($pattern)-1]==='*') {9913 if(strncasecmp($this->_pagePath,$pattern,strlen($pattern)-1)===0)9914 {9915 $ruleApplies=true;9916 break;9917 }9918 }9919 }9920 }9921 }9922 if($ruleApplies)9923 {9924 $action = isset($authorization['action'])?$authorization['action']:'';9925 $users = isset($authorization['users'])?$authorization['users']:'';9926 $roles = isset($authorization['roles'])?$authorization['roles']:'';9927 $verb = isset($authorization['verb'])?$authorization['verb']:'';9928 $ips = isset($authorization['ips'])?$authorization['ips']:'';9929 $rules[]=new TAuthorizationRule($action,$users,$roles,$verb,$ips);9930 }9931 }9932 $this->_rules=array_merge($rules,$this->_rules);9933 }9934 if(isset($config['pages']) && is_array($config['pages']))9935 {9936 if(isset($config['pages']['properties']))9937 {9938 $this->_properties = array_merge($this->_properties, $config['pages']['properties']);9939 unset($config['pages']['properties']);9940 }9941 foreach($config['pages'] as $id => $page)9942 {9943 $properties = array();9944 if(isset($page['properties']))9945 {9946 $properties=$page['properties'];9947 unset($page['properties']);9948 }9949 $matching=false;9950 $id=($configPagePath==='')?$id:$configPagePath.'.'.$id;9951 if(strcasecmp($id,$this->_pagePath)===0)9952 $matching=true;9953 else if($id[strlen($id)-1]==='*') $matching=strncasecmp($this->_pagePath,$id,strlen($id)-1)===0;9954 if($matching)9955 $this->_properties=array_merge($this->_properties,$properties);9956 }9957 }9958 if(isset($config['includes']) && is_array($config['includes']))9959 {9960 foreach($config['includes'] as $include)9961 {9962 $when = isset($include['when'])?true:false;9963 if(!isset($include['file']))9964 throw new TConfigurationException('pageserviceconf_includefile_required');9965 $filePath = $include['file'];9966 if(isset($this->_includes[$filePath]))9967 $this->_includes[$filePath]=array($configPagePath,'('.$this->_includes[$filePath][1].') || ('.$when.')');9968 else9969 $this->_includes[$filePath]=array($configPagePath,$when);9970 }9971 }9972 }9973 public function loadPageConfigurationFromXml($dom,$configPath,$configPagePath)9974 {9975 if(($authorizationNode=$dom->getElementByTagName('authorization'))!==null)9976 {9977 $rules=array();9978 foreach($authorizationNode->getElements() as $node)9979 {9980 $patterns=$node->getAttribute('pages');9981 $ruleApplies=false;9982 if(empty($patterns) || trim($patterns)==='*') $ruleApplies=true;9983 else9984 {9985 foreach(explode(',',$patterns) as $pattern)9986 {9987 if(($pattern=trim($pattern))!=='')9988 {9989 if($configPagePath!=='') $pattern=$configPagePath.'.'.$pattern;9990 if(strcasecmp($pattern,$this->_pagePath)===0)9991 {9992 $ruleApplies=true;9993 break;9994 }9995 if($pattern[strlen($pattern)-1]==='*') {9996 if(strncasecmp($this->_pagePath,$pattern,strlen($pattern)-1)===0)9997 {9998 $ruleApplies=true;9999 break;10000 }10001 }10002 }10003 }10004 }10005 if($ruleApplies)10006 $rules[]=new TAuthorizationRule($node->getTagName(),$node->getAttribute('users'),$node->getAttribute('roles'),$node->getAttribute('verb'),$node->getAttribute('ips'));10007 }10008 $this->_rules=array_merge($rules,$this->_rules);10009 }10010 if(($pagesNode=$dom->getElementByTagName('pages'))!==null)10011 {10012 $this->_properties=array_merge($this->_properties,$pagesNode->getAttributes()->toArray());10013 foreach($pagesNode->getElementsByTagName('page') as $node)10014 {10015 $properties=$node->getAttributes();10016 $id=$properties->remove('id');10017 if(empty($id))10018 throw new TConfigurationException('pageserviceconf_page_invalid',$configPath);10019 $matching=false;10020 $id=($configPagePath==='')?$id:$configPagePath.'.'.$id;10021 if(strcasecmp($id,$this->_pagePath)===0)10022 $matching=true;10023 else if($id[strlen($id)-1]==='*') $matching=strncasecmp($this->_pagePath,$id,strlen($id)-1)===0;10024 if($matching)10025 $this->_properties=array_merge($this->_properties,$properties->toArray());10026 }10027 }10028 foreach($dom->getElementsByTagName('include') as $node)10029 {10030 if(($when=$node->getAttribute('when'))===null)10031 $when=true;10032 if(($filePath=$node->getAttribute('file'))===null)10033 throw new TConfigurationException('pageserviceconf_includefile_required');10034 if(isset($this->_includes[$filePath]))10035 $this->_includes[$filePath]=array($configPagePath,'('.$this->_includes[$filePath][1].') || ('.$when.')');10036 else10037 $this->_includes[$filePath]=array($configPagePath,$when);10038 }10039 }10040}10041class TAssetManager extends TModule10042{10043 const DEFAULT_BASEPATH='assets';10044 private $_basePath=null;10045 private $_baseUrl=null;10046 private $_checkTimestamp=false;10047 private $_application;10048 private $_published=array();10049 private $_initialized=false;10050 public function init($config)10051 {10052 $application=$this->getApplication();10053 if($this->_basePath===null)10054 $this->_basePath=dirname($application->getRequest()->getApplicationFilePath()).DIRECTORY_SEPARATOR.self::DEFAULT_BASEPATH;10055 if(!is_writable($this->_basePath) || !is_dir($this->_basePath))10056 throw new TConfigurationException('assetmanager_basepath_invalid',$this->_basePath);10057 if($this->_baseUrl===null)10058 $this->_baseUrl=rtrim(dirname($application->getRequest()->getApplicationUrl()),'/\\').'/'.self::DEFAULT_BASEPATH;10059 $application->setAssetManager($this);10060 $this->_initialized=true;10061 }10062 public function getBasePath()10063 {10064 return $this->_basePath;10065 }10066 public function setBasePath($value)10067 {10068 if($this->_initialized)10069 throw new TInvalidOperationException('assetmanager_basepath_unchangeable');10070 else10071 {10072 $this->_basePath=Prado::getPathOfNamespace($value);10073 if($this->_basePath===null || !is_dir($this->_basePath) || !is_writable($this->_basePath))10074 throw new TInvalidDataValueException('assetmanager_basepath_invalid',$value);10075 }10076 }10077 public function getBaseUrl()10078 {10079 return $this->_baseUrl;10080 }10081 public function setBaseUrl($value)10082 {10083 if($this->_initialized)10084 throw new TInvalidOperationException('assetmanager_baseurl_unchangeable');10085 else10086 $this->_baseUrl=rtrim($value,'/');10087 }10088 public function publishFilePath($path,$checkTimestamp=false)10089 {10090 if(isset($this->_published[$path]))10091 return $this->_published[$path];10092 else if(empty($path) || ($fullpath=realpath($path))===false)10093 throw new TInvalidDataValueException('assetmanager_filepath_invalid',$path);10094 else if(is_file($fullpath))10095 {10096 $dir=$this->hash(dirname($fullpath));10097 $fileName=basename($fullpath);10098 $dst=$this->_basePath.DIRECTORY_SEPARATOR.$dir;10099 if(!is_file($dst.DIRECTORY_SEPARATOR.$fileName) || $checkTimestamp || $this->getApplication()->getMode()!==TApplicationMode::Performance)10100 $this->copyFile($fullpath,$dst);10101 return $this->_published[$path]=$this->_baseUrl.'/'.$dir.'/'.$fileName;10102 }10103 else10104 {10105 $dir=$this->hash($fullpath);10106 if(!is_dir($this->_basePath.DIRECTORY_SEPARATOR.$dir) || $checkTimestamp || $this->getApplication()->getMode()!==TApplicationMode::Performance)10107 {10108 $this->copyDirectory($fullpath,$this->_basePath.DIRECTORY_SEPARATOR.$dir);10109 }10110 return $this->_published[$path]=$this->_baseUrl.'/'.$dir;10111 }10112 }10113 public function getPublished()10114 {10115 return $this->_published;10116 }10117 protected function setPublished($values=array())10118 {10119 $this->_published = $values;10120 }10121 public function getPublishedPath($path)10122 {10123 $path=realpath($path);10124 if(is_file($path))10125 return $this->_basePath.DIRECTORY_SEPARATOR.$this->hash(dirname($path)).DIRECTORY_SEPARATOR.basename($path);10126 else10127 return $this->_basePath.DIRECTORY_SEPARATOR.$this->hash($path);10128 }10129 public function getPublishedUrl($path)10130 {10131 $path=realpath($path);10132 if(is_file($path))10133 return $this->_baseUrl.'/'.$this->hash(dirname($path)).'/'.basename($path);10134 else10135 return $this->_baseUrl.'/'.$this->hash($path);10136 }10137 protected function hash($dir)10138 {10139 return sprintf('%x',crc32($dir.Prado::getVersion()));10140 }10141 protected function copyFile($src,$dst)10142 {10143 if(!is_dir($dst))10144 {10145 @mkdir($dst);10146 @chmod($dst, PRADO_CHMOD);10147 }10148 $dstFile=$dst.DIRECTORY_SEPARATOR.basename($src);10149 if(@filemtime($dstFile)<@filemtime($src))10150 {10151 @copy($src,$dstFile);10152 }10153 }10154 public function copyDirectory($src,$dst)10155 {10156 if(!is_dir($dst))10157 {10158 @mkdir($dst);10159 @chmod($dst, PRADO_CHMOD);10160 }10161 if($folder=@opendir($src))10162 {10163 while($file=@readdir($folder))10164 {10165 if($file==='.' || $file==='..' || $file==='.svn')10166 continue;10167 else if(is_file($src.DIRECTORY_SEPARATOR.$file))10168 {10169 if(@filemtime($dst.DIRECTORY_SEPARATOR.$file)<@filemtime($src.DIRECTORY_SEPARATOR.$file))10170 {10171 @copy($src.DIRECTORY_SEPARATOR.$file,$dst.DIRECTORY_SEPARATOR.$file);10172 @chmod($dst.DIRECTORY_SEPARATOR.$file, PRADO_CHMOD);10173 }10174 }10175 else10176 $this->copyDirectory($src.DIRECTORY_SEPARATOR.$file,$dst.DIRECTORY_SEPARATOR.$file);10177 }10178 closedir($folder);10179 } else {10180 throw new TInvalidDataValueException('assetmanager_source_directory_invalid', $src);10181 }10182 }10183 public function publishTarFile($tarfile, $md5sum, $checkTimestamp=false)10184 {10185 if(isset($this->_published[$md5sum]))10186 return $this->_published[$md5sum];10187 else if(($fullpath=realpath($md5sum))===false || !is_file($fullpath))10188 throw new TInvalidDataValueException('assetmanager_tarchecksum_invalid',$md5sum);10189 else10190 {10191 $dir=$this->hash(dirname($fullpath));10192 $fileName=basename($fullpath);10193 $dst=$this->_basePath.DIRECTORY_SEPARATOR.$dir;10194 if(!is_file($dst.DIRECTORY_SEPARATOR.$fileName) || $checkTimestamp || $this->getApplication()->getMode()!==TApplicationMode::Performance)10195 {10196 if(@filemtime($dst.DIRECTORY_SEPARATOR.$fileName)<@filemtime($fullpath))10197 {10198 $this->copyFile($fullpath,$dst);10199 $this->deployTarFile($tarfile,$dst);10200 }10201 }10202 return $this->_published[$md5sum]=$this->_baseUrl.'/'.$dir;10203 }10204 }10205 protected function deployTarFile($path,$destination)10206 {10207 if(($fullpath=realpath($path))===false || !is_file($fullpath))10208 throw new TIOException('assetmanager_tarfile_invalid',$path);10209 else10210 {10211 Prado::using('System.IO.TTarFileExtractor');10212 $tar = new TTarFileExtractor($fullpath);10213 return $tar->extract($destination);10214 }10215 }10216}10217class TGlobalization extends TModule10218{10219 private $_defaultCharset = 'UTF-8';10220 private $_defaultCulture = 'en';10221 private $_charset=null;10222 private $_culture=null;10223 private $_translation;10224 private $_translateDefaultCulture=true;10225 public function init($config)10226 {10227 if($this->_charset===null)10228 $this->_charset=$this->getDefaultCharset();10229 if($this->_culture===null)10230 $this->_culture=$this->getDefaultCulture();10231 if($config!==null)10232 {10233 if($this->getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP)10234 $translation = isset($config['translate'])?$config['translate']:null;10235 else10236 {10237 $t = $config->getElementByTagName('translation');10238 $translation = ($t)?$t->getAttributes():null;10239 }10240 if($translation)10241 $this->setTranslationConfiguration($translation);10242 }10243 $this->getApplication()->setGlobalization($this);10244 }10245 public function getTranslateDefaultCulture()10246 {10247 return $this->_translateDefaultCulture;10248 }10249 public function setTranslateDefaultCulture($value)10250 {10251 $this->_translateDefaultCulture = TPropertyValue::ensureBoolean($value);10252 }10253 public function getDefaultCulture()10254 {10255 return $this->_defaultCulture;10256 }10257 public function setDefaultCulture($culture)10258 {10259 $this->_defaultCulture = str_replace('-','_',$culture);10260 }10261 public function getDefaultCharset()10262 {10263 return $this->_defaultCharset;10264 }10265 public function setDefaultCharset($charset)10266 {10267 $this->_defaultCharset = $charset;10268 }10269 public function getCulture()10270 {10271 return $this->_culture;10272 }10273 public function setCulture($culture)10274 {10275 $this->_culture = str_replace('-','_',$culture);10276 }10277 public function getCharset()10278 {10279 return $this->_charset;10280 }10281 public function setCharset($charset)10282 {10283 $this->_charset = $charset;10284 }10285 public function getTranslationConfiguration()10286 {10287 return (!$this->_translateDefaultCulture && ($this->getDefaultCulture() == $this->getCulture()))10288 ? null10289 : $this->_translation;10290 }10291 protected function setTranslationConfiguration($config)10292 {10293 if($config['type'] == 'XLIFF' || $config['type'] == 'gettext')10294 {10295 if($config['source'])10296 {10297 $config['source'] = Prado::getPathOfNamespace($config['source']);10298 if(!is_dir($config['source']))10299 {10300 if(@mkdir($config['source'])===false)10301 throw new TConfigurationException('globalization_source_path_failed',10302 $config['source']);10303 chmod($config['source'], PRADO_CHMOD); }10304 }10305 else10306 {10307 throw new TConfigurationException("invalid source dir '{$config['source']}'");10308 }10309 }10310 if(isset($config['cache']) && TPropertyValue::ensureBoolean($config['cache']))10311 {10312 $config['cache'] = $this->getApplication()->getRunTimePath().'/i18n';10313 if(!is_dir($config['cache']))10314 {10315 if(@mkdir($config['cache'])===false)10316 throw new TConfigurationException('globalization_cache_path_failed',10317 $config['cache']);10318 chmod($config['cache'], PRADO_CHMOD); }10319 }10320 else10321 {10322 unset($config['cache']);10323 }10324 $this->_translation = $config;10325 }10326 public function getTranslationCatalogue()10327 {10328 return $this->_translation['catalogue'];10329 }10330 public function setTranslationCatalogue($value)10331 {10332 $this->_translation['catalogue'] = $value;10333 }10334 public function getCultureVariants($culture=null)10335 {10336 if($culture===null) $culture = $this->getCulture();10337 $variants = explode('_', $culture);10338 $result = array();10339 for(; count($variants) > 0; array_pop($variants))10340 $result[] = implode('_', $variants);10341 return $result;10342 }10343 public function getLocalizedResource($file,$culture=null)10344 {10345 $files = array();10346 $variants = $this->getCultureVariants($culture);10347 $path = pathinfo($file);10348 foreach($variants as $variant)10349 $files[] = $path['dirname'].DIRECTORY_SEPARATOR.$variant.DIRECTORY_SEPARATOR.$path['basename'];10350 $filename = substr($path['basename'],0,strrpos($path['basename'],'.'));10351 foreach($variants as $variant)10352 $files[] = $path['dirname'].DIRECTORY_SEPARATOR.$filename.'.'.$variant.'.'.$path['extension'];10353 $files[] = $file;10354 return $files;10355 }10356}10357class TApplication extends TComponent10358{10359 const STATE_OFF='Off';10360 const STATE_DEBUG='Debug';10361 const STATE_NORMAL='Normal';10362 const STATE_PERFORMANCE='Performance';10363 const PAGE_SERVICE_ID='page';10364 const CONFIG_FILE_XML='application.xml';10365 const CONFIG_FILE_EXT_XML='.xml';10366 const CONFIG_TYPE_XML = 'xml';10367 const CONFIG_FILE_PHP='application.php';10368 const CONFIG_FILE_EXT_PHP='.php';10369 const CONFIG_TYPE_PHP = 'php';10370 const RUNTIME_PATH='runtime';10371 const CONFIGCACHE_FILE='config.cache';10372 const GLOBAL_FILE='global.cache';10373 private static $_steps=array(10374 'onBeginRequest',10375 'onLoadState',10376 'onLoadStateComplete',10377 'onAuthentication',10378 'onAuthenticationComplete',10379 'onAuthorization',10380 'onAuthorizationComplete',10381 'onPreRunService',10382 'runService',10383 'onSaveState',10384 'onSaveStateComplete',10385 'onPreFlushOutput',10386 'flushOutput'10387 );10388 private $_id;10389 private $_uniqueID;10390 private $_requestCompleted=false;10391 private $_step;10392 private $_services;10393 private $_service;10394 private $_modules=array();10395 private $_lazyModules=array();10396 private $_parameters;10397 private $_configFile;10398 private $_configFileExt;10399 private $_configType;10400 private $_basePath;10401 private $_runtimePath;10402 private $_stateChanged=false;10403 private $_globals=array();10404 private $_cacheFile;10405 private $_errorHandler;10406 private $_request;10407 private $_response;10408 private $_session;10409 private $_cache;10410 private $_statePersister;10411 private $_user;10412 private $_globalization;10413 private $_security;10414 private $_assetManager;10415 private $_authRules;10416 private $_mode=TApplicationMode::Debug;10417 private $_pageServiceID = self::PAGE_SERVICE_ID;10418 public function __construct($basePath='protected',$cacheConfig=true, $configType=self::CONFIG_TYPE_XML)10419 {10420 Prado::setApplication($this);10421 $this->setConfigurationType($configType);10422 $this->resolvePaths($basePath);10423 if($cacheConfig)10424 $this->_cacheFile=$this->_runtimePath.DIRECTORY_SEPARATOR.self::CONFIGCACHE_FILE;10425 $this->_uniqueID=md5($this->_runtimePath);10426 $this->_parameters=new TMap;10427 $this->_services=array($this->getPageServiceID()=>array('TPageService',array(),null));10428 Prado::setPathOfAlias('Application',$this->_basePath);10429 }10430 protected function resolvePaths($basePath)10431 {10432 if(empty($basePath) || ($basePath=realpath($basePath))===false)10433 throw new TConfigurationException('application_basepath_invalid',$basePath);10434 if(is_dir($basePath) && is_file($basePath.DIRECTORY_SEPARATOR.$this->getConfigurationFileName()))10435 $configFile=$basePath.DIRECTORY_SEPARATOR.$this->getConfigurationFileName();10436 else if(is_file($basePath))10437 {10438 $configFile=$basePath;10439 $basePath=dirname($configFile);10440 }10441 else10442 $configFile=null;10443 $runtimePath=$basePath.DIRECTORY_SEPARATOR.self::RUNTIME_PATH;10444 if(is_writable($runtimePath))10445 {10446 if($configFile!==null)10447 {10448 $runtimePath.=DIRECTORY_SEPARATOR.basename($configFile).'-'.Prado::getVersion();10449 if(!is_dir($runtimePath))10450 {10451 if(@mkdir($runtimePath)===false)10452 throw new TConfigurationException('application_runtimepath_failed',$runtimePath);10453 @chmod($runtimePath, PRADO_CHMOD); }10454 $this->setConfigurationFile($configFile);10455 }10456 $this->setBasePath($basePath);10457 $this->setRuntimePath($runtimePath);10458 }10459 else10460 throw new TConfigurationException('application_runtimepath_invalid',$runtimePath);10461 }10462 public function run()10463 {10464 try10465 {10466 $this->initApplication();10467 $n=count(self::$_steps);10468 $this->_step=0;10469 $this->_requestCompleted=false;10470 while($this->_step<$n)10471 {10472 if($this->_mode===self::STATE_OFF)10473 throw new THttpException(503,'application_unavailable');10474 if($this->_requestCompleted)10475 break;10476 $method=self::$_steps[$this->_step];10477 $this->$method();10478 $this->_step++;10479 }10480 }10481 catch(Exception $e)10482 {10483 $this->onError($e);10484 }10485 $this->onEndRequest();10486 }10487 public function completeRequest()10488 {10489 $this->_requestCompleted=true;10490 }10491 public function getRequestCompleted()10492 {10493 return $this->_requestCompleted;10494 }10495 public function getGlobalState($key,$defaultValue=null)10496 {10497 return isset($this->_globals[$key])?$this->_globals[$key]:$defaultValue;10498 }10499 public function setGlobalState($key,$value,$defaultValue=null,$forceSave=false)10500 {10501 $this->_stateChanged=true;10502 if($value===$defaultValue)10503 unset($this->_globals[$key]);10504 else10505 $this->_globals[$key]=$value;10506 if($forceSave)10507 $this->saveGlobals();10508 }10509 public function clearGlobalState($key)10510 {10511 $this->_stateChanged=true;10512 unset($this->_globals[$key]);10513 }10514 protected function loadGlobals()10515 {10516 $this->_globals=$this->getApplicationStatePersister()->load();10517 }10518 protected function saveGlobals()10519 {10520 if($this->_stateChanged)10521 {10522 $this->_stateChanged=false;10523 $this->getApplicationStatePersister()->save($this->_globals);10524 }10525 }10526 public function getID()10527 {10528 return $this->_id;10529 }10530 public function setID($value)10531 {10532 $this->_id=$value;10533 }10534 public function getPageServiceID()10535 {10536 return $this->_pageServiceID;10537 }10538 public function setPageServiceID($value)10539 {10540 $this->_pageServiceID=$value;10541 }10542 public function getUniqueID()10543 {10544 return $this->_uniqueID;10545 }10546 public function getMode()10547 {10548 return $this->_mode;10549 }10550 public function setMode($value)10551 {10552 $this->_mode=TPropertyValue::ensureEnum($value,'TApplicationMode');10553 }10554 public function getBasePath()10555 {10556 return $this->_basePath;10557 }10558 public function setBasePath($value)10559 {10560 $this->_basePath=$value;10561 }10562 public function getConfigurationFile()10563 {10564 return $this->_configFile;10565 }10566 public function setConfigurationFile($value)10567 {10568 $this->_configFile=$value;10569 }10570 public function getConfigurationType()10571 {10572 return $this->_configType;10573 }10574 public function setConfigurationType($value)10575 {10576 $this->_configType = $value;10577 }10578 public function getConfigurationFileExt()10579 {10580 if($this->_configFileExt===null)10581 {10582 switch($this->_configType)10583 {10584 case TApplication::CONFIG_TYPE_PHP:10585 $this->_configFileExt = TApplication::CONFIG_FILE_EXT_PHP;10586 break;10587 default:10588 $this->_configFileExt = TApplication::CONFIG_FILE_EXT_XML;10589 }10590 }10591 return $this->_configFileExt;10592 }10593 public function getConfigurationFileName()10594 {10595 static $fileName;10596 if($fileName == null)10597 {10598 switch($this->_configType)10599 {10600 case TApplication::CONFIG_TYPE_PHP:10601 $fileName = TApplication::CONFIG_FILE_PHP;10602 break;10603 default:10604 $fileName = TApplication::CONFIG_FILE_XML;10605 }10606 }10607 return $fileName;10608 }10609 public function getRuntimePath()10610 {10611 return $this->_runtimePath;10612 }10613 public function setRuntimePath($value)10614 {10615 $this->_runtimePath=$value;10616 if($this->_cacheFile)10617 $this->_cacheFile=$this->_runtimePath.DIRECTORY_SEPARATOR.self::CONFIGCACHE_FILE;10618 $this->_uniqueID=md5($this->_runtimePath);10619 }10620 public function getService()10621 {10622 return $this->_service;10623 }10624 public function setService($value)10625 {10626 $this->_service=$value;10627 }10628 public function setModule($id,IModule $module=null)10629 {10630 if(isset($this->_modules[$id]))10631 throw new TConfigurationException('application_moduleid_duplicated',$id);10632 else10633 $this->_modules[$id]=$module;10634 }10635 public function getModule($id)10636 {10637 if(!array_key_exists($id, $this->_modules))10638 return null;10639 if($this->_modules[$id]===null)10640 {10641 $module = $this->internalLoadModule($id, true);10642 $module[0]->init($module[1]);10643 }10644 return $this->_modules[$id];10645 }10646 public function getModules()10647 {10648 return $this->_modules;10649 }10650 public function getParameters()10651 {10652 return $this->_parameters;10653 }10654 public function getRequest()10655 {10656 if(!$this->_request)10657 {10658 $this->_request=new THttpRequest;10659 $this->_request->init(null);10660 }10661 return $this->_request;10662 }10663 public function setRequest(THttpRequest $request)10664 {10665 $this->_request=$request;10666 }10667 public function getResponse()10668 {10669 if(!$this->_response)10670 {10671 $this->_response=new THttpResponse;10672 $this->_response->init(null);10673 }10674 return $this->_response;10675 }10676 public function setResponse(THttpResponse $response)10677 {10678 $this->_response=$response;10679 }10680 public function getSession()10681 {10682 if(!$this->_session)10683 {10684 $this->_session=new THttpSession;10685 $this->_session->init(null);10686 }10687 return $this->_session;10688 }10689 public function setSession(THttpSession $session)10690 {10691 $this->_session=$session;10692 }10693 public function getErrorHandler()10694 {10695 if(!$this->_errorHandler)10696 {10697 $this->_errorHandler=new TErrorHandler;10698 $this->_errorHandler->init(null);10699 }10700 return $this->_errorHandler;10701 }10702 public function setErrorHandler(TErrorHandler $handler)10703 {10704 $this->_errorHandler=$handler;10705 }10706 public function getSecurityManager()10707 {10708 if(!$this->_security)10709 {10710 $this->_security=new TSecurityManager;10711 $this->_security->init(null);10712 }10713 return $this->_security;10714 }10715 public function setSecurityManager(TSecurityManager $sm)10716 {10717 $this->_security=$sm;10718 }10719 public function getAssetManager()10720 {10721 if(!$this->_assetManager)10722 {10723 $this->_assetManager=new TAssetManager;10724 $this->_assetManager->init(null);10725 }10726 return $this->_assetManager;10727 }10728 public function setAssetManager(TAssetManager $value)10729 {10730 $this->_assetManager=$value;10731 }10732 public function getApplicationStatePersister()10733 {10734 if(!$this->_statePersister)10735 {10736 $this->_statePersister=new TApplicationStatePersister;10737 $this->_statePersister->init(null);10738 }10739 return $this->_statePersister;10740 }10741 public function setApplicationStatePersister(IStatePersister $persister)10742 {10743 $this->_statePersister=$persister;10744 }10745 public function getCache()10746 {10747 return $this->_cache;10748 }10749 public function setCache(ICache $cache)10750 {10751 $this->_cache=$cache;10752 }10753 public function getUser()10754 {10755 return $this->_user;10756 }10757 public function setUser(IUser $user)10758 {10759 $this->_user=$user;10760 }10761 public function getGlobalization($createIfNotExists=true)10762 {10763 if($this->_globalization===null && $createIfNotExists)10764 {10765 $this->_globalization=new TGlobalization;10766 $this->_globalization->init(null);10767 }10768 return $this->_globalization;10769 }10770 public function setGlobalization(TGlobalization $glob)10771 {10772 $this->_globalization=$glob;10773 }10774 public function getAuthorizationRules()10775 {10776 if($this->_authRules===null)10777 $this->_authRules=new TAuthorizationRuleCollection;10778 return $this->_authRules;10779 }10780 protected function getApplicationConfigurationClass()10781 {10782 return 'TApplicationConfiguration';10783 }10784 protected function internalLoadModule($id, $force=false)10785 {10786 list($moduleClass, $initProperties, $configElement)=$this->_lazyModules[$id];10787 if(isset($initProperties['lazy']) && $initProperties['lazy'] && !$force)10788 {10789 $this->setModule($id, null);10790 return null;10791 }10792 $module=Prado::createComponent($moduleClass);10793 foreach($initProperties as $name=>$value)10794 {10795 if($name==='lazy') continue;10796 $module->setSubProperty($name,$value);10797 }10798 $this->setModule($id,$module);10799 $this->_lazyModules[$id]=null;10800 return array($module,$configElement);10801 }10802 public function applyConfiguration($config,$withinService=false)10803 {10804 if($config->getIsEmpty())10805 return;10806 foreach($config->getAliases() as $alias=>$path)10807 Prado::setPathOfAlias($alias,$path);10808 foreach($config->getUsings() as $using)10809 Prado::using($using);10810 if(!$withinService)10811 {10812 foreach($config->getProperties() as $name=>$value)10813 $this->setSubProperty($name,$value);10814 }10815 if(empty($this->_services))10816 $this->_services=array($this->getPageServiceID()=>array('TPageService',array(),null));10817 foreach($config->getParameters() as $id=>$parameter)10818 {10819 if(is_array($parameter))10820 {10821 $component=Prado::createComponent($parameter[0]);10822 foreach($parameter[1] as $name=>$value)10823 $component->setSubProperty($name,$value);10824 $this->_parameters->add($id,$component);10825 }10826 else10827 $this->_parameters->add($id,$parameter);10828 }10829 $modules=array();10830 foreach($config->getModules() as $id=>$moduleConfig)10831 {10832 if(!is_string($id))10833 $id='_module'.count($this->_lazyModules);10834 $this->_lazyModules[$id]=$moduleConfig;10835 if($module = $this->internalLoadModule($id))10836 $modules[]=$module;10837 }10838 foreach($modules as $module)10839 $module[0]->init($module[1]);10840 foreach($config->getServices() as $serviceID=>$serviceConfig)10841 $this->_services[$serviceID]=$serviceConfig;10842 foreach($config->getExternalConfigurations() as $filePath=>$condition)10843 {10844 if($condition!==true)10845 $condition=$this->evaluateExpression($condition);10846 if($condition)10847 {10848 if(($path=Prado::getPathOfNamespace($filePath,$this->getConfigurationFileExt()))===null || !is_file($path))10849 throw new TConfigurationException('application_includefile_invalid',$filePath);10850 $cn=$this->getApplicationConfigurationClass();10851 $c=new $cn;10852 $c->loadFromFile($path);10853 $this->applyConfiguration($c,$withinService);10854 }10855 }10856 }10857 protected function initApplication()10858 {10859 if($this->_configFile!==null)10860 {10861 if($this->_cacheFile===null || @filemtime($this->_cacheFile)<filemtime($this->_configFile))10862 {10863 $config=new TApplicationConfiguration;10864 $config->loadFromFile($this->_configFile);10865 if($this->_cacheFile!==null)10866 file_put_contents($this->_cacheFile,serialize($config),LOCK_EX);10867 }10868 else10869 $config=unserialize(file_get_contents($this->_cacheFile));10870 $this->applyConfiguration($config,false);10871 }10872 if(($serviceID=$this->getRequest()->resolveRequest(array_keys($this->_services)))===null)10873 $serviceID=$this->getPageServiceID();10874 $this->startService($serviceID);10875 }10876 public function startService($serviceID)10877 {10878 if(isset($this->_services[$serviceID]))10879 {10880 list($serviceClass,$initProperties,$configElement)=$this->_services[$serviceID];10881 $service=Prado::createComponent($serviceClass);10882 if(!($service instanceof IService))10883 throw new THttpException(500,'application_service_invalid',$serviceClass);10884 if(!$service->getEnabled())10885 throw new THttpException(500,'application_service_unavailable',$serviceClass);10886 $service->setID($serviceID);10887 $this->setService($service);10888 foreach($initProperties as $name=>$value)10889 $service->setSubProperty($name,$value);10890 if($configElement!==null)10891 {10892 $config=new TApplicationConfiguration;10893 if($this->getConfigurationType()==self::CONFIG_TYPE_PHP)10894 $config->loadFromPhp($configElement,$this->getBasePath());10895 else10896 $config->loadFromXml($configElement,$this->getBasePath());10897 $this->applyConfiguration($config,true);10898 }10899 $service->init($configElement);10900 }10901 else10902 throw new THttpException(500,'application_service_unknown',$serviceID);10903 }10904 public function onError($param)10905 {10906 Prado::log($param->getMessage(),TLogger::ERROR,'System.TApplication');10907 $this->raiseEvent('OnError',$this,$param);10908 $this->getErrorHandler()->handleError($this,$param);10909 }10910 public function onBeginRequest()10911 {10912 $this->raiseEvent('OnBeginRequest',$this,null);10913 }10914 public function onAuthentication()10915 {10916 $this->raiseEvent('OnAuthentication',$this,null);10917 }10918 public function onAuthenticationComplete()10919 {10920 $this->raiseEvent('OnAuthenticationComplete',$this,null);10921 }10922 public function onAuthorization()10923 {10924 $this->raiseEvent('OnAuthorization',$this,null);10925 }10926 public function onAuthorizationComplete()10927 {10928 $this->raiseEvent('OnAuthorizationComplete',$this,null);10929 }10930 public function onLoadState()10931 {10932 $this->loadGlobals();10933 $this->raiseEvent('OnLoadState',$this,null);10934 }10935 public function onLoadStateComplete()10936 {10937 $this->raiseEvent('OnLoadStateComplete',$this,null);10938 }10939 public function onPreRunService()10940 {10941 $this->raiseEvent('OnPreRunService',$this,null);10942 }10943 public function runService()10944 {10945 if($this->_service)10946 $this->_service->run();10947 }10948 public function onSaveState()10949 {10950 $this->raiseEvent('OnSaveState',$this,null);10951 $this->saveGlobals();10952 }10953 public function onSaveStateComplete()10954 {10955 $this->raiseEvent('OnSaveStateComplete',$this,null);10956 }10957 public function onPreFlushOutput()10958 {10959 $this->raiseEvent('OnPreFlushOutput',$this,null);10960 }10961 public function flushOutput($continueBuffering = true)10962 {10963 $this->getResponse()->flush($continueBuffering);10964 }10965 public function onEndRequest()10966 {10967 $this->flushOutput(false); $this->saveGlobals(); $this->raiseEvent('OnEndRequest',$this,null);10968 }10969}10970class TApplicationMode extends TEnumerable10971{10972 const Off='Off';10973 const Debug='Debug';10974 const Normal='Normal';10975 const Performance='Performance';10976}10977class TApplicationConfiguration extends TComponent10978{10979 private $_properties=array();10980 private $_usings=array();10981 private $_aliases=array();10982 private $_modules=array();10983 private $_services=array();10984 private $_parameters=array();10985 private $_includes=array();10986 private $_empty=true;10987 public function loadFromFile($fname)10988 {10989 if(Prado::getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP)10990 {10991 $fcontent = include $fname;10992 $this->loadFromPhp($fcontent,dirname($fname));10993 }10994 else10995 {10996 $dom=new TXmlDocument;10997 $dom->loadFromFile($fname);10998 $this->loadFromXml($dom,dirname($fname));10999 }11000 }11001 public function getIsEmpty()11002 {11003 return $this->_empty;11004 }11005 public function loadFromPhp($config, $configPath)11006 {11007 if(isset($config['application']))11008 {11009 foreach($config['application'] as $name=>$value)11010 {11011 $this->_properties[$name]=$value;11012 }11013 $this->_empty = false;11014 }11015 if(isset($config['paths']) && is_array($config['paths']))11016 $this->loadPathsPhp($config['paths'],$configPath);11017 if(isset($config['modules']) && is_array($config['modules']))11018 $this->loadModulesPhp($config['modules'],$configPath);11019 if(isset($config['services']) && is_array($config['services']))11020 $this->loadServicesPhp($config['services'],$configPath);11021 if(isset($config['parameters']) && is_array($config['parameters']))11022 $this->loadParametersPhp($config['parameters'], $configPath);11023 if(isset($config['includes']) && is_array($config['includes']))11024 $this->loadExternalXml($config['includes'],$configPath);11025 }11026 public function loadFromXml($dom,$configPath)11027 {11028 foreach($dom->getAttributes() as $name=>$value)11029 {11030 $this->_properties[$name]=$value;11031 $this->_empty=false;11032 }11033 foreach($dom->getElements() as $element)11034 {11035 switch($element->getTagName())11036 {11037 case 'paths':11038 $this->loadPathsXml($element,$configPath);11039 break;11040 case 'modules':11041 $this->loadModulesXml($element,$configPath);11042 break;11043 case 'services':11044 $this->loadServicesXml($element,$configPath);11045 break;11046 case 'parameters':11047 $this->loadParametersXml($element,$configPath);11048 break;11049 case 'include':11050 $this->loadExternalXml($element,$configPath);11051 break;11052 default:11053 break;11054 }11055 }11056 }11057 protected function loadPathsPhp($pathsNode, $configPath)11058 {11059 if(isset($pathsNode['aliases']) && is_array($pathsNode['aliases']))11060 {11061 foreach($pathsNode['aliases'] as $id=>$path)11062 {11063 $path=str_replace('\\','/',$path);11064 if(preg_match('/^\\/|.:\\/|.:\\\\/',$path)) $p=realpath($path);11065 else11066 $p=realpath($configPath.DIRECTORY_SEPARATOR.$path);11067 if($p===false || !is_dir($p))11068 throw new TConfigurationException('appconfig_aliaspath_invalid',$id,$path);11069 if(isset($this->_aliases[$id]))11070 throw new TConfigurationException('appconfig_alias_redefined',$id);11071 $this->_aliases[$id]=$p;11072 }11073 }11074 if(isset($pathsNode['using']) && is_array($pathsNode['using']))11075 {11076 foreach($pathsNode['using'] as $namespace)11077 {11078 $this->_usings[] = $namespace;11079 }11080 }11081 }11082 protected function loadPathsXml($pathsNode,$configPath)11083 {11084 foreach($pathsNode->getElements() as $element)11085 {11086 switch($element->getTagName())11087 {11088 case 'alias':11089 {11090 if(($id=$element->getAttribute('id'))!==null && ($path=$element->getAttribute('path'))!==null)11091 {11092 $path=str_replace('\\','/',$path);11093 if(preg_match('/^\\/|.:\\/|.:\\\\/',$path)) $p=realpath($path);11094 else11095 $p=realpath($configPath.DIRECTORY_SEPARATOR.$path);11096 if($p===false || !is_dir($p))11097 throw new TConfigurationException('appconfig_aliaspath_invalid',$id,$path);11098 if(isset($this->_aliases[$id]))11099 throw new TConfigurationException('appconfig_alias_redefined',$id);11100 $this->_aliases[$id]=$p;11101 }11102 else11103 throw new TConfigurationException('appconfig_alias_invalid');11104 $this->_empty=false;11105 break;11106 }11107 case 'using':11108 {11109 if(($namespace=$element->getAttribute('namespace'))!==null)11110 $this->_usings[]=$namespace;11111 else11112 throw new TConfigurationException('appconfig_using_invalid');11113 $this->_empty=false;11114 break;11115 }11116 default:11117 throw new TConfigurationException('appconfig_paths_invalid',$element->getTagName());11118 }11119 }11120 }11121 protected function loadModulesPhp($modulesNode, $configPath)11122 {11123 foreach($modulesNode as $id=>$module)11124 {11125 if(!isset($module['class']))11126 throw new TConfigurationException('appconfig_moduletype_required',$id);11127 $type = $module['class'];11128 unset($module['class']);11129 $properties = array();11130 if(isset($module['properties']))11131 {11132 $properties = $module['properties'];11133 unset($module['properties']);11134 }11135 $properties['id'] = $id;11136 $this->_modules[$id]=array($type,$properties,$module);11137 $this->_empty=false;11138 }11139 }11140 protected function loadModulesXml($modulesNode,$configPath)11141 {11142 foreach($modulesNode->getElements() as $element)11143 {11144 if($element->getTagName()==='module')11145 {11146 $properties=$element->getAttributes();11147 $id=$properties->itemAt('id');11148 $type=$properties->remove('class');11149 if($type===null)11150 throw new TConfigurationException('appconfig_moduletype_required',$id);11151 $element->setParent(null);11152 if($id===null)11153 $this->_modules[]=array($type,$properties->toArray(),$element);11154 else11155 $this->_modules[$id]=array($type,$properties->toArray(),$element);11156 $this->_empty=false;11157 }11158 else11159 throw new TConfigurationException('appconfig_modules_invalid',$element->getTagName());11160 }11161 }11162 protected function loadServicesPhp($servicesNode,$configPath)11163 {11164 foreach($servicesNode as $id => $service)11165 {11166 if(!isset($service['class']))11167 throw new TConfigurationException('appconfig_servicetype_required');11168 $type = $service['class'];11169 $properties = isset($service['properties']) ? $service['properties'] : array();11170 unset($service['properties']);11171 $properties['id'] = $id;11172 $this->_services[$id] = array($type,$properties,$service);11173 $this->_empty = false;11174 }11175 }11176 protected function loadServicesXml($servicesNode,$configPath)11177 {11178 foreach($servicesNode->getElements() as $element)11179 {11180 if($element->getTagName()==='service')11181 {11182 $properties=$element->getAttributes();11183 if(($id=$properties->itemAt('id'))===null)11184 throw new TConfigurationException('appconfig_serviceid_required');11185 if(($type=$properties->remove('class'))===null)11186 throw new TConfigurationException('appconfig_servicetype_required',$id);11187 $element->setParent(null);11188 $this->_services[$id]=array($type,$properties->toArray(),$element);11189 $this->_empty=false;11190 }11191 else11192 throw new TConfigurationException('appconfig_services_invalid',$element->getTagName());11193 }11194 }11195 protected function loadParametersPhp($parametersNode,$configPath)11196 {11197 foreach($parametersNode as $id => $parameter)11198 {11199 if(is_array($parameter))11200 {11201 if(isset($parameter['class']))11202 {11203 $type = $parameter['class'];11204 unset($parameter['class']);11205 $properties = isset($service['properties']) ? $service['properties'] : array();11206 $properties['id'] = $id;11207 $this->_parameters[$id] = array($type,$properties);11208 }11209 }11210 else11211 {11212 $this->_parameters[$id] = $parameter;11213 }11214 }11215 }11216 protected function loadParametersXml($parametersNode,$configPath)11217 {11218 foreach($parametersNode->getElements() as $element)11219 {11220 if($element->getTagName()==='parameter')11221 {11222 $properties=$element->getAttributes();11223 if(($id=$properties->remove('id'))===null)11224 throw new TConfigurationException('appconfig_parameterid_required');11225 if(($type=$properties->remove('class'))===null)11226 {11227 if(($value=$properties->remove('value'))===null)11228 $this->_parameters[$id]=$element;11229 else11230 $this->_parameters[$id]=$value;11231 }11232 else11233 $this->_parameters[$id]=array($type,$properties->toArray());11234 $this->_empty=false;11235 }11236 else11237 throw new TConfigurationException('appconfig_parameters_invalid',$element->getTagName());11238 }11239 }11240 protected function loadExternalPhp($includeNode,$configPath)11241 {11242 foreach($includeNode as $include)11243 {11244 $when = isset($include['when'])?true:false;11245 if(!isset($include['file']))11246 throw new TConfigurationException('appconfig_includefile_required');11247 $filePath = $include['file'];11248 if(isset($this->_includes[$filePath]))11249 $this->_includes[$filePath]='('.$this->_includes[$filePath].') || ('.$when.')';11250 else11251 $$this->_includes[$filePath]=$when;11252 $this->_empty=false;11253 }11254 }11255 protected function loadExternalXml($includeNode,$configPath)11256 {11257 if(($when=$includeNode->getAttribute('when'))===null)11258 $when=true;11259 if(($filePath=$includeNode->getAttribute('file'))===null)11260 throw new TConfigurationException('appconfig_includefile_required');11261 if(isset($this->_includes[$filePath]))11262 $this->_includes[$filePath]='('.$this->_includes[$filePath].') || ('.$when.')';11263 else11264 $this->_includes[$filePath]=$when;11265 $this->_empty=false;11266 }11267 public function getProperties()11268 {11269 return $this->_properties;11270 }11271 public function getAliases()11272 {11273 return $this->_aliases;11274 }11275 public function getUsings()11276 {11277 return $this->_usings;11278 }11279 public function getModules()11280 {11281 return $this->_modules;11282 }11283 public function getServices()11284 {11285 return $this->_services;11286 }11287 public function getParameters()11288 {11289 return $this->_parameters;11290 }11291 public function getExternalConfigurations()11292 {11293 return $this->_includes;11294 }11295}11296class TApplicationStatePersister extends TModule implements IStatePersister11297{11298 const CACHE_NAME='prado:appstate';11299 public function init($config)11300 {11301 $this->getApplication()->setApplicationStatePersister($this);11302 }11303 protected function getStateFilePath()11304 {11305 return $this->getApplication()->getRuntimePath().'/global.cache';11306 }11307 public function load()11308 {11309 if(($cache=$this->getApplication()->getCache())!==null && ($value=$cache->get(self::CACHE_NAME))!==false)11310 return unserialize($value);11311 else11312 {11313 if(($content=@file_get_contents($this->getStateFilePath()))!==false)11314 return unserialize($content);11315 else11316 return null;11317 }11318 }11319 public function save($state)11320 {11321 $content=serialize($state);11322 $saveFile=true;11323 if(($cache=$this->getApplication()->getCache())!==null)11324 {11325 if($cache->get(self::CACHE_NAME)===$content)11326 $saveFile=false;11327 else11328 $cache->set(self::CACHE_NAME,$content);11329 }11330 if($saveFile)11331 {11332 $fileName=$this->getStateFilePath();11333 file_put_contents($fileName,$content,LOCK_EX);11334 }11335 }11336}11337class TShellApplication extends TApplication11338{11339 public function run()11340 {11341 $this->initApplication();11342 }11343}11344?>...

Full Screen

Full Screen

Rule.php

Source:Rule.php Github

copy

Full Screen

...48 self::ensureKeyword($arr);49 self::ensureName($arr);50 self::ensureDescription($arr);51 self::ensureChildren($arr);52 self::ensureId($arr);53 return new self(54 Location::fromArray($arr['location']),55 array_values(array_map(fn (array $member) => Tag::fromArray($member), $arr['tags'])),56 (string) $arr['keyword'],57 (string) $arr['name'],58 (string) $arr['description'],59 array_values(array_map(fn (array $member) => RuleChild::fromArray($member), $arr['children'])),60 (string) $arr['id'],61 );62 }63 /**64 * @psalm-assert array{location: array} $arr65 */66 private static function ensureLocation(array $arr): void67 {68 if (!array_key_exists('location', $arr)) {69 throw new SchemaViolationException('Property \'location\' is required but was not found');70 }71 if (array_key_exists('location', $arr) && !is_array($arr['location'])) {72 throw new SchemaViolationException('Property \'location\' was not array');73 }74 }75 /**76 * @psalm-assert array{tags: array} $arr77 */78 private static function ensureTags(array $arr): void79 {80 if (!array_key_exists('tags', $arr)) {81 throw new SchemaViolationException('Property \'tags\' is required but was not found');82 }83 if (array_key_exists('tags', $arr) && !is_array($arr['tags'])) {84 throw new SchemaViolationException('Property \'tags\' was not array');85 }86 }87 /**88 * @psalm-assert array{keyword: string|int|bool} $arr89 */90 private static function ensureKeyword(array $arr): void91 {92 if (!array_key_exists('keyword', $arr)) {93 throw new SchemaViolationException('Property \'keyword\' is required but was not found');94 }95 if (array_key_exists('keyword', $arr) && is_array($arr['keyword'])) {96 throw new SchemaViolationException('Property \'keyword\' was array');97 }98 }99 /**100 * @psalm-assert array{name: string|int|bool} $arr101 */102 private static function ensureName(array $arr): void103 {104 if (!array_key_exists('name', $arr)) {105 throw new SchemaViolationException('Property \'name\' is required but was not found');106 }107 if (array_key_exists('name', $arr) && is_array($arr['name'])) {108 throw new SchemaViolationException('Property \'name\' was array');109 }110 }111 /**112 * @psalm-assert array{description: string|int|bool} $arr113 */114 private static function ensureDescription(array $arr): void115 {116 if (!array_key_exists('description', $arr)) {117 throw new SchemaViolationException('Property \'description\' is required but was not found');118 }119 if (array_key_exists('description', $arr) && is_array($arr['description'])) {120 throw new SchemaViolationException('Property \'description\' was array');121 }122 }123 /**124 * @psalm-assert array{children: array} $arr125 */126 private static function ensureChildren(array $arr): void127 {128 if (!array_key_exists('children', $arr)) {129 throw new SchemaViolationException('Property \'children\' is required but was not found');130 }131 if (array_key_exists('children', $arr) && !is_array($arr['children'])) {132 throw new SchemaViolationException('Property \'children\' was not array');133 }134 }135 /**136 * @psalm-assert array{id: string|int|bool} $arr137 */138 private static function ensureId(array $arr): void139 {140 if (!array_key_exists('id', $arr)) {141 throw new SchemaViolationException('Property \'id\' is required but was not found');142 }143 if (array_key_exists('id', $arr) && is_array($arr['id'])) {144 throw new SchemaViolationException('Property \'id\' was array');145 }146 }147}...

Full Screen

Full Screen

ensureId

Using AI Code Generation

copy

Full Screen

1require_once 'Rule.php';2$rule = new Rule();3$rule->ensureId(2);4require_once 'Rule.php';5$rule = new Rule();6$rule->ensureId(3);7require_once 'Rule.php';8$rule = new Rule();9$rule->ensureId(4);10require_once 'Rule.php';11$rule = new Rule();12$rule->ensureId(5);13require_once 'Rule.php';14$rule = new Rule();15$rule->ensureId(6);16require_once 'Rule.php';17$rule = new Rule();18$rule->ensureId(7);19require_once 'Rule.php';20$rule = new Rule();21$rule->ensureId(8);22require_once 'Rule.php';23$rule = new Rule();24$rule->ensureId(9);25require_once 'Rule.php';26$rule = new Rule();27$rule->ensureId(10);28require_once 'Rule.php';29$rule = new Rule();30$rule->ensureId(11);31require_once 'Rule.php';32$rule = new Rule();33$rule->ensureId(12);34require_once 'Rule.php';35$rule = new Rule();36$rule->ensureId(13);37require_once 'Rule.php';38$rule = new Rule();39$rule->ensureId(14);

Full Screen

Full Screen

ensureId

Using AI Code Generation

copy

Full Screen

1$rule = new Rule();2$rule->ensureId($id);3$rule = new Rule();4$rule->ensureId($id);5$rule = new Rule();6$rule->ensureId($id);7$rule = new Rule();8$rule->ensureId($id);9$rule = new Rule();10$rule->ensureId($id);11$rule = new Rule();12$rule->ensureId($id);13$rule = new Rule();14$rule->ensureId($id);15$rule = new Rule();16$rule->ensureId($id);17$rule = new Rule();18$rule->ensureId($id);19$rule = new Rule();20$rule->ensureId($id);21$rule = new Rule();22$rule->ensureId($id);23$rule = new Rule();24$rule->ensureId($id);25$rule = new Rule();26$rule->ensureId($id);27$rule = new Rule();28$rule->ensureId($id);29$rule = new Rule();30$rule->ensureId($id);31$rule = new Rule();32$rule->ensureId($id);

Full Screen

Full Screen

ensureId

Using AI Code Generation

copy

Full Screen

1$rule = new Rule();2$rule->ensureId("1");3$rule->ensureId("2");4$rule->ensureId("3");5$rule->ensureId("4");6$rule->ensureId("5");7$rule->ensureId("6");8$rule->ensureId("7");9$rule->ensureId("8");10$rule->ensureId("9");11$rule->ensureId("10");12$rule->ensureId("11");13$rule->ensureId("12");14$rule->ensureId("13");15$rule->ensureId("14");16$rule->ensureId("15");17$rule->ensureId("16");18$rule->ensureId("17");19$rule->ensureId("18");20$rule->ensureId("19");21$rule->ensureId("20");22$rule->ensureId("21");23$rule->ensureId("22");24$rule->ensureId("23");25$rule->ensureId("24");26$rule->ensureId("25");27$rule->ensureId("26");28$rule->ensureId("27");29$rule->ensureId("28");30$rule->ensureId("29");31$rule->ensureId("30");32$rule->ensureId("31");33$rule->ensureId("32");34$rule->ensureId("33");35$rule->ensureId("34");36$rule->ensureId("35");37$rule->ensureId("36");38$rule->ensureId("37");39$rule->ensureId("38");40$rule->ensureId("39");41$rule->ensureId("40");42$rule->ensureId("41");43$rule->ensureId("42");44$rule->ensureId("43");45$rule->ensureId("44");46$rule->ensureId("45");47$rule->ensureId("46");48$rule->ensureId("47");49$rule->ensureId("48");50$rule->ensureId("49");51$rule->ensureId("50");52$rule->ensureId("51");53$rule->ensureId("52");54$rule->ensureId("53");55$rule->ensureId("54");56$rule->ensureId("55");57$rule->ensureId("56");58$rule->ensureId("57");59$rule->ensureId("58");60$rule->ensureId("59");61$rule->ensureId("60");62$rule->ensureId("61");

Full Screen

Full Screen

ensureId

Using AI Code Generation

copy

Full Screen

1$rule = new Rule();2$rule->ensureId(1);3$rule = new Rule();4$rule->ensureId(1);5class Rule {6 private static $id;7 public static function ensureId($id) {8 if (self::$id === null) {9 self::$id = $id;10 } else if (self::$id != $id) {11 throw new Exception('Id already set to ' . self::$id);12 }13 }14}

Full Screen

Full Screen

ensureId

Using AI Code Generation

copy

Full Screen

1require_once('Rule.php');2$rule = new Rule();3$rule->ensureId(1);4require_once('Rule.php');5$rule = new Rule();6$rule->ensureId(1);7require_once('Rule.php');8$rule = new Rule();9$rule->ensureId(1);10require_once('Rule.php');11$rule = new Rule();12$rule->ensureId(1);13require_once('Rule.php');14$rule = new Rule();15$rule->ensureId(1);16require_once('Rule.php');17$rule = new Rule();18$rule->ensureId(1);19require_once('Rule.php');20$rule = new Rule();21$rule->ensureId(1);22require_once('Rule.php');23$rule = new Rule();24$rule->ensureId(1);25require_once('Rule.php');26$rule = new Rule();27$rule->ensureId(1);28require_once('Rule.php');29$rule = new Rule();30$rule->ensureId(1);31require_once('Rule.php');32$rule = new Rule();33$rule->ensureId(1);34require_once('Rule.php');35$rule = new Rule();36$rule->ensureId(1);

Full Screen

Full Screen

ensureId

Using AI Code Generation

copy

Full Screen

1$rule = new Rule();2$rule->ensureId( $rule_id );3$rule = new Rule();4$rule->ensureId( $rule_id );5$rule = new Rule();6$rule->ensureId( $rule_id );7$rule = new Rule();8$rule->ensureId( $rule_id );9$rule = new Rule();10$rule->ensureId( $rule_id );11$rule = new Rule();12$rule->ensureId( $rule_id );13$rule = new Rule();14$rule->ensureId( $rule_id );15$rule = new Rule();16$rule->ensureId( $rule_id );17$rule = new Rule();18$rule->ensureId( $rule_id );19$rule = new Rule();20$rule->ensureId( $rule_id );21$rule = new Rule();22$rule->ensureId( $rule_id );23$rule = new Rule();24$rule->ensureId( $rule_id );25$rule = new Rule();26$rule->ensureId( $rule_id );27$rule = new Rule();28$rule->ensureId( $rule_id );29$rule = new Rule();30$rule->ensureId( $rule_id );

Full Screen

Full Screen

ensureId

Using AI Code Generation

copy

Full Screen

1require_once __DIR__ . '/vendor/autoload.php';2use \Respect\Validation\Validator as v;3use \Respect\Validation\Exceptions\NestedValidationExceptionInterface;4try {5 v::numeric()->ensureId(1)->assert('a');6} catch (NestedValidationExceptionInterface $e) {7 echo $e->getMainMessage() . "8";9}

Full Screen

Full Screen

ensureId

Using AI Code Generation

copy

Full Screen

1require_once 'Rule.php';2$rule = new Rule();3$rule->ensureId(2);4echo $rule->getId();5PHP: How to use the get_class_methods() function6PHP: How to use the get_class_vars() function7PHP: How to use the get_declared_classes() function8PHP: How to use the get_declared_interfaces() function9PHP: How to use the get_declared_traits() function10PHP: How to use the get_object_vars() function11PHP: How to use the get_parent_class() function12PHP: How to use the get_class() function13PHP: How to use the get_called_class() function14PHP: How to use the get_class_methods() function15PHP: How to use the get_class_vars() function16PHP: How to use the get_declared_classes() function17PHP: How to use the get_declared_interfaces() function18PHP: How to use the get_declared_traits() function19PHP: How to use the get_object_vars() function20PHP: How to use the get_parent_class() function21PHP: How to use the get_class() function22PHP: How to use the get_called_class() function23PHP: How to use the get_class_methods() function24PHP: How to use the get_class_vars() function25PHP: How to use the get_declared_classes() function26PHP: How to use the get_declared_interfaces() function27PHP: How to use the get_declared_traits() function28PHP: How to use the get_object_vars() function29PHP: How to use the get_parent_class() function30PHP: How to use the get_class() function31PHP: How to use the get_called_class() function32PHP: How to use the get_class_methods() function33PHP: How to use the get_class_vars() function34PHP: How to use the get_declared_classes() function35PHP: How to use the get_declared_interfaces() function36PHP: How to use the get_declared_traits() function37PHP: How to use the get_object_vars() function

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Cucumber Common Library automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Trigger ensureId code on LambdaTest Cloud Grid

Execute automation tests with ensureId on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful