├── tests └── .gitignore ├── CHANGELOG.md ├── .gitignore ├── composer.json ├── src ├── Log │ └── Logger.php ├── FirstYiiCompatibility.php ├── Yii.php ├── Db │ └── ActiveQuery.php └── YiiBase.php └── README.md /tests/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Change Log 2 | ========== 3 | 4 | next 5 | ---- 6 | 7 | - Added ActiveQuery decorator. 8 | 9 | 0.1, July 25, 2014 10 | ------------------ 11 | 12 | - Initial release. 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # phpstorm 2 | .idea* 3 | !.idea/codeStyleSettings.xml 4 | 5 | # netbeans 6 | nbproject 7 | 8 | # zend studio for eclipse 9 | .buildpath 10 | .project 11 | .settings 12 | 13 | # windows thumbnail cache 14 | Thumbs.db 15 | /src/local 16 | 17 | # Mac DS_Store Files 18 | .DS_Store 19 | 20 | # phpunit 21 | phpunit.phar 22 | /phpunit.xml 23 | 24 | # composer 25 | /vendor 26 | composer.phar 27 | composer.lock 28 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slavcodev/yii2-yii-bridge", 3 | "description": "Yii bridge between v1.1.x and v2.0", 4 | "keywords": ["yii2", "yii1"], 5 | "type": "yii2-extension", 6 | "license": "BSD-3-Clause", 7 | "support": { 8 | "issues": "https://github.com/slavcodev/yii2-yii-bridge/issues", 9 | "source": "https://github.com/slavcodev/yii2-yii-bridge" 10 | }, 11 | "authors": [ 12 | { 13 | "name": "Veaceslav Medvedev", 14 | "email": "slavcopost@gmail.com" 15 | } 16 | ], 17 | "minimum-stability": "dev", 18 | "require": { 19 | "yiisoft/yii2": "*", 20 | "yiisoft/yii": ">=1.1.15" 21 | }, 22 | "autoload": { 23 | "psr-4": { 24 | "Slavcodev\\YiiBridge\\": "./src" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Log/Logger.php: -------------------------------------------------------------------------------- 1 | 6 | * @license http://www.opensource.org/licenses/bsd-license.php 7 | */ 8 | 9 | namespace Slavcodev\YiiBridge\Log; 10 | 11 | use yii\base\UnknownMethodException; 12 | use yii\log\Logger as BaseLogger; 13 | use CLogger; 14 | 15 | /** 16 | * Class Logger 17 | * 18 | * @author Veaceslav Medvedev 19 | * @version 0.1 20 | */ 21 | class Logger extends BaseLogger 22 | { 23 | private $old; 24 | 25 | private function getOldLogger() 26 | { 27 | if (!$this->old) { 28 | $this->old = new CLogger(); 29 | } 30 | return $this->old; 31 | } 32 | 33 | public function __call($name, $params) 34 | { 35 | try { 36 | return parent::__call($name, $params); 37 | } catch (UnknownMethodException $e) { 38 | return call_user_func_array([$this->getOldLogger(), $name], $params); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/FirstYiiCompatibility.php: -------------------------------------------------------------------------------- 1 | 6 | * @license http://www.opensource.org/licenses/bsd-license.php 7 | */ 8 | 9 | namespace Slavcodev\YiiBridge; 10 | 11 | use yii\log\Logger as BaseLogger; 12 | use CLogger; 13 | 14 | /** 15 | * Class FirstYiiCompatibility 16 | * 17 | * @author Veaceslav Medvedev 18 | * @version 0.1 19 | */ 20 | trait FirstYiiCompatibility 21 | { 22 | public static $enableIncludePath = true; 23 | 24 | /** @var \yii\log\Logger */ 25 | private static $_logger; 26 | 27 | public static function __callStatic($name, $arguments) 28 | { 29 | return call_user_func_array(['YiiBase', $name], $arguments); 30 | } 31 | 32 | public static function getLogger() 33 | { 34 | if (self::$_logger === null) { 35 | self::$_logger = static::createObject('\Slavcodev\YiiBridge\Log\Logger'); 36 | parent::setLogger(self::$_logger); 37 | } 38 | return parent::getLogger(); 39 | } 40 | 41 | public static function log($msg, $level = CLogger::LEVEL_INFO, $category = 'application') 42 | { 43 | switch ($level) { 44 | case CLogger::LEVEL_TRACE: 45 | $level = BaseLogger::LEVEL_TRACE; 46 | break; 47 | case CLogger::LEVEL_WARNING: 48 | $level = BaseLogger::LEVEL_WARNING; 49 | break; 50 | case CLogger::LEVEL_INFO: 51 | $level = BaseLogger::LEVEL_INFO; 52 | break; 53 | case CLogger::LEVEL_PROFILE: 54 | $level = BaseLogger::LEVEL_PROFILE; 55 | break; 56 | default: 57 | $level = BaseLogger::LEVEL_ERROR; 58 | } 59 | 60 | static::getLogger()->log($msg, $level, $category); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Yii.php: -------------------------------------------------------------------------------- 1 | 6 | * @license http://www.opensource.org/licenses/bsd-license.php 7 | */ 8 | 9 | // Required in Yii1 path 10 | if (!defined('YII1_PATH')) { 11 | throw new Exception('Yii1 Framework not found.'); 12 | } elseif (!defined('YII1_BASE_PATH')) { 13 | // You need version of file after this commit 14 | // @link https://github.com/yiisoft/yii/commit/e08e47ce3ce503b5eb92f9f9bd14d36ac07e1ae9 15 | define('YII1_BASE_PATH', YII1_PATH . DIRECTORY_SEPARATOR . 'YiiBase.php'); 16 | } 17 | 18 | // Required in Yii2 path 19 | if (!defined('YII2_PATH')) { 20 | throw new Exception('Yii2 Framework not found.'); 21 | } elseif (!defined('YII2_BASE_PATH')) { 22 | define('YII2_BASE_PATH', YII2_PATH . DIRECTORY_SEPARATOR . 'BaseYii.php'); 23 | } 24 | 25 | // Predefine Yii1 constants before included YiiBase.php 26 | defined('YII_ZII_PATH') or define('YII_ZII_PATH', YII1_PATH . DIRECTORY_SEPARATOR . 'zii'); 27 | 28 | // We must first include Yii2 base class to define the correct constant 29 | require(YII2_BASE_PATH); 30 | 31 | // Include Yii1 base class 32 | require(YII1_BASE_PATH); 33 | 34 | // Override Yii1 system alias 35 | YiiBase::setPathOfAlias('system', YII1_PATH); 36 | 37 | /** 38 | * Yii bridge between v1.1.x and v2.0. 39 | * 40 | * @method static CWebApplication|CConsoleApplication app() 41 | * @method static CWebApplication|CConsoleApplication createApplication($class, $config = null) 42 | * @method static mixed createComponent($config) 43 | * @method static string import($alias, $forceInclude = false) 44 | * @method static string getPathOfAlias($alias) 45 | * @method static void setPathOfAlias($alias, $path) 46 | * @method static void trace($msg, $category = 'application') 47 | * 48 | * @author Veaceslav Medvedev 49 | * @version 0.1 50 | * @since 1.1.17 51 | */ 52 | class Yii extends \yii\BaseYii 53 | { 54 | use Slavcodev\YiiBridge\FirstYiiCompatibility; 55 | } 56 | 57 | // Yii2 Autoloader and class map 58 | // @link https://github.com/yiisoft/yii2/blob/master/framework/Yii.php#L25:L28 59 | spl_autoload_register(['Yii', 'autoload'], true, true); 60 | Yii::$classMap = include(YII2_PATH . '/classes.php'); 61 | Yii::$container = new yii\di\Container(); 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Yii bridge between v1.1.x and v2.0 2 | ================================== 3 | 4 | > Warning: The extension was made for early Yii 2.0 releases and likely does not work with current version. 5 | 6 | ### Installation 7 | 8 | The preferred way to install this extension is through [composer](http://getcomposer.org/download/). 9 | 10 | Either run 11 | 12 | ``` 13 | php composer.phar require --prefer-dist slavcodev/yii2-yii-bridge "*" 14 | ``` 15 | 16 | or add 17 | 18 | ```json 19 | "slavcodev/yii2-yii-bridge": "*" 20 | ``` 21 | 22 | to the require section of your composer.json. 23 | 24 | ### Usage 25 | 26 | To use this bridge, edit your entry script (`index.php`) 27 | 28 | ```php 29 | // Define project directories. 30 | $rootPath = dirname(dirname(__DIR__)); 31 | 32 | /** 33 | * Include composer autoloader 34 | * @var \Composer\Autoload\ClassLoader $loader Registered composer autoloader. 35 | */ 36 | $loader = require($rootPath . '/vendor/autoload.php'); 37 | 38 | // Load Yii 1 base class 39 | define('YII1_PATH', $rootPath . '/vendor/yiisoft/yii/framework'); 40 | // Load Yii 2 base class 41 | define('YII2_PATH', $rootPath . '/vendor/yiisoft/yii2'); 42 | 43 | // Override base class until v1.1.17 will released. 44 | // You need version of file after this commit 45 | // @link https://github.com/yiisoft/yii/commit/e08e47ce3ce503b5eb92f9f9bd14d36ac07e1ae9 46 | // define('YII1_BASE_PATH', $rootPath . '/vendor/slavcodev/yii2-yii-bridge/YiiBase.php'); 47 | 48 | // Include Yii bridge class file. 49 | require($rootPath . '/vendor/slavcodev/yii2-yii-bridge/Yii.php'); 50 | 51 | // Create old application, but NOT run it! 52 | $gaffer = Yii::createWebApplication($v1AppConfig); 53 | 54 | // Create new application and run. Have fun! 55 | $application = new yii\web\Application($v2AppConfig); 56 | $application->run(); 57 | ``` 58 | 59 | Now you can use old models in your Yii2 application, i.e 60 | 61 | ```php 62 | // Access new application 63 | echo Yii::$app->user->id; 64 | 65 | // Access old application 66 | echo Yii::app()->user->id; 67 | 68 | // Use Yii2 grid, data provider with Yii1 ActiveRecords 69 | echo yii\grid\GridView::widget([ 70 | 'dataProvider' => new \yii\data\ArrayDataProvider([ 71 | 'allModels' => User::model()->with('address.country')->findAll(), 72 | ]), 73 | 'columns' => [ 74 | ['attribute' => 'id'], 75 | ['attribute' => 'name'], 76 | ['attribute' => 'address.country.name'], 77 | ] 78 | ]); 79 | 80 | // Save Yii1 AR in Yii2 controller 81 | public function actionCreate() 82 | { 83 | $user = new User(); 84 | 85 | if ($data = Yii::app()->request->getPost(CHtml::modelName($user))) { 86 | $model->attributes = $data; 87 | 88 | if ($model->save()) { 89 | return $this->redirect(['view', 'id' => $model->id]); 90 | } 91 | } 92 | 93 | return $this->render('create', [ 94 | 'model' => $user, 95 | ]); 96 | } 97 | ``` 98 | -------------------------------------------------------------------------------- /src/Db/ActiveQuery.php: -------------------------------------------------------------------------------- 1 | 6 | * @license http://www.opensource.org/licenses/bsd-license.php 7 | */ 8 | 9 | namespace Slavcodev\YiiBridge\Db; 10 | 11 | use Yii; 12 | use CActiveRecord; 13 | use yii\db\ActiveQuery as BaseActiveQuery; 14 | 15 | /** 16 | * Class ActiveQuery 17 | * 18 | * @todo See changes https://github.com/yiisoft/yii2/commits/master/framework/db/ActiveQuery.php 19 | * 20 | * @author Veaceslav Medvedev 21 | * @version 0.1 22 | */ 23 | class ActiveQuery extends BaseActiveQuery 24 | { 25 | /** @var \CActiveRecord */ 26 | protected $finder; 27 | 28 | public function __construct($modelClass, $config = []) 29 | { 30 | parent::__construct($modelClass, $config); 31 | $this->finder = CActiveRecord::model($modelClass); 32 | } 33 | 34 | /** 35 | * @param null $db 36 | * 37 | * @return array|\CActiveRecord[] 38 | */ 39 | public function all($db = null) 40 | { 41 | $cmd = $this->createCommand($db); 42 | $rows = $this->finder->findAllBySql($cmd->getSql(), $cmd->params); 43 | return $this->populate($rows); 44 | } 45 | 46 | /** 47 | * @param null $db 48 | * 49 | * @return array|null|CActiveRecord 50 | */ 51 | public function one($db = null) 52 | { 53 | $cmd = $this->createCommand($db); 54 | $row = $this->finder->findBySql($cmd->getSql(), $cmd->params); 55 | if ($row !== null) { 56 | $models = $this->populate([$row]); 57 | return reset($models) ?: null; 58 | } else { 59 | return null; 60 | } 61 | } 62 | 63 | public function createCommand($db = null) 64 | { 65 | if ($db === null) { 66 | $db = Yii::$app->getDb(); 67 | } 68 | 69 | return parent::createCommand($db); 70 | } 71 | 72 | public function prepare($builder) 73 | { 74 | // override private `buildJoinWith()` 75 | if (!empty($this->joinWith)) { 76 | $this->buildJoinWith(); 77 | $this->joinWith = null; // clean it up to avoid issue https://github.com/yiisoft/yii2/issues/2687 78 | } 79 | 80 | if (empty($this->from)) { 81 | $this->from = [$this->finder->tableName()]; 82 | } 83 | 84 | return parent::prepare($builder); 85 | } 86 | 87 | /** 88 | * @param array|CActiveRecord[] $rows 89 | * 90 | * @return array|CActiveRecord[] 91 | */ 92 | public function populate($rows) 93 | { 94 | if (empty($rows)) { 95 | return []; 96 | } 97 | 98 | if (!empty($this->with)) { 99 | $this->findWith($this->with, $rows); 100 | } 101 | 102 | if ($this->asArray || !empty($this->indexBy)) { 103 | $data = []; 104 | 105 | foreach ($rows as $key => $row) { 106 | if (is_string($this->indexBy)) { 107 | $key = $row[$this->indexBy]; 108 | } elseif (is_callable($this->indexBy)) { 109 | $key = call_user_func($this->indexBy, $row); 110 | } 111 | 112 | if ($this->asArray) { 113 | $values = $row->getAttributes(); 114 | 115 | if (!empty($this->with)) { 116 | foreach ($this->with as $relatedName) { 117 | $values[$relatedName] = $row->getRelated($relatedName); 118 | } 119 | } 120 | } 121 | 122 | $data[$key] = isset($values) ? $values : $row; 123 | } 124 | } 125 | 126 | return isset($data) ? $data : $rows; 127 | } 128 | 129 | /** 130 | * @param CActiveRecord|mixed $primaryModel 131 | * @param string $name 132 | * 133 | * @return self 134 | */ 135 | private function getRelatedQuery($primaryModel, $name) 136 | { 137 | $relation = $primaryModel->getActiveRelation($name); 138 | $table = $primaryModel->getMetaData()->tableSchema; 139 | 140 | $query = new self($relation->className); 141 | $query->multiple = $relation instanceof \CHasManyRelation; 142 | $query->primaryModel = $primaryModel; 143 | 144 | if (isset($relation->through)) { 145 | $query->via($relation->through); 146 | $query->link = [current($relation->foreignKey) => key($relation->foreignKey)]; 147 | } else { 148 | $query->link = [$table->primaryKey => $relation->foreignKey]; 149 | } 150 | 151 | return $query; 152 | } 153 | 154 | public function via($relationName, callable $callable = null) 155 | { 156 | $relation = $this->getRelatedQuery($this->primaryModel, $relationName); 157 | $this->via = [$relationName, $relation]; 158 | if ($callable !== null) { 159 | call_user_func($callable, $relation); 160 | } 161 | return $this; 162 | } 163 | 164 | /** 165 | * @param array $with 166 | * @param array|CActiveRecord[] $models 167 | */ 168 | public function findWith($with, &$models) 169 | { 170 | $relations = []; 171 | 172 | foreach ($with as $name => $callback) { 173 | if (is_integer($name)) { 174 | $name = $callback; 175 | $callback = null; 176 | } 177 | 178 | if (($pos = strpos($name, '.')) !== false) { 179 | // with sub-relations 180 | $childName = substr($name, $pos + 1); 181 | $name = substr($name, 0, $pos); 182 | } else { 183 | $childName = null; 184 | } 185 | 186 | if (!isset($relations[$name])) { 187 | $query = $this->getRelatedQuery($this->finder, $name); 188 | $query->primaryModel = null; 189 | $relations[$name] = $query; 190 | } else { 191 | $query = $relations[$name]; 192 | } 193 | 194 | if (isset($childName)) { 195 | $query->with[$childName] = $callback; 196 | } elseif ($callback !== null) { 197 | call_user_func($callback, $query); 198 | } 199 | } 200 | 201 | /* @var $relation ActiveQuery */ 202 | foreach ($relations as $name => $relation) { 203 | if ($relation->asArray === null) { 204 | // inherit asArray from primary query 205 | $relation->asArray($this->asArray); 206 | } 207 | $relation->populateRelation($name, $models); 208 | } 209 | } 210 | 211 | private function buildJoinWith() 212 | { 213 | $join = $this->join; 214 | $this->join = []; 215 | 216 | foreach ($this->joinWith as $config) { 217 | list ($with, $eagerLoading, $joinType) = $config; 218 | 219 | $this->joinWithRelations(new $this->modelClass, $with, $joinType); 220 | 221 | if (is_array($eagerLoading)) { 222 | foreach ($with as $name => $callback) { 223 | if (is_integer($name)) { 224 | if (!in_array($callback, $eagerLoading, true)) { 225 | unset($with[$name]); 226 | } 227 | } elseif (!in_array($name, $eagerLoading, true)) { 228 | unset($with[$name]); 229 | } 230 | } 231 | } elseif (!$eagerLoading) { 232 | $with = []; 233 | } 234 | 235 | $this->with($with); 236 | } 237 | 238 | // remove duplicated joins added by joinWithRelations that may be added 239 | // e.g. when joining a relation and a via relation at the same time 240 | $uniqueJoins = []; 241 | foreach ($this->join as $j) { 242 | $uniqueJoins[serialize($j)] = $j; 243 | } 244 | $this->join = array_values($uniqueJoins); 245 | 246 | if (!empty($join)) { 247 | // append explicit join to joinWith() 248 | // https://github.com/yiisoft/yii2/issues/2880 249 | $this->join = empty($this->join) ? $join : array_merge($this->join, $join); 250 | } 251 | } 252 | 253 | /** 254 | * @param \CActiveRecord $model 255 | * @param array $with 256 | * @param array|string $joinType 257 | */ 258 | private function joinWithRelations($model, $with, $joinType) 259 | { 260 | $relations = []; 261 | 262 | foreach ($with as $name => $callback) { 263 | if (is_integer($name)) { 264 | $name = $callback; 265 | $callback = null; 266 | } 267 | 268 | 269 | $primaryModel = $model; 270 | $parent = $this; 271 | $prefix = ''; 272 | while (($pos = strpos($name, '.')) !== false) { 273 | $childName = substr($name, $pos + 1); 274 | $name = substr($name, 0, $pos); 275 | $fullName = $prefix === '' ? $name : "$prefix.$name"; 276 | if (!isset($relations[$fullName])) { 277 | $relations[$fullName] = $relation = $this->getRelatedQuery($primaryModel, $name); 278 | $this->joinWithRelation($parent, $relation, $this->getJoinType($joinType, $fullName)); 279 | } else { 280 | $relation = $relations[$fullName]; 281 | } 282 | $primaryModel = new $relation->modelClass; 283 | $parent = $relation; 284 | $prefix = $fullName; 285 | $name = $childName; 286 | } 287 | 288 | $fullName = $prefix === '' ? $name : "$prefix.$name"; 289 | 290 | if (!isset($relations[$fullName])) { 291 | $relations[$fullName] = $relation = $this->getRelatedQuery($primaryModel, $name); 292 | 293 | if ($callback !== null) { 294 | call_user_func($callback, $relation); 295 | } 296 | 297 | if (!empty($relation->joinWith)) { 298 | $relation->buildJoinWith(); 299 | } 300 | 301 | $this->joinWithRelation($parent, $relation, $this->getJoinType($joinType, $fullName)); 302 | } 303 | } 304 | } 305 | 306 | private function getJoinType($joinType, $name) 307 | { 308 | if (is_array($joinType) && isset($joinType[$name])) { 309 | return $joinType[$name]; 310 | } else { 311 | return is_string($joinType) ? $joinType : 'INNER JOIN'; 312 | } 313 | } 314 | 315 | /** 316 | * @param self $parent 317 | * @param self $child 318 | * @param string $joinType 319 | */ 320 | private function joinWithRelation($parent, $child, $joinType) 321 | { 322 | $via = $child->via; 323 | $child->via = null; 324 | if ($via instanceof ActiveQuery) { 325 | // via table 326 | $this->joinWithRelation($parent, $via, $joinType); 327 | $this->joinWithRelation($via, $child, $joinType); 328 | 329 | return; 330 | } elseif (is_array($via)) { 331 | // via relation 332 | $this->joinWithRelation($parent, $via[1], $joinType); 333 | $this->joinWithRelation($via[1], $child, $joinType); 334 | 335 | return; 336 | } 337 | 338 | list ($parentTable, $parentAlias) = $this->getQueryTableName($parent); 339 | list ($childTable, $childAlias) = $this->getQueryTableName($child); 340 | 341 | if (!empty($child->link)) { 342 | 343 | if (strpos($parentAlias, '{{') === false) { 344 | $parentAlias = '{{' . $parentAlias . '}}'; 345 | } 346 | if (strpos($childAlias, '{{') === false) { 347 | $childAlias = '{{' . $childAlias . '}}'; 348 | } 349 | 350 | $on = []; 351 | foreach ($child->link as $childColumn => $parentColumn) { 352 | $on[] = "$parentAlias.[[$parentColumn]] = $childAlias.[[$childColumn]]"; 353 | } 354 | $on = implode(' AND ', $on); 355 | if (!empty($child->on)) { 356 | $on = ['and', $on, $child->on]; 357 | } 358 | } else { 359 | $on = $child->on; 360 | } 361 | $this->join($joinType, empty($child->from) ? $childTable : $child->from, $on); 362 | 363 | if (!empty($child->where)) { 364 | $this->andWhere($child->where); 365 | } 366 | if (!empty($child->having)) { 367 | $this->andHaving($child->having); 368 | } 369 | if (!empty($child->orderBy)) { 370 | $this->addOrderBy($child->orderBy); 371 | } 372 | if (!empty($child->groupBy)) { 373 | $this->addGroupBy($child->groupBy); 374 | } 375 | if (!empty($child->params)) { 376 | $this->addParams($child->params); 377 | } 378 | if (!empty($child->join)) { 379 | foreach ($child->join as $join) { 380 | $this->join[] = $join; 381 | } 382 | } 383 | if (!empty($child->union)) { 384 | foreach ($child->union as $union) { 385 | $this->union[] = $union; 386 | } 387 | } 388 | } 389 | 390 | /** 391 | * @param self $query 392 | * @return array 393 | */ 394 | private function getQueryTableName($query) 395 | { 396 | if (empty($query->from)) { 397 | $tableName = $query->finder->tableName(); 398 | } else { 399 | $tableName = ''; 400 | foreach ($query->from as $alias => $tableName) { 401 | if (is_string($alias)) { 402 | return [$tableName, $alias]; 403 | } else { 404 | break; 405 | } 406 | } 407 | } 408 | 409 | if (preg_match('/^(.*?)\s+({{\w+}}|\w+)$/', $tableName, $matches)) { 410 | $alias = $matches[2]; 411 | } else { 412 | $alias = $tableName; 413 | } 414 | 415 | return [$tableName, $alias]; 416 | } 417 | } 418 | -------------------------------------------------------------------------------- /src/YiiBase.php: -------------------------------------------------------------------------------- 1 | 6 | * @link http://www.yiiframework.com/ 7 | * @copyright 2008-2013 Yii Software LLC 8 | * @license http://www.yiiframework.com/license/ 9 | * @package system 10 | * @since 1.0 11 | */ 12 | 13 | /** 14 | * Gets the application start timestamp. 15 | */ 16 | defined('YII_BEGIN_TIME') or define('YII_BEGIN_TIME',microtime(true)); 17 | /** 18 | * This constant defines whether the application should be in debug mode or not. Defaults to false. 19 | */ 20 | defined('YII_DEBUG') or define('YII_DEBUG',false); 21 | /** 22 | * This constant defines how much call stack information (file name and line number) should be logged by Yii::trace(). 23 | * Defaults to 0, meaning no backtrace information. If it is greater than 0, 24 | * at most that number of call stacks will be logged. Note, only user application call stacks are considered. 25 | */ 26 | defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',0); 27 | /** 28 | * This constant defines whether exception handling should be enabled. Defaults to true. 29 | */ 30 | defined('YII_ENABLE_EXCEPTION_HANDLER') or define('YII_ENABLE_EXCEPTION_HANDLER',true); 31 | /** 32 | * This constant defines whether error handling should be enabled. Defaults to true. 33 | */ 34 | defined('YII_ENABLE_ERROR_HANDLER') or define('YII_ENABLE_ERROR_HANDLER',true); 35 | /** 36 | * Defines the Yii framework installation path. 37 | */ 38 | defined('YII_PATH') or define('YII_PATH',dirname(__FILE__)); 39 | /** 40 | * Defines the Zii library installation path. 41 | */ 42 | defined('YII_ZII_PATH') or define('YII_ZII_PATH',YII_PATH.DIRECTORY_SEPARATOR.'zii'); 43 | 44 | /** 45 | * YiiBase is a helper class serving common framework functionalities. 46 | * 47 | * Do not use YiiBase directly. Instead, use its child class {@link Yii} where 48 | * you can customize methods of YiiBase. 49 | * 50 | * @author Qiang Xue 51 | * @package system 52 | * @since 1.0 53 | */ 54 | class YiiBase 55 | { 56 | /** 57 | * @var array class map used by the Yii autoloading mechanism. 58 | * The array keys are the class names and the array values are the corresponding class file paths. 59 | * @since 1.1.5 60 | */ 61 | public static $classMap=array(); 62 | /** 63 | * @var boolean whether to rely on PHP include path to autoload class files. Defaults to true. 64 | * You may set this to be false if your hosting environment doesn't allow changing the PHP 65 | * include path, or if you want to append additional autoloaders to the default Yii autoloader. 66 | * @since 1.1.8 67 | */ 68 | public static $enableIncludePath=true; 69 | 70 | private static $_aliases=array('system'=>YII_PATH,'zii'=>YII_ZII_PATH); // alias => path 71 | private static $_imports=array(); // alias => class name or directory 72 | private static $_includePaths; // list of include paths 73 | private static $_app; 74 | private static $_logger; 75 | 76 | 77 | 78 | /** 79 | * @return string the version of Yii framework 80 | */ 81 | public static function getVersion() 82 | { 83 | return '1.1.16-dev'; 84 | } 85 | 86 | /** 87 | * Creates a Web application instance. 88 | * @param mixed $config application configuration. 89 | * If a string, it is treated as the path of the file that contains the configuration; 90 | * If an array, it is the actual configuration information. 91 | * Please make sure you specify the {@link CApplication::basePath basePath} property in the configuration, 92 | * which should point to the directory containing all application logic, template and data. 93 | * If not, the directory will be defaulted to 'protected'. 94 | * @return CWebApplication 95 | */ 96 | public static function createWebApplication($config=null) 97 | { 98 | return self::createApplication('CWebApplication',$config); 99 | } 100 | 101 | /** 102 | * Creates a console application instance. 103 | * @param mixed $config application configuration. 104 | * If a string, it is treated as the path of the file that contains the configuration; 105 | * If an array, it is the actual configuration information. 106 | * Please make sure you specify the {@link CApplication::basePath basePath} property in the configuration, 107 | * which should point to the directory containing all application logic, template and data. 108 | * If not, the directory will be defaulted to 'protected'. 109 | * @return CConsoleApplication 110 | */ 111 | public static function createConsoleApplication($config=null) 112 | { 113 | return self::createApplication('CConsoleApplication',$config); 114 | } 115 | 116 | /** 117 | * Creates an application of the specified class. 118 | * @param string $class the application class name 119 | * @param mixed $config application configuration. This parameter will be passed as the parameter 120 | * to the constructor of the application class. 121 | * @return mixed the application instance 122 | */ 123 | public static function createApplication($class,$config=null) 124 | { 125 | return new $class($config); 126 | } 127 | 128 | /** 129 | * Returns the application singleton or null if the singleton has not been created yet. 130 | * @return CApplication the application singleton, null if the singleton has not been created yet. 131 | */ 132 | public static function app() 133 | { 134 | return self::$_app; 135 | } 136 | 137 | /** 138 | * Stores the application instance in the class static member. 139 | * This method helps implement a singleton pattern for CApplication. 140 | * Repeated invocation of this method or the CApplication constructor 141 | * will cause the throw of an exception. 142 | * To retrieve the application instance, use {@link app()}. 143 | * @param CApplication $app the application instance. If this is null, the existing 144 | * application singleton will be removed. 145 | * @throws CException if multiple application instances are registered. 146 | */ 147 | public static function setApplication($app) 148 | { 149 | if(self::$_app===null || $app===null) 150 | self::$_app=$app; 151 | else 152 | throw new CException(Yii::t('yii','Yii application can only be created once.')); 153 | } 154 | 155 | /** 156 | * @return string the path of the framework 157 | */ 158 | public static function getFrameworkPath() 159 | { 160 | return self::$_aliases['system']; 161 | } 162 | 163 | /** 164 | * Creates an object and initializes it based on the given configuration. 165 | * 166 | * The specified configuration can be either a string or an array. 167 | * If the former, the string is treated as the object type which can 168 | * be either the class name or {@link YiiBase::getPathOfAlias class path alias}. 169 | * If the latter, the 'class' element is treated as the object type, 170 | * and the rest of the name-value pairs in the array are used to initialize 171 | * the corresponding object properties. 172 | * 173 | * Any additional parameters passed to this method will be 174 | * passed to the constructor of the object being created. 175 | * 176 | * @param mixed $config the configuration. It can be either a string or an array. 177 | * @return mixed the created object 178 | * @throws CException if the configuration does not have a 'class' element. 179 | */ 180 | public static function createComponent($config) 181 | { 182 | if(is_string($config)) 183 | { 184 | $type=$config; 185 | $config=array(); 186 | } 187 | elseif(isset($config['class'])) 188 | { 189 | $type=$config['class']; 190 | unset($config['class']); 191 | } 192 | else 193 | throw new CException(Yii::t('yii','Object configuration must be an array containing a "class" element.')); 194 | 195 | if(!class_exists($type,false)) 196 | $type=Yii::import($type,true); 197 | 198 | if(($n=func_num_args())>1) 199 | { 200 | $args=func_get_args(); 201 | if($n===2) 202 | $object=new $type($args[1]); 203 | elseif($n===3) 204 | $object=new $type($args[1],$args[2]); 205 | elseif($n===4) 206 | $object=new $type($args[1],$args[2],$args[3]); 207 | else 208 | { 209 | unset($args[0]); 210 | $class=new ReflectionClass($type); 211 | // Note: ReflectionClass::newInstanceArgs() is available for PHP 5.1.3+ 212 | // $object=$class->newInstanceArgs($args); 213 | $object=call_user_func_array(array($class,'newInstance'),$args); 214 | } 215 | } 216 | else 217 | $object=new $type; 218 | 219 | foreach($config as $key=>$value) 220 | $object->$key=$value; 221 | 222 | return $object; 223 | } 224 | 225 | /** 226 | * Imports a class or a directory. 227 | * 228 | * Importing a class is like including the corresponding class file. 229 | * The main difference is that importing a class is much lighter because it only 230 | * includes the class file when the class is referenced the first time. 231 | * 232 | * Importing a directory is equivalent to adding a directory into the PHP include path. 233 | * If multiple directories are imported, the directories imported later will take 234 | * precedence in class file searching (i.e., they are added to the front of the PHP include path). 235 | * 236 | * Path aliases are used to import a class or directory. For example, 237 | *
    238 | *
  • application.components.GoogleMap: import the GoogleMap class.
  • 239 | *
  • application.components.*: import the components directory.
  • 240 | *
