* @link http://www.yiiframework.com/
* @copyright 2008-2013 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_TRACE_LEVEL' ) or define ( 'YII_TRACE_LEVEL', 0 );
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__ ) );
defined ( 'YII_ZII_PATH' ) or define ( 'YII_ZII_PATH', YII_PATH . DIRECTORY_SEPARATOR . 'zii' );
class YiiBase {
public static $classMap = array ();
public static $enableIncludePath = true;
private static $_aliases = array (
'system' => YII_PATH,
'zii' => YII_ZII_PATH
); // alias => path
private static $_imports = array (); // alias => class name or directory
private static $_includePaths; // list of include paths
private static $_app;
private static $_logger;
public static function getVersion() {
return '1.1.14';
}
public static function createWebApplication($config = null) {
return self::createApplication ( 'CWebApplication', $config );
}
public static function createConsoleApplication($config = null) {
return self::createApplication ( 'CConsoleApplication', $config );
}
public static function createApplication($class, $config = null) {
return new $class ( $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 ();
} elseif (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 ();
if ($n === 2)
$object = new $type ( $args [1] );
elseif ($n === 3)
$object = new $type ( $args [1], $args [2] );
elseif ($n === 4)
$object = new $type ( $args [1], $args [2], $args [3] );
else {
unset ( $args [0] );
$class = new ReflectionClass ( $type );
// Note: ReflectionClass::newInstanceArgs() is available for PHP 5.1.3+
// $object=$class->newInstanceArgs($args);
$object = call_user_func_array ( array (
$class,
'newInstance'
), $args );
}
} 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 ) || interface_exists ( $alias, false ))
return self::$_imports [$alias] = $alias;
if (($pos = strrpos ( $alias, '\\' )) !== false) // a class name in PHP 5.3 namespace format
{
$namespace = str_replace ( '\\', '.', ltrim ( substr ( $alias, 0, $pos ), '\\' ) );
if (($path = self::getPathOfAlias ( $namespace )) !== false) {
$classFile = $path . DIRECTORY_SEPARATOR . substr ( $alias, $pos + 1 ) . '.php';
if ($forceInclude) {
if (is_file ( $classFile ))
require ($classFile);
else
throw new CException ( Yii::t ( 'yii', 'Alias "{alias}" is invalid. Make sure it points to an existing PHP file and the file is readable.', array (
'{alias}' => $alias
) ) );
self::$_imports [$alias] = $alias;
} else
self::$classMap [$alias] = $classFile;
return $alias;
} else {
// try to autoload the class with an autoloader
if (class_exists ( $alias, true ))
return self::$_imports [$alias] = $alias;
else
throw new CException ( Yii::t ( 'yii', 'Alias "{alias}" is invalid. Make sure it points to an existing directory or file.', array (
'{alias}' => $namespace
) ) );
}
}
if (($pos = strrpos ( $alias, '.' )) === false) // a simple class name
{
if ($forceInclude && self::autoload ( $alias ))
self::$_imports [$alias] = $alias;
return $alias;
}
$className = ( string ) substr ( $alias, $pos + 1 );
$isClass = $className !== '*';
if ($isClass && (class_exists ( $className, false ) || interface_exists ( $className, false )))
return self::$_imports [$alias] = $className;
if (($path = self::getPathOfAlias ( $alias )) !== false) {
if ($isClass) {
if ($forceInclude) {
if (is_file ( $path . '.php' ))
require ($path . '.php');
else
throw new CException ( Yii::t ( 'yii', 'Alias "{alias}" is invalid. Make sure it points to an existing PHP file and the file is readable.', array (
'{alias}' => $alias
) ) );
self::$_imports [$alias] = $className;
} else
self::$classMap [$className] = $path . '.php';
return $className;
} else // a directory
{
if (self::$_includePaths === null) {
self::$_includePaths = array_unique ( explode ( PATH_SEPARATOR, get_include_path () ) );
if (($pos = array_search ( '.', self::$_includePaths, true )) !== false)
unset ( self::$_includePaths [$pos] );
}
array_unshift ( self::$_includePaths, $path );
if (self::$enableIncludePath && set_include_path ( '.' . PATH_SEPARATOR . implode ( PATH_SEPARATOR, self::$_includePaths ) ) === false)
self::$enableIncludePath = false;
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];
elseif (($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 );
elseif (self::$_app instanceof CWebApplication) {
if (self::$_app->findModule ( $rootAlias ) !== null)
return self::getPathOfAlias ( $alias );
}
}
return false;
}
public static function setPathOfAlias($alias, $path) {
if (empty ( $path ))
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::$classMap [$className] ))
include (self::$classMap [$className]);
elseif (isset ( self::$_coreClasses [$className] ))
include (YII_PATH . self::$_coreClasses [$className]);
else {
// include class file relying on include_path
if (strpos ( $className, '\\' ) === false) // class without namespace
{
if (self::$enableIncludePath === false) {
foreach ( self::$_includePaths as $path ) {
$classFile = $path . DIRECTORY_SEPARATOR . $className . '.php';
if (is_file ( $classFile )) {
include ($classFile);
if (YII_DEBUG && basename ( realpath ( $classFile ) ) !== $className . '.php')
throw new CException ( Yii::t ( 'yii', 'Class name "{class}" does not match class file "{file}".', array (
'{class}' => $className,
'{file}' => $classFile
) ) );
break;
}
}
} else
include ($className . '.php');
} else // class name with namespace in PHP 5.3
{
$namespace = str_replace ( '\\', '.', ltrim ( $className, '\\' ) );
if (($path = self::getPathOfAlias ( $namespace )) !== false)
include ($path . '.php');
else
return false;
}
return class_exists ( $className, false ) || interface_exists ( $className, false );
}
return true;
}
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 ();
if (YII_DEBUG && YII_TRACE_LEVEL > 0 && $level !== CLogger::LEVEL_PROFILE) {
$traces = debug_backtrace ();
$count = 0;
foreach ( $traces as $trace ) {
if (isset ( $trace ['file'], $trace ['line'] ) && strpos ( $trace ['file'], YII_PATH ) !== 0) {
$msg .= "\nin " . $trace ['file'] . ' (' . $trace ['line'] . ')';
if (++ $count >= YII_TRACE_LEVEL)
break;
}
}
}
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 setLogger($logger) {
self::$_logger = $logger;
}
public static function powered() {
return Yii::t ( 'yii', 'Powered by {yii}.', array (
'{yii}' => 'Yii Framework'
) );
}
public static function t($category, $message, $params = array(), $source = null, $language = null) {
if (self::$_app !== null) {
if ($source === null)
$source = ($category === 'yii' || $category === 'zii') ? 'coreMessages' : 'messages';
if (($source = self::$_app->getComponent ( $source )) !== null)
$message = $source->translate ( $category, $message, $language );
}
if ($params === array ())
return $message;
if (! is_array ( $params ))
$params = array (
$params
);
if (isset ( $params [0] )) // number choice
{
if (strpos ( $message, '|' ) !== false) {
if (strpos ( $message, '#' ) === false) {
$chunks = explode ( '|', $message );
$expressions = self::$_app->getLocale ( $language )->getPluralRules ();
if ($n = min ( count ( $chunks ), count ( $expressions ) )) {
for($i = 0; $i < $n; $i ++)
$chunks [$i] = $expressions [$i] . '#' . $chunks [$i];
$message = implode ( '|', $chunks );
}
}
$message = CChoiceFormat::format ( $message, $params [0] );
}
if (! isset ( $params ['{n}'] ))
$params ['{n}'] = $params [0];
unset ( $params [0] );
}
return $params !== array () ? strtr ( $message, $params ) : $message;
}
public static function registerAutoloader($callback, $append = false) {
if ($append) {
self::$enableIncludePath = false;
spl_autoload_register ( $callback );
} else {
spl_autoload_unregister ( array (
'YiiBase',
'autoload'
) );
spl_autoload_register ( $callback );
spl_autoload_register ( array (
'YiiBase',
'autoload'
) );
}
}
private static $_coreClasses = array (
'CApplication' => '/base/CApplication.php',
'CApplicationComponent' => '/base/CApplicationComponent.php',
'CBehavior' => '/base/CBehavior.php',
'CComponent' => '/base/CComponent.php',
'CErrorEvent' => '/base/CErrorEvent.php',
'CErrorHandler' => '/base/CErrorHandler.php',
'CException' => '/base/CException.php',
'CExceptionEvent' => '/base/CExceptionEvent.php',
'CHttpException' => '/base/CHttpException.php',
'CModel' => '/base/CModel.php',
'CModelBehavior' => '/base/CModelBehavior.php',
'CModelEvent' => '/base/CModelEvent.php',
'CModule' => '/base/CModule.php',
'CSecurityManager' => '/base/CSecurityManager.php',
'CStatePersister' => '/base/CStatePersister.php',
'CApcCache' => '/caching/CApcCache.php',
'CCache' => '/caching/CCache.php',
'CDbCache' => '/caching/CDbCache.php',
'CDummyCache' => '/caching/CDummyCache.php',
'CEAcceleratorCache' => '/caching/CEAcceleratorCache.php',
'CFileCache' => '/caching/CFileCache.php',
'CMemCache' => '/caching/CMemCache.php',
'CRedisCache' => '/caching/CRedisCache.php',
'CWinCache' => '/caching/CWinCache.php',
'CXCache' => '/caching/CXCache.php',
'CZendDataCache' => '/caching/CZendDataCache.php',
'CCacheDependency' => '/caching/dependencies/CCacheDependency.php',
'CChainedCacheDependency' => '/caching/dependencies/CChainedCacheDependency.php',
'CDbCacheDependency' => '/caching/dependencies/CDbCacheDependency.php',
'CDirectoryCacheDependency' => '/caching/dependencies/CDirectoryCacheDependency.php',
'CExpressionDependency' => '/caching/dependencies/CExpressionDependency.php',
'CFileCacheDependency' => '/caching/dependencies/CFileCacheDependency.php',
'CGlobalStateCacheDependency' => '/caching/dependencies/CGlobalStateCacheDependency.php',
'CAttributeCollection' => '/collections/CAttributeCollection.php',
'CConfiguration' => '/collections/CConfiguration.php',
'CList' => '/collections/CList.php',
'CListIterator' => '/collections/CListIterator.php',
'CMap' => '/collections/CMap.php',
'CMapIterator' => '/collections/CMapIterator.php',
'CQueue' => '/collections/CQueue.php',
'CQueueIterator' => '/collections/CQueueIterator.php',
'CStack' => '/collections/CStack.php',
'CStackIterator' => '/collections/CStackIterator.php',
'CTypedList' => '/collections/CTypedList.php',
'CTypedMap' => '/collections/CTypedMap.php',
'CConsoleApplication' => '/console/CConsoleApplication.php',
'CConsoleCommand' => '/console/CConsoleCommand.php',
'CConsoleCommandBehavior' => '/console/CConsoleCommandBehavior.php',
'CConsoleCommandEvent' => '/console/CConsoleCommandEvent.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',
'CDbMigration' => '/db/CDbMigration.php',
'CDbTransaction' => '/db/CDbTransaction.php',
'CActiveFinder' => '/db/ar/CActiveFinder.php',
'CActiveRecord' => '/db/ar/CActiveRecord.php',
'CActiveRecordBehavior' => '/db/ar/CActiveRecordBehavior.php',
'CDbColumnSchema' => '/db/schema/CDbColumnSchema.php',
'CDbCommandBuilder' => '/db/schema/CDbCommandBuilder.php',
'CDbCriteria' => '/db/schema/CDbCriteria.php',
'CDbExpression' => '/db/schema/CDbExpression.php',
'CDbSchema' => '/db/schema/CDbSchema.php',
'CDbTableSchema' => '/db/schema/CDbTableSchema.php',
'CMssqlColumnSchema' => '/db/schema/mssql/CMssqlColumnSchema.php',
'CMssqlCommandBuilder' => '/db/schema/mssql/CMssqlCommandBuilder.php',
'CMssqlPdoAdapter' => '/db/schema/mssql/CMssqlPdoAdapter.php',
'CMssqlSchema' => '/db/schema/mssql/CMssqlSchema.php',
'CMssqlSqlsrvPdoAdapter' => '/db/schema/mssql/CMssqlSqlsrvPdoAdapter.php',
'CMssqlTableSchema' => '/db/schema/mssql/CMssqlTableSchema.php',
'CMysqlColumnSchema' => '/db/schema/mysql/CMysqlColumnSchema.php',
'CMysqlCommandBuilder' => '/db/schema/mysql/CMysqlCommandBuilder.php',
'CMysqlSchema' => '/db/schema/mysql/CMysqlSchema.php',
'CMysqlTableSchema' => '/db/schema/mysql/CMysqlTableSchema.php',
'COciColumnSchema' => '/db/schema/oci/COciColumnSchema.php',
'COciCommandBuilder' => '/db/schema/oci/COciCommandBuilder.php',
'COciSchema' => '/db/schema/oci/COciSchema.php',
'COciTableSchema' => '/db/schema/oci/COciTableSchema.php',
'CPgsqlColumnSchema' => '/db/schema/pgsql/CPgsqlColumnSchema.php',
'CPgsqlCommandBuilder' => '/db/schema/pgsql/CPgsqlCommandBuilder.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',
'CChoiceFormat' => '/i18n/CChoiceFormat.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',
'CChainedLogFilter' => '/logging/CChainedLogFilter.php',
'CDbLogRoute' => '/logging/CDbLogRoute.php',
'CEmailLogRoute' => '/logging/CEmailLogRoute.php',
'CFileLogRoute' => '/logging/CFileLogRoute.php',
'CLogFilter' => '/logging/CLogFilter.php',
'CLogRoute' => '/logging/CLogRoute.php',
'CLogRouter' => '/logging/CLogRouter.php',
'CLogger' => '/logging/CLogger.php',
'CProfileLogRoute' => '/logging/CProfileLogRoute.php',
'CWebLogRoute' => '/logging/CWebLogRoute.php',
'CDateTimeParser' => '/utils/CDateTimeParser.php',
'CFileHelper' => '/utils/CFileHelper.php',
'CFormatter' => '/utils/CFormatter.php',
'CLocalizedFormatter' => '/utils/CLocalizedFormatter.php',
'CMarkdownParser' => '/utils/CMarkdownParser.php',
'CPasswordHelper' => '/utils/CPasswordHelper.php',
'CPropertyValue' => '/utils/CPropertyValue.php',
'CTimestamp' => '/utils/CTimestamp.php',
'CVarDumper' => '/utils/CVarDumper.php',
'CBooleanValidator' => '/validators/CBooleanValidator.php',
'CCaptchaValidator' => '/validators/CCaptchaValidator.php',
'CCompareValidator' => '/validators/CCompareValidator.php',
'CDateValidator' => '/validators/CDateValidator.php',
'CDefaultValueValidator' => '/validators/CDefaultValueValidator.php',
'CEmailValidator' => '/validators/CEmailValidator.php',
'CExistValidator' => '/validators/CExistValidator.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',
'CSafeValidator' => '/validators/CSafeValidator.php',
'CStringValidator' => '/validators/CStringValidator.php',
'CTypeValidator' => '/validators/CTypeValidator.php',
'CUniqueValidator' => '/validators/CUniqueValidator.php',
'CUnsafeValidator' => '/validators/CUnsafeValidator.php',
'CUrlValidator' => '/validators/CUrlValidator.php',
'CValidator' => '/validators/CValidator.php',
'CActiveDataProvider' => '/web/CActiveDataProvider.php',
'CArrayDataProvider' => '/web/CArrayDataProvider.php',
'CAssetManager' => '/web/CAssetManager.php',
'CBaseController' => '/web/CBaseController.php',
'CCacheHttpSession' => '/web/CCacheHttpSession.php',
'CClientScript' => '/web/CClientScript.php',
'CController' => '/web/CController.php',
'CDataProvider' => '/web/CDataProvider.php',
'CDataProviderIterator' => '/web/CDataProviderIterator.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',
'CHttpSessionIterator' => '/web/CHttpSessionIterator.php',
'COutputEvent' => '/web/COutputEvent.php',
'CPagination' => '/web/CPagination.php',
'CSort' => '/web/CSort.php',
'CSqlDataProvider' => '/web/CSqlDataProvider.php',
'CTheme' => '/web/CTheme.php',
'CThemeManager' => '/web/CThemeManager.php',
'CUploadedFile' => '/web/CUploadedFile.php',
'CUrlManager' => '/web/CUrlManager.php',
'CWebApplication' => '/web/CWebApplication.php',
'CWebModule' => '/web/CWebModule.php',
'CWidgetFactory' => '/web/CWidgetFactory.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',
'CHttpCacheFilter' => '/web/filters/CHttpCacheFilter.php',
'CInlineFilter' => '/web/filters/CInlineFilter.php',
'CForm' => '/web/form/CForm.php',
'CFormButtonElement' => '/web/form/CFormButtonElement.php',
'CFormElement' => '/web/form/CFormElement.php',
'CFormElementCollection' => '/web/form/CFormElementCollection.php',
'CFormInputElement' => '/web/form/CFormInputElement.php',
'CFormStringElement' => '/web/form/CFormStringElement.php',
'CGoogleApi' => '/web/helpers/CGoogleApi.php',
'CHtml' => '/web/helpers/CHtml.php',
'CJSON' => '/web/helpers/CJSON.php',
'CJavaScript' => '/web/helpers/CJavaScript.php',
'CJavaScriptExpression' => '/web/helpers/CJavaScriptExpression.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',
'CActiveForm' => '/web/widgets/CActiveForm.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;
private $_m;
public function __get($name) {
$getter = 'get' . $name;
if (method_exists ( $this, $getter ))
return $this->$getter ();
elseif (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];
} elseif (isset ( $this->_m [$name] ))
return $this->_m [$name];
elseif (is_array ( $this->_m )) {
foreach ( $this->_m as $object ) {
if ($object->getEnabled () && (property_exists ( $object, $name ) || $object->canGetProperty ( $name )))
return $object->$name;
}
}
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 ))
return $this->$setter ( $value );
elseif (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]->add ( $value );
} elseif (is_array ( $this->_m )) {
foreach ( $this->_m as $object ) {
if ($object->getEnabled () && (property_exists ( $object, $name ) || $object->canSetProperty ( $name )))
return $object->$name = $value;
}
}
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;
elseif (strncasecmp ( $name, 'on', 2 ) === 0 && method_exists ( $this, $name )) {
$name = strtolower ( $name );
return isset ( $this->_e [$name] ) && $this->_e [$name]->getCount ();
} elseif (is_array ( $this->_m )) {
if (isset ( $this->_m [$name] ))
return true;
foreach ( $this->_m as $object ) {
if ($object->getEnabled () && (property_exists ( $object, $name ) || $object->canGetProperty ( $name )))
return $object->$name !== null;
}
}
return false;
}
public function __unset($name) {
$setter = 'set' . $name;
if (method_exists ( $this, $setter ))
$this->$setter ( null );
elseif (strncasecmp ( $name, 'on', 2 ) === 0 && method_exists ( $this, $name ))
unset ( $this->_e [strtolower ( $name )] );
elseif (is_array ( $this->_m )) {
if (isset ( $this->_m [$name] ))
$this->detachBehavior ( $name );
else {
foreach ( $this->_m as $object ) {
if ($object->getEnabled ()) {
if (property_exists ( $object, $name ))
return $object->$name = null;
elseif ($object->canSetProperty ( $name ))
return $object->$setter ( null );
}
}
}
} elseif (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 __call($name, $parameters) {
if ($this->_m !== null) {
foreach ( $this->_m as $object ) {
if ($object->getEnabled () && method_exists ( $object, $name ))
return call_user_func_array ( array (
$object,
$name
), $parameters );
}
}
if (class_exists ( 'Closure', false ) && $this->canGetProperty ( $name ) && $this->$name instanceof Closure)
return call_user_func_array ( $this->$name, $parameters );
throw new CException ( Yii::t ( 'yii', '{class} and its behaviors do not have a method or closure named "{name}".', array (
'{class}' => get_class ( $this ),
'{name}' => $name
) ) );
}
public function asa($behavior) {
return isset ( $this->_m [$behavior] ) ? $this->_m [$behavior] : null;
}
public function attachBehaviors($behaviors) {
foreach ( $behaviors as $name => $behavior )
$this->attachBehavior ( $name, $behavior );
}
public function detachBehaviors() {
if ($this->_m !== null) {
foreach ( $this->_m as $name => $behavior )
$this->detachBehavior ( $name );
$this->_m = null;
}
}
public function attachBehavior($name, $behavior) {
if (! ($behavior instanceof IBehavior))
$behavior = Yii::createComponent ( $behavior );
$behavior->setEnabled ( true );
$behavior->attach ( $this );
return $this->_m [$name] = $behavior;
}
public function detachBehavior($name) {
if (isset ( $this->_m [$name] )) {
$this->_m [$name]->detach ( $this );
$behavior = $this->_m [$name];
unset ( $this->_m [$name] );
return $behavior;
}
}
public function enableBehaviors() {
if ($this->_m !== null) {
foreach ( $this->_m as $behavior )
$behavior->setEnabled ( true );
}
}
public function disableBehaviors() {
if ($this->_m !== null) {
foreach ( $this->_m as $behavior )
$behavior->setEnabled ( false );
}
}
public function enableBehavior($name) {
if (isset ( $this->_m [$name] ))
$this->_m [$name]->setEnabled ( true );
}
public function disableBehavior($name) {
if (isset ( $this->_m [$name] ))
$this->_m [$name]->setEnabled ( false );
}
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 ))
return $this->getEventHandlers ( $name )->remove ( $handler ) !== false;
else
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 );
elseif (is_callable ( $handler, true )) {
if (is_array ( $handler )) {
// an array: 0 - object, 1 - method name
list ( $object, $method ) = $handler;
if (is_string ( $object )) // static method call
call_user_func ( $handler, $event );
elseif (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 // PHP 5.3: anonymous function
call_user_func ( $handler, $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}' => gettype ( $handler )
) ) );
// stop further handling if param.handled is set true
if (($event instanceof CEvent) && $event->handled)
return;
}
} elseif (YII_DEBUG && ! $this->hasEvent ( $name ))
throw new CException ( Yii::t ( 'yii', 'Event "{class}.{event}" is not defined.', array (
'{class}' => get_class ( $this ),
'{event}' => $name
) ) );
}
public function evaluateExpression($_expression_, $_data_ = array()) {
if (is_string ( $_expression_ )) {
extract ( $_data_ );
return eval ( 'return ' . $_expression_ . ';' );
} else {
$_data_ [] = $this;
return call_user_func_array ( $_expression_, $_data_ );
}
}
}
class CEvent extends CComponent {
public $sender;
public $handled = false;
public $params;
public function __construct($sender = null, $params = null) {
$this->sender = $sender;
$this->params = $params;
}
}
class CEnumerable {
}
abstract class CModule extends CComponent {
public $preload = array ();
public $behaviors = array ();
private $_id;
private $_parentModule;
private $_basePath;
private $_modulePath;
private $_params;
private $_modules = array ();
private $_moduleConfig = array ();
private $_components = array ();
private $_componentConfig = array ();
public function __construct($id, $parent, $config = null) {
$this->_id = $id;
$this->_parentModule = $parent;
// set basePath at early as possible to avoid trouble
if (is_string ( $config ))
$config = require ($config);
if (isset ( $config ['basePath'] )) {
$this->setBasePath ( $config ['basePath'] );
unset ( $config ['basePath'] );
}
Yii::setPathOfAlias ( $id, $this->getBasePath () );
$this->preinit ();
$this->configure ( $config );
$this->attachBehaviors ( $this->behaviors );
$this->preloadComponents ();
$this->init ();
}
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 getId() {
return $this->_id;
}
public function setId($id) {
$this->_id = $id;
}
public function getBasePath() {
if ($this->_basePath === null) {
$class = new ReflectionClass ( get_class ( $this ) );
$this->_basePath = dirname ( $class->getFileName () );
}
return $this->_basePath;
}
public function setBasePath($path) {
if (($this->_basePath = realpath ( $path )) === false || ! is_dir ( $this->_basePath ))
throw new CException ( Yii::t ( 'yii', 'Base path "{path}" is not a valid directory.', array (
'{path}' => $path
) ) );
}
public function getParams() {
if ($this->_params !== null)
return $this->_params;
else {
$this->_params = new CAttributeCollection ();
$this->_params->caseSensitive = true;
return $this->_params;
}
}
public function setParams($value) {
$params = $this->getParams ();
foreach ( $value as $k => $v )
$params->add ( $k, $v );
}
public function getModulePath() {
if ($this->_modulePath !== null)
return $this->_modulePath;
else
return $this->_modulePath = $this->getBasePath () . DIRECTORY_SEPARATOR . 'modules';
}
public function setModulePath($value) {
if (($this->_modulePath = realpath ( $value )) === false || ! is_dir ( $this->_modulePath ))
throw new CException ( Yii::t ( 'yii', 'The module path "{path}" is not a valid directory.', array (
'{path}' => $value
) ) );
}
public function setImport($aliases) {
foreach ( $aliases as $alias )
Yii::import ( $alias );
}
public function setAliases($mappings) {
foreach ( $mappings as $name => $alias ) {
if (($path = Yii::getPathOfAlias ( $alias )) !== false)
Yii::setPathOfAlias ( $name, $path );
else
Yii::setPathOfAlias ( $name, $alias );
}
}
public function getParentModule() {
return $this->_parentModule;
}
public function getModule($id) {
if (isset ( $this->_modules [$id] ) || array_key_exists ( $id, $this->_modules ))
return $this->_modules [$id];
elseif (isset ( $this->_moduleConfig [$id] )) {
$config = $this->_moduleConfig [$id];
if (! isset ( $config ['enabled'] ) || $config ['enabled']) {
$class = $config ['class'];
unset ( $config ['class'], $config ['enabled'] );
if ($this === Yii::app ())
$module = Yii::createComponent ( $class, $id, null, $config );
else
$module = Yii::createComponent ( $class, $this->getId () . '/' . $id, $this, $config );
return $this->_modules [$id] = $module;
}
}
}
public function hasModule($id) {
return isset ( $this->_moduleConfig [$id] ) || isset ( $this->_modules [$id] );
}
public function getModules() {
return $this->_moduleConfig;
}
public function setModules($modules) {
foreach ( $modules as $id => $module ) {
if (is_int ( $id )) {
$id = $module;
$module = array ();
}
if (! isset ( $module ['class'] )) {
Yii::setPathOfAlias ( $id, $this->getModulePath () . DIRECTORY_SEPARATOR . $id );
$module ['class'] = $id . '.' . ucfirst ( $id ) . 'Module';
}
if (isset ( $this->_moduleConfig [$id] ))
$this->_moduleConfig [$id] = CMap::mergeArray ( $this->_moduleConfig [$id], $module );
else
$this->_moduleConfig [$id] = $module;
}
}
public function hasComponent($id) {
return isset ( $this->_components [$id] ) || isset ( $this->_componentConfig [$id] );
}
public function getComponent($id, $createIfNull = true) {
if (isset ( $this->_components [$id] ))
return $this->_components [$id];
elseif (isset ( $this->_componentConfig [$id] ) && $createIfNull) {
$config = $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, $merge = true) {
if ($component === null) {
unset ( $this->_components [$id] );
return;
} elseif ($component instanceof IApplicationComponent) {
$this->_components [$id] = $component;
if (! $component->getIsInitialized ())
$component->init ();
return;
} elseif (isset ( $this->_components [$id] )) {
if (isset ( $component ['class'] ) && get_class ( $this->_components [$id] ) !== $component ['class']) {
unset ( $this->_components [$id] );
$this->_componentConfig [$id] = $component; // we should ignore merge here
return;
}
foreach ( $component as $key => $value ) {
if ($key !== 'class')
$this->_components [$id]->$key = $value;
}
} elseif (isset ( $this->_componentConfig [$id] ['class'], $component ['class'] ) && $this->_componentConfig [$id] ['class'] !== $component ['class']) {
$this->_componentConfig [$id] = $component; // we should ignore merge here
return;
}
if (isset ( $this->_componentConfig [$id] ) && $merge)
$this->_componentConfig [$id] = CMap::mergeArray ( $this->_componentConfig [$id], $component );
else
$this->_componentConfig [$id] = $component;
}
public function getComponents($loadedOnly = true) {
if ($loadedOnly)
return $this->_components;
else
return array_merge ( $this->_componentConfig, $this->_components );
}
public function setComponents($components, $merge = true) {
foreach ( $components as $id => $component )
$this->setComponent ( $id, $component, $merge );
}
public function configure($config) {
if (is_array ( $config )) {
foreach ( $config as $key => $value )
$this->$key = $value;
}
}
protected function preloadComponents() {
foreach ( $this->preload as $id )
$this->getComponent ( $id );
}
protected function preinit() {
}
protected function init() {
}
}
abstract class CApplication extends CModule {
public $name = 'My Application';
public $charset = 'UTF-8';
public $sourceLanguage = 'en_us';
private $_id;
private $_basePath;
private $_runtimePath;
private $_extensionPath;
private $_globalState;
private $_stateChanged;
private $_ended = false;
private $_language;
private $_homeUrl;
abstract public function processRequest();
public function __construct($config = null) {
Yii::setApplication ( $this );
// set basePath at early as possible to avoid trouble
if (is_string ( $config ))
$config = require ($config);
if (isset ( $config ['basePath'] )) {
$this->setBasePath ( $config ['basePath'] );
unset ( $config ['basePath'] );
} else
$this->setBasePath ( 'protected' );
Yii::setPathOfAlias ( 'application', $this->getBasePath () );
Yii::setPathOfAlias ( 'webroot', dirname ( $_SERVER ['SCRIPT_FILENAME'] ) );
if (isset ( $config ['extensionPath'] )) {
$this->setExtensionPath ( $config ['extensionPath'] );
unset ( $config ['extensionPath'] );
} else
Yii::setPathOfAlias ( 'ext', $this->getBasePath () . DIRECTORY_SEPARATOR . 'extensions' );
if (isset ( $config ['aliases'] )) {
$this->setAliases ( $config ['aliases'] );
unset ( $config ['aliases'] );
}
$this->preinit ();
$this->initSystemHandlers ();
$this->registerCoreComponents ();
$this->configure ( $config );
$this->attachBehaviors ( $this->behaviors );
$this->preloadComponents ();
$this->init ();
}
public function run() {
if ($this->hasEventHandler ( 'onBeginRequest' ))
$this->onBeginRequest ( new CEvent ( $this ) );
register_shutdown_function ( array (
$this,
'end'
), 0, false );
$this->processRequest ();
if ($this->hasEventHandler ( 'onEndRequest' ))
$this->onEndRequest ( new CEvent ( $this ) );
}
public function end($status = 0, $exit = true) {
if ($this->hasEventHandler ( 'onEndRequest' ))
$this->onEndRequest ( new CEvent ( $this ) );
if ($exit)
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 = sprintf ( '%x', crc32 ( $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;
}
public function getExtensionPath() {
return Yii::getPathOfAlias ( 'ext' );
}
public function setExtensionPath($path) {
if (($extensionPath = realpath ( $path )) === false || ! is_dir ( $extensionPath ))
throw new CException ( Yii::t ( 'yii', 'Extension path "{path}" does not exist.', array (
'{path}' => $path
) ) );
Yii::setPathOfAlias ( 'ext', $extensionPath );
}
public function getLanguage() {
return $this->_language === null ? $this->sourceLanguage : $this->_language;
}
public function setLanguage($language) {
$this->_language = $language;
}
public function getTimeZone() {
return date_default_timezone_get ();
}
public function setTimeZone($value) {
date_default_timezone_set ( $value );
}
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 getLocaleDataPath() {
return CLocale::$dataPath === null ? Yii::getPathOfAlias ( 'system.i18n.data' ) : CLocale::$dataPath;
}
public function setLocaleDataPath($value) {
CLocale::$dataPath = $value;
}
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 getRequest() {
return $this->getComponent ( 'request' );
}
public function getUrlManager() {
return $this->getComponent ( 'urlManager' );
}
public function getController() {
return null;
}
public function createUrl($route, $params = array(), $ampersand = '&') {
return $this->getUrlManager ()->createUrl ( $route, $params, $ampersand );
}
public function createAbsoluteUrl($route, $params = array(), $schema = '', $ampersand = '&') {
$url = $this->createUrl ( $route, $params, $ampersand );
if (strpos ( $url, 'http' ) === 0)
return $url;
else
return $this->getRequest ()->getHostInfo ( $schema ) . $url;
}
public function getBaseUrl($absolute = false) {
return $this->getRequest ()->getBaseUrl ( $absolute );
}
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 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 ();
$changed = $this->_stateChanged;
if ($value === $defaultValue) {
if (isset ( $this->_globalState [$key] )) {
unset ( $this->_globalState [$key] );
$this->_stateChanged = true;
}
} elseif (! isset ( $this->_globalState [$key] ) || $this->_globalState [$key] !== $value) {
$this->_globalState [$key] = $value;
$this->_stateChanged = true;
}
if ($this->_stateChanged !== $changed)
$this->attachEventHandler ( 'onEndRequest', array (
$this,
'saveGlobalState'
) );
}
public function clearGlobalState($key) {
$this->setGlobalState ( $key, true, true );
}
public function loadGlobalState() {
$persister = $this->getStatePersister ();
if (($this->_globalState = $persister->load ()) === null)
$this->_globalState = array ();
$this->_stateChanged = false;
$this->detachEventHandler ( 'onEndRequest', array (
$this,
'saveGlobalState'
) );
}
public function saveGlobalState() {
if ($this->_stateChanged) {
$this->_stateChanged = false;
$this->detachEventHandler ( 'onEndRequest', array (
$this,
'saveGlobalState'
) );
$this->getStatePersister ()->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;
// php <5.2 doesn't support string conversion auto-magically
$message = $exception->__toString ();
if (isset ( $_SERVER ['REQUEST_URI'] ))
$message .= "\nREQUEST_URI=" . $_SERVER ['REQUEST_URI'];
if (isset ( $_SERVER ['HTTP_REFERER'] ))
$message .= "\nHTTP_REFERER=" . $_SERVER ['HTTP_REFERER'];
$message .= "\n---";
Yii::log ( $message, CLogger::LEVEL_ERROR, $category );
try {
$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 );
}
} catch ( Exception $e ) {
$this->displayException ( $e );
}
try {
$this->end ( 1 );
} catch ( Exception $e ) {
// use the most primitive way to log error
$msg = get_class ( $e ) . ': ' . $e->getMessage () . ' (' . $e->getFile () . ':' . $e->getLine () . ")\n";
$msg .= $e->getTraceAsString () . "\n";
$msg .= "Previous exception:\n";
$msg .= get_class ( $exception ) . ': ' . $exception->getMessage () . ' (' . $exception->getFile () . ':' . $exception->getLine () . ")\n";
$msg .= $exception->getTraceAsString () . "\n";
$msg .= '$_SERVER=' . var_export ( $_SERVER, true );
error_log ( $msg );
exit ( 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)\nStack trace:\n";
$trace = debug_backtrace ();
// skip the first 3 stacks as they do not tell the error position
if (count ( $trace ) > 3)
$trace = array_slice ( $trace, 3 );
foreach ( $trace as $i => $t ) {
if (! isset ( $t ['file'] ))
$t ['file'] = 'unknown';
if (! isset ( $t ['line'] ))
$t ['line'] = 0;
if (! isset ( $t ['function'] ))
$t ['function'] = 'unknown';
$log .= "#$i {$t['file']}({$t['line']}): ";
if (isset ( $t ['object'] ) && is_object ( $t ['object'] ))
$log .= get_class ( $t ['object'] ) . '->';
$log .= "{$t['function']}()\n";
}
if (isset ( $_SERVER ['REQUEST_URI'] ))
$log .= 'REQUEST_URI=' . $_SERVER ['REQUEST_URI'];
Yii::log ( $log, CLogger::LEVEL_ERROR, 'php' );
try {
Yii::import ( 'CErrorEvent', true );
$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 );
}
} catch ( Exception $e ) {
$this->displayException ( $e );
}
try {
$this->end ( 1 );
} catch ( Exception $e ) {
// use the most primitive way to log error
$msg = get_class ( $e ) . ': ' . $e->getMessage () . ' (' . $e->getFile () . ':' . $e->getLine () . ")\n";
$msg .= $e->getTraceAsString () . "\n";
$msg .= "Previous error:\n";
$msg .= $log . "\n";
$msg .= '$_SERVER=' . var_export ( $_SERVER, true );
error_log ( $msg );
exit ( 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 "
PHP Error [$code]
\n";
echo "$message ($file:$line)
\n";
echo '';
$trace = debug_backtrace ();
// skip the first 3 stacks as they do not tell the error position
if (count ( $trace ) > 3)
$trace = array_slice ( $trace, 3 );
foreach ( $trace as $i => $t ) {
if (! isset ( $t ['file'] ))
$t ['file'] = 'unknown';
if (! isset ( $t ['line'] ))
$t ['line'] = 0;
if (! isset ( $t ['function'] ))
$t ['function'] = 'unknown';
echo "#$i {$t['file']}({$t['line']}): ";
if (isset ( $t ['object'] ) && is_object ( $t ['object'] ))
echo get_class ( $t ['object'] ) . '->';
echo "{$t['function']}()\n";
}
echo '
';
} else {
echo "PHP Error [$code]
\n";
echo "$message
\n";
}
}
public function displayException($exception) {
if (YII_DEBUG) {
echo '' . get_class ( $exception ) . "
\n";
echo '' . $exception->getMessage () . ' (' . $exception->getFile () . ':' . $exception->getLine () . ')
';
echo '' . $exception->getTraceAsString () . '
';
} else {
echo '' . get_class ( $exception ) . "
\n";
echo '' . $exception->getMessage () . '
';
}
}
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'
),
'urlManager' => array (
'class' => 'CUrlManager'
),
'request' => array (
'class' => 'CHttpRequest'
),
'format' => array (
'class' => 'CFormatter'
)
);
$this->setComponents ( $components );
}
}
class CWebApplication extends CApplication {
public $defaultController = 'site';
public $layout = 'main';
public $controllerMap = array ();
public $catchAllRequest;
public $controllerNamespace;
private $_controllerPath;
private $_viewPath;
private $_systemViewPath;
private $_layoutPath;
private $_controller;
private $_theme;
public function processRequest() {
if (is_array ( $this->catchAllRequest ) && isset ( $this->catchAllRequest [0] )) {
$route = $this->catchAllRequest [0];
foreach ( array_splice ( $this->catchAllRequest, 1 ) as $name => $value )
$_GET [$name] = $value;
} else
$route = $this->getUrlManager ()->parseUrl ( $this->getRequest () );
$this->runController ( $route );
}
protected function registerCoreComponents() {
parent::registerCoreComponents ();
$components = array (
'session' => array (
'class' => 'CHttpSession'
),
'assetManager' => array (
'class' => 'CAssetManager'
),
'user' => array (
'class' => 'CWebUser'
),
'themeManager' => array (
'class' => 'CThemeManager'
),
'authManager' => array (
'class' => 'CPhpAuthManager'
),
'clientScript' => array (
'class' => 'CClientScript'
),
'widgetFactory' => array (
'class' => 'CWidgetFactory'
)
);
$this->setComponents ( $components );
}
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 getWidgetFactory() {
return $this->getComponent ( 'widgetFactory' );
}
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 runController($route) {
if (($ca = $this->createController ( $route )) !== null) {
list ( $controller, $actionID ) = $ca;
$oldController = $this->_controller;
$this->_controller = $controller;
$controller->init ();
$controller->run ( $actionID );
$this->_controller = $oldController;
} else
throw new CHttpException ( 404, Yii::t ( 'yii', 'Unable to resolve the request "{route}".', array (
'{route}' => $route === '' ? $this->defaultController : $route
) ) );
}
public function createController($route, $owner = null) {
if ($owner === null)
$owner = $this;
if (($route = trim ( $route, '/' )) === '')
$route = $owner->defaultController;
$caseSensitive = $this->getUrlManager ()->caseSensitive;
$route .= '/';
while ( ($pos = strpos ( $route, '/' )) !== false ) {
$id = substr ( $route, 0, $pos );
if (! preg_match ( '/^\w+$/', $id ))
return null;
if (! $caseSensitive)
$id = strtolower ( $id );
$route = ( string ) substr ( $route, $pos + 1 );
if (! isset ( $basePath )) // first segment
{
if (isset ( $owner->controllerMap [$id] )) {
return array (
Yii::createComponent ( $owner->controllerMap [$id], $id, $owner === $this ? null : $owner ),
$this->parseActionParams ( $route )
);
}
if (($module = $owner->getModule ( $id )) !== null)
return $this->createController ( $route, $module );
$basePath = $owner->getControllerPath ();
$controllerID = '';
} else
$controllerID .= '/';
$className = ucfirst ( $id ) . 'Controller';
$classFile = $basePath . DIRECTORY_SEPARATOR . $className . '.php';
if ($owner->controllerNamespace !== null)
$className = $owner->controllerNamespace . '\\' . $className;
if (is_file ( $classFile )) {
if (! class_exists ( $className, false ))
require ($classFile);
if (class_exists ( $className, false ) && is_subclass_of ( $className, 'CController' )) {
$id [0] = strtolower ( $id [0] );
return array (
new $className ( $controllerID . $id, $owner === $this ? null : $owner ),
$this->parseActionParams ( $route )
);
}
return null;
}
$controllerID .= $id;
$basePath .= DIRECTORY_SEPARATOR . $id;
}
}
protected function parseActionParams($pathInfo) {
if (($pos = strpos ( $pathInfo, '/' )) !== false) {
$manager = $this->getUrlManager ();
$manager->parsePathInfo ( ( string ) substr ( $pathInfo, $pos + 1 ) );
$actionID = substr ( $pathInfo, 0, $pos );
return $manager->caseSensitive ? $actionID : strtolower ( $actionID );
} else
return $pathInfo;
}
public function getController() {
return $this->_controller;
}
public function setController($value) {
$this->_controller = $value;
}
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
) ) );
}
public function beforeControllerAction($controller, $action) {
return true;
}
public function afterControllerAction($controller, $action) {
}
public function findModule($id) {
if (($controller = $this->getController ()) !== null && ($module = $controller->getModule ()) !== null) {
do {
if (($m = $module->getModule ( $id )) !== null)
return $m;
} while ( ($module = $module->getParentModule ()) !== null );
}
if (($m = $this->getModule ( $id )) !== null)
return $m;
}
protected function init() {
parent::init ();
// preload 'request' so that it has chance to respond to onBeginRequest event.
$this->getRequest ();
}
}
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) {
if ($key === null)
$this->_d [] = $value;
else
$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 );
} elseif ($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 );
}
} elseif ($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) {
$args = func_get_args ();
$res = array_shift ( $args );
while ( ! empty ( $args ) ) {
$next = array_shift ( $args );
foreach ( $next as $k => $v ) {
if (is_integer ( $k ))
isset ( $res [$k] ) ? $res [] = $v : $res [$k] = $v;
elseif (is_array ( $v ) && isset ( $res [$k] ) && is_array ( $res [$k] ))
$res [$k] = self::mergeArray ( $res [$k], $v );
else
$res [$k] = $v;
}
}
return $res;
}
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 CLogger extends CComponent {
const LEVEL_TRACE = 'trace';
const LEVEL_WARNING = 'warning';
const LEVEL_ERROR = 'error';
const LEVEL_INFO = 'info';
const LEVEL_PROFILE = 'profile';
public $autoFlush = 10000;
public $autoDump = false;
private $_logs = array ();
private $_logCount = 0;
private $_levels;
private $_categories;
private $_except = array ();
private $_timings;
private $_processing = false;
public function log($message, $level = 'info', $category = 'application') {
$this->_logs [] = array (
$message,
$level,
$category,
microtime ( true )
);
$this->_logCount ++;
if ($this->autoFlush > 0 && $this->_logCount >= $this->autoFlush && ! $this->_processing) {
$this->_processing = true;
$this->flush ( $this->autoDump );
$this->_processing = false;
}
}
public function getLogs($levels = '', $categories = array(), $except = array()) {
$this->_levels = preg_split ( '/[\s,]+/', strtolower ( $levels ), - 1, PREG_SPLIT_NO_EMPTY );
if (is_string ( $categories ))
$this->_categories = preg_split ( '/[\s,]+/', strtolower ( $categories ), - 1, PREG_SPLIT_NO_EMPTY );
else
$this->_categories = array_filter ( array_map ( 'strtolower', $categories ) );
if (is_string ( $except ))
$this->_except = preg_split ( '/[\s,]+/', strtolower ( $except ), - 1, PREG_SPLIT_NO_EMPTY );
else
$this->_except = array_filter ( array_map ( 'strtolower', $except ) );
$ret = $this->_logs;
if (! empty ( $levels ))
$ret = array_values ( array_filter ( $ret, array (
$this,
'filterByLevel'
) ) );
if (! empty ( $this->_categories ) || ! empty ( $this->_except ))
$ret = array_values ( array_filter ( $ret, array (
$this,
'filterByCategory'
) ) );
return $ret;
}
private function filterByCategory($value) {
return $this->filterAllCategories ( $value, 2 );
}
private function filterTimingByCategory($value) {
return $this->filterAllCategories ( $value, 1 );
}
private function filterAllCategories($value, $index) {
$cat = strtolower ( $value [$index] );
$ret = empty ( $this->_categories );
foreach ( $this->_categories as $category ) {
if ($cat === $category || (($c = rtrim ( $category, '.*' )) !== $category && strpos ( $cat, $c ) === 0))
$ret = true;
}
if ($ret) {
foreach ( $this->_except as $category ) {
if ($cat === $category || (($c = rtrim ( $category, '.*' )) !== $category && strpos ( $cat, $c ) === 0))
$ret = false;
}
}
return $ret;
}
private function filterByLevel($value) {
return in_array ( strtolower ( $value [1] ), $this->_levels );
}
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;
}
}
}
public function getProfilingResults($token = null, $categories = null, $refresh = false) {
if ($this->_timings === null || $refresh)
$this->calculateTimings ();
if ($token === null && $categories === null)
return $this->_timings;
$timings = $this->_timings;
if ($categories !== null) {
$this->_categories = preg_split ( '/[\s,]+/', strtolower ( $categories ), - 1, PREG_SPLIT_NO_EMPTY );
$timings = array_filter ( $timings, array (
$this,
'filterTimingByCategory'
) );
}
$results = array ();
foreach ( $timings as $timing ) {
if ($token === null || $timing [0] === $token)
$results [] = $timing [2];
}
return $results;
}
private function calculateTimings() {
$this->_timings = array ();
$stack = array ();
foreach ( $this->_logs as $log ) {
if ($log [1] !== CLogger::LEVEL_PROFILE)
continue;
list ( $message, $level, $category, $timestamp ) = $log;
if (! strncasecmp ( $message, 'begin:', 6 )) {
$log [0] = substr ( $message, 6 );
$stack [] = $log;
} elseif (! strncasecmp ( $message, 'end:', 4 )) {
$token = substr ( $message, 4 );
if (($last = array_pop ( $stack )) !== null && $last [0] === $token) {
$delta = $log [3] - $last [3];
$this->_timings [] = array (
$message,
$category,
$delta
);
} else
throw new CException ( Yii::t ( 'yii', 'CProfileLogRoute found a mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.', array (
'{token}' => $token
) ) );
}
}
$now = microtime ( true );
while ( ($last = array_pop ( $stack )) !== null ) {
$delta = $now - $last [3];
$this->_timings [] = array (
$last [0],
$last [2],
$delta
);
}
}
public function flush($dumpLogs = false) {
$this->onFlush ( new CEvent ( $this, array (
'dumpLogs' => $dumpLogs
) ) );
$this->_logs = array ();
$this->_logCount = 0;
}
public function onFlush($event) {
$this->raiseEvent ( 'onFlush', $event );
}
}
abstract class CApplicationComponent extends CComponent implements IApplicationComponent {
public $behaviors = array ();
private $_initialized = false;
public function init() {
$this->attachBehaviors ( $this->behaviors );
$this->_initialized = true;
}
public function getIsInitialized() {
return $this->_initialized;
}
}
class CHttpRequest extends CApplicationComponent {
public $enableCookieValidation = false;
public $enableCsrfValidation = false;
public $csrfTokenName = 'YII_CSRF_TOKEN';
public $csrfCookie;
private $_requestUri;
private $_pathInfo;
private $_scriptFile;
private $_scriptUrl;
private $_hostInfo;
private $_baseUrl;
private $_cookies;
private $_preferredAcceptTypes;
private $_preferredLanguages;
private $_csrfToken;
private $_restParams;
public function init() {
parent::init ();
$this->normalizeRequest ();
}
protected function normalizeRequest() {
// normalize request
if (function_exists ( 'get_magic_quotes_gpc' ) && 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)
Yii::app ()->attachEventHandler ( 'onBeginRequest', array (
$this,
'validateCsrfToken'
) );
}
public function stripSlashes(&$data) {
if (is_array ( $data )) {
if (count ( $data ) == 0)
return $data;
$keys = array_map ( 'stripslashes', array_keys ( $data ) );
$data = array_combine ( $keys, array_values ( $data ) );
return array_map ( array (
$this,
'stripSlashes'
), $data );
} else
return stripslashes ( $data );
}
public function getParam($name, $defaultValue = null) {
return isset ( $_GET [$name] ) ? $_GET [$name] : (isset ( $_POST [$name] ) ? $_POST [$name] : $defaultValue);
}
public function getQuery($name, $defaultValue = null) {
return isset ( $_GET [$name] ) ? $_GET [$name] : $defaultValue;
}
public function getPost($name, $defaultValue = null) {
return isset ( $_POST [$name] ) ? $_POST [$name] : $defaultValue;
}
public function getDelete($name, $defaultValue = null) {
if ($this->getIsDeleteViaPostRequest ())
return $this->getPost ( $name, $defaultValue );
if ($this->getIsDeleteRequest ()) {
$restParams = $this->getRestParams ();
return isset ( $restParams [$name] ) ? $restParams [$name] : $defaultValue;
} else
return $defaultValue;
}
public function getPut($name, $defaultValue = null) {
if ($this->getIsPutViaPostRequest ())
return $this->getPost ( $name, $defaultValue );
if ($this->getIsPutRequest ()) {
$restParams = $this->getRestParams ();
return isset ( $restParams [$name] ) ? $restParams [$name] : $defaultValue;
} else
return $defaultValue;
}
public function getRestParams() {
if ($this->_restParams === null) {
$result = array ();
if (function_exists ( 'mb_parse_str' ))
mb_parse_str ( $this->getRawBody (), $result );
else
parse_str ( $this->getRawBody (), $result );
$this->_restParams = $result;
}
return $this->_restParams;
}
public function getRawBody() {
static $rawBody;
if ($rawBody === null)
$rawBody = file_get_contents ( 'php://input' );
return $rawBody;
}
public function getUrl() {
return $this->getRequestUri ();
}
public function getHostInfo($schema = '') {
if ($this->_hostInfo === null) {
if ($secure = $this->getIsSecureConnection ())
$http = 'https';
else
$http = 'http';
if (isset ( $_SERVER ['HTTP_HOST'] ))
$this->_hostInfo = $http . '://' . $_SERVER ['HTTP_HOST'];
else {
$this->_hostInfo = $http . '://' . $_SERVER ['SERVER_NAME'];
$port = $secure ? $this->getSecurePort () : $this->getPort ();
if (($port !== 80 && ! $secure) || ($port !== 443 && $secure))
$this->_hostInfo .= ':' . $port;
}
}
if ($schema !== '') {
$secure = $this->getIsSecureConnection ();
if ($secure && $schema === 'https' || ! $secure && $schema === 'http')
return $this->_hostInfo;
$port = $schema === 'https' ? $this->getSecurePort () : $this->getPort ();
if ($port !== 80 && $schema === 'http' || $port !== 443 && $schema === 'https')
$port = ':' . $port;
else
$port = '';
$pos = strpos ( $this->_hostInfo, ':' );
return $schema . substr ( $this->_hostInfo, $pos, strcspn ( $this->_hostInfo, ':', $pos + 1 ) + 1 ) . $port;
} else
return $this->_hostInfo;
}
public function setHostInfo($value) {
$this->_hostInfo = rtrim ( $value, '/' );
}
public function getBaseUrl($absolute = false) {
if ($this->_baseUrl === null)
$this->_baseUrl = rtrim ( dirname ( $this->getScriptUrl () ), '\\/' );
return $absolute ? $this->getHostInfo () . $this->_baseUrl : $this->_baseUrl;
}
public function setBaseUrl($value) {
$this->_baseUrl = $value;
}
public function getScriptUrl() {
if ($this->_scriptUrl === null) {
$scriptName = basename ( $_SERVER ['SCRIPT_FILENAME'] );
if (basename ( $_SERVER ['SCRIPT_NAME'] ) === $scriptName)
$this->_scriptUrl = $_SERVER ['SCRIPT_NAME'];
elseif (basename ( $_SERVER ['PHP_SELF'] ) === $scriptName)
$this->_scriptUrl = $_SERVER ['PHP_SELF'];
elseif (isset ( $_SERVER ['ORIG_SCRIPT_NAME'] ) && basename ( $_SERVER ['ORIG_SCRIPT_NAME'] ) === $scriptName)
$this->_scriptUrl = $_SERVER ['ORIG_SCRIPT_NAME'];
elseif (($pos = strpos ( $_SERVER ['PHP_SELF'], '/' . $scriptName )) !== false)
$this->_scriptUrl = substr ( $_SERVER ['SCRIPT_NAME'], 0, $pos ) . '/' . $scriptName;
elseif (isset ( $_SERVER ['DOCUMENT_ROOT'] ) && strpos ( $_SERVER ['SCRIPT_FILENAME'], $_SERVER ['DOCUMENT_ROOT'] ) === 0)
$this->_scriptUrl = str_replace ( '\\', '/', str_replace ( $_SERVER ['DOCUMENT_ROOT'], '', $_SERVER ['SCRIPT_FILENAME'] ) );
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) {
$pathInfo = $this->getRequestUri ();
if (($pos = strpos ( $pathInfo, '?' )) !== false)
$pathInfo = substr ( $pathInfo, 0, $pos );
$pathInfo = $this->decodePathInfo ( $pathInfo );
$scriptUrl = $this->getScriptUrl ();
$baseUrl = $this->getBaseUrl ();
if (strpos ( $pathInfo, $scriptUrl ) === 0)
$pathInfo = substr ( $pathInfo, strlen ( $scriptUrl ) );
elseif ($baseUrl === '' || strpos ( $pathInfo, $baseUrl ) === 0)
$pathInfo = substr ( $pathInfo, strlen ( $baseUrl ) );
elseif (strpos ( $_SERVER ['PHP_SELF'], $scriptUrl ) === 0)
$pathInfo = substr ( $_SERVER ['PHP_SELF'], strlen ( $scriptUrl ) );
else
throw new CException ( Yii::t ( 'yii', 'CHttpRequest is unable to determine the path info of the request.' ) );
$this->_pathInfo = trim ( $pathInfo, '/' );
}
return $this->_pathInfo;
}
protected function decodePathInfo($pathInfo) {
$pathInfo = urldecode ( $pathInfo );
// is it UTF-8?
// http://w3.org/International/questions/qa-forms-utf-8.html
if (preg_match ( '%^(?:
[\x09\x0A\x0D\x20-\x7E] # ASCII
| [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
)*$%xs', $pathInfo )) {
return $pathInfo;
} else {
return utf8_encode ( $pathInfo );
}
}
public function getRequestUri() {
if ($this->_requestUri === null) {
if (isset ( $_SERVER ['HTTP_X_REWRITE_URL'] )) // IIS
$this->_requestUri = $_SERVER ['HTTP_X_REWRITE_URL'];
elseif (isset ( $_SERVER ['REQUEST_URI'] )) {
$this->_requestUri = $_SERVER ['REQUEST_URI'];
if (! empty ( $_SERVER ['HTTP_HOST'] )) {
if (strpos ( $this->_requestUri, $_SERVER ['HTTP_HOST'] ) !== false)
$this->_requestUri = preg_replace ( '/^\w+:\/\/[^\/]+/', '', $this->_requestUri );
} else
$this->_requestUri = preg_replace ( '/^(http|https):\/\/[^\/]+/i', '', $this->_requestUri );
} elseif (isset ( $_SERVER ['ORIG_PATH_INFO'] )) // IIS 5.0 CGI
{
$this->_requestUri = $_SERVER ['ORIG_PATH_INFO'];
if (! empty ( $_SERVER ['QUERY_STRING'] ))
$this->_requestUri .= '?' . $_SERVER ['QUERY_STRING'];
} else
throw new CException ( Yii::t ( 'yii', 'CHttpRequest is unable to determine the request URI.' ) );
}
return $this->_requestUri;
}
public function getQueryString() {
return isset ( $_SERVER ['QUERY_STRING'] ) ? $_SERVER ['QUERY_STRING'] : '';
}
public function getIsSecureConnection() {
return isset ( $_SERVER ['HTTPS'] ) && ($_SERVER ['HTTPS'] == 'on' || $_SERVER ['HTTPS'] == 1) || isset ( $_SERVER ['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER ['HTTP_X_FORWARDED_PROTO'] == 'https';
}
public function getRequestType() {
if (isset ( $_POST ['_method'] ))
return strtoupper ( $_POST ['_method'] );
return strtoupper ( isset ( $_SERVER ['REQUEST_METHOD'] ) ? $_SERVER ['REQUEST_METHOD'] : 'GET' );
}
public function getIsPostRequest() {
return isset ( $_SERVER ['REQUEST_METHOD'] ) && ! strcasecmp ( $_SERVER ['REQUEST_METHOD'], 'POST' );
}
public function getIsDeleteRequest() {
return (isset ( $_SERVER ['REQUEST_METHOD'] ) && ! strcasecmp ( $_SERVER ['REQUEST_METHOD'], 'DELETE' )) || $this->getIsDeleteViaPostRequest ();
}
protected function getIsDeleteViaPostRequest() {
return isset ( $_POST ['_method'] ) && ! strcasecmp ( $_POST ['_method'], 'DELETE' );
}
public function getIsPutRequest() {
return (isset ( $_SERVER ['REQUEST_METHOD'] ) && ! strcasecmp ( $_SERVER ['REQUEST_METHOD'], 'PUT' )) || $this->getIsPutViaPostRequest ();
}
protected function getIsPutViaPostRequest() {
return isset ( $_POST ['_method'] ) && ! strcasecmp ( $_POST ['_method'], 'PUT' );
}
public function getIsAjaxRequest() {
return isset ( $_SERVER ['HTTP_X_REQUESTED_WITH'] ) && $_SERVER ['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest';
}
public function getIsFlashRequest() {
return isset ( $_SERVER ['HTTP_USER_AGENT'] ) && (stripos ( $_SERVER ['HTTP_USER_AGENT'], 'Shockwave' ) !== false || stripos ( $_SERVER ['HTTP_USER_AGENT'], 'Flash' ) !== 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 isset ( $_SERVER ['HTTP_USER_AGENT'] ) ? $_SERVER ['HTTP_USER_AGENT'] : null;
}
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($userAgent = null) {
return get_browser ( $userAgent, true );
}
public function getAcceptTypes() {
return isset ( $_SERVER ['HTTP_ACCEPT'] ) ? $_SERVER ['HTTP_ACCEPT'] : null;
}
private $_port;
public function getPort() {
if ($this->_port === null)
$this->_port = ! $this->getIsSecureConnection () && isset ( $_SERVER ['SERVER_PORT'] ) ? ( int ) $_SERVER ['SERVER_PORT'] : 80;
return $this->_port;
}
public function setPort($value) {
$this->_port = ( int ) $value;
$this->_hostInfo = null;
}
private $_securePort;
public function getSecurePort() {
if ($this->_securePort === null)
$this->_securePort = $this->getIsSecureConnection () && isset ( $_SERVER ['SERVER_PORT'] ) ? ( int ) $_SERVER ['SERVER_PORT'] : 443;
return $this->_securePort;
}
public function setSecurePort($value) {
$this->_securePort = ( int ) $value;
$this->_hostInfo = null;
}
public function getCookies() {
if ($this->_cookies !== null)
return $this->_cookies;
else
return $this->_cookies = new CCookieCollection ( $this );
}
public function redirect($url, $terminate = true, $statusCode = 302) {
if (strpos ( $url, '/' ) === 0 && strpos ( $url, '//' ) !== 0)
$url = $this->getHostInfo () . $url;
header ( 'Location: ' . $url, true, $statusCode );
if ($terminate)
Yii::app ()->end ();
}
public static function parseAcceptHeader($header) {
$matches = array ();
$accepts = array ();
// get individual entries with their type, subtype, basetype and params
preg_match_all ( '/(?:\G\s?,\s?|^)(\w+|\*)\/(\w+|\*)(?:\+(\w+))?|(? $matches [1] [$i],
'subType' => $matches [2] [$i],
'baseType' => null,
'params' => array ()
);
// fill in the base type if it exists
if ($matches [3] [$i] !== null && $matches [3] [$i] !== '')
$accept ['baseType'] = $matches [3] [$i];
// continue looping while there is no new content type, to fill in all accompanying params
for($i ++; $i < $itemLen; $i ++) {
// if the next content type is null, then the item is a param for the current content type
if ($matches [1] [$i] === null || $matches [1] [$i] === '') {
// if this is the quality param, convert it to a double
if ($matches [4] [$i] === 'q') {
// sanity check on q value
$q = ( double ) $matches [5] [$i];
if ($q > 1)
$q = ( double ) 1;
elseif ($q < 0)
$q = ( double ) 0;
$accept ['params'] [$matches [4] [$i]] = $q;
} else
$accept ['params'] [$matches [4] [$i]] = $matches [5] [$i];
} else
break;
}
// q defaults to 1 if not explicitly given
if (! isset ( $accept ['params'] ['q'] ))
$accept ['params'] ['q'] = ( double ) 1;
$accepts [] = $accept;
}
}
return $accepts;
}
public static function compareAcceptTypes($a, $b) {
// check for equal quality first
if ($a ['params'] ['q'] === $b ['params'] ['q'])
if (! ($a ['type'] === '*' xor $b ['type'] === '*'))
if (! ($a ['subType'] === '*' xor $b ['subType'] === '*'))
// finally, higher number of parameters counts as greater precedence
if (count ( $a ['params'] ) === count ( $b ['params'] ))
return 0;
else
return count ( $a ['params'] ) < count ( $b ['params'] ) ? 1 : - 1;
// more specific takes precedence - whichever one doesn't have a * subType
else
return $a ['subType'] === '*' ? 1 : - 1;
// more specific takes precedence - whichever one doesn't have a * type
else
return $a ['type'] === '*' ? 1 : - 1;
else
return ($a ['params'] ['q'] < $b ['params'] ['q']) ? 1 : - 1;
}
public function getPreferredAcceptTypes() {
if ($this->_preferredAcceptTypes === null) {
$accepts = self::parseAcceptHeader ( $this->getAcceptTypes () );
usort ( $accepts, array (
get_class ( $this ),
'compareAcceptTypes'
) );
$this->_preferredAcceptTypes = $accepts;
}
return $this->_preferredAcceptTypes;
}
public function getPreferredAcceptType() {
$preferredAcceptTypes = $this->getPreferredAcceptTypes ();
return empty ( $preferredAcceptTypes ) ? false : $preferredAcceptTypes [0];
}
public function getPreferredLanguages() {
if ($this->_preferredLanguages === null) {
$sortedLanguages = array ();
if (isset ( $_SERVER ['HTTP_ACCEPT_LANGUAGE'] ) && $n = preg_match_all ( '/([\w\-_]+)(?:\s*;\s*q\s*=\s*(\d*\.?\d*))?/', $_SERVER ['HTTP_ACCEPT_LANGUAGE'], $matches )) {
$languages = array ();
for($i = 0; $i < $n; ++ $i) {
$q = $matches [2] [$i];
if ($q === '')
$q = 1;
if ($q)
$languages [] = array (
( float ) $q,
$matches [1] [$i]
);
}
usort ( $languages, create_function ( '$a,$b', 'if($a[0]==$b[0]) {return 0;} return ($a[0]<$b[0]) ? 1 : -1;' ) );
foreach ( $languages as $language )
$sortedLanguages [] = $language [1];
}
$this->_preferredLanguages = $sortedLanguages;
}
return $this->_preferredLanguages;
}
public function getPreferredLanguage() {
$preferredLanguages = $this->getPreferredLanguages ();
return ! empty ( $preferredLanguages ) ? CLocale::getCanonicalID ( $preferredLanguages [0] ) : false;
}
public function sendFile($fileName, $content, $mimeType = null, $terminate = true) {
if ($mimeType === null) {
if (($mimeType = CFileHelper::getMimeTypeByExtension ( $fileName )) === null)
$mimeType = 'text/plain';
}
$fileSize = (function_exists ( 'mb_strlen' ) ? mb_strlen ( $content, '8bit' ) : strlen ( $content ));
$contentStart = 0;
$contentEnd = $fileSize - 1;
if (isset ( $_SERVER ['HTTP_RANGE'] )) {
header ( 'Accept-Ranges: bytes' );
// client sent us a multibyte range, can not hold this one for now
if (strpos ( $_SERVER ['HTTP_RANGE'], ',' ) !== false) {
header ( "Content-Range: bytes $contentStart-$contentEnd/$fileSize" );
throw new CHttpException ( 416, 'Requested Range Not Satisfiable' );
}
$range = str_replace ( 'bytes=', '', $_SERVER ['HTTP_RANGE'] );
// range requests starts from "-", so it means that data must be dumped the end point.
if ($range [0] === '-')
$contentStart = $fileSize - substr ( $range, 1 );
else {
$range = explode ( '-', $range );
$contentStart = $range [0];
// check if the last-byte-pos presents in header
if ((isset ( $range [1] ) && is_numeric ( $range [1] )))
$contentEnd = $range [1];
}
/*
* Check the range and make sure it's treated according to the specs.
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
*/
// End bytes can not be larger than $end.
$contentEnd = ($contentEnd > $fileSize) ? $fileSize - 1 : $contentEnd;
// Validate the requested range and return an error if it's not correct.
$wrongContentStart = ($contentStart > $contentEnd || $contentStart > $fileSize - 1 || $contentStart < 0);
if ($wrongContentStart) {
header ( "Content-Range: bytes $contentStart-$contentEnd/$fileSize" );
throw new CHttpException ( 416, 'Requested Range Not Satisfiable' );
}
header ( 'HTTP/1.1 206 Partial Content' );
header ( "Content-Range: bytes $contentStart-$contentEnd/$fileSize" );
} else
header ( 'HTTP/1.1 200 OK' );
$length = $contentEnd - $contentStart + 1; // Calculate new content length
header ( 'Pragma: public' );
header ( 'Expires: 0' );
header ( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
header ( "Content-Type: $mimeType" );
header ( 'Content-Length: ' . $length );
header ( "Content-Disposition: attachment; filename=\"$fileName\"" );
header ( 'Content-Transfer-Encoding: binary' );
$content = function_exists ( 'mb_substr' ) ? mb_substr ( $content, $contentStart, $length ) : substr ( $content, $contentStart, $length );
if ($terminate) {
// clean up the application first because the file downloading could take long time
// which may cause timeout of some resources (such as DB connection)
ob_start ();
Yii::app ()->end ( 0, false );
ob_end_clean ();
echo $content;
exit ( 0 );
} else
echo $content;
}
public function xSendFile($filePath, $options = array()) {
if (! isset ( $options ['forceDownload'] ) || $options ['forceDownload'])
$disposition = 'attachment';
else
$disposition = 'inline';
if (! isset ( $options ['saveName'] ))
$options ['saveName'] = basename ( $filePath );
if (! isset ( $options ['mimeType'] )) {
if (($options ['mimeType'] = CFileHelper::getMimeTypeByExtension ( $filePath )) === null)
$options ['mimeType'] = 'text/plain';
}
if (! isset ( $options ['xHeader'] ))
$options ['xHeader'] = 'X-Sendfile';
if ($options ['mimeType'] !== null)
header ( 'Content-Type: ' . $options ['mimeType'] );
header ( 'Content-Disposition: ' . $disposition . '; filename="' . $options ['saveName'] . '"' );
if (isset ( $options ['addHeaders'] )) {
foreach ( $options ['addHeaders'] as $header => $value )
header ( $header . ': ' . $value );
}
header ( trim ( $options ['xHeader'] ) . ': ' . $filePath );
if (! isset ( $options ['terminate'] ) || $options ['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 ( mt_rand (), true ) ) );
if (is_array ( $this->csrfCookie )) {
foreach ( $this->csrfCookie as $name => $value )
$cookie->$name = $value;
}
return $cookie;
}
public function validateCsrfToken($event) {
if ($this->getIsPostRequest () || $this->getIsPutRequest () || $this->getIsDeleteRequest ()) {
$cookies = $this->getCookies ();
$method = $this->getRequestType ();
switch ($method) {
case 'POST' :
$userToken = $this->getPost ( $this->csrfTokenName );
break;
case 'PUT' :
$userToken = $this->getPut ( $this->csrfTokenName );
break;
case 'DELETE' :
$userToken = $this->getDelete ( $this->csrfTokenName );
}
if (! empty ( $userToken ) && $cookies->contains ( $this->csrfTokenName )) {
$cookieToken = $cookies->itemAt ( $this->csrfTokenName )->value;
$valid = $cookieToken === $userToken;
} else
$valid = false;
if (! $valid)
throw new CHttpException ( 400, Yii::t ( 'yii', 'The CSRF token could not be verified.' ) );
}
}
}
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 (is_string ( $value ) && ($value = $sm->validateData ( $value )) !== false)
$cookies [$name] = new CHttpCookie ( $name, @unserialize ( $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, $options = array()) {
if (($cookie = parent::remove ( $name )) !== null) {
if ($this->_initialized) {
$cookie->configure ( $options );
$this->removeCookie ( $cookie );
}
}
return $cookie;
}
protected function addCookie($cookie) {
$value = $cookie->value;
if ($this->_request->enableCookieValidation)
$value = Yii::app ()->getSecurityManager ()->hashData ( serialize ( $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, '', 0, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httpOnly );
else
setcookie ( $cookie->name, '', 0, $cookie->path, $cookie->domain, $cookie->secure );
}
}
class CUrlManager extends CApplicationComponent {
const CACHE_KEY = 'Yii.CUrlManager.rules';
const GET_FORMAT = 'get';
const PATH_FORMAT = 'path';
public $rules = array ();
public $urlSuffix = '';
public $showScriptName = true;
public $appendParams = true;
public $routeVar = 'r';
public $caseSensitive = true;
public $matchValue = false;
public $cacheID = 'cache';
public $useStrictParsing = false;
public $urlRuleClass = 'CUrlRule';
private $_urlFormat = self::GET_FORMAT;
private $_rules = array ();
private $_baseUrl;
public function init() {
parent::init ();
$this->processRules ();
}
protected function processRules() {
if (empty ( $this->rules ) || $this->getUrlFormat () === self::GET_FORMAT)
return;
if ($this->cacheID !== false && ($cache = Yii::app ()->getComponent ( $this->cacheID )) !== null) {
$hash = md5 ( serialize ( $this->rules ) );
if (($data = $cache->get ( self::CACHE_KEY )) !== false && isset ( $data [1] ) && $data [1] === $hash) {
$this->_rules = $data [0];
return;
}
}
foreach ( $this->rules as $pattern => $route )
$this->_rules [] = $this->createUrlRule ( $route, $pattern );
if (isset ( $cache ))
$cache->set ( self::CACHE_KEY, array (
$this->_rules,
$hash
) );
}
public function addRules($rules, $append = true) {
if ($append) {
foreach ( $rules as $pattern => $route )
$this->_rules [] = $this->createUrlRule ( $route, $pattern );
} else {
$rules = array_reverse ( $rules );
foreach ( $rules as $pattern => $route )
array_unshift ( $this->_rules, $this->createUrlRule ( $route, $pattern ) );
}
}
protected function createUrlRule($route, $pattern) {
if (is_array ( $route ) && isset ( $route ['class'] ))
return $route;
else {
$urlRuleClass = Yii::import ( $this->urlRuleClass, true );
return new $urlRuleClass ( $route, $pattern );
}
}
public function createUrl($route, $params = array(), $ampersand = '&') {
unset ( $params [$this->routeVar] );
foreach ( $params as $i => $param )
if ($param === null)
$params [$i] = '';
if (isset ( $params ['#'] )) {
$anchor = '#' . $params ['#'];
unset ( $params ['#'] );
} else
$anchor = '';
$route = trim ( $route, '/' );
foreach ( $this->_rules as $i => $rule ) {
if (is_array ( $rule ))
$this->_rules [$i] = $rule = Yii::createComponent ( $rule );
if (($url = $rule->createUrl ( $this, $route, $params, $ampersand )) !== false) {
if ($rule->hasHostInfo)
return $url === '' ? '/' . $anchor : $url . $anchor;
else
return $this->getBaseUrl () . '/' . $url . $anchor;
}
}
return $this->createUrlDefault ( $route, $params, $ampersand ) . $anchor;
}
protected function createUrlDefault($route, $params, $ampersand) {
if ($this->getUrlFormat () === self::PATH_FORMAT) {
$url = rtrim ( $this->getBaseUrl () . '/' . $route, '/' );
if ($this->appendParams) {
$url = rtrim ( $url . '/' . $this->createPathInfo ( $params, '/', '/' ), '/' );
return $route === '' ? $url : $url . $this->urlSuffix;
} else {
if ($route !== '')
$url .= $this->urlSuffix;
$query = $this->createPathInfo ( $params, '=', $ampersand );
return $query === '' ? $url : $url . '?' . $query;
}
} else {
$url = $this->getBaseUrl ();
if (! $this->showScriptName)
$url .= '/';
if ($route !== '') {
$url .= '?' . $this->routeVar . '=' . $route;
if (($query = $this->createPathInfo ( $params, '=', $ampersand )) !== '')
$url .= $ampersand . $query;
} elseif (($query = $this->createPathInfo ( $params, '=', $ampersand )) !== '')
$url .= '?' . $query;
return $url;
}
}
public function parseUrl($request) {
if ($this->getUrlFormat () === self::PATH_FORMAT) {
$rawPathInfo = $request->getPathInfo ();
$pathInfo = $this->removeUrlSuffix ( $rawPathInfo, $this->urlSuffix );
foreach ( $this->_rules as $i => $rule ) {
if (is_array ( $rule ))
$this->_rules [$i] = $rule = Yii::createComponent ( $rule );
if (($r = $rule->parseUrl ( $this, $request, $pathInfo, $rawPathInfo )) !== false)
return isset ( $_GET [$this->routeVar] ) ? $_GET [$this->routeVar] : $r;
}
if ($this->useStrictParsing)
throw new CHttpException ( 404, Yii::t ( 'yii', 'Unable to resolve the request "{route}".', array (
'{route}' => $pathInfo
) ) );
else
return $pathInfo;
} elseif (isset ( $_GET [$this->routeVar] ))
return $_GET [$this->routeVar];
elseif (isset ( $_POST [$this->routeVar] ))
return $_POST [$this->routeVar];
else
return '';
}
public function parsePathInfo($pathInfo) {
if ($pathInfo === '')
return;
$segs = explode ( '/', $pathInfo . '/' );
$n = count ( $segs );
for($i = 0; $i < $n - 1; $i += 2) {
$key = $segs [$i];
if ($key === '')
continue;
$value = $segs [$i + 1];
if (($pos = strpos ( $key, '[' )) !== false && ($m = preg_match_all ( '/\[(.*?)\]/', $key, $matches )) > 0) {
$name = substr ( $key, 0, $pos );
for($j = $m - 1; $j >= 0; -- $j) {
if ($matches [1] [$j] === '')
$value = array (
$value
);
else
$value = array (
$matches [1] [$j] => $value
);
}
if (isset ( $_GET [$name] ) && is_array ( $_GET [$name] ))
$value = CMap::mergeArray ( $_GET [$name], $value );
$_REQUEST [$name] = $_GET [$name] = $value;
} else
$_REQUEST [$key] = $_GET [$key] = $value;
}
}
public function createPathInfo($params, $equal, $ampersand, $key = null) {
$pairs = array ();
foreach ( $params as $k => $v ) {
if ($key !== null)
$k = $key . '[' . $k . ']';
if (is_array ( $v ))
$pairs [] = $this->createPathInfo ( $v, $equal, $ampersand, $k );
else
$pairs [] = urlencode ( $k ) . $equal . urlencode ( $v );
}
return implode ( $ampersand, $pairs );
}
public function removeUrlSuffix($pathInfo, $urlSuffix) {
if ($urlSuffix !== '' && substr ( $pathInfo, - strlen ( $urlSuffix ) ) === $urlSuffix)
return substr ( $pathInfo, 0, - strlen ( $urlSuffix ) );
else
return $pathInfo;
}
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 setBaseUrl($value) {
$this->_baseUrl = $value;
}
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".' ) );
}
}
abstract class CBaseUrlRule extends CComponent {
public $hasHostInfo = false;
abstract public function createUrl($manager, $route, $params, $ampersand);
abstract public function parseUrl($manager, $request, $pathInfo, $rawPathInfo);
}
class CUrlRule extends CBaseUrlRule {
public $urlSuffix;
public $caseSensitive;
public $defaultParams = array ();
public $matchValue;
public $verb;
public $parsingOnly = false;
public $route;
public $references = array ();
public $routePattern;
public $pattern;
public $template;
public $params = array ();
public $append;
public $hasHostInfo;
public function __construct($route, $pattern) {
if (is_array ( $route )) {
foreach ( array (
'urlSuffix',
'caseSensitive',
'defaultParams',
'matchValue',
'verb',
'parsingOnly'
) as $name ) {
if (isset ( $route [$name] ))
$this->$name = $route [$name];
}
if (isset ( $route ['pattern'] ))
$pattern = $route ['pattern'];
$route = $route [0];
}
$this->route = trim ( $route, '/' );
$tr2 ['/'] = $tr ['/'] = '\\/';
if (strpos ( $route, '<' ) !== false && preg_match_all ( '/<(\w+)>/', $route, $matches2 )) {
foreach ( $matches2 [1] as $name )
$this->references [$name] = "<$name>";
}
$this->hasHostInfo = ! strncasecmp ( $pattern, 'http://', 7 ) || ! strncasecmp ( $pattern, 'https://', 8 );
if ($this->verb !== null)
$this->verb = preg_split ( '/[\s,]+/', strtoupper ( $this->verb ), - 1, PREG_SPLIT_NO_EMPTY );
if (preg_match_all ( '/<(\w+):?(.*?)?>/', $pattern, $matches )) {
$tokens = array_combine ( $matches [1], $matches [2] );
foreach ( $tokens as $name => $value ) {
if ($value === '')
$value = '[^\/]+';
$tr ["<$name>"] = "(?P<$name>$value)";
if (isset ( $this->references [$name] ))
$tr2 ["<$name>"] = $tr ["<$name>"];
else
$this->params [$name] = $value;
}
}
$p = rtrim ( $pattern, '*' );
$this->append = $p !== $pattern;
$p = trim ( $p, '/' );
$this->template = preg_replace ( '/<(\w+):?.*?>/', '<$1>', $p );
$this->pattern = '/^' . strtr ( $this->template, $tr ) . '\/';
if ($this->append)
$this->pattern .= '/u';
else
$this->pattern .= '$/u';
if ($this->references !== array ())
$this->routePattern = '/^' . strtr ( $this->route, $tr2 ) . '$/u';
if (YII_DEBUG && @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($manager, $route, $params, $ampersand) {
if ($this->parsingOnly)
return false;
if ($manager->caseSensitive && $this->caseSensitive === null || $this->caseSensitive)
$case = '';
else
$case = 'i';
$tr = array ();
if ($route !== $this->route) {
if ($this->routePattern !== null && preg_match ( $this->routePattern . $case, $route, $matches )) {
foreach ( $this->references as $key => $name )
$tr [$name] = $matches [$key];
} else
return false;
}
foreach ( $this->defaultParams as $key => $value ) {
if (isset ( $params [$key] )) {
if ($params [$key] == $value)
unset ( $params [$key] );
else
return false;
}
}
foreach ( $this->params as $key => $value )
if (! isset ( $params [$key] ))
return false;
if ($manager->matchValue && $this->matchValue === null || $this->matchValue) {
foreach ( $this->params as $key => $value ) {
if (! preg_match ( '/\A' . $value . '\z/u' . $case, $params [$key] ))
return false;
}
}
foreach ( $this->params as $key => $value ) {
$tr ["<$key>"] = urlencode ( $params [$key] );
unset ( $params [$key] );
}
$suffix = $this->urlSuffix === null ? $manager->urlSuffix : $this->urlSuffix;
$url = strtr ( $this->template, $tr );
if ($this->hasHostInfo) {
$hostInfo = Yii::app ()->getRequest ()->getHostInfo ();
if (stripos ( $url, $hostInfo ) === 0)
$url = substr ( $url, strlen ( $hostInfo ) );
}
if (empty ( $params ))
return $url !== '' ? $url . $suffix : $url;
if ($this->append)
$url .= '/' . $manager->createPathInfo ( $params, '/', '/' ) . $suffix;
else {
if ($url !== '')
$url .= $suffix;
$url .= '?' . $manager->createPathInfo ( $params, '=', $ampersand );
}
return $url;
}
public function parseUrl($manager, $request, $pathInfo, $rawPathInfo) {
if ($this->verb !== null && ! in_array ( $request->getRequestType (), $this->verb, true ))
return false;
if ($manager->caseSensitive && $this->caseSensitive === null || $this->caseSensitive)
$case = '';
else
$case = 'i';
if ($this->urlSuffix !== null)
$pathInfo = $manager->removeUrlSuffix ( $rawPathInfo, $this->urlSuffix );
// URL suffix required, but not found in the requested URL
if ($manager->useStrictParsing && $pathInfo === $rawPathInfo) {
$urlSuffix = $this->urlSuffix === null ? $manager->urlSuffix : $this->urlSuffix;
if ($urlSuffix != '' && $urlSuffix !== '/')
return false;
}
if ($this->hasHostInfo)
$pathInfo = strtolower ( $request->getHostInfo () ) . rtrim ( '/' . $pathInfo, '/' );
$pathInfo .= '/';
if (preg_match ( $this->pattern . $case, $pathInfo, $matches )) {
foreach ( $this->defaultParams as $name => $value ) {
if (! isset ( $_GET [$name] ))
$_REQUEST [$name] = $_GET [$name] = $value;
}
$tr = array ();
foreach ( $matches as $key => $value ) {
if (isset ( $this->references [$key] ))
$tr [$this->references [$key]] = $value;
elseif (isset ( $this->params [$key] ))
$_REQUEST [$key] = $_GET [$key] = $value;
}
if ($pathInfo !== $matches [0]) // there're additional GET params
$manager->parsePathInfo ( ltrim ( substr ( $pathInfo, strlen ( $matches [0] ) ), '/' ) );
if ($this->routePattern !== null)
return strtr ( $this->route, $tr );
else
return $this->route;
} else
return false;
}
}
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 && $renderer->fileExtension === '.' . CFileHelper::getExtension ( $viewFile ))
$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()) {
$widget = Yii::app ()->getWidgetFactory ()->createWidget ( $this, $className, $properties );
$widget->init ();
return $widget;
}
public function widget($className, $properties = array(), $captureOutput = false) {
if ($captureOutput) {
ob_start ();
ob_implicit_flush ( false );
$widget = $this->createWidget ( $className, $properties );
$widget->run ();
return ob_get_clean ();
} else {
$widget = $this->createWidget ( $className, $properties );
$widget->run ();
return $widget;
}
}
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 = null, $data = array()) {
$this->beginWidget ( 'CContentDecorator', array (
'view' => $view,
'data' => $data
) );
}
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;
private $_module;
public function __construct($id, $module = null) {
$this->_id = $id;
$this->_module = $module;
$this->attachBehaviors ( $this->behaviors () );
}
public function init() {
}
public function filters() {
return array ();
}
public function actions() {
return array ();
}
public function behaviors() {
return array ();
}
public function accessRules() {
return array ();
}
public function run($actionID) {
if (($action = $this->createAction ( $actionID )) !== null) {
if (($parent = $this->getModule ()) === null)
$parent = Yii::app ();
if ($parent->beforeControllerAction ( $this, $action )) {
$this->runActionWithFilters ( $action, $this->filters () );
$parent->afterControllerAction ( $this, $action );
}
} 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 )) {
if ($action->runWithParams ( $this->getActionParams () ) === false)
$this->invalidActionParams ( $action );
else
$this->afterAction ( $action );
}
$this->_action = $priorAction;
}
public function getActionParams() {
return $_GET;
}
public function invalidActionParams($action) {
throw new CHttpException ( 400, Yii::t ( 'yii', 'Your request is invalid.' ) );
}
public function processOutput($output) {
Yii::app ()->getClientScript ()->render ( $output );
// if using page caching, we should delay dynamic output replacement
if ($this->_dynamicOutput !== null && $this->isCachingStackEmpty ()) {
$output = $this->processDynamicOutput ( $output );
$this->_dynamicOutput = null;
}
if ($this->_pageStates === null)
$this->_pageStates = $this->loadPageStates ();
if (! empty ( $this->_pageStates ))
$this->savePageStates ( $this->_pageStates, $output );
return $output;
}
public function processDynamicOutput($output) {
if ($this->_dynamicOutput) {
$output = preg_replace_callback ( '/<###dynamic-(\d+)###>/', array (
$this,
'replaceDynamicOutput'
), $output );
}
return $output;
}
protected function replaceDynamicOutput($matches) {
$content = $matches [0];
if (isset ( $this->_dynamicOutput [$matches [1]] )) {
$content = $this->_dynamicOutput [$matches [1]];
$this->_dynamicOutput [$matches [1]] = null;
}
return $content;
}
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 {
$action = $this->createActionFromMap ( $this->actions (), $actionID, $actionID );
if ($action !== null && ! method_exists ( $action, 'run' ))
throw new CException ( Yii::t ( 'yii', 'Action class {class} must implement the "run" method.', array (
'{class}' => get_class ( $action )
) ) );
return $action;
}
}
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 );
} elseif ($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;
elseif (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 getUniqueId() {
return $this->_module ? $this->_module->getId () . '/' . $this->_id : $this->_id;
}
public function getRoute() {
if (($action = $this->getAction ()) !== null)
return $this->getUniqueId () . '/' . $action->getId ();
else
return $this->getUniqueId ();
}
public function getModule() {
return $this->_module;
}
public function getViewPath() {
if (($module = $this->getModule ()) === null)
$module = Yii::app ();
return $module->getViewPath () . DIRECTORY_SEPARATOR . $this->getId ();
}
public function getViewFile($viewName) {
if (($theme = Yii::app ()->getTheme ()) !== null && ($viewFile = $theme->getViewFile ( $this, $viewName )) !== false)
return $viewFile;
$moduleViewPath = $basePath = Yii::app ()->getViewPath ();
if (($module = $this->getModule ()) !== null)
$moduleViewPath = $module->getViewPath ();
return $this->resolveViewFile ( $viewName, $this->getViewPath (), $basePath, $moduleViewPath );
}
public function getLayoutFile($layoutName) {
if ($layoutName === false)
return false;
if (($theme = Yii::app ()->getTheme ()) !== null && ($layoutFile = $theme->getLayoutFile ( $this, $layoutName )) !== false)
return $layoutFile;
if (empty ( $layoutName )) {
$module = $this->getModule ();
while ( $module !== null ) {
if ($module->layout === false)
return false;
if (! empty ( $module->layout ))
break;
$module = $module->getParentModule ();
}
if ($module === null)
$module = Yii::app ();
$layoutName = $module->layout;
} elseif (($module = $this->getModule ()) === null)
$module = Yii::app ();
return $this->resolveViewFile ( $layoutName, $module->getLayoutPath (), Yii::app ()->getViewPath (), $module->getViewPath () );
}
public function resolveViewFile($viewName, $viewPath, $basePath, $moduleViewPath = null) {
if (empty ( $viewName ))
return false;
if ($moduleViewPath === null)
$moduleViewPath = $basePath;
if (($renderer = Yii::app ()->getViewRenderer ()) !== null)
$extension = $renderer->fileExtension;
else
$extension = '.php';
if ($viewName [0] === '/') {
if (strncmp ( $viewName, '//', 2 ) === 0)
$viewFile = $basePath . $viewName;
else
$viewFile = $moduleViewPath . $viewName;
} elseif (strpos ( $viewName, '.' ))
$viewFile = Yii::getPathOfAlias ( $viewName );
else
$viewFile = $viewPath . DIRECTORY_SEPARATOR . $viewName;
if (is_file ( $viewFile . $extension ))
return Yii::app ()->findLocalizedFile ( $viewFile . $extension );
elseif ($extension !== '.php' && is_file ( $viewFile . '.php' ))
return Yii::app ()->findLocalizedFile ( $viewFile . '.php' );
else
return false;
}
public function getClips() {
if ($this->_clips !== null)
return $this->_clips;
else
return $this->_clips = new CMap ();
}
public function forward($route, $exit = true) {
if (strpos ( $route, '/' ) === false)
$this->run ( $route );
else {
if ($route [0] !== '/' && ($module = $this->getModule ()) !== null)
$route = $module->getId () . '/' . $route;
Yii::app ()->runController ( $route );
}
if ($exit)
Yii::app ()->end ();
}
public function render($view, $data = null, $return = false) {
if ($this->beforeRender ( $view )) {
$output = $this->renderPartial ( $view, $data, true );
if (($layoutFile = $this->getLayoutFile ( $this->layout )) !== false)
$output = $this->renderFile ( $layoutFile, array (
'content' => $output
), true );
$this->afterRender ( $view, $output );
$output = $this->processOutput ( $output );
if ($return)
return $output;
else
echo $output;
}
}
protected function beforeRender($view) {
return true;
}
protected function afterRender($view, &$output) {
}
public function renderText($text, $return = false) {
if (($layoutFile = $this->getLayoutFile ( $this->layout )) !== false)
$text = $this->renderFile ( $layoutFile, array (
'content' => $text
), true );
$text = $this->processOutput ( $text );
if ($return)
return $text;
else
echo $text;
}
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 renderClip($name, $params = array(), $return = false) {
$text = isset ( $this->clips [$name] ) ? strtr ( $this->clips [$name], $params ) : '';
if ($return)
return $text;
else
echo $text;
}
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) {
$this->recordCachingAction ( '', 'renderDynamicInternal', array (
$callback,
$params
) );
if (is_string ( $callback ) && method_exists ( $this, $callback ))
$callback = array (
$this,
$callback
);
$this->_dynamicOutput [] = call_user_func_array ( $callback, $params );
}
public function createUrl($route, $params = array(), $ampersand = '&') {
if ($route === '')
$route = $this->getId () . '/' . $this->getAction ()->getId ();
elseif (strpos ( $route, '/' ) === false)
$route = $this->getId () . '/' . $route;
if ($route [0] !== '/' && ($module = $this->getModule ()) !== null)
$route = $module->getId () . '/' . $route;
return Yii::app ()->createUrl ( trim ( $route, '/' ), $params, $ampersand );
}
public function createAbsoluteUrl($route, $params = array(), $schema = '', $ampersand = '&') {
$url = $this->createUrl ( $route, $params, $ampersand );
if (strpos ( $url, 'http' ) === 0)
return $url;
else
return Yii::app ()->getRequest ()->getHostInfo ( $schema ) . $url;
}
public function getPageTitle() {
if ($this->_pageTitle !== null)
return $this->_pageTitle;
else {
$name = ucfirst ( basename ( $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, $statusCode = 302) {
if (is_array ( $url )) {
$route = isset ( $url [0] ) ? $url [0] : '';
$url = $this->createUrl ( $route, array_splice ( $url, 1 ) );
}
Yii::app ()->getRequest ()->redirect ( $url, $terminate, $statusCode );
}
public function refresh($terminate = true, $anchor = '') {
$this->redirect ( Yii::app ()->getRequest ()->getUrl () . $anchor, $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($createIfNull = true) {
if (! $this->_cachingStack)
$this->_cachingStack = new CStack ();
return $this->_cachingStack;
}
public function isCachingStackEmpty() {
return $this->_cachingStack === null || ! $this->_cachingStack->getCount ();
}
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 invalid.' ) );
}
public function filterAjaxOnly($filterChain) {
if (Yii::app ()->getRequest ()->getIsAjaxRequest ())
$filterChain->run ();
else
throw new CHttpException ( 400, Yii::t ( 'yii', 'Your request is invalid.' ) );
}
public function filterAccessControl($filterChain) {
$filter = new CAccessControlFilter ();
$filter->setRules ( $this->accessRules () );
$filter->filter ( $filterChain );
}
public function getPageState($name, $defaultValue = null) {
if ($this->_pageStates === null)
$this->_pageStates = $this->loadPageStates ();
return isset ( $this->_pageStates [$name] ) ? $this->_pageStates [$name] : $defaultValue;
}
public function setPageState($name, $value, $defaultValue = null) {
if ($this->_pageStates === null)
$this->_pageStates = $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 (! 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)
return unserialize ( $data );
}
}
return array ();
}
protected function savePageStates($states, &$output) {
$data = Yii::app ()->getSecurityManager ()->hashData ( serialize ( $states ) );
if (extension_loaded ( 'zlib' ))
$data = gzcompress ( $data );
$value = base64_encode ( $data );
$output = str_replace ( CHtml::pageStateField ( '' ), CHtml::pageStateField ( $value ), $output );
}
}
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;
}
public function runWithParams($params) {
$method = new ReflectionMethod ( $this, 'run' );
if ($method->getNumberOfParameters () > 0)
return $this->runWithParamsInternal ( $this, $method, $params );
else
return $this->run ();
}
protected function runWithParamsInternal($object, $method, $params) {
$ps = array ();
foreach ( $method->getParameters () as $i => $param ) {
$name = $param->getName ();
if (isset ( $params [$name] )) {
if ($param->isArray ())
$ps [] = is_array ( $params [$name] ) ? $params [$name] : array (
$params [$name]
);
elseif (! is_array ( $params [$name] ))
$ps [] = $params [$name];
else
return false;
} elseif ($param->isDefaultValueAvailable ())
$ps [] = $param->getDefaultValue ();
else
return false;
}
$method->invokeArgs ( $object, $ps );
return true;
}
}
class CInlineAction extends CAction {
public function run() {
$method = 'action' . $this->getId ();
$this->getController ()->$method ();
}
public function runWithParams($params) {
$methodName = 'action' . $this->getId ();
$controller = $this->getController ();
$method = new ReflectionMethod ( $controller, $methodName );
if ($method->getNumberOfParameters () > 0)
return $this->runWithParamsInternal ( $controller, $method, $params );
else
return $controller->$methodName ();
}
}
class CWebUser extends CApplicationComponent implements IWebUser {
const FLASH_KEY_PREFIX = 'Yii.CWebUser.flash.';
const FLASH_COUNTERS = 'Yii.CWebUser.flashcounters';
const STATES_VAR = '__states';
const AUTH_TIMEOUT_VAR = '__timeout';
const AUTH_ABSOLUTE_TIMEOUT_VAR = '__absolute_timeout';
public $allowAutoLogin = false;
public $guestName = 'Guest';
public $loginUrl = array (
'/site/login'
);
public $identityCookie;
public $authTimeout;
public $absoluteAuthTimeout;
public $autoRenewCookie = false;
public $autoUpdateFlash = true;
public $loginRequiredAjaxResponse;
private $_keyPrefix;
private $_access = array ();
public function __get($name) {
if ($this->hasState ( $name ))
return $this->getState ( $name );
else
return parent::__get ( $name );
}
public function __set($name, $value) {
if ($this->hasState ( $name ))
$this->setState ( $name, $value );
else
parent::__set ( $name, $value );
}
public function __isset($name) {
if ($this->hasState ( $name ))
return $this->getState ( $name ) !== null;
else
return parent::__isset ( $name );
}
public function __unset($name) {
if ($this->hasState ( $name ))
$this->setState ( $name, null );
else
parent::__unset ( $name );
}
public function init() {
parent::init ();
Yii::app ()->getSession ()->open ();
if ($this->getIsGuest () && $this->allowAutoLogin)
$this->restoreFromCookie ();
elseif ($this->autoRenewCookie && $this->allowAutoLogin)
$this->renewCookie ();
if ($this->autoUpdateFlash)
$this->updateFlash ();
$this->updateAuthStatus ();
}
public function login($identity, $duration = 0) {
$id = $identity->getId ();
$states = $identity->getPersistentStates ();
if ($this->beforeLogin ( $id, $states, false )) {
$this->changeIdentity ( $id, $identity->getName (), $states );
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 )
) ) );
}
if ($this->absoluteAuthTimeout)
$this->setState ( self::AUTH_ABSOLUTE_TIMEOUT_VAR, time () + $this->absoluteAuthTimeout );
$this->afterLogin ( false );
}
return ! $this->getIsGuest ();
}
public function logout($destroySession = true) {
if ($this->beforeLogout ()) {
if ($this->allowAutoLogin) {
Yii::app ()->getRequest ()->getCookies ()->remove ( $this->getStateKeyPrefix () );
if ($this->identityCookie !== null) {
$cookie = $this->createIdentityCookie ( $this->getStateKeyPrefix () );
$cookie->value = null;
$cookie->expire = 0;
Yii::app ()->getRequest ()->getCookies ()->add ( $cookie->name, $cookie );
}
}
if ($destroySession)
Yii::app ()->getSession ()->destroy ();
else
$this->clearStates ();
$this->_access = array ();
$this->afterLogout ();
}
}
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($defaultUrl = null) {
if ($defaultUrl === null) {
$defaultReturnUrl = Yii::app ()->getUrlManager ()->showScriptName ? Yii::app ()->getRequest ()->getScriptUrl () : Yii::app ()->getRequest ()->getBaseUrl () . '/';
} else {
$defaultReturnUrl = CHtml::normalizeUrl ( $defaultUrl );
}
return $this->getState ( '__returnUrl', $defaultReturnUrl );
}
public function setReturnUrl($value) {
$this->setState ( '__returnUrl', $value );
}
public function loginRequired() {
$app = Yii::app ();
$request = $app->getRequest ();
if (! $request->getIsAjaxRequest ()) {
$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 );
}
} elseif (isset ( $this->loginRequiredAjaxResponse )) {
echo $this->loginRequiredAjaxResponse;
Yii::app ()->end ();
}
throw new CHttpException ( 403, Yii::t ( 'yii', 'Login Required' ) );
}
protected function beforeLogin($id, $states, $fromCookie) {
return true;
}
protected function afterLogin($fromCookie) {
}
protected function beforeLogout() {
return true;
}
protected function afterLogout() {
}
protected function restoreFromCookie() {
$app = Yii::app ();
$request = $app->getRequest ();
$cookie = $request->getCookies ()->itemAt ( $this->getStateKeyPrefix () );
if ($cookie && ! empty ( $cookie->value ) && is_string ( $cookie->value ) && ($data = $app->getSecurityManager ()->validateData ( $cookie->value )) !== false) {
$data = @unserialize ( $data );
if (is_array ( $data ) && isset ( $data [0], $data [1], $data [2], $data [3] )) {
list ( $id, $name, $duration, $states ) = $data;
if ($this->beforeLogin ( $id, $states, true )) {
$this->changeIdentity ( $id, $name, $states );
if ($this->autoRenewCookie) {
$this->saveToCookie ( $duration );
}
$this->afterLogin ( true );
}
}
}
}
protected function renewCookie() {
$request = Yii::app ()->getRequest ();
$cookies = $request->getCookies ();
$cookie = $cookies->itemAt ( $this->getStateKeyPrefix () );
if ($cookie && ! empty ( $cookie->value ) && ($data = Yii::app ()->getSecurityManager ()->validateData ( $cookie->value )) !== false) {
$data = @unserialize ( $data );
if (is_array ( $data ) && isset ( $data [0], $data [1], $data [2], $data [3] )) {
$this->saveToCookie ( $data [2] );
}
}
}
protected function saveToCookie($duration) {
$app = Yii::app ();
$cookie = $this->createIdentityCookie ( $this->getStateKeyPrefix () );
$cookie->expire = time () + $duration;
$data = array (
$this->getId (),
$this->getName (),
$duration,
$this->saveIdentityStates ()
);
$cookie->value = $app->getSecurityManager ()->hashData ( serialize ( $data ) );
$app->getRequest ()->getCookies ()->add ( $cookie->name, $cookie );
}
protected function createIdentityCookie($name) {
$cookie = new CHttpCookie ( $name, '' );
if (is_array ( $this->identityCookie )) {
foreach ( $this->identityCookie as $name => $value )
$cookie->$name = $value;
}
return $cookie;
}
public function getStateKeyPrefix() {
if ($this->_keyPrefix !== null)
return $this->_keyPrefix;
else
return $this->_keyPrefix = md5 ( 'Yii.' . get_class ( $this ) . '.' . Yii::app ()->getId () );
}
public function setStateKeyPrefix($value) {
$this->_keyPrefix = $value;
}
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 hasState($key) {
$key = $this->getStateKeyPrefix () . $key;
return isset ( $_SESSION [$key] );
}
public function clearStates() {
$keys = array_keys ( $_SESSION );
$prefix = $this->getStateKeyPrefix ();
$n = strlen ( $prefix );
foreach ( $keys as $key ) {
if (! strncmp ( $key, $prefix, $n ))
unset ( $_SESSION [$key] );
}
}
public function getFlashes($delete = true) {
$flashes = array ();
$prefix = $this->getStateKeyPrefix () . self::FLASH_KEY_PREFIX;
$keys = array_keys ( $_SESSION );
$n = strlen ( $prefix );
foreach ( $keys as $key ) {
if (! strncmp ( $key, $prefix, $n )) {
$flashes [substr ( $key, $n )] = $_SESSION [$key];
if ($delete)
unset ( $_SESSION [$key] );
}
}
if ($delete)
$this->setState ( self::FLASH_COUNTERS, array () );
return $flashes;
}
public function getFlash($key, $defaultValue = null, $delete = true) {
$value = $this->getState ( self::FLASH_KEY_PREFIX . $key, $defaultValue );
if ($delete)
$this->setFlash ( $key, null );
return $value;
}
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, false ) !== null;
}
protected function changeIdentity($id, $name, $states) {
Yii::app ()->getSession ()->regenerateID ( true );
$this->setId ( $id );
$this->setName ( $name );
$this->loadIdentityStates ( $states );
}
protected function saveIdentityStates() {
$states = array ();
foreach ( $this->getState ( self::STATES_VAR, array () ) as $name => $dummy )
$states [$name] = $this->getState ( $name );
return $states;
}
protected function loadIdentityStates($states) {
$names = array ();
if (is_array ( $states )) {
foreach ( $states as $name => $value ) {
$this->setState ( $name, $value );
$names [$name] = true;
}
}
$this->setState ( self::STATES_VAR, $names );
}
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 () );
}
protected function updateAuthStatus() {
if (($this->authTimeout !== null || $this->absoluteAuthTimeout !== null) && ! $this->getIsGuest ()) {
$expires = $this->getState ( self::AUTH_TIMEOUT_VAR );
$expiresAbsolute = $this->getState ( self::AUTH_ABSOLUTE_TIMEOUT_VAR );
if ($expires !== null && $expires < time () || $expiresAbsolute !== null && $expiresAbsolute < time ())
$this->logout ( false );
else
$this->setState ( self::AUTH_TIMEOUT_VAR, time () + $this->authTimeout );
}
}
public function checkAccess($operation, $params = array(), $allowCaching = true) {
if ($allowCaching && $params === array () && isset ( $this->_access [$operation] ))
return $this->_access [$operation];
$access = Yii::app ()->getAuthManager ()->checkAccess ( $operation, $this->getId (), $params );
if ($allowCaching && $params === array ())
$this->_access [$operation] = $access;
return $access;
}
}
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 ($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 ();
if (YII_DEBUG && session_id () == '') {
$message = Yii::t ( 'yii', 'Failed to start session.' );
if (function_exists ( 'error_get_last' )) {
$error = error_get_last ();
if (isset ( $error ['message'] ))
$message = $error ['message'];
}
Yii::log ( $message, CLogger::LEVEL_WARNING, 'system.web.CHttpSession' );
}
}
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 regenerateID($deleteOldSession = false) {
session_regenerate_id ( $deleteOldSession );
}
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 );
if (isset ( $httponly ))
session_set_cookie_params ( $lifetime, $path, $domain, $secure, $httponly );
else
session_set_cookie_params ( $lifetime, $path, $domain, $secure );
}
public function getCookieMode() {
if (ini_get ( 'session.use_cookies' ) === '0')
return 'none';
elseif (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' );
ini_set ( 'session.use_only_cookies', '0' );
} elseif ($value === 'allow') {
ini_set ( 'session.use_cookies', '1' );
ini_set ( 'session.use_only_cookies', '0' );
} elseif ($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 ( float ) (ini_get ( 'session.gc_probability' ) / ini_get ( 'session.gc_divisor' ) * 100);
}
public function setGCProbability($value) {
if ($value >= 0 && $value <= 100) {
// percent * 21474837 / 2147483647 ≈ percent * 0.01
ini_set ( 'session.gc_probability', floor ( $value * 21474836.47 ) );
ini_set ( 'session.gc_divisor', 2147483647 );
} else
throw new CException ( Yii::t ( 'yii', 'CHttpSession.gcProbability "{value}" is invalid. It must be a float 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 get($key, $defaultValue = null) {
return isset ( $_SESSION [$key] ) ? $_SESSION [$key] : $defaultValue;
}
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 CHtml {
const ID_PREFIX = 'yt';
public static $errorSummaryCss = 'errorSummary';
public static $errorMessageCss = 'errorMessage';
public static $errorCss = 'error';
public static $errorContainerTag = 'div';
public static $requiredCss = 'required';
public static $beforeRequiredLabel = '';
public static $afterRequiredLabel = ' *';
public static $count = 0;
public static $liveEvents = true;
public static $closeSingleTags = true;
public static $renderSpecialAttributesValue = true;
private static $_modelNameConverter;
public static function encode($text) {
return htmlspecialchars ( $text, ENT_QUOTES, Yii::app ()->charset );
}
public static function decode($text) {
return htmlspecialchars_decode ( $text, ENT_QUOTES );
}
public static function encodeArray($data) {
$d = array ();
foreach ( $data as $key => $value ) {
if (is_string ( $key ))
$key = htmlspecialchars ( $key, ENT_QUOTES, Yii::app ()->charset );
if (is_string ( $value ))
$value = htmlspecialchars ( $value, ENT_QUOTES, Yii::app ()->charset );
elseif (is_array ( $value ))
$value = self::encodeArray ( $value );
$d [$key] = $value;
}
return $d;
}
public static function tag($tag, $htmlOptions = array(), $content = false, $closeTag = true) {
$html = '<' . $tag . self::renderAttributes ( $htmlOptions );
if ($content === false)
return $closeTag && self::$closeSingleTags ? $html . ' />' : $html . '>';
else
return $closeTag ? $html . '>' . $content . '' . $tag . '>' : $html . '>' . $content;
}
public static function openTag($tag, $htmlOptions = array()) {
return '<' . $tag . self::renderAttributes ( $htmlOptions ) . '>';
}
public static function closeTag($tag) {
return '' . $tag . '>';
}
public static function cdata($text) {
return '';
}
public static function metaTag($content, $name = null, $httpEquiv = null, $options = array()) {
if ($name !== null)
$options ['name'] = $name;
if ($httpEquiv !== null)
$options ['http-equiv'] = $httpEquiv;
$options ['content'] = $content;
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 "";
}
public static function refresh($seconds, $url = '') {
$content = "$seconds";
if ($url !== '')
$content .= ';url=' . self::normalizeUrl ( $url );
Yii::app ()->clientScript->registerMetaTag ( $content, null, 'refresh' );
}
public static function cssFile($url, $media = '') {
return CHtml::linkTag ( 'stylesheet', 'text/css', $url, $media !== '' ? $media : null );
}
public static function script($text, array $htmlOptions = array()) {
$defaultHtmlOptions = array (
'type' => 'text/javascript'
);
$htmlOptions = array_merge ( $defaultHtmlOptions, $htmlOptions );
return self::tag ( 'script', $htmlOptions, "\n/**/\n" );
}
public static function scriptFile($url, array $htmlOptions = array()) {
$defaultHtmlOptions = array (
'type' => 'text/javascript',
'src' => $url
);
$htmlOptions = array_merge ( $defaultHtmlOptions, $htmlOptions );
return self::tag ( 'script', $htmlOptions, '' );
}
public static function form($action = '', $method = 'post', $htmlOptions = array()) {
return self::beginForm ( $action, $method, $htmlOptions );
}
public static function beginForm($action = '', $method = 'post', $htmlOptions = array()) {
$htmlOptions ['action'] = $url = self::normalizeUrl ( $action );
$htmlOptions ['method'] = $method;
$form = self::tag ( 'form', $htmlOptions, false, false );
$hiddens = array ();
if (! strcasecmp ( $method, 'get' ) && ($pos = strpos ( $url, '?' )) !== false) {
foreach ( explode ( '&', substr ( $url, $pos + 1 ) ) as $pair ) {
if (($pos = strpos ( $pair, '=' )) !== false)
$hiddens [] = self::hiddenField ( urldecode ( substr ( $pair, 0, $pos ) ), urldecode ( substr ( $pair, $pos + 1 ) ), array (
'id' => false
) );
else
$hiddens [] = self::hiddenField ( urldecode ( $pair ), '', array (
'id' => false
) );
}
}
$request = Yii::app ()->request;
if ($request->enableCsrfValidation && ! strcasecmp ( $method, 'post' ))
$hiddens [] = self::hiddenField ( $request->csrfTokenName, $request->getCsrfToken (), array (
'id' => false
) );
if ($hiddens !== array ())
$form .= "\n" . self::tag ( 'div', array (
'style' => 'display:none'
), implode ( "\n", $hiddens ) );
return $form;
}
public static function endForm() {
return '';
}
public static function statefulForm($action = '', $method = 'post', $htmlOptions = array()) {
return self::form ( $action, $method, $htmlOptions ) . "\n" . self::tag ( 'div', array (
'style' => 'display:none'
), self::pageStateField ( '' ) );
}
public static function pageStateField($value) {
return '';
}
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 mailto($text, $email = '', $htmlOptions = array()) {
if ($email === '')
$email = $text;
return self::link ( $text, 'mailto:' . $email, $htmlOptions );
}
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'] )) {
if (! array_key_exists ( 'name', $htmlOptions ))
$htmlOptions ['name'] = self::ID_PREFIX . self::$count ++;
}
if (! isset ( $htmlOptions ['type'] ))
$htmlOptions ['type'] = 'button';
if (! isset ( $htmlOptions ['value'] ) && $htmlOptions ['type'] != 'image')
$htmlOptions ['value'] = $label;
self::clientChange ( 'click', $htmlOptions );
return self::tag ( 'input', $htmlOptions );
}
public static function htmlButton($label = 'button', $htmlOptions = array()) {
if (! isset ( $htmlOptions ['name'] ))
$htmlOptions ['name'] = self::ID_PREFIX . self::$count ++;
if (! isset ( $htmlOptions ['type'] ))
$htmlOptions ['type'] = 'button';
self::clientChange ( 'click', $htmlOptions );
return self::tag ( 'button', $htmlOptions, $label );
}
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()) {
if ($for === false)
unset ( $htmlOptions ['for'] );
else
$htmlOptions ['for'] = $for;
if (isset ( $htmlOptions ['required'] )) {
if ($htmlOptions ['required']) {
if (isset ( $htmlOptions ['class'] ))
$htmlOptions ['class'] .= ' ' . self::$requiredCss;
else
$htmlOptions ['class'] = self::$requiredCss;
$label = self::$beforeRequiredLabel . $label . self::$afterRequiredLabel;
}
unset ( $htmlOptions ['required'] );
}
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 numberField($name, $value = '', $htmlOptions = array()) {
self::clientChange ( 'change', $htmlOptions );
return self::inputField ( 'number', $name, $value, $htmlOptions );
}
public static function rangeField($name, $value = '', $htmlOptions = array()) {
self::clientChange ( 'change', $htmlOptions );
return self::inputField ( 'range', $name, $value, $htmlOptions );
}
public static function dateField($name, $value = '', $htmlOptions = array()) {
self::clientChange ( 'change', $htmlOptions );
return self::inputField ( 'date', $name, $value, $htmlOptions );
}
public static function timeField($name, $value = '', $htmlOptions = array()) {
self::clientChange ( 'change', $htmlOptions );
return self::inputField ( 'time', $name, $value, $htmlOptions );
}
public static function emailField($name, $value = '', $htmlOptions = array()) {
self::clientChange ( 'change', $htmlOptions );
return self::inputField ( 'email', $name, $value, $htmlOptions );
}
public static function telField($name, $value = '', $htmlOptions = array()) {
self::clientChange ( 'change', $htmlOptions );
return self::inputField ( 'tel', $name, $value, $htmlOptions );
}
public static function urlField($name, $value = '', $htmlOptions = array()) {
self::clientChange ( 'change', $htmlOptions );
return self::inputField ( 'url', $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 );
elseif ($htmlOptions ['id'] === false)
unset ( $htmlOptions ['id'] );
self::clientChange ( 'change', $htmlOptions );
return self::tag ( 'textarea', $htmlOptions, isset ( $htmlOptions ['encode'] ) && ! $htmlOptions ['encode'] ? $value : 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 );
if (array_key_exists ( 'uncheckValue', $htmlOptions )) {
$uncheck = $htmlOptions ['uncheckValue'];
unset ( $htmlOptions ['uncheckValue'] );
} else
$uncheck = null;
if ($uncheck !== null) {
// add a hidden field so that if the radio button is not selected, it still submits a value
if (isset ( $htmlOptions ['id'] ) && $htmlOptions ['id'] !== false)
$uncheckOptions = array (
'id' => self::ID_PREFIX . $htmlOptions ['id']
);
else
$uncheckOptions = array (
'id' => false
);
$hidden = self::hiddenField ( $name, $uncheck, $uncheckOptions );
} else
$hidden = '';
// add a hidden field so that if the radio button is not selected, it still submits a value
return $hidden . 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 );
if (array_key_exists ( 'uncheckValue', $htmlOptions )) {
$uncheck = $htmlOptions ['uncheckValue'];
unset ( $htmlOptions ['uncheckValue'] );
} else
$uncheck = null;
if ($uncheck !== null) {
// add a hidden field so that if the check box is not checked, it still submits a value
if (isset ( $htmlOptions ['id'] ) && $htmlOptions ['id'] !== false)
$uncheckOptions = array (
'id' => self::ID_PREFIX . $htmlOptions ['id']
);
else
$uncheckOptions = array (
'id' => false
);
$hidden = self::hiddenField ( $name, $uncheck, $uncheckOptions );
} else
$hidden = '';
// add a hidden field so that if the check box is not checked, it still submits a value
return $hidden . 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 );
elseif ($htmlOptions ['id'] === false)
unset ( $htmlOptions ['id'] );
self::clientChange ( 'change', $htmlOptions );
$options = "\n" . self::listOptions ( $select, $data, $htmlOptions );
$hidden = '';
if (! empty ( $htmlOptions ['multiple'] )) {
if (substr ( $htmlOptions ['name'], - 2 ) !== '[]')
$htmlOptions ['name'] .= '[]';
if (isset ( $htmlOptions ['unselectValue'] )) {
$hiddenOptions = isset ( $htmlOptions ['id'] ) ? array (
'id' => self::ID_PREFIX . $htmlOptions ['id']
) : array (
'id' => false
);
$hidden = self::hiddenField ( substr ( $htmlOptions ['name'], 0, - 2 ), $htmlOptions ['unselectValue'], $hiddenOptions );
unset ( $htmlOptions ['unselectValue'] );
}
}
// add a hidden field so that if the option is not selected, it still submits a value
return $hidden . self::tag ( 'select', $htmlOptions, $options );
}
public static function listBox($name, $select, $data, $htmlOptions = array()) {
if (! isset ( $htmlOptions ['size'] ))
$htmlOptions ['size'] = 4;
if (! empty ( $htmlOptions ['multiple'] )) {
if (substr ( $name, - 2 ) !== '[]')
$name .= '[]';
}
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'] : "
\n";
$container = isset ( $htmlOptions ['container'] ) ? $htmlOptions ['container'] : 'span';
unset ( $htmlOptions ['template'], $htmlOptions ['separator'], $htmlOptions ['container'] );
if (substr ( $name, - 2 ) !== '[]')
$name .= '[]';
if (isset ( $htmlOptions ['checkAll'] )) {
$checkAllLabel = $htmlOptions ['checkAll'];
$checkAllLast = isset ( $htmlOptions ['checkAllLast'] ) && $htmlOptions ['checkAllLast'];
}
unset ( $htmlOptions ['checkAll'], $htmlOptions ['checkAllLast'] );
$labelOptions = isset ( $htmlOptions ['labelOptions'] ) ? $htmlOptions ['labelOptions'] : array ();
unset ( $htmlOptions ['labelOptions'] );
$items = array ();
$baseID = isset ( $htmlOptions ['baseID'] ) ? $htmlOptions ['baseID'] : self::getIdByName ( $name );
unset ( $htmlOptions ['baseID'] );
$id = 0;
$checkAll = true;
foreach ( $data as $value => $labelTitle ) {
$checked = ! is_array ( $select ) && ! strcmp ( $value, $select ) || is_array ( $select ) && in_array ( $value, $select );
$checkAll = $checkAll && $checked;
$htmlOptions ['value'] = $value;
$htmlOptions ['id'] = $baseID . '_' . $id ++;
$option = self::checkBox ( $name, $checked, $htmlOptions );
$beginLabel = self::openTag ( 'label', $labelOptions );
$label = self::label ( $labelTitle, $htmlOptions ['id'], $labelOptions );
$endLabel = self::closeTag ( 'label' );
$items [] = strtr ( $template, array (
'{input}' => $option,
'{beginLabel}' => $beginLabel,
'{label}' => $label,
'{labelTitle}' => $labelTitle,
'{endLabel}' => $endLabel
) );
}
if (isset ( $checkAllLabel )) {
$htmlOptions ['value'] = 1;
$htmlOptions ['id'] = $id = $baseID . '_all';
$option = self::checkBox ( $id, $checkAll, $htmlOptions );
$beginLabel = self::openTag ( 'label', $labelOptions );
$label = self::label ( $checkAllLabel, $id, $labelOptions );
$endLabel = self::closeTag ( 'label' );
$item = strtr ( $template, array (
'{input}' => $option,
'{beginLabel}' => $beginLabel,
'{label}' => $label,
'{labelTitle}' => $checkAllLabel,
'{endLabel}' => $endLabel
) );
if ($checkAllLast)
$items [] = $item;
else
array_unshift ( $items, $item );
$name = strtr ( $name, array (
'[' => '\\[',
']' => '\\]'
) );
$js = <<getClientScript ();
$cs->registerCoreScript ( 'jquery' );
$cs->registerScript ( $id, $js );
}
if (empty ( $container ))
return implode ( $separator, $items );
else
return self::tag ( $container, array (
'id' => $baseID
), 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'] : "
\n";
$container = isset ( $htmlOptions ['container'] ) ? $htmlOptions ['container'] : 'span';
unset ( $htmlOptions ['template'], $htmlOptions ['separator'], $htmlOptions ['container'] );
$labelOptions = isset ( $htmlOptions ['labelOptions'] ) ? $htmlOptions ['labelOptions'] : array ();
unset ( $htmlOptions ['labelOptions'] );
if (isset ( $htmlOptions ['empty'] )) {
if (! is_array ( $htmlOptions ['empty'] ))
$htmlOptions ['empty'] = array (
'' => $htmlOptions ['empty']
);
$data = array_merge ( $htmlOptions ['empty'], $data );
unset ( $htmlOptions ['empty'] );
}
$items = array ();
$baseID = isset ( $htmlOptions ['baseID'] ) ? $htmlOptions ['baseID'] : self::getIdByName ( $name );
unset ( $htmlOptions ['baseID'] );
$id = 0;
foreach ( $data as $value => $labelTitle ) {
$checked = ! strcmp ( $value, $select );
$htmlOptions ['value'] = $value;
$htmlOptions ['id'] = $baseID . '_' . $id ++;
$option = self::radioButton ( $name, $checked, $htmlOptions );
$beginLabel = self::openTag ( 'label', $labelOptions );
$label = self::label ( $labelTitle, $htmlOptions ['id'], $labelOptions );
$endLabel = self::closeTag ( 'label' );
$items [] = strtr ( $template, array (
'{input}' => $option,
'{beginLabel}' => $beginLabel,
'{label}' => $label,
'{labelTitle}' => $labelTitle,
'{endLabel}' => $endLabel
) );
}
if (empty ( $container ))
return implode ( $separator, $items );
else
return self::tag ( $container, array (
'id' => $baseID
), 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';
$htmlOptions ['type'] = 'submit';
return self::ajaxButton ( $label, $url, $ajaxOptions, $htmlOptions );
}
public static function ajax($options) {
Yii::app ()->getClientScript ()->registerCoreScript ( 'jquery' );
if (! isset ( $options ['url'] ))
$options ['url'] = new CJavaScriptExpression ( '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'] = new CJavaScriptExpression ( 'jQuery(this).parents("form").serialize()' );
foreach ( array (
'beforeSend',
'complete',
'error',
'success'
) as $name ) {
if (isset ( $options [$name] ) && ! ($options [$name] instanceof CJavaScriptExpression))
$options [$name] = new CJavaScriptExpression ( $options [$name] );
}
if (isset ( $options ['update'] )) {
if (! isset ( $options ['success'] ))
$options ['success'] = new CJavaScriptExpression ( 'function(html){jQuery("' . $options ['update'] . '").html(html)}' );
unset ( $options ['update'] );
}
if (isset ( $options ['replace'] )) {
if (! isset ( $options ['success'] ))
$options ['success'] = new CJavaScriptExpression ( '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 normalizeUrl($url) {
if (is_array ( $url )) {
if (isset ( $url [0] )) {
if (($c = Yii::app ()->getController ()) !== null)
$url = $c->createUrl ( $url [0], array_splice ( $url, 1 ) );
else
$url = Yii::app ()->createUrl ( $url [0], array_splice ( $url, 1 ) );
} else
$url = '';
}
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 );
elseif ($htmlOptions ['id'] === false)
unset ( $htmlOptions ['id'] );
return self::tag ( 'input', $htmlOptions );
}
public static function activeLabel($model, $attribute, $htmlOptions = array()) {
$inputName = self::resolveName ( $model, $attribute );
if (isset ( $htmlOptions ['for'] )) {
$for = $htmlOptions ['for'];
unset ( $htmlOptions ['for'] );
} else
$for = self::getIdByName ( $inputName );
if (isset ( $htmlOptions ['label'] )) {
if (($label = $htmlOptions ['label']) === false)
return '';
unset ( $htmlOptions ['label'] );
} else
$label = $model->getAttributeLabel ( $attribute );
if ($model->hasErrors ( $attribute ))
self::addErrorCss ( $htmlOptions );
return self::label ( $label, $for, $htmlOptions );
}
public static function activeLabelEx($model, $attribute, $htmlOptions = array()) {
$realAttribute = $attribute;
self::resolveName ( $model, $attribute ); // strip off square brackets if any
$htmlOptions ['required'] = $model->isAttributeRequired ( $attribute );
return self::activeLabel ( $model, $realAttribute, $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 activeSearchField($model, $attribute, $htmlOptions = array()) {
self::resolveNameID ( $model, $attribute, $htmlOptions );
self::clientChange ( 'change', $htmlOptions );
return self::activeInputField ( 'search', $model, $attribute, $htmlOptions );
}
public static function activeUrlField($model, $attribute, $htmlOptions = array()) {
self::resolveNameID ( $model, $attribute, $htmlOptions );
self::clientChange ( 'change', $htmlOptions );
return self::activeInputField ( 'url', $model, $attribute, $htmlOptions );
}
public static function activeEmailField($model, $attribute, $htmlOptions = array()) {
self::resolveNameID ( $model, $attribute, $htmlOptions );
self::clientChange ( 'change', $htmlOptions );
return self::activeInputField ( 'email', $model, $attribute, $htmlOptions );
}
public static function activeNumberField($model, $attribute, $htmlOptions = array()) {
self::resolveNameID ( $model, $attribute, $htmlOptions );
self::clientChange ( 'change', $htmlOptions );
return self::activeInputField ( 'number', $model, $attribute, $htmlOptions );
}
public static function activeRangeField($model, $attribute, $htmlOptions = array()) {
self::resolveNameID ( $model, $attribute, $htmlOptions );
self::clientChange ( 'change', $htmlOptions );
return self::activeInputField ( 'range', $model, $attribute, $htmlOptions );
}
public static function activeDateField($model, $attribute, $htmlOptions = array()) {
self::resolveNameID ( $model, $attribute, $htmlOptions );
self::clientChange ( 'change', $htmlOptions );
return self::activeInputField ( 'date', $model, $attribute, $htmlOptions );
}
public static function activeTimeField($model, $attribute, $htmlOptions = array()) {
self::resolveNameID ( $model, $attribute, $htmlOptions );
self::clientChange ( 'change', $htmlOptions );
return self::activeInputField ( 'time', $model, $attribute, $htmlOptions );
}
public static function activeTelField($model, $attribute, $htmlOptions = array()) {
self::resolveNameID ( $model, $attribute, $htmlOptions );
self::clientChange ( 'change', $htmlOptions );
return self::activeInputField ( 'tel', $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 );
if (isset ( $htmlOptions ['value'] )) {
$text = $htmlOptions ['value'];
unset ( $htmlOptions ['value'] );
} else
$text = self::resolveValue ( $model, $attribute );
return self::tag ( 'textarea', $htmlOptions, isset ( $htmlOptions ['encode'] ) && ! $htmlOptions ['encode'] ? $text : self::encode ( $text ) );
}
public static function activeFileField($model, $attribute, $htmlOptions = array()) {
self::resolveNameID ( $model, $attribute, $htmlOptions );
// add a hidden field so that if a model only has a file field, we can
// still use isset($_POST[$modelClass]) to detect if the input is submitted
$hiddenOptions = isset ( $htmlOptions ['id'] ) ? array (
'id' => self::ID_PREFIX . $htmlOptions ['id']
) : array (
'id' => false
);
return self::hiddenField ( $htmlOptions ['name'], '', $hiddenOptions ) . 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 (! isset ( $htmlOptions ['checked'] ) && self::resolveValue ( $model, $attribute ) == $htmlOptions ['value'])
$htmlOptions ['checked'] = 'checked';
self::clientChange ( 'click', $htmlOptions );
if (array_key_exists ( 'uncheckValue', $htmlOptions )) {
$uncheck = $htmlOptions ['uncheckValue'];
unset ( $htmlOptions ['uncheckValue'] );
} else
$uncheck = '0';
$hiddenOptions = isset ( $htmlOptions ['id'] ) ? array (
'id' => self::ID_PREFIX . $htmlOptions ['id']
) : array (
'id' => false
);
$hidden = $uncheck !== null ? self::hiddenField ( $htmlOptions ['name'], $uncheck, $hiddenOptions ) : '';
// add a hidden field so that if the radio button is not selected, it still submits a value
return $hidden . 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 (! isset ( $htmlOptions ['checked'] ) && self::resolveValue ( $model, $attribute ) == $htmlOptions ['value'])
$htmlOptions ['checked'] = 'checked';
self::clientChange ( 'click', $htmlOptions );
if (array_key_exists ( 'uncheckValue', $htmlOptions )) {
$uncheck = $htmlOptions ['uncheckValue'];
unset ( $htmlOptions ['uncheckValue'] );
} else
$uncheck = '0';
$hiddenOptions = isset ( $htmlOptions ['id'] ) ? array (
'id' => self::ID_PREFIX . $htmlOptions ['id']
) : array (
'id' => false
);
$hidden = $uncheck !== null ? self::hiddenField ( $htmlOptions ['name'], $uncheck, $hiddenOptions ) : '';
return $hidden . self::activeInputField ( 'checkbox', $model, $attribute, $htmlOptions );
}
public static function activeDropDownList($model, $attribute, $data, $htmlOptions = array()) {
self::resolveNameID ( $model, $attribute, $htmlOptions );
$selection = self::resolveValue ( $model, $attribute );
$options = "\n" . self::listOptions ( $selection, $data, $htmlOptions );
self::clientChange ( 'change', $htmlOptions );
if ($model->hasErrors ( $attribute ))
self::addErrorCss ( $htmlOptions );
$hidden = '';
if (! empty ( $htmlOptions ['multiple'] )) {
if (substr ( $htmlOptions ['name'], - 2 ) !== '[]')
$htmlOptions ['name'] .= '[]';
if (isset ( $htmlOptions ['unselectValue'] )) {
$hiddenOptions = isset ( $htmlOptions ['id'] ) ? array (
'id' => self::ID_PREFIX . $htmlOptions ['id']
) : array (
'id' => false
);
$hidden = self::hiddenField ( substr ( $htmlOptions ['name'], 0, - 2 ), $htmlOptions ['unselectValue'], $hiddenOptions );
unset ( $htmlOptions ['unselectValue'] );
}
}
return $hidden . 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 = self::resolveValue ( $model, $attribute );
if ($model->hasErrors ( $attribute ))
self::addErrorCss ( $htmlOptions );
$name = $htmlOptions ['name'];
unset ( $htmlOptions ['name'] );
if (array_key_exists ( 'uncheckValue', $htmlOptions )) {
$uncheck = $htmlOptions ['uncheckValue'];
unset ( $htmlOptions ['uncheckValue'] );
} else
$uncheck = '';
$hiddenOptions = isset ( $htmlOptions ['id'] ) ? array (
'id' => self::ID_PREFIX . $htmlOptions ['id']
) : array (
'id' => false
);
$hidden = $uncheck !== null ? self::hiddenField ( $name, $uncheck, $hiddenOptions ) : '';
return $hidden . self::checkBoxList ( $name, $selection, $data, $htmlOptions );
}
public static function activeRadioButtonList($model, $attribute, $data, $htmlOptions = array()) {
self::resolveNameID ( $model, $attribute, $htmlOptions );
$selection = self::resolveValue ( $model, $attribute );
if ($model->hasErrors ( $attribute ))
self::addErrorCss ( $htmlOptions );
$name = $htmlOptions ['name'];
unset ( $htmlOptions ['name'] );
if (array_key_exists ( 'uncheckValue', $htmlOptions )) {
$uncheck = $htmlOptions ['uncheckValue'];
unset ( $htmlOptions ['uncheckValue'] );
} else
$uncheck = '';
$hiddenOptions = isset ( $htmlOptions ['id'] ) ? array (
'id' => self::ID_PREFIX . $htmlOptions ['id']
) : array (
'id' => false
);
$hidden = $uncheck !== null ? self::hiddenField ( $name, $uncheck, $hiddenOptions ) : '';
return $hidden . self::radioButtonList ( $name, $selection, $data, $htmlOptions );
}
public static function errorSummary($model, $header = null, $footer = null, $htmlOptions = array()) {
$content = '';
if (! is_array ( $model ))
$model = array (
$model
);
if (isset ( $htmlOptions ['firstError'] )) {
$firstError = $htmlOptions ['firstError'];
unset ( $htmlOptions ['firstError'] );
} else
$firstError = false;
foreach ( $model as $m ) {
foreach ( $m->getErrors () as $errors ) {
foreach ( $errors as $error ) {
if ($error != '')
$content .= "$error\n";
if ($firstError)
break;
}
}
}
if ($content !== '') {
if ($header === null)
$header = '' . Yii::t ( 'yii', 'Please fix the following input errors:' ) . '
';
if (! isset ( $htmlOptions ['class'] ))
$htmlOptions ['class'] = self::$errorSummaryCss;
return self::tag ( 'div', $htmlOptions, $header . "\n" . $footer );
} else
return '';
}
public static function error($model, $attribute, $htmlOptions = array()) {
self::resolveName ( $model, $attribute ); // turn [a][b]attr into attr
$error = $model->getError ( $attribute );
if ($error != '') {
if (! isset ( $htmlOptions ['class'] ))
$htmlOptions ['class'] = self::$errorMessageCss;
return self::tag ( self::$errorContainerTag, $htmlOptions, $error );
} else
return '';
}
public static function listData($models, $valueField, $textField, $groupField = '') {
$listData = array ();
if ($groupField === '') {
foreach ( $models as $model ) {
$value = self::value ( $model, $valueField );
$text = self::value ( $model, $textField );
$listData [$value] = $text;
}
} else {
foreach ( $models as $model ) {
$group = self::value ( $model, $groupField );
$value = self::value ( $model, $valueField );
$text = self::value ( $model, $textField );
if ($group === null)
$listData [$value] = $text;
else
$listData [$group] [$value] = $text;
}
}
return $listData;
}
public static function value($model, $attribute, $defaultValue = null) {
if (is_scalar ( $attribute ) || $attribute === null)
foreach ( explode ( '.', $attribute ) as $name ) {
if (is_object ( $model ) && isset ( $model->$name ))
$model = $model->$name;
elseif (is_array ( $model ) && isset ( $model [$name] ))
$model = $model [$name];
else
return $defaultValue;
}
else
return call_user_func ( $attribute, $model );
return $model;
}
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 modelName($model) {
if (is_callable ( self::$_modelNameConverter ))
return call_user_func ( self::$_modelNameConverter, $model );
$className = is_object ( $model ) ? get_class ( $model ) : ( string ) $model;
return trim ( str_replace ( '\\', '_', $className ), '_' );
}
public static function setModelNameConverter($converter) {
if (is_callable ( $converter ))
self::$_modelNameConverter = $converter;
elseif ($converter === null)
self::$_modelNameConverter = null;
else
throw new CException ( Yii::t ( 'yii', 'The $converter argument must be a valid callback or null.' ) );
}
public static function activeName($model, $attribute) {
$a = $attribute; // because the attribute name may be changed by resolveName
return self::resolveName ( $model, $a );
}
protected static function activeInputField($type, $model, $attribute, $htmlOptions) {
$htmlOptions ['type'] = $type;
if ($type === 'text' || $type === 'password') {
if (! isset ( $htmlOptions ['maxlength'] )) {
foreach ( $model->getValidators ( $attribute ) as $validator ) {
if ($validator instanceof CStringValidator && $validator->max !== null) {
$htmlOptions ['maxlength'] = $validator->max;
break;
}
}
} elseif ($htmlOptions ['maxlength'] === false)
unset ( $htmlOptions ['maxlength'] );
}
if ($type === 'file')
unset ( $htmlOptions ['value'] );
elseif (! isset ( $htmlOptions ['value'] ))
$htmlOptions ['value'] = self::resolveValue ( $model, $attribute );
if ($model->hasErrors ( $attribute ))
self::addErrorCss ( $htmlOptions );
return self::tag ( 'input', $htmlOptions );
}
public static function listOptions($selection, $listData, &$htmlOptions) {
$raw = isset ( $htmlOptions ['encode'] ) && ! $htmlOptions ['encode'];
$content = '';
if (isset ( $htmlOptions ['prompt'] )) {
$content .= '\n";
unset ( $htmlOptions ['prompt'] );
}
if (isset ( $htmlOptions ['empty'] )) {
if (! is_array ( $htmlOptions ['empty'] ))
$htmlOptions ['empty'] = array (
'' => $htmlOptions ['empty']
);
foreach ( $htmlOptions ['empty'] as $value => $label )
$content .= '\n";
unset ( $htmlOptions ['empty'] );
}
if (isset ( $htmlOptions ['options'] )) {
$options = $htmlOptions ['options'];
unset ( $htmlOptions ['options'] );
} else
$options = array ();
$key = isset ( $htmlOptions ['key'] ) ? $htmlOptions ['key'] : 'primaryKey';
if (is_array ( $selection )) {
foreach ( $selection as $i => $item ) {
if (is_object ( $item ))
$selection [$i] = $item->$key;
}
} elseif (is_object ( $selection ))
$selection = $selection->$key;
foreach ( $listData as $key => $value ) {
if (is_array ( $value )) {
$content .= '' . "\n";
} else {
$attributes = array (
'value' => ( string ) $key,
'encode' => ! $raw
);
if (! is_array ( $selection ) && ! strcmp ( $key, $selection ) || is_array ( $selection ) && in_array ( $key, $selection ))
$attributes ['selected'] = 'selected';
if (isset ( $options [$key] ))
$attributes = array_merge ( $attributes, $options [$key] );
$content .= self::tag ( 'option', $attributes, $raw ? ( string ) $value : self::encode ( ( string ) $value ) ) . "\n";
}
}
unset ( $htmlOptions ['key'] );
return $content;
}
protected static function clientChange($event, &$htmlOptions) {
if (! isset ( $htmlOptions ['submit'] ) && ! isset ( $htmlOptions ['confirm'] ) && ! isset ( $htmlOptions ['ajax'] ))
return;
if (isset ( $htmlOptions ['live'] )) {
$live = $htmlOptions ['live'];
unset ( $htmlOptions ['live'] );
} else
$live = self::$liveEvents;
if (isset ( $htmlOptions ['return'] ) && $htmlOptions ['return'])
$return = 'return true';
else
$return = 'return false';
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 ['submit'] )) {
$cs->registerCoreScript ( 'yii' );
$request = Yii::app ()->getRequest ();
if ($request->enableCsrfValidation && isset ( $htmlOptions ['csrf'] ) && $htmlOptions ['csrf'])
$htmlOptions ['params'] [$request->csrfTokenName] = $request->getCsrfToken ();
if (isset ( $htmlOptions ['params'] ))
$params = CJavaScript::encode ( $htmlOptions ['params'] );
else
$params = '{}';
if ($htmlOptions ['submit'] !== '')
$url = CJavaScript::quote ( self::normalizeUrl ( $htmlOptions ['submit'] ) );
else
$url = '';
$handler .= "jQuery.yii.submitForm(this,'$url',$params);{$return};";
}
if (isset ( $htmlOptions ['ajax'] ))
$handler .= self::ajax ( $htmlOptions ['ajax'] ) . "{$return};";
if (isset ( $htmlOptions ['confirm'] )) {
$confirm = 'confirm(\'' . CJavaScript::quote ( $htmlOptions ['confirm'] ) . '\')';
if ($handler !== '')
$handler = "if($confirm) {" . $handler . "} else return false;";
else
$handler = "return $confirm;";
}
if ($live)
$cs->registerScript ( 'Yii.CHtml.#' . $id, "jQuery('body').on('$event','#$id',function(){{$handler}});" );
else
$cs->registerScript ( 'Yii.CHtml.#' . $id, "jQuery('#$id').on('$event', function(){{$handler}});" );
unset ( $htmlOptions ['params'], $htmlOptions ['submit'], $htmlOptions ['ajax'], $htmlOptions ['confirm'], $htmlOptions ['return'], $htmlOptions ['csrf'] );
}
public static function resolveNameID($model, &$attribute, &$htmlOptions) {
if (! isset ( $htmlOptions ['name'] ))
$htmlOptions ['name'] = self::resolveName ( $model, $attribute );
if (! isset ( $htmlOptions ['id'] ))
$htmlOptions ['id'] = self::getIdByName ( $htmlOptions ['name'] );
elseif ($htmlOptions ['id'] === false)
unset ( $htmlOptions ['id'] );
}
public static function resolveName($model, &$attribute) {
$modelName = self::modelName ( $model );
if (($pos = strpos ( $attribute, '[' )) !== false) {
if ($pos !== 0) // e.g. name[a][b]
return $modelName . '[' . substr ( $attribute, 0, $pos ) . ']' . substr ( $attribute, $pos );
if (($pos = strrpos ( $attribute, ']' )) !== false && $pos !== strlen ( $attribute ) - 1) // e.g. [a][b]name
{
$sub = substr ( $attribute, 0, $pos + 1 );
$attribute = substr ( $attribute, $pos + 1 );
return $modelName . $sub . '[' . $attribute . ']';
}
if (preg_match ( '/\](\w+\[.*)$/', $attribute, $matches )) {
$name = $modelName . '[' . str_replace ( ']', '][', trim ( strtr ( $attribute, array (
'][' => ']',
'[' => ']'
) ), ']' ) ) . ']';
$attribute = $matches [1];
return $name;
}
}
return $modelName . '[' . $attribute . ']';
}
public static function resolveValue($model, $attribute) {
if (($pos = strpos ( $attribute, '[' )) !== false) {
if ($pos === 0) // [a]name[b][c], should ignore [a]
{
if (preg_match ( '/\](\w+(\[.+)?)/', $attribute, $matches ))
$attribute = $matches [1]; // we get: name[b][c]
if (($pos = strpos ( $attribute, '[' )) === false)
return $model->$attribute;
}
$name = substr ( $attribute, 0, $pos );
$value = $model->$name;
foreach ( explode ( '][', rtrim ( substr ( $attribute, $pos + 1 ), ']' ) ) as $id ) {
if ((is_array ( $value ) || $value instanceof ArrayAccess) && isset ( $value [$id] ))
$value = $value [$id];
else
return null;
}
return $value;
} else
return $model->$attribute;
}
protected static function addErrorCss(&$htmlOptions) {
if (empty ( self::$errorCss ))
return;
if (isset ( $htmlOptions ['class'] ))
$htmlOptions ['class'] .= ' ' . self::$errorCss;
else
$htmlOptions ['class'] = self::$errorCss;
}
public static function renderAttributes($htmlOptions) {
static $specialAttributes = array (
'async' => 1,
'autofocus' => 1,
'autoplay' => 1,
'checked' => 1,
'controls' => 1,
'declare' => 1,
'default' => 1,
'defer' => 1,
'disabled' => 1,
'formnovalidate' => 1,
'hidden' => 1,
'ismap' => 1,
'loop' => 1,
'multiple' => 1,
'muted' => 1,
'nohref' => 1,
'noresize' => 1,
'novalidate' => 1,
'open' => 1,
'readonly' => 1,
'required' => 1,
'reversed' => 1,
'scoped' => 1,
'seamless' => 1,
'selected' => 1,
'typemustmatch' => 1
);
if ($htmlOptions === array ())
return '';
$html = '';
if (isset ( $htmlOptions ['encode'] )) {
$raw = ! $htmlOptions ['encode'];
unset ( $htmlOptions ['encode'] );
} else
$raw = false;
foreach ( $htmlOptions as $name => $value ) {
if (isset ( $specialAttributes [$name] )) {
if ($value) {
$html .= ' ' . $name;
if (self::$renderSpecialAttributesValue)
$html .= '="' . $name . '"';
}
} elseif ($value !== null)
$html .= ' ' . $name . '="' . ($raw ? $value : self::encode ( $value )) . '"';
}
return $html;
}
}
class CWidgetFactory extends CApplicationComponent implements IWidgetFactory {
public $enableSkin = false;
public $widgets = array ();
public $skinnableWidgets;
public $skinPath;
private $_skins = array (); // class name, skin name, property name => value
public function init() {
parent::init ();
if ($this->enableSkin && $this->skinPath === null)
$this->skinPath = Yii::app ()->getViewPath () . DIRECTORY_SEPARATOR . 'skins';
}
public function createWidget($owner, $className, $properties = array()) {
$className = Yii::import ( $className, true );
$widget = new $className ( $owner );
if (isset ( $this->widgets [$className] ))
$properties = $properties === array () ? $this->widgets [$className] : CMap::mergeArray ( $this->widgets [$className], $properties );
if ($this->enableSkin) {
if ($this->skinnableWidgets === null || in_array ( $className, $this->skinnableWidgets )) {
$skinName = isset ( $properties ['skin'] ) ? $properties ['skin'] : 'default';
if ($skinName !== false && ($skin = $this->getSkin ( $className, $skinName )) !== array ())
$properties = $properties === array () ? $skin : CMap::mergeArray ( $skin, $properties );
}
}
foreach ( $properties as $name => $value )
$widget->$name = $value;
return $widget;
}
protected function getSkin($className, $skinName) {
if (! isset ( $this->_skins [$className] [$skinName] )) {
$skinFile = $this->skinPath . DIRECTORY_SEPARATOR . $className . '.php';
if (is_file ( $skinFile ))
$this->_skins [$className] = require ($skinFile);
else
$this->_skins [$className] = array ();
if (($theme = Yii::app ()->getTheme ()) !== null) {
$skinFile = $theme->getSkinPath () . DIRECTORY_SEPARATOR . $className . '.php';
if (is_file ( $skinFile )) {
$skins = require ($skinFile);
foreach ( $skins as $name => $skin )
$this->_skins [$className] [$name] = $skin;
}
}
if (! isset ( $this->_skins [$className] [$skinName] ))
$this->_skins [$className] [$skinName] = array ();
}
return $this->_skins [$className] [$skinName];
}
}
class CWidget extends CBaseController {
public $actionPrefix;
public $skin = 'default';
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;
elseif ($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($checkTheme = false) {
$className = get_class ( $this );
$scope = $checkTheme ? 'theme' : 'local';
if (isset ( self::$_viewPaths [$className] [$scope] ))
return self::$_viewPaths [$className] [$scope];
else {
if ($checkTheme && ($theme = Yii::app ()->getTheme ()) !== null) {
$path = $theme->getViewPath () . DIRECTORY_SEPARATOR;
if (strpos ( $className, '\\' ) !== false) // namespaced class
$path .= str_replace ( '\\', '_', ltrim ( $className, '\\' ) );
else
$path .= $className;
if (is_dir ( $path ))
return self::$_viewPaths [$className] ['theme'] = $path;
}
$class = new ReflectionClass ( $className );
return self::$_viewPaths [$className] ['local'] = dirname ( $class->getFileName () ) . DIRECTORY_SEPARATOR . 'views';
}
}
public function getViewFile($viewName) {
if (($renderer = Yii::app ()->getViewRenderer ()) !== null)
$extension = $renderer->fileExtension;
else
$extension = '.php';
if (strpos ( $viewName, '.' )) // a path alias
$viewFile = Yii::getPathOfAlias ( $viewName );
else {
$viewFile = $this->getViewPath ( true ) . DIRECTORY_SEPARATOR . $viewName;
if (is_file ( $viewFile . $extension ))
return Yii::app ()->findLocalizedFile ( $viewFile . $extension );
elseif ($extension !== '.php' && is_file ( $viewFile . '.php' ))
return Yii::app ()->findLocalizedFile ( $viewFile . '.php' );
$viewFile = $this->getViewPath ( false ) . DIRECTORY_SEPARATOR . $viewName;
}
if (is_file ( $viewFile . $extension ))
return Yii::app ()->findLocalizedFile ( $viewFile . $extension );
elseif ($extension !== '.php' && is_file ( $viewFile . '.php' ))
return Yii::app ()->findLocalizedFile ( $viewFile . '.php' );
else
return 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;
public $scriptMap = array ();
public $packages = array ();
public $corePackages;
public $scripts = array ();
protected $cssFiles = array ();
protected $scriptFiles = array ();
protected $metaTags = array ();
protected $linkTags = array ();
protected $css = array ();
protected $hasScripts = false;
protected $coreScripts = array ();
public $coreScriptPosition = self::POS_HEAD;
public $defaultScriptFilePosition = self::POS_HEAD;
public $defaultScriptPosition = self::POS_READY;
private $_baseUrl;
public function reset() {
$this->hasScripts = false;
$this->coreScripts = array ();
$this->cssFiles = array ();
$this->css = array ();
$this->scriptFiles = array ();
$this->scripts = array ();
$this->metaTags = array ();
$this->linkTags = array ();
$this->recordCachingAction ( 'clientScript', 'reset', array () );
}
public function render(&$output) {
if (! $this->hasScripts)
return;
$this->renderCoreScripts ();
if (! empty ( $this->scriptMap ))
$this->remapScripts ();
$this->unifyScripts ();
$this->renderHead ( $output );
if ($this->enableJavaScript) {
$this->renderBodyBegin ( $output );
$this->renderBodyEnd ( $output );
}
}
protected function unifyScripts() {
if (! $this->enableJavaScript)
return;
$map = array ();
if (isset ( $this->scriptFiles [self::POS_HEAD] ))
$map = $this->scriptFiles [self::POS_HEAD];
if (isset ( $this->scriptFiles [self::POS_BEGIN] )) {
foreach ( $this->scriptFiles [self::POS_BEGIN] as $scriptFile => $scriptFileValue ) {
if (isset ( $map [$scriptFile] ))
unset ( $this->scriptFiles [self::POS_BEGIN] [$scriptFile] );
else
$map [$scriptFile] = true;
}
}
if (isset ( $this->scriptFiles [self::POS_END] )) {
foreach ( $this->scriptFiles [self::POS_END] as $key => $scriptFile ) {
if (isset ( $map [$key] ))
unset ( $this->scriptFiles [self::POS_END] [$key] );
}
}
}
protected function remapScripts() {
$cssFiles = array ();
foreach ( $this->cssFiles as $url => $media ) {
$name = basename ( $url );
if (isset ( $this->scriptMap [$name] )) {
if ($this->scriptMap [$name] !== false)
$cssFiles [$this->scriptMap [$name]] = $media;
} elseif (isset ( $this->scriptMap ['*.css'] )) {
if ($this->scriptMap ['*.css'] !== false)
$cssFiles [$this->scriptMap ['*.css']] = $media;
} else
$cssFiles [$url] = $media;
}
$this->cssFiles = $cssFiles;
$jsFiles = array ();
foreach ( $this->scriptFiles as $position => $scriptFiles ) {
$jsFiles [$position] = array ();
foreach ( $scriptFiles as $scriptFile => $scriptFileValue ) {
$name = basename ( $scriptFile );
if (isset ( $this->scriptMap [$name] )) {
if ($this->scriptMap [$name] !== false)
$jsFiles [$position] [$this->scriptMap [$name]] = $this->scriptMap [$name];
} elseif (isset ( $this->scriptMap ['*.js'] )) {
if ($this->scriptMap ['*.js'] !== false)
$jsFiles [$position] [$this->scriptMap ['*.js']] = $this->scriptMap ['*.js'];
} else
$jsFiles [$position] [$scriptFile] = $scriptFileValue;
}
}
$this->scriptFiles = $jsFiles;
}
protected function renderScriptBatch(array $scripts) {
$html = '';
$scriptBatches = array ();
foreach ( $scripts as $scriptValue ) {
if (is_array ( $scriptValue )) {
$scriptContent = $scriptValue ['content'];
unset ( $scriptValue ['content'] );
$scriptHtmlOptions = $scriptValue;
} else {
$scriptContent = $scriptValue;
$scriptHtmlOptions = array ();
}
$key = serialize ( ksort ( $scriptHtmlOptions ) );
$scriptBatches [$key] ['htmlOptions'] = $scriptHtmlOptions;
$scriptBatches [$key] ['scripts'] [] = $scriptContent;
}
foreach ( $scriptBatches as $scriptBatch )
if (! empty ( $scriptBatch ['scripts'] ))
$html .= CHtml::script ( implode ( "\n", $scriptBatch ['scripts'] ), $scriptBatch ['htmlOptions'] ) . "\n";
return $html;
}
public function renderCoreScripts() {
if ($this->coreScripts === null)
return;
$cssFiles = array ();
$jsFiles = array ();
foreach ( $this->coreScripts as $name => $package ) {
$baseUrl = $this->getPackageBaseUrl ( $name );
if (! empty ( $package ['js'] )) {
foreach ( $package ['js'] as $js )
$jsFiles [$baseUrl . '/' . $js] = $baseUrl . '/' . $js;
}
if (! empty ( $package ['css'] )) {
foreach ( $package ['css'] as $css )
$cssFiles [$baseUrl . '/' . $css] = '';
}
}
// merge in place
if ($cssFiles !== array ()) {
foreach ( $this->cssFiles as $cssFile => $media )
$cssFiles [$cssFile] = $media;
$this->cssFiles = $cssFiles;
}
if ($jsFiles !== array ()) {
if (isset ( $this->scriptFiles [$this->coreScriptPosition] )) {
foreach ( $this->scriptFiles [$this->coreScriptPosition] as $url => $value )
$jsFiles [$url] = $value;
}
$this->scriptFiles [$this->coreScriptPosition] = $jsFiles;
}
}
public function renderHead(&$output) {
$html = '';
foreach ( $this->metaTags as $meta )
$html .= CHtml::metaTag ( $meta ['content'], null, null, $meta ) . "\n";
foreach ( $this->linkTags as $link )
$html .= CHtml::linkTag ( null, null, null, null, $link ) . "\n";
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) {
if (isset ( $this->scriptFiles [self::POS_HEAD] )) {
foreach ( $this->scriptFiles [self::POS_HEAD] as $scriptFileValueUrl => $scriptFileValue ) {
if (is_array ( $scriptFileValue ))
$html .= CHtml::scriptFile ( $scriptFileValueUrl, $scriptFileValue ) . "\n";
else
$html .= CHtml::scriptFile ( $scriptFileValueUrl ) . "\n";
}
}
if (isset ( $this->scripts [self::POS_HEAD] ))
$html .= $this->renderScriptBatch ( $this->scripts [self::POS_HEAD] );
}
if ($html !== '') {
$count = 0;
$output = preg_replace ( '/(]*>|<\\/head\s*>)/is', '<###head###>$1', $output, 1, $count );
if ($count)
$output = str_replace ( '<###head###>', $html, $output );
else
$output = $html . $output;
}
}
public function renderBodyBegin(&$output) {
$html = '';
if (isset ( $this->scriptFiles [self::POS_BEGIN] )) {
foreach ( $this->scriptFiles [self::POS_BEGIN] as $scriptFileUrl => $scriptFileValue ) {
if (is_array ( $scriptFileValue ))
$html .= CHtml::scriptFile ( $scriptFileUrl, $scriptFileValue ) . "\n";
else
$html .= CHtml::scriptFile ( $scriptFileUrl ) . "\n";
}
}
if (isset ( $this->scripts [self::POS_BEGIN] ))
$html .= $this->renderScriptBatch ( $this->scripts [self::POS_BEGIN] );
if ($html !== '') {
$count = 0;
$output = preg_replace ( '/(]*>)/is', '$1<###begin###>', $output, 1, $count );
if ($count)
$output = str_replace ( '<###begin###>', $html, $output );
else
$output = $html . $output;
}
}
public function renderBodyEnd(&$output) {
if (! isset ( $this->scriptFiles [self::POS_END] ) && ! isset ( $this->scripts [self::POS_END] ) && ! isset ( $this->scripts [self::POS_READY] ) && ! isset ( $this->scripts [self::POS_LOAD] ))
return;
$fullPage = 0;
$output = preg_replace ( '/(<\\/body\s*>)/is', '<###end###>$1', $output, 1, $fullPage );
$html = '';
if (isset ( $this->scriptFiles [self::POS_END] )) {
foreach ( $this->scriptFiles [self::POS_END] as $scriptFileUrl => $scriptFileValue ) {
if (is_array ( $scriptFileValue ))
$html .= CHtml::scriptFile ( $scriptFileUrl, $scriptFileValue ) . "\n";
else
$html .= CHtml::scriptFile ( $scriptFileUrl ) . "\n";
}
}
$scripts = isset ( $this->scripts [self::POS_END] ) ? $this->scripts [self::POS_END] : array ();
if (isset ( $this->scripts [self::POS_READY] )) {
if ($fullPage)
$scripts [] = "jQuery(function($) {\n" . implode ( "\n", $this->scripts [self::POS_READY] ) . "\n});";
else
$scripts [] = implode ( "\n", $this->scripts [self::POS_READY] );
}
if (isset ( $this->scripts [self::POS_LOAD] )) {
if ($fullPage)
$scripts [] = "jQuery(window).on('load',function() {\n" . implode ( "\n", $this->scripts [self::POS_LOAD] ) . "\n});";
else
$scripts [] = implode ( "\n", $this->scripts [self::POS_LOAD] );
}
if (! empty ( $scripts ))
$html .= $this->renderScriptBatch ( $scripts );
if ($fullPage)
$output = str_replace ( '<###end###>', $html, $output );
else
$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 getPackageBaseUrl($name) {
if (! isset ( $this->coreScripts [$name] ))
return false;
$package = $this->coreScripts [$name];
if (isset ( $package ['baseUrl'] )) {
$baseUrl = $package ['baseUrl'];
if ($baseUrl === '' || $baseUrl [0] !== '/' && strpos ( $baseUrl, '://' ) === false)
$baseUrl = Yii::app ()->getRequest ()->getBaseUrl () . '/' . $baseUrl;
$baseUrl = rtrim ( $baseUrl, '/' );
} elseif (isset ( $package ['basePath'] ))
$baseUrl = Yii::app ()->getAssetManager ()->publish ( Yii::getPathOfAlias ( $package ['basePath'] ) );
else
$baseUrl = $this->getCoreScriptUrl ();
return $this->coreScripts [$name] ['baseUrl'] = $baseUrl;
}
public function registerPackage($name) {
return $this->registerCoreScript ( $name );
}
public function registerCoreScript($name) {
if (isset ( $this->coreScripts [$name] ))
return $this;
if (isset ( $this->packages [$name] ))
$package = $this->packages [$name];
else {
if ($this->corePackages === null)
$this->corePackages = require (YII_PATH . '/web/js/packages.php');
if (isset ( $this->corePackages [$name] ))
$package = $this->corePackages [$name];
}
if (isset ( $package )) {
if (! empty ( $package ['depends'] )) {
foreach ( $package ['depends'] as $p )
$this->registerCoreScript ( $p );
}
$this->coreScripts [$name] = $package;
$this->hasScripts = true;
$params = func_get_args ();
$this->recordCachingAction ( 'clientScript', 'registerCoreScript', $params );
}
return $this;
}
public function registerCssFile($url, $media = '') {
$this->hasScripts = true;
$this->cssFiles [$url] = $media;
$params = func_get_args ();
$this->recordCachingAction ( 'clientScript', 'registerCssFile', $params );
return $this;
}
public function registerCss($id, $css, $media = '') {
$this->hasScripts = true;
$this->css [$id] = array (
$css,
$media
);
$params = func_get_args ();
$this->recordCachingAction ( 'clientScript', 'registerCss', $params );
return $this;
}
public function registerScriptFile($url, $position = null, array $htmlOptions = array()) {
if ($position === null)
$position = $this->defaultScriptFilePosition;
$this->hasScripts = true;
if (empty ( $htmlOptions ))
$value = $url;
else {
$value = $htmlOptions;
$value ['src'] = $url;
}
$this->scriptFiles [$position] [$url] = $value;
$params = func_get_args ();
$this->recordCachingAction ( 'clientScript', 'registerScriptFile', $params );
return $this;
}
public function registerScript($id, $script, $position = null, array $htmlOptions = array()) {
if ($position === null)
$position = $this->defaultScriptPosition;
$this->hasScripts = true;
if (empty ( $htmlOptions ))
$scriptValue = $script;
else {
if ($position == self::POS_LOAD || $position == self::POS_READY)
throw new CException ( Yii::t ( 'yii', 'Script HTML options are not allowed for "CClientScript::POS_LOAD" and "CClientScript::POS_READY".' ) );
$scriptValue = $htmlOptions;
$scriptValue ['content'] = $script;
}
$this->scripts [$position] [$id] = $scriptValue;
if ($position === self::POS_READY || $position === self::POS_LOAD)
$this->registerCoreScript ( 'jquery' );
$params = func_get_args ();
$this->recordCachingAction ( 'clientScript', 'registerScript', $params );
return $this;
}
public function registerMetaTag($content, $name = null, $httpEquiv = null, $options = array(), $id = null) {
$this->hasScripts = true;
if ($name !== null)
$options ['name'] = $name;
if ($httpEquiv !== null)
$options ['http-equiv'] = $httpEquiv;
$options ['content'] = $content;
$this->metaTags [null === $id ? count ( $this->metaTags ) : $id] = $options;
$params = func_get_args ();
$this->recordCachingAction ( 'clientScript', 'registerMetaTag', $params );
return $this;
}
public function registerLinkTag($relation = null, $type = null, $href = null, $media = null, $options = array()) {
$this->hasScripts = true;
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->linkTags [serialize ( $options )] = $options;
$params = func_get_args ();
$this->recordCachingAction ( 'clientScript', 'registerLinkTag', $params );
return $this;
}
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->scriptFiles [$position] [$url] );
}
public function isScriptRegistered($id, $position = self::POS_READY) {
return isset ( $this->scripts [$position] [$id] );
}
protected function recordCachingAction($context, $method, $params) {
if (($controller = Yii::app ()->getController ()) !== null)
$controller->recordCachingAction ( $context, $method, $params );
}
public function addPackage($name, $definition) {
$this->packages [$name] = $definition;
return $this;
}
}
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];
elseif ($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;
elseif ($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
return false;
}
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 );
} elseif ($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 );
} elseif ($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 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)
$filter = CInlineFilter::create ( $controller, trim ( substr ( $filter, 0, $pos ) ) );
} else
$filter = CInlineFilter::create ( $controller, $filter );
} elseif (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;
$filter = Yii::createComponent ( $filter );
}
if (is_object ( $filter )) {
$filter->init ();
$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 );
}
}
public function init() {
}
protected function preFilter($filterChain) {
return true;
}
protected function postFilter($filterChain) {
}
}
class CInlineFilter extends CFilter {
public $name;
public static function create($controller, $filterName) {
if (method_exists ( $controller, 'filter' . $filterName )) {
$filter = new CInlineFilter ();
$filter->name = $filterName;
return $filter;
} else
throw new CException ( Yii::t ( 'yii', 'Filter "{filter}" is invalid. Controller "{class}" does not have the filter method "filter{filter}".', array (
'{filter}' => $filterName,
'{class}' => get_class ( $controller )
) ) );
}
public function filter($filterChain) {
$method = 'filter' . $this->name;
$filterChain->controller->$method ( $filterChain );
}
}
class CAccessControlFilter extends CFilter {
public $message;
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 ) {
if ($name === 'expression' || $name === 'roles' || $name === 'message' || $name === 'deniedCallback')
$r->$name = $value;
else
$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 ();
foreach ( $this->getRules () as $rule ) {
if (($allow = $rule->isUserAllowed ( $user, $filterChain->controller, $filterChain->action, $ip, $verb )) > 0) // allowed
break;
elseif ($allow < 0) // denied
{
if (isset ( $rule->deniedCallback ))
call_user_func ( $rule->deniedCallback, $rule );
else
$this->accessDenied ( $user, $this->resolveErrorMessage ( $rule ) );
return false;
}
}
return true;
}
protected function resolveErrorMessage($rule) {
if ($rule->message !== null)
return $rule->message;
elseif ($this->message !== null)
return $this->message;
else
return Yii::t ( 'yii', 'You are not authorized to perform this action.' );
}
protected function accessDenied($user, $message) {
if ($user->getIsGuest ())
$user->loginRequired ();
else
throw new CHttpException ( 403, $message );
}
}
class CAccessRule extends CComponent {
public $allow;
public $actions;
public $controllers;
public $users;
public $roles;
public $ips;
public $verbs;
public $expression;
public $message;
public $deniedCallback;
public function isUserAllowed($user, $controller, $action, $ip, $verb) {
if ($this->isActionMatched ( $action ) && $this->isUserMatched ( $user ) && $this->isRoleMatched ( $user ) && $this->isIpMatched ( $ip ) && $this->isVerbMatched ( $verb ) && $this->isControllerMatched ( $controller ) && $this->isExpressionMatched ( $user ))
return $this->allow ? 1 : - 1;
else
return 0;
}
protected function isActionMatched($action) {
return empty ( $this->actions ) || in_array ( strtolower ( $action->getId () ), $this->actions );
}
protected function isControllerMatched($controller) {
return empty ( $this->controllers ) || in_array ( strtolower ( $controller->getUniqueId () ), $this->controllers );
}
protected function isUserMatched($user) {
if (empty ( $this->users ))
return true;
foreach ( $this->users as $u ) {
if ($u === '*')
return true;
elseif ($u === '?' && $user->getIsGuest ())
return true;
elseif ($u === '@' && ! $user->getIsGuest ())
return true;
elseif (! strcasecmp ( $u, $user->getName () ))
return true;
}
return false;
}
protected function isRoleMatched($user) {
if (empty ( $this->roles ))
return true;
foreach ( $this->roles as $key => $role ) {
if (is_numeric ( $key )) {
if ($user->checkAccess ( $role ))
return true;
} else {
if ($user->checkAccess ( $key, $role ))
return true;
}
}
return false;
}
protected 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;
}
protected function isVerbMatched($verb) {
return empty ( $this->verbs ) || in_array ( strtolower ( $verb ), $this->verbs );
}
protected function isExpressionMatched($user) {
if ($this->expression === null)
return true;
else
return $this->evaluateExpression ( $this->expression, array (
'user' => $user
) );
}
}
abstract class CModel extends CComponent implements IteratorAggregate, ArrayAccess {
private $_errors = array (); // attribute name => array of errors
private $_validators; // validators
private $_scenario = ''; // scenario
abstract public function attributeNames();
public function rules() {
return array ();
}
public function behaviors() {
return array ();
}
public function attributeLabels() {
return array ();
}
public function validate($attributes = null, $clearErrors = true) {
if ($clearErrors)
$this->clearErrors ();
if ($this->beforeValidate ()) {
foreach ( $this->getValidators () as $validator )
$validator->validate ( $this, $attributes );
$this->afterValidate ();
return ! $this->hasErrors ();
} else
return false;
}
protected function afterConstruct() {
if ($this->hasEventHandler ( 'onAfterConstruct' ))
$this->onAfterConstruct ( new CEvent ( $this ) );
}
protected function beforeValidate() {
$event = new CModelEvent ( $this );
$this->onBeforeValidate ( $event );
return $event->isValid;
}
protected function afterValidate() {
$this->onAfterValidate ( new CEvent ( $this ) );
}
public function onAfterConstruct($event) {
$this->raiseEvent ( 'onAfterConstruct', $event );
}
public function onBeforeValidate($event) {
$this->raiseEvent ( 'onBeforeValidate', $event );
}
public function onAfterValidate($event) {
$this->raiseEvent ( 'onAfterValidate', $event );
}
public function getValidatorList() {
if ($this->_validators === null)
$this->_validators = $this->createValidators ();
return $this->_validators;
}
public function getValidators($attribute = null) {
if ($this->_validators === null)
$this->_validators = $this->createValidators ();
$validators = array ();
$scenario = $this->getScenario ();
foreach ( $this->_validators as $validator ) {
if ($validator->applyTo ( $scenario )) {
if ($attribute === null || in_array ( $attribute, $validator->attributes, true ))
$validators [] = $validator;
}
}
return $validators;
}
public function createValidators() {
$validators = new CList ();
foreach ( $this->rules () as $rule ) {
if (isset ( $rule [0], $rule [1] )) // attributes, validator name
$validators->add ( 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;
}
public function isAttributeRequired($attribute) {
foreach ( $this->getValidators ( $attribute ) as $validator ) {
if ($validator instanceof CRequiredValidator)
return true;
}
return false;
}
public function isAttributeSafe($attribute) {
$attributes = $this->getSafeAttributeNames ();
return in_array ( $attribute, $attributes );
}
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 getError($attribute) {
return isset ( $this->_errors [$attribute] ) ? reset ( $this->_errors [$attribute] ) : null;
}
public function addError($attribute, $error) {
$this->_errors [$attribute] [] = $error;
}
public function addErrors($errors) {
foreach ( $errors as $attribute => $error ) {
if (is_array ( $error )) {
foreach ( $error as $e )
$this->addError ( $attribute, $e );
} else
$this->addError ( $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 ( '/(?attributeNames () as $name )
$values [$name] = $this->$name;
if (is_array ( $names )) {
$values2 = array ();
foreach ( $names as $name )
$values2 [$name] = isset ( $values [$name] ) ? $values [$name] : null;
return $values2;
} else
return $values;
}
public function setAttributes($values, $safeOnly = true) {
if (! is_array ( $values ))
return;
$attributes = array_flip ( $safeOnly ? $this->getSafeAttributeNames () : $this->attributeNames () );
foreach ( $values as $name => $value ) {
if (isset ( $attributes [$name] ))
$this->$name = $value;
elseif ($safeOnly)
$this->onUnsafeAttribute ( $name, $value );
}
}
public function unsetAttributes($names = null) {
if ($names === null)
$names = $this->attributeNames ();
foreach ( $names as $name )
$this->$name = null;
}
public function onUnsafeAttribute($name, $value) {
if (YII_DEBUG)
Yii::log ( Yii::t ( 'yii', 'Failed to set unsafe attribute "{attribute}" of "{class}".', array (
'{attribute}' => $name,
'{class}' => get_class ( $this )
) ), CLogger::LEVEL_WARNING );
}
public function getScenario() {
return $this->_scenario;
}
public function setScenario($value) {
$this->_scenario = $value;
}
public function getSafeAttributeNames() {
$attributes = array ();
$unsafe = array ();
foreach ( $this->getValidators () as $validator ) {
if (! $validator->safe) {
foreach ( $validator->attributes as $name )
$unsafe [] = $name;
} else {
foreach ( $validator->attributes as $name )
$attributes [$name] = true;
}
}
foreach ( $unsafe as $name )
unset ( $attributes [$name] );
return array_keys ( $attributes );
}
public function getIterator() {
$attributes = $this->getAttributes ();
return new CMapIterator ( $attributes );
}
public function offsetExists($offset) {
return property_exists ( $this, $offset );
}
public function offsetGet($offset) {
return $this->$offset;
}
public function offsetSet($offset, $item) {
$this->$offset = $item;
}
public function offsetUnset($offset) {
unset ( $this->$offset );
}
}
abstract class CActiveRecord extends CModel {
const BELONGS_TO = 'CBelongsToRelation';
const HAS_ONE = 'CHasOneRelation';
const HAS_MANY = 'CHasManyRelation';
const MANY_MANY = 'CManyManyRelation';
const STAT = 'CStatRelation';
public static $db;
private static $_models = array (); // class name => model
private static $_md = array (); // class name => meta data
private $_new = false; // whether this instance is new or not
private $_attributes = array (); // attribute name => attribute value
private $_related = array (); // attribute name => related objects
private $_c; // query criteria (used by finder only)
private $_pk; // old primary key value
private $_alias = 't'; // the table alias being used for query
public function __construct($scenario = 'insert') {
if ($scenario === null) // internally used by populateRecord() and model()
return;
$this->setScenario ( $scenario );
$this->setIsNewRecord ( true );
$this->_attributes = $this->getMetaData ()->attributeDefaults;
$this->init ();
$this->attachBehaviors ( $this->behaviors () );
$this->afterConstruct ();
}
public function init() {
}
public function cache($duration, $dependency = null, $queryCount = 1) {
$this->getDbConnection ()->cache ( $duration, $dependency, $queryCount );
return $this;
}
public function __sleep() {
return array_keys ( ( array ) $this );
}
public function __get($name) {
if (isset ( $this->_attributes [$name] ))
return $this->_attributes [$name];
elseif (isset ( $this->getMetaData ()->columns [$name] ))
return null;
elseif (isset ( $this->_related [$name] ))
return $this->_related [$name];
elseif (isset ( $this->getMetaData ()->relations [$name] ))
return $this->getRelated ( $name );
else
return parent::__get ( $name );
}
public function __set($name, $value) {
if ($this->setAttribute ( $name, $value ) === false) {
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;
elseif (isset ( $this->getMetaData ()->columns [$name] ))
return false;
elseif (isset ( $this->_related [$name] ))
return true;
elseif (isset ( $this->getMetaData ()->relations [$name] ))
return $this->getRelated ( $name ) !== null;
else
return parent::__isset ( $name );
}
public function __unset($name) {
if (isset ( $this->getMetaData ()->columns [$name] ))
unset ( $this->_attributes [$name] );
elseif (isset ( $this->getMetaData ()->relations [$name] ))
unset ( $this->_related [$name] );
else
parent::__unset ( $name );
}
public function __call($name, $parameters) {
if (isset ( $this->getMetaData ()->relations [$name] )) {
if (empty ( $parameters ))
return $this->getRelated ( $name, false );
else
return $this->getRelated ( $name, false, $parameters [0] );
}
$scopes = $this->scopes ();
if (isset ( $scopes [$name] )) {
$this->getDbCriteria ()->mergeWith ( $scopes [$name] );
return $this;
}
return parent::__call ( $name, $parameters );
}
public function getRelated($name, $refresh = false, $params = array()) {
if (! $refresh && $params === array () && (isset ( $this->_related [$name] ) || array_key_exists ( $name, $this->_related )))
return $this->_related [$name];
$md = $this->getMetaData ();
if (! isset ( $md->relations [$name] ))
throw new CDbException ( Yii::t ( 'yii', '{class} does not have relation "{name}".', array (
'{class}' => get_class ( $this ),
'{name}' => $name
) ) );
$relation = $md->relations [$name];
if ($this->getIsNewRecord () && ! $refresh && ($relation instanceof CHasOneRelation || $relation instanceof CHasManyRelation))
return $relation instanceof CHasOneRelation ? null : array ();
if ($params !== array ()) // dynamic query
{
$exists = isset ( $this->_related [$name] ) || array_key_exists ( $name, $this->_related );
if ($exists)
$save = $this->_related [$name];
if ($params instanceof CDbCriteria)
$params = $params->toArray ();
$r = array (
$name => $params
);
} else
$r = $name;
unset ( $this->_related [$name] );
$finder = $this->getActiveFinder ( $r );
$finder->lazyFind ( $this );
if (! isset ( $this->_related [$name] )) {
if ($relation instanceof CHasManyRelation)
$this->_related [$name] = array ();
elseif ($relation instanceof CStatRelation)
$this->_related [$name] = $relation->defaultValue;
else
$this->_related [$name] = null;
}
if ($params !== array ()) {
$results = $this->_related [$name];
if ($exists)
$this->_related [$name] = $save;
else
unset ( $this->_related [$name] );
return $results;
} else
return $this->_related [$name];
}
public function hasRelated($name) {
return isset ( $this->_related [$name] ) || array_key_exists ( $name, $this->_related );
}
public function getDbCriteria($createIfNull = true) {
if ($this->_c === null) {
if (($c = $this->defaultScope ()) !== array () || $createIfNull)
$this->_c = new CDbCriteria ( $c );
}
return $this->_c;
}
public function setDbCriteria($criteria) {
$this->_c = $criteria;
}
public function defaultScope() {
return array ();
}
public function resetScope($resetDefault = true) {
if ($resetDefault)
$this->_c = new CDbCriteria ();
else
$this->_c = null;
return $this;
}
public static function model($className = __CLASS__) {
if (isset ( self::$_models [$className] ))
return self::$_models [$className];
else {
$model = self::$_models [$className] = new $className ( null );
$model->attachBehaviors ( $model->behaviors () );
return $model;
}
}
public function getMetaData() {
$className = get_class ( $this );
if (! array_key_exists ( $className, self::$_md )) {
self::$_md [$className] = null; // preventing recursive invokes of {@link getMetaData()} via {@link __get()}
self::$_md [$className] = new CActiveRecordMetaData ( $this );
}
return self::$_md [$className];
}
public function refreshMetaData() {
$className = get_class ( $this );
if (array_key_exists ( $className, self::$_md ))
unset ( self::$_md [$className] );
}
public function tableName() {
return get_class ( $this );
}
public function primaryKey() {
}
public function relations() {
return array ();
}
public function scopes() {
return array ();
}
public function attributeNames() {
return array_keys ( $this->getMetaData ()->columns );
}
public function getAttributeLabel($attribute) {
$labels = $this->attributeLabels ();
if (isset ( $labels [$attribute] ))
return $labels [$attribute];
elseif (strpos ( $attribute, '.' ) !== false) {
$segs = explode ( '.', $attribute );
$name = array_pop ( $segs );
$model = $this;
foreach ( $segs as $seg ) {
$relations = $model->getMetaData ()->relations;
if (isset ( $relations [$seg] ))
$model = CActiveRecord::model ( $relations [$seg]->className );
else
break;
}
return $model->getAttributeLabel ( $name );
} else
return $this->generateAttributeLabel ( $attribute );
}
public function getDbConnection() {
if (self::$db !== null)
return self::$db;
else {
self::$db = Yii::app ()->getDb ();
if (self::$db instanceof CDbConnection)
return self::$db;
else
throw new CDbException ( Yii::t ( 'yii', 'Active Record requires a "db" CDbConnection application component.' ) );
}
}
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;
elseif (isset ( $this->_attributes [$name] ))
return $this->_attributes [$name];
}
public function setAttribute($name, $value) {
if (property_exists ( $this, $name ))
$this->$name = $value;
elseif (isset ( $this->getMetaData ()->columns [$name] ))
$this->_attributes [$name] = $value;
else
return false;
return true;
}
public function addRelatedRecord($name, $record, $index) {
if ($index !== false) {
if (! isset ( $this->_related [$name] ))
$this->_related [$name] = array ();
if ($record instanceof CActiveRecord) {
if ($index === true)
$this->_related [$name] [] = $record;
else
$this->_related [$name] [$index] = $record;
}
} elseif (! 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;
elseif ($names === true && ! isset ( $attributes [$name] ))
$attributes [$name] = null;
}
if (is_array ( $names )) {
$attrs = array ();
foreach ( $names as $name ) {
if (property_exists ( $this, $name ))
$attrs [$name] = $this->$name;
else
$attrs [$name] = isset ( $attributes [$name] ) ? $attributes [$name] : null;
}
return $attrs;
} else
return $attributes;
}
public function save($runValidation = true, $attributes = null) {
if (! $runValidation || $this->validate ( $attributes ))
return $this->getIsNewRecord () ? $this->insert ( $attributes ) : $this->update ( $attributes );
else
return false;
}
public function getIsNewRecord() {
return $this->_new;
}
public function setIsNewRecord($value) {
$this->_new = $value;
}
public function onBeforeSave($event) {
$this->raiseEvent ( 'onBeforeSave', $event );
}
public function onAfterSave($event) {
$this->raiseEvent ( 'onAfterSave', $event );
}
public function onBeforeDelete($event) {
$this->raiseEvent ( 'onBeforeDelete', $event );
}
public function onAfterDelete($event) {
$this->raiseEvent ( 'onAfterDelete', $event );
}
public function onBeforeFind($event) {
$this->raiseEvent ( 'onBeforeFind', $event );
}
public function onAfterFind($event) {
$this->raiseEvent ( 'onAfterFind', $event );
}
public function getActiveFinder($with) {
return new CActiveFinder ( $this, $with );
}
public function onBeforeCount($event) {
$this->raiseEvent ( 'onBeforeCount', $event );
}
protected function beforeSave() {
if ($this->hasEventHandler ( 'onBeforeSave' )) {
$event = new CModelEvent ( $this );
$this->onBeforeSave ( $event );
return $event->isValid;
} else
return true;
}
protected function afterSave() {
if ($this->hasEventHandler ( 'onAfterSave' ))
$this->onAfterSave ( new CEvent ( $this ) );
}
protected function beforeDelete() {
if ($this->hasEventHandler ( 'onBeforeDelete' )) {
$event = new CModelEvent ( $this );
$this->onBeforeDelete ( $event );
return $event->isValid;
} else
return true;
}
protected function afterDelete() {
if ($this->hasEventHandler ( 'onAfterDelete' ))
$this->onAfterDelete ( new CEvent ( $this ) );
}
protected function beforeFind() {
if ($this->hasEventHandler ( 'onBeforeFind' )) {
$event = new CModelEvent ( $this );
$this->onBeforeFind ( $event );
}
}
protected function beforeCount() {
if ($this->hasEventHandler ( 'onBeforeCount' ))
$this->onBeforeCount ( new CEvent ( $this ) );
}
protected function afterFind() {
if ($this->hasEventHandler ( 'onAfterFind' ))
$this->onAfterFind ( new CEvent ( $this ) );
}
public function beforeFindInternal() {
$this->beforeFind ();
}
public function afterFindInternal() {
$this->afterFind ();
}
public function insert($attributes = null) {
if (! $this->getIsNewRecord ())
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) {
if (is_string ( $primaryKey ) && $this->$primaryKey === null)
$this->$primaryKey = $builder->getLastInsertID ( $table );
elseif (is_array ( $primaryKey )) {
foreach ( $primaryKey as $pk ) {
if ($this->$pk === null) {
$this->$pk = $builder->getLastInsertID ( $table );
break;
}
}
}
}
$this->_pk = $this->getPrimaryKey ();
$this->afterSave ();
$this->setIsNewRecord ( false );
$this->setScenario ( 'update' );
return true;
}
}
return false;
}
public function update($attributes = null) {
if ($this->getIsNewRecord ())
throw new CDbException ( Yii::t ( 'yii', 'The active record cannot be updated because it is new.' ) );
if ($this->beforeSave ()) {
if ($this->_pk === null)
$this->_pk = $this->getPrimaryKey ();
$this->updateByPk ( $this->getOldPrimaryKey (), $this->getAttributes ( $attributes ) );
$this->_pk = $this->getPrimaryKey ();
$this->afterSave ();
return true;
} else
return false;
}
public function saveAttributes($attributes) {
if (! $this->getIsNewRecord ()) {
$values = array ();
foreach ( $attributes as $name => $value ) {
if (is_integer ( $name ))
$values [$value] = $this->$value;
else
$values [$name] = $this->$name = $value;
}
if ($this->_pk === null)
$this->_pk = $this->getPrimaryKey ();
if ($this->updateByPk ( $this->getOldPrimaryKey (), $values ) > 0) {
$this->_pk = $this->getPrimaryKey ();
return true;
} else
return false;
} else
throw new CDbException ( Yii::t ( 'yii', 'The active record cannot be updated because it is new.' ) );
}
public function saveCounters($counters) {
$builder = $this->getCommandBuilder ();
$table = $this->getTableSchema ();
$criteria = $builder->createPkCriteria ( $table, $this->getOldPrimaryKey () );
$command = $builder->createUpdateCounterCommand ( $this->getTableSchema (), $counters, $criteria );
if ($command->execute ()) {
foreach ( $counters as $name => $value )
$this->$name = $this->$name + $value;
return true;
} else
return false;
}
public function delete() {
if (! $this->getIsNewRecord ()) {
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 (($record = $this->findByPk ( $this->getPrimaryKey () )) !== null) {
$this->_attributes = array ();
$this->_related = array ();
foreach ( $this->getMetaData ()->columns as $name => $column ) {
if (property_exists ( $this, $name ))
$this->$name = $record->$name;
else
$this->_attributes [$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};
elseif (is_array ( $table->primaryKey )) {
$values = array ();
foreach ( $table->primaryKey as $name )
$values [$name] = $this->$name;
return $values;
} else
return null;
}
public function setPrimaryKey($value) {
$this->_pk = $this->getPrimaryKey ();
$table = $this->getMetaData ()->tableSchema;
if (is_string ( $table->primaryKey ))
$this->{$table->primaryKey} = $value;
elseif (is_array ( $table->primaryKey )) {
foreach ( $table->primaryKey as $name )
$this->$name = $value [$name];
}
}
public function getOldPrimaryKey() {
return $this->_pk;
}
public function setOldPrimaryKey($value) {
$this->_pk = $value;
}
protected function query($criteria, $all = false) {
$this->beforeFind ();
$this->applyScopes ( $criteria );
if (empty ( $criteria->with )) {
if (! $all)
$criteria->limit = 1;
$command = $this->getCommandBuilder ()->createFindCommand ( $this->getTableSchema (), $criteria, $this->getTableAlias () );
return $all ? $this->populateRecords ( $command->queryAll (), true, $criteria->index ) : $this->populateRecord ( $command->queryRow () );
} else {
$finder = $this->getActiveFinder ( $criteria->with );
return $finder->query ( $criteria, $all );
}
}
public function applyScopes(&$criteria) {
if (! empty ( $criteria->scopes )) {
$scs = $this->scopes ();
$c = $this->getDbCriteria ();
foreach ( ( array ) $criteria->scopes as $k => $v ) {
if (is_integer ( $k )) {
if (is_string ( $v )) {
if (isset ( $scs [$v] )) {
$c->mergeWith ( $scs [$v], true );
continue;
}
$scope = $v;
$params = array ();
} elseif (is_array ( $v )) {
$scope = key ( $v );
$params = current ( $v );
}
} elseif (is_string ( $k )) {
$scope = $k;
$params = $v;
}
call_user_func_array ( array (
$this,
$scope
), ( array ) $params );
}
}
if (isset ( $c ) || ($c = $this->getDbCriteria ( false )) !== null) {
$c->mergeWith ( $criteria );
$criteria = $c;
$this->resetScope ( false );
}
}
public function getTableAlias($quote = false, $checkScopes = true) {
if ($checkScopes && ($criteria = $this->getDbCriteria ( false )) !== null && $criteria->alias != '')
$alias = $criteria->alias;
else
$alias = $this->_alias;
return $quote ? $this->getDbConnection ()->getSchema ()->quoteTableName ( $alias ) : $alias;
}
public function setTableAlias($alias) {
$this->_alias = $alias;
}
public function find($condition = '', $params = array()) {
$criteria = $this->getCommandBuilder ()->createCriteria ( $condition, $params );
return $this->query ( $criteria );
}
public function findAll($condition = '', $params = array()) {
$criteria = $this->getCommandBuilder ()->createCriteria ( $condition, $params );
return $this->query ( $criteria, true );
}
public function findByPk($pk, $condition = '', $params = array()) {
$prefix = $this->getTableAlias ( true ) . '.';
$criteria = $this->getCommandBuilder ()->createPkCriteria ( $this->getTableSchema (), $pk, $condition, $params, $prefix );
return $this->query ( $criteria );
}
public function findAllByPk($pk, $condition = '', $params = array()) {
$prefix = $this->getTableAlias ( true ) . '.';
$criteria = $this->getCommandBuilder ()->createPkCriteria ( $this->getTableSchema (), $pk, $condition, $params, $prefix );
return $this->query ( $criteria, true );
}
public function findByAttributes($attributes, $condition = '', $params = array()) {
$prefix = $this->getTableAlias ( true ) . '.';
$criteria = $this->getCommandBuilder ()->createColumnCriteria ( $this->getTableSchema (), $attributes, $condition, $params, $prefix );
return $this->query ( $criteria );
}
public function findAllByAttributes($attributes, $condition = '', $params = array()) {
$prefix = $this->getTableAlias ( true ) . '.';
$criteria = $this->getCommandBuilder ()->createColumnCriteria ( $this->getTableSchema (), $attributes, $condition, $params, $prefix );
return $this->query ( $criteria, true );
}
public function findBySql($sql, $params = array()) {
$this->beforeFind ();
if (($criteria = $this->getDbCriteria ( false )) !== null && ! empty ( $criteria->with )) {
$this->resetScope ( false );
$finder = $this->getActiveFinder ( $criteria->with );
return $finder->findBySql ( $sql, $params );
} else {
$command = $this->getCommandBuilder ()->createSqlCommand ( $sql, $params );
return $this->populateRecord ( $command->queryRow () );
}
}
public function findAllBySql($sql, $params = array()) {
$this->beforeFind ();
if (($criteria = $this->getDbCriteria ( false )) !== null && ! empty ( $criteria->with )) {
$this->resetScope ( false );
$finder = $this->getActiveFinder ( $criteria->with );
return $finder->findAllBySql ( $sql, $params );
} else {
$command = $this->getCommandBuilder ()->createSqlCommand ( $sql, $params );
return $this->populateRecords ( $command->queryAll () );
}
}
public function count($condition = '', $params = array()) {
$builder = $this->getCommandBuilder ();
$this->beforeCount ();
$criteria = $builder->createCriteria ( $condition, $params );
$this->applyScopes ( $criteria );
if (empty ( $criteria->with ))
return $builder->createCountCommand ( $this->getTableSchema (), $criteria )->queryScalar ();
else {
$finder = $this->getActiveFinder ( $criteria->with );
return $finder->count ( $criteria );
}
}
public function countByAttributes($attributes, $condition = '', $params = array()) {
$prefix = $this->getTableAlias ( true ) . '.';
$builder = $this->getCommandBuilder ();
$this->beforeCount ();
$criteria = $builder->createColumnCriteria ( $this->getTableSchema (), $attributes, $condition, $params, $prefix );
$this->applyScopes ( $criteria );
if (empty ( $criteria->with ))
return $builder->createCountCommand ( $this->getTableSchema (), $criteria )->queryScalar ();
else {
$finder = $this->getActiveFinder ( $criteria->with );
return $finder->count ( $criteria );
}
}
public function countBySql($sql, $params = array()) {
$this->beforeCount ();
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 = '1';
$criteria->limit = 1;
$this->applyScopes ( $criteria );
if (empty ( $criteria->with ))
return $builder->createFindCommand ( $table, $criteria, $this->getTableAlias ( false, false ) )->queryRow () !== false;
else {
$criteria->select = '*';
$finder = $this->getActiveFinder ( $criteria->with );
return $finder->count ( $criteria ) > 0;
}
}
public function with() {
if (func_num_args () > 0) {
$with = func_get_args ();
if (is_array ( $with [0] )) // the parameter is given as an array
$with = $with [0];
if (! empty ( $with ))
$this->getDbCriteria ()->mergeWith ( array (
'with' => $with
) );
}
return $this;
}
public function together() {
$this->getDbCriteria ()->together = true;
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 deleteAllByAttributes($attributes, $condition = '', $params = array()) {
$builder = $this->getCommandBuilder ();
$table = $this->getTableSchema ();
$criteria = $builder->createColumnCriteria ( $table, $attributes, $condition, $params );
$command = $builder->createDeleteCommand ( $table, $criteria );
return $command->execute ();
}
public function populateRecord($attributes, $callAfterFind = true) {
if ($attributes !== false) {
$record = $this->instantiate ( $attributes );
$record->setScenario ( 'update' );
$record->init ();
$md = $record->getMetaData ();
foreach ( $attributes as $name => $value ) {
if (property_exists ( $record, $name ))
$record->$name = $value;
elseif (isset ( $md->columns [$name] ))
$record->_attributes [$name] = $value;
}
$record->_pk = $record->getPrimaryKey ();
$record->attachBehaviors ( $record->behaviors () );
if ($callAfterFind)
$record->afterFind ();
return $record;
} else
return null;
}
public function populateRecords($data, $callAfterFind = true, $index = null) {
$records = array ();
foreach ( $data as $attributes ) {
if (($record = $this->populateRecord ( $attributes, $callAfterFind )) !== null) {
if ($index === null)
$records [] = $record;
else
$records [$record->$index] = $record;
}
}
return $records;
}
protected function instantiate($attributes) {
$class = get_class ( $this );
$model = new $class ( null );
return $model;
}
public function offsetExists($offset) {
return $this->__isset ( $offset );
}
}
class CBaseActiveRelation extends CComponent {
public $name;
public $className;
public $foreignKey;
public $select = '*';
public $condition = '';
public $params = array ();
public $group = '';
public $join = '';
public $having = '';
public $order = '';
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;
}
public function mergeWith($criteria, $fromScope = false) {
if ($criteria instanceof CDbCriteria)
$criteria = $criteria->toArray ();
if (isset ( $criteria ['select'] ) && $this->select !== $criteria ['select']) {
if ($this->select === '*')
$this->select = $criteria ['select'];
elseif ($criteria ['select'] !== '*') {
$select1 = is_string ( $this->select ) ? preg_split ( '/\s*,\s*/', trim ( $this->select ), - 1, PREG_SPLIT_NO_EMPTY ) : $this->select;
$select2 = is_string ( $criteria ['select'] ) ? preg_split ( '/\s*,\s*/', trim ( $criteria ['select'] ), - 1, PREG_SPLIT_NO_EMPTY ) : $criteria ['select'];
$this->select = array_merge ( $select1, array_diff ( $select2, $select1 ) );
}
}
if (isset ( $criteria ['condition'] ) && $this->condition !== $criteria ['condition']) {
if ($this->condition === '')
$this->condition = $criteria ['condition'];
elseif ($criteria ['condition'] !== '')
$this->condition = "({$this->condition}) AND ({$criteria['condition']})";
}
if (isset ( $criteria ['params'] ) && $this->params !== $criteria ['params'])
$this->params = array_merge ( $this->params, $criteria ['params'] );
if (isset ( $criteria ['order'] ) && $this->order !== $criteria ['order']) {
if ($this->order === '')
$this->order = $criteria ['order'];
elseif ($criteria ['order'] !== '')
$this->order = $criteria ['order'] . ', ' . $this->order;
}
if (isset ( $criteria ['group'] ) && $this->group !== $criteria ['group']) {
if ($this->group === '')
$this->group = $criteria ['group'];
elseif ($criteria ['group'] !== '')
$this->group .= ', ' . $criteria ['group'];
}
if (isset ( $criteria ['join'] ) && $this->join !== $criteria ['join']) {
if ($this->join === '')
$this->join = $criteria ['join'];
elseif ($criteria ['join'] !== '')
$this->join .= ' ' . $criteria ['join'];
}
if (isset ( $criteria ['having'] ) && $this->having !== $criteria ['having']) {
if ($this->having === '')
$this->having = $criteria ['having'];
elseif ($criteria ['having'] !== '')
$this->having = "({$this->having}) AND ({$criteria['having']})";
}
}
}
class CStatRelation extends CBaseActiveRelation {
public $select = 'COUNT(*)';
public $defaultValue = 0;
public function mergeWith($criteria, $fromScope = false) {
if ($criteria instanceof CDbCriteria)
$criteria = $criteria->toArray ();
parent::mergeWith ( $criteria, $fromScope );
if (isset ( $criteria ['defaultValue'] ))
$this->defaultValue = $criteria ['defaultValue'];
}
}
class CActiveRelation extends CBaseActiveRelation {
public $joinType = 'LEFT OUTER JOIN';
public $on = '';
public $alias;
public $with = array ();
public $together;
public $scopes;
public $through;
public function mergeWith($criteria, $fromScope = false) {
if ($criteria instanceof CDbCriteria)
$criteria = $criteria->toArray ();
if ($fromScope) {
if (isset ( $criteria ['condition'] ) && $this->on !== $criteria ['condition']) {
if ($this->on === '')
$this->on = $criteria ['condition'];
elseif ($criteria ['condition'] !== '')
$this->on = "({$this->on}) AND ({$criteria['condition']})";
}
unset ( $criteria ['condition'] );
}
parent::mergeWith ( $criteria );
if (isset ( $criteria ['joinType'] ))
$this->joinType = $criteria ['joinType'];
if (isset ( $criteria ['on'] ) && $this->on !== $criteria ['on']) {
if ($this->on === '')
$this->on = $criteria ['on'];
elseif ($criteria ['on'] !== '')
$this->on = "({$this->on}) AND ({$criteria['on']})";
}
if (isset ( $criteria ['with'] ))
$this->with = $criteria ['with'];
if (isset ( $criteria ['alias'] ))
$this->alias = $criteria ['alias'];
if (isset ( $criteria ['together'] ))
$this->together = $criteria ['together'];
}
}
class CBelongsToRelation extends CActiveRelation {
}
class CHasOneRelation extends CActiveRelation {
}
class CHasManyRelation extends CActiveRelation {
public $limit = - 1;
public $offset = - 1;
public $index;
public function mergeWith($criteria, $fromScope = false) {
if ($criteria instanceof CDbCriteria)
$criteria = $criteria->toArray ();
parent::mergeWith ( $criteria, $fromScope );
if (isset ( $criteria ['limit'] ) && $criteria ['limit'] > 0)
$this->limit = $criteria ['limit'];
if (isset ( $criteria ['offset'] ) && $criteria ['offset'] >= 0)
$this->offset = $criteria ['offset'];
if (isset ( $criteria ['index'] ))
$this->index = $criteria ['index'];
}
}
class CManyManyRelation extends CHasManyRelation {
private $_junctionTableName = null;
private $_junctionForeignKeys = null;
public function getJunctionTableName() {
if ($this->_junctionTableName === null)
$this->initJunctionData ();
return $this->_junctionTableName;
}
public function getJunctionForeignKeys() {
if ($this->_junctionForeignKeys === null)
$this->initJunctionData ();
return $this->_junctionForeignKeys;
}
private function initJunctionData() {
if (! preg_match ( '/^\s*(.*?)\((.*)\)\s*$/', $this->foreignKey, $matches ))
throw new CDbException ( Yii::t ( 'yii', 'The relation "{relation}" in active record class "{class}" is specified with an invalid foreign key. The format of the foreign key must be "joinTable(fk1,fk2,...)".', array (
'{class}' => $this->className,
'{relation}' => $this->name
) ) );
$this->_junctionTableName = $matches [1];
$this->_junctionForeignKeys = preg_split ( '/\s*,\s*/', $matches [2], - 1, PREG_SPLIT_NO_EMPTY );
}
}
class CActiveRecordMetaData {
public $tableSchema;
public $columns;
public $relations = array ();
public $attributeDefaults = array ();
private $_modelClassName;
public function __construct($model) {
$this->_modelClassName = get_class ( $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}' => $this->_modelClassName,
'{table}' => $tableName
) ) );
if ($table->primaryKey === null) {
$table->primaryKey = $model->primaryKey ();
if (is_string ( $table->primaryKey ) && isset ( $table->columns [$table->primaryKey] ))
$table->columns [$table->primaryKey]->isPrimaryKey = true;
elseif (is_array ( $table->primaryKey )) {
foreach ( $table->primaryKey as $name ) {
if (isset ( $table->columns [$name] ))
$table->columns [$name]->isPrimaryKey = true;
}
}
}
$this->tableSchema = $table;
$this->columns = $table->columns;
foreach ( $table->columns as $name => $column ) {
if (! $column->isPrimaryKey && $column->defaultValue !== null)
$this->attributeDefaults [$name] = $column->defaultValue;
}
foreach ( $model->relations () as $name => $config ) {
$this->addRelation ( $name, $config );
}
}
public function addRelation($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}' => $this->_modelClassName,
'{relation}' => $name
) ) );
}
public function hasRelation($name) {
return isset ( $this->relations [$name] );
}
public function removeRelation($name) {
unset ( $this->relations [$name] );
}
}
class CDbConnection extends CApplicationComponent {
public $connectionString;
public $username = '';
public $password = '';
public $schemaCachingDuration = 0;
public $schemaCachingExclude = array ();
public $schemaCacheID = 'cache';
public $queryCachingDuration = 0;
public $queryCachingDependency;
public $queryCachingCount = 0;
public $queryCacheID = 'cache';
public $autoConnect = true;
public $charset;
public $emulatePrepare;
public $enableParamLogging = false;
public $enableProfiling = false;
public $tablePrefix;
public $initSQLs;
public $driverMap = array (
'pgsql' => 'CPgsqlSchema', // PostgreSQL
'mysqli' => 'CMysqlSchema', // MySQL
'mysql' => 'CMysqlSchema', // MySQL
'sqlite' => 'CSqliteSchema', // sqlite 3
'sqlite2' => 'CSqliteSchema', // sqlite 2
'mssql' => 'CMssqlSchema', // Mssql driver on windows hosts
'dblib' => 'CMssqlSchema', // dblib drivers on linux (and maybe others os) hosts
'sqlsrv' => 'CMssqlSchema', // Mssql
'oci' => 'COciSchema'
) // Oracle driver
;
public $pdoClass = 'PDO';
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 ();
}
}
public function cache($duration, $dependency = null, $queryCount = 1) {
$this->queryCachingDuration = $duration;
$this->queryCachingDependency = $dependency;
$this->queryCachingCount = $queryCount;
return $this;
}
protected function open() {
if ($this->_pdo === null) {
if (empty ( $this->connectionString ))
throw new CDbException ( 'CDbConnection.connectionString cannot be empty.' );
try {
$this->_pdo = $this->createPdoInstance ();
$this->initConnection ( $this->_pdo );
$this->_active = true;
} catch ( PDOException $e ) {
if (YII_DEBUG) {
throw new CDbException ( 'CDbConnection failed to open the DB connection: ' . $e->getMessage (), ( int ) $e->getCode (), $e->errorInfo );
} else {
Yii::log ( $e->getMessage (), CLogger::LEVEL_ERROR, 'exception.CDbException' );
throw new CDbException ( 'CDbConnection failed to open the DB connection.', ( int ) $e->getCode (), $e->errorInfo );
}
}
}
}
protected function close() {
$this->_pdo = null;
$this->_active = false;
$this->_schema = null;
}
protected function createPdoInstance() {
$pdoClass = $this->pdoClass;
if (($pos = strpos ( $this->connectionString, ':' )) !== false) {
$driver = strtolower ( substr ( $this->connectionString, 0, $pos ) );
if ($driver === 'mssql' || $driver === 'dblib')
$pdoClass = 'CMssqlPdoAdapter';
elseif ($driver === 'sqlsrv')
$pdoClass = 'CMssqlSqlsrvPdoAdapter';
}
if (! class_exists ( $pdoClass ))
throw new CDbException ( Yii::t ( 'yii', 'CDbConnection is unable to find PDO class "{className}". Make sure PDO is installed correctly.', array (
'{className}' => $pdoClass
) ) );
@$instance = new $pdoClass ( $this->connectionString, $this->username, $this->password, $this->_attributes );
if (! $instance)
throw new CDbException ( Yii::t ( 'yii', 'CDbConnection failed to open the DB connection.' ) );
return $instance;
}
protected function initConnection($pdo) {
$pdo->setAttribute ( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
if ($this->emulatePrepare !== null && constant ( 'PDO::ATTR_EMULATE_PREPARES' ))
$pdo->setAttribute ( PDO::ATTR_EMULATE_PREPARES, $this->emulatePrepare );
if ($this->charset !== null) {
$driver = strtolower ( $pdo->getAttribute ( PDO::ATTR_DRIVER_NAME ) );
if (in_array ( $driver, array (
'pgsql',
'mysql',
'mysqli'
) ))
$pdo->exec ( 'SET NAMES ' . $pdo->quote ( $this->charset ) );
}
if ($this->initSQLs !== null) {
foreach ( $this->initSQLs as $sql )
$pdo->exec ( $sql );
}
}
public function getPdoInstance() {
return $this->_pdo;
}
public function createCommand($query = null) {
$this->setActive ( true );
return new CDbCommand ( $this, $query );
}
public function getCurrentTransaction() {
if ($this->_transaction !== null) {
if ($this->_transaction->getActive ())
return $this->_transaction;
}
return null;
}
public function beginTransaction() {
$this->setActive ( true );
$this->_pdo->beginTransaction ();
return $this->_transaction = new CDbTransaction ( $this );
}
public function getSchema() {
if ($this->_schema !== null)
return $this->_schema;
else {
$driver = $this->getDriverName ();
if (isset ( $this->driverMap [$driver] ))
return $this->_schema = Yii::createComponent ( $this->driverMap [$driver], $this );
else
throw new CDbException ( Yii::t ( 'yii', 'CDbConnection does not support reading schema for {driver} database.', array (
'{driver}' => $driver
) ) );
}
}
public function getCommandBuilder() {
return $this->getSchema ()->getCommandBuilder ();
}
public function getLastInsertID($sequenceName = '') {
$this->setActive ( true );
return $this->_pdo->lastInsertId ( $sequenceName );
}
public function quoteValue($str) {
if (is_int ( $str ) || is_float ( $str ))
return $str;
$this->setActive ( true );
if (($value = $this->_pdo->quote ( $str )) !== false)
return $value;
else // the driver doesn't support quote (e.g. oci)
return "'" . addcslashes ( str_replace ( "'", "''", $str ), "\000\n\r\\\032" ) . "'";
}
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,
'resource' => PDO::PARAM_LOB,
'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() {
if (($pos = strpos ( $this->connectionString, ':' )) !== false)
return strtolower ( substr ( $this->connectionString, 0, $pos ) );
// 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) {
$this->setActive ( true );
return $this->_pdo->getAttribute ( $name );
}
public function setAttribute($name, $value) {
if ($this->_pdo instanceof PDO)
$this->_pdo->setAttribute ( $name, $value );
else
$this->_attributes [$name] = $value;
}
public function getAttributes() {
return $this->_attributes;
}
public function setAttributes($values) {
foreach ( $values as $name => $value )
$this->_attributes [$name] = $value;
}
public function getStats() {
$logger = Yii::getLogger ();
$timings = $logger->getProfilingResults ( null, 'system.db.CDbCommand.query' );
$count = count ( $timings );
$time = array_sum ( $timings );
$timings = $logger->getProfilingResults ( null, 'system.db.CDbCommand.execute' );
$count += count ( $timings );
$time += array_sum ( $timings );
return array (
$count,
$time
);
}
}
abstract class CDbSchema extends CComponent {
public $columnTypes = array ();
private $_tableNames = array ();
private $_tables = array ();
private $_connection;
private $_builder;
private $_cacheExclude = array ();
abstract protected function loadTable($name);
public function __construct($conn) {
$this->_connection = $conn;
foreach ( $conn->schemaCachingExclude as $name )
$this->_cacheExclude [$name] = true;
}
public function getDbConnection() {
return $this->_connection;
}
public function getTable($name, $refresh = false) {
if ($refresh === false && isset ( $this->_tables [$name] ))
return $this->_tables [$name];
else {
if ($this->_connection->tablePrefix !== null && strpos ( $name, '{{' ) !== false)
$realName = preg_replace ( '/\{\{(.*?)\}\}/', $this->_connection->tablePrefix . '$1', $name );
else
$realName = $name;
// temporarily disable query caching
if ($this->_connection->queryCachingDuration > 0) {
$qcDuration = $this->_connection->queryCachingDuration;
$this->_connection->queryCachingDuration = 0;
}
if (! isset ( $this->_cacheExclude [$name] ) && ($duration = $this->_connection->schemaCachingDuration) > 0 && $this->_connection->schemaCacheID !== false && ($cache = Yii::app ()->getComponent ( $this->_connection->schemaCacheID )) !== null) {
$key = 'yii:dbschema' . $this->_connection->connectionString . ':' . $this->_connection->username . ':' . $name;
$table = $cache->get ( $key );
if ($refresh === true || $table === false) {
$table = $this->loadTable ( $realName );
if ($table !== null)
$cache->set ( $key, $table, $duration );
}
$this->_tables [$name] = $table;
} else
$this->_tables [$name] = $table = $this->loadTable ( $realName );
if (isset ( $qcDuration )) // re-enable query caching
$this->_connection->queryCachingDuration = $qcDuration;
return $table;
}
}
public function getTables($schema = '') {
$tables = array ();
foreach ( $this->getTableNames ( $schema ) as $name ) {
if (($table = $this->getTable ( $name )) !== null)
$tables [$name] = $table;
}
return $tables;
}
public function getTableNames($schema = '') {
if (! isset ( $this->_tableNames [$schema] ))
$this->_tableNames [$schema] = $this->findTableNames ( $schema );
return $this->_tableNames [$schema];
}
public function getCommandBuilder() {
if ($this->_builder !== null)
return $this->_builder;
else
return $this->_builder = $this->createCommandBuilder ();
}
public function refresh() {
if (($duration = $this->_connection->schemaCachingDuration) > 0 && $this->_connection->schemaCacheID !== false && ($cache = Yii::app ()->getComponent ( $this->_connection->schemaCacheID )) !== null) {
foreach ( array_keys ( $this->_tables ) as $name ) {
if (! isset ( $this->_cacheExclude [$name] )) {
$key = 'yii:dbschema' . $this->_connection->connectionString . ':' . $this->_connection->username . ':' . $name;
$cache->delete ( $key );
}
}
}
$this->_tables = array ();
$this->_tableNames = array ();
$this->_builder = null;
}
public function quoteTableName($name) {
if (strpos ( $name, '.' ) === false)
return $this->quoteSimpleTableName ( $name );
$parts = explode ( '.', $name );
foreach ( $parts as $i => $part )
$parts [$i] = $this->quoteSimpleTableName ( $part );
return implode ( '.', $parts );
}
public function quoteSimpleTableName($name) {
return "'" . $name . "'";
}
public function quoteColumnName($name) {
if (($pos = strrpos ( $name, '.' )) !== false) {
$prefix = $this->quoteTableName ( substr ( $name, 0, $pos ) ) . '.';
$name = substr ( $name, $pos + 1 );
} else
$prefix = '';
return $prefix . ($name === '*' ? $name : $this->quoteSimpleColumnName ( $name ));
}
public function quoteSimpleColumnName($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 );
if ($this->_connection->tablePrefix !== null) {
if (strpos ( $name1, '{' ) !== false)
$name1 = $this->_connection->tablePrefix . str_replace ( array (
'{',
'}'
), '', $name1 );
if (strpos ( $name2, '{' ) !== false)
$name2 = $this->_connection->tablePrefix . str_replace ( array (
'{',
'}'
), '', $name2 );
}
return $name1 === $name2;
}
public function resetSequence($table, $value = null) {
}
public function checkIntegrity($check = true, $schema = '') {
}
protected function createCommandBuilder() {
return new CDbCommandBuilder ( $this );
}
protected function findTableNames($schema = '') {
throw new CDbException ( Yii::t ( 'yii', '{class} does not support fetching all table names.', array (
'{class}' => get_class ( $this )
) ) );
}
public function getColumnType($type) {
if (isset ( $this->columnTypes [$type] ))
return $this->columnTypes [$type];
elseif (($pos = strpos ( $type, ' ' )) !== false) {
$t = substr ( $type, 0, $pos );
return (isset ( $this->columnTypes [$t] ) ? $this->columnTypes [$t] : $t) . substr ( $type, $pos );
} else
return $type;
}
public function createTable($table, $columns, $options = null) {
$cols = array ();
foreach ( $columns as $name => $type ) {
if (is_string ( $name ))
$cols [] = "\t" . $this->quoteColumnName ( $name ) . ' ' . $this->getColumnType ( $type );
else
$cols [] = "\t" . $type;
}
$sql = "CREATE TABLE " . $this->quoteTableName ( $table ) . " (\n" . implode ( ",\n", $cols ) . "\n)";
return $options === null ? $sql : $sql . ' ' . $options;
}
public function renameTable($table, $newName) {
return 'RENAME TABLE ' . $this->quoteTableName ( $table ) . ' TO ' . $this->quoteTableName ( $newName );
}
public function dropTable($table) {
return "DROP TABLE " . $this->quoteTableName ( $table );
}
public function truncateTable($table) {
return "TRUNCATE TABLE " . $this->quoteTableName ( $table );
}
public function addColumn($table, $column, $type) {
return 'ALTER TABLE ' . $this->quoteTableName ( $table ) . ' ADD ' . $this->quoteColumnName ( $column ) . ' ' . $this->getColumnType ( $type );
}
public function dropColumn($table, $column) {
return "ALTER TABLE " . $this->quoteTableName ( $table ) . " DROP COLUMN " . $this->quoteColumnName ( $column );
}
public function renameColumn($table, $name, $newName) {
return "ALTER TABLE " . $this->quoteTableName ( $table ) . " RENAME COLUMN " . $this->quoteColumnName ( $name ) . " TO " . $this->quoteColumnName ( $newName );
}
public function alterColumn($table, $column, $type) {
return 'ALTER TABLE ' . $this->quoteTableName ( $table ) . ' CHANGE ' . $this->quoteColumnName ( $column ) . ' ' . $this->quoteColumnName ( $column ) . ' ' . $this->getColumnType ( $type );
}
public function addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete = null, $update = null) {
$columns = preg_split ( '/\s*,\s*/', $columns, - 1, PREG_SPLIT_NO_EMPTY );
foreach ( $columns as $i => $col )
$columns [$i] = $this->quoteColumnName ( $col );
$refColumns = preg_split ( '/\s*,\s*/', $refColumns, - 1, PREG_SPLIT_NO_EMPTY );
foreach ( $refColumns as $i => $col )
$refColumns [$i] = $this->quoteColumnName ( $col );
$sql = 'ALTER TABLE ' . $this->quoteTableName ( $table ) . ' ADD CONSTRAINT ' . $this->quoteColumnName ( $name ) . ' FOREIGN KEY (' . implode ( ', ', $columns ) . ')' . ' REFERENCES ' . $this->quoteTableName ( $refTable ) . ' (' . implode ( ', ', $refColumns ) . ')';
if ($delete !== null)
$sql .= ' ON DELETE ' . $delete;
if ($update !== null)
$sql .= ' ON UPDATE ' . $update;
return $sql;
}
public function dropForeignKey($name, $table) {
return 'ALTER TABLE ' . $this->quoteTableName ( $table ) . ' DROP CONSTRAINT ' . $this->quoteColumnName ( $name );
}
public function createIndex($name, $table, $column, $unique = false) {
$cols = array ();
$columns = preg_split ( '/\s*,\s*/', $column, - 1, PREG_SPLIT_NO_EMPTY );
foreach ( $columns as $col ) {
if (strpos ( $col, '(' ) !== false)
$cols [] = $col;
else
$cols [] = $this->quoteColumnName ( $col );
}
return ($unique ? 'CREATE UNIQUE INDEX ' : 'CREATE INDEX ') . $this->quoteTableName ( $name ) . ' ON ' . $this->quoteTableName ( $table ) . ' (' . implode ( ', ', $cols ) . ')';
}
public function dropIndex($name, $table) {
return 'DROP INDEX ' . $this->quoteTableName ( $name ) . ' ON ' . $this->quoteTableName ( $table );
}
public function addPrimaryKey($name, $table, $columns) {
if (is_string ( $columns ))
$columns = preg_split ( '/\s*,\s*/', $columns, - 1, PREG_SPLIT_NO_EMPTY );
foreach ( $columns as $i => $col )
$columns [$i] = $this->quoteColumnName ( $col );
return 'ALTER TABLE ' . $this->quoteTableName ( $table ) . ' ADD CONSTRAINT ' . $this->quoteColumnName ( $name ) . ' PRIMARY KEY (' . implode ( ', ', $columns ) . ' )';
}
public function dropPrimaryKey($name, $table) {
return 'ALTER TABLE ' . $this->quoteTableName ( $table ) . ' DROP CONSTRAINT ' . $this->quoteColumnName ( $name );
}
}
class CSqliteSchema extends CDbSchema {
public $columnTypes = array (
'pk' => 'integer PRIMARY KEY AUTOINCREMENT NOT NULL',
'string' => 'varchar(255)',
'text' => 'text',
'integer' => 'integer',
'float' => 'float',
'decimal' => 'decimal',
'datetime' => 'datetime',
'timestamp' => 'timestamp',
'time' => 'time',
'date' => 'date',
'binary' => 'blob',
'boolean' => 'tinyint(1)',
'money' => 'decimal(19,4)'
);
public function resetSequence($table, $value = null) {
if ($table->sequenceName === null)
return;
if ($value !== null)
$value = ( int ) ($value) - 1;
else
$value = ( int ) $this->getDbConnection ()->createCommand ( "SELECT MAX(`{$table->primaryKey}`) FROM {$table->rawName}" )->queryScalar ();
try {
// it's possible that 'sqlite_sequence' does not exist
$this->getDbConnection ()->createCommand ( "UPDATE sqlite_sequence SET seq='$value' WHERE name='{$table->name}'" )->execute ();
} catch ( Exception $e ) {
}
}
public function checkIntegrity($check = true, $schema = '') {
$this->getDbConnection ()->createCommand ( 'PRAGMA foreign_keys=' . ( int ) $check )->execute ();
}
protected function findTableNames($schema = '') {
$sql = "SELECT DISTINCT tbl_name FROM sqlite_master WHERE tbl_name<>'sqlite_sequence'";
return $this->getDbConnection ()->createCommand ( $sql )->queryColumn ();
}
protected function createCommandBuilder() {
return new CSqliteCommandBuilder ( $this );
}
protected function loadTable($name) {
$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;
elseif (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 = '';
$table->columns [$table->primaryKey]->autoIncrement = true;
}
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->comment = null; // SQLite does not support column comments at all
$c->init ( strtolower ( $column ['type'] ), $column ['dflt_value'] );
return $c;
}
public function renameTable($table, $newName) {
return 'ALTER TABLE ' . $this->quoteTableName ( $table ) . ' RENAME TO ' . $this->quoteTableName ( $newName );
}
public function truncateTable($table) {
return "DELETE FROM " . $this->quoteTableName ( $table );
}
public function dropColumn($table, $column) {
throw new CDbException ( Yii::t ( 'yii', 'Dropping DB column is not supported by SQLite.' ) );
}
public function renameColumn($table, $name, $newName) {
throw new CDbException ( Yii::t ( 'yii', 'Renaming a DB column is not supported by SQLite.' ) );
}
public function addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete = null, $update = null) {
throw new CDbException ( Yii::t ( 'yii', 'Adding a foreign key constraint to an existing table is not supported by SQLite.' ) );
}
public function dropForeignKey($name, $table) {
throw new CDbException ( Yii::t ( 'yii', 'Dropping a foreign key constraint is not supported by SQLite.' ) );
}
public function alterColumn($table, $column, $type) {
throw new CDbException ( Yii::t ( 'yii', 'Altering a DB column is not supported by SQLite.' ) );
}
public function dropIndex($name, $table) {
return 'DROP INDEX ' . $this->quoteTableName ( $name );
}
public function addPrimaryKey($name, $table, $columns) {
throw new CDbException ( Yii::t ( 'yii', 'Adding a primary key after table has been created is not supported by SQLite.' ) );
}
public function dropPrimaryKey($name, $table) {
throw new CDbException ( Yii::t ( 'yii', 'Removing a primary key after table has been created is not supported by SQLite.' ) );
}
}
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 {
public $params = array ();
private $_connection;
private $_text;
private $_statement;
private $_paramLog = array ();
private $_query;
private $_fetchMode = array (
PDO::FETCH_ASSOC
);
public function __construct(CDbConnection $connection, $query = null) {
$this->_connection = $connection;
if (is_array ( $query )) {
foreach ( $query as $name => $value )
$this->$name = $value;
} else
$this->setText ( $query );
}
public function __sleep() {
$this->_statement = null;
return array_keys ( get_object_vars ( $this ) );
}
public function setFetchMode($mode) {
$params = func_get_args ();
$this->_fetchMode = $params;
return $this;
}
public function reset() {
$this->_text = null;
$this->_query = null;
$this->_statement = null;
$this->_paramLog = array ();
$this->params = array ();
return $this;
}
public function getText() {
if ($this->_text == '' && ! empty ( $this->_query ))
$this->setText ( $this->buildQuery ( $this->_query ) );
return $this->_text;
}
public function setText($value) {
if ($this->_connection->tablePrefix !== null && $value != '')
$this->_text = preg_replace ( '/{{(.*?)}}/', $this->_connection->tablePrefix . '\1', $value );
else
$this->_text = $value;
$this->cancel ();
return $this;
}
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 () );
$this->_paramLog = array ();
} catch ( Exception $e ) {
Yii::log ( 'Error in preparing SQL: ' . $this->getText (), CLogger::LEVEL_ERROR, 'system.db.CDbCommand' );
$errorInfo = $e instanceof PDOException ? $e->errorInfo : null;
throw new CDbException ( Yii::t ( 'yii', 'CDbCommand failed to prepare the SQL statement: {error}', array (
'{error}' => $e->getMessage ()
) ), ( int ) $e->getCode (), $errorInfo );
}
}
}
public function cancel() {
$this->_statement = null;
}
public function bindParam($name, &$value, $dataType = null, $length = null, $driverOptions = null) {
$this->prepare ();
if ($dataType === null)
$this->_statement->bindParam ( $name, $value, $this->_connection->getPdoType ( gettype ( $value ) ) );
elseif ($length === null)
$this->_statement->bindParam ( $name, $value, $dataType );
elseif ($driverOptions === null)
$this->_statement->bindParam ( $name, $value, $dataType, $length );
else
$this->_statement->bindParam ( $name, $value, $dataType, $length, $driverOptions );
$this->_paramLog [$name] = &$value;
return $this;
}
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 );
$this->_paramLog [$name] = $value;
return $this;
}
public function bindValues($values) {
$this->prepare ();
foreach ( $values as $name => $value ) {
$this->_statement->bindValue ( $name, $value, $this->_connection->getPdoType ( gettype ( $value ) ) );
$this->_paramLog [$name] = $value;
}
return $this;
}
public function execute($params = array()) {
if ($this->_connection->enableParamLogging && ($pars = array_merge ( $this->_paramLog, $params )) !== array ()) {
$p = array ();
foreach ( $pars as $name => $value )
$p [$name] = $name . '=' . var_export ( $value, true );
$par = '. Bound with ' . implode ( ', ', $p );
} else
$par = '';
try {
if ($this->_connection->enableProfiling)
Yii::beginProfile ( 'system.db.CDbCommand.execute(' . $this->getText () . $par . ')', 'system.db.CDbCommand.execute' );
$this->prepare ();
if ($params === array ())
$this->_statement->execute ();
else
$this->_statement->execute ( $params );
$n = $this->_statement->rowCount ();
if ($this->_connection->enableProfiling)
Yii::endProfile ( 'system.db.CDbCommand.execute(' . $this->getText () . $par . ')', 'system.db.CDbCommand.execute' );
return $n;
} catch ( Exception $e ) {
if ($this->_connection->enableProfiling)
Yii::endProfile ( 'system.db.CDbCommand.execute(' . $this->getText () . $par . ')', 'system.db.CDbCommand.execute' );
$errorInfo = $e instanceof PDOException ? $e->errorInfo : null;
$message = $e->getMessage ();
Yii::log ( Yii::t ( 'yii', 'CDbCommand::execute() failed: {error}. The SQL statement executed was: {sql}.', array (
'{error}' => $message,
'{sql}' => $this->getText () . $par
) ), CLogger::LEVEL_ERROR, 'system.db.CDbCommand' );
if (YII_DEBUG)
$message .= '. The SQL statement executed was: ' . $this->getText () . $par;
throw new CDbException ( Yii::t ( 'yii', 'CDbCommand failed to execute the SQL statement: {error}', array (
'{error}' => $message
) ), ( int ) $e->getCode (), $errorInfo );
}
}
public function query($params = array()) {
return $this->queryInternal ( '', 0, $params );
}
public function queryAll($fetchAssociative = true, $params = array()) {
return $this->queryInternal ( 'fetchAll', $fetchAssociative ? $this->_fetchMode : PDO::FETCH_NUM, $params );
}
public function queryRow($fetchAssociative = true, $params = array()) {
return $this->queryInternal ( 'fetch', $fetchAssociative ? $this->_fetchMode : PDO::FETCH_NUM, $params );
}
public function queryScalar($params = array()) {
$result = $this->queryInternal ( 'fetchColumn', 0, $params );
if (is_resource ( $result ) && get_resource_type ( $result ) === 'stream')
return stream_get_contents ( $result );
else
return $result;
}
public function queryColumn($params = array()) {
return $this->queryInternal ( 'fetchAll', array (
PDO::FETCH_COLUMN,
0
), $params );
}
private function queryInternal($method, $mode, $params = array()) {
$params = array_merge ( $this->params, $params );
if ($this->_connection->enableParamLogging && ($pars = array_merge ( $this->_paramLog, $params )) !== array ()) {
$p = array ();
foreach ( $pars as $name => $value )
$p [$name] = $name . '=' . var_export ( $value, true );
$par = '. Bound with ' . implode ( ', ', $p );
} else
$par = '';
if ($this->_connection->queryCachingCount > 0 && $method !== '' && $this->_connection->queryCachingDuration > 0 && $this->_connection->queryCacheID !== false && ($cache = Yii::app ()->getComponent ( $this->_connection->queryCacheID )) !== null) {
$this->_connection->queryCachingCount --;
$cacheKey = 'yii:dbquery' . $this->_connection->connectionString . ':' . $this->_connection->username;
$cacheKey .= ':' . $this->getText () . ':' . serialize ( array_merge ( $this->_paramLog, $params ) );
if (($result = $cache->get ( $cacheKey )) !== false) {
return $result [0];
}
}
try {
if ($this->_connection->enableProfiling)
Yii::beginProfile ( 'system.db.CDbCommand.query(' . $this->getText () . $par . ')', 'system.db.CDbCommand.query' );
$this->prepare ();
if ($params === array ())
$this->_statement->execute ();
else
$this->_statement->execute ( $params );
if ($method === '')
$result = new CDbDataReader ( $this );
else {
$mode = ( array ) $mode;
call_user_func_array ( array (
$this->_statement,
'setFetchMode'
), $mode );
$result = $this->_statement->$method ();
$this->_statement->closeCursor ();
}
if ($this->_connection->enableProfiling)
Yii::endProfile ( 'system.db.CDbCommand.query(' . $this->getText () . $par . ')', 'system.db.CDbCommand.query' );
if (isset ( $cache, $cacheKey ))
$cache->set ( $cacheKey, array (
$result
), $this->_connection->queryCachingDuration, $this->_connection->queryCachingDependency );
return $result;
} catch ( Exception $e ) {
if ($this->_connection->enableProfiling)
Yii::endProfile ( 'system.db.CDbCommand.query(' . $this->getText () . $par . ')', 'system.db.CDbCommand.query' );
$errorInfo = $e instanceof PDOException ? $e->errorInfo : null;
$message = $e->getMessage ();
Yii::log ( Yii::t ( 'yii', 'CDbCommand::{method}() failed: {error}. The SQL statement executed was: {sql}.', array (
'{method}' => $method,
'{error}' => $message,
'{sql}' => $this->getText () . $par
) ), CLogger::LEVEL_ERROR, 'system.db.CDbCommand' );
if (YII_DEBUG)
$message .= '. The SQL statement executed was: ' . $this->getText () . $par;
throw new CDbException ( Yii::t ( 'yii', 'CDbCommand failed to execute the SQL statement: {error}', array (
'{error}' => $message
) ), ( int ) $e->getCode (), $errorInfo );
}
}
public function buildQuery($query) {
$sql = ! empty ( $query ['distinct'] ) ? 'SELECT DISTINCT' : 'SELECT';
$sql .= ' ' . (! empty ( $query ['select'] ) ? $query ['select'] : '*');
if (! empty ( $query ['from'] ))
$sql .= "\nFROM " . $query ['from'];
else
throw new CDbException ( Yii::t ( 'yii', 'The DB query must contain the "from" portion.' ) );
if (! empty ( $query ['join'] ))
$sql .= "\n" . (is_array ( $query ['join'] ) ? implode ( "\n", $query ['join'] ) : $query ['join']);
if (! empty ( $query ['where'] ))
$sql .= "\nWHERE " . $query ['where'];
if (! empty ( $query ['group'] ))
$sql .= "\nGROUP BY " . $query ['group'];
if (! empty ( $query ['having'] ))
$sql .= "\nHAVING " . $query ['having'];
if (! empty ( $query ['union'] ))
$sql .= "\nUNION (\n" . (is_array ( $query ['union'] ) ? implode ( "\n) UNION (\n", $query ['union'] ) : $query ['union']) . ')';
if (! empty ( $query ['order'] ))
$sql .= "\nORDER BY " . $query ['order'];
$limit = isset ( $query ['limit'] ) ? ( int ) $query ['limit'] : - 1;
$offset = isset ( $query ['offset'] ) ? ( int ) $query ['offset'] : - 1;
if ($limit >= 0 || $offset > 0)
$sql = $this->_connection->getCommandBuilder ()->applyLimit ( $sql, $limit, $offset );
return $sql;
}
public function select($columns = '*', $option = '') {
if (is_string ( $columns ) && strpos ( $columns, '(' ) !== false)
$this->_query ['select'] = $columns;
else {
if (! is_array ( $columns ))
$columns = preg_split ( '/\s*,\s*/', trim ( $columns ), - 1, PREG_SPLIT_NO_EMPTY );
foreach ( $columns as $i => $column ) {
if (is_object ( $column ))
$columns [$i] = ( string ) $column;
elseif (strpos ( $column, '(' ) === false) {
if (preg_match ( '/^(.*?)(?i:\s+as\s+|\s+)(.*)$/', $column, $matches ))
$columns [$i] = $this->_connection->quoteColumnName ( $matches [1] ) . ' AS ' . $this->_connection->quoteColumnName ( $matches [2] );
else
$columns [$i] = $this->_connection->quoteColumnName ( $column );
}
}
$this->_query ['select'] = implode ( ', ', $columns );
}
if ($option != '')
$this->_query ['select'] = $option . ' ' . $this->_query ['select'];
return $this;
}
public function getSelect() {
return isset ( $this->_query ['select'] ) ? $this->_query ['select'] : '';
}
public function setSelect($value) {
$this->select ( $value );
}
public function selectDistinct($columns = '*') {
$this->_query ['distinct'] = true;
return $this->select ( $columns );
}
public function getDistinct() {
return isset ( $this->_query ['distinct'] ) ? $this->_query ['distinct'] : false;
}
public function setDistinct($value) {
$this->_query ['distinct'] = $value;
}
public function from($tables) {
if (is_string ( $tables ) && strpos ( $tables, '(' ) !== false)
$this->_query ['from'] = $tables;
else {
if (! is_array ( $tables ))
$tables = preg_split ( '/\s*,\s*/', trim ( $tables ), - 1, PREG_SPLIT_NO_EMPTY );
foreach ( $tables as $i => $table ) {
if (strpos ( $table, '(' ) === false) {
if (preg_match ( '/^(.*?)(?i:\s+as\s+|\s+)(.*)$/', $table, $matches )) // with alias
$tables [$i] = $this->_connection->quoteTableName ( $matches [1] ) . ' ' . $this->_connection->quoteTableName ( $matches [2] );
else
$tables [$i] = $this->_connection->quoteTableName ( $table );
}
}
$this->_query ['from'] = implode ( ', ', $tables );
}
return $this;
}
public function getFrom() {
return isset ( $this->_query ['from'] ) ? $this->_query ['from'] : '';
}
public function setFrom($value) {
$this->from ( $value );
}
public function where($conditions, $params = array()) {
$this->_query ['where'] = $this->processConditions ( $conditions );
foreach ( $params as $name => $value )
$this->params [$name] = $value;
return $this;
}
public function andWhere($conditions, $params = array()) {
if (isset ( $this->_query ['where'] ))
$this->_query ['where'] = $this->processConditions ( array (
'AND',
$this->_query ['where'],
$conditions
) );
else
$this->_query ['where'] = $this->processConditions ( $conditions );
foreach ( $params as $name => $value )
$this->params [$name] = $value;
return $this;
}
public function orWhere($conditions, $params = array()) {
if (isset ( $this->_query ['where'] ))
$this->_query ['where'] = $this->processConditions ( array (
'OR',
$this->_query ['where'],
$conditions
) );
else
$this->_query ['where'] = $this->processConditions ( $conditions );
foreach ( $params as $name => $value )
$this->params [$name] = $value;
return $this;
}
public function getWhere() {
return isset ( $this->_query ['where'] ) ? $this->_query ['where'] : '';
}
public function setWhere($value) {
$this->where ( $value );
}
public function join($table, $conditions, $params = array()) {
return $this->joinInternal ( 'join', $table, $conditions, $params );
}
public function getJoin() {
return isset ( $this->_query ['join'] ) ? $this->_query ['join'] : '';
}
public function setJoin($value) {
$this->_query ['join'] = $value;
}
public function leftJoin($table, $conditions, $params = array()) {
return $this->joinInternal ( 'left join', $table, $conditions, $params );
}
public function rightJoin($table, $conditions, $params = array()) {
return $this->joinInternal ( 'right join', $table, $conditions, $params );
}
public function crossJoin($table) {
return $this->joinInternal ( 'cross join', $table );
}
public function naturalJoin($table) {
return $this->joinInternal ( 'natural join', $table );
}
public function group($columns) {
if (is_string ( $columns ) && strpos ( $columns, '(' ) !== false)
$this->_query ['group'] = $columns;
else {
if (! is_array ( $columns ))
$columns = preg_split ( '/\s*,\s*/', trim ( $columns ), - 1, PREG_SPLIT_NO_EMPTY );
foreach ( $columns as $i => $column ) {
if (is_object ( $column ))
$columns [$i] = ( string ) $column;
elseif (strpos ( $column, '(' ) === false)
$columns [$i] = $this->_connection->quoteColumnName ( $column );
}
$this->_query ['group'] = implode ( ', ', $columns );
}
return $this;
}
public function getGroup() {
return isset ( $this->_query ['group'] ) ? $this->_query ['group'] : '';
}
public function setGroup($value) {
$this->group ( $value );
}
public function having($conditions, $params = array()) {
$this->_query ['having'] = $this->processConditions ( $conditions );
foreach ( $params as $name => $value )
$this->params [$name] = $value;
return $this;
}
public function getHaving() {
return isset ( $this->_query ['having'] ) ? $this->_query ['having'] : '';
}
public function setHaving($value) {
$this->having ( $value );
}
public function order($columns) {
if (is_string ( $columns ) && strpos ( $columns, '(' ) !== false)
$this->_query ['order'] = $columns;
else {
if (! is_array ( $columns ))
$columns = preg_split ( '/\s*,\s*/', trim ( $columns ), - 1, PREG_SPLIT_NO_EMPTY );
foreach ( $columns as $i => $column ) {
if (is_object ( $column ))
$columns [$i] = ( string ) $column;
elseif (strpos ( $column, '(' ) === false) {
if (preg_match ( '/^(.*?)\s+(asc|desc)$/i', $column, $matches ))
$columns [$i] = $this->_connection->quoteColumnName ( $matches [1] ) . ' ' . strtoupper ( $matches [2] );
else
$columns [$i] = $this->_connection->quoteColumnName ( $column );
}
}
$this->_query ['order'] = implode ( ', ', $columns );
}
return $this;
}
public function getOrder() {
return isset ( $this->_query ['order'] ) ? $this->_query ['order'] : '';
}
public function setOrder($value) {
$this->order ( $value );
}
public function limit($limit, $offset = null) {
$this->_query ['limit'] = ( int ) $limit;
if ($offset !== null)
$this->offset ( $offset );
return $this;
}
public function getLimit() {
return isset ( $this->_query ['limit'] ) ? $this->_query ['limit'] : - 1;
}
public function setLimit($value) {
$this->limit ( $value );
}
public function offset($offset) {
$this->_query ['offset'] = ( int ) $offset;
return $this;
}
public function getOffset() {
return isset ( $this->_query ['offset'] ) ? $this->_query ['offset'] : - 1;
}
public function setOffset($value) {
$this->offset ( $value );
}
public function union($sql) {
if (isset ( $this->_query ['union'] ) && is_string ( $this->_query ['union'] ))
$this->_query ['union'] = array (
$this->_query ['union']
);
$this->_query ['union'] [] = $sql;
return $this;
}
public function getUnion() {
return isset ( $this->_query ['union'] ) ? $this->_query ['union'] : '';
}
public function setUnion($value) {
$this->_query ['union'] = $value;
}
public function insert($table, $columns) {
$params = array ();
$names = array ();
$placeholders = array ();
foreach ( $columns as $name => $value ) {
$names [] = $this->_connection->quoteColumnName ( $name );
if ($value instanceof CDbExpression) {
$placeholders [] = $value->expression;
foreach ( $value->params as $n => $v )
$params [$n] = $v;
} else {
$placeholders [] = ':' . $name;
$params [':' . $name] = $value;
}
}
$sql = 'INSERT INTO ' . $this->_connection->quoteTableName ( $table ) . ' (' . implode ( ', ', $names ) . ') VALUES (' . implode ( ', ', $placeholders ) . ')';
return $this->setText ( $sql )->execute ( $params );
}
public function update($table, $columns, $conditions = '', $params = array()) {
$lines = array ();
foreach ( $columns as $name => $value ) {
if ($value instanceof CDbExpression) {
$lines [] = $this->_connection->quoteColumnName ( $name ) . '=' . $value->expression;
foreach ( $value->params as $n => $v )
$params [$n] = $v;
} else {
$lines [] = $this->_connection->quoteColumnName ( $name ) . '=:' . $name;
$params [':' . $name] = $value;
}
}
$sql = 'UPDATE ' . $this->_connection->quoteTableName ( $table ) . ' SET ' . implode ( ', ', $lines );
if (($where = $this->processConditions ( $conditions )) != '')
$sql .= ' WHERE ' . $where;
return $this->setText ( $sql )->execute ( $params );
}
public function delete($table, $conditions = '', $params = array()) {
$sql = 'DELETE FROM ' . $this->_connection->quoteTableName ( $table );
if (($where = $this->processConditions ( $conditions )) != '')
$sql .= ' WHERE ' . $where;
return $this->setText ( $sql )->execute ( $params );
}
public function createTable($table, $columns, $options = null) {
return $this->setText ( $this->getConnection ()->getSchema ()->createTable ( $table, $columns, $options ) )->execute ();
}
public function renameTable($table, $newName) {
return $this->setText ( $this->getConnection ()->getSchema ()->renameTable ( $table, $newName ) )->execute ();
}
public function dropTable($table) {
return $this->setText ( $this->getConnection ()->getSchema ()->dropTable ( $table ) )->execute ();
}
public function truncateTable($table) {
$schema = $this->getConnection ()->getSchema ();
$n = $this->setText ( $schema->truncateTable ( $table ) )->execute ();
if (strncasecmp ( $this->getConnection ()->getDriverName (), 'sqlite', 6 ) === 0)
$schema->resetSequence ( $schema->getTable ( $table ) );
return $n;
}
public function addColumn($table, $column, $type) {
return $this->setText ( $this->getConnection ()->getSchema ()->addColumn ( $table, $column, $type ) )->execute ();
}
public function dropColumn($table, $column) {
return $this->setText ( $this->getConnection ()->getSchema ()->dropColumn ( $table, $column ) )->execute ();
}
public function renameColumn($table, $name, $newName) {
return $this->setText ( $this->getConnection ()->getSchema ()->renameColumn ( $table, $name, $newName ) )->execute ();
}
public function alterColumn($table, $column, $type) {
return $this->setText ( $this->getConnection ()->getSchema ()->alterColumn ( $table, $column, $type ) )->execute ();
}
public function addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete = null, $update = null) {
return $this->setText ( $this->getConnection ()->getSchema ()->addForeignKey ( $name, $table, $columns, $refTable, $refColumns, $delete, $update ) )->execute ();
}
public function dropForeignKey($name, $table) {
return $this->setText ( $this->getConnection ()->getSchema ()->dropForeignKey ( $name, $table ) )->execute ();
}
public function createIndex($name, $table, $column, $unique = false) {
return $this->setText ( $this->getConnection ()->getSchema ()->createIndex ( $name, $table, $column, $unique ) )->execute ();
}
public function dropIndex($name, $table) {
return $this->setText ( $this->getConnection ()->getSchema ()->dropIndex ( $name, $table ) )->execute ();
}
private function processConditions($conditions) {
if (! is_array ( $conditions ))
return $conditions;
elseif ($conditions === array ())
return '';
$n = count ( $conditions );
$operator = strtoupper ( $conditions [0] );
if ($operator === 'OR' || $operator === 'AND') {
$parts = array ();
for($i = 1; $i < $n; ++ $i) {
$condition = $this->processConditions ( $conditions [$i] );
if ($condition !== '')
$parts [] = '(' . $condition . ')';
}
return $parts === array () ? '' : implode ( ' ' . $operator . ' ', $parts );
}
if (! isset ( $conditions [1], $conditions [2] ))
return '';
$column = $conditions [1];
if (strpos ( $column, '(' ) === false)
$column = $this->_connection->quoteColumnName ( $column );
$values = $conditions [2];
if (! is_array ( $values ))
$values = array (
$values
);
if ($operator === 'IN' || $operator === 'NOT IN') {
if ($values === array ())
return $operator === 'IN' ? '0=1' : '';
foreach ( $values as $i => $value ) {
if (is_string ( $value ))
$values [$i] = $this->_connection->quoteValue ( $value );
else
$values [$i] = ( string ) $value;
}
return $column . ' ' . $operator . ' (' . implode ( ', ', $values ) . ')';
}
if ($operator === 'LIKE' || $operator === 'NOT LIKE' || $operator === 'OR LIKE' || $operator === 'OR NOT LIKE') {
if ($values === array ())
return $operator === 'LIKE' || $operator === 'OR LIKE' ? '0=1' : '';
if ($operator === 'LIKE' || $operator === 'NOT LIKE')
$andor = ' AND ';
else {
$andor = ' OR ';
$operator = $operator === 'OR LIKE' ? 'LIKE' : 'NOT LIKE';
}
$expressions = array ();
foreach ( $values as $value )
$expressions [] = $column . ' ' . $operator . ' ' . $this->_connection->quoteValue ( $value );
return implode ( $andor, $expressions );
}
throw new CDbException ( Yii::t ( 'yii', 'Unknown operator "{operator}".', array (
'{operator}' => $operator
) ) );
}
private function joinInternal($type, $table, $conditions = '', $params = array()) {
if (strpos ( $table, '(' ) === false) {
if (preg_match ( '/^(.*?)(?i:\s+as\s+|\s+)(.*)$/', $table, $matches )) // with alias
$table = $this->_connection->quoteTableName ( $matches [1] ) . ' ' . $this->_connection->quoteTableName ( $matches [2] );
else
$table = $this->_connection->quoteTableName ( $table );
}
$conditions = $this->processConditions ( $conditions );
if ($conditions != '')
$conditions = ' ON ' . $conditions;
if (isset ( $this->_query ['join'] ) && is_string ( $this->_query ['join'] ))
$this->_query ['join'] = array (
$this->_query ['join']
);
$this->_query ['join'] [] = strtoupper ( $type ) . ' ' . $table . $conditions;
foreach ( $params as $name => $value )
$this->params [$name] = $value;
return $this;
}
public function addPrimaryKey($name, $table, $columns) {
return $this->setText ( $this->getConnection ()->getSchema ()->addPrimaryKey ( $name, $table, $columns ) )->execute ();
}
public function dropPrimaryKey($name, $table) {
return $this->setText ( $this->getConnection ()->getSchema ()->dropPrimaryKey ( $name, $table ) )->execute ();
}
}
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 $autoIncrement = false;
public $comment = '';
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 && stripos ( $dbType, 'unsigned int' ) === false)
$this->type = 'integer';
elseif (stripos ( $dbType, 'bool' ) !== false)
$this->type = 'boolean';
elseif (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 || $value instanceof CDbExpression)
return $value;
if ($value === '' && $this->allowNull)
return $this->type === 'string' ? '' : null;
switch ($this->type) {
case 'string' :
return ( string ) $value;
case 'integer' :
return ( integer ) $value;
case 'boolean' :
return ( boolean ) $value;
case 'double' :
default :
return $value;
}
}
}
class CSqliteColumnSchema extends CDbColumnSchema {
protected function extractDefault($defaultValue) {
if ($this->dbType === 'timestamp' && $defaultValue === 'CURRENT_TIMESTAMP')
$this->defaultValue = null;
else
$this->defaultValue = $this->typecast ( strcasecmp ( $defaultValue, 'null' ) ? $defaultValue : null );
if ($this->type === 'string' && $this->defaultValue !== null) // PHP 5.2.6 adds single quotes while 5.2.0 doesn't
$this->defaultValue = trim ( $this->defaultValue, "'\"" );
}
}
abstract class CValidator extends CComponent {
public static $builtInValidators = array (
'required' => 'CRequiredValidator',
'filter' => 'CFilterValidator',
'match' => 'CRegularExpressionValidator',
'email' => 'CEmailValidator',
'url' => 'CUrlValidator',
'unique' => 'CUniqueValidator',
'compare' => 'CCompareValidator',
'length' => 'CStringValidator',
'in' => 'CRangeValidator',
'numerical' => 'CNumberValidator',
'captcha' => 'CCaptchaValidator',
'type' => 'CTypeValidator',
'file' => 'CFileValidator',
'default' => 'CDefaultValueValidator',
'exist' => 'CExistValidator',
'boolean' => 'CBooleanValidator',
'safe' => 'CSafeValidator',
'unsafe' => 'CUnsafeValidator',
'date' => 'CDateValidator'
);
public $attributes;
public $message;
public $skipOnError = false;
public $on;
public $except;
public $safe = true;
public $enableClientValidation = true;
abstract protected function validateAttribute($object, $attribute);
public static function createValidator($name, $object, $attributes, $params = array()) {
if (is_string ( $attributes ))
$attributes = preg_split ( '/[\s,]+/', $attributes, - 1, PREG_SPLIT_NO_EMPTY );
if (isset ( $params ['on'] )) {
if (is_array ( $params ['on'] ))
$on = $params ['on'];
else
$on = preg_split ( '/[\s,]+/', $params ['on'], - 1, PREG_SPLIT_NO_EMPTY );
} else
$on = array ();
if (isset ( $params ['except'] )) {
if (is_array ( $params ['except'] ))
$except = $params ['except'];
else
$except = preg_split ( '/[\s,]+/', $params ['except'], - 1, PREG_SPLIT_NO_EMPTY );
} else
$except = array ();
if (method_exists ( $object, $name )) {
$validator = new CInlineValidator ();
$validator->attributes = $attributes;
$validator->method = $name;
if (isset ( $params ['clientValidate'] )) {
$validator->clientValidate = $params ['clientValidate'];
unset ( $params ['clientValidate'] );
}
$validator->params = $params;
if (isset ( $params ['skipOnError'] ))
$validator->skipOnError = $params ['skipOnError'];
} else {
$params ['attributes'] = $attributes;
if (isset ( self::$builtInValidators [$name] ))
$className = Yii::import ( self::$builtInValidators [$name], true );
else
$className = Yii::import ( $name, true );
$validator = new $className ();
foreach ( $params as $name => $value )
$validator->$name = $value;
}
$validator->on = empty ( $on ) ? array () : array_combine ( $on, $on );
$validator->except = empty ( $except ) ? array () : array_combine ( $except, $except );
return $validator;
}
public function validate($object, $attributes = null) {
if (is_array ( $attributes ))
$attributes = array_intersect ( $this->attributes, $attributes );
else
$attributes = $this->attributes;
foreach ( $attributes as $attribute ) {
if (! $this->skipOnError || ! $object->hasErrors ( $attribute ))
$this->validateAttribute ( $object, $attribute );
}
}
public function clientValidateAttribute($object, $attribute) {
}
public function applyTo($scenario) {
if (isset ( $this->except [$scenario] ))
return false;
return empty ( $this->on ) || isset ( $this->on [$scenario] );
}
protected function addError($object, $attribute, $message, $params = array()) {
$params ['{attribute}'] = $object->getAttributeLabel ( $attribute );
$object->addError ( $attribute, strtr ( $message, $params ) );
}
protected function isEmpty($value, $trim = false) {
return $value === null || $value === array () || $value === '' || $trim && is_scalar ( $value ) && trim ( $value ) === '';
}
}
class CStringValidator extends CValidator {
public $max;
public $min;
public $is;
public $tooShort;
public $tooLong;
public $allowEmpty = true;
public $encoding;
protected function validateAttribute($object, $attribute) {
$value = $object->$attribute;
if ($this->allowEmpty && $this->isEmpty ( $value ))
return;
if (is_array ( $value )) {
// https://github.com/yiisoft/yii/issues/1955
$this->addError ( $object, $attribute, Yii::t ( 'yii', '{attribute} is invalid.' ) );
return;
}
if (function_exists ( 'mb_strlen' ) && $this->encoding !== false)
$length = mb_strlen ( $value, $this->encoding ? $this->encoding : Yii::app ()->charset );
else
$length = strlen ( $value );
if ($this->min !== null && $length < $this->min) {
$message = $this->tooShort !== null ? $this->tooShort : Yii::t ( 'yii', '{attribute} is too short (minimum is {min} characters).' );
$this->addError ( $object, $attribute, $message, array (
'{min}' => $this->min
) );
}
if ($this->max !== null && $length > $this->max) {
$message = $this->tooLong !== null ? $this->tooLong : Yii::t ( 'yii', '{attribute} is too long (maximum is {max} characters).' );
$this->addError ( $object, $attribute, $message, array (
'{max}' => $this->max
) );
}
if ($this->is !== null && $length !== $this->is) {
$message = $this->message !== null ? $this->message : Yii::t ( 'yii', '{attribute} is of the wrong length (should be {length} characters).' );
$this->addError ( $object, $attribute, $message, array (
'{length}' => $this->is
) );
}
}
public function clientValidateAttribute($object, $attribute) {
$label = $object->getAttributeLabel ( $attribute );
if (($message = $this->message) === null)
$message = Yii::t ( 'yii', '{attribute} is of the wrong length (should be {length} characters).' );
$message = strtr ( $message, array (
'{attribute}' => $label,
'{length}' => $this->is
) );
if (($tooShort = $this->tooShort) === null)
$tooShort = Yii::t ( 'yii', '{attribute} is too short (minimum is {min} characters).' );
$tooShort = strtr ( $tooShort, array (
'{attribute}' => $label,
'{min}' => $this->min
) );
if (($tooLong = $this->tooLong) === null)
$tooLong = Yii::t ( 'yii', '{attribute} is too long (maximum is {max} characters).' );
$tooLong = strtr ( $tooLong, array (
'{attribute}' => $label,
'{max}' => $this->max
) );
$js = '';
if ($this->min !== null) {
$js .= "
if(value.length<{$this->min}) {
messages.push(" . CJSON::encode ( $tooShort ) . ");
}
";
}
if ($this->max !== null) {
$js .= "
if(value.length>{$this->max}) {
messages.push(" . CJSON::encode ( $tooLong ) . ");
}
";
}
if ($this->is !== null) {
$js .= "
if(value.length!={$this->is}) {
messages.push(" . CJSON::encode ( $message ) . ");
}
";
}
if ($this->allowEmpty) {
$js = "
if(jQuery.trim(value)!='') {
$js
}
";
}
return $js;
}
}
class CRequiredValidator extends CValidator {
public $requiredValue;
public $strict = false;
public $trim = true;
protected function validateAttribute($object, $attribute) {
$value = $object->$attribute;
if ($this->requiredValue !== null) {
if (! $this->strict && $value != $this->requiredValue || $this->strict && $value !== $this->requiredValue) {
$message = $this->message !== null ? $this->message : Yii::t ( 'yii', '{attribute} must be {value}.', array (
'{value}' => $this->requiredValue
) );
$this->addError ( $object, $attribute, $message );
}
} elseif ($this->isEmpty ( $value, $this->trim )) {
$message = $this->message !== null ? $this->message : Yii::t ( 'yii', '{attribute} cannot be blank.' );
$this->addError ( $object, $attribute, $message );
}
}
public function clientValidateAttribute($object, $attribute) {
$message = $this->message;
if ($this->requiredValue !== null) {
if ($message === null)
$message = Yii::t ( 'yii', '{attribute} must be {value}.' );
$message = strtr ( $message, array (
'{value}' => $this->requiredValue,
'{attribute}' => $object->getAttributeLabel ( $attribute )
) );
return "
if(value!=" . CJSON::encode ( $this->requiredValue ) . ") {
messages.push(" . CJSON::encode ( $message ) . ");
}
";
} else {
if ($message === null)
$message = Yii::t ( 'yii', '{attribute} cannot be blank.' );
$message = strtr ( $message, array (
'{attribute}' => $object->getAttributeLabel ( $attribute )
) );
if ($this->trim)
$emptyCondition = "jQuery.trim(value)==''";
else
$emptyCondition = "value==''";
return "
if({$emptyCondition}) {
messages.push(" . CJSON::encode ( $message ) . ");
}
";
}
}
}
class CNumberValidator extends CValidator {
public $integerOnly = false;
public $allowEmpty = true;
public $max;
public $min;
public $tooBig;
public $tooSmall;
public $integerPattern = '/^\s*[+-]?\d+\s*$/';
public $numberPattern = '/^\s*[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\s*$/';
protected function validateAttribute($object, $attribute) {
$value = $object->$attribute;
if ($this->allowEmpty && $this->isEmpty ( $value ))
return;
if (! is_numeric ( $value )) {
// https://github.com/yiisoft/yii/issues/1955
// https://github.com/yiisoft/yii/issues/1669
$message = $this->message !== null ? $this->message : Yii::t ( 'yii', '{attribute} must be a number.' );
$this->addError ( $object, $attribute, $message );
return;
}
if ($this->integerOnly) {
if (! preg_match ( $this->integerPattern, "$value" )) {
$message = $this->message !== null ? $this->message : Yii::t ( 'yii', '{attribute} must be an integer.' );
$this->addError ( $object, $attribute, $message );
}
} else {
if (! preg_match ( $this->numberPattern, "$value" )) {
$message = $this->message !== null ? $this->message : Yii::t ( 'yii', '{attribute} must be a number.' );
$this->addError ( $object, $attribute, $message );
}
}
if ($this->min !== null && $value < $this->min) {
$message = $this->tooSmall !== null ? $this->tooSmall : Yii::t ( 'yii', '{attribute} is too small (minimum is {min}).' );
$this->addError ( $object, $attribute, $message, array (
'{min}' => $this->min
) );
}
if ($this->max !== null && $value > $this->max) {
$message = $this->tooBig !== null ? $this->tooBig : Yii::t ( 'yii', '{attribute} is too big (maximum is {max}).' );
$this->addError ( $object, $attribute, $message, array (
'{max}' => $this->max
) );
}
}
public function clientValidateAttribute($object, $attribute) {
$label = $object->getAttributeLabel ( $attribute );
if (($message = $this->message) === null)
$message = $this->integerOnly ? Yii::t ( 'yii', '{attribute} must be an integer.' ) : Yii::t ( 'yii', '{attribute} must be a number.' );
$message = strtr ( $message, array (
'{attribute}' => $label
) );
if (($tooBig = $this->tooBig) === null)
$tooBig = Yii::t ( 'yii', '{attribute} is too big (maximum is {max}).' );
$tooBig = strtr ( $tooBig, array (
'{attribute}' => $label,
'{max}' => $this->max
) );
if (($tooSmall = $this->tooSmall) === null)
$tooSmall = Yii::t ( 'yii', '{attribute} is too small (minimum is {min}).' );
$tooSmall = strtr ( $tooSmall, array (
'{attribute}' => $label,
'{min}' => $this->min
) );
$pattern = $this->integerOnly ? $this->integerPattern : $this->numberPattern;
$js = "
if(!value.match($pattern)) {
messages.push(" . CJSON::encode ( $message ) . ");
}
";
if ($this->min !== null) {
$js .= "
if(value<{$this->min}) {
messages.push(" . CJSON::encode ( $tooSmall ) . ");
}
";
}
if ($this->max !== null) {
$js .= "
if(value>{$this->max}) {
messages.push(" . CJSON::encode ( $tooBig ) . ");
}
";
}
if ($this->allowEmpty) {
$js = "
if(jQuery.trim(value)!='') {
$js
}
";
}
return $js;
}
}
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;
}
}
interface IApplicationComponent {
public function init();
public function getIsInitialized();
}
interface ICache {
public function get($id);
public function mget($ids);
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 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());
public function loginRequired();
}
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);
}
interface IBehavior {
public function attach($component);
public function detach($component);
public function getEnabled();
public function setEnabled($value);
}
interface IWidgetFactory {
public function createWidget($owner, $className, $properties = array());
}
interface IDataProvider {
public function getId();
public function getItemCount($refresh = false);
public function getTotalItemCount($refresh = false);
public function getData($refresh = false);
public function getKeys($refresh = false);
public function getSort();
public function getPagination();
}
interface ILogFilter {
public function filter(&$logs);
}
?>