Browse Source

Merge branch 'master' of github.com:yiisoft/yii2 into sphinx

tags/2.0.0-beta
Klimov Paul 11 years ago
parent
commit
cfb3e98bf6
  1. 21
      apps/advanced/common/models/LoginForm.php
  2. 21
      apps/basic/models/LoginForm.php
  3. 3
      build/controllers/ClassmapController.php
  4. 2
      extensions/bootstrap/Progress.php
  5. 15
      extensions/gii/generators/model/Generator.php
  6. 12
      extensions/jui/README.md
  7. 8
      extensions/swiftmailer/Mailer.php
  8. 3
      framework/yii/base/Application.php
  9. 2
      framework/yii/base/Component.php
  10. 22
      framework/yii/caching/ApcCache.php
  11. 103
      framework/yii/caching/Cache.php
  12. 21
      framework/yii/caching/MemCache.php
  13. 24
      framework/yii/caching/WinCache.php
  14. 13
      framework/yii/classes.php
  15. 2
      framework/yii/console/controllers/MigrateController.php
  16. 13
      framework/yii/data/Pagination.php
  17. 4
      framework/yii/db/ActiveQuery.php
  18. 12
      framework/yii/db/ActiveQueryTrait.php
  19. 11
      framework/yii/db/ActiveRecord.php
  20. 3
      framework/yii/db/ActiveRelation.php
  21. 7
      framework/yii/db/ActiveRelationTrait.php
  22. 14
      framework/yii/db/cubrid/Schema.php
  23. 3
      framework/yii/helpers/BaseHtml.php
  24. 219
      framework/yii/test/DbFixtureManager.php
  25. 110
      framework/yii/test/DbTestTrait.php
  26. 25
      framework/yii/test/TestCase.php
  27. 25
      framework/yii/test/WebTestCase.php
  28. 10
      framework/yii/web/AssetConverter.php
  29. 10
      framework/yii/web/Request.php
  30. 2
      framework/yii/web/Session.php
  31. 7
      tests/unit/TestCase.php
  32. 2
      tests/unit/framework/base/ExceptionTest.php
  33. 35
      tests/unit/framework/caching/CacheTestCase.php
  34. 17
      tests/unit/framework/db/ActiveRecordTest.php
  35. 2
      tests/unit/framework/helpers/ArrayHelperTest.php
  36. 10
      tests/unit/framework/helpers/FileHelperTest.php
  37. 2
      tests/unit/framework/helpers/JsonTest.php
  38. 4
      tests/unit/framework/helpers/StringHelperTest.php
  39. 4
      tests/unit/framework/helpers/VarDumperTest.php
  40. 2
      tests/unit/framework/mail/BaseMessageTest.php

21
apps/advanced/common/models/LoginForm.php

@ -14,6 +14,8 @@ class LoginForm extends Model
public $password;
public $rememberMe = true;
private $_user = false;
/**
* @return array the validation rules.
*/
@ -35,7 +37,7 @@ class LoginForm extends Model
*/
public function validatePassword()
{
$user = User::findByUsername($this->username);
$user = $this->getUser();
if (!$user || !$user->validatePassword($this->password)) {
$this->addError('password', 'Incorrect username or password.');
}
@ -48,11 +50,22 @@ class LoginForm extends Model
public function login()
{
if ($this->validate()) {
$user = User::findByUsername($this->username);
Yii::$app->user->login($user, $this->rememberMe ? 3600*24*30 : 0);
return true;
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0);
} else {
return false;
}
}
/**
* Finds user by [[username]]
*
* @return User|null
*/
private function getUser()
{
if ($this->_user === false) {
$this->_user = User::findByUsername($this->username);
}
return $this->_user;
}
}

21
apps/basic/models/LoginForm.php

@ -14,6 +14,8 @@ class LoginForm extends Model
public $password;
public $rememberMe = true;
private $_user = false;
/**
* @return array the validation rules.
*/
@ -35,7 +37,7 @@ class LoginForm extends Model
*/
public function validatePassword()
{
$user = User::findByUsername($this->username);
$user = $this->getUser();
if (!$user || !$user->validatePassword($this->password)) {
$this->addError('password', 'Incorrect username or password.');
}
@ -48,11 +50,22 @@ class LoginForm extends Model
public function login()
{
if ($this->validate()) {
$user = User::findByUsername($this->username);
Yii::$app->user->login($user, $this->rememberMe ? 3600*24*30 : 0);
return true;
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0);
} else {
return false;
}
}
/**
* Finds user by [[username]]
*
* @return User|null
*/
private function getUser()
{
if ($this->_user === false) {
$this->_user = User::findByUsername($this->username);
}
return $this->_user;
}
}

3
build/controllers/ClassmapController.php

@ -46,10 +46,7 @@ class ClassmapController extends Controller
'except' => [
'Yii.php',
'BaseYii.php',
'/debug/',
'/console/',
'/test/',
'/gii/',
],
];
$files = FileHelper::findFiles($root, $options);

2
extensions/bootstrap/Progress.php

