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 && !$t