241 | * 242 | * The same path alias can be imported multiple times, but only the first time is effective. 243 | * Importing a directory does not import any of its subdirectories. 244 | * 245 | * Starting from version 1.1.5, this method can also be used to import a class in namespace format 246 | * (available for PHP 5.3 or above only). It is similar to importing a class in path alias format, 247 | * except that the dot separator is replaced by the backslash separator. For example, importing 248 | * application\components\GoogleMap is similar to importing application.components.GoogleMap. 249 | * The difference is that the former class is using qualified name, while the latter unqualified. 250 | * 251 | * Note, importing a class in namespace format requires that the namespace corresponds to 252 | * a valid path alias once backslash characters are replaced with dot characters. 253 | * For example, the namespace application\components must correspond to a valid 254 | * path alias application.components. 255 | * 256 | * @param string $alias path alias to be imported 257 | * @param boolean $forceInclude whether to include the class file immediately. If false, the class file 258 | * will be included only when the class is being used. This parameter is used only when 259 | * the path alias refers to a class. 260 | * @return string the class name or the directory that this alias refers to 261 | * @throws CException if the alias is invalid 262 | */ 263 | public static function import($alias,$forceInclude=false) 264 | { 265 | if(isset(self::$_imports[$alias])) // previously imported 266 | return self::$_imports[$alias]; 267 | 268 | if(class_exists($alias,false) || interface_exists($alias,false)) 269 | return self::$_imports[$alias]=$alias; 270 | 271 | if(($pos=strrpos($alias,'\\'))!==false) // a class name in PHP 5.3 namespace format 272 | { 273 | $namespace=str_replace('\\','.',ltrim(substr($alias,0,$pos),'\\')); 274 | if(($path=self::getPathOfAlias($namespace))!==false) 275 | { 276 | $classFile=$path.DIRECTORY_SEPARATOR.substr($alias,$pos+1).'.php'; 277 | if($forceInclude) 278 | { 279 | if(is_file($classFile)) 280 | require($classFile); 281 | else 282 | 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))); 283 | self::$_imports[$alias]=$alias; 284 | } 285 | else 286 | self::$classMap[$alias]=$classFile; 287 | return $alias; 288 | } 289 | else 290 | { 291 | // try to autoload the class with an autoloader 292 | if (class_exists($alias,true)) 293 | return self::$_imports[$alias]=$alias; 294 | else 295 | throw new CException(Yii::t('yii','Alias "{alias}" is invalid. Make sure it points to an existing directory or file.', 296 | array('{alias}'=>$namespace))); 297 | } 298 | } 299 | 300 | if(($pos=strrpos($alias,'.'))===false) // a simple class name 301 | { 302 | // try to autoload the class with an autoloader if $forceInclude is true 303 | if($forceInclude && (Yii::autoload($alias,true) || class_exists($alias,true))) 304 | self::$_imports[$alias]=$alias; 305 | return $alias; 306 | } 307 | 308 | $className=(string)substr($alias,$pos+1); 309 | $isClass=$className!=='*'; 310 | 311 | if($isClass && (class_exists($className,false) || interface_exists($className,false))) 312 | return self::$_imports[$alias]=$className; 313 | 314 | if(($path=self::getPathOfAlias($alias))!==false) 315 | { 316 | if($isClass) 317 | { 318 | if($forceInclude) 319 | { 320 | if(is_file($path.'.php')) 321 | require($path.'.php'); 322 | else 323 | 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))); 324 | self::$_imports[$alias]=$className; 325 | } 326 | else 327 | self::$classMap[$className]=$path.'.php'; 328 | return $className; 329 | } 330 | else // a directory 331 | { 332 | if(self::$_includePaths===null) 333 | { 334 | self::$_includePaths=array_unique(explode(PATH_SEPARATOR,get_include_path())); 335 | if(($pos=array_search('.',self::$_includePaths,true))!==false) 336 | unset(self::$_includePaths[$pos]); 337 | } 338 | 339 | array_unshift(self::$_includePaths,$path); 340 | 341 | if(self::$enableIncludePath && set_include_path('.'.PATH_SEPARATOR.implode(PATH_SEPARATOR,self::$_includePaths))===false) 342 | self::$enableIncludePath=false; 343 | 344 | return self::$_imports[$alias]=$path; 345 | } 346 | } 347 | else 348 | throw new CException(Yii::t('yii','Alias "{alias}" is invalid. Make sure it points to an existing directory or file.', 349 | array('{alias}'=>$alias))); 350 | } 351 | 352 | /** 353 | * Translates an alias into a file path. 354 | * Note, this method does not ensure the existence of the resulting file path. 355 | * It only checks if the root alias is valid or not. 356 | * @param string $alias alias (e.g. system.web.CController) 357 | * @return mixed file path corresponding to the alias, false if the alias is invalid. 358 | */ 359 | public static function getPathOfAlias($alias) 360 | { 361 | if(isset(self::$_aliases[$alias])) 362 | return self::$_aliases[$alias]; 363 | elseif(($pos=strpos($alias,'.'))!==false) 364 | { 365 | $rootAlias=substr($alias,0,$pos); 366 | if(isset(self::$_aliases[$rootAlias])) 367 | return self::$_aliases[$alias]=rtrim(self::$_aliases[$rootAlias].DIRECTORY_SEPARATOR.str_replace('.',DIRECTORY_SEPARATOR,substr($alias,$pos+1)),'*'.DIRECTORY_SEPARATOR); 368 | elseif(self::$_app instanceof CWebApplication) 369 | { 370 | if(self::$_app->findModule($rootAlias)!==null) 371 | return self::getPathOfAlias($alias); 372 | } 373 | } 374 | return false; 375 | } 376 | 377 | /** 378 | * Create a path alias. 379 | * Note, this method neither checks the existence of the path nor normalizes the path. 380 | * @param string $alias alias to the path 381 | * @param string $path the path corresponding to the alias. If this is null, the corresponding 382 | * path alias will be removed. 383 | */ 384 | public static function setPathOfAlias($alias,$path) 385 | { 386 | if(empty($path)) 387 | unset(self::$_aliases[$alias]); 388 | else 389 | self::$_aliases[$alias]=rtrim($path,'\\/'); 390 | } 391 | 392 | /** 393 | * Class autoload loader. 394 | * This method is provided to be invoked within an __autoload() magic method. 395 | * @param string $className class name 396 | * @param bool $classMapOnly whether to load classes via classmap only 397 | * @return boolean whether the class has been loaded successfully 398 | * @throws CException When class name does not match class file in debug mode. 399 | */ 400 | public static function autoload($className,$classMapOnly=false) 401 | { 402 | // use include so that the error PHP file may appear 403 | if(isset(self::$classMap[$className])) 404 | include(self::$classMap[$className]); 405 | elseif(isset(self::$_coreClasses[$className])) 406 | include(self::$_aliases['system'].self::$_coreClasses[$className]); 407 | elseif($classMapOnly) 408 | return false; 409 | else 410 | { 411 | // include class file relying on include_path 412 | if(strpos($className,'\\')===false) // class without namespace 413 | { 414 | if(self::$enableIncludePath===false) 415 | { 416 | foreach(self::$_includePaths as $path) 417 | { 418 | $classFile=$path.DIRECTORY_SEPARATOR.$className.'.php'; 419 | if(is_file($classFile)) 420 | { 421 | include($classFile); 422 | if(YII_DEBUG && basename(realpath($classFile))!==$className.'.php') 423 | throw new CException(Yii::t('yii','Class name "{class}" does not match class file "{file}".', array( 424 | '{class}'=>$className, 425 | '{file}'=>$classFile, 426 | ))); 427 | break; 428 | } 429 | } 430 | } 431 | else 432 | include($className.'.php'); 433 | } 434 | else // class name with namespace in PHP 5.3 435 | { 436 | $namespace=str_replace('\\','.',ltrim($className,'\\')); 437 | if(($path=self::getPathOfAlias($namespace))!==false) 438 | include($path.'.php'); 439 | else 440 | return false; 441 | } 442 | return class_exists($className,false) || interface_exists($className,false); 443 | } 444 | return true; 445 | } 446 | 447 | /** 448 | * Writes a trace message. 449 | * This method will only log a message when the application is in debug mode. 450 | * @param string $msg message to be logged 451 | * @param string $category category of the message 452 | * @see log 453 | */ 454 | public static function trace($msg,$category='application') 455 | { 456 | if(YII_DEBUG) 457 | self::log($msg,CLogger::LEVEL_TRACE,$category); 458 | } 459 | 460 | /** 461 | * Logs a message. 462 | * Messages logged by this method may be retrieved via {@link CLogger::getLogs} 463 | * and may be recorded in different media, such as file, email, database, using 464 | * {@link CLogRouter}. 465 | * @param string $msg message to be logged 466 | * @param string $level level of the message (e.g. 'trace', 'warning', 'error'). It is case-insensitive. 467 | * @param string $category category of the message (e.g. 'system.web'). It is case-insensitive. 468 | */ 469 | public static function log($msg,$level=CLogger::LEVEL_INFO,$category='application') 470 | { 471 | if(self::$_logger===null) 472 | self::$_logger=new CLogger; 473 | if(YII_DEBUG && YII_TRACE_LEVEL>0 && $level!==CLogger::LEVEL_PROFILE) 474 | { 475 | $traces=debug_backtrace(); 476 | $count=0; 477 | foreach($traces as $trace) 478 | { 479 | if(isset($trace['file'],$trace['line']) && strpos($trace['file'],self::$_aliases['system'])!==0) 480 | { 481 | $msg.="\nin ".$trace['file'].' ('.$trace['line'].')'; 482 | if(++$count>=YII_TRACE_LEVEL) 483 | break; 484 | } 485 | } 486 | } 487 | self::$_logger->log($msg,$level,$category); 488 | } 489 | 490 | /** 491 | * Marks the beginning of a code block for profiling. 492 | * This has to be matched with a call to {@link endProfile()} with the same token. 493 | * The begin- and end- calls must also be properly nested, e.g., 494 | *
495 |      * Yii::beginProfile('block1');
496 |      * Yii::beginProfile('block2');
497 |      * Yii::endProfile('block2');
498 |      * Yii::endProfile('block1');
499 |      * 
500 | * The following sequence is not valid: 501 | *
502 |      * Yii::beginProfile('block1');
503 |      * Yii::beginProfile('block2');
504 |      * Yii::endProfile('block1');
505 |      * Yii::endProfile('block2');
506 |      * 
507 | * @param string $token token for the code block 508 | * @param string $category the category of this log message 509 | * @see endProfile 510 | */ 511 | public static function beginProfile($token,$category='application') 512 | { 513 | self::log('begin:'.$token,CLogger::LEVEL_PROFILE,$category); 514 | } 515 | 516 | /** 517 | * Marks the end of a code block for profiling. 518 | * This has to be matched with a previous call to {@link beginProfile()} with the same token. 519 | * @param string $token token for the code block 520 | * @param string $category the category of this log message 521 | * @see beginProfile 522 | */ 523 | public static function endProfile($token,$category='application') 524 | { 525 | self::log('end:'.$token,CLogger::LEVEL_PROFILE,$category); 526 | } 527 | 528 | /** 529 | * @return CLogger message logger 530 | */ 531 | public static function getLogger() 532 | { 533 | if(self::$_logger!==null) 534 | return self::$_logger; 535 | else 536 | return self::$_logger=new CLogger; 537 | } 538 | 539 | /** 540 | * Sets the logger object. 541 | * @param CLogger $logger the logger object. 542 | * @since 1.1.8 543 | */ 544 | public static function setLogger($logger) 545 | { 546 | self::$_logger=$logger; 547 | } 548 | 549 | /** 550 | * Returns a string that can be displayed on your Web page showing Powered-by-Yii information 551 | * @return string a string that can be displayed on your Web page showing Powered-by-Yii information 552 | */ 553 | public static function powered() 554 | { 555 | return Yii::t('yii','Powered by {yii}.', array('{yii}'=>'Yii Framework')); 556 | } 557 | 558 | /** 559 | * Translates a message to the specified language. 560 | * This method supports choice format (see {@link CChoiceFormat}), 561 | * i.e., the message returned will be chosen from a few candidates according to the given 562 | * number value. This feature is mainly used to solve plural format issue in case 563 | * a message has different plural forms in some languages. 564 | * @param string $category message category. Please use only word letters. Note, category 'yii' is 565 | * reserved for Yii framework core code use. See {@link CPhpMessageSource} for 566 | * more interpretation about message category. 567 | * @param string $message the original message 568 | * @param array $params parameters to be applied to the message using strtr. 569 | * The first parameter can be a number without key. 570 | * And in this case, the method will call {@link CChoiceFormat::format} to choose 571 | * an appropriate message translation. 572 | * Starting from version 1.1.6 you can pass parameter for {@link CChoiceFormat::format} 573 | * or plural forms format without wrapping it with array. 574 | * This parameter is then available as {n} in the message translation string. 575 | * @param string $source which message source application component to use. 576 | * Defaults to null, meaning using 'coreMessages' for messages belonging to 577 | * the 'yii' category and using 'messages' for the rest messages. 578 | * @param string $language the target language. If null (default), the {@link CApplication::getLanguage application language} will be used. 579 | * @return string the translated message 580 | * @see CMessageSource 581 | */ 582 | public static function t($category,$message,$params=array(),$source=null,$language=null) 583 | { 584 | if(self::$_app!==null) 585 | { 586 | if($source===null) 587 | $source=($category==='yii'||$category==='zii')?'coreMessages':'messages'; 588 | if(($source=self::$_app->getComponent($source))!==null) 589 | $message=$source->translate($category,$message,$language); 590 | } 591 | if($params===array()) 592 | return $message; 593 | if(!is_array($params)) 594 | $params=array($params); 595 | if(isset($params[0])) // number choice 596 | { 597 | if(strpos($message,'|')!==false) 598 | { 599 | if(strpos($message,'#')===false) 600 | { 601 | $chunks=explode('|',$message); 602 | $expressions=self::$_app->getLocale($language)->getPluralRules(); 603 | if($n=min(count($chunks),count($expressions))) 604 | { 605 | for($i=0;$i<$n;$i++) 606 | $chunks[$i]=$expressions[$i].'#'.$chunks[$i]; 607 | 608 | $message=implode('|',$chunks); 609 | } 610 | } 611 | $message=CChoiceFormat::format($message,$params[0]); 612 | } 613 | if(!isset($params['{n}'])) 614 | $params['{n}']=$params[0]; 615 | unset($params[0]); 616 | } 617 | return $params!==array() ? strtr($message,$params) : $message; 618 | } 619 | 620 | /** 621 | * Registers a new class autoloader. 622 | * The new autoloader will be placed before {@link autoload} and after 623 | * any other existing autoloaders. 624 | * @param callback $callback a valid PHP callback (function name or array($className,$methodName)). 625 | * @param boolean $append whether to append the new autoloader after the default Yii autoloader. 626 | * Be careful using this option as it will disable {@link enableIncludePath autoloading via include path} 627 | * when set to true. After this the Yii autoloader can not rely on loading classes via simple include anymore 628 | * and you have to {@link import} all classes explicitly. 629 | */ 630 | public static function registerAutoloader($callback, $append=false) 631 | { 632 | if($append) 633 | { 634 | self::$enableIncludePath=false; 635 | spl_autoload_register($callback); 636 | } 637 | else 638 | { 639 | spl_autoload_unregister(array('YiiBase','autoload')); 640 | spl_autoload_register($callback); 641 | spl_autoload_register(array('YiiBase','autoload')); 642 | } 643 | } 644 | 645 | /** 646 | * @var array class map for core Yii classes. 647 | * NOTE, DO NOT MODIFY THIS ARRAY MANUALLY. IF YOU CHANGE OR ADD SOME CORE CLASSES, 648 | * PLEASE RUN 'build autoload' COMMAND TO UPDATE THIS ARRAY. 649 | */ 650 | private static $_coreClasses=array( 651 | 'CApplication' => '/base/CApplication.php', 652 | 'CApplicationComponent' => '/base/CApplicationComponent.php', 653 | 'CBehavior' => '/base/CBehavior.php', 654 | 'CComponent' => '/base/CComponent.php', 655 | 'CErrorEvent' => '/base/CErrorEvent.php', 656 | 'CErrorHandler' => '/base/CErrorHandler.php', 657 | 'CException' => '/base/CException.php', 658 | 'CExceptionEvent' => '/base/CExceptionEvent.php', 659 | 'CHttpException' => '/base/CHttpException.php', 660 | 'CModel' => '/base/CModel.php', 661 | 'CModelBehavior' => '/base/CModelBehavior.php', 662 | 'CModelEvent' => '/base/CModelEvent.php', 663 | 'CModule' => '/base/CModule.php', 664 | 'CSecurityManager' => '/base/CSecurityManager.php', 665 | 'CStatePersister' => '/base/CStatePersister.php', 666 | 'CApcCache' => '/caching/CApcCache.php', 667 | 'CCache' => '/caching/CCache.php', 668 | 'CDbCache' => '/caching/CDbCache.php', 669 | 'CDummyCache' => '/caching/CDummyCache.php', 670 | 'CEAcceleratorCache' => '/caching/CEAcceleratorCache.php', 671 | 'CFileCache' => '/caching/CFileCache.php', 672 | 'CMemCache' => '/caching/CMemCache.php', 673 | 'CRedisCache' => '/caching/CRedisCache.php', 674 | 'CWinCache' => '/caching/CWinCache.php', 675 | 'CXCache' => '/caching/CXCache.php', 676 | 'CZendDataCache' => '/caching/CZendDataCache.php', 677 | 'CCacheDependency' => '/caching/dependencies/CCacheDependency.php', 678 | 'CChainedCacheDependency' => '/caching/dependencies/CChainedCacheDependency.php', 679 | 'CDbCacheDependency' => '/caching/dependencies/CDbCacheDependency.php', 680 | 'CDirectoryCacheDependency' => '/caching/dependencies/CDirectoryCacheDependency.php', 681 | 'CExpressionDependency' => '/caching/dependencies/CExpressionDependency.php', 682 | 'CFileCacheDependency' => '/caching/dependencies/CFileCacheDependency.php', 683 | 'CGlobalStateCacheDependency' => '/caching/dependencies/CGlobalStateCacheDependency.php', 684 | 'CAttributeCollection' => '/collections/CAttributeCollection.php', 685 | 'CConfiguration' => '/collections/CConfiguration.php', 686 | 'CList' => '/collections/CList.php', 687 | 'CListIterator' => '/collections/CListIterator.php', 688 | 'CMap' => '/collections/CMap.php', 689 | 'CMapIterator' => '/collections/CMapIterator.php', 690 | 'CQueue' => '/collections/CQueue.php', 691 | 'CQueueIterator' => '/collections/CQueueIterator.php', 692 | 'CStack' => '/collections/CStack.php', 693 | 'CStackIterator' => '/collections/CStackIterator.php', 694 | 'CTypedList' => '/collections/CTypedList.php', 695 | 'CTypedMap' => '/collections/CTypedMap.php', 696 | 'CConsoleApplication' => '/console/CConsoleApplication.php', 697 | 'CConsoleCommand' => '/console/CConsoleCommand.php', 698 | 'CConsoleCommandBehavior' => '/console/CConsoleCommandBehavior.php', 699 | 'CConsoleCommandEvent' => '/console/CConsoleCommandEvent.php', 700 | 'CConsoleCommandRunner' => '/console/CConsoleCommandRunner.php', 701 | 'CHelpCommand' => '/console/CHelpCommand.php', 702 | 'CDbCommand' => '/db/CDbCommand.php', 703 | 'CDbConnection' => '/db/CDbConnection.php', 704 | 'CDbDataReader' => '/db/CDbDataReader.php', 705 | 'CDbException' => '/db/CDbException.php', 706 | 'CDbMigration' => '/db/CDbMigration.php', 707 | 'CDbTransaction' => '/db/CDbTransaction.php', 708 | 'CActiveFinder' => '/db/ar/CActiveFinder.php', 709 | 'CActiveRecord' => '/db/ar/CActiveRecord.php', 710 | 'CActiveRecordBehavior' => '/db/ar/CActiveRecordBehavior.php', 711 | 'CDbColumnSchema' => '/db/schema/CDbColumnSchema.php', 712 | 'CDbCommandBuilder' => '/db/schema/CDbCommandBuilder.php', 713 | 'CDbCriteria' => '/db/schema/CDbCriteria.php', 714 | 'CDbExpression' => '/db/schema/CDbExpression.php', 715 | 'CDbSchema' => '/db/schema/CDbSchema.php', 716 | 'CDbTableSchema' => '/db/schema/CDbTableSchema.php', 717 | 'CCubridColumnSchema' => '/db/schema/cubrid/CCubridColumnSchema.php', 718 | 'CCubridSchema' => '/db/schema/cubrid/CCubridSchema.php', 719 | 'CCubridTableSchema' => '/db/schema/cubrid/CCubridTableSchema.php', 720 | 'CMssqlColumnSchema' => '/db/schema/mssql/CMssqlColumnSchema.php', 721 | 'CMssqlCommandBuilder' => '/db/schema/mssql/CMssqlCommandBuilder.php', 722 | 'CMssqlPdoAdapter' => '/db/schema/mssql/CMssqlPdoAdapter.php', 723 | 'CMssqlSchema' => '/db/schema/mssql/CMssqlSchema.php', 724 | 'CMssqlSqlsrvPdoAdapter' => '/db/schema/mssql/CMssqlSqlsrvPdoAdapter.php', 725 | 'CMssqlTableSchema' => '/db/schema/mssql/CMssqlTableSchema.php', 726 | 'CMysqlColumnSchema' => '/db/schema/mysql/CMysqlColumnSchema.php', 727 | 'CMysqlCommandBuilder' => '/db/schema/mysql/CMysqlCommandBuilder.php', 728 | 'CMysqlSchema' => '/db/schema/mysql/CMysqlSchema.php', 729 | 'CMysqlTableSchema' => '/db/schema/mysql/CMysqlTableSchema.php', 730 | 'COciColumnSchema' => '/db/schema/oci/COciColumnSchema.php', 731 | 'COciCommandBuilder' => '/db/schema/oci/COciCommandBuilder.php', 732 | 'COciSchema' => '/db/schema/oci/COciSchema.php', 733 | 'COciTableSchema' => '/db/schema/oci/COciTableSchema.php', 734 | 'CPgsqlColumnSchema' => '/db/schema/pgsql/CPgsqlColumnSchema.php', 735 | 'CPgsqlCommandBuilder' => '/db/schema/pgsql/CPgsqlCommandBuilder.php', 736 | 'CPgsqlSchema' => '/db/schema/pgsql/CPgsqlSchema.php', 737 | 'CPgsqlTableSchema' => '/db/schema/pgsql/CPgsqlTableSchema.php', 738 | 'CSqliteColumnSchema' => '/db/schema/sqlite/CSqliteColumnSchema.php', 739 | 'CSqliteCommandBuilder' => '/db/schema/sqlite/CSqliteCommandBuilder.php', 740 | 'CSqliteSchema' => '/db/schema/sqlite/CSqliteSchema.php', 741 | 'CChoiceFormat' => '/i18n/CChoiceFormat.php', 742 | 'CDateFormatter' => '/i18n/CDateFormatter.php', 743 | 'CDbMessageSource' => '/i18n/CDbMessageSource.php', 744 | 'CGettextMessageSource' => '/i18n/CGettextMessageSource.php', 745 | 'CLocale' => '/i18n/CLocale.php', 746 | 'CMessageSource' => '/i18n/CMessageSource.php', 747 | 'CNumberFormatter' => '/i18n/CNumberFormatter.php', 748 | 'CPhpMessageSource' => '/i18n/CPhpMessageSource.php', 749 | 'CGettextFile' => '/i18n/gettext/CGettextFile.php', 750 | 'CGettextMoFile' => '/i18n/gettext/CGettextMoFile.php', 751 | 'CGettextPoFile' => '/i18n/gettext/CGettextPoFile.php', 752 | 'CChainedLogFilter' => '/logging/CChainedLogFilter.php', 753 | 'CDbLogRoute' => '/logging/CDbLogRoute.php', 754 | 'CEmailLogRoute' => '/logging/CEmailLogRoute.php', 755 | 'CFileLogRoute' => '/logging/CFileLogRoute.php', 756 | 'CLogFilter' => '/logging/CLogFilter.php', 757 | 'CLogRoute' => '/logging/CLogRoute.php', 758 | 'CLogRouter' => '/logging/CLogRouter.php', 759 | 'CLogger' => '/logging/CLogger.php', 760 | 'CProfileLogRoute' => '/logging/CProfileLogRoute.php', 761 | 'CSysLogRoute' => '/logging/CSysLogRoute.php', 762 | 'CWebLogRoute' => '/logging/CWebLogRoute.php', 763 | 'CDateTimeParser' => '/utils/CDateTimeParser.php', 764 | 'CFileHelper' => '/utils/CFileHelper.php', 765 | 'CFormatter' => '/utils/CFormatter.php', 766 | 'CLocalizedFormatter' => '/utils/CLocalizedFormatter.php', 767 | 'CMarkdownParser' => '/utils/CMarkdownParser.php', 768 | 'CPasswordHelper' => '/utils/CPasswordHelper.php', 769 | 'CPropertyValue' => '/utils/CPropertyValue.php', 770 | 'CTimestamp' => '/utils/CTimestamp.php', 771 | 'CVarDumper' => '/utils/CVarDumper.php', 772 | 'CBooleanValidator' => '/validators/CBooleanValidator.php', 773 | 'CCaptchaValidator' => '/validators/CCaptchaValidator.php', 774 | 'CCompareValidator' => '/validators/CCompareValidator.php', 775 | 'CDateValidator' => '/validators/CDateValidator.php', 776 | 'CDefaultValueValidator' => '/validators/CDefaultValueValidator.php', 777 | 'CEmailValidator' => '/validators/CEmailValidator.php', 778 | 'CExistValidator' => '/validators/CExistValidator.php', 779 | 'CFileValidator' => '/validators/CFileValidator.php', 780 | 'CFilterValidator' => '/validators/CFilterValidator.php', 781 | 'CInlineValidator' => '/validators/CInlineValidator.php', 782 | 'CNumberValidator' => '/validators/CNumberValidator.php', 783 | 'CRangeValidator' => '/validators/CRangeValidator.php', 784 | 'CRegularExpressionValidator' => '/validators/CRegularExpressionValidator.php', 785 | 'CRequiredValidator' => '/validators/CRequiredValidator.php', 786 | 'CSafeValidator' => '/validators/CSafeValidator.php', 787 | 'CStringValidator' => '/validators/CStringValidator.php', 788 | 'CTypeValidator' => '/validators/CTypeValidator.php', 789 | 'CUniqueValidator' => '/validators/CUniqueValidator.php', 790 | 'CUnsafeValidator' => '/validators/CUnsafeValidator.php', 791 | 'CUrlValidator' => '/validators/CUrlValidator.php', 792 | 'CValidator' => '/validators/CValidator.php', 793 | 'CActiveDataProvider' => '/web/CActiveDataProvider.php', 794 | 'CArrayDataProvider' => '/web/CArrayDataProvider.php', 795 | 'CAssetManager' => '/web/CAssetManager.php', 796 | 'CBaseController' => '/web/CBaseController.php', 797 | 'CCacheHttpSession' => '/web/CCacheHttpSession.php', 798 | 'CClientScript' => '/web/CClientScript.php', 799 | 'CController' => '/web/CController.php', 800 | 'CDataProvider' => '/web/CDataProvider.php', 801 | 'CDataProviderIterator' => '/web/CDataProviderIterator.php', 802 | 'CDbHttpSession' => '/web/CDbHttpSession.php', 803 | 'CExtController' => '/web/CExtController.php', 804 | 'CFormModel' => '/web/CFormModel.php', 805 | 'CHttpCookie' => '/web/CHttpCookie.php', 806 | 'CHttpRequest' => '/web/CHttpRequest.php', 807 | 'CHttpSession' => '/web/CHttpSession.php', 808 | 'CHttpSessionIterator' => '/web/CHttpSessionIterator.php', 809 | 'COutputEvent' => '/web/COutputEvent.php', 810 | 'CPagination' => '/web/CPagination.php', 811 | 'CSort' => '/web/CSort.php', 812 | 'CSqlDataProvider' => '/web/CSqlDataProvider.php', 813 | 'CTheme' => '/web/CTheme.php', 814 | 'CThemeManager' => '/web/CThemeManager.php', 815 | 'CUploadedFile' => '/web/CUploadedFile.php', 816 | 'CUrlManager' => '/web/CUrlManager.php', 817 | 'CWebApplication' => '/web/CWebApplication.php', 818 | 'CWebModule' => '/web/CWebModule.php', 819 | 'CWidgetFactory' => '/web/CWidgetFactory.php', 820 | 'CAction' => '/web/actions/CAction.php', 821 | 'CInlineAction' => '/web/actions/CInlineAction.php', 822 | 'CViewAction' => '/web/actions/CViewAction.php', 823 | 'CAccessControlFilter' => '/web/auth/CAccessControlFilter.php', 824 | 'CAuthAssignment' => '/web/auth/CAuthAssignment.php', 825 | 'CAuthItem' => '/web/auth/CAuthItem.php', 826 | 'CAuthManager' => '/web/auth/CAuthManager.php', 827 | 'CBaseUserIdentity' => '/web/auth/CBaseUserIdentity.php', 828 | 'CDbAuthManager' => '/web/auth/CDbAuthManager.php', 829 | 'CPhpAuthManager' => '/web/auth/CPhpAuthManager.php', 830 | 'CUserIdentity' => '/web/auth/CUserIdentity.php', 831 | 'CWebUser' => '/web/auth/CWebUser.php', 832 | 'CFilter' => '/web/filters/CFilter.php', 833 | 'CFilterChain' => '/web/filters/CFilterChain.php', 834 | 'CHttpCacheFilter' => '/web/filters/CHttpCacheFilter.php', 835 | 'CInlineFilter' => '/web/filters/CInlineFilter.php', 836 | 'CForm' => '/web/form/CForm.php', 837 | 'CFormButtonElement' => '/web/form/CFormButtonElement.php', 838 | 'CFormElement' => '/web/form/CFormElement.php', 839 | 'CFormElementCollection' => '/web/form/CFormElementCollection.php', 840 | 'CFormInputElement' => '/web/form/CFormInputElement.php', 841 | 'CFormStringElement' => '/web/form/CFormStringElement.php', 842 | 'CGoogleApi' => '/web/helpers/CGoogleApi.php', 843 | 'CHtml' => '/web/helpers/CHtml.php', 844 | 'CJSON' => '/web/helpers/CJSON.php', 845 | 'CJavaScript' => '/web/helpers/CJavaScript.php', 846 | 'CJavaScriptExpression' => '/web/helpers/CJavaScriptExpression.php', 847 | 'CPradoViewRenderer' => '/web/renderers/CPradoViewRenderer.php', 848 | 'CViewRenderer' => '/web/renderers/CViewRenderer.php', 849 | 'CWebService' => '/web/services/CWebService.php', 850 | 'CWebServiceAction' => '/web/services/CWebServiceAction.php', 851 | 'CWsdlGenerator' => '/web/services/CWsdlGenerator.php', 852 | 'CActiveForm' => '/web/widgets/CActiveForm.php', 853 | 'CAutoComplete' => '/web/widgets/CAutoComplete.php', 854 | 'CClipWidget' => '/web/widgets/CClipWidget.php', 855 | 'CContentDecorator' => '/web/widgets/CContentDecorator.php', 856 | 'CFilterWidget' => '/web/widgets/CFilterWidget.php', 857 | 'CFlexWidget' => '/web/widgets/CFlexWidget.php', 858 | 'CHtmlPurifier' => '/web/widgets/CHtmlPurifier.php', 859 | 'CInputWidget' => '/web/widgets/CInputWidget.php', 860 | 'CMarkdown' => '/web/widgets/CMarkdown.php', 861 | 'CMaskedTextField' => '/web/widgets/CMaskedTextField.php', 862 | 'CMultiFileUpload' => '/web/widgets/CMultiFileUpload.php', 863 | 'COutputCache' => '/web/widgets/COutputCache.php', 864 | 'COutputProcessor' => '/web/widgets/COutputProcessor.php', 865 | 'CStarRating' => '/web/widgets/CStarRating.php', 866 | 'CTabView' => '/web/widgets/CTabView.php', 867 | 'CTextHighlighter' => '/web/widgets/CTextHighlighter.php', 868 | 'CTreeView' => '/web/widgets/CTreeView.php', 869 | 'CWidget' => '/web/widgets/CWidget.php', 870 | 'CCaptcha' => '/web/widgets/captcha/CCaptcha.php', 871 | 'CCaptchaAction' => '/web/widgets/captcha/CCaptchaAction.php', 872 | 'CBasePager' => '/web/widgets/pagers/CBasePager.php', 873 | 'CLinkPager' => '/web/widgets/pagers/CLinkPager.php', 874 | 'CListPager' => '/web/widgets/pagers/CListPager.php', 875 | ); 876 | } 877 | 878 | spl_autoload_register(array('YiiBase','autoload')); 879 | require(YII1_PATH.'/base/interfaces.php'); 880 | --------------------------------------------------------------------------------