@ -48,7 +48,7 @@ use yii\helpers\Html;
* 'bars' => [
* ['percent' => 30, 'options' => ['class' => 'bar-danger']],
* ['percent' => 30, 'label' => 'test', 'options' => ['class' => 'bar-success']],
* ['percent' => 35, 'options' => array['class' => 'bar-warning']],
* ['percent' => 35, 'options' => ['class' => 'bar-warning']],
* ]
* ]);
* ```

15
extensions/gii/generators/model/Generator.php

@ -115,11 +115,16 @@ class Generator extends \yii\gii\Generator
*/
public function autoCompleteData()
{
return [
'tableName' => function () {
return $this->getDbConnection()->getSchema()->getTableNames();
},
];
$db = $this->getDbConnection();
if ($db !== null) {
return [
'tableName' => function () use ($db) {
return $db->getSchema()->getTableNames();
},
];
} else {
return [];
}
}
/**

12
extensions/jui/README.md

@ -6,7 +6,17 @@ and makes using JQuery UI widgets in Yii applications extremely easy. For exampl
single line of code in a view file would render a JQuery UI DatePicker widget:
```php
<?= yii\jui\DatePicker::widget(['name' => 'start']) ?>
<?= yii\jui\DatePicker::widget(['name' => 'attributeName']) ?>
```
Configuring the Jquery UI options should be done using the clientOptions attribute:
```php
<?= yii\jui\DatePicker::widget(['name' => 'attributeName', 'clientOptions' => ['dateFormat' => 'yy-mm-dd']]) ?>
```
If you want to use the JUI widget in an ActiveRecord form, it can be done like this:
```php
<?= $form->field($model,'attributeName')->widget(DatePicker::className(),['clientOptions' => ['dateFormat' => 'yy-mm-dd']]) ?>
```

8
extensions/swiftmailer/Mailer.php

@ -17,9 +17,9 @@ use yii\mail\BaseMailer;
* To use Mailer, you should configure it in the application configuration like the following,
*
* ~~~
* 'components' => array(
* 'components' => [
* ...
* 'email' => array(
* 'email' => [
* 'class' => 'yii\swiftmailer\Mailer',
* 'transport' => [
* 'class' => 'Swift_SmtpTransport',
@ -29,9 +29,9 @@ use yii\mail\BaseMailer;
* 'port' => '587',
* 'encryption' => 'tls',
* ],
* ),
* ],
* ...
* ),
* ],
* ~~~
*
* You may also skip the configuration of the [[transport]] property. In that case, the default

3
framework/yii/base/Application.php

@ -31,7 +31,8 @@ use yii\web\HttpException;
* @property \yii\web\UrlManager $urlManager The URL manager for this application. This property is read-only.
* @property string $vendorPath The directory that stores vendor files. Defaults to "vendor" directory under
* [[basePath]].
* @property View $view The view object that is used to render various view files. This property is read-only.
* @property View|\yii\web\View $view The view object that is used to render various view files. This property
* is read-only.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0

2
framework/yii/base/Component.php

@ -452,7 +452,7 @@ class Component extends Object
$event->data = $handler[1];
call_user_func($handler[0], $event);
// stop further handling if the event is handled
if ($event instanceof Event && $event->handled) {
if ($event->handled) {
return;
}
}

22
framework/yii/caching/ApcCache.php

@ -72,6 +72,17 @@ class ApcCache extends Cache
}
/**
* Stores multiple key-value pairs in cache.
* @param array $data array where key corresponds to cache key while value
* @param integer $expire the number of seconds in which the cached values will expire. 0 means never expire.
* @return array array of failed keys
*/
protected function setValues($data, $expire)
{
return array_keys(apc_store($data, null, $expire));
}
/**
* Stores a value identified by a key into cache if the cache does not contain this key.
* This is the implementation of the method declared in the parent class.
* @param string $key the key identifying the value to be cached
@ -85,6 +96,17 @@ class ApcCache extends Cache
}
/**
* Adds multiple key-value pairs to cache.
* @param array $data array where key corresponds to cache key while value is the value stored
* @param integer $expire the number of seconds in which the cached values will expire. 0 means never expire.
* @return array array of failed keys
*/
protected function addValues($data, $expire)
{
return array_keys(apc_add($data, null, $expire));
}
/**
* Deletes a value with the specified key from cache
* This is the implementation of the method declared in the parent class.
* @param string $key the key of the value to be deleted

103
framework/yii/caching/Cache.php

@ -216,6 +216,69 @@ abstract class Cache extends Component implements \ArrayAccess
}
/**
* Stores multiple items in cache. Each item contains a value identified by a key.
* If the cache already contains such a key, the existing value and
* expiration time will be replaced with the new ones, respectively.
*
* @param array $items the items to be cached, as key-value pairs.
* @param integer $expire default number of seconds in which the cached values will expire. 0 means never expire.
* @param Dependency $dependency dependency of the cached items. If the dependency changes,
* the corresponding values in the cache will be invalidated when it is fetched via [[get()]].
* This parameter is ignored if [[serializer]] is false.
* @return boolean whether the items are successfully stored into cache
*/
public function mset($items, $expire = 0, $dependency = null)
{
if ($dependency !== null && $this->serializer !== false) {
$dependency->evaluateDependency($this);
}
$data = [];
foreach ($items as $key => $value) {
$itemKey = $this->buildKey($key);
if ($this->serializer === null) {
$itemValue = serialize([$value, $dependency]);
} elseif ($this->serializer !== false) {
$itemValue = call_user_func($this->serializer[0], [$value, $dependency]);
}
$data[$itemKey] = $itemValue;
}
return $this->setValues($data, $expire);
}
/**
* Stores multiple items in cache. Each item contains a value identified by a key.
* If the cache already contains such a key, the existing value and expiration time will be preserved.
*
* @param array $items the items to be cached, as key-value pairs.
* @param integer $expire default number of seconds in which the cached values will expire. 0 means never expire.
* @param Dependency $dependency dependency of the cached items. If the dependency changes,
* the corresponding values in the cache will be invalidated when it is fetched via [[get()]].
* This parameter is ignored if [[serializer]] is false.
* @return boolean whether the items are successfully stored into cache
*/
public function madd($items, $expire = 0, $dependency = null)
{
if ($dependency !== null && $this->serializer !== false) {
$dependency->evaluateDependency($this);
}
$data = [];
foreach ($items as $key => $value) {
$itemKey = $this->buildKey($key);
if ($this->serializer === null) {
$itemValue = serialize([$value, $dependency]);
} elseif ($this->serializer !== false) {
$itemValue = call_user_func($this->serializer[0], [$value, $dependency]);
}
$data[$itemKey] = $itemValue;
}
return $this->addValues($data, $expire);
}
/**
* Stores a value identified by a key into cache if the cache does not contain this key.
* Nothing will be done if the cache already contains the key.
* @param mixed $key a key identifying the value to be cached. This can be a simple string or
@ -327,6 +390,46 @@ abstract class Cache extends Component implements \ArrayAccess
}
/**
* Stores multiple key-value pairs in cache.
* The default implementation calls [[setValue()]] multiple times store values one by one. If the underlying cache
* storage supports multiset, this method should be overridden to exploit that feature.
* @param array $data array where key corresponds to cache key while value is the value stored
* @param integer $expire the number of seconds in which the cached values will expire. 0 means never expire.
* @return array array of failed keys
*/
protected function setValues($data, $expire)
{
$failedKeys = [];
foreach ($data as $key => $value)
{
if ($this->setValue($key, $value, $expire) === false) {
$failedKeys[] = $key;
}
}
return $failedKeys;
}
/**
* Adds multiple key-value pairs to cache.
* The default implementation calls [[addValue()]] multiple times add values one by one. If the underlying cache
* storage supports multiadd, this method should be overridden to exploit that feature.
* @param array $data array where key corresponds to cache key while value is the value stored
* @param integer $expire the number of seconds in which the cached values will expire. 0 means never expire.
* @return array array of failed keys
*/
protected function addValues($data, $expire)
{
$failedKeys = [];
foreach ($data as $key => $value)
{
if ($this->addValue($key, $value, $expire) === false) {
$failedKeys[] = $key;
}
}
return $failedKeys;
}
/**
* Returns whether there is a cache entry with a specified key.
* This method is required by the interface ArrayAccess.
* @param string $key a key identifying the cached value

21
framework/yii/caching/MemCache.php

@ -202,6 +202,27 @@ class MemCache extends Cache
}
/**
* Stores multiple key-value pairs in cache.
* @param array $data array where key corresponds to cache key while value is the value stored
* @param integer $expire the number of seconds in which the cached values will expire. 0 means never expire.
* @return array array of failed keys. Always empty in case of using memcached.
*/
protected function setValues($data, $expire)
{
if ($this->useMemcached) {
if ($expire > 0) {
$expire += time();
} else {
$expire = 0;
}
$this->_cache->setMulti($data, $expire);
return [];
} else {
return parent::setValues($data, $expire);
}
}
/**
* Stores a value identified by a key into cache if the cache does not contain this key.
* This is the implementation of the method declared in the parent class.
*

24
framework/yii/caching/WinCache.php

@ -72,6 +72,17 @@ class WinCache extends Cache
}
/**
* Stores multiple key-value pairs in cache.
* @param array $data array where key corresponds to cache key while value is the value stored
* @param integer $expire the number of seconds in which the cached values will expire. 0 means never expire.
* @return array array of failed keys
*/
protected function setValues($data, $expire)
{
return wincache_ucache_set($data, null, $expire);
}
/**
* Stores a value identified by a key into cache if the cache does not contain this key.
* This is the implementation of the method declared in the parent class.
*
@ -86,6 +97,19 @@ class WinCache extends Cache
}
/**
* Adds multiple key-value pairs to cache.
* The default implementation calls [[addValue()]] multiple times add values one by one. If the underlying cache
* storage supports multiadd, this method should be overridden to exploit that feature.
* @param array $data array where key corresponds to cache key while value is the value stored
* @param integer $expire the number of seconds in which the cached values will expire. 0 means never expire.
* @return array array of failed keys
*/
protected function addValues($data, $expire)
{
return wincache_ucache_add($data, null, $expire);
}
/**
* Deletes a value with the specified key from cache
* This is the implementation of the method declared in the parent class.
* @param string $key the key of the value to be deleted

13
framework/yii/classes.php

@ -76,8 +76,12 @@ return [
'yii\data\Pagination' => YII_PATH . '/data/Pagination.php',
'yii\data\Sort' => YII_PATH . '/data/Sort.php',
'yii\db\ActiveQuery' => YII_PATH . '/db/ActiveQuery.php',
'yii\db\ActiveQueryInterface' => YII_PATH . '/db/ActiveQueryInterface.php',
'yii\db\ActiveQueryTrait' => YII_PATH . '/db/ActiveQueryTrait.php',
'yii\db\ActiveRecord' => YII_PATH . '/db/ActiveRecord.php',
'yii\db\ActiveRelation' => YII_PATH . '/db/ActiveRelation.php',
'yii\db\ActiveRelationInterface' => YII_PATH . '/db/ActiveRelationInterface.php',
'yii\db\ActiveRelationTrait' => YII_PATH . '/db/ActiveRelationTrait.php',
'yii\db\ColumnSchema' => YII_PATH . '/db/ColumnSchema.php',
'yii\db\Command' => YII_PATH . '/db/Command.php',
'yii\db\Connection' => YII_PATH . '/db/Connection.php',
@ -87,6 +91,8 @@ return [
'yii\db\Migration' => YII_PATH . '/db/Migration.php',
'yii\db\Query' => YII_PATH . '/db/Query.php',
'yii\db\QueryBuilder' => YII_PATH . '/db/QueryBuilder.php',
'yii\db\QueryInterface' => YII_PATH . '/db/QueryInterface.php',
'yii\db\QueryTrait' => YII_PATH . '/db/QueryTrait.php',
'yii\db\Schema' => YII_PATH . '/db/Schema.php',
'yii\db\StaleObjectException' => YII_PATH . '/db/StaleObjectException.php',
'yii\db\TableSchema' => YII_PATH . '/db/TableSchema.php',
@ -149,6 +155,10 @@ return [
'yii\log\FileTarget' => YII_PATH . '/log/FileTarget.php',
'yii\log\Logger' => YII_PATH . '/log/Logger.php',
'yii\log\Target' => YII_PATH . '/log/Target.php',
'yii\mail\BaseMailer' => YII_PATH . '/mail/BaseMailer.php',
'yii\mail\BaseMessage' => YII_PATH . '/mail/BaseMessage.php',
'yii\mail\MailerInterface' => YII_PATH . '/mail/MailerInterface.php',
'yii\mail\MessageInterface' => YII_PATH . '/mail/MessageInterface.php',
'yii\mutex\DbMutex' => YII_PATH . '/mutex/DbMutex.php',
'yii\mutex\FileMutex' => YII_PATH . '/mutex/FileMutex.php',
'yii\mutex\Mutex' => YII_PATH . '/mutex/Mutex.php',
@ -161,6 +171,8 @@ return [
'yii\redis\Connection' => YII_PATH . '/redis/Connection.php',
'yii\redis\Transaction' => YII_PATH . '/redis/Transaction.php',
'yii\requirements\YiiRequirementChecker' => YII_PATH . '/requirements/YiiRequirementChecker.php',
'yii\test\DbFixtureManager' => YII_PATH . '/test/DbFixtureManager.php',
'yii\test\DbTestTrait' => YII_PATH . '/test/DbTestTrait.php',
'yii\validators\BooleanValidator' => YII_PATH . '/validators/BooleanValidator.php',
'yii\validators\CompareValidator' => YII_PATH . '/validators/CompareValidator.php',
'yii\validators\DateValidator' => YII_PATH . '/validators/DateValidator.php',
@ -169,6 +181,7 @@ return [
'yii\validators\ExistValidator' => YII_PATH . '/validators/ExistValidator.php',
'yii\validators\FileValidator' => YII_PATH . '/validators/FileValidator.php',
'yii\validators\FilterValidator' => YII_PATH . '/validators/FilterValidator.php',
'yii\validators\ImageValidator' => YII_PATH . '/validators/ImageValidator.php',
'yii\validators\InlineValidator' => YII_PATH . '/validators/InlineValidator.php',
'yii\validators\NumberValidator' => YII_PATH . '/validators/NumberValidator.php',
'yii\validators\PunycodeAsset' => YII_PATH . '/validators/PunycodeAsset.php',

2
framework/yii/console/controllers/MigrateController.php

@ -594,7 +594,7 @@ class MigrateController extends Controller
{
echo 'Creating migration history table "' . $this->migrationTable . '"...';
$this->db->createCommand()->createTable($this->migrationTable, [
'version' => 'varchar(255) NOT NULL PRIMARY KEY',
'version' => 'varchar(180) NOT NULL PRIMARY KEY',
'apply_time' => 'integer',
])->execute();
$this->db->createCommand()->insert($this->migrationTable, [

13
framework/yii/data/Pagination.php

@ -9,6 +9,7 @@ namespace yii\data;
use Yii;
use yii\base\Object;
use yii\web\Request;
/**
* Pagination represents information relevant to pagination of data items.
@ -83,7 +84,7 @@ class Pagination extends Object
public $route;
/**
* @var array parameters (name => value) that should be used to obtain the current page number
* and to create new pagination URLs. If not set, $_GET will be used instead.
* and to create new pagination URLs. If not set, all parameters from $_GET will be used instead.
*
* The array element indexed by [[pageVar]] is considered to be the current page number.
* If the element does not exist, the current page number is considered 0.
@ -131,7 +132,10 @@ class Pagination extends Object
public function getPage($recalculate = false)
{
if ($this->_page === null || $recalculate) {
$params = $this->params === null ? $_GET : $this->params;
if (($params = $this->params) === null) {
$request = Yii::$app->getRequest();
$params = $request instanceof Request ? $request->get() : [];
}
if (isset($params[$this->pageVar]) && is_scalar($params[$this->pageVar])) {
$this->_page = (int)$params[$this->pageVar] - 1;
if ($this->validatePage) {
@ -169,7 +173,10 @@ class Pagination extends Object
*/
public function createUrl($page)
{
$params = $this->params === null ? $_GET : $this->params;
if (($params = $this->params) === null) {
$request = Yii::$app->getRequest();
$params = $request instanceof Request ? $request->get() : [];
}
if ($page > 0 || $page >= 0 && $this->forcePageVar) {
$params[$this->pageVar] = $page + 1;
} else {

4
framework/yii/db/ActiveQuery.php

@ -68,7 +68,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface
if (!empty($rows)) {
$models = $this->createModels($rows);
if (!empty($this->with)) {
$this->populateRelations($models, $this->with);
$this->findWith($this->with, $models);
}
return $models;
} else {
@ -98,7 +98,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface
}
if (!empty($this->with)) {
$models = [$model];
$this->populateRelations($models, $this->with);
$this->findWith($this->with, $models);
$model = $models[0];
}
return $model;

12
framework/yii/db/ActiveQueryTrait.php

@ -21,7 +21,7 @@ trait ActiveQueryTrait
*/
public $modelClass;
/**
* @var array list of relations that this query should be performed with
* @var array a list of relations that this query should be performed with
*/
public $with;
/**
@ -143,10 +143,12 @@ trait ActiveQueryTrait
}
/**
* @param ActiveRecord[] $models
* @param array $with
* Finds records corresponding to one or multiple relations and populates them into the primary models.
* @param array $with a list of relations that this query should be performed with. Please
* refer to [[with()]] for details about specifying this parameter.
* @param ActiveRecord[] $models the primary models
*/
private function populateRelations(&$models, $with)
public function findWith($with, &$models)
{
$primaryModel = new $this->modelClass;
$relations = $this->normalizeRelations($primaryModel, $with);
@ -155,7 +157,7 @@ trait ActiveQueryTrait
// inherit asArray from primary query
$relation->asArray = $this->asArray;
}
$relation->findWith($name, $models);
$relation->populateRelation($name, $models);
}
}

11
framework/yii/db/ActiveRecord.php

@ -1485,18 +1485,19 @@ class ActiveRecord extends Model
}
/**
* @param array $keys
* @return boolean
* Returns a value indicating whether the given set of attributes represents the primary key for this model
* @param array $keys the set of attributes to check
* @return boolean whether the given set of attributes represents the primary key for this model
*/
private function isPrimaryKey($keys)
public static function isPrimaryKey($keys)
{
$pks = $this->primaryKey();
$pks = static::primaryKey();
foreach ($keys as $key) {
if (!in_array($key, $pks, true)) {
return false;
}
}
return true;
return count($keys) === count($pks);
}
/**

3
framework/yii/db/ActiveRelation.php

@ -20,9 +20,6 @@ namespace yii\db;
*
* If a relation involves a pivot table, it may be specified by [[via()]] or [[viaTable()]] method.
*
* @property array|ActiveRelation $via the query associated with the pivot table. Please call [[via()]]
* or [[viaTable()]] to set this property instead of directly setting it.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0

7
framework/yii/db/ActiveRelationTrait.php

@ -73,13 +73,12 @@ trait ActiveRelationTrait
/**
* Finds the related records and populates them into the primary models.
* This method is internally used by [[ActiveQuery]]. Do not call it directly.
* @param string $name the relation name
* @param array $primaryModels primary models
* @return array the related models
* @throws InvalidConfigException
* @throws InvalidConfigException if [[link]] is invalid
*/
public function findWith($name, &$primaryModels)
public function populateRelation($name, &$primaryModels)
{
if (!is_array($this->link)) {
throw new InvalidConfigException('Invalid link: it must be an array of key-value pairs.');
@ -96,7 +95,7 @@ trait ActiveRelationTrait
/** @var ActiveRelationTrait $viaQuery */
list($viaName, $viaQuery) = $this->via;
$viaQuery->primaryModel = null;
$viaModels = $viaQuery->findWith($viaName, $primaryModels);
$viaModels = $viaQuery->populateRelation($viaName, $primaryModels);
$this->filterByModels($viaModels);
} else {
$this->filterByModels($primaryModels);

14
framework/yii/db/cubrid/Schema.php

@ -138,11 +138,15 @@ class Schema extends \yii\db\Schema
foreach ($columns as $info) {
$column = $this->loadColumnSchema($info);
$table->columns[$column->name] = $column;
if ($column->isPrimaryKey) {
$table->primaryKey[] = $column->name;
if ($column->autoIncrement) {
$table->sequenceName = '';
}
}
$primaryKeys = $this->db->pdo->cubrid_schema(\PDO::CUBRID_SCH_PRIMARY_KEY, $table->name);
foreach ($primaryKeys as $key) {
$column = $table->columns[$key['ATTR_NAME']];
$column->isPrimaryKey = true;
$table->primaryKey[] = $column->name;
if ($column->autoIncrement) {
$table->sequenceName = '';
}
}

3
framework/yii/helpers/BaseHtml.php

@ -653,6 +653,9 @@ class BaseHtml
*/
public static function dropDownList($name, $selection = null, $items = [], $options = [])
{
if (!empty($options['multiple'])) {
return static::listBox($name, $selection, $items, $options);
}
$options['name'] = $name;
$selectOptions = static::renderSelectOptions($selection, $items, $options);
return static::tag('select', "\n" . $selectOptions . "\n", $options);

219
framework/yii/test/DbFixtureManager.php

@ -0,0 +1,219 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\test;
use Yii;
use yii\base\Component;
use yii\base\InvalidConfigException;
use yii\db\ActiveRecord;
use yii\db\Connection;
/**
* DbFixtureManager manages database fixtures during tests.
*
* A fixture represents a list of rows for a specific table. For a test method,
* using a fixture means that at the beginning of the method, the table has and only
* has the rows that are given in the fixture. Therefore, the table's state is
* predictable.
*
* A fixture is represented as a PHP script whose name (without suffix) is the
* same as the table name (if schema name is needed, it should be prefixed to
* the table name). The PHP script returns an array representing a list of table
* rows. Each row is an associative array of column values indexed by column names.
*
* Fixtures must be stored under the [[basePath]] directory. The directory
* may contain a file named `init.php` which will be executed before any fixture is loaded.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class DbFixtureManager extends Component
{
/**
* @var string the init script file that should be executed before running each test.
* This should be a path relative to [[basePath]].
*/
public $initScript = 'init.php';
/**
* @var string the base path containing all fixtures. This can be either a directory path or path alias.
*/
public $basePath = '@app/tests/fixtures';
/**
* @var Connection|string the DB connection object or the application component ID of the DB connection.
* After the DbFixtureManager object is created, if you want to change this property, you should only assign it
* with a DB connection object.
*/
public $db = 'db';
/**
* @var array list of database schemas that the test tables may reside in. Defaults to
* array(''), meaning using the default schema (an empty string refers to the
* default schema). This property is mainly used when turning on and off integrity checks
* so that fixture data can be populated into the database without causing problem.
*/
public $schemas = [''];
private $_rows; // fixture name, row alias => row
private $_models; // fixture name, row alias => record (or class name)
private $_modelClasses;
/**
* Loads the specified fixtures.
*
* This method does the following things to load the fixtures:
*
* - Run [[initScript]] if any.
* - Clean up data and models loaded in memory previously.
* - Load each specified fixture by calling [[loadFixture()]].
*
* @param array $fixtures a list of fixtures (fixture name => table name or AR class name) to be loaded.
* Each array element can be either a table name (with schema prefix if needed), or a fully-qualified
* ActiveRecord class name (e.g. `app\models\Post`). An element can be associated with a key
* which will be treated as the fixture name.
* @return array the loaded fixture data (fixture name => table rows)
* @throws InvalidConfigException if a model class specifying a fixture is not an ActiveRecord class.
*/
public function load(array $fixtures = [])
{
$this->basePath = Yii::getAlias($this->basePath);
if (is_string($this->db)) {
$this->db = Yii::$app->getComponent($this->db);
}
if (!$this->db instanceof Connection) {
throw new InvalidConfigException("The 'db' property must be either a DB connection instance or the application component ID of a DB connection.");
}
foreach ($fixtures as $name => $fixture) {
if (strpos($fixture, '\\') !== false) {
$model = new $fixture;
if ($model instanceof ActiveRecord) {
$this->_modelClasses[$name] = $fixture;
$fixtures[$name] = $model->getTableSchema()->name;
} else {
throw new InvalidConfigException("Fixture '$fixture' must be an ActiveRecord class.");
}
}
}
$this->_modelClasses = $this->_rows = $this->_models = [];
$this->checkIntegrity(false);
if (!empty($this->initScript)) {
$initFile = $this->basePath . '/' . $this->initScript;
if (is_file($initFile)) {
require($initFile);
}
}
foreach ($fixtures as $name => $tableName) {
$rows = $this->loadFixture($tableName);
if (is_array($rows)) {
$this->_rows[$name] = $rows;
}
}
$this->checkIntegrity(true);
return $this->_rows;
}
/**
* Loads the fixture for the specified table.
*
* This method does the following tasks to load the fixture for a table:
*
* - Remove existing rows in the table.
* - If there is any auto-incremental column, the corresponding sequence will be reset to 0.
* - If a fixture file is found, it will be executed, and its return value will be treated
* as rows which will then be inserted into the table.
*
* @param string $tableName table name
* @return array|boolean the loaded fixture rows indexed by row aliases (if any).
* False is returned if the table does not have a fixture.
* @throws InvalidConfigException if the specified table does not exist
*/
public function loadFixture($tableName)
{
$table = $this->db->getSchema()->getTableSchema($tableName);
if ($table === null) {
throw new InvalidConfigException("Table does not exist: $tableName");
}
$this->db->createCommand()->truncateTable($tableName);
$fileName = $this->basePath . '/' . $tableName . '.php';
if (!is_file($fileName)) {
return false;
}
$rows = [];
foreach (require($fileName) as $alias => $row) {
$this->db->createCommand()->insert($tableName, $row)->execute();
if ($table->sequenceName !== null) {
foreach ($table->primaryKey as $pk) {
if (!isset($row[$pk])) {
$row[$pk] = $this->db->getLastInsertID($table->sequenceName);
break;
}
}
}
$rows[$alias] = $row;
}
return $rows;
}
/**
* Returns the fixture data rows.
* The rows will have updated primary key values if the primary key is auto-incremental.
* @param string $fixtureName the fixture name
* @return array the fixture data rows. False is returned if there is no such fixture data.
*/
public function getRows($fixtureName)
{
return isset($this->_rows[$fixtureName]) ? $this->_rows[$fixtureName] : false;
}
/**
* Returns the specified ActiveRecord instance in the fixture data.
* @param string $fixtureName the fixture name
* @param string $modelName the alias for the fixture data row
* @return \yii\db\ActiveRecord the ActiveRecord instance. Null is returned if there is no such fixture row.
*/
public function getModel($fixtureName, $modelName)
{
if (!isset($this->_modelClasses[$fixtureName]) || !isset($this->_rows[$fixtureName][$modelName])) {
return null;
}
if (isset($this->_models[$fixtureName][$modelName])) {
return $this->_models[$fixtureName][$modelName];
}
$row = $this->_rows[$fixtureName][$modelName];
/** @var \yii\db\ActiveRecord $modelClass */
$modelClass = $this->_models[$fixtureName];
/** @var \yii\db\ActiveRecord $model */
$model = new $modelClass;
$keys = [];
foreach ($model->primaryKey() as $key) {
$keys[$key] = isset($row[$key]) ? $row[$key] : null;
}
return $this->_models[$fixtureName][$modelName] = $modelClass::find($keys);
}
/**
* Enables or disables database integrity check.
* This method may be used to temporarily turn off foreign constraints check.
* @param boolean $check whether to enable database integrity check
*/
public function checkIntegrity($check)
{
foreach ($this->schemas as $schema) {
$this->db->createCommand()->checkIntegrity($check, $schema);
}
}
}

110
framework/yii/test/DbTestTrait.php

@ -0,0 +1,110 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\test;
use Yii;
/**
* DbTestTrait implements the commonly used methods for setting up and accessing fixture data.
*
* To use DbTestTrait, call the [[loadFixtures()]] method in the setup method in a test case class.
* The specified fixtures will be loaded and accessible through [[getFixtureData()]] and [[getFixtureModel()]].
*
* For example,
*
* ~~~
* use yii\test\DbTestTrait;
* use app\models\Post;
* use app\models\User;
*
* class PostTestCase extends \PHPUnit_Framework_TestCase
* {
* use DbTestTrait;
*
* public function setUp()
* {
* $this->loadFixtures([
* 'posts' => Post::className(),
* 'users' => User::className(),
* ]);
* }
* }
* ~~~
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
trait DbTestTrait
{
/**
* Loads the specified fixtures.
*
* This method should typically be called in the setup method of test cases so that
* the fixtures are loaded before running each test method.
*
* This method does the following things:
*
* - Run [[DbFixtureManager::initScript]] if it is found under [[DbFixtureManager::basePath]].
* - Clean up data and models loaded in memory previously.
* - Load each specified fixture:
* * Truncate the corresponding table.
* * If a fixture file named `TableName.php` is found under [[DbFixtureManager::basePath]],
* the file will be executed, and the return value will be treated as rows which will
* then be inserted into the table.
*
* @param array $fixtures a list of fixtures (fixture name => table name or AR class name) to be loaded.
* Each array element can be either a table name (with schema prefix if needed), or a fully-qualified
* ActiveRecord class name (e.g. `app\models\Post`). An element can be optionally associated with a key
* which will be treated as the fixture name. For example,
*
* ~~~
* [
* 'tbl_comment',
* 'users' => 'tbl_user', // 'users' is the fixture name, 'tbl_user' is a table name
* 'posts' => 'app\models\Post, // 'app\models\Post' is a model class name
* ]
* ~~~
*
* @return array the loaded fixture data (fixture name => table rows)
*/
public function loadFixtures(array $fixtures = [])
{
return $this->getFixtureManager()->load($fixtures);
}
/**
* Returns the DB fixture manager.
* @return DbFixtureManager the DB fixture manager
*/
public function getFixtureManager()
{
return Yii::$app->getComponent('fixture');
}
/**
* Returns the table rows of the named fixture.
* @param string $fixtureName the fixture name.
* @return array the named fixture table rows. False is returned if there is no such fixture data.
*/
public function getFixtureRows($fixtureName)
{
return $this->getFixtureManager()->getRows($fixtureName);
}
/**
* Returns the named AR instance corresponding to the named fixture.
* @param string $fixtureName the fixture name.
* @param string $modelName the name of the fixture data row
* @return \yii\db\ActiveRecord the named AR instance corresponding to the named fixture.
* Null is returned if there is no such fixture or the record cannot be found.
*/
public function getFixtureModel($fixtureName, $modelName)
{
return $this->getFixtureManager()->getModel($fixtureName, $modelName);
}
}

25
framework/yii/test/TestCase.php

@ -1,25 +0,0 @@
<?php
/**
* TestCase class.
*
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\test;
require_once('PHPUnit/Runner/Version.php');
spl_autoload_unregister(['Yii', 'autoload']);
require_once('PHPUnit/Autoload.php');
spl_autoload_register(['Yii', 'autoload']); // put yii's autoloader at the end
/**
* TestCase is the base class for all test case classes.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
abstract class TestCase extends \PHPUnit_Framework_TestCase
{
}

25
framework/yii/test/WebTestCase.php

@ -1,25 +0,0 @@
<?php
/**
* WebTestCase class.
*
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\test;
require_once('PHPUnit/Runner/Version.php');
spl_autoload_unregister(['Yii','autoload']);
require_once('PHPUnit/Autoload.php');
spl_autoload_register(['Yii','autoload']); // put yii's autoloader at the end
/**
* WebTestCase is the base class for all test case classes.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
abstract class WebTestCase extends \PHPUnit_Extensions_SeleniumTestCase
{
}

10
framework/yii/web/AssetConverter.php

@ -74,11 +74,11 @@ class AssetConverter extends Component implements AssetConverterInterface
'{from}' => escapeshellarg("$basePath/$asset"),
'{to}' => escapeshellarg("$basePath/$result"),
]);
$descriptor = array(
1 => array('pipe', 'w'),
2 => array('pipe', 'w'),
);
$pipes = array();
$descriptor = [
1 => ['pipe', 'w'],
2 => ['pipe', 'w'],
];
$pipes = [];
$proc = proc_open($command, $descriptor, $pipes, $basePath);
$stdout = stream_get_contents($pipes[1]);
$stderr = stream_get_contents($pipes[2]);

10
framework/yii/web/Request.php

@ -35,7 +35,6 @@ use yii\helpers\Security;
* @property string $csrfTokenFromHeader The CSRF token sent via [[CSRF_HEADER]] by browser. Null is returned
* if no such header is sent. This property is read-only.
* @property array $delete The DELETE request parameter values. This property is read-only.
* @property array $get The GET request parameter values. This property is read-only.
* @property string $hostInfo Schema and hostname part (with port number if needed) of the request URL (e.g.
* `http://www.yiiframework.com`).
* @property boolean $isAjax Whether this is an AJAX (XMLHttpRequest) request. This property is read-only.
@ -312,15 +311,6 @@ class Request extends \yii\base\Request
}
/**
* Returns the GET request parameter values.
* @return array the GET request parameter values
*/
public function getGet()
{
return $_GET;
}
/**
* Returns the named POST parameter value.
* If the POST parameter does not exist, the second parameter to this method will be returned.
* @param string $name the POST parameter name. If not specified, whole $_POST is returned.

2
framework/yii/web/Session.php

@ -46,7 +46,7 @@ use yii\base\InvalidParamException;
* call methods such as [[setFlash()]], [[getFlash()]].
*
* @property array $allFlashes Flash messages (key => message). This property is read-only.
* @property array $cookieParams The session cookie parameters.
* @property array $cookieParams The session cookie parameters. This property is read-only.
* @property integer $count The number of session variables. This property is read-only.
* @property string $flash The key identifying the flash message. Note that flash messages and normal session
* variables share the same name space. If you have a normal session variable using the same name, its value will

7
tests/unit/TestCase.php

@ -2,10 +2,15 @@
namespace yiiunit;
require_once('PHPUnit/Runner/Version.php');
spl_autoload_unregister(['Yii', 'autoload']);
require_once('PHPUnit/Autoload.php');
spl_autoload_register(['Yii', 'autoload']); // put yii's autoloader at the end
/**
* This is the base class for all yii framework unit tests.
*/
abstract class TestCase extends \yii\test\TestCase
abstract class TestCase extends \PHPUnit_Framework_TestCase
{
public static $params;

2
tests/unit/framework/base/ExceptionTest.php

@ -1,7 +1,7 @@
<?php
namespace yiiunit\framework\base;
use yii\test\TestCase;
use yiiunit\TestCase;
use yii\base\UserException;
use yii\base\InvalidCallException;

35
tests/unit/framework/caching/CacheTestCase.php

@ -91,6 +91,26 @@ abstract class CacheTestCase extends TestCase
$this->assertEquals('array_test', $array['array_test']);
}
public function testMset()
{
$cache = $this->getCacheInstance();
$cache->flush();
$cache->mset([
'string_test' => 'string_test',
'number_test' => 42,
'array_test' => ['array_test' => 'array_test'],
]);
$this->assertEquals('string_test', $cache->get('string_test'));
$this->assertEquals(42, $cache->get('number_test'));
$array = $cache->get('array_test');
$this->assertArrayHasKey('array_test', $array);
$this->assertEquals('array_test', $array['array_test']);
}
public function testExists()
{
$cache = $this->prepare();
@ -164,6 +184,21 @@ abstract class CacheTestCase extends TestCase
$this->assertEquals(13, $cache->get('add_test'));
}
public function testMadd()
{
$cache = $this->prepare();
$this->assertFalse($cache->get('add_test'));
$cache->madd([
'number_test' => 13,
'add_test' => 13,
]);
$this->assertEquals(42, $cache->get('number_test'));
$this->assertEquals(13, $cache->get('add_test'));
}
public function testDelete()
{
$cache = $this->prepare();

17
tests/unit/framework/db/ActiveRecordTest.php

@ -489,4 +489,21 @@ class ActiveRecordTest extends DatabaseTestCase
$customers = Customer::find()->where(['status' => false])->all();
$this->assertEquals(1, count($customers));
}
public function testIsPrimaryKey()
{
$this->assertFalse(Customer::isPrimaryKey([]));
$this->assertTrue(Customer::isPrimaryKey(['id']));
$this->assertFalse(Customer::isPrimaryKey(['id', 'name']));
$this->assertFalse(Customer::isPrimaryKey(['name']));
$this->assertFalse(Customer::isPrimaryKey(['name', 'email']));
$this->assertFalse(OrderItem::isPrimaryKey([]));
$this->assertFalse(OrderItem::isPrimaryKey(['order_id']));
$this->assertFalse(OrderItem::isPrimaryKey(['item_id']));
$this->assertFalse(OrderItem::isPrimaryKey(['quantity']));
$this->assertFalse(OrderItem::isPrimaryKey(['quantity', 'subtotal']));
$this->assertTrue(OrderItem::isPrimaryKey(['order_id', 'item_id']));
$this->assertFalse(OrderItem::isPrimaryKey(['order_id', 'item_id', 'quantity']));
}
}

