Files
yii/framework/yiilite.php
2008-12-25 16:21:15 +00:00

6571 lines
180 KiB
PHP

<?php
/**
* Yii bootstrap file.
*
* This file is automatically generated using 'build lite' command.
* It is the result of merging commonly used Yii class files with
* comments and trace statements removed away.
*
* By using this file instead of yii.php, an Yii application may
* improve performance due to the reduction of PHP parsing time.
* The performance improvement is especially obvious when PHP APC extension
* is enabled.
*
* DO NOT modify this file manually.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
* @version $Id$
* @since 1.0
*/
defined('YII_BEGIN_TIME') or define('YII_BEGIN_TIME',microtime(true));
defined('YII_DEBUG') or define('YII_DEBUG',false);
defined('YII_ENABLE_EXCEPTION_HANDLER') or define('YII_ENABLE_EXCEPTION_HANDLER',true);
defined('YII_ENABLE_ERROR_HANDLER') or define('YII_ENABLE_ERROR_HANDLER',true);
defined('YII_PATH') or define('YII_PATH',dirname(__FILE__));
class YiiBase
{
private static $_aliases=array('system'=>YII_PATH); // alias => path
private static $_imports=array(); // alias => class name or directory
private static $_classes=array();
private static $_app;
private static $_logger;
public static function getVersion()
{
return '1.1-dev';
}
public static function createWebApplication($config=null)
{
return new CWebApplication($config);
}
public static function createConsoleApplication($config=null)
{
return new CConsoleApplication($config);
}
public static function app()
{
return self::$_app;
}
public static function setApplication($app)
{
if(self::$_app===null || $app===null)
self::$_app=$app;
else
throw new CException(Yii::t('yii','Yii application can only be created once.'));
}
public static function getFrameworkPath()
{
return YII_PATH;
}
public static function createComponent($config)
{
if(is_string($config))
{
$type=$config;
$config=array();
}
else if(isset($config['class']))
{
$type=$config['class'];
unset($config['class']);
}
else
throw new CException(Yii::t('yii','Object configuration must be an array containing a "class" element.'));
if(!class_exists($type,false))
$type=Yii::import($type,true);
if(($n=func_num_args())>1)
{
$args=func_get_args();
for($s='$args[1]',$i=2;$i<$n;++$i)
$s.=",\$args[$i]";
eval("\$object=new $type($s);");
}
else
$object=new $type;
foreach($config as $key=>$value)
$object->$key=$value;
return $object;
}
public static function import($alias,$forceInclude=false)
{
if(isset(self::$_imports[$alias])) // previously imported
return self::$_imports[$alias];
if(class_exists($alias,false))
return self::$_imports[$alias]=$alias;
if(isset(self::$_coreClasses[$alias]) || ($pos=strrpos($alias,'.'))===false) // a simple class name
{
self::$_imports[$alias]=$alias;
if($forceInclude && !class_exists($alias,false))
{
if(isset(self::$_coreClasses[$alias])) // a core class
require(YII_PATH.self::$_coreClasses[$alias]);
else
require($alias.'.php');
}
return $alias;
}
if(($className=(string)substr($alias,$pos+1))!=='*' && class_exists($className,false))
return self::$_imports[$alias]=$className;
if(($path=self::getPathOfAlias($alias))!==false)
{
if($className!=='*')
{
self::$_imports[$alias]=$className;
if($forceInclude)
require($path.'.php');
else
self::$_classes[$className]=$path.'.php';
return $className;
}
else // a directory
{
set_include_path(get_include_path().PATH_SEPARATOR.$path);
return self::$_imports[$alias]=$path;
}
}
else
throw new CException(Yii::t('yii','Alias "{alias}" is invalid. Make sure it points to an existing directory or file.',
array('{alias}'=>$alias)));
}
public static function getPathOfAlias($alias)
{
if(isset(self::$_aliases[$alias]))
return self::$_aliases[$alias];
else if(($pos=strpos($alias,'.'))!==false)
{
$rootAlias=substr($alias,0,$pos);
if(isset(self::$_aliases[$rootAlias]))
return self::$_aliases[$alias]=rtrim(self::$_aliases[$rootAlias].DIRECTORY_SEPARATOR.str_replace('.',DIRECTORY_SEPARATOR,substr($alias,$pos+1)),'*'.DIRECTORY_SEPARATOR);
}
return self::$_aliases[$alias]=false;
}
public static function setPathOfAlias($alias,$path)
{
if($path===null)
unset(self::$_aliases[$alias]);
else
self::$_aliases[$alias]=rtrim($path,'\\/');
}
public static function autoload($className)
{
// use include so that the error PHP file may appear
if(isset(self::$_coreClasses[$className]))
include(YII_PATH.self::$_coreClasses[$className]);
else if(isset(self::$_classes[$className]))
include(self::$_classes[$className]);
else
include($className.'.php');
}
public static function trace($msg,$category='application')
{
if(YII_DEBUG)
self::log($msg,CLogger::LEVEL_TRACE,$category);
}
public static function log($msg,$level=CLogger::LEVEL_INFO,$category='application')
{
if(self::$_logger===null)
self::$_logger=new CLogger;
self::$_logger->log($msg,$level,$category);
}
public static function beginProfile($token,$category='application')
{
self::log('begin:'.$token,CLogger::LEVEL_PROFILE,$category);
}
public static function endProfile($token,$category='application')
{
self::log('end:'.$token,CLogger::LEVEL_PROFILE,$category);
}
public static function getLogger()
{
if(self::$_logger!==null)
return self::$_logger;
else
return self::$_logger=new CLogger;
}
public static function powered()
{
return 'Powered by <a href="http://www.yiiframework.com/">Yii Framework</a>.';
}
public static function t($category,$message,$params=array(),$source=null)
{
if(self::$_app!==null)
{
if($source===null)
$source=$category==='yii'?'coreMessages':'messages';
if(($source=self::$_app->getComponent($source))!==null)
$message=$source->translate($category,$message);
}
return $params!==array() ? strtr($message,$params) : $message;
}
private static $_coreClasses=array(
'CApplication' => '/base/CApplication.php',
'CApplicationComponent' => '/base/CApplicationComponent.php',
'CComponent' => '/base/CComponent.php',
'CErrorHandler' => '/base/CErrorHandler.php',
'CException' => '/base/CException.php',
'CHttpException' => '/base/CHttpException.php',
'CModel' => '/base/CModel.php',
'CSecurityManager' => '/base/CSecurityManager.php',
'CStatePersister' => '/base/CStatePersister.php',
'CApcCache' => '/caching/CApcCache.php',
'CCache' => '/caching/CCache.php',
'CDbCache' => '/caching/CDbCache.php',
'CMemCache' => '/caching/CMemCache.php',
'CCacheDependency' => '/caching/dependencies/CCacheDependency.php',
'CChainedCacheDependency' => '/caching/dependencies/CChainedCacheDependency.php',
'CDbCacheDependency' => '/caching/dependencies/CDbCacheDependency.php',
'CDirectoryCacheDependency' => '/caching/dependencies/CDirectoryCacheDependency.php',
'CFileCacheDependency' => '/caching/dependencies/CFileCacheDependency.php',
'CGlobalStateCacheDependency' => '/caching/dependencies/CGlobalStateCacheDependency.php',
'CAttributeCollection' => '/collections/CAttributeCollection.php',
'CConfiguration' => '/collections/CConfiguration.php',
'CList' => '/collections/CList.php',
'CMap' => '/collections/CMap.php',
'CQueue' => '/collections/CQueue.php',
'CStack' => '/collections/CStack.php',
'CTypedList' => '/collections/CTypedList.php',
'CConsoleApplication' => '/console/CConsoleApplication.php',
'CConsoleCommand' => '/console/CConsoleCommand.php',
'CConsoleCommandRunner' => '/console/CConsoleCommandRunner.php',
'CHelpCommand' => '/console/CHelpCommand.php',
'CDbCommand' => '/db/CDbCommand.php',
'CDbConnection' => '/db/CDbConnection.php',
'CDbDataReader' => '/db/CDbDataReader.php',
'CDbException' => '/db/CDbException.php',
'CDbTransaction' => '/db/CDbTransaction.php',
'CActiveFinder' => '/db/ar/CActiveFinder.php',
'CActiveRecord' => '/db/ar/CActiveRecord.php',
'CDbColumnSchema' => '/db/schema/CDbColumnSchema.php',
'CDbCommandBuilder' => '/db/schema/CDbCommandBuilder.php',
'CDbCriteria' => '/db/schema/CDbCriteria.php',
'CDbSchema' => '/db/schema/CDbSchema.php',
'CDbTableSchema' => '/db/schema/CDbTableSchema.php',
'CMysqlColumnSchema' => '/db/schema/mysql/CMysqlColumnSchema.php',
'CMysqlSchema' => '/db/schema/mysql/CMysqlSchema.php',
'CMysqlTableSchema' => '/db/schema/mysql/CMysqlTableSchema.php',
'CPgsqlColumnSchema' => '/db/schema/pgsql/CPgsqlColumnSchema.php',
'CPgsqlSchema' => '/db/schema/pgsql/CPgsqlSchema.php',
'CPgsqlTableSchema' => '/db/schema/pgsql/CPgsqlTableSchema.php',
'CSqliteColumnSchema' => '/db/schema/sqlite/CSqliteColumnSchema.php',
'CSqliteCommandBuilder' => '/db/schema/sqlite/CSqliteCommandBuilder.php',
'CSqliteSchema' => '/db/schema/sqlite/CSqliteSchema.php',
'CDateFormatter' => '/i18n/CDateFormatter.php',
'CDbMessageSource' => '/i18n/CDbMessageSource.php',
'CGettextMessageSource' => '/i18n/CGettextMessageSource.php',
'CLocale' => '/i18n/CLocale.php',
'CMessageSource' => '/i18n/CMessageSource.php',
'CNumberFormatter' => '/i18n/CNumberFormatter.php',
'CPhpMessageSource' => '/i18n/CPhpMessageSource.php',
'CGettextFile' => '/i18n/gettext/CGettextFile.php',
'CGettextMoFile' => '/i18n/gettext/CGettextMoFile.php',
'CGettextPoFile' => '/i18n/gettext/CGettextPoFile.php',
'CDbLogRoute' => '/logging/CDbLogRoute.php',
'CEmailLogRoute' => '/logging/CEmailLogRoute.php',
'CFileLogRoute' => '/logging/CFileLogRoute.php',
'CLogRoute' => '/logging/CLogRoute.php',
'CLogRouter' => '/logging/CLogRouter.php',
'CLogger' => '/logging/CLogger.php',
'CProfileLogRoute' => '/logging/CProfileLogRoute.php',
'CWebLogRoute' => '/logging/CWebLogRoute.php',
'CDateParser' => '/utils/CDateParser.php',
'CFileHelper' => '/utils/CFileHelper.php',
'CMarkdownParser' => '/utils/CMarkdownParser.php',
'CTimestamp' => '/utils/CTimestamp.php',
'CVarDumper' => '/utils/CVarDumper.php',
'CCaptchaValidator' => '/validators/CCaptchaValidator.php',
'CCompareValidator' => '/validators/CCompareValidator.php',
'CEmailValidator' => '/validators/CEmailValidator.php',
'CFileValidator' => '/validators/CFileValidator.php',
'CFilterValidator' => '/validators/CFilterValidator.php',
'CInlineValidator' => '/validators/CInlineValidator.php',
'CNumberValidator' => '/validators/CNumberValidator.php',
'CRangeValidator' => '/validators/CRangeValidator.php',
'CRegularExpressionValidator' => '/validators/CRegularExpressionValidator.php',
'CRequiredValidator' => '/validators/CRequiredValidator.php',
'CStringValidator' => '/validators/CStringValidator.php',
'CTypeValidator' => '/validators/CTypeValidator.php',
'CUniqueValidator' => '/validators/CUniqueValidator.php',
'CUrlValidator' => '/validators/CUrlValidator.php',
'CValidator' => '/validators/CValidator.php',
'CAssetManager' => '/web/CAssetManager.php',
'CBaseController' => '/web/CBaseController.php',
'CCacheHttpSession' => '/web/CCacheHttpSession.php',
'CClientScript' => '/web/CClientScript.php',
'CController' => '/web/CController.php',
'CDbHttpSession' => '/web/CDbHttpSession.php',
'CExtController' => '/web/CExtController.php',
'CFormModel' => '/web/CFormModel.php',
'CHttpCookie' => '/web/CHttpCookie.php',
'CHttpRequest' => '/web/CHttpRequest.php',
'CHttpSession' => '/web/CHttpSession.php',
'COutputEvent' => '/web/COutputEvent.php',
'CPagination' => '/web/CPagination.php',
'CTheme' => '/web/CTheme.php',
'CThemeManager' => '/web/CThemeManager.php',
'CUploadedFile' => '/web/CUploadedFile.php',
'CUrlManager' => '/web/CUrlManager.php',
'CWebApplication' => '/web/CWebApplication.php',
'CAction' => '/web/actions/CAction.php',
'CInlineAction' => '/web/actions/CInlineAction.php',
'CViewAction' => '/web/actions/CViewAction.php',
'CAccessControlFilter' => '/web/auth/CAccessControlFilter.php',
'CAuthAssignment' => '/web/auth/CAuthAssignment.php',
'CAuthItem' => '/web/auth/CAuthItem.php',
'CAuthManager' => '/web/auth/CAuthManager.php',
'CBaseUserIdentity' => '/web/auth/CBaseUserIdentity.php',
'CDbAuthManager' => '/web/auth/CDbAuthManager.php',
'CPhpAuthManager' => '/web/auth/CPhpAuthManager.php',
'CUserIdentity' => '/web/auth/CUserIdentity.php',
'CWebUser' => '/web/auth/CWebUser.php',
'CFilter' => '/web/filters/CFilter.php',
'CFilterChain' => '/web/filters/CFilterChain.php',
'CInlineFilter' => '/web/filters/CInlineFilter.php',
'CHtml' => '/web/helpers/CHtml.php',
'CJSON' => '/web/helpers/CJSON.php',
'CJavaScript' => '/web/helpers/CJavaScript.php',
'CPradoViewRenderer' => '/web/renderers/CPradoViewRenderer.php',
'CViewRenderer' => '/web/renderers/CViewRenderer.php',
'CWebService' => '/web/services/CWebService.php',
'CWebServiceAction' => '/web/services/CWebServiceAction.php',
'CWsdlGenerator' => '/web/services/CWsdlGenerator.php',
'CAutoComplete' => '/web/widgets/CAutoComplete.php',
'CClipWidget' => '/web/widgets/CClipWidget.php',
'CContentDecorator' => '/web/widgets/CContentDecorator.php',
'CFilterWidget' => '/web/widgets/CFilterWidget.php',
'CFlexWidget' => '/web/widgets/CFlexWidget.php',
'CHtmlPurifier' => '/web/widgets/CHtmlPurifier.php',
'CInputWidget' => '/web/widgets/CInputWidget.php',
'CMarkdown' => '/web/widgets/CMarkdown.php',
'CMaskedTextField' => '/web/widgets/CMaskedTextField.php',
'CMultiFileUpload' => '/web/widgets/CMultiFileUpload.php',
'COutputCache' => '/web/widgets/COutputCache.php',
'COutputProcessor' => '/web/widgets/COutputProcessor.php',
'CStarRating' => '/web/widgets/CStarRating.php',
'CTabView' => '/web/widgets/CTabView.php',
'CTextHighlighter' => '/web/widgets/CTextHighlighter.php',
'CTreeView' => '/web/widgets/CTreeView.php',
'CWidget' => '/web/widgets/CWidget.php',
'CCaptcha' => '/web/widgets/captcha/CCaptcha.php',
'CCaptchaAction' => '/web/widgets/captcha/CCaptchaAction.php',
'CBasePager' => '/web/widgets/pagers/CBasePager.php',
'CLinkPager' => '/web/widgets/pagers/CLinkPager.php',
'CListPager' => '/web/widgets/pagers/CListPager.php',
);
}
spl_autoload_register(array('YiiBase','autoload'));
class Yii extends YiiBase
{
}
class CComponent
{
private $_e;
public function __get($name)
{
$getter='get'.$name;
if(method_exists($this,$getter))
return $this->$getter();
else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name))
{
// duplicating getEventHandlers() here for performance
$name=strtolower($name);
if(!isset($this->_e[$name]))
$this->_e[$name]=new CList;
return $this->_e[$name];
}
else
throw new CException(Yii::t('yii','Property "{class}.{property}" is not defined.',
array('{class}'=>get_class($this), '{property}'=>$name)));
}
public function __set($name,$value)
{
$setter='set'.$name;
if(method_exists($this,$setter))
$this->$setter($value);
else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name))
{
// duplicating getEventHandlers() here for performance
$name=strtolower($name);
if(!isset($this->_e[$name]))
$this->_e[$name]=new CList;
$this->_e[$name]->add($value);
}
else if(method_exists($this,'get'.$name))
throw new CException(Yii::t('yii','Property "{class}.{property}" is read only.',
array('{class}'=>get_class($this), '{property}'=>$name)));
else
throw new CException(Yii::t('yii','Property "{class}.{property}" is not defined.',
array('{class}'=>get_class($this), '{property}'=>$name)));
}
public function __isset($name)
{
$getter='get'.$name;
if(method_exists($this,$getter))
return $this->$getter()!==null;
else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name))
{
$name=strtolower($name);
return isset($this->_e[$name]) && $this->_e[$name]->getCount();
}
else
return false;
}
public function __unset($name)
{
$setter='set'.$name;
if(method_exists($this,$setter))
$this->$setter(null);
else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name))
unset($this->_e[strtolower($name)]);
else if(method_exists($this,'get'.$name))
throw new CException(Yii::t('yii','Property "{class}.{property}" is read only.',
array('{class}'=>get_class($this), '{property}'=>$name)));
}
public function hasProperty($name)
{
return method_exists($this,'get'.$name) || method_exists($this,'set'.$name);
}
public function canGetProperty($name)
{
return method_exists($this,'get'.$name);
}
public function canSetProperty($name)
{
return method_exists($this,'set'.$name);
}
public function hasEvent($name)
{
return !strncasecmp($name,'on',2) && method_exists($this,$name);
}
public function hasEventHandler($name)
{
$name=strtolower($name);
return isset($this->_e[$name]) && $this->_e[$name]->getCount()>0;
}
public function getEventHandlers($name)
{
if($this->hasEvent($name))
{
$name=strtolower($name);
if(!isset($this->_e[$name]))
$this->_e[$name]=new CList;
return $this->_e[$name];
}
else
throw new CException(Yii::t('yii','Event "{class}.{event}" is not defined.',
array('{class}'=>get_class($this), '{event}'=>$name)));
}
public function attachEventHandler($name,$handler)
{
$this->getEventHandlers($name)->add($handler);
}
public function detachEventHandler($name,$handler)
{
if($this->hasEventHandler($name))
{
try
{
$this->getEventHandlers($name)->remove($handler);
return true;
}
catch(Exception $e)
{
}
}
return false;
}
public function raiseEvent($name,$event)
{
$name=strtolower($name);
if(isset($this->_e[$name]))
{
foreach($this->_e[$name] as $handler)
{
if(is_string($handler))
call_user_func($handler,$event);
else if(is_callable($handler,true))
{
// an array: 0 - object, 1 - method name
list($object,$method)=$handler;
if(is_string($object)) // static method call
call_user_func($handler,$event);
else if(method_exists($object,$method))
$object->$method($event);
else
throw new CException(Yii::t('yii','Event "{class}.{event}" is attached with an invalid handler "{handler}".',
array('{class}'=>get_class($this), '{event}'=>$name, '{handler}'=>$handler[1])));
}
else
throw new CException(Yii::t('yii','Event "{class}.{event}" is attached with an invalid handler "{handler}".',
array('{class}'=>get_class($this), '{event}'=>$name, '{handler}'=>gettype($handler))));
// stop further handling if param.handled is set true
if(($event instanceof CEvent) && $event->handled)
return;
}
}
else if(YII_DEBUG && !$this->hasEvent($name))
throw new CException(Yii::t('yii','Event "{class}.{event}" is not defined.',
array('{class}'=>get_class($this), '{event}'=>$name)));
}
}
class CEvent extends CComponent
{
public $sender;
public $handled=false;
public function __construct($sender=null)
{
$this->sender=$sender;
}
}
class CEnumerable
{
}
class CPropertyValue
{
public static function ensureBoolean($value)
{
if (is_string($value))
return !strcasecmp($value,'true') || $value!=0;
else
return (boolean)$value;
}
public static function ensureString($value)
{
if (is_bool($value))
return $value?'true':'false';
else
return (string)$value;
}
public static function ensureInteger($value)
{
return (integer)$value;
}
public static function ensureFloat($value)
{
return (float)$value;
}
public static function ensureArray($value)
{
if(is_string($value))
{
$value = trim($value);
$len = strlen($value);
if ($len >= 2 && $value[0] == '(' && $value[$len-1] == ')')
{
eval('$array=array'.$value.';');
return $array;
}
else
return $len>0?array($value):array();
}
else
return (array)$value;
}
public static function ensureObject($value)
{
return (object)$value;
}
public static function ensureEnum($value,$enumType)
{
static $types=array();
if(!isset($types[$enumType]))
$types[$enumType]=new ReflectionClass($enumType);
if($types[$enumType]->hasConstant($value))
return $value;
else
throw new CException(Yii::t('yii','Invalid enumerable value "{value}". Please make sure it is among ({enum}).',
array('{value}'=>$value, '{enum}'=>implode(', ',$types[$enumType]->getConstants()))));
}
}
abstract class CApplication extends CComponent
{
public $name='My Application';
public $charset='UTF-8';
public $preload=array();
public $sourceLanguage='en_us';
private $_id;
private $_basePath;
private $_runtimePath;
private $_extensionPath;
private $_globalState;
private $_stateChanged;
private $_params;
private $_components=array();
private $_componentConfig=array();
private $_ended=false;
private $_language;
abstract public function processRequest();
public function __construct($config=null)
{
Yii::setApplication($this);
$this->initSystemHandlers();
$this->registerCoreComponents();
$this->configure($config);
$this->init();
}
protected function init()
{
$this->preloadComponents();
}
public function __get($name)
{
if($this->hasComponent($name))
return $this->getComponent($name);
else
return parent::__get($name);
}
public function __isset($name)
{
if($this->hasComponent($name))
return $this->getComponent($name)!==null;
else
return parent::__isset($name);
}
public function run()
{
$this->onBeginRequest(new CEvent($this));
$this->processRequest();
$this->onEndRequest(new CEvent($this));
}
public function end($status=0)
{
$this->onEndRequest(new CEvent($this));
exit($status);
}
public function onBeginRequest($event)
{
$this->raiseEvent('onBeginRequest',$event);
}
public function onEndRequest($event)
{
if(!$this->_ended)
{
$this->_ended=true;
$this->raiseEvent('onEndRequest',$event);
}
}
public function getId()
{
if($this->_id!==null)
return $this->_id;
else
return $this->_id=md5($this->getBasePath().$this->name);
}
public function setId($id)
{
$this->_id=$id;
}
public function getBasePath()
{
return $this->_basePath;
}
public function setBasePath($path)
{
if(($this->_basePath=realpath($path))===false || !is_dir($this->_basePath))
throw new CException(Yii::t('yii','Application base path "{path}" is not a valid directory.',
array('{path}'=>$path)));
}
public function getRuntimePath()
{
if($this->_runtimePath!==null)
return $this->_runtimePath;
else
{
$this->setRuntimePath($this->getBasePath().DIRECTORY_SEPARATOR.'runtime');
return $this->_runtimePath;
}
}
public function setRuntimePath($path)
{
if(($runtimePath=realpath($path))===false || !is_dir($runtimePath) || !is_writable($runtimePath))
throw new CException(Yii::t('yii','Application runtime path "{path}" is not valid. Please make sure it is a directory writable by the Web server process.',
array('{path}'=>$path)));
$this->_runtimePath=$runtimePath;
}
final public function getExtensionPath()
{
if($this->_extensionPath!==null)
return $this->_extensionPath;
else
return $this->_extensionPath=$this->getBasePath().DIRECTORY_SEPARATOR.'extensions';
}
public function setImport($aliases)
{
foreach($aliases as $alias)
Yii::import($alias);
}
public function getLanguage()
{
return $this->_language===null ? $this->sourceLanguage : $this->_language;
}
public function setLanguage($language)
{
$this->_language=$language;
}
public function findLocalizedFile($srcFile,$srcLanguage=null,$language=null)
{
if($srcLanguage===null)
$srcLanguage=$this->sourceLanguage;
if($language===null)
$language=$this->getLanguage();
if($language===$srcLanguage)
return $srcFile;
$desiredFile=dirname($srcFile).DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.basename($srcFile);
return is_file($desiredFile) ? $desiredFile : $srcFile;
}
public function getLocale($localeID=null)
{
return CLocale::getInstance($localeID===null?$this->getLanguage():$localeID);
}
public function getNumberFormatter()
{
return $this->getLocale()->getNumberFormatter();
}
public function getDateFormatter()
{
return $this->getLocale()->getDateFormatter();
}
public function getDb()
{
return $this->getComponent('db');
}
public function getErrorHandler()
{
return $this->getComponent('errorHandler');
}
public function getSecurityManager()
{
return $this->getComponent('securityManager');
}
public function getStatePersister()
{
return $this->getComponent('statePersister');
}
public function getCache()
{
return $this->getComponent('cache');
}
public function getCoreMessages()
{
return $this->getComponent('coreMessages');
}
public function getMessages()
{
return $this->getComponent('messages');
}
public function getParams()
{
if($this->_params!==null)
return $this->_params;
else
return $this->_params=new CAttributeCollection;
}
public function setParams($value)
{
if(is_array($value))
$this->_params=new CAttributeCollection($value);
else
$this->_params=$value;
}
public function getGlobalState($key,$defaultValue=null)
{
if($this->_globalState===null)
$this->loadGlobalState();
if(isset($this->_globalState[$key]))
return $this->_globalState[$key];
else
return $defaultValue;
}
public function setGlobalState($key,$value,$defaultValue=null)
{
if($this->_globalState===null)
$this->loadGlobalState();
$this->_stateChanged=true;
if($value===$defaultValue)
unset($this->_globalState[$key]);
else
$this->_globalState[$key]=$value;
}
public function clearGlobalState($key)
{
if($this->_globalState===null)
$this->loadGlobalState();
if(isset($this->_globals[$key]))
{
$this->_stateChanged=true;
unset($this->_globals[$key]);
}
}
protected function loadGlobalState()
{
$persister=$this->getStatePersister();
if(($this->_globalState=$persister->load())===null)
$this->_globalState=array();
$this->_stateChanged=false;
$this->attachEventHandler('onEndRequest',array($this,'saveGlobalState'));
}
protected function saveGlobalState()
{
if($this->_stateChanged)
{
$persister=$this->getStatePersister();
$this->_stateChanged=false;
$persister->save($this->_globalState);
}
}
public function handleException($exception)
{
// disable error capturing to avoid recursive errors
restore_error_handler();
restore_exception_handler();
$category='exception.'.get_class($exception);
if($exception instanceof CHttpException)
$category.='.'.$exception->statusCode;
$message=(string)$exception;
if(isset($_SERVER['REQUEST_URI']))
$message.=' REQUEST_URI='.$_SERVER['REQUEST_URI'];
Yii::log($message,CLogger::LEVEL_ERROR,$category);
$event=new CExceptionEvent($this,$exception);
$this->onException($event);
if(!$event->handled)
{
// try an error handler
if(($handler=$this->getErrorHandler())!==null)
$handler->handle($event);
else
$this->displayException($exception);
}
$this->end(1);
}
public function handleError($code,$message,$file,$line)
{
if($code & error_reporting())
{
// disable error capturing to avoid recursive errors
restore_error_handler();
restore_exception_handler();
$log="$message ($file:$line)";
if(isset($_SERVER['REQUEST_URI']))
$log.=' REQUEST_URI='.$_SERVER['REQUEST_URI'];
Yii::log($log,CLogger::LEVEL_ERROR,'php');
$event=new CErrorEvent($this,$code,$message,$file,$line);
$this->onError($event);
if(!$event->handled)
{
// try an error handler
if(($handler=$this->getErrorHandler())!==null)
$handler->handle($event);
else
$this->displayError($code,$message,$file,$line);
}
$this->end(1);
}
}
public function onException($event)
{
$this->raiseEvent('onException',$event);
}
public function onError($event)
{
$this->raiseEvent('onError',$event);
}
public function displayError($code,$message,$file,$line)
{
if(YII_DEBUG)
{
echo "<h1>PHP Error [$code]</h1>\n";
echo "<p>$message ($file:$line)</p>\n";
echo '<pre>';
debug_print_backtrace();
echo '</pre>';
}
else
{
echo "<h1>PHP Error [$code]</h1>\n";
echo "<p>$message</p>\n";
}
}
public function displayException($exception)
{
if(YII_DEBUG)
{
echo '<h1>'.get_class($exception)."</h1>\n";
echo '<p>'.$exception->getMessage().' ('.$exception->getFile().':'.$exception->getLine().')</p>';
echo '<pre>'.$exception->getTraceAsString().'</pre>';
}
else
{
echo '<h1>'.get_class($exception)."</h1>\n";
echo '<p>'.$exception->getMessage().'</p>';
}
}
public function hasComponent($id)
{
return isset($this->_components[$id]) || isset($this->_componentConfig[$id]);
}
public function getComponent($id)
{
if(isset($this->_components[$id]))
return $this->_components[$id];
else if(isset($this->_componentConfig[$id]))
{
$config=$this->_componentConfig[$id];
unset($this->_componentConfig[$id]);
if(!isset($config['enabled']) || $config['enabled'])
{
unset($config['enabled']);
$component=Yii::createComponent($config);
$component->init();
return $this->_components[$id]=$component;
}
}
}
public function setComponent($id,$component)
{
$this->_components[$id]=$component;
if(!$component->getIsInitialized())
$component->init();
}
protected function configure($config)
{
if(is_string($config))
$config=require($config);
if(isset($config['basePath']))
{
$basePath=$config['basePath'];
unset($config['basePath']);
}
else
$basePath='protected';
$this->setBasePath($basePath);
Yii::setPathOfAlias('application',$this->getBasePath());
if(is_array($config))
{
foreach($config as $key=>$value)
$this->$key=$value;
}
}
protected function initSystemHandlers()
{
if(YII_ENABLE_EXCEPTION_HANDLER)
set_exception_handler(array($this,'handleException'));
if(YII_ENABLE_ERROR_HANDLER)
set_error_handler(array($this,'handleError'),error_reporting());
}
protected function registerCoreComponents()
{
$components=array(
'coreMessages'=>array(
'class'=>'CPhpMessageSource',
'language'=>'en_us',
'basePath'=>YII_PATH.DIRECTORY_SEPARATOR.'messages',
),
'db'=>array(
'class'=>'CDbConnection',
),
'messages'=>array(
'class'=>'CPhpMessageSource',
),
'errorHandler'=>array(
'class'=>'CErrorHandler',
),
'securityManager'=>array(
'class'=>'CSecurityManager',
),
'statePersister'=>array(
'class'=>'CStatePersister',
),
);
$this->setComponents($components);
}
protected function preloadComponents()
{
foreach($this->preload as $id)
$this->getComponent($id);
}
public function getComponents()
{
return $this->_components;
}
public function setComponents($components)
{
foreach($components as $id=>$component)
{
if($component instanceof IApplicationComponent)
$this->setComponent($id,$component);
else if(isset($this->_componentConfig[$id]))
$this->_componentConfig[$id]=CMap::mergeArray($this->_componentConfig[$id],$component);
else
$this->_componentConfig[$id]=$component;
}
}
}
class CExceptionEvent extends CEvent
{
public $exception;
public function __construct($sender,$exception)
{
$this->exception=$exception;
parent::__construct($sender);
}
}
class CErrorEvent extends CEvent
{
public $code;
public $message;
public $file;
public $line;
public function __construct($sender,$code,$message,$file,$line)
{
$this->code=$code;
$this->message=$message;
$this->file=$file;
$this->line=$line;
parent::__construct($sender);
}
}
class CWebApplication extends CApplication
{
public $defaultController='site';
public $layout='main';
public $controllerMap=array();
public $catchAllRequest;
private $_controllerPath;
private $_viewPath;
private $_systemViewPath;
private $_layoutPath;
private $_controller;
private $_homeUrl;
private $_theme;
public function processRequest()
{
if(is_array($this->catchAllRequest) && isset($this->catchAllRequest[0]))
{
$segs=explode('/',$this->catchAllRequest[0]);
$controllerID=$segs[0];
$actionID=isset($segs[1])?$segs[1]:'';
foreach(array_splice($this->catchAllRequest,1) as $name=>$value)
$_GET[$name]=$value;
}
else
list($controllerID,$actionID)=$this->resolveRequest();
$this->runController($controllerID,$actionID);
}
protected function resolveRequest()
{
$route=$this->getUrlManager()->parseUrl($this->getRequest());
if(($pos=strrpos($route,'/'))!==false)
return array(substr($route,0,$pos),(string)substr($route,$pos+1));
else
return array($route,'');
}
public function runController($controllerID,$actionID)
{
if(($controller=$this->createController($controllerID))!==null)
{
$oldController=$this->_controller;
$this->_controller=$controller;
$controller->init();
$controller->run($actionID);
$this->_controller=$oldController;
}
else
throw new CHttpException(404,Yii::t('yii','The requested controller "{controller}" does not exist.',
array('{controller}'=>$controllerID===''?$this->defaultController:$controllerID)));
}
protected function registerCoreComponents()
{
parent::registerCoreComponents();
$components=array(
'urlManager'=>array(
'class'=>'CUrlManager',
),
'request'=>array(
'class'=>'CHttpRequest',
),
'session'=>array(
'class'=>'CHttpSession',
),
'assetManager'=>array(
'class'=>'CAssetManager',
),
'user'=>array(
'class'=>'CWebUser',
),
'themeManager'=>array(
'class'=>'CThemeManager',
),
'authManager'=>array(
'class'=>'CPhpAuthManager',
),
'clientScript'=>array(
'class'=>'CClientScript',
),
);
$this->setComponents($components);
}
public function getRequest()
{
return $this->getComponent('request');
}
public function getUrlManager()
{
return $this->getComponent('urlManager');
}
public function getAuthManager()
{
return $this->getComponent('authManager');
}
public function getAssetManager()
{
return $this->getComponent('assetManager');
}
public function getSession()
{
return $this->getComponent('session');
}
public function getUser()
{
return $this->getComponent('user');
}
public function getViewRenderer()
{
return $this->getComponent('viewRenderer');
}
public function getClientScript()
{
return $this->getComponent('clientScript');
}
public function getThemeManager()
{
return $this->getComponent('themeManager');
}
public function getTheme()
{
if(is_string($this->_theme))
$this->_theme=$this->getThemeManager()->getTheme($this->_theme);
return $this->_theme;
}
public function setTheme($value)
{
$this->_theme=$value;
}
public function createUrl($route,$params=array(),$ampersand='&')
{
return $this->getUrlManager()->createUrl($route,$params,$ampersand);
}
public function createAbsoluteUrl($route,$params=array(),$schema='',$ampersand='&')
{
return $this->getRequest()->getHostInfo($schema).$this->createUrl($route,$params,$ampersand);
}
public function getBaseUrl()
{
return $this->getRequest()->getBaseUrl();
}
public function getHomeUrl()
{
if($this->_homeUrl===null)
{
if($this->getUrlManager()->showScriptName)
return $this->getRequest()->getScriptUrl();
else
return $this->getRequest()->getBaseUrl().'/';
}
else
return $this->_homeUrl;
}
public function setHomeUrl($value)
{
$this->_homeUrl=$value;
}
public function createController($id)
{
if($id==='')
$id=$this->defaultController;
if(!preg_match('/^\w+(\.\w+)*$/',$id))
return null;
if(isset($this->controllerMap[$id]))
return Yii::createComponent($this->controllerMap[$id],$id);
if(($pos=strrpos($id,'.'))!==false)
{
$classFile=str_replace('.',DIRECTORY_SEPARATOR,$id).'Controller';
$classFile[$pos+1]=strtoupper($classFile[$pos+1]);
$className=basename($classFile);
$classFile=$this->getControllerPath().DIRECTORY_SEPARATOR.$classFile.'.php';
}
else
{
$className=ucfirst($id).'Controller';
$classFile=$this->getControllerPath().DIRECTORY_SEPARATOR.$className.'.php';
}
if(is_file($classFile))
{
require_once($classFile);
if(class_exists($className,false) && is_subclass_of($className,'CController'))
return new $className($id);
}
}
public function getController()
{
return $this->_controller;
}
public function getControllerPath()
{
if($this->_controllerPath!==null)
return $this->_controllerPath;
else
return $this->_controllerPath=$this->getBasePath().DIRECTORY_SEPARATOR.'controllers';
}
public function setControllerPath($value)
{
if(($this->_controllerPath=realpath($value))===false || !is_dir($this->_controllerPath))
throw new CException(Yii::t('yii','The controller path "{path}" is not a valid directory.',
array('{path}'=>$value)));
}
public function getViewPath()
{
if($this->_viewPath!==null)
return $this->_viewPath;
else
return $this->_viewPath=$this->getBasePath().DIRECTORY_SEPARATOR.'views';
}
public function setViewPath($path)
{
if(($this->_viewPath=realpath($path))===false || !is_dir($this->_viewPath))
throw new CException(Yii::t('yii','The view path "{path}" is not a valid directory.',
array('{path}'=>$path)));
}
public function getSystemViewPath()
{
if($this->_systemViewPath!==null)
return $this->_systemViewPath;
else
return $this->_systemViewPath=$this->getViewPath().DIRECTORY_SEPARATOR.'system';
}
public function setSystemViewPath($path)
{
if(($this->_systemViewPath=realpath($path))===false || !is_dir($this->_systemViewPath))
throw new CException(Yii::t('yii','The system view path "{path}" is not a valid directory.',
array('{path}'=>$path)));
}
public function getLayoutPath()
{
if($this->_layoutPath!==null)
return $this->_layoutPath;
else
return $this->_layoutPath=$this->getViewPath().DIRECTORY_SEPARATOR.'layouts';
}
public function setLayoutPath($path)
{
if(($this->_layoutPath=realpath($path))===false || !is_dir($this->_layoutPath))
throw new CException(Yii::t('yii','The layout path "{path}" is not a valid directory.',
array('{path}'=>$path)));
}
}
class CMap extends CComponent implements IteratorAggregate,ArrayAccess,Countable
{
private $_d=array();
private $_r=false;
public function __construct($data=null,$readOnly=false)
{
if($data!==null)
$this->copyFrom($data);
$this->setReadOnly($readOnly);
}
public function getReadOnly()
{
return $this->_r;
}
protected function setReadOnly($value)
{
$this->_r=$value;
}
public function getIterator()
{
return new CMapIterator($this->_d);
}
public function count()
{
return $this->getCount();
}
public function getCount()
{
return count($this->_d);
}
public function getKeys()
{
return array_keys($this->_d);
}
public function itemAt($key)
{
if(isset($this->_d[$key]))
return $this->_d[$key];
else
return null;
}
public function add($key,$value)
{
if(!$this->_r)
$this->_d[$key]=$value;
else
throw new CException(Yii::t('yii','The map is read only.'));
}
public function remove($key)
{
if(!$this->_r)
{
if(isset($this->_d[$key]))
{
$value=$this->_d[$key];
unset($this->_d[$key]);
return $value;
}
else
{
// it is possible the value is null, which is not detected by isset
unset($this->_d[$key]);
return null;
}
}
else
throw new CException(Yii::t('yii','The map is read only.'));
}
public function clear()
{
foreach(array_keys($this->_d) as $key)
$this->remove($key);
}
public function contains($key)
{
return isset($this->_d[$key]) || array_key_exists($key,$this->_d);
}
public function toArray()
{
return $this->_d;
}
public function copyFrom($data)
{
if(is_array($data) || $data instanceof Traversable)
{
if($this->getCount()>0)
$this->clear();
if($data instanceof CMap)
$data=$data->_d;
foreach($data as $key=>$value)
$this->add($key,$value);
}
else if($data!==null)
throw new CException(Yii::t('yii','Map data must be an array or an object implementing Traversable.'));
}
public function mergeWith($data,$recursive=true)
{
if(is_array($data) || $data instanceof Traversable)
{
if($data instanceof CMap)
$data=$data->_d;
if($recursive)
{
if($data instanceof Traversable)
{
$d=array();
foreach($data as $key=>$value)
$d[$key]=$value;
$this->_d=self::mergeArray($this->_d,$d);
}
else
$this->_d=self::mergeArray($this->_d,$data);
}
else
{
foreach($data as $key=>$value)
$this->add($key,$value);
}
}
else if($data!==null)
throw new CException(Yii::t('yii','Map data must be an array or an object implementing Traversable.'));
}
public static function mergeArray($a,$b)
{
foreach($b as $k=>$v)
{
if(is_integer($k))
$a[]=$v;
else if(is_array($v) && isset($a[$k]) && is_array($a[$k]))
$a[$k]=self::mergeArray($a[$k],$v);
else
$a[$k]=$v;
}
return $a;
}
public function offsetExists($offset)
{
return $this->contains($offset);
}
public function offsetGet($offset)
{
return $this->itemAt($offset);
}
public function offsetSet($offset,$item)
{
$this->add($offset,$item);
}
public function offsetUnset($offset)
{
$this->remove($offset);
}
}
class CMapIterator implements Iterator
{
private $_d;
private $_keys;
private $_key;
public function __construct(&$data)
{
$this->_d=&$data;
$this->_keys=array_keys($data);
}
public function rewind()
{
$this->_key=reset($this->_keys);
}
public function key()
{
return $this->_key;
}
public function current()
{
return $this->_d[$this->_key];
}
public function next()
{
$this->_key=next($this->_keys);
}
public function valid()
{
return $this->_key!==false;
}
}
class CLogger extends CComponent
{
const LEVEL_TRACE='trace';
const LEVEL_WARNING='warning';
const LEVEL_ERROR='error';
const LEVEL_INFO='info';
const LEVEL_PROFILE='profile';
private $_logs=array();
private $_levels;
private $_categories;
public function log($message,$level='info',$category='application')
{
$this->_logs[]=array($message,$level,$category,microtime(true));
}
public function getLogs($levels='',$categories='')
{
$this->_levels=preg_split('/[\s,]+/',strtolower($levels),-1,PREG_SPLIT_NO_EMPTY);
$this->_categories=preg_split('/[\s,]+/',strtolower($categories),-1,PREG_SPLIT_NO_EMPTY);
if(empty($levels) && empty($categories))
return $this->_logs;
else if(empty($levels))
return array_values(array_filter(array_filter($this->_logs,array($this,'filterByCategory'))));
else if(empty($categories))
return array_values(array_filter(array_filter($this->_logs,array($this,'filterByLevel'))));
else
{
$ret=array_values(array_filter(array_filter($this->_logs,array($this,'filterByLevel'))));
return array_values(array_filter(array_filter($ret,array($this,'filterByCategory'))));
}
}
private function filterByCategory($value)
{
foreach($this->_categories as $category)
{
$cat=strtolower($value[2]);
if($cat===$category || (($c=rtrim($category,'.*'))!==$category && strpos($cat,$c)===0))
return $value;
}
return false;
}
private function filterByLevel($value)
{
return in_array(strtolower($value[1]),$this->_levels)?$value:false;
}
public function getExecutionTime()
{
return microtime(true)-YII_BEGIN_TIME;
}
public function getMemoryUsage()
{
if(function_exists('memory_get_usage'))
return memory_get_usage();
else
{
$output=array();
if(strncmp(PHP_OS,'WIN',3)===0)
{
exec('tasklist /FI "PID eq ' . getmypid() . '" /FO LIST',$output);
return isset($output[5])?preg_replace('/[\D]/','',$output[5])*1024 : 0;
}
else
{
$pid=getmypid();
exec("ps -eo%mem,rss,pid | grep $pid", $output);
$output=explode(" ",$output[0]);
return isset($output[1]) ? $output[1]*1024 : 0;
}
}
}
}
abstract class CApplicationComponent extends CComponent implements IApplicationComponent
{
private $_initialized=false;
public function init()
{
$this->_initialized=true;
}
public function getIsInitialized()
{
return $this->_initialized;
}
}
class CUrlManager extends CApplicationComponent
{
const CACHE_KEY='CUrlManager.rules';
const GET_FORMAT='get';
const PATH_FORMAT='path';
public $urlSuffix='';
public $showScriptName=true;
public $routeVar='r';
public $caseSensitive=true;
private $_urlFormat=self::GET_FORMAT;
private $_rules=array();
private $_groups=array();
private $_baseUrl;
public function init()
{
parent::init();
$this->processRules();
}
protected function processRules()
{
if(empty($this->_rules) || $this->getUrlFormat()===self::GET_FORMAT)
return;
if(($cache=Yii::app()->getCache())!==null)
{
$hash=md5(serialize($this->_rules));
if(($data=$cache->get(self::CACHE_KEY))!==false && isset($data[1]) && $data[1]===$hash)
{
$this->_groups=$data[0];
return;
}
}
foreach($this->_rules as $pattern=>$route)
$this->_groups[$route][]=new CUrlRule($route,$pattern);
if($cache!==null)
$cache->set(self::CACHE_KEY,array($this->_groups,$hash));
}
public function getRules()
{
return $this->_rules;
}
public function setRules($value)
{
if($this->_rules===array())
$this->_rules=$value;
else
$this->_rules=array_merge($this->_rules,$value);
}
public function createUrl($route,$params=array(),$ampersand='&')
{
unset($params[$this->routeVar]);
if(isset($this->_groups[$route]))
{
foreach($this->_groups[$route] as $rule)
{
if(($url=$rule->createUrl($params,$this->urlSuffix,$ampersand))!==false)
return $this->getBaseUrl().'/'.$url;
}
}
return $this->createUrlDefault($route,$params,$ampersand);
}
protected function createUrlDefault($route,$params,$ampersand)
{
if($this->getUrlFormat()===self::PATH_FORMAT)
{
$url=rtrim($this->getBaseUrl().'/'.$route,'/');
foreach($params as $key=>$value)
{
if("$value"!=='')
$url.='/'.urlencode($key).'/'.urlencode($value);
}
return $url.$this->urlSuffix;
}
else
{
$pairs=$route!==''?array($this->routeVar.'='.$route):array();
foreach($params as $key=>$value)
$pairs[]=urlencode($key).'='.urlencode($value);
$baseUrl=$this->getBaseUrl();
if(!$this->showScriptName)
$baseUrl.='/';
if(($query=implode($ampersand,$pairs))!=='')
return $baseUrl.'?'.$query;
else
return $baseUrl;
}
}
public function parseUrl($request)
{
if($this->getUrlFormat()===self::PATH_FORMAT)
{
$pathInfo=$this->removeUrlSuffix($request->getPathInfo());
foreach($this->_groups as $rules)
{
foreach($rules as $rule)
{
if(($r=$rule->parseUrl($pathInfo))!==false)
{
$route=isset($_GET[$this->routeVar])?$_GET[$this->routeVar]:$r;
return $this->caseSensitive?$route:strtolower($route);
}
}
}
$route=$this->parseUrlDefault($pathInfo);
}
else if(isset($_GET[$this->routeVar]))
$route=$_GET[$this->routeVar];
else if(isset($_POST[$this->routeVar]))
$route=$_POST[$this->routeVar];
else
return '';
return $this->caseSensitive?$route:strtolower($route);
}
protected function removeUrlSuffix($pathInfo)
{
if(($ext=$this->urlSuffix)!=='' && substr($pathInfo,-strlen($ext))===$ext)
return substr($pathInfo,0,-strlen($ext));
else
return $pathInfo;
}
protected function parseUrlDefault($pathInfo)
{
$segs=explode('/',$pathInfo.'/');
$n=count($segs);
for($i=2;$i<$n-1;$i+=2)
$_GET[urldecode($segs[$i])]=urldecode($segs[$i+1]);
return $segs[0].'/'.$segs[1];
}
public function getBaseUrl()
{
if($this->_baseUrl!==null)
return $this->_baseUrl;
else
{
if($this->showScriptName)
$this->_baseUrl=Yii::app()->getRequest()->getScriptUrl();
else
$this->_baseUrl=Yii::app()->getRequest()->getBaseUrl();
return $this->_baseUrl;
}
}
public function getUrlFormat()
{
return $this->_urlFormat;
}
public function setUrlFormat($value)
{
if($value===self::PATH_FORMAT || $value===self::GET_FORMAT)
$this->_urlFormat=$value;
else
throw new CException(Yii::t('yii','CUrlManager.UrlFormat must be either "path" or "get".'));
}
}
class CUrlRule extends CComponent
{
public $route;
public $pattern;
public $template;
public $params;
public $append;
public $signature;
public $caseSensitive=true;
public function __construct($route,$pattern)
{
$this->route=$route;
if(preg_match_all('/<(\w+):?(.*?)?>/',$pattern,$matches))
$this->params=array_combine($matches[1],$matches[2]);
else
$this->params=array();
$p=rtrim($pattern,'*');
$this->append=$p!==$pattern;
$p=trim($p,'/');
$this->template=preg_replace('/<(\w+):?.*?>/','<$1>',$p);
if(($pos=strpos($p,'<'))!==false)
$this->signature=substr($p,0,$pos);
else
$this->signature=$p;
$tr['/']='\\/';
foreach($this->params as $key=>$value)
$tr["<$key>"]="(?P<$key>".($value!==''?$value:'[^\/]+').')';
$this->pattern='/^'.strtr($this->template,$tr).'\/';
if($this->append)
$this->pattern.='/u';
else
$this->pattern.='$/u';
if(!$this->caseSensitive)
$this->pattern.='i';
if(@preg_match($this->pattern,'test')===false)
throw new CException(Yii::t('yii','The URL pattern "{pattern}" for route "{route}" is not a valid regular expression.',
array('{route}'=>$route,'{pattern}'=>$pattern)));
}
public function createUrl($params,$suffix,$ampersand)
{
foreach($this->params as $key=>$value)
{
if(!isset($params[$key]))
return false;
}
$tr=array();
$rest=array();
$sep=$this->append?'/':'=';
foreach($params as $key=>$value)
{
if(isset($this->params[$key]))
$tr["<$key>"]=$value;
else if("$value"!=='')
$rest[]=urlencode($key).$sep.urlencode($value);
}
$url=strtr($this->template,$tr);
if($rest===array())
return $url!=='' ? $url.$suffix : $url;
else
{
if($this->append)
{
$url.='/'.implode('/',$rest);
if($url!=='')
$url.=$suffix;
}
else
{
if($url!=='')
$url.=$suffix;
$url.='?'.implode($ampersand,$rest);
}
return $url;
}
}
public function parseUrl($pathInfo)
{
$func=$this->caseSensitive?'strncmp':'strncasecmp';
if($func($pathInfo,$this->signature,strlen($this->signature)))
return false;
$pathInfo.='/';
if(preg_match($this->pattern,$pathInfo,$matches))
{
foreach($matches as $key=>$value)
{
if(is_string($key))
$_GET[$key]=urldecode($value);
}
if($pathInfo!==$matches[0])
{
$segs=explode('/',ltrim(substr($pathInfo,strlen($matches[0])),'/'));
$n=count($segs);
for($i=0;$i<$n-1;$i+=2)
$_GET[urldecode($segs[$i])]=urldecode($segs[$i+1]);
}
return $this->route;
}
else
return false;
}
}
class CHttpRequest extends CApplicationComponent
{
public $enableCookieValidation=false;
public $enableCsrfValidation=false;
public $csrfTokenName='YII_CSRF_TOKEN';
public $csrfCookie;
private $_pathInfo;
private $_scriptFile;
private $_scriptUrl;
private $_hostInfo;
private $_url;
private $_baseUrl;
private $_cookies;
private $_preferredLanguage;
private $_csrfToken;
public function init()
{
parent::init();
$this->normalizeRequest();
}
protected function normalizeRequest()
{
// normalize request
if(get_magic_quotes_gpc())
{
if(isset($_GET))
$_GET=$this->stripSlashes($_GET);
if(isset($_POST))
$_POST=$this->stripSlashes($_POST);
if(isset($_REQUEST))
$_REQUEST=$this->stripSlashes($_REQUEST);
if(isset($_COOKIE))
$_COOKIE=$this->stripSlashes($_COOKIE);
}
if($this->enableCsrfValidation && !$this->performCsrfValidation())
throw new CHttpException(400,Yii::t('yii','The CSRF token could not be verified.'));
}
public function stripSlashes(&$data)
{
return is_array($data)?array_map(array($this,'stripSlashes'),$data):stripslashes($data);
}
public function getUrl()
{
if($this->_url!==null)
return $this->_url;
else
{
if(isset($_SERVER['REQUEST_URI']))
$this->_url=$_SERVER['REQUEST_URI'];
else
{
$this->_url=$this->getScriptUrl();
if(($pathInfo=$this->getPathInfo())!=='')
$this->_url.='/'.$pathInfo;
if(($queryString=$this->getQueryString())!=='')
$this->_url.='?'.$queryString;
}
return $this->_url;
}
}
public function getHostInfo($schema='')
{
if($this->_hostInfo===null)
{
if($secure=$this->getIsSecureConnection())
$schema='https';
else
$schema='http';
$segs=explode(':',$_SERVER['HTTP_HOST']);
$url=$schema.'://'.$segs[0];
$port=$_SERVER['SERVER_PORT'];
if(($port!=80 && !$secure) || ($port!=443 && $secure))
$url.=':'.$port;
$this->_hostInfo=$url;
}
if($schema!=='' && ($pos=strpos($this->_hostInfo,':'))!==false)
return $schema.substr($this->_hostInfo,$pos);
else
return $this->_hostInfo;
}
public function setHostInfo($value)
{
$this->_hostInfo=rtrim($value,'/');
}
public function getBaseUrl()
{
if($this->_baseUrl===null)
$this->_baseUrl=rtrim(dirname($this->getScriptUrl()),'\\/');
return $this->_baseUrl;
}
public function setBaseUrl($value)
{
$this->_baseUrl=$value;
}
public function getScriptUrl()
{
if($this->_scriptUrl!==null)
return $this->_scriptUrl;
else
{
if(isset($_SERVER['SCRIPT_NAME']))
$this->_scriptUrl=$_SERVER['SCRIPT_NAME'];
else
throw new CException(Yii::t('yii','CHttpRequest is unable to determine the entry script URL.'));
return $this->_scriptUrl;
}
}
public function setScriptUrl($value)
{
$this->_scriptUrl='/'.trim($value,'/');
}
public function getPathInfo()
{
if($this->_pathInfo===null)
$this->_pathInfo=trim(isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : $this->guessPathInfo(), '/');
return $this->_pathInfo;
}
protected function guessPathInfo()
{
if($_SERVER['PHP_SELF']!==$_SERVER['SCRIPT_NAME'])
{
if(strpos($_SERVER['PHP_SELF'],$_SERVER['SCRIPT_NAME'])===0)
return substr($_SERVER['PHP_SELF'],strlen($_SERVER['SCRIPT_NAME']));
}
else if(isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'],$_SERVER['SCRIPT_NAME'])!==0)
{
// REQUEST_URI doesn't contain SCRIPT_NAME, which means some rewrite rule is in effect
$base=strtr(dirname($_SERVER['SCRIPT_NAME']),'\\','/');
if(strpos($_SERVER['REQUEST_URI'],$base)===0)
{
$pathInfo=substr($_SERVER['REQUEST_URI'],strlen($base));
if(($pos=strpos($pathInfo,'?'))!==false)
return substr($pathInfo,0,$pos);
else
return $pathInfo;
}
}
return '';
}
public function getQueryString()
{
return isset($_SERVER['QUERY_STRING'])?$_SERVER['QUERY_STRING']:'';
}
public function getIsSecureConnection()
{
return isset($_SERVER['HTTPS']) && !strcasecmp($_SERVER['HTTPS'],'on');
}
public function getRequestType()
{
return strtoupper(isset($_SERVER['REQUEST_METHOD'])?$_SERVER['REQUEST_METHOD']:'GET');
}
public function getIsPostRequest()
{
return !strcasecmp($_SERVER['REQUEST_METHOD'],'POST');
}
public function getIsAjaxRequest()
{
return isset($_SERVER['HTTP_X_REQUESTED_WITH'])?$_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest' : false;
}
public function getServerName()
{
return $_SERVER['SERVER_NAME'];
}
public function getServerPort()
{
return $_SERVER['SERVER_PORT'];
}
public function getUrlReferrer()
{
return isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:null;
}
public function getUserAgent()
{
return $_SERVER['HTTP_USER_AGENT'];
}
public function getUserHostAddress()
{
return isset($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:'127.0.0.1';
}
public function getUserHost()
{
return isset($_SERVER['REMOTE_HOST'])?$_SERVER['REMOTE_HOST']:null;
}
public function getScriptFile()
{
if($this->_scriptFile!==null)
return $this->_scriptFile;
else
return $this->_scriptFile=realpath($_SERVER['SCRIPT_FILENAME']);
}
public function getBrowser()
{
return get_browser();
}
public function getAcceptTypes()
{
return $_SERVER['HTTP_ACCEPT'];
}
public function getCookies()
{
if($this->_cookies!==null)
return $this->_cookies;
else
return $this->_cookies=new CCookieCollection($this);
}
public function redirect($url,$terminate=true)
{
if(strpos($url,'/')===0)
$url=$this->getHostInfo().$url;
header('Location: '.$url);
if($terminate)
Yii::app()->end();
}
public function getPreferredLanguage()
{
if($this->_preferredLanguage===null)
{
if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && ($n=preg_match_all('/([\w\-_]+)\s*(;\s*q\s*=\s*(\d*\.\d*))?/',$_SERVER['HTTP_ACCEPT_LANGUAGE'],$matches))>0)
{
$languages=array();
for($i=0;$i<$n;++$i)
$languages[$matches[1][$i]]=empty($matches[3][$i]) ? 1.0 : floatval($matches[3][$i]);
arsort($languages);
foreach($languages as $language=>$pref)
return $this->_preferredLanguage=CLocale::getCanonicalID($language);
}
return $this->_preferredLanguage=false;
}
return $this->_preferredLanguage;
}
public function sendFile($fileName,$content,$mimeType=null,$terminate=true)
{
if($mimeType===null)
{
if(($mimeType=CFileHelper::getMimeTypeByExtension($fileName))===null)
$mimeType='text/plain';
}
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-type: $mimeType");
header('Content-Length: '.strlen($content));
header("Content-Disposition: attachment; filename=\"$fileName\"");
header('Content-Transfer-Encoding: binary');
echo $content;
if($terminate)
Yii::app()->end();
}
public function getCsrfToken()
{
if($this->_csrfToken===null)
{
$cookie=$this->getCookies()->itemAt($this->csrfTokenName);
if(!$cookie || ($this->_csrfToken=$cookie->value)==null)
{
$cookie=$this->createCsrfCookie();
$this->_csrfToken=$cookie->value;
$this->getCookies()->add($cookie->name,$cookie);
}
}
return $this->_csrfToken;
}
protected function createCsrfCookie()
{
$cookie=new CHttpCookie($this->csrfTokenName,sha1(uniqid(rand(),true)));
if(is_array($this->csrfCookie))
{
foreach($this->csrfCookie as $name=>$value)
$cookie->$name=$value;
}
return $cookie;
}
protected function performCsrfValidation()
{
if(!$this->getIsPostRequest())
return true;
$cookies=$this->getCookies();
if($cookies->contains($this->csrfTokenName) && isset($_POST[$this->csrfTokenName]))
{
$tokenFromCookie=$cookies->itemAt($this->csrfTokenName)->value;
$tokenFromPost=$_POST[$this->csrfTokenName];
return $tokenFromCookie===$tokenFromPost;
}
else
return false;
}
}
class CCookieCollection extends CMap
{
private $_request;
private $_initialized=false;
public function __construct(CHttpRequest $request)
{
$this->_request=$request;
$this->copyfrom($this->getCookies());
$this->_initialized=true;
}
public function getRequest()
{
return $this->_request;
}
protected function getCookies()
{
$cookies=array();
if($this->_request->enableCookieValidation)
{
$sm=Yii::app()->getSecurityManager();
foreach($_COOKIE as $name=>$value)
{
if(($value=$sm->validateData($value))!==false)
$cookies[$name]=new CHttpCookie($name,$value);
}
}
else
{
foreach($_COOKIE as $name=>$value)
$cookies[$name]=new CHttpCookie($name,$value);
}
return $cookies;
}
public function add($name,$cookie)
{
if($cookie instanceof CHttpCookie)
{
$this->remove($name);
parent::add($name,$cookie);
if($this->_initialized)
$this->addCookie($cookie);
}
else
throw new CException(Yii::t('yii','CHttpCookieCollection can only hold CHttpCookie objects.'));
}
public function remove($name)
{
if(($cookie=parent::remove($name))!==null)
{
if($this->_initialized)
$this->removeCookie($cookie);
}
return $cookie;
}
protected function addCookie($cookie)
{
$value=$cookie->value;
if($this->_request->enableCookieValidation)
$value=Yii::app()->getSecurityManager()->hashData($value);
if(version_compare(PHP_VERSION,'5.2.0','>='))
setcookie($cookie->name,$value,$cookie->expire,$cookie->path,$cookie->domain,$cookie->secure,$cookie->httpOnly);
else
setcookie($cookie->name,$value,$cookie->expire,$cookie->path,$cookie->domain,$cookie->secure);
}
protected function removeCookie($cookie)
{
if(version_compare(PHP_VERSION,'5.2.0','>='))
setcookie($cookie->name,null,0,$cookie->path,$cookie->domain,$cookie->secure,$cookie->httpOnly);
else
setcookie($cookie->name,null,0,$cookie->path,$cookie->domain,$cookie->secure);
}
}
abstract class CBaseController extends CComponent
{
private $_widgetStack=array();
abstract public function getViewFile($viewName);
public function renderFile($viewFile,$data=null,$return=false)
{
$widgetCount=count($this->_widgetStack);
if(($renderer=Yii::app()->getViewRenderer())!==null)
$content=$renderer->renderFile($this,$viewFile,$data,$return);
else
$content=$this->renderInternal($viewFile,$data,$return);
if(count($this->_widgetStack)===$widgetCount)
return $content;
else
{
$widget=end($this->_widgetStack);
throw new CException(Yii::t('yii','{controller} contains improperly nested widget tags in its view "{view}". A {widget} widget does not have an endWidget() call.',
array('{controller}'=>get_class($this), '{view}'=>$viewFile, '{widget}'=>get_class($widget))));
}
}
public function renderInternal($_viewFile_,$_data_=null,$_return_=false)
{
// we use special variable names here to avoid conflict when extracting data
if(is_array($_data_))
extract($_data_,EXTR_PREFIX_SAME,'data');
else
$data=$_data_;
if($_return_)
{
ob_start();
ob_implicit_flush(false);
require($_viewFile_);
return ob_get_clean();
}
else
require($_viewFile_);
}
public function createWidget($className,$properties=array())
{
$className=Yii::import($className,true);
$widget=new $className($this);
foreach($properties as $name=>$value)
$widget->$name=$value;
$widget->init();
return $widget;
}
public function widget($className,$properties=array())
{
$widget=$this->createWidget($className,$properties);
$widget->run();
}
public function beginWidget($className,$properties=array())
{
$widget=$this->createWidget($className,$properties);
$this->_widgetStack[]=$widget;
return $widget;
}
public function endWidget($id='')
{
if(($widget=array_pop($this->_widgetStack))!==null)
{
$widget->run();
return $widget;
}
else
throw new CException(Yii::t('yii','{controller} has an extra endWidget({id}) call in its view.',
array('{controller}'=>get_class($this),'{id}'=>$id)));
}
public function beginClip($id,$properties=array())
{
$properties['id']=$id;
$this->beginWidget('CClipWidget',$properties);
}
public function endClip()
{
$this->endWidget('CClipWidget');
}
public function beginCache($id,$properties=array())
{
$properties['id']=$id;
$cache=$this->beginWidget('COutputCache',$properties);
if($cache->getIsContentCached())
{
$this->endCache();
return false;
}
else
return true;
}
public function endCache()
{
$this->endWidget('COutputCache');
}
public function beginContent($view,$properties=array())
{
$properties['view']=$view;
$this->beginWidget('CContentDecorator',$properties);
}
public function endContent()
{
$this->endWidget('CContentDecorator');
}
}
class CController extends CBaseController
{
const STATE_INPUT_NAME='YII_PAGE_STATE';
public $layout;
public $defaultAction='index';
private $_id;
private $_action;
private $_pageTitle;
private $_cachingStack;
private $_clips;
private $_dynamicOutput;
private $_pageStates;
public function __construct($id)
{
$this->_id=$id;
}
public function init()
{
}
public function filters()
{
return array();
}
public function actions()
{
return array();
}
public function accessRules()
{
return array();
}
public function run($actionID)
{
if(($action=$this->createAction($actionID))!==null)
$this->runActionWithFilters($action,$this->filters());
else
$this->missingAction($actionID);
}
public function runActionWithFilters($action,$filters)
{
if(empty($filters))
$this->runAction($action);
else
{
$priorAction=$this->_action;
$this->_action=$action;
CFilterChain::create($this,$action,$filters)->run();
$this->_action=$priorAction;
}
}
public function runAction($action)
{
$priorAction=$this->_action;
$this->_action=$action;
if($this->beforeAction($action))
{
$action->run();
$this->afterAction($action);
}
$this->_action=$priorAction;
}
public function processOutput($output)
{
Yii::app()->getClientScript()->render($output);
if($this->_dynamicOutput)
{
$output=preg_replace_callback('/<###dynamic-(\d+)###>/',array($this,'replaceDynamicOutput'),$output);
$this->_dynamicOutput=null;
}
if($this->_pageStates!==null || isset($_POST[self::STATE_INPUT_NAME]))
{
$states=$this->savePageStates();
$output=str_replace(CHtml::pageStateField(''),CHtml::pageStateField($states),$output);
}
return $output;
}
protected function replaceDynamicOutput($matches)
{
return isset($this->_dynamicOutput[$matches[1]]) ? $this->_dynamicOutput[$matches[1]] : $matches[0];
}
public function createAction($actionID)
{
if($actionID==='')
$actionID=$this->defaultAction;
if(method_exists($this,'action'.$actionID) && strcasecmp($actionID,'s')) // we have actions method
return new CInlineAction($this,$actionID);
else
return $this->createActionFromMap($this->actions(),$actionID,$actionID);
}
protected function createActionFromMap($actionMap,$actionID,$requestActionID,$config=array())
{
if(($pos=strpos($actionID,'.'))===false && isset($actionMap[$actionID]))
{
$baseConfig=is_array($actionMap[$actionID]) ? $actionMap[$actionID] : array('class'=>$actionMap[$actionID]);
return Yii::createComponent(empty($config)?$baseConfig:array_merge($baseConfig,$config),$this,$requestActionID);
}
else if($pos===false)
return null;
// the action is defined in a provider
$prefix=substr($actionID,0,$pos+1);
if(!isset($actionMap[$prefix]))
return null;
$actionID=(string)substr($actionID,$pos+1);
$provider=$actionMap[$prefix];
if(is_string($provider))
$providerType=$provider;
else if(is_array($provider) && isset($provider['class']))
{
$providerType=$provider['class'];
if(isset($provider[$actionID]))
{
if(is_string($provider[$actionID]))
$config=array_merge(array('class'=>$provider[$actionID]),$config);
else
$config=array_merge($provider[$actionID],$config);
}
}
else
throw new CException(Yii::t('yii','Object configuration must be an array containing a "class" element.'));
$class=Yii::import($providerType,true);
$map=call_user_func(array($class,'actions'));
return $this->createActionFromMap($map,$actionID,$requestActionID,$config);
}
public function missingAction($actionID)
{
throw new CHttpException(404,Yii::t('yii','The system is unable to find the requested action "{action}".',
array('{action}'=>$actionID==''?$this->defaultAction:$actionID)));
}
public function getAction()
{
return $this->_action;
}
public function setAction($value)
{
$this->_action=$value;
}
public function getId()
{
return $this->_id;
}
public function getViewPath()
{
return Yii::app()->getViewPath().DIRECTORY_SEPARATOR.str_replace('.',DIRECTORY_SEPARATOR,$this->getId());
}
public function getViewFile($viewName)
{
if(($theme=Yii::app()->getTheme())!==null && ($viewFile=$theme->getViewFile($this,$viewName))!==false)
return $viewFile;
if($viewName[0]==='/')
$viewFile=Yii::app()->getViewPath().$viewName.'.php';
else
$viewFile=$this->getViewPath().DIRECTORY_SEPARATOR.$viewName.'.php';
return is_file($viewFile) ? Yii::app()->findLocalizedFile($viewFile) : false;
}
public function getLayoutFile($layoutName)
{
if(($theme=Yii::app()->getTheme())!==null && ($layoutFile=$theme->getLayoutFile($this,$layoutName))!==false)
return $layoutFile;
if($layoutName[0]==='/')
$layoutFile=Yii::app()->getViewPath().$layoutName.'.php';
else
$layoutFile=Yii::app()->getLayoutPath().DIRECTORY_SEPARATOR.$layoutName.'.php';
return is_file($layoutFile) ? Yii::app()->findLocalizedFile($layoutFile) : false;
}
public function getClips()
{
if($this->_clips!==null)
return $this->_clips;
else
return $this->_clips=new CMap;
}
public function render($view,$data=null,$return=false)
{
if(($layout=$this->layout)==null)
$layout=Yii::app()->layout;
$output=$this->renderPartial($view,$data,true);
if(!empty($layout) && ($layoutFile=$this->getLayoutFile($layout))!==false)
$output=$this->renderFile($layoutFile,array('content'=>$output),true);
$output=$this->processOutput($output);
if($return)
return $output;
else
echo $output;
}
public function renderText($text,$return=false)
{
if(($layout=$this->layout)==null)
$layout=Yii::app()->layout;
if(!empty($layout) && ($layoutFile=$this->getLayoutFile($layout))!==false)
$output=$this->renderFile($layoutFile,array('content'=>$text),true);
else
$output=$text;
$output=$this->processOutput($output);
if($return)
return $output;
else
echo $output;
}
public function renderPartial($view,$data=null,$return=false,$processOutput=false)
{
if(($viewFile=$this->getViewFile($view))!==false)
{
$output=$this->renderFile($viewFile,$data,true);
if($processOutput)
$output=$this->processOutput($output);
if($return)
return $output;
else
echo $output;
}
else
throw new CException(Yii::t('yii','{controller} cannot find the requested view "{view}".',
array('{controller}'=>get_class($this), '{view}'=>$view)));
}
public function renderDynamic($callback)
{
$n=count($this->_dynamicOutput);
echo "<###dynamic-$n###>";
$params=func_get_args();
array_shift($params);
$this->renderDynamicInternal($callback,$params);
}
public function renderDynamicInternal($callback,$params)
{
if(is_string($callback) && method_exists($this,$callback))
$callback=array($this,$callback);
$this->_dynamicOutput[]=call_user_func_array($callback,$params);
$this->recordCachingAction('','renderDynamicInternal',array($callback,$params));
}
public function createUrl($route,$params=array(),$ampersand='&')
{
if(strpos($route,'/')===false)
$route=$this->getId().'/'.($route==='' ? $this->getAction()->getId() : $route);
return Yii::app()->createUrl($route,$params,$ampersand);
}
public function createAbsoluteUrl($route,$params=array(),$schema='',$ampersand='&')
{
return Yii::app()->getRequest()->getHostInfo($schema).$this->createUrl($route,$params,$ampersand);
}
public function getPageTitle()
{
if($this->_pageTitle!==null)
return $this->_pageTitle;
else
{
$name=ucfirst(basename(str_replace('.','/',$this->getId())));
if($this->getAction()!==null && strcasecmp($this->getAction()->getId(),$this->defaultAction))
return $this->_pageTitle=Yii::app()->name.' - '.ucfirst($this->getAction()->getId()).' '.$name;
else
return $this->_pageTitle=Yii::app()->name.' - '.$name;
}
}
public function setPageTitle($value)
{
$this->_pageTitle=$value;
}
public function redirect($url,$terminate=true)
{
if(is_array($url))
{
$route=isset($url[0]) ? $url[0] : '';
$url=$this->createUrl($route,array_splice($url,1));
}
Yii::app()->getRequest()->redirect($url,$terminate);
}
public function refresh($terminate=true)
{
$this->redirect(Yii::app()->getRequest()->getUrl(),$terminate);
}
public function recordCachingAction($context,$method,$params)
{
if($this->_cachingStack) // record only when there is an active output cache
{
foreach($this->_cachingStack as $cache)
$cache->recordAction($context,$method,$params);
}
}
public function getCachingStack()
{
if(!$this->_cachingStack)
$this->_cachingStack=new CStack;
return $this->_cachingStack;
}
protected function beforeAction($action)
{
return true;
}
protected function afterAction($action)
{
}
public function filterPostOnly($filterChain)
{
if(Yii::app()->getRequest()->getIsPostRequest())
$filterChain->run();
else
throw new CHttpException(400,Yii::t('yii','Your request is not valid.'));
}
public function filterAjaxOnly($filterChain)
{
if(Yii::app()->getRequest()->getIsAjaxRequest())
$filterChain->run();
else
throw new CHttpException(400,Yii::t('yii','Your request is not valid.'));
}
public function filterAccessControl($filterChain)
{
$filter=new CAccessControlFilter;
$filter->setRules($this->accessRules());
$filter->filter($filterChain);
}
public function paginate($itemCount,$pageSize=null,$pageVar=null)
{
$pages=new CPagination;
$pages->setItemCount($itemCount);
if($pageSize!==null)
$pages->pageSize=$pageSize;
if($pageVar!==null)
$pages->pageVar=$pageVar;
return $pages;
}
public function getPageState($name,$defaultValue=null)
{
if($this->_pageStates===null)
$this->loadPageStates();
return isset($this->_pageStates[$name])?$this->_pageStates[$name]:$defaultValue;
}
public function setPageState($name,$value,$defaultValue=null)
{
if($this->_pageStates===null)
$this->loadPageStates();
if($value===$defaultValue)
unset($this->_pageStates[$name]);
else
$this->_pageStates[$name]=$value;
$params=func_get_args();
$this->recordCachingAction('','setPageState',$params);
}
public function clearPageStates()
{
$this->_pageStates=array();
}
protected function loadPageStates()
{
if(isset($_POST[self::STATE_INPUT_NAME]) && !empty($_POST[self::STATE_INPUT_NAME]))
{
if(($data=base64_decode($_POST[self::STATE_INPUT_NAME]))!==false)
{
if(extension_loaded('zlib'))
$data=@gzuncompress($data);
if(($data=Yii::app()->getSecurityManager()->validateData($data))!==false)
{
$this->_pageStates=unserialize($data);
return;
}
}
}
$this->_pageStates=array();
}
protected function savePageStates()
{
if($this->_pageStates===null)
$this->loadPageStates();
if(empty($this->_pageStates))
return '';
else
{
$data=Yii::app()->getSecurityManager()->hashData(serialize($this->_pageStates));
if(extension_loaded('zlib'))
$data=gzcompress($data);
return base64_encode($data);
}
}
}
abstract class CAction extends CComponent implements IAction
{
private $_id;
private $_controller;
public function __construct($controller,$id)
{
$this->_controller=$controller;
$this->_id=$id;
}
public function getController()
{
return $this->_controller;
}
public function getId()
{
return $this->_id;
}
}
class CInlineAction extends CAction
{
public function run()
{
$method='action'.$this->getId();
$this->getController()->$method();
}
}
class CWebUser extends CApplicationComponent implements IWebUser
{
const FLASH_KEY_PREFIX='Yii.CWebUser.flash.';
const FLASH_COUNTERS='Yii.CWebUser.flash.counters';
public $allowAutoLogin=false;
public $guestName='Guest';
public $loginUrl=array('site/login');
private $_keyPrefix;
public function init()
{
parent::init();
Yii::app()->getSession()->open();
if($this->getIsGuest() && $this->allowAutoLogin)
$this->restoreFromCookie();
$this->updateFlash();
}
public function login($identity,$duration=0)
{
$this->changeIdentity($identity->getId(),$identity->getName(),$identity->getPersistentStates());
if($duration>0)
{
if($this->allowAutoLogin)
$this->saveToCookie($duration);
else
throw new CException(Yii::t('yii','{class}.allowAutoLogin must be set true in order to use cookie-based authentication.',
array('{class}'=>get_class($this))));
}
}
public function logout()
{
if($this->allowAutoLogin)
Yii::app()->getRequest()->getCookies()->remove($this->getStateKeyPrefix());
$this->clearStates();
}
public function getIsGuest()
{
return $this->getState('_id')===null;
}
public function getId()
{
return $this->getState('_id');
}
public function setId($value)
{
$this->setState('_id',$value);
}
public function getName()
{
if(($name=$this->getState('_name'))!==null)
return $name;
else
return $this->guestName;
}
public function setName($value)
{
$this->setState('_name',$value);
}
public function getReturnUrl()
{
return $this->getState('_returnUrl',Yii::app()->getRequest()->getScriptUrl());
}
public function setReturnUrl($value)
{
$this->setState('_returnUrl',$value);
}
public function loginRequired()
{
$app=Yii::app();
$request=$app->getRequest();
$this->setReturnUrl($request->getUrl());
if(($url=$this->loginUrl)!==null)
{
if(is_array($url))
{
$route=isset($url[0]) ? $url[0] : $app->defaultController;
$url=$app->createUrl($route,array_splice($url,1));
}
$request->redirect($url);
}
else
throw new CHttpException(401,Yii::t('yii','Login Required'));
}
protected function restoreFromCookie()
{
$app=Yii::app();
$cookie=$app->getRequest()->getCookies()->itemAt($this->getStateKeyPrefix());
if($cookie && !empty($cookie->value) && ($data=$app->getSecurityManager()->validateData($cookie->value))!==false)
{
$data=unserialize($data);
if(isset($data[0],$data[1],$data[2],$data[3]))
{
list($id,$name,$address,$states)=$data;
if($address===$app->getRequest()->getUserHostAddress())
$this->changeIdentity($id,$name,$states);
}
}
}
protected function saveToCookie($duration)
{
$app=Yii::app();
$cookie=new CHttpCookie($this->getStateKeyPrefix(),'');
$cookie->expire=time()+$duration;
$data=array(
$this->getId(),
$this->getName(),
$app->getRequest()->getUserHostAddress(),
$this->saveIdentityStates(),
);
$cookie->value=$app->getSecurityManager()->hashData(serialize($data));
$app->getRequest()->getCookies()->add($cookie->name,$cookie);
}
public function onRestoreFromCookie($event)
{
$this->raiseEvent('onRestoreFromCookie',$event);
}
protected function getStateKeyPrefix()
{
if($this->_keyPrefix!==null)
return $this->_keyPrefix;
else
return $this->_keyPrefix=md5('Yii.'.get_class($this).'.'.Yii::app()->getId());
}
public function getState($key,$defaultValue=null)
{
$key=$this->getStateKeyPrefix().$key;
return isset($_SESSION[$key]) ? $_SESSION[$key] : $defaultValue;
}
public function setState($key,$value,$defaultValue=null)
{
$key=$this->getStateKeyPrefix().$key;
if($value===$defaultValue)
unset($_SESSION[$key]);
else
$_SESSION[$key]=$value;
}
public function clearStates()
{
Yii::app()->getSession()->destroy();
}
public function getFlash($key,$defaultValue=null)
{
return $this->getState(self::FLASH_KEY_PREFIX.$key,$defaultValue);
}
public function setFlash($key,$value,$defaultValue=null)
{
$this->setState(self::FLASH_KEY_PREFIX.$key,$value,$defaultValue);
$counters=$this->getState(self::FLASH_COUNTERS,array());
if($value===$defaultValue)
unset($counters[$key]);
else
$counters[$key]=0;
$this->setState(self::FLASH_COUNTERS,$counters,array());
}
public function hasFlash($key)
{
return $this->getFlash($key)!==null;
}
protected function changeIdentity($id,$name,$states)
{
$this->setId($id);
$this->setName($name);
$this->loadIdentityStates($states);
}
protected function saveIdentityStates()
{
$states=array();
foreach($this->getState('_states',array()) as $name)
$states[$name]=$this->getState($name);
return $states;
}
protected function loadIdentityStates($states)
{
if(is_array($states))
{
foreach($states as $name=>$value)
$this->setState($name,$value);
$this->setState('_states',array_keys($states));
}
else
$this->setState('_states',array());
}
protected function updateFlash()
{
$counters=$this->getState(self::FLASH_COUNTERS);
if(!is_array($counters))
return;
foreach($counters as $key=>$count)
{
if($count)
{
unset($counters[$key]);
$this->setState(self::FLASH_KEY_PREFIX.$key,null);
}
else
$counters[$key]++;
}
$this->setState(self::FLASH_COUNTERS,$counters,array());
}
public function checkAccess($operation,$params=array())
{
return Yii::app()->getAuthManager()->checkAccess($operation,$this->getId(),$params);
}
}
class CHttpSession extends CApplicationComponent implements IteratorAggregate,ArrayAccess,Countable
{
public $autoStart=true;
public function init()
{
parent::init();
if($this->autoStart)
$this->open();
register_shutdown_function(array($this,'close'));
}
public function getUseCustomStorage()
{
return false;
}
public function open()
{
if(session_id()==='')
{
if($this->getUseCustomStorage())
session_set_save_handler(array($this,'openSession'),array($this,'closeSession'),array($this,'readSession'),array($this,'writeSession'),array($this,'destroySession'),array($this,'gcSession'));
session_start();
}
}
public function close()
{
if(session_id()!=='')
@session_write_close();
}
public function destroy()
{
if(session_id()!=='')
{
@session_unset();
@session_destroy();
}
}
public function getIsStarted()
{
return session_id()!=='';
}
public function getSessionID()
{
return session_id();
}
public function setSessionID($value)
{
session_id($value);
}
public function getSessionName()
{
return session_name();
}
public function setSessionName($value)
{
session_name($value);
}
public function getSavePath()
{
return session_save_path();
}
public function setSavePath($value)
{
if(is_dir($value))
session_save_path($value);
else
throw new CException(Yii::t('yii','CHttpSession.savePath "{path}" is not a valid directory.',
array('{path}'=>$value)));
}
public function getCookieParams()
{
return session_get_cookie_params();
}
public function setCookieParams($value)
{
$data=session_get_cookie_params();
extract($data);
extract($value);
session_set_cookie_params($lifetime,$path,$domain,$secure);
}
public function getCookieMode()
{
if(ini_get('session.use_cookies')==='0')
return 'none';
else if(ini_get('session.use_only_cookies')==='0')
return 'allow';
else
return 'only';
}
public function setCookieMode($value)
{
if($value==='none')
ini_set('session.use_cookies','0');
else if($value==='allow')
{
ini_set('session.use_cookies','1');
ini_set('session.use_only_cookies','0');
}
else if($value==='only')
{
ini_set('session.use_cookies','1');
ini_set('session.use_only_cookies','1');
}
else
throw new CException(Yii::t('yii','CHttpSession.cookieMode can only be "none", "allow" or "only".'));
}
public function getGCProbability()
{
return (int)ini_get('session.gc_probability');
}
public function setGCProbability($value)
{
$value=(int)$value;
if($value>=0 && $value<=100)
{
ini_set('session.gc_probability',$value);
ini_set('session.gc_divisor','100');
}
else
throw new CException(Yii::t('yii','CHttpSession.gcProbability "{value}" is invalid. It must be an integer between 0 and 100.',
array('{value}'=>$value)));
}
public function getUseTransparentSessionID()
{
return ini_get('session.use_trans_sid')==1;
}
public function setUseTransparentSessionID($value)
{
ini_set('session.use_trans_sid',$value?'1':'0');
}
public function getTimeout()
{
return (int)ini_get('session.gc_maxlifetime');
}
public function setTimeout($value)
{
ini_set('session.gc_maxlifetime',$value);
}
public function openSession($savePath,$sessionName)
{
return true;
}
public function closeSession()
{
return true;
}
public function readSession($id)
{
return '';
}
public function writeSession($id,$data)
{
return true;
}
public function destroySession($id)
{
return true;
}
public function gcSession($maxLifetime)
{
return true;
}
//------ The following methods enable CHttpSession to be CMap-like -----
public function getIterator()
{
return new CHttpSessionIterator;
}
public function getCount()
{
return count($_SESSION);
}
public function count()
{
return $this->getCount();
}
public function getKeys()
{
return array_keys($_SESSION);
}
public function itemAt($key)
{
return isset($_SESSION[$key]) ? $_SESSION[$key] : null;
}
public function add($key,$value)
{
$_SESSION[$key]=$value;
}
public function remove($key)
{
if(isset($_SESSION[$key]))
{
$value=$_SESSION[$key];
unset($_SESSION[$key]);
return $value;
}
else
return null;
}
public function clear()
{
foreach(array_keys($_SESSION) as $key)
unset($_SESSION[$key]);
}
public function contains($key)
{
return isset($_SESSION[$key]);
}
public function toArray()
{
return $_SESSION;
}
public function offsetExists($offset)
{
return isset($_SESSION[$offset]);
}
public function offsetGet($offset)
{
return isset($_SESSION[$offset]) ? $_SESSION[$offset] : null;
}
public function offsetSet($offset,$item)
{
$_SESSION[$offset]=$item;
}
public function offsetUnset($offset)
{
unset($_SESSION[$offset]);
}
}
class CHttpSessionIterator implements Iterator
{
private $_keys;
private $_key;
public function __construct()
{
$this->_keys=array_keys($_SESSION);
}
public function rewind()
{
$this->_key=reset($this->_keys);
}
public function key()
{
return $this->_key;
}
public function current()
{
return isset($_SESSION[$this->_key])?$_SESSION[$this->_key]:null;
}
public function next()
{
do
{
$this->_key=next($this->_keys);
}
while(!isset($_SESSION[$this->_key]) && $this->_key!==false);
}
public function valid()
{
return $this->_key!==false;
}
}
class CHtml
{
const ID_PREFIX='yt';
public static $errorSummaryCss='errorSummary';
public static $errorMessageCss='errorMessage';
public static $errorCss='error';
private static $_count=0;
public static function encode($text)
{
return htmlspecialchars($text,ENT_QUOTES,Yii::app()->charset);
}
public static function tag($tag,$htmlOptions=array(),$content=false,$closeTag=true)
{
$html='<' . $tag;
foreach($htmlOptions as $name=>$value)
$html .= ' ' . $name . '="' . self::encode($value) . '"';
if($content===false)
return $closeTag ? $html.'/>' : $html.'>';
else
return $closeTag ? $html.'>'.$content.'</'.$tag.'>' : $html.'>'.$content;
}
public static function openTag($tag,$htmlOptions=array())
{
$html='<' . $tag;
foreach($htmlOptions as $name=>$value)
$html .= ' ' . $name . '="' . self::encode($value) . '"';
return $html . '>';
}
public static function closeTag($tag)
{
return '</'.$tag.'>';
}
public static function cdata($text)
{
return '<![CDATA[' . $text . ']]>';
}
public static function metaTag($content,$name=null,$httpEquiv=null,$options=array())
{
$options['content']=$content;
if($name!==null)
$options['name']=$name;
if($httpEquiv!==null)
$options['http-equiv']=$httpEquiv;
return self::tag('meta',$options);
}
public static function linkTag($relation=null,$type=null,$href=null,$media=null,$options=array())
{
if($relation!==null)
$options['rel']=$relation;
if($type!==null)
$options['type']=$type;
if($href!==null)
$options['href']=$href;
if($media!==null)
$options['media']=$media;
return self::tag('link',$options);
}
public static function css($text,$media='')
{
if($media!=='')
$media=' media="'.$media.'"';
return "<style type=\"text/css\"{$media}>\n/*<![CDATA[*/\n{$text}\n/*]]>*/\n</style>";
}
public static function cssFile($url,$media='')
{
if($media!=='')
$media=' media="'.$media.'"';
return '<link rel="stylesheet" type="text/css" href="'.self::encode($url).'"'.$media.'/>';
}
public static function script($text)
{
return "<script type=\"text/javascript\">\n/*<![CDATA[*/\n{$text}\n/*]]>*/\n</script>";
}
public static function scriptFile($url)
{
return '<script type="text/javascript" src="'.self::encode($url).'"></script>';
}
public static function form($action='',$method='post',$htmlOptions=array())
{
$htmlOptions['action']=self::normalizeUrl($action);
$htmlOptions['method']=$method;
$form=self::tag('form',$htmlOptions,false,false);
$request=Yii::app()->request;
if($request->enableCsrfValidation)
{
$token=self::hiddenField($request->csrfTokenName,$request->getCsrfToken());
$form.="\n".$token;
}
return $form;
}
public static function statefulForm($action='',$method='post',$htmlOptions=array())
{
return self::form($action,$method,$htmlOptions)."\n".self::pageStateField('');
}
public static function pageStateField($value)
{
return '<input type="hidden" name="'.CController::STATE_INPUT_NAME.'" value="'.$value.'" />';
}
public static function link($text,$url='#',$htmlOptions=array())
{
if($url!=='')
$htmlOptions['href']=self::normalizeUrl($url);
self::clientChange('click',$htmlOptions);
return self::tag('a',$htmlOptions,$text);
}
public static function image($src,$alt='',$htmlOptions=array())
{
$htmlOptions['src']=$src;
$htmlOptions['alt']=$alt;
return self::tag('img',$htmlOptions);
}
public static function button($label='button',$htmlOptions=array())
{
if(!isset($htmlOptions['name']))
$htmlOptions['name']=self::ID_PREFIX.self::$_count++;
if(!isset($htmlOptions['type']))
$htmlOptions['type']='button';
if(!isset($htmlOptions['value']))
$htmlOptions['value']=$label;
self::clientChange('click',$htmlOptions);
return self::tag('input',$htmlOptions);
}
public static function submitButton($label='submit',$htmlOptions=array())
{
$htmlOptions['type']='submit';
return self::button($label,$htmlOptions);
}
public static function resetButton($label='reset',$htmlOptions=array())
{
$htmlOptions['type']='reset';
return self::button($label,$htmlOptions);
}
public static function imageButton($src,$htmlOptions=array())
{
$htmlOptions['src']=$src;
$htmlOptions['type']='image';
return self::button('submit',$htmlOptions);
}
public static function linkButton($label='submit',$htmlOptions=array())
{
if(!isset($htmlOptions['submit']))
$htmlOptions['submit']=isset($htmlOptions['href']) ? $htmlOptions['href'] : '';
return self::link($label,'#',$htmlOptions);
}
public static function label($label,$for,$htmlOptions=array())
{
$htmlOptions['for']=$for;
return self::tag('label',$htmlOptions,$label);
}
public static function textField($name,$value='',$htmlOptions=array())
{
self::clientChange('change',$htmlOptions);
return self::inputField('text',$name,$value,$htmlOptions);
}
public static function hiddenField($name,$value='',$htmlOptions=array())
{
return self::inputField('hidden',$name,$value,$htmlOptions);
}
public static function passwordField($name,$value='',$htmlOptions=array())
{
self::clientChange('change',$htmlOptions);
return self::inputField('password',$name,$value,$htmlOptions);
}
public static function fileField($name,$value='',$htmlOptions=array())
{
return self::inputField('file',$name,$value,$htmlOptions);
}
public static function textArea($name,$value='',$htmlOptions=array())
{
$htmlOptions['name']=$name;
if(!isset($htmlOptions['id']))
$htmlOptions['id']=self::getIdByName($name);
self::clientChange('change',$htmlOptions);
return self::tag('textarea',$htmlOptions,self::encode($value));
}
public static function radioButton($name,$checked=false,$htmlOptions=array())
{
if($checked)
$htmlOptions['checked']='checked';
else
unset($htmlOptions['checked']);
$value=isset($htmlOptions['value']) ? $htmlOptions['value'] : 1;
self::clientChange('click',$htmlOptions);
return self::inputField('radio',$name,$value,$htmlOptions);
}
public static function checkBox($name,$checked=false,$htmlOptions=array())
{
if($checked)
$htmlOptions['checked']='checked';
else
unset($htmlOptions['checked']);
$value=isset($htmlOptions['value']) ? $htmlOptions['value'] : 1;
self::clientChange('click',$htmlOptions);
return self::inputField('checkbox',$name,$value,$htmlOptions);
}
public static function dropDownList($name,$select,$data,$htmlOptions=array())
{
$htmlOptions['name']=$name;
if(!isset($htmlOptions['id']))
$htmlOptions['id']=self::getIdByName($name);
self::clientChange('change',$htmlOptions);
$options="\n".self::listOptions($select,$data,$htmlOptions);
return self::tag('select',$htmlOptions,$options);
}
public static function listBox($name,$select,$data,$htmlOptions=array())
{
if(!isset($htmlOptions['size']))
$htmlOptions['size']=4;
return self::dropDownList($name,$select,$data,$htmlOptions);
}
public static function checkBoxList($name,$select,$data,$htmlOptions=array())
{
$template=isset($htmlOptions['template'])?$htmlOptions['template']:'{input} {label}';
$separator=isset($htmlOptions['separator'])?$htmlOptions['separator']:"<br/>\n";
unset($htmlOptions['template'],$htmlOptions['separator']);
if(substr($name,-2)!=='[]')
$name.='[]';
$items=array();
$baseID=self::getIdByName($name);
$id=0;
foreach($data as $value=>$label)
{
$checked=!is_array($select) && !strcmp($value,$select) || is_array($select) && in_array($value,$select);
$htmlOptions['value']=$value;
$htmlOptions['id']=$baseID.'_'.$id++;
$option=self::checkBox($name,$checked,$htmlOptions);
$items[]=strtr($template,array('{input}'=>$option,'{label}'=>$label));
}
return implode($separator,$items);
}
public static function radioButtonList($name,$select,$data,$htmlOptions=array())
{
$template=isset($htmlOptions['template'])?$htmlOptions['template']:'{input} {label}';
$separator=isset($htmlOptions['separator'])?$htmlOptions['separator']:"<br/>\n";
unset($htmlOptions['template'],$htmlOptions['separator']);
$items=array();
$baseID=self::getIdByName($name);
$id=0;
foreach($data as $value=>$label)
{
$checked=!strcmp($value,$select);
$htmlOptions['value']=$value;
$htmlOptions['id']=$baseID.'_'.$id++;
$option=self::radioButton($name,$checked,$htmlOptions);
$items[]=strtr($template,array('{input}'=>$option,'{label}'=>$label));
}
return implode($separator,$items);
}
public static function ajaxLink($text,$url,$ajaxOptions=array(),$htmlOptions=array())
{
if(!isset($htmlOptions['href']))
$htmlOptions['href']='#';
$ajaxOptions['url']=$url;
$htmlOptions['ajax']=$ajaxOptions;
self::clientChange('click',$htmlOptions);
return self::tag('a',$htmlOptions,$text);
}
public static function ajaxButton($label,$url,$ajaxOptions=array(),$htmlOptions=array())
{
$ajaxOptions['url']=$url;
$htmlOptions['ajax']=$ajaxOptions;
return self::button($label,$htmlOptions);
}
public static function ajaxSubmitButton($label,$url,$ajaxOptions=array(),$htmlOptions=array())
{
$ajaxOptions['type']='POST';
return self::ajaxButton($label,$url,$ajaxOptions,$htmlOptions);
}
public static function ajax($options)
{
Yii::app()->getClientScript()->registerCoreScript('jquery');
if(!isset($options['url']))
$options['url']='js:location.href';
else
$options['url']=self::normalizeUrl($options['url']);
if(!isset($options['cache']))
$options['cache']=false;
if(!isset($options['data']) && isset($options['type']))
$options['data']='js:jQuery(this).parents("form").serialize()';
foreach(array('beforeSend','complete','error','success') as $name)
{
if(isset($options[$name]) && strpos($options[$name],'js:')!==0)
$options[$name]='js:'.$options[$name];
}
if(isset($options['update']))
{
if(!isset($options['success']))
$options['success']='js:function(html){jQuery("'.$options['update'].'").html(html)}';
unset($options['update']);
}
if(isset($options['replace']))
{
if(!isset($options['success']))
$options['success']='js:function(html){jQuery("'.$options['replace'].'").replaceWith(html)}';
unset($options['replace']);
}
return 'jQuery.ajax('.CJavaScript::encode($options).');';
}
public static function asset($path,$hashByName=false)
{
return Yii::app()->getAssetManager()->publish($path,$hashByName);
}
public static function coreScript($name)
{
return Yii::app()->getClientScript()->renderCoreScript($name);
}
public static function normalizeUrl($url)
{
if(is_array($url))
$url=isset($url[0]) ? Yii::app()->getController()->createUrl($url[0],array_splice($url,1)) : '';
return $url==='' ? Yii::app()->getRequest()->getUrl() : $url;
}
protected static function inputField($type,$name,$value,$htmlOptions)
{
$htmlOptions['type']=$type;
$htmlOptions['value']=$value;
$htmlOptions['name']=$name;
if(!isset($htmlOptions['id']))
$htmlOptions['id']=self::getIdByName($name);
return self::tag('input',$htmlOptions);
}
public static function activeLabel($model,$attribute,$htmlOptions=array())
{
if(($pos=strpos($attribute,'['))!==false)
$name=get_class($model).substr($attribute,$pos).'['.($attribute=substr($attribute,0,$pos)).']';
else
$name=get_class($model).'['.$attribute.']';
$label=$model->getAttributeLabel($attribute);
$for=self::getIdByName($name);
if($model->hasErrors($attribute))
self::addErrorCss($htmlOptions);
return self::label($label,$for,$htmlOptions);
}
public static function activeTextField($model,$attribute,$htmlOptions=array())
{
self::resolveNameID($model,$attribute,$htmlOptions);
self::clientChange('change',$htmlOptions);
return self::activeInputField('text',$model,$attribute,$htmlOptions);
}
public static function activeHiddenField($model,$attribute,$htmlOptions=array())
{
self::resolveNameID($model,$attribute,$htmlOptions);
return self::activeInputField('hidden',$model,$attribute,$htmlOptions);
}
public static function activePasswordField($model,$attribute,$htmlOptions=array())
{
self::resolveNameID($model,$attribute,$htmlOptions);
self::clientChange('change',$htmlOptions);
return self::activeInputField('password',$model,$attribute,$htmlOptions);
}
public static function activeTextArea($model,$attribute,$htmlOptions=array())
{
self::resolveNameID($model,$attribute,$htmlOptions);
self::clientChange('change',$htmlOptions);
if($model->hasErrors($attribute))
self::addErrorCss($htmlOptions);
return self::tag('textarea',$htmlOptions,self::encode($model->$attribute));
}
public static function activeFileField($model,$attribute,$htmlOptions=array())
{
self::resolveNameID($model,$attribute,$htmlOptions);
return self::activeInputField('file',$model,$attribute,$htmlOptions);
}
public static function activeRadioButton($model,$attribute,$htmlOptions=array())
{
self::resolveNameID($model,$attribute,$htmlOptions);
if(!isset($htmlOptions['value']))
$htmlOptions['value']=1;
if($model->$attribute)
$htmlOptions['checked']='checked';
self::clientChange('click',$htmlOptions);
return self::hiddenField($htmlOptions['name'],$htmlOptions['value']?0:-1,array('id'=>self::ID_PREFIX.$htmlOptions['id']))
. self::activeInputField('radio',$model,$attribute,$htmlOptions);
}
public static function activeCheckBox($model,$attribute,$htmlOptions=array())
{
self::resolveNameID($model,$attribute,$htmlOptions);
if(!isset($htmlOptions['value']))
$htmlOptions['value']=1;
if($model->$attribute)
$htmlOptions['checked']='checked';
self::clientChange('click',$htmlOptions);
return self::hiddenField($htmlOptions['name'],'',array('id'=>self::ID_PREFIX.$htmlOptions['id']))
. self::activeInputField('checkbox',$model,$attribute,$htmlOptions);
}
public static function activeDropDownList($model,$attribute,$data,$htmlOptions=array())
{
self::resolveNameID($model,$attribute,$htmlOptions);
$selection=$model->$attribute;
$options="\n".self::listOptions($selection,$data,$htmlOptions);
self::clientChange('change',$htmlOptions);
if($model->hasErrors($attribute))
self::addErrorCss($htmlOptions);
return self::tag('select',$htmlOptions,$options);
}
public static function activeListBox($model,$attribute,$data,$htmlOptions=array())
{
if(!isset($htmlOptions['size']))
$htmlOptions['size']=4;
return self::activeDropDownList($model,$attribute,$data,$htmlOptions);
}
public static function activeCheckBoxList($model,$attribute,$data,$htmlOptions=array())
{
self::resolveNameID($model,$attribute,$htmlOptions);
$selection=$model->$attribute;
if($model->hasErrors($attribute))
self::addErrorCss($htmlOptions);
$name=$htmlOptions['name'];
unset($htmlOptions['name'],$htmlOptions['id']);
return self::hiddenField($name,'',array('id'=>self::ID_PREFIX.$htmlOptions['id']))
. self::checkBoxList($name,$selection,$data,$htmlOptions);
}
public static function activeRadioButtonList($model,$attribute,$data,$htmlOptions=array())
{
self::resolveNameID($model,$attribute,$htmlOptions);
$selection=$model->$attribute;
if($model->hasErrors($attribute))
self::addErrorCss($htmlOptions);
$name=$htmlOptions['name'];
unset($htmlOptions['name'],$htmlOptions['id']);
return self::hiddenField($name,'',array('id'=>self::ID_PREFIX.$htmlOptions['id']))
. self::radioButtonList($name,$selection,$data,$htmlOptions);
}
public static function getActiveId($model,$attribute)
{
return get_class($model).'_'.$attribute;
}
public static function errorSummary($model,$header='',$footer='')
{
if($header==='')
$header='<p>'.Yii::t('yii','Please fix the following input errors:').'</p>';
$content='';
if(!is_array($model))
$model=array($model);
foreach($model as $m)
{
foreach($m->getErrors() as $errors)
{
foreach($errors as $error)
$content.="<li>$error</li>\n";
}
}
if($content!=='')
return self::tag('div',array('class'=>self::$errorSummaryCss),$header."\n<ul>\n$content</ul>".$footer);
else
return '';
}
public static function error($model,$attribute)
{
$errors=$model->getErrors($attribute);
if(!empty($errors))
return self::tag('div',array('class'=>self::$errorMessageCss),reset($errors));
else
return '';
}
public static function listData($models,$valueField,$textField,$groupField='')
{
$listData=array();
if($groupField==='')
{
foreach($models as $model)
$listData[$model->$valueField]=$model->$textField;
}
else
{
foreach($models as $model)
$listData[$model->$groupField][$model->$valueField]=$model->$textField;
}
return $listData;
}
public static function getIdByName($name)
{
return str_replace(array('[]', '][', '[', ']'), array('', '_', '_', ''), $name);
}
public static function activeId($model,$attribute)
{
return self::getIdByName(self::activeName($model,$attribute));
}
public static function activeName($model,$attribute)
{
if(($pos=strpos($attribute,'['))!==false)
return get_class($model).substr($attribute,$pos).'['.substr($attribute,0,$pos).']';
else
return get_class($model).'['.$attribute.']';
}
protected static function activeInputField($type,$model,$attribute,$htmlOptions)
{
$htmlOptions['type']=$type;
if(!isset($htmlOptions['value']))
$htmlOptions['value']=$model->$attribute;
if($model->hasErrors($attribute))
self::addErrorCss($htmlOptions);
return self::tag('input',$htmlOptions);
}
protected static function listOptions($selection,$listData,&$htmlOptions)
{
$content='';
if(isset($htmlOptions['prompt']))
{
$content.='<option value="">'.self::encode($htmlOptions['prompt'])."</option>\n";
unset($htmlOptions['prompt']);
}
if(isset($htmlOptions['empty']))
{
$content.='<option value="">'.self::encode($htmlOptions['empty'])."</option>\n";
unset($htmlOptions['empty']);
}
foreach($listData as $key=>$value)
{
if(is_array($value))
{
$content.='<optgroup label="'.self::encode($key)."\">\n";
$dummy=array();
$content.=self::listOptions($selection,$value,$dummy);
$content.='</optgroup>'."\n";
}
else if(!is_array($selection) && !strcmp($key,$selection) || is_array($selection) && in_array($key,$selection))
$content.='<option value="'.self::encode((string)$key).'" selected="selected">'.self::encode((string)$value)."</option>\n";
else
$content.='<option value="'.self::encode((string)$key).'">'.self::encode((string)$value)."</option>\n";
}
return $content;
}
protected static function clientChange($event,&$htmlOptions)
{
if(isset($htmlOptions['submit']) || isset($htmlOptions['confirm']) || isset($htmlOptions['ajax']))
{
if(isset($htmlOptions['on'.$event]))
{
$handler=trim($htmlOptions['on'.$event],';').';';
unset($htmlOptions['on'.$event]);
}
else
$handler='';
if(isset($htmlOptions['id']))
$id=$htmlOptions['id'];
else
$id=$htmlOptions['id']=isset($htmlOptions['name'])?$htmlOptions['name']:self::ID_PREFIX.self::$_count++;
$cs=Yii::app()->getClientScript();
$cs->registerCoreScript('jquery');
if(isset($htmlOptions['params']))
$params=CJavaScript::encode($htmlOptions['params']);
else
$params='{}';
if(isset($htmlOptions['submit']))
{
$cs->registerCoreScript('yii');
if($htmlOptions['submit']!=='')
$url=CJavaScript::quote(self::normalizeUrl($htmlOptions['submit']));
else
$url='';
$handler.="jQuery.yii.submitForm(this,'$url',$params);return false;";
}
if(isset($htmlOptions['ajax']))
$handler.=self::ajax($htmlOptions['ajax']).'return false;';
if(isset($htmlOptions['confirm']))
{
$confirm='confirm(\''.CJavaScript::quote($htmlOptions['confirm']).'\')';
if($handler!=='')
$handler="if($confirm) {".$handler."} else return false;";
else
$handler="return $confirm;";
}
$cs->registerScript('Yii.CHtml.#'.$id,"jQuery('#$id').$event(function(){{$handler}});");
}
unset($htmlOptions['params'],$htmlOptions['submit'],$htmlOptions['ajax'],$htmlOptions['confirm']);
}
protected static function resolveNameID($model,&$attribute,&$htmlOptions)
{
if(!isset($htmlOptions['name']))
{
if(($pos=strpos($attribute,'['))!==false)
$htmlOptions['name']=get_class($model).substr($attribute,$pos).'['.($attribute=substr($attribute,0,$pos)).']';
else
$htmlOptions['name']=get_class($model).'['.$attribute.']';
}
if(!isset($htmlOptions['id']))
$htmlOptions['id']=self::getIdByName($htmlOptions['name']);
}
protected static function addErrorCss(&$htmlOptions)
{
if(isset($htmlOptions['class']))
$htmlOptions['class'].=' '.self::$errorCss;
else
$htmlOptions['class']=self::$errorCss;
}
}
class CWidget extends CBaseController
{
public $actionPrefix;
private static $_viewPaths;
private static $_counter=0;
private $_id;
private $_owner;
public static function actions()
{
return array();
}
public function __construct($owner=null)
{
$this->_owner=$owner===null?Yii::app()->getController():$owner;
}
public function getOwner()
{
return $this->_owner;
}
public function getId($autoGenerate=true)
{
if($this->_id!==null)
return $this->_id;
else if($autoGenerate)
return $this->_id='yw'.self::$_counter++;
}
public function setId($value)
{
$this->_id=$value;
}
public function getController()
{
if($this->_owner instanceof CController)
return $this->_owner;
else
return Yii::app()->getController();
}
public function init()
{
}
public function run()
{
}
public function getViewPath()
{
$className=get_class($this);
if(isset(self::$_viewPaths[$className]))
return self::$_viewPaths[$className];
else
{
$class=new ReflectionClass(get_class($this));
return self::$_viewPaths[$className]=dirname($class->getFileName()).DIRECTORY_SEPARATOR.'views';
}
}
public function getViewFile($viewName)
{
$viewFile=$this->getViewPath().DIRECTORY_SEPARATOR.$viewName.'.php';
return is_file($viewFile) ? Yii::app()->findLocalizedFile($viewFile) : false;
}
public function render($view,$data=null,$return=false)
{
if(($viewFile=$this->getViewFile($view))!==false)
return $this->renderFile($viewFile,$data,$return);
else
throw new CException(Yii::t('yii','{widget} cannot find the view "{view}".',
array('{widget}'=>get_class($this), '{view}'=>$view)));
}
}
class CClientScript extends CApplicationComponent
{
const POS_HEAD=0;
const POS_BEGIN=1;
const POS_END=2;
const POS_LOAD=3;
const POS_READY=4;
public $enableJavaScript=true;
private $_hasScripts=false;
private $_packages;
private $_dependencies;
private $_baseUrl;
private $_coreScripts=array();
private $_cssFiles=array();
private $_css=array();
private $_scriptFiles=array();
private $_scripts=array();
private $_metas=array();
private $_links=array();
public function reset()
{
$this->_hasScripts=false;
$this->_coreScripts=array();
$this->_cssFiles=array();
$this->_css=array();
$this->_scriptFiles=array();
$this->_scripts=array();
$this->_metas=array();
$this->_links=array();
Yii::app()->getController()->recordCachingAction('clientScript','reset',array());
}
public function render(&$output)
{
if(!$this->_hasScripts)
return;
$this->renderHead($output);
if($this->enableJavaScript)
{
$this->renderBodyBegin($output);
$this->renderBodyEnd($output);
}
}
protected function renderHead(&$output)
{
$html='';
foreach($this->_metas as $meta)
$html.=CHtml::metaTag($meta['content'],null,null,$meta);
foreach($this->_links as $link)
$html.=CHtml::linkTag(null,null,null,null,$link);
foreach($this->_cssFiles as $url=>$media)
$html.=CHtml::cssFile($url,$media)."\n";
foreach($this->_css as $css)
$html.=CHtml::css($css[0],$css[1])."\n";
if($this->enableJavaScript)
{
foreach($this->_coreScripts as $name)
{
if(is_string($name))
$html.=$this->renderCoreScript($name);
}
if(isset($this->_scriptFiles[self::POS_HEAD]))
{
foreach($this->_scriptFiles[self::POS_HEAD] as $scriptFile)
$html.=CHtml::scriptFile($scriptFile)."\n";
}
if(isset($this->_scripts[self::POS_HEAD]))
$html.=CHtml::script(implode("\n",$this->_scripts[self::POS_HEAD]))."\n";
}
if($html!=='')
{
$output=preg_replace('/(<title\b[^>]*>|<\\/head\s*>)/is',$html.'$1',$output,1,$count);
if(!$count)
$output=$html.$output;
}
}
protected function renderBodyBegin(&$output)
{
$html='';
if(isset($this->_scriptFiles[self::POS_BEGIN]))
{
foreach($this->_scriptFiles[self::POS_BEGIN] as $scriptFile)
$html.=CHtml::scriptFile($scriptFile)."\n";
}
if(isset($this->_scripts[self::POS_BEGIN]))
$html.=CHtml::script(implode("\n",$this->_scripts[self::POS_BEGIN]))."\n";
if($html!=='')
{
$output=preg_replace('/(<body\b[^>]*>)/is','$1'.$html,$output,1,$count);
if(!$count)
$output=$html.$output;
}
}
protected function renderBodyEnd(&$output)
{
$html='';
if(isset($this->_scriptFiles[self::POS_END]))
{
foreach($this->_scriptFiles[self::POS_END] as $scriptFile)
$html.=CHtml::scriptFile($scriptFile)."\n";
}
$scripts=isset($this->_scripts[self::POS_END]) ? $this->_scripts[self::POS_END] : array();
if(isset($this->_scripts[self::POS_READY]))
$scripts[]="jQuery(document).ready(function() {\n".implode("\n",$this->_scripts[self::POS_READY])."\n});";
if(isset($this->_scripts[self::POS_LOAD]))
$scripts[]="window.onload=function() {\n".implode("\n",$this->_scripts[self::POS_LOAD])."\n};";
if(!empty($scripts))
$html.=CHtml::script(implode("\n",$scripts))."\n";
if($html!=='')
{
$output=preg_replace('/(<\\/body\s*>)/is',$html.'$1',$output,1,$count);
if(!$count)
$output=$output.$html;
}
}
public function getCoreScriptUrl()
{
if($this->_baseUrl!==null)
return $this->_baseUrl;
else
return $this->_baseUrl=Yii::app()->getAssetManager()->publish(YII_PATH.'/web/js/source');
}
public function setCoreScriptUrl($value)
{
$this->_baseUrl=$value;
}
public function renderCoreScript($name)
{
if(isset($this->_coreScripts[$name]) && $this->_coreScripts[$name]===true || !$this->enableJavaScript)
return '';
$this->_coreScripts[$name]=true;
if($this->_packages===null)
{
$config=require(YII_PATH.'/web/js/packages.php');
$this->_packages=$config[0];
$this->_dependencies=$config[1];
}
$baseUrl=$this->getCoreScriptUrl();
$html='';
if(isset($this->_dependencies[$name]))
{
foreach($this->_dependencies[$name] as $depName)
$html.=$this->renderCoreScript($depName);
}
if(isset($this->_packages[$name]))
{
foreach($this->_packages[$name] as $path)
{
if(substr($path,-4)==='.css')
$html.=CHtml::cssFile($baseUrl.'/'.$path)."\n";
else
$html.=CHtml::scriptFile($baseUrl.'/'.$path)."\n";
}
}
return $html;
}
public function registerCoreScript($name)
{
$this->_hasScripts=true;
$this->_coreScripts[$name]=$name;
$params=func_get_args();
Yii::app()->getController()->recordCachingAction('clientScript','registerCoreScript',$params);
}
public function registerCssFile($url,$media='')
{
$this->_hasScripts=true;
$this->_cssFiles[$url]=$media;
$params=func_get_args();
Yii::app()->getController()->recordCachingAction('clientScript','registerCssFile',$params);
}
public function registerCss($id,$css,$media='')
{
$this->_hasScripts=true;
$this->_css[$id]=array($css,$media);
$params=func_get_args();
Yii::app()->getController()->recordCachingAction('clientScript','registerCss',$params);
}
public function registerScriptFile($url,$position=self::POS_HEAD)
{
$this->_hasScripts=true;
$this->_scriptFiles[$position][$url]=$url;
$params=func_get_args();
Yii::app()->getController()->recordCachingAction('clientScript','registerScriptFile',$params);
}
public function registerScript($id,$script,$position=self::POS_READY)
{
$this->_hasScripts=true;
$this->_scripts[$position][$id]=$script;
if($position===self::POS_READY)
$this->registerCoreScript('jquery');
$params=func_get_args();
Yii::app()->getController()->recordCachingAction('clientScript','registerScript',$params);
}
public function registerMetaTag($content,$name=null,$httpEquiv=null,$options=array())
{
$options['content']=$content;
if($name!==null)
$options['name']=$name;
if($httpEquiv!==null)
$options['http-equiv']=$httpEquiv;
$this->_metas[serialize($options)]=$options;
$params=func_get_args();
Yii::app()->getController()->recordCachingAction('clientScript','registerMetaTag',$params);
}
public function registerLinkTag($relation=null,$type=null,$href=null,$media=null,$options=array())
{
if($relation!==null)
$options['rel']=$relation;
if($type!==null)
$options['type']=$type;
if($href!==null)
$options['href']=$href;
if($media!==null)
$options['media']=$media;
$this->_links[serialize($options)]=$options;
$params=func_get_args();
Yii::app()->getController()->recordCachingAction('clientScript','registerLinkTag',$params);
}
public function isCssFileRegistered($url)
{
return isset($this->_cssFiles[$url]);
}
public function isCssRegistered($id)
{
return isset($this->_css[$id]);
}
public function isScriptFileRegistered($url,$position=self::POS_HEAD)
{
return isset($this->_bodyScriptFiles[$position][$url]);
}
public function isScriptRegistered($id,$position=self::POS_READY)
{
return isset($this->_scripts[$position][$id]);
}
}
class CList extends CComponent implements IteratorAggregate,ArrayAccess,Countable
{
private $_d=array();
private $_c=0;
private $_r=false;
public function __construct($data=null,$readOnly=false)
{
if($data!==null)
$this->copyFrom($data);
$this->setReadOnly($readOnly);
}
public function getReadOnly()
{
return $this->_r;
}
protected function setReadOnly($value)
{
$this->_r=$value;
}
public function getIterator()
{
return new CListIterator($this->_d);
}
public function count()
{
return $this->getCount();
}
public function getCount()
{
return $this->_c;
}
public function itemAt($index)
{
if(isset($this->_d[$index]))
return $this->_d[$index];
else if($index>=0 && $index<$this->_c) // in case the value is null
return $this->_d[$index];
else
throw new CException(Yii::t('yii','List index "{index}" is out of bound.',
array('{index}'=>$index)));
}
public function add($item)
{
$this->insertAt($this->_c,$item);
return $this->_c-1;
}
public function insertAt($index,$item)
{
if(!$this->_r)
{
if($index===$this->_c)
$this->_d[$this->_c++]=$item;
else if($index>=0 && $index<$this->_c)
{
array_splice($this->_d,$index,0,array($item));
$this->_c++;
}
else
throw new CException(Yii::t('yii','List index "{index}" is out of bound.',
array('{index}'=>$index)));
}
else
throw new CException(Yii::t('yii','The list is read only.'));
}
public function remove($item)
{
if(($index=$this->indexOf($item))>=0)
{
$this->removeAt($index);
return $index;
}
else
throw new CException(Yii::t('yii','Unable to find the list item.'));
}
public function removeAt($index)
{
if(!$this->_r)
{
if($index>=0 && $index<$this->_c)
{
$this->_c--;
if($index===$this->_c)
return array_pop($this->_d);
else
{
$item=$this->_d[$index];
array_splice($this->_d,$index,1);
return $item;
}
}
else
throw new CException(Yii::t('yii','List index "{index}" is out of bound.',
array('{index}'=>$index)));
}
else
throw new CException(Yii::t('yii','The list is read only.'));
}
public function clear()
{
for($i=$this->_c-1;$i>=0;--$i)
$this->removeAt($i);
}
public function contains($item)
{
return $this->indexOf($item)>=0;
}
public function indexOf($item)
{
if(($index=array_search($item,$this->_d,true))!==false)
return $index;
else
return -1;
}
public function toArray()
{
return $this->_d;
}
public function copyFrom($data)
{
if(is_array($data) || ($data instanceof Traversable))
{
if($this->_c>0)
$this->clear();
if($data instanceof CList)
$data=$data->_d;
foreach($data as $item)
$this->add($item);
}
else if($data!==null)
throw new CException(Yii::t('yii','List data must be an array or an object implementing Traversable.'));
}
public function mergeWith($data)
{
if(is_array($data) || ($data instanceof Traversable))
{
if($data instanceof CList)
$data=$data->_d;
foreach($data as $item)
$this->add($item);
}
else if($data!==null)
throw new CException(Yii::t('yii','List data must be an array or an object implementing Traversable.'));
}
public function offsetExists($offset)
{
return ($offset>=0 && $offset<$this->_c);
}
public function offsetGet($offset)
{
return $this->itemAt($offset);
}
public function offsetSet($offset,$item)
{
if($offset===null || $offset===$this->_c)
$this->insertAt($this->_c,$item);
else
{
$this->removeAt($offset);
$this->insertAt($offset,$item);
}
}
public function offsetUnset($offset)
{
$this->removeAt($offset);
}
}
class CListIterator implements Iterator
{
private $_d;
private $_i;
private $_c;
public function __construct(&$data)
{
$this->_d=&$data;
$this->_i=0;
$this->_c=count($this->_d);
}
public function rewind()
{
$this->_i=0;
}
public function key()
{
return $this->_i;
}
public function current()
{
return $this->_d[$this->_i];
}
public function next()
{
$this->_i++;
}
public function valid()
{
return $this->_i<$this->_c;
}
}
class CFilterChain extends CList
{
public $controller;
public $action;
public $filterIndex=0;
public function __construct($controller,$action)
{
$this->controller=$controller;
$this->action=$action;
}
public static function create($controller,$action,$filters)
{
$chain=new CFilterChain($controller,$action);
$actionID=$action->getId();
foreach($filters as $filter)
{
if(is_string($filter)) // filterName [+|- action1 action2]
{
if(($pos=strpos($filter,'+'))!==false || ($pos=strpos($filter,'-'))!==false)
{
$matched=preg_match("/\b{$actionID}\b/i",substr($filter,$pos+1))>0;
if(($filter[$pos]==='+')===$matched)
$chain->add(CInlineFilter::create($controller,trim(substr($filter,0,$pos))));
}
else
$chain->add(CInlineFilter::create($controller,$filter));
}
else if(is_array($filter)) // array('path.to.class [+|- action1, action2]','param1'=>'value1',...)
{
if(!isset($filter[0]))
throw new CException(Yii::t('yii','The first element in a filter configuration must be the filter class.'));
$filterClass=$filter[0];
unset($filter[0]);
if(($pos=strpos($filterClass,'+'))!==false || ($pos=strpos($filterClass,'-'))!==false)
{
$matched=preg_match("/\b{$actionID}\b/i",substr($filterClass,$pos+1))>0;
if(($filterClass[$pos]==='+')===$matched)
$filterClass=trim(substr($filterClass,0,$pos));
else
continue;
}
$filter['class']=$filterClass;
$chain->add(Yii::createComponent($filter));
}
else
$chain->add($filter);
}
return $chain;
}
public function insertAt($index,$item)
{
if($item instanceof IFilter)
parent::insertAt($index,$item);
else
throw new CException(Yii::t('yii','CFilterChain can only take objects implementing the IFilter interface.'));
}
public function run()
{
if($this->offsetExists($this->filterIndex))
{
$filter=$this->itemAt($this->filterIndex++);
$filter->filter($this);
}
else
$this->controller->runAction($this->action);
}
}
class CFilter extends CComponent implements IFilter
{
public function filter($filterChain)
{
if($this->preFilter($filterChain))
{
$filterChain->run();
$this->postFilter($filterChain);
}
}
protected function preFilter($filterChain)
{
return true;
}
protected function postFilter($filterChain)
{
}
}
class CInlineFilter extends CFilter
{
public $name;
public static function create($controller,$filterName)
{
$filter=new CInlineFilter;
$filter->name=$filterName;
return $filter;
}
public function filter($filterChain)
{
$method='filter'.$this->name;
if(method_exists($filterChain->controller,$method))
$filterChain->controller->$method($filterChain);
else
throw new CException(Yii::t('yii','Filter "{filter}" is invalid. Controller "{class}" does have the filter method "filter{filter}".',
array('{filter}'=>$this->name, '{class}'=>get_class($filterChain->controller))));
}
}
class CAccessControlFilter extends CFilter
{
private $_rules=array();
public function getRules()
{
return $this->_rules;
}
public function setRules($rules)
{
foreach($rules as $rule)
{
if(is_array($rule) && isset($rule[0]))
{
$r=new CAccessRule;
$r->allow=$rule[0]==='allow';
foreach(array_slice($rule,1) as $name=>$value)
$r->$name=array_map('strtolower',$value);
$this->_rules[]=$r;
}
}
}
protected function preFilter($filterChain)
{
$app=Yii::app();
$request=$app->getRequest();
$user=$app->getUser();
$verb=$request->getRequestType();
$ip=$request->getUserHostAddress();
$action=$filterChain->action;
foreach($this->_rules as $rule)
{
if(($allow=$rule->isUserAllowed($user,$action,$ip,$verb))>0) // allowed
break;
else if($allow<0) // denied
{
if($user->getIsGuest())
{
$user->loginRequired();
return false;
}
else
throw new CHttpException(401,Yii::t('yii','You are not authorized to perform this action.'));
}
}
return true;
}
}
class CAccessRule extends CComponent
{
public $allow;
public $actions;
public $users;
public $roles;
public $ips;
public $verbs;
public function isUserAllowed($user,$action,$ip,$verb)
{
if($this->isActionMatched($action)
&& $this->isUserMatched($user)
&& $this->isRoleMatched($user)
&& $this->isIpMatched($ip)
&& $this->isVerbMatched($verb))
return $this->allow ? 1 : -1;
else
return 0;
}
private function isActionMatched($action)
{
return empty($this->actions) || in_array(strtolower($action->getId()),$this->actions);
}
private function isUserMatched($user)
{
if(empty($this->users))
return true;
foreach($this->users as $u)
{
if($u==='*')
return true;
else if($u==='?' && $user->getIsGuest())
return true;
else if($u==='@' && !$user->getIsGuest())
return true;
else if(!strcasecmp($u,$user->getName()))
return true;
}
return false;
}
private function isRoleMatched($user)
{
if(empty($this->roles))
return true;
foreach($this->roles as $role)
{
if($user->checkAccess($role))
return true;
}
return false;
}
private function isIpMatched($ip)
{
if(empty($this->ips))
return true;
foreach($this->ips as $rule)
{
if($rule==='*' || $rule===$ip || (($pos=strpos($rule,'*'))!==false && !strncmp($ip,$rule,$pos)))
return true;
}
return false;
}
private function isVerbMatched($verb)
{
return empty($this->verbs) || in_array(strtolower($verb),$this->verbs);
}
}
abstract class CModel extends CComponent
{
private $_errors=array(); // attribute name => array of errors
public function validate($attributes=null,$on=null)
{
$this->clearErrors();
if($this->beforeValidate($on))
{
foreach($this->getValidators() as $validator)
{
if(empty($on) || $validator->on===array() || in_array($on,$validator->on))
$validator->validate($this,$attributes);
}
$this->afterValidate($on);
return !$this->hasErrors();
}
else
return false;
}
protected function beforeValidate($on)
{
return true;
}
protected function afterValidate($on)
{
}
public function createValidators()
{
$validators=array();
foreach($this->rules() as $rule)
{
if(isset($rule[0],$rule[1])) // attributes, validator name
$validators[]=CValidator::createValidator($rule[1],$this,$rule[0],array_slice($rule,2));
else
throw new CException(Yii::t('yii','{class} has an invalid validation rule. The rule must specify attributes to be validated and the validator name.',
array('{class}'=>get_class($this))));
}
return $validators;
}
protected function getValidators()
{
return $this->createValidators();
}
public function attributeLabels()
{
return array();
}
public function rules()
{
return array();
}
public function getAttributeLabel($attribute)
{
$labels=$this->attributeLabels();
if(isset($labels[$attribute]))
return $labels[$attribute];
else
return $this->generateAttributeLabel($attribute);
}
public function hasErrors($attribute=null)
{
if($attribute===null)
return $this->_errors!==array();
else
return isset($this->_errors[$attribute]);
}
public function getErrors($attribute=null)
{
if($attribute===null)
return $this->_errors;
else
return isset($this->_errors[$attribute]) ? $this->_errors[$attribute] : array();
}
public function addError($attribute,$error)
{
$this->_errors[$attribute][]=$error;
}
public function clearErrors($attribute=null)
{
if($attribute===null)
$this->_errors=array();
else
unset($this->_errors[$attribute]);
}
public function generateAttributeLabel($name)
{
return ucwords(trim(strtolower(str_replace(array('-','_'),' ',preg_replace('/(?<![A-Z])[A-Z]/', ' \0', $name)))));
}
}
abstract class CActiveRecord extends CModel
{
const BELONGS_TO='CBelongsToRelation';
const HAS_ONE='CHasOneRelation';
const HAS_MANY='CHasManyRelation';
const MANY_MANY='CManyManyRelation';
public static $db;
public $isNewRecord=false;
private static $_models=array(); // class name => model
private $_md;
private $_attributes=array(); // attribute name => attribute value
private $_related=array(); // attribute name => related objects
public function __construct($attributes=array())
{
if($attributes===null) // internally used by populateRecord() and model()
return;
$this->isNewRecord=true;
$this->_attributes=$this->getMetaData()->attributeDefaults;
if($attributes!==array())
$this->setAttributes($attributes);
$this->afterConstruct();
}
public function __sleep()
{
$this->_md=null;
return array_keys((array)$this);
}
public function __get($name)
{
if(isset($this->_attributes[$name]))
return $this->_attributes[$name];
else if(isset($this->getMetaData()->columns[$name]))
return null;
else if(isset($this->_related[$name]))
return $this->_related[$name];
else if(isset($this->getMetaData()->relations[$name]))
{
if(!array_key_exists($name,$this->_related))
{
$relation=$this->getMetaData()->relations[$name];
$finder=new CActiveFinder($this,array($name=>$relation->with));
$finder->lazyFind($this);
}
return $this->_related[$name];
}
else
return parent::__get($name);
}
public function __set($name,$value)
{
if(isset($this->getMetaData()->columns[$name]))
$this->_attributes[$name]=$value;
else if(isset($this->getMetaData()->relations[$name]))
$this->_related[$name]=$value;
else
parent::__set($name,$value);
}
public function __isset($name)
{
if(isset($this->_attributes[$name]))
return true;
else if(isset($this->getMetaData()->columns[$name]))
return false;
else if(isset($this->_related[$name]))
return true;
else if(isset($this->getMetaData()->relations[$name]))
{
if(!array_key_exists($name,$this->_related))
{
$relation=$this->getMetaData()->relations[$name];
$finder=new CActiveFinder($this,array($name=>$relation->with));
$finder->lazyFind($this);
}
return $this->_related[$name]!==null;
}
else
return parent::__isset($name);
}
public function __unset($name)
{
if(isset($this->getMetaData()->columns[$name]))
unset($this->_attributes[$name]);
else if(isset($this->getMetaData()->relations[$name]))
unset($this->_related[$name]);
else
parent::__unset($name);
}
public static function model($className=__CLASS__)
{
if(isset(self::$_models[$className]))
return self::$_models[$className];
else
{
$model=self::$_models[$className]=new $className(null);
$model->isNewRecord=false;
$model->_md=new CActiveRecordMetaData($model);
return $model;
}
}
public function getMetaData()
{
if($this->_md!==null)
return $this->_md;
else
return $this->_md=self::model(get_class($this))->_md;
}
public function tableName()
{
return get_class($this);
}
public function protectedAttributes()
{
return array();
}
public function safeAttributes()
{
$table=$this->getDbConnection()->getSchema()->getTable($this->tableName());
$protectedAttributes=array_flip($this->protectedAttributes());
$safeAttributes=array();
foreach($table->columns as $name=>$column)
{
if(!$column->isPrimaryKey && !isset($protectedAttributes[$name]))
$safeAttributes[]=$name;
}
return $safeAttributes;
}
public function relations()
{
return array();
}
public function getDbConnection()
{
if(self::$db!==null)
return self::$db;
else
{
self::$db=Yii::app()->getDb();
if(self::$db instanceof CDbConnection)
{
self::$db->setActive(true);
return self::$db;
}
else
throw new CDbException(Yii::t('yii','Active Record requires a "db" CDbConnection application component.'));
}
}
public function getAttributeLabel($attribute)
{
if(($label=$this->getMetaData()->getAttributeLabel($attribute))!==null)
return $label;
else
return $this->generateAttributeLabel($attribute);
}
public function getActiveRelation($name)
{
return isset($this->getMetaData()->relations[$name]) ? $this->getMetaData()->relations[$name] : null;
}
public function getTableSchema()
{
return $this->getMetaData()->tableSchema;
}
public function getCommandBuilder()
{
return $this->getDbConnection()->getSchema()->getCommandBuilder();
}
public function hasAttribute($name)
{
return isset($this->getMetaData()->columns[$name]);
}
public function getAttribute($name)
{
if(property_exists($this,$name))
return $this->$name;
else if(isset($this->_attributes[$name]))
return $this->_attributes[$name];
else if(isset($this->getMetaData()->columns[$name]))
return null;
else
throw new CDbException(Yii::t('yii','{class} does not have attribute "{name}".',
array('{class}'=>get_class($this), '{name}'=>$name)));
}
public function setAttribute($name,$value)
{
if(property_exists($this,$name))
$this->$name=$value;
else if(isset($this->getMetaData()->columns[$name]))
$this->_attributes[$name]=$value;
else
throw new CDbException(Yii::t('yii','{class} does not have attribute "{name}".',
array('{class}'=>get_class($this), '{name}'=>$name)));
}
public function addRelatedRecord($name,$record,$multiple)
{
if($multiple)
{
if(!isset($this->_related[$name]))
$this->_related[$name]=array();
if($record instanceof CActiveRecord)
$this->_related[$name][]=$record;
}
else if(!isset($this->_related[$name]))
$this->_related[$name]=$record;
}
public function getAttributes($names=true)
{
$attributes=$this->_attributes;
foreach($this->getMetaData()->columns as $name=>$column)
{
if(property_exists($this,$name))
$attributes[$name]=$this->$name;
else if($names===true && !isset($attributes[$name]))
$attributes[$name]=null;
}
if(is_array($names))
{
$attrs=array();
foreach($names as $name)
$attrs[$name]=isset($attributes[$name])?$attributes[$name]:null;
return $attrs;
}
else
return $attributes;
}
public function setAttributes($values,$safeAttributes=null,$safeAttributesOnly=true)
{
if(is_array($values))
{
if($safeAttributesOnly)
{
if(empty($safeAttributes))
$safeAttributes=$this->getMetaData()->safeAttributes;
else
$safeAttributes=array_flip($safeAttributes);
foreach($values as $name=>$value)
{
if(isset($safeAttributes[$name]))
$this->$name=$value;
}
}
else
{
foreach($values as $name=>$value)
$this->$name=$value;
}
}
}
public function save($runValidation=true,$attributes=null)
{
if(!$runValidation || $this->validate($attributes,$this->isNewRecord?'insert':'update'))
return $this->isNewRecord ? $this->insert($attributes) : $this->update($attributes);
else
return false;
}
protected function getValidators()
{
return $this->getMetaData()->getValidators();
}
protected function beforeSave()
{
return true;
}
protected function afterSave()
{
}
protected function beforeDelete()
{
return true;
}
protected function afterDelete()
{
}
protected function afterConstruct()
{
}
protected function afterFind()
{
}
public function insert($attributes=null)
{
if(!$this->isNewRecord)
throw new CDbException(Yii::t('yii','The active record cannot be inserted to database because it is not new.'));
if($this->beforeSave())
{
$builder=$this->getCommandBuilder();
$table=$this->getMetaData()->tableSchema;
$command=$builder->createInsertCommand($table,$this->getAttributes($attributes));
if($command->execute())
{
$primaryKey=$table->primaryKey;
if($table->sequenceName!==null && is_string($primaryKey) && $this->$primaryKey===null)
$this->$primaryKey=$builder->getLastInsertID($table);
$this->afterSave();
$this->isNewRecord=false;
return true;
}
else
$this->afterSave();
}
else
return false;
}
public function update($attributes=null)
{
if($this->isNewRecord)
throw new CDbException(Yii::t('yii','The active record cannot be updated because it is new.'));
if($this->beforeSave())
{
$result=$this->updateByPk($this->getPrimaryKey(),$this->getAttributes($attributes))>0;
$this->afterSave();
return $result;
}
else
return false;
}
public function saveAttributes($attributes)
{
if(!$this->isNewRecord)
{
$values=array();
foreach($attributes as $name=>$value)
{
if(is_integer($name))
$values[$value]=$this->$value;
else
$values[$name]=$this->$name=$value;
}
return $this->updateByPk($this->getPrimaryKey(),$values)>0;
}
else
throw new CDbException(Yii::t('yii','The active record cannot be updated because it is new.'));
}
public function delete()
{
if(!$this->isNewRecord)
{
if($this->beforeDelete())
{
$result=$this->deleteByPk($this->getPrimaryKey())>0;
$this->afterDelete();
return $result;
}
else
return false;
}
else
throw new CDbException(Yii::t('yii','The active record cannot be deleted because it is new.'));
}
public function refresh()
{
if(!$this->isNewRecord && ($record=$this->findByPk($this->getPrimaryKey()))!==null)
{
$this->_attributes=array();
$this->_related=array();
foreach($this->getMetaData()->columns as $name=>$column)
$this->$name=$record->$name;
return true;
}
else
return false;
}
public function equals($record)
{
return $this->tableName()===$record->tableName() && $this->getPrimaryKey()===$record->getPrimaryKey();
}
public function getPrimaryKey()
{
$table=$this->getMetaData()->tableSchema;
if(is_string($table->primaryKey))
return $this->{$table->primaryKey};
else if(is_array($table->primaryKey))
{
$values=array();
foreach($table->primaryKey as $name)
$values[$name]=$this->$name;
return $values;
}
else
return null;
}
public function find($condition='',$params=array())
{
$builder=$this->getCommandBuilder();
$criteria=$builder->createCriteria($condition,$params);
$criteria->limit=1;
$command=$builder->createFindCommand($this->getTableSchema(),$criteria);
return $this->populateRecord($command->queryRow());
}
public function findAll($condition='',$params=array())
{
$builder=$this->getCommandBuilder();
$criteria=$builder->createCriteria($condition,$params);
$command=$builder->createFindCommand($this->getTableSchema(),$criteria);
return $this->populateRecords($command->queryAll());
}
public function findByPk($pk,$condition='',$params=array())
{
$builder=$this->getCommandBuilder();
$criteria=$builder->createPkCriteria($this->getTableSchema(),$pk,$condition,$params);
$criteria->limit=1;
$command=$builder->createFindCommand($this->getTableSchema(),$criteria);
return $this->populateRecord($command->queryRow());
}
public function findAllByPk($pk,$condition='',$params=array())
{
$builder=$this->getCommandBuilder();
$criteria=$builder->createPkCriteria($this->getTableSchema(),$pk,$condition,$params);
$command=$builder->createFindCommand($this->getTableSchema(),$criteria);
return $this->populateRecords($command->queryAll());
}
public function findByAttributes($attributes,$condition='',$params=array())
{
$builder=$this->getCommandBuilder();
$criteria=$builder->createColumnCriteria($this->getTableSchema(),$attributes,$condition,$params);
$criteria->limit=1;
$command=$builder->createFindCommand($this->getTableSchema(),$criteria);
return $this->populateRecord($command->queryRow());
}
public function findAllByAttributes($attributes,$condition='',$params=array())
{
$builder=$this->getCommandBuilder();
$criteria=$builder->createColumnCriteria($this->getTableSchema(),$attributes,$condition,$params);
$command=$builder->createFindCommand($this->getTableSchema(),$criteria);
return $this->populateRecords($command->queryAll());
}
public function findBySql($sql,$params=array())
{
$command=$this->getCommandBuilder()->createSqlCommand($sql,$params);
return $this->populateRecord($command->queryRow());
}
public function findAllBySql($sql,$params=array())
{
$command=$this->getCommandBuilder()->createSqlCommand($sql,$params);
return $this->populateRecords($command->queryAll());
}
public function count($condition='',$params=array())
{
$builder=$this->getCommandBuilder();
$criteria=$builder->createCriteria($condition,$params);
return $builder->createCountCommand($this->getTableSchema(),$criteria)->queryScalar();
}
public function countBySql($sql,$params=array())
{
return $this->getCommandBuilder()->createSqlCommand($sql,$params)->queryScalar();
}
public function exists($condition,$params=array())
{
$builder=$this->getCommandBuilder();
$criteria=$builder->createCriteria($condition,$params);
$table=$this->getTableSchema();
$criteria->select=reset($table->columns)->rawName;
$criteria->limit=1;
return $builder->createFindCommand($table,$criteria)->queryRow()!==false;
}
public function with()
{
if(func_num_args()>0)
{
$with=func_get_args();
return new CActiveFinder($this,$with);
}
else
return $this;
}
public function updateByPk($pk,$attributes,$condition='',$params=array())
{
$builder=$this->getCommandBuilder();
$table=$this->getTableSchema();
$criteria=$builder->createPkCriteria($table,$pk,$condition,$params);
$command=$builder->createUpdateCommand($table,$attributes,$criteria);
return $command->execute();
}
public function updateAll($attributes,$condition='',$params=array())
{
$builder=$this->getCommandBuilder();
$criteria=$builder->createCriteria($condition,$params);
$command=$builder->createUpdateCommand($this->getTableSchema(),$attributes,$criteria);
return $command->execute();
}
public function updateCounters($counters,$condition='',$params=array())
{
$builder=$this->getCommandBuilder();
$criteria=$builder->createCriteria($condition,$params);
$command=$builder->createUpdateCounterCommand($this->getTableSchema(),$counters,$criteria);
return $command->execute();
}
public function deleteByPk($pk,$condition='',$params=array())
{
$builder=$this->getCommandBuilder();
$criteria=$builder->createPkCriteria($this->getTableSchema(),$pk,$condition,$params);
$command=$builder->createDeleteCommand($this->getTableSchema(),$criteria);
return $command->execute();
}
public function deleteAll($condition='',$params=array())
{
$builder=$this->getCommandBuilder();
$criteria=$builder->createCriteria($condition,$params);
$command=$builder->createDeleteCommand($this->getTableSchema(),$criteria);
return $command->execute();
}
public function populateRecord($attributes)
{
if($attributes!==false)
{
$class=get_class($this);
$record=new $class(null);
$record->isNewRecord=false;
$record->_md=$this->getMetaData();
foreach($attributes as $name=>$value)
{
if(property_exists($record,$name))
$record->$name=$value;
else if(isset($record->_md->columns[$name]))
$record->_attributes[$name]=$value;
}
$record->afterFind();
return $record;
}
else
return null;
}
public function populateRecords($data)
{
$records=array();
$class=get_class($this);
$md=$this->getMetaData();
$table=$md->tableSchema;
foreach($data as $attributes)
{
$record=new $class(null);
$record->isNewRecord=false;
$record->_md=$md;
foreach($attributes as $name=>$value)
{
if(property_exists($record,$name))
$record->$name=$value;
else if(isset($record->_md->columns[$name]))
$record->_attributes[$name]=$value;
}
$record->afterFind();
$records[]=$record;
}
return $records;
}
}
class CActiveRelation extends CComponent
{
public $name;
public $className;
public $foreignKey;
public $joinType='LEFT OUTER JOIN';
public $select='*';
public $condition='';
public $order='';
public $alias;
public $aliasToken='??';
public $with=array();
public function __construct($name,$className,$foreignKey,$options=array())
{
$this->name=$name;
$this->className=$className;
$this->foreignKey=$foreignKey;
foreach($options as $name=>$value)
$this->$name=$value;
}
}
class CBelongsToRelation extends CActiveRelation
{
}
class CHasOneRelation extends CActiveRelation
{
}
class CHasManyRelation extends CActiveRelation
{
public $group='';
public $having='';
public $limit=-1;
public $offset=-1;
}
class CManyManyRelation extends CHasManyRelation
{
}
class CActiveRecordMetaData
{
public $tableSchema;
public $columns;
public $relations=array();
public $attributeDefaults=array();
public $safeAttributes=array();
private $_model;
private $_attributeLabels;
private $_validators;
public function __construct($model)
{
$this->_model=$model;
$tableName=$model->tableName();
if(($table=$model->getDbConnection()->getSchema()->getTable($tableName))===null)
throw new CDbException(Yii::t('yii','The table "{table}" for active record class "{class}" cannot be found in the database.',
array('{class}'=>get_class($model),'{table}'=>$tableName)));
$this->tableSchema=$table;
$this->columns=$table->columns;
$this->safeAttributes=array_flip($model->safeAttributes($table));
foreach($table->columns as $name=>$column)
{
if(!$column->isPrimaryKey && $column->defaultValue!==null)
$this->attributeDefaults[$name]=$column->defaultValue;
}
foreach($model->relations() as $name=>$config)
{
if(isset($config[0],$config[1],$config[2])) // relation class, AR class, FK
$this->relations[$name]=new $config[0]($name,$config[1],$config[2],array_slice($config,3));
else
throw new CDbException(Yii::t('yii','Active record "{class}" has an invalid configuration for relation "{relation}". It must specify the relation type, the related active record class and the foreign key.',
array('{class}'=>get_class($model),'{relation}'=>$name)));
}
}
public function getAttributeLabel($attribute)
{
if($this->_attributeLabels===null)
$this->_attributeLabels=$this->_model->attributeLabels();
return isset($this->_attributeLabels[$attribute]) ? $this->_attributeLabels[$attribute] : null;
}
public function getValidators()
{
if(!$this->_validators)
$this->_validators=$this->_model->createValidators();
return $this->_validators;
}
}
class CDbConnection extends CApplicationComponent
{
public $connectionString;
public $username='';
public $password='';
public $schemaCachingDuration=0;
public $schemaCachingExclude=array();
public $autoConnect=true;
public $charset;
public $emulatePrepare=false;
private $_attributes=array();
private $_active=false;
private $_pdo;
private $_transaction;
private $_schema;
public function __construct($dsn='',$username='',$password='')
{
$this->connectionString=$dsn;
$this->username=$username;
$this->password=$password;
}
public function __sleep()
{
$this->close();
return array_keys(get_object_vars($this));
}
public static function getAvailableDrivers()
{
return PDO::getAvailableDrivers();
}
public function init()
{
parent::init();
if($this->autoConnect)
$this->setActive(true);
}
public function getActive()
{
return $this->_active;
}
public function setActive($value)
{
if($value!=$this->_active)
{
if($value)
$this->open();
else
$this->close();
}
}
protected function open()
{
if($this->_pdo===null)
{
if(empty($this->connectionString))
throw new CDbException(Yii::t('yii','CDbConnection.connectionString cannot be empty.'));
try
{
$this->_pdo=new PDO($this->connectionString,$this->username,
$this->password,$this->_attributes);
$this->initConnection($this->_pdo);
$this->_active=true;
}
catch(PDOException $e)
{
throw new CDbException(Yii::t('yii','CDbConnection failed to open the DB connection: {error}',
array('{error}'=>$e->getMessage())));
}
}
}
protected function close()
{
$this->_pdo=null;
$this->_active=false;
$this->_schema=null;
}
protected function initConnection($pdo)
{
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if($this->emulatePrepare && constant('PDO::ATTR_EMULATE_PREPARES'))
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,true);
if($this->charset===null)
return;
switch(strtolower($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)))
{
case 'pgsql':
$stmt=$pdo->prepare('SET client_encoding TO ?');
$stmt->execute(array($this->charset));
break;
case 'mysqli':
case 'mysql':
$stmt=$pdo->prepare('SET CHARACTER SET ?');
$stmt->execute(array($this->charset));
break;
}
}
public function getPdoInstance()
{
return $this->_pdo;
}
public function createCommand($sql)
{
if($this->getActive())
return new CDbCommand($this,$sql);
else
throw new CDbException(Yii::t('yii','CDbConnection is inactive and cannot perform any DB operations.'));
}
public function getCurrentTransaction()
{
if($this->_transaction!==null)
{
if($this->_transaction->getActive())
return $this->_transaction;
}
return null;
}
public function beginTransaction()
{
if($this->getActive())
{
$this->_pdo->beginTransaction();
return $this->_transaction=new CDbTransaction($this);
}
else
throw new CDbException(Yii::t('yii','CDbConnection is inactive and cannot perform any DB operations.'));
}
public function getSchema()
{
if($this->_schema!==null)
return $this->_schema;
else
{
if(!$this->getActive())
throw new CDbException(Yii::t('yii','CDbConnection is inactive and cannot perform any DB operations.'));
$driver=$this->getDriverName();
switch(strtolower($driver))
{
case 'pgsql':
return $this->_schema=new CPgsqlSchema($this);
case 'mysqli':
case 'mysql':
return $this->_schema=new CMysqlSchema($this);
case 'sqlite': // sqlite 3
case 'sqlite2': // sqlite 2
return $this->_schema=new CSqliteSchema($this);
case 'mssql': // Mssql driver on windows hosts
case 'dblib': // dblib drivers on linux (and maybe others os) hosts
case 'oci':
case 'ibm':
default:
throw new CDbException(Yii::t('yii','CDbConnection does not support reading schema for {driver} database.',
array('{driver}'=>$driver)));
}
}
}
public function getLastInsertID($sequenceName='')
{
if($this->getActive())
return $this->_pdo->lastInsertId($sequenceName);
else
throw new CDbException(Yii::t('yii','CDbConnection is inactive and cannot perform any DB operations.'));
}
public function quoteValue($str)
{
if($this->getActive())
return $this->_pdo->quote($str);
else
throw new CDbException(Yii::t('yii','CDbConnection is inactive and cannot perform any DB operations.'));
}
public function quoteTableName($name)
{
return $this->getSchema()->quoteTableName($name);
}
public function quoteColumnName($name)
{
return $this->getSchema()->quoteColumnName($name);
}
public function getPdoType($type)
{
static $map=array
(
'boolean'=>PDO::PARAM_BOOL,
'integer'=>PDO::PARAM_INT,
'string'=>PDO::PARAM_STR,
'NULL'=>PDO::PARAM_NULL,
);
return isset($map[$type]) ? $map[$type] : PDO::PARAM_STR;
}
public function getColumnCase()
{
return $this->getAttribute(PDO::ATTR_CASE);
}
public function setColumnCase($value)
{
$this->setAttribute(PDO::ATTR_CASE,$value);
}
public function getNullConversion()
{
return $this->getAttribute(PDO::ATTR_ORACLE_NULLS);
}
public function setNullConversion($value)
{
$this->setAttribute(PDO::ATTR_ORACLE_NULLS,$value);
}
public function getAutoCommit()
{
return $this->getAttribute(PDO::ATTR_AUTOCOMMIT);
}
public function setAutoCommit($value)
{
$this->setAttribute(PDO::ATTR_AUTOCOMMIT,$value);
}
public function getPersistent()
{
return $this->getAttribute(PDO::ATTR_PERSISTENT);
}
public function setPersistent($value)
{
return $this->setAttribute(PDO::ATTR_PERSISTENT,$value);
}
public function getDriverName()
{
return $this->getAttribute(PDO::ATTR_DRIVER_NAME);
}
public function getClientVersion()
{
return $this->getAttribute(PDO::ATTR_CLIENT_VERSION);
}
public function getConnectionStatus()
{
return $this->getAttribute(PDO::ATTR_CONNECTION_STATUS);
}
public function getPrefetch()
{
return $this->getAttribute(PDO::ATTR_PREFETCH);
}
public function getServerInfo()
{
return $this->getAttribute(PDO::ATTR_SERVER_INFO);
}
public function getServerVersion()
{
return $this->getAttribute(PDO::ATTR_SERVER_VERSION);
}
public function getTimeout()
{
return $this->getAttribute(PDO::ATTR_TIMEOUT);
}
public function getAttribute($name)
{
if($this->getActive())
return $this->_pdo->getAttribute($name);
else
throw new CDbException(Yii::t('yii','CDbConnection is inactive and cannot perform any DB operations.'));
}
public function setAttribute($name,$value)
{
if($this->_pdo instanceof PDO)
$this->_pdo->setAttribute($name,$value);
else
$this->_attributes[$name]=$value;
}
}
abstract class CDbSchema extends CComponent
{
private $_tables=array();
private $_connection;
private $_builder;
private $_cacheExclude=array();
abstract protected function createTable($name);
public function __construct($conn)
{
$conn->setActive(true);
$this->_connection=$conn;
foreach($conn->schemaCachingExclude as $name)
$this->_cacheExclude[$name]=true;
}
public function getDbConnection()
{
return $this->_connection;
}
public function getTable($name)
{
if(isset($this->_tables[$name]))
return $this->_tables[$name];
else if(!isset($this->_cacheExclude[$name]) && ($duration=$this->_connection->schemaCachingDuration)>0 && ($cache=Yii::app()->getCache())!==null)
{
$key='yii:dbschema'.$this->_connection->connectionString.':'.$this->_connection->username.':'.$name;
if(($table=$cache->get($key))===false)
{
$table=$this->createTable($name);
$cache->set($key,$table,$duration);
}
return $this->_tables[$name]=$table;
}
else
return $this->_tables[$name]=$this->createTable($name);
}
public function getCommandBuilder()
{
if($this->_builder!==null)
return $this->_builder;
else
return $this->_builder=$this->createCommandBuilder();
}
protected function createCommandBuilder()
{
return new CDbCommandBuilder($this);
}
public function refresh()
{
$this->_tables=array();
$this->_builder=null;
}
public function quoteTableName($name)
{
return "'".$name."'";
}
public function quoteColumnName($name)
{
return '"'.$name.'"';
}
public function compareTableNames($name1,$name2)
{
$name1=str_replace(array('"','`',"'"),'',$name1);
$name2=str_replace(array('"','`',"'"),'',$name2);
if(($pos=strrpos($name1,'.'))!==false)
$name1=substr($name1,$pos+1);
if(($pos=strrpos($name2,'.'))!==false)
$name2=substr($name2,$pos+1);
return $name1===$name2;
}
}
class CSqliteSchema extends CDbSchema
{
protected function createCommandBuilder()
{
return new CSqliteCommandBuilder($this);
}
protected function createTable($name)
{
$db=$this->getDbConnection();
$table=new CDbTableSchema;
$table->name=$name;
$table->rawName=$this->quoteTableName($name);
if($this->findColumns($table))
{
$this->findConstraints($table);
return $table;
}
else
return null;
}
protected function findColumns($table)
{
$sql="PRAGMA table_info({$table->rawName})";
$columns=$this->getDbConnection()->createCommand($sql)->queryAll();
if(empty($columns))
return false;
foreach($columns as $column)
{
$c=$this->createColumn($column);
$table->columns[$c->name]=$c;
if($c->isPrimaryKey)
{
if($table->primaryKey===null)
$table->primaryKey=$c->name;
else if(is_string($table->primaryKey))
$table->primaryKey=array($table->primaryKey,$c->name);
else
$table->primaryKey[]=$c->name;
}
}
if(is_string($table->primaryKey) && !strncasecmp($table->columns[$table->primaryKey]->dbType,'int',3))
$table->sequenceName='';
return true;
}
protected function findConstraints($table)
{
$foreignKeys=array();
$sql="PRAGMA foreign_key_list({$table->rawName})";
$keys=$this->getDbConnection()->createCommand($sql)->queryAll();
foreach($keys as $key)
{
$column=$table->columns[$key['from']];
$column->isForeignKey=true;
$foreignKeys[$key['from']]=array($key['table'],$key['to']);
}
$table->foreignKeys=$foreignKeys;
}
protected function createColumn($column)
{
$c=new CSqliteColumnSchema;
$c->name=$column['name'];
$c->rawName=$this->quoteColumnName($c->name);
$c->allowNull=!$column['notnull'];
$c->isPrimaryKey=$column['pk']!=0;
$c->isForeignKey=false;
$c->init(strtolower($column['type']),$column['dflt_value']);
return $c;
}
}
class CDbTableSchema extends CComponent
{
public $name;
public $rawName;
public $primaryKey;
public $sequenceName;
public $foreignKeys=array();
public $columns=array();
public function getColumn($name)
{
return isset($this->columns[$name]) ? $this->columns[$name] : null;
}
public function getColumnNames()
{
return array_keys($this->columns);
}
}
class CDbCommand extends CComponent
{
private $_connection;
private $_text='';
private $_statement=null;
public function __construct(CDbConnection $connection,$text)
{
$this->_connection=$connection;
$this->setText($text);
}
public function __sleep()
{
$this->_statement=null;
return array_keys(get_object_vars($this));
}
public function getText()
{
return $this->_text;
}
public function setText($value)
{
$this->_text=$value;
$this->cancel();
}
public function getConnection()
{
return $this->_connection;
}
public function getPdoStatement()
{
return $this->_statement;
}
public function prepare()
{
if($this->_statement==null)
{
try
{
$this->_statement=$this->getConnection()->getPdoInstance()->prepare($this->getText());
}
catch(Exception $e)
{
throw new CDbException(Yii::t('yii','CDbCommand failed to prepare the SQL statement: {error}',
array('{error}'=>$e->getMessage())));
}
}
}
public function cancel()
{
$this->_statement=null;
}
public function bindParam($name, &$value, $dataType=null, $length=null)
{
$this->prepare();
if($dataType===null)
$this->_statement->bindParam($name,$value,$this->_connection->getPdoType(gettype($value)));
else if($length===null)
$this->_statement->bindParam($name,$value,$dataType);
else
$this->_statement->bindParam($name,$value,$dataType,$length);
}
public function bindValue($name, $value, $dataType=null)
{
$this->prepare();
if($dataType===null)
$this->_statement->bindValue($name,$value,$this->_connection->getPdoType(gettype($value)));
else
$this->_statement->bindValue($name,$value,$dataType);
}
public function execute()
{
try
{
if($this->_statement instanceof PDOStatement)
{
$this->_statement->execute();
return $this->_statement->rowCount();
}
else
return $this->getConnection()->getPdoInstance()->exec($this->getText());
}
catch(Exception $e)
{
throw new CDbException(Yii::t('yii','CDbCommand failed to execute the SQL statement: {error}',
array('{error}'=>$e->getMessage())));
}
}
public function query()
{
return $this->queryInternal('',0);
}
public function queryAll($fetchAssociative=true)
{
return $this->queryInternal('fetchAll',$fetchAssociative ? PDO::FETCH_ASSOC : PDO::FETCH_NUM);
}
public function queryRow($fetchAssociative=true)
{
return $this->queryInternal('fetch',$fetchAssociative ? PDO::FETCH_ASSOC : PDO::FETCH_NUM);
}
public function queryScalar()
{
$result=$this->queryInternal('fetchColumn',0);
if(is_resource($result) && get_resource_type($result)==='stream')
return stream_get_contents($result);
else
return $result;
}
public function queryColumn()
{
return $this->queryInternal('fetchAll',PDO::FETCH_COLUMN);
}
private function queryInternal($method,$mode)
{
try
{
if($this->_statement instanceof PDOStatement)
$this->_statement->execute();
else
$this->_statement=$this->getConnection()->getPdoInstance()->query($this->getText());
if($method==='')
return new CDbDataReader($this);
$result=$this->_statement->{$method}($mode);
$this->_statement->closeCursor();
return $result;
}
catch(Exception $e)
{
throw new CDbException(Yii::t('yii','CDbCommand failed to execute the SQL statement: {error}',
array('{error}'=>$e->getMessage())));
}
}
}
class CDbColumnSchema extends CComponent
{
public $name;
public $rawName;
public $allowNull;
public $dbType;
public $type;
public $defaultValue;
public $size;
public $precision;
public $scale;
public $isPrimaryKey;
public $isForeignKey;
public function init($dbType, $defaultValue)
{
$this->dbType=$dbType;
$this->extractType($dbType);
$this->extractLimit($dbType);
if($defaultValue!==null)
$this->extractDefault($defaultValue);
}
protected function extractType($dbType)
{
if(stripos($dbType,'int')!==false)
$this->type='integer';
else if(stripos($dbType,'bool')!==false)
$this->type='boolean';
else if(preg_match('/(real|floa|doub)/i',$dbType))
$this->type='double';
else
$this->type='string';
}
protected function extractLimit($dbType)
{
if(strpos($dbType,'(') && preg_match('/\((.*)\)/',$dbType,$matches))
{
$values=explode(',',$matches[1]);
$this->size=$this->precision=(int)$values[0];
if(isset($values[1]))
$this->scale=(int)$values[1];
}
}
protected function extractDefault($defaultValue)
{
$this->defaultValue=$this->typecast($defaultValue);
}
public function typecast($value)
{
if(gettype($value)===$this->type || $value===null)
return $value;
if($value==='')
return $this->type==='string' ? '' : null;
switch($this->type)
{
case 'integer': return (integer)$value;
case 'boolean': return (boolean)$value;
case 'double': return (double)$value;
case 'string': return (string)$value;
default: return $value;
}
}
}
class CSqliteColumnSchema extends CDbColumnSchema
{
protected function extractDefault($defaultValue)
{
if($this->type==='string') // PHP 5.2.6 adds single quotes while 5.2.0 doesn't
$this->defaultValue=trim($defaultValue,"'\"");
else
$this->defaultValue=$this->typecast($defaultValue);
}
}
class CDbCommandBuilder extends CComponent
{
private $_schema;
private $_connection;
public function __construct($schema)
{
$this->_schema=$schema;
$this->_connection=$schema->getDbConnection();
}
public function getDbConnection()
{
return $this->_connection;
}
public function getSchema()
{
return $this->_schema;
}
public function getLastInsertID($table)
{
if($table->sequenceName!==null)
return $this->_connection->getLastInsertID($table->sequenceName);
else
return null;
}
public function createFindCommand($table,$criteria)
{
$select=is_array($criteria->select) ? implode(', ',$criteria->select) : $criteria->select;
$sql="SELECT {$select} FROM {$table->rawName}";
$sql=$this->applyJoin($sql,$criteria->join);
$sql=$this->applyCondition($sql,$criteria->condition);
$sql=$this->applyGroup($sql,$criteria->group);
$sql=$this->applyHaving($sql,$criteria->having);
$sql=$this->applyOrder($sql,$criteria->order);
$sql=$this->applyLimit($sql,$criteria->limit,$criteria->offset);
$command=$this->_connection->createCommand($sql);
$this->bindValues($command,$criteria->params);
return $command;
}
public function createCountCommand($table,$criteria)
{
$criteria->select='COUNT(*)';
return $this->createFindCommand($table,$criteria);
}
public function createDeleteCommand($table,$criteria)
{
$sql="DELETE FROM {$table->rawName}";
$sql=$this->applyJoin($sql,$criteria->join);
$sql=$this->applyCondition($sql,$criteria->condition);
$sql=$this->applyGroup($sql,$criteria->group);
$sql=$this->applyHaving($sql,$criteria->having);
$sql=$this->applyOrder($sql,$criteria->order);
$sql=$this->applyLimit($sql,$criteria->limit,$criteria->offset);
$command=$this->_connection->createCommand($sql);
$this->bindValues($command,$criteria->params);
return $command;
}
public function createInsertCommand($table,$data)
{
$fields=array();
$values=array();
$placeholders=array();
foreach($data as $name=>$value)
{
if(($column=$table->getColumn($name))!==null && ($value!==null || $column->allowNull))
{
$fields[]=$column->rawName;
$placeholders[]=':'.$name;
$values[':'.$name]=$column->typecast($value);
}
}
$sql="INSERT INTO {$table->rawName} (".implode(', ',$fields).') VALUES ('.implode(', ',$placeholders).')';
$command=$this->_connection->createCommand($sql);
foreach($values as $name=>$value)
$command->bindValue($name,$value);
return $command;
}
public function createUpdateCommand($table,$data,$criteria)
{
$fields=array();
$values=array();
$bindByPosition=isset($criteria->params[0]);
foreach($data as $name=>$value)
{
if(($column=$table->getColumn($name))!==null)
{
if($bindByPosition)
{
$fields[]=$column->rawName.'=?';
$values[]=$column->typecast($value);
}
else
{
$fields[]=$column->rawName.'=:'.$name;
$values[':'.$name]=$column->typecast($value);
}
}
}
if($fields===array())
throw new CDbException(Yii::t('yii','No columns are being updated for table "{table}".',
array('{table}'=>$table->name)));
$sql="UPDATE {$table->rawName} SET ".implode(', ',$fields);
$sql=$this->applyJoin($sql,$criteria->join);
$sql=$this->applyCondition($sql,$criteria->condition);
$sql=$this->applyOrder($sql,$criteria->order);
$sql=$this->applyLimit($sql,$criteria->limit,$criteria->offset);
$command=$this->_connection->createCommand($sql);
$this->bindValues($command,array_merge($values,$criteria->params));
return $command;
}
public function createUpdateCounterCommand($table,$counters,$criteria)
{
$fields=array();
foreach($counters as $name=>$value)
{
if(($column=$table->getColumn($name))!==null)
{
$value=(int)$value;
if($value<0)
$fields[]="{$column->rawName}={$column->rawName}-".(-$value);
else
$fields[]="{$column->rawName}={$column->rawName}+".$value;
}
}
if($fields!==array())
{
$sql="UPDATE {$table->rawName} SET ".implode(', ',$fields);
$sql=$this->applyJoin($sql,$criteria->join);
$sql=$this->applyCondition($sql,$criteria->condition);
$sql=$this->applyOrder($sql,$criteria->order);
$sql=$this->applyLimit($sql,$criteria->limit,$criteria->offset);
$command=$this->_connection->createCommand($sql);
$this->bindValues($command,$criteria->params);
return $command;
}
else
throw new CDbException(Yii::t('yii','No counter columns are being updated for table "{table}".',
array('{table}'=>$table->name)));
}
public function createSqlCommand($sql,$params=array())
{
$command=$this->_connection->createCommand($sql);
$this->bindValues($command,$params);
return $command;
}
public function applyJoin($sql,$join)
{
if($join!=='')
return $sql.' '.$join;
else
return $sql;
}
public function applyCondition($sql,$condition)
{
if($condition!=='')
return $sql.' WHERE '.$condition;
else
return $sql;
}
public function applyOrder($sql,$orderBy)
{
if($orderBy!=='')
return $sql.' ORDER BY '.$orderBy;
else
return $sql;
}
public function applyLimit($sql,$limit,$offset)
{
if($limit>=0)
$sql.=' LIMIT '.(int)$limit;
if($offset>0)
$sql.=' OFFSET '.(int)$offset;
return $sql;
}
public function applyGroup($sql,$group)
{
if($group!=='')
return $sql.' GROUP BY '.$group;
else
return $sql;
}
public function applyHaving($sql,$having)
{
if($having!=='')
return $sql.' HAVING '.$having;
else
return $sql;
}
public function bindValues($command, $values)
{
if(($n=count($values))===0)
return;
if(isset($values[0])) // question mark placeholders
{
for($i=0;$i<$n;++$i)
$command->bindValue($i+1,$values[$i]);
}
else // named placeholders
{
foreach($values as $name=>$value)
{
if($name[0]!==':')
$name=':'.$name;
$command->bindValue($name,$value);
}
}
}
public function createCriteria($condition='',$params=array())
{
if(is_array($condition))
$criteria=new CDbCriteria($condition);
else if($condition instanceof CDbCriteria)
$criteria=clone $condition;
else
{
$criteria=new CDbCriteria;
$criteria->condition=$condition;
$criteria->params=$params;
}
return $criteria;
}
public function createPkCriteria($table,$pk,$condition='',$params=array())
{
$criteria=$this->createCriteria($condition,$params);
if(!is_array($pk)) // single key
$pk=array($pk);
if(is_array($table->primaryKey) && !isset($pk[0]) && $pk!==array()) // single composite key
$pk=array($pk);
$condition=$this->createPkCondition($table,$pk);
if($criteria->condition!=='')
$criteria->condition=$condition.' AND ('.$criteria->condition.')';
else
$criteria->condition=$condition;
return $criteria;
}
public function createPkCondition($table,$values,$prefix=null)
{
if(($n=count($values))<1)
return '0=1';
if($prefix===null)
$prefix=$table->rawName.'.';
if(is_string($table->primaryKey))
{
// simple key: $values=array(pk1,pk2,...)
$column=$table->columns[$table->primaryKey];
foreach($values as &$value)
{
$value=$column->typecast($value);
if(is_string($value))
$value=$this->_connection->quoteValue($value);
}
if($n===1)
return $prefix.$column->rawName.'='.$values[0];
else
return $prefix.$column->rawName.' IN ('.implode(', ',$values).')';
}
else if(is_array($table->primaryKey))
{
// composite key: $values=array(array('pk1'=>'v1','pk2'=>'v2'),array(...))
foreach($table->primaryKey as $name)
{
$column=$table->columns[$name];
for($i=0;$i<$n;++$i)
{
if(isset($values[$i][$name]))
{
$value=$column->typecast($values[$i][$name]);
if(is_string($value))
$values[$i][$name]=$this->_connection->quoteValue($value);
else
$values[$i][$name]=$value;
}
else
throw new CDbException(Yii::t('yii','The value for the primary key "{key}" is not supplied when querying the table "{table}".',
array('{table}'=>$table->name,'{key}'=>$name)));
}
}
if(count($values)===1)
{
$entries=array();
foreach($values[0] as $name=>$value)
$entries[]=$prefix.$table->columns[$name]->rawName.'='.$value;
return implode(' AND ',$entries);
}
else
return $this->createCompositePkCondition($table,$values,$prefix);
}
else
throw new CDbException(Yii::t('yii','Table "{table}" does not have a primary key defined.',
array('{table}'=>$table->name)));
}
protected function createCompositePkCondition($table,$values,$prefix)
{
if($prefix===null)
$prefix=$table->rawName.'.';
$keyNames=array();
foreach(array_keys($values[0]) as $name)
$keyNames[]=$prefix.$table->columns[$name]->rawName;
$vs=array();
foreach($values as $value)
$vs[]='('.implode(', ',$value).')';
return '('.implode(', ',$keyNames).') IN ('.implode(', ',$vs).')';
}
public function createColumnCriteria($table,$columns,$condition='',$params=array())
{
$criteria=$this->createCriteria($condition,$params);
$bindByPosition=isset($criteria->params[0]);
$conditions=array();
$values=array();
foreach($columns as $name=>$value)
{
if(($column=$table->getColumn($name))!==null)
{
if($value!==null)
{
if($bindByPosition)
{
$conditions[]=$table->rawName.'.'.$column->rawName.'=?';
$values[]=$value;
}
else
{
$conditions[]=$table->rawName.'.'.$column->rawName.'=:'.$name;
$values[':'.$name]=$value;
}
}
else
$conditions[]=$table->rawName.'.'.$column->rawName.' IS NULL';
}
else
throw new CDbException(Yii::t('yii','Table "{table}" does not have a column named "{column}".',
array('{table}'=>$table->name,'{column}'=>$name)));
}
$criteria->params=array_merge($values,$criteria->params);
if(isset($conditions[0]))
{
if($criteria->condition!=='')
$criteria->condition=implode(' AND ',$conditions).' AND ('.$criteria->condition.')';
else
$criteria->condition=implode(' AND ',$conditions);
}
return $criteria;
}
public function createSearchCondition($table,$columns,$keywords,$prefix=null)
{
if(!is_array($keywords))
$keywords=preg_split('/\s+/u',$keywords,-1,PREG_SPLIT_NO_EMPTY);
if(empty($keywords))
return '';
if($prefix===null)
$prefix=$table->rawName.'.';
$conditions=array();
foreach($columns as $name)
{
if(($column=$table->getColumn($name))===null)
throw new CDbException(Yii::t('yii','Table "{table}" does not have a column named "{column}".',
array('{table}'=>$table->name,'{column}'=>$name)));
$condition=array();
foreach($keywords as $keyword)
$condition[]=$prefix.$column->rawName.' LIKE '.$this->_connection->quoteValue('%'.$keyword.'%');
$conditions[]=implode(' AND ',$condition);
}
return '('.implode(' OR ',$conditions).')';
}
}
class CSqliteCommandBuilder extends CDbCommandBuilder
{
protected function createCompositePkCondition($table,$values,$prefix)
{
$keyNames=array();
foreach(array_keys($values[0]) as $name)
$keyNames[]=$prefix.$table->columns[$name]->rawName;
$vs=array();
foreach($values as $value)
$vs[]=implode("||','||",$value);
return implode("||','||",$keyNames).' IN ('.implode(', ',$vs).')';
}
}
class CDbCriteria
{
public $select='*';
public $condition='';
public $params=array();
public $limit=-1;
public $offset=-1;
public $order='';
public $group='';
public $join='';
public $having='';
public function __construct($data=array())
{
foreach($data as $name=>$value)
$this->$name=$value;
}
}
class CPagination extends CComponent
{
const DEFAULT_PAGE_SIZE=10;
public $pageVar='page';
public $route='';
private $_pageSize=self::DEFAULT_PAGE_SIZE;
private $_itemCount=0;
private $_currentPage;
public function getPageSize()
{
return $this->_pageSize;
}
public function setPageSize($value)
{
if(($this->_pageSize=$value)<=0)
$this->_pageSize=self::DEFAULT_PAGE_SIZE;
}
public function getItemCount()
{
return $this->_itemCount;
}
public function setItemCount($value)
{
if(($this->_itemCount=$value)<0)
$this->_itemCount=0;
}
public function getPageCount()
{
return (int)(($this->_itemCount+$this->_pageSize-1)/$this->_pageSize);
}
public function getCurrentPage($recalculate=true)
{
if($this->_currentPage===null || $recalculate)
{
if(isset($_GET[$this->pageVar]))
{
$this->_currentPage=(int)$_GET[$this->pageVar]-1;
$pageCount=$this->getPageCount();
if($this->_currentPage>=$pageCount)
$this->_currentPage=$pageCount-1;
if($this->_currentPage<0)
$this->_currentPage=0;
}
else
$this->_currentPage=0;
}
return $this->_currentPage;
}
public function setCurrentPage($value)
{
$this->_currentPage=$value;
}
public function createPageUrl($controller,$page)
{
$params=($this->route==='')?$_GET:array();
if($page>0) // page 0 is the default
$params[$this->pageVar]=$page+1;
else
unset($params[$this->pageVar]);
return $controller->createUrl($this->route,$params);
}
}
class CJavaScript
{
public static function quote($js,$forUrl=false)
{
if($forUrl)
return strtr($js,array('%'=>'%25',"\t"=>'\t',"\n"=>'\n',"\r"=>'\r','"'=>'\"','\''=>'\\\'','\\'=>'\\\\'));
else
return strtr($js,array("\t"=>'\t',"\n"=>'\n',"\r"=>'\r','"'=>'\"','\''=>'\\\'','\\'=>'\\\\'));
}
public static function encode($value)
{
if(is_string($value))
{
if(strpos($value,'js:')===0)
return substr($value,3);
else
return "'".self::quote($value)."'";
}
else if($value===null)
return 'null';
else if(is_bool($value))
return $value?'true':'false';
else if(is_integer($value))
return "$value";
else if(is_float($value))
{
if($value===-INF)
return 'Number.NEGATIVE_INFINITY';
else if($value===INF)
return 'Number.POSITIVE_INFINITY';
else
return "$value";
}
else if(is_object($value))
return self::encode(get_object_vars($value));
else if(is_array($value))
{
$es=array();
if(($n=count($value))>0 && array_keys($value)!==range(0,$n-1))
{
foreach($value as $k=>$v)
$es[]="'".self::quote($k)."':".self::encode($v);
return '{'.implode(',',$es).'}';
}
else
{
foreach($value as $v)
$es[]=self::encode($v);
return '['.implode(',',$es).']';
}
}
else
return '';
}
public static function jsonEncode($data)
{
if(function_exists('json_encode'))
return json_encode($data);
else
{
return CJSON::encode($data);
}
}
public static function jsonDecode($data,$useArray=true)
{
if(function_exists('json_decode'))
return json_decode($data,$useArray);
else
return CJSON::decode($data,$useArray);
}
}
class CAssetManager extends CApplicationComponent
{
const DEFAULT_BASEPATH='assets';
private $_basePath;
private $_baseUrl;
private $_published=array();
public function init()
{
parent::init();
$request=Yii::app()->getRequest();
if($this->getBasePath()===null)
$this->setBasePath(dirname($request->getScriptFile()).DIRECTORY_SEPARATOR.self::DEFAULT_BASEPATH);
if($this->getBaseUrl()===null)
$this->setBaseUrl($request->getBaseUrl().'/'.self::DEFAULT_BASEPATH);
}
public function getBasePath()
{
return $this->_basePath;
}
public function setBasePath($value)
{
if(($basePath=realpath($value))!==false && is_dir($basePath) && is_writable($basePath))
$this->_basePath=$basePath;
else
throw new CException(Yii::t('yii','CAssetManager.basePath "{path}" is invalid. Please make sure the directory exists and is writable by the Web server process.',
array('{path}'=>$value)));
}
public function getBaseUrl()
{
return $this->_baseUrl;
}
public function setBaseUrl($value)
{
$this->_baseUrl=rtrim($value,'/');
}
public function publish($path,$hashByName=false,$level=-1)
{
if(isset($this->_published[$path]))
return $this->_published[$path];
else if(($src=realpath($path))!==false)
{
if(is_file($src))
{
$dir=$this->hash($hashByName ? basename($src) : dirname($src));
$fileName=basename($src);
$dstDir=$this->getBasePath().DIRECTORY_SEPARATOR.$dir;
$dstFile=$dstDir.DIRECTORY_SEPARATOR.$fileName;
if(@filemtime($dstFile)<@filemtime($src))
{
if(!is_dir($dstDir))
{
mkdir($dstDir);
@chmod($dstDir,0777);
}
copy($src,$dstFile);
}
return $this->_published[$path]=$this->getBaseUrl()."/$dir/$fileName";
}
else
{
$dir=$this->hash($hashByName ? basename($src) : $src);
$dstDir=$this->getBasePath().DIRECTORY_SEPARATOR.$dir;
if(!is_dir($dstDir))
CFileHelper::copyDirectory($src,$dstDir,array('exclude'=>array('.svn'),'level'=>$level));
return $this->_published[$path]=$this->getBaseUrl().'/'.$dir;
}
}
else
throw new CException(Yii::t('yii','The asset "{asset}" to be pulished does not exist.',
array('{asset}'=>$path)));
}
public function getPublishedPath($path,$hashByName=false)
{
if(($path=realpath($path))!==false)
{
$base=$this->getBasePath().DIRECTORY_SEPARATOR;
if(is_file($path))
return $base . $this->hash($hashByName ? basename($path) : dirname($path)) . DIRECTORY_SEPARATOR . basename($path);
else
return $base . $this->hash($hashByName ? basename($path) : $path);
}
else
return false;
}
public function getPublishedUrl($path,$hashByName=false)
{
if(isset($this->_published[$path]))
return $this->_published[$path];
if(($path=realpath($path))!==false)
{
if(is_file($path))
return $this->getBaseUrl().'/'.$this->hash($hashByName ? basename($path) : dirname($path)).'/'.basename($path);
else
return $this->getBaseUrl().'/'.$this->hash($hashByName ? basename($path) : $path);
}
else
return false;
}
protected function hash($path)
{
return sprintf('%x',crc32($path.Yii::getVersion()));
}
}
class CFileHelper
{
public static function copyDirectory($src,$dst,$options=array())
{
$fileTypes=array();
$exclude=array();
$level=-1;
extract($options);
self::copyDirectoryRecursive($src,$dst,'',$fileTypes,$exclude,$level);
}
public static function findFiles($dir,$options=array())
{
$fileTypes=array();
$exclude=array();
$level=-1;
extract($options);
$list=self::findFilesRecursive($dir,'',$fileTypes,$exclude,$level);
sort($list);
return $list;
}
protected static function copyDirectoryRecursive($src,$dst,$base,$fileTypes,$exclude,$level)
{
@mkdir($dst);
@chmod($dst,0777);
$folder=opendir($src);
while($file=readdir($folder))
{
if($file==='.' || $file==='..')
continue;
$path=$src.DIRECTORY_SEPARATOR.$file;
$isFile=is_file($path);
if(self::validatePath($base,$file,$isFile,$fileTypes,$exclude))
{
if($isFile)
copy($path,$dst.DIRECTORY_SEPARATOR.$file);
else if($level)
self::copyDirectoryRecursive($path,$dst.DIRECTORY_SEPARATOR.$file,$base.'/'.$file,$fileTypes,$exclude,$level-1);
}
}
closedir($folder);
}
protected static function findFilesRecursive($dir,$base,$fileTypes,$exclude,$level)
{
$list=array();
$handle=opendir($dir);
while($file=readdir($handle))
{
if($file==='.' || $file==='..')
continue;
$path=$dir.DIRECTORY_SEPARATOR.$file;
$isFile=is_file($path);
if(self::validatePath($base,$file,$isFile,$fileTypes,$exclude))
{
if($isFile)
$list[]=$path;
else if($level)
$list=array_merge($list,self::findFilesRecursive($path,$base.'/'.$file,$fileTypes,$exclude,$level-1));
}
}
closedir($handle);
return $list;
}
protected static function validatePath($base,$file,$isFile,$fileTypes,$exclude)
{
foreach($exclude as $e)
{
if($file===$e || strpos($base.'/'.$file,$e)===0)
return false;
}
if(!$isFile || empty($fileTypes))
return true;
if(($pos=strrpos($file,'.'))!==false)
{
$type=substr($file,$pos+1);
return in_array($type,$fileTypes);
}
else
return false;
}
public static function getMimeType($file)
{
if(function_exists('finfo_open'))
{
if($info=finfo_open(FILEINFO_MIME))
return finfo_file($info,$file);
else
return null;
}
if(function_exists('mime_content_type'))
return mime_content_type($file);
return self::getMimeTypeByExtension($file);
}
public static function getMimeTypeByExtension($file)
{
static $extensions;
if($extensions===null)
$extensions=require(Yii::getPathOfAlias('system.utils.mimeTypes').'.php');
if(($pos=strrpos($file,'.'))!==false)
{
$ext=strtolower(substr($file,$pos+1));
if(isset($extensions[$ext]))
return $extensions[$ext];
}
return null;
}
}
interface IApplicationComponent
{
public function init();
public function getIsInitialized();
}
interface ICache
{
public function get($id);
public function set($id,$value,$expire=0,$dependency=null);
public function add($id,$value,$expire=0,$dependency=null);
public function delete($id);
public function flush();
}
interface ICacheDependency
{
public function evaluateDependency();
public function getHasChanged();
}
interface IStatePersister
{
public function load();
public function save($state);
}
interface IFilter
{
public function filter($filterChain);
}
interface IAction
{
public function run();
public function getId();
public function getController();
}
interface IWebServiceProvider
{
public function beforeWebMethod($service);
public function afterWebMethod($service);
}
interface IViewRenderer
{
public function renderFile($context,$file,$data,$return);
}
interface IUserIdentity
{
public function authenticate();
public function getIsAuthenticated();
public function getId();
public function getName();
public function getPersistentStates();
}
interface IWebUser
{
public function getId();
public function getName();
public function getIsGuest();
public function checkAccess($operation,$params=array());
}
interface IAuthManager
{
public function checkAccess($itemName,$userId,$params=array());
public function createAuthItem($name,$type,$description='',$bizRule=null,$data=null);
public function removeAuthItem($name);
public function getAuthItems($type=null,$userId=null);
public function getAuthItem($name);
public function saveAuthItem($item,$oldName=null);
public function addItemChild($itemName,$childName);
public function removeItemChild($itemName,$childName);
public function hasItemChild($itemName,$childName);
public function getItemChildren($itemName);
public function assign($itemName,$userId,$bizRule=null,$data=null);
public function revoke($itemName,$userId);
public function isAssigned($itemName,$userId);
public function getAuthAssignment($itemName,$userId);
public function getAuthAssignments($userId);
public function saveAuthAssignment($assignment);
public function clearAll();
public function clearAuthAssignments();
public function save();
public function executeBizRule($bizRule,$params,$data);
}
?>