2
tests/unit/framework/helpers/ArrayHelperTest.php

@ -4,7 +4,7 @@ namespace yiiunit\framework\helpers;
use yii\base\Object;
use yii\helpers\ArrayHelper;
use yii\test\TestCase;
use yiiunit\TestCase;
use yii\data\Sort;
class Post1

10
tests/unit/framework/helpers/FileHelperTest.php

@ -1,7 +1,7 @@
<?php
use yii\helpers\FileHelper;
use yii\test\TestCase;
use yiiunit\TestCase;
/**
* Unit test for [[yii\helpers\FileHelper]]
@ -126,10 +126,10 @@ class FileHelperTest extends TestCase
FileHelper::copyDirectory($srcDirName, $dstDirName);
$this->assertTrue(file_exists($dstDirName), 'Destination directory does not exist!');
$this->assertFileExists($dstDirName, 'Destination directory does not exist!');
foreach ($files as $name => $content) {
$fileName = $dstDirName . DIRECTORY_SEPARATOR . $name;
$this->assertTrue(file_exists($fileName), 'Directory file is missing!');
$this->assertFileExists($fileName);
$this->assertEquals($content, file_get_contents($fileName), 'Incorrect file content!');
}
}
@ -189,7 +189,7 @@ class FileHelperTest extends TestCase
FileHelper::removeDirectory($dirName);
$this->assertFalse(file_exists($dirName), 'Unable to remove directory!');
$this->assertFileNotExists($dirName, 'Unable to remove directory!');
// should be silent about non-existing directories
FileHelper::removeDirectory($basePath . DIRECTORY_SEPARATOR . 'nonExisting');
@ -277,7 +277,7 @@ class FileHelperTest extends TestCase
$basePath = $this->testFilePath;
$dirName = $basePath . DIRECTORY_SEPARATOR . 'test_dir_level_1' . DIRECTORY_SEPARATOR . 'test_dir_level_2';
$this->assertTrue(FileHelper::createDirectory($dirName), 'FileHelper::createDirectory should return true if directory was created!');
$this->assertTrue(file_exists($dirName), 'Unable to create directory recursively!');
$this->assertFileExists($dirName, 'Unable to create directory recursively!');
$this->assertTrue(FileHelper::createDirectory($dirName), 'FileHelper::createDirectory should return true for already existing directories!');
}

2
tests/unit/framework/helpers/JsonTest.php

@ -4,7 +4,7 @@
namespace yiiunit\framework\helpers;
use yii\helpers\Json;
use yii\test\TestCase;
use yiiunit\TestCase;
use yii\web\JsExpression;
/**

4
tests/unit/framework/helpers/StringHelperTest.php

@ -1,8 +1,8 @@
<?php
namespace yiiunit\framework\helpers;
use \yii\helpers\StringHelper as StringHelper;
use yii\test\TestCase;
use yii\helpers\StringHelper;
use yiiunit\TestCase;
/**
* StringHelperTest

4
tests/unit/framework/helpers/VarDumperTest.php

@ -1,8 +1,8 @@
<?php
namespace yiiunit\framework\helpers;
use \yii\helpers\VarDumper;
use yii\test\TestCase;
use yii\helpers\VarDumper;
use yiiunit\TestCase;
/**
* @group helpers

2
tests/unit/framework/mail/BaseMessageTest.php

@ -69,7 +69,7 @@ class BaseMessageTest extends TestCase
class TestMailer extends BaseMailer
{
public $messageClass = 'yiiunit\framework\mail\TestMessage';
public $sentMessages = array();
public $sentMessages = [];
protected function sendMessage($message)
{

Loading…
Cancel
Save