mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-03 22:32:40 +08:00
Merge branch 'master' of https://github.com/yiisoft/yii2 into schema-cache-fixes
This commit is contained in:
@ -47,3 +47,25 @@ Changed current directory to <directory>
|
||||
путём запуска команды `codecept` без указания пути. Тем не менее, данный подход может не подойти. К примеру, в двух
|
||||
разных проектах может потребоваться установить разные версии Codeception. Для простоты все команды в разделах про
|
||||
тестирование используются так, будто Codeception установлен глобально.
|
||||
|
||||
### Настройка веб-сервера Apache
|
||||
|
||||
Если вы используете Apache и настроили его как описано в разделе «[Установка Yii](start-installation.md)», то для тестов вам необходимо создать отдельный виртуальный хост который будет работать с той же папкой, но использовать входной скрипт `index-test.php`:
|
||||
```
|
||||
<VirtualHost *:80>
|
||||
DocumentRoot "path/to/basic/webb"
|
||||
ServerName mysite-test
|
||||
<Directory "path/to/basic/web">
|
||||
Order Allow,Deny
|
||||
Allow from all
|
||||
AddDefaultCharset utf-8
|
||||
DirectoryIndex index-test.php
|
||||
RewriteEngine on
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule . index-test.php
|
||||
</Directory>
|
||||
</VirtualHost>
|
||||
```
|
||||
Так мы укажем веб серверу перенаправлять все запросы на скрипт `index-test.php`.
|
||||
> Note: Обратите внимание, что здесь мы указываем параметр `DirectoryIndex`, помимо тех параметров, которые были указаны для первого хоста. Это сделано с той целью, чтобы при обращении к главной странице по адресу `mysite-test` также использовался бы скрипт `index-test.php`.
|
||||
|
||||
@ -4,6 +4,14 @@ Yii Framework 2 Change Log
|
||||
2.0.12 under development
|
||||
--------------------------
|
||||
|
||||
- Bug #14052: Fixed processing parse errors on PHP 7 since these are instances of `\ParseError` (samdark)
|
||||
- Bug #13790: Fixed error in `\yii\widgets\MaskedInput` JavaScript by raising version required (samdark)
|
||||
- Bug #14033: Fixed `yii\filters\AccessRule::matchIp()` erroring in case IP is not defined under HHVM (Kolyunya)
|
||||
- Bug #13848: `yii\di\Instance::ensure()` wasn't throwing an exception when `$type` is specified and `$reference` object isn't instance of `$type` (c-jonua)
|
||||
- Enh #13226: `yii cache` command now warns about the fact that it's not able to flush APC cache from console (samdark)
|
||||
- Bug #13689: Fixed handling of errors in closures (mikehaertl)
|
||||
- Bug #11719: Fixed `yii\db\Connection::$enableQueryCache` caused infinite loop when the same connection was used for `yii\caching\DbCache` (michaelarnauts)
|
||||
- Bug #10346: Fixed "DOMException: Invalid Character Error" in `yii\web\XmlResponseFormatter::buildXml()` (sasha-ch)
|
||||
- Bug #13694: `yii\widgets\Pjax` now sends `X-Pjax-Url` header with response to fix redirect (wleona3, Faryshta)
|
||||
- Bug #14012: `yii\db\pgsql\Schema::findViewNames()` was skipping materialized views (insolita)
|
||||
- Bug #13362: Fixed return value of `yii\caching\MemCache::setValues()` (masterklavi)
|
||||
@ -13,7 +21,7 @@ Yii Framework 2 Change Log
|
||||
- Bug #13671: Fixed error handler trace to work correctly with XDebug (samdark)
|
||||
- Bug #13657: Fixed `yii\helpers\StringHelper::truncateHtml()` skip extra tags at the end (sam002)
|
||||
- Bug #7946: Fixed a bug when the `form` attribute was not propagated to the hidden input of the checkbox (Kolyunya)
|
||||
- Bug #13087: Fixed getting active validators for safe attribute (developeruz)
|
||||
- Bug #13087: Fixed getting active validators for safe attribute (developeruz, klimov-paul)
|
||||
- Bug #13571: Fix `yii\db\mssql\QueryBuilder::checkIntegrity` for all tables (boboldehampsink)
|
||||
- Bug #11230: Include `defaultRoles` in `yii\rbac\DbManager->getRolesByUser()` results (developeruz)
|
||||
- Enh #13243: Added support for unicode attribute names in `yii\widgets\DetailView` (arogachev)
|
||||
@ -33,6 +41,7 @@ Yii Framework 2 Change Log
|
||||
- Bug #8120: Fixes LIKE special characters escaping for Cubrid/MSSQL/Oracle/SQLite in `yii\db\QueryBuilder` (sergeymakinen)
|
||||
- Bug #12715: Exception `SAVEPOINT LEVEL1 does not exist` instead of deadlock exception (Vovan-VE)
|
||||
- Enh #8641: Enhanced `yii\console\Request::resolve()` to prevent passing parameters, that begin from digits (silverfire)
|
||||
- Enh #13179: Added `yii\data\Sort::parseSortParam` allowing to customize sort param in descendant class (leandrogehlen)
|
||||
- Enh #13278: `yii\caching\DbQueryDependency` created allowing specification of the cache dependency via `yii\db\QueryInterface` (klimov-paul)
|
||||
- Enh #13467: `yii\data\ActiveDataProvider` no longer queries models if models count is zero (kLkA, Kolyunya)
|
||||
- Enh #13523: Plural rule for pasta (developeruz)
|
||||
@ -75,6 +84,7 @@ Yii Framework 2 Change Log
|
||||
- Enh #13981: `yii\caching\Cache::getOrSet()` now supports both `Closure` and `callable` (silverfire)
|
||||
- Enh #13911: Significantly enhanced MSSQL schema reading performance (paulzi, WebdevMerlion)
|
||||
- Bug #14072: Fixed a bug where `\yii\db\Command::createTable()`, `addForeignKey()`, `dropForeignKey()`, `addCommentOnColumn()`, and `dropCommentFromColumn()` weren't refreshing the table cache on `yii\db\Schema` (brandonkelly)
|
||||
- Enh #14059: Removed unused AR instantiating for calling of static methods (ElisDN)
|
||||
|
||||
2.0.11.2 February 08, 2017
|
||||
--------------------------
|
||||
|
||||
@ -136,9 +136,8 @@ class DbCache extends Cache
|
||||
$this->db->enableQueryCache = true;
|
||||
|
||||
return $result;
|
||||
} else {
|
||||
return $query->createCommand($this->db)->queryScalar();
|
||||
}
|
||||
return $query->createCommand($this->db)->queryScalar();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -187,19 +186,21 @@ class DbCache extends Cache
|
||||
*/
|
||||
protected function setValue($key, $value, $duration)
|
||||
{
|
||||
$command = $this->db->createCommand()
|
||||
$result = $this->db->noCache(function (Connection $db) use ($key, $value, $duration) {
|
||||
$command = $db->createCommand()
|
||||
->update($this->cacheTable, [
|
||||
'expire' => $duration > 0 ? $duration + time() : 0,
|
||||
'data' => [$value, \PDO::PARAM_LOB],
|
||||
], ['id' => $key]);
|
||||
return $command->execute();
|
||||
});
|
||||
|
||||
if ($command->execute()) {
|
||||
if ($result) {
|
||||
$this->gc();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return $this->addValue($key, $value, $duration);
|
||||
}
|
||||
return $this->addValue($key, $value, $duration);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -216,12 +217,14 @@ class DbCache extends Cache
|
||||
$this->gc();
|
||||
|
||||
try {
|
||||
$this->db->createCommand()
|
||||
$this->db->noCache(function (Connection $db) use ($key, $value, $duration) {
|
||||
$db->createCommand()
|
||||
->insert($this->cacheTable, [
|
||||
'id' => $key,
|
||||
'expire' => $duration > 0 ? $duration + time() : 0,
|
||||
'data' => [$value, \PDO::PARAM_LOB],
|
||||
])->execute();
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
@ -237,9 +240,11 @@ class DbCache extends Cache
|
||||
*/
|
||||
protected function deleteValue($key)
|
||||
{
|
||||
$this->db->createCommand()
|
||||
$this->db->noCache(function (Connection $db) use ($key) {
|
||||
$db->createCommand()
|
||||
->delete($this->cacheTable, ['id' => $key])
|
||||
->execute();
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@
|
||||
"ezyang/htmlpurifier": "~4.6",
|
||||
"cebe/markdown": "~1.0.0 | ~1.1.0",
|
||||
"bower-asset/jquery": "2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable",
|
||||
"bower-asset/jquery.inputmask": "~3.2.2 | ~3.3.3",
|
||||
"bower-asset/jquery.inputmask": "~3.2.2 | ~3.3.5",
|
||||
"bower-asset/punycode": "1.3.*",
|
||||
"bower-asset/yii2-pjax": "~2.0.1"
|
||||
},
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
namespace yii\console\controllers;
|
||||
|
||||
use Yii;
|
||||
use yii\caching\ApcCache;
|
||||
use yii\console\Controller;
|
||||
use yii\caching\Cache;
|
||||
use yii\helpers\Console;
|
||||
@ -32,7 +33,7 @@ use yii\console\Exception;
|
||||
* configured are different from web application, web application cache won't be cleared. In order to fix it please
|
||||
* duplicate web application cache components in console config. You can use any component names.
|
||||
*
|
||||
* Both APC and OpCache aren't shared between PHP processes so flushing cache from command line has no effect on web.
|
||||
* APC is not shared between PHP processes so flushing cache from command line has no effect on web.
|
||||
* Flushing web cache could be either done by:
|
||||
*
|
||||
* - Putting a php file under web root and calling it via HTTP
|
||||
@ -99,7 +100,7 @@ class CacheController extends Controller
|
||||
$cachesInfo[] = [
|
||||
'name' => $name,
|
||||
'class' => $class,
|
||||
'is_flushed' => Yii::$app->get($name)->flush(),
|
||||
'is_flushed' => $this->canBeFlushed($class) ? Yii::$app->get($name)->flush() : false,
|
||||
];
|
||||
}
|
||||
|
||||
@ -123,7 +124,7 @@ class CacheController extends Controller
|
||||
$cachesInfo[] = [
|
||||
'name' => $name,
|
||||
'class' => $class,
|
||||
'is_flushed' => Yii::$app->get($name)->flush(),
|
||||
'is_flushed' => $this->canBeFlushed($class) ? Yii::$app->get($name)->flush() : false,
|
||||
];
|
||||
}
|
||||
|
||||
@ -178,7 +179,11 @@ class CacheController extends Controller
|
||||
$this->stdout("The following caches were found in the system:\n\n", Console::FG_YELLOW);
|
||||
|
||||
foreach ($caches as $name => $class) {
|
||||
if ($this->canBeFlushed($class)) {
|
||||
$this->stdout("\t* $name ($class)\n", Console::FG_GREEN);
|
||||
} else {
|
||||
$this->stdout("\t* $name ($class) - can not be flushed via console\n", Console::FG_YELLOW);
|
||||
}
|
||||
}
|
||||
|
||||
$this->stdout("\n");
|
||||
@ -256,7 +261,7 @@ class CacheController extends Controller
|
||||
$findAll = ($cachesNames === []);
|
||||
|
||||
foreach ($components as $name => $component) {
|
||||
if (!$findAll && !in_array($name, $cachesNames)) {
|
||||
if (!$findAll && !in_array($name, $cachesNames, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -281,4 +286,14 @@ class CacheController extends Controller
|
||||
{
|
||||
return is_subclass_of($className, Cache::className());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if cache of a certain class can be flushed
|
||||
* @param string $className class name.
|
||||
* @return bool
|
||||
*/
|
||||
private function canBeFlushed($className)
|
||||
{
|
||||
return !is_a($className, ApcCache::className(), true) || php_sapi_name() !== "cli";
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ interface DataProviderInterface
|
||||
public function getSort();
|
||||
|
||||
/**
|
||||
* @return Pagination the pagination object. If this is false, it means the pagination is disabled.
|
||||
* @return Pagination|false the pagination object. If this is false, it means the pagination is disabled.
|
||||
*/
|
||||
public function getPagination();
|
||||
}
|
||||
|
||||
@ -243,8 +243,8 @@ class Sort extends Object
|
||||
$request = Yii::$app->getRequest();
|
||||
$params = $request instanceof Request ? $request->getQueryParams() : [];
|
||||
}
|
||||
if (isset($params[$this->sortParam]) && is_scalar($params[$this->sortParam])) {
|
||||
$attributes = explode($this->separator, $params[$this->sortParam]);
|
||||
if (isset($params[$this->sortParam])) {
|
||||
$attributes = $this->parseSortParam($params[$this->sortParam]);
|
||||
foreach ($attributes as $attribute) {
|
||||
$descending = false;
|
||||
if (strncmp($attribute, '-', 1) === 0) {
|
||||
@ -268,6 +268,33 @@ class Sort extends Object
|
||||
return $this->_attributeOrders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the value of [[sortParam]] into an array of sort attributes.
|
||||
*
|
||||
* The format must be the attribute name only for ascending
|
||||
* or the attribute name prefixed with `-` for descending.
|
||||
*
|
||||
* For example the following return value will result in ascending sort by
|
||||
* `category` and descending sort by `created_at`:
|
||||
*
|
||||
* ```php
|
||||
* [
|
||||
* 'category',
|
||||
* '-created_at'
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* @param string $param the value of the [[sortParam]].
|
||||
* @return array the valid sort attributes.
|
||||
* @since 2.0.12
|
||||
* @see $separator for the attribute name separator.
|
||||
* @see $sortParam
|
||||
*/
|
||||
protected function parseSortParam($param)
|
||||
{
|
||||
return is_scalar($param) ? explode($this->separator, $param) : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the currently sort information.
|
||||
* @param array|null $attributeOrders sort directions indexed by attribute names.
|
||||
|
||||
@ -163,6 +163,9 @@ class SqlDataProvider extends BaseDataProvider
|
||||
*/
|
||||
protected function prepareTotalCount()
|
||||
{
|
||||
return (new Query())->from(['sub' => "({$this->sql})"])->count('*', $this->db);
|
||||
return (new Query([
|
||||
'from' => ['sub' => "({$this->sql})"],
|
||||
'params' => $this->params
|
||||
]))->count('*', $this->db);
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,9 +276,8 @@ class QueryBuilder extends \yii\db\QueryBuilder
|
||||
if (!$modelClass) {
|
||||
return null;
|
||||
}
|
||||
/* @var $model \yii\db\ActiveRecord */
|
||||
$model = new $modelClass;
|
||||
$schema = $model->getTableSchema();
|
||||
/* @var $modelClass \yii\db\ActiveRecord */
|
||||
$schema = $modelClass::getTableSchema();
|
||||
return array_keys($schema->columns);
|
||||
}
|
||||
|
||||
|
||||
@ -116,7 +116,12 @@ class Instance
|
||||
$container = Yii::$container;
|
||||
}
|
||||
unset($reference['class']);
|
||||
return $container->get($class, [], $reference);
|
||||
$component = $container->get($class, [], $reference);
|
||||
if ($type === null || $component instanceof $type) {
|
||||
return $component;
|
||||
} else {
|
||||
throw new InvalidConfigException('Invalid data type: ' . $class .'. ' . $type . ' is expected.');
|
||||
}
|
||||
} elseif (empty($reference)) {
|
||||
throw new InvalidConfigException('The required component is not specified.');
|
||||
}
|
||||
|
||||
@ -115,9 +115,9 @@ class AccessRule extends Component
|
||||
&& $this->matchCustom($action)
|
||||
) {
|
||||
return $this->allow ? true : false;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -165,7 +165,7 @@ class AccessRule extends Component
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $ip the IP address
|
||||
* @param string|null $ip the IP address
|
||||
* @return bool whether the rule applies to the IP address
|
||||
*/
|
||||
protected function matchIP($ip)
|
||||
@ -174,7 +174,14 @@ class AccessRule extends Component
|
||||
return true;
|
||||
}
|
||||
foreach ($this->ips as $rule) {
|
||||
if ($rule === '*' || $rule === $ip || (($pos = strpos($rule, '*')) !== false && !strncmp($ip, $rule, $pos))) {
|
||||
if ($rule === '*' ||
|
||||
$rule === $ip ||
|
||||
(
|
||||
$ip !== null &&
|
||||
($pos = strpos($rule, '*')) !== false &&
|
||||
strncmp($ip, $rule, $pos) === 0
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ return [
|
||||
'{attribute} must be a string.' => '{attribute} musí byť reťazec.',
|
||||
'{attribute} must be a valid IP address.' => '{attribute} musí byť platná IP adresa.',
|
||||
'{attribute} must be an IP address with specified subnet.' => '{attribute} musí byť IP adresa so špecifikovanou podsieťou.',
|
||||
'{attribute} must be an integer.' => '{attribute} musí byť integer.',
|
||||
'{attribute} must be an integer.' => '{attribute} musí byť celé číslo.',
|
||||
'{attribute} must be either "{true}" or "{false}".' => '{attribute} musí byť "{true}" alebo "{false}".',
|
||||
'{attribute} must be equal to "{compareValueOrAttribute}".' => '{attribute} musí byť "{compareValueOrAttribute}".',
|
||||
'{attribute} must be greater than "{compareValueOrAttribute}".' => '{attribute} musí byť väčšie ako "{compareValueOrAttribute}".',
|
||||
|
||||
@ -194,7 +194,7 @@ abstract class BaseManager extends Component implements ManagerInterface
|
||||
* @since 2.0.12
|
||||
* @return Role[] default roles. The array is indexed by the role names
|
||||
*/
|
||||
public function getDefaultRoles()
|
||||
public function getDefaultRoleInstances()
|
||||
{
|
||||
$result = [];
|
||||
foreach ($this->defaultRoles as $roleName) {
|
||||
|
||||
@ -466,7 +466,7 @@ class DbManager extends BaseManager
|
||||
->andWhere(['a.user_id' => (string) $userId])
|
||||
->andWhere(['b.type' => Item::TYPE_ROLE]);
|
||||
|
||||
$roles = $this->getDefaultRoles();
|
||||
$roles = $this->getDefaultRoleInstances();
|
||||
foreach ($query->all($this->db) as $row) {
|
||||
$roles[$row['name']] = $this->populateItem($row);
|
||||
}
|
||||
|
||||
@ -392,7 +392,7 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
public function getRolesByUser($userId)
|
||||
{
|
||||
$roles = $this->getDefaultRoles();
|
||||
$roles = $this->getDefaultRoleInstances();
|
||||
foreach ($this->getAssignments($userId) as $name => $assignment) {
|
||||
$role = $this->items[$assignment->roleName];
|
||||
if ($role->type === Item::TYPE_ROLE) {
|
||||
|
||||
@ -65,10 +65,8 @@ abstract class BaseActiveFixture extends DbFixture implements \IteratorAggregate
|
||||
$row = $this->data[$name];
|
||||
/* @var $modelClass \yii\db\ActiveRecord */
|
||||
$modelClass = $this->modelClass;
|
||||
/* @var $model \yii\db\ActiveRecord */
|
||||
$model = new $modelClass;
|
||||
$keys = [];
|
||||
foreach ($model->primaryKey() as $key) {
|
||||
foreach ($modelClass::primaryKey() as $key) {
|
||||
$keys[$key] = isset($row[$key]) ? $row[$key] : null;
|
||||
}
|
||||
|
||||
|
||||
@ -48,6 +48,8 @@ use yii\base\NotSupportedException;
|
||||
*
|
||||
* For more details and usage information on Validator, see the [guide article on validators](guide:input-validation).
|
||||
*
|
||||
* @property array $attributeNames cleaned attribute names without the `!` character at the beginning. This property is read-only.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
@ -101,11 +103,6 @@ class Validator extends Component
|
||||
* please specify them as an array; for single attribute, you may use either a string or an array.
|
||||
*/
|
||||
public $attributes = [];
|
||||
/**
|
||||
* @var array cleaned attribute names. Contains attribute names without `!` character at the beginning
|
||||
* @since 2.0.12
|
||||
*/
|
||||
private $_attributeNames = [];
|
||||
/**
|
||||
* @var string the user-defined error message. It may contain the following placeholders which
|
||||
* will be replaced accordingly by the validator:
|
||||
@ -238,7 +235,6 @@ class Validator extends Component
|
||||
$this->attributes = (array) $this->attributes;
|
||||
$this->on = (array) $this->on;
|
||||
$this->except = (array) $this->except;
|
||||
$this->setAttributeNames((array)$this->attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -459,23 +455,13 @@ class Validator extends Component
|
||||
|
||||
/**
|
||||
* Returns cleaned attribute names without the `!` character at the beginning
|
||||
* @return array
|
||||
* @return array attribute names.
|
||||
* @since 2.0.12
|
||||
*/
|
||||
public function getAttributeNames()
|
||||
{
|
||||
return $this->_attributeNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves attribute names without `!` character at the beginning
|
||||
* @param array $attributeNames
|
||||
* @since 2.0.12
|
||||
*/
|
||||
private function setAttributeNames($attributeNames)
|
||||
{
|
||||
$this->_attributeNames = array_map(function($attribute) {
|
||||
return array_map(function($attribute) {
|
||||
return ltrim($attribute, '!');
|
||||
}, $attributeNames);
|
||||
}, $this->attributes);
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,7 +191,7 @@ class ErrorHandler extends \yii\base\ErrorHandler
|
||||
$url = null;
|
||||
|
||||
$shouldGenerateLink = true;
|
||||
if ($method !== null) {
|
||||
if ($method !== null && substr_compare($method, '{closure}', -9) !== 0) {
|
||||
$reflection = new \ReflectionMethod($class, $method);
|
||||
$shouldGenerateLink = $reflection->isPublic() || $reflection->isProtected();
|
||||
}
|
||||
@ -306,11 +306,11 @@ class ErrorHandler extends \yii\base\ErrorHandler
|
||||
|
||||
/**
|
||||
* Renders call stack.
|
||||
* @param \Exception $exception exception to get call stack from
|
||||
* @param \Exception|\ParseError $exception exception to get call stack from
|
||||
* @return string HTML content of the rendered call stack.
|
||||
* @since 2.0.12
|
||||
*/
|
||||
public function renderCallStack(\Exception $exception)
|
||||
public function renderCallStack($exception)
|
||||
{
|
||||
$out = '<ul>';
|
||||
$out .= $this->renderCallStackItem($exception->getFile(), $exception->getLine(), null, null, [], 1);
|
||||
|
||||
@ -190,6 +190,11 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
|
||||
|
||||
/**
|
||||
* Frees all session variables and destroys all data registered to a session.
|
||||
*
|
||||
* This method has no effect when session is not [[getIsActive()|active]].
|
||||
* Make sure to call [[open()]] before calling it.
|
||||
* @see open()
|
||||
* @see isActive
|
||||
*/
|
||||
public function destroy()
|
||||
{
|
||||
@ -271,8 +276,15 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
|
||||
|
||||
/**
|
||||
* Updates the current session ID with a newly generated one.
|
||||
*
|
||||
* Please refer to <http://php.net/session_regenerate_id> for more details.
|
||||
*
|
||||
* This method has no effect when session is not [[getIsActive()|active]].
|
||||
* Make sure to call [[open()]] before calling it.
|
||||
*
|
||||
* @param bool $deleteOldSession Whether to delete the old associated session file or not.
|
||||
* @see open()
|
||||
* @see isActive
|
||||
*/
|
||||
public function regenerateID($deleteOldSession = false)
|
||||
{
|
||||
|
||||
@ -10,6 +10,7 @@ namespace yii\web;
|
||||
use DOMDocument;
|
||||
use DOMElement;
|
||||
use DOMText;
|
||||
use DOMException;
|
||||
use yii\base\Arrayable;
|
||||
use yii\base\Component;
|
||||
use yii\helpers\StringHelper;
|
||||
@ -94,11 +95,11 @@ class XmlResponseFormatter extends Component implements ResponseFormatterInterfa
|
||||
if (is_int($name) && is_object($value)) {
|
||||
$this->buildXml($element, $value);
|
||||
} elseif (is_array($value) || is_object($value)) {
|
||||
$child = new DOMElement(is_int($name) ? $this->itemTag : $name);
|
||||
$child = new DOMElement($this->getValidXmlElementName($name));
|
||||
$element->appendChild($child);
|
||||
$this->buildXml($child, $value);
|
||||
} else {
|
||||
$child = new DOMElement(is_int($name) ? $this->itemTag : $name);
|
||||
$child = new DOMElement($this->getValidXmlElementName($name));
|
||||
$element->appendChild($child);
|
||||
$child->appendChild(new DOMText($this->formatScalarValue($value)));
|
||||
}
|
||||
@ -143,4 +144,39 @@ class XmlResponseFormatter extends Component implements ResponseFormatterInterfa
|
||||
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns element name ready to be used in DOMElement if
|
||||
* name is not empty, is not int and is valid.
|
||||
*
|
||||
* Falls back to [[itemTag]] otherwise.
|
||||
*
|
||||
* @param mixed $name
|
||||
* @return string
|
||||
* @since 2.0.12
|
||||
*/
|
||||
protected function getValidXmlElementName($name)
|
||||
{
|
||||
if (empty($name) || is_int($name) || !$this->isValidXmlName($name)) {
|
||||
return $this->itemTag;
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if name is valid to be used in XML
|
||||
*
|
||||
* @param mixed $name
|
||||
* @return bool
|
||||
* @see http://stackoverflow.com/questions/2519845/how-to-check-if-string-is-a-valid-xml-element-name/2519943#2519943
|
||||
*/
|
||||
protected function isValidXmlName($name)
|
||||
{
|
||||
try {
|
||||
new DOMElement($name);
|
||||
return true;
|
||||
} catch (DOMException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,4 +225,36 @@ class SortTest extends TestCase
|
||||
|
||||
$this->assertEquals('<a class="asc" href="/index.php?r=site%2Findex&sort=-age%2C-name" data-sort="-age,-name">Age</a>', $sort->link('age'));
|
||||
}
|
||||
|
||||
public function testParseSortParam()
|
||||
{
|
||||
$sort = new CustomSort([
|
||||
'attributes' => [
|
||||
'age',
|
||||
'name'
|
||||
],
|
||||
'params' => [
|
||||
'sort' => [
|
||||
['field' => 'age', 'dir' => 'asc'],
|
||||
['field' => 'name', 'dir' => 'desc']
|
||||
]
|
||||
],
|
||||
'enableMultiSort' => true
|
||||
]);
|
||||
|
||||
$this->assertEquals(SORT_ASC, $sort->getAttributeOrder('age'));
|
||||
$this->assertEquals(SORT_DESC, $sort->getAttributeOrder('name'));
|
||||
}
|
||||
}
|
||||
|
||||
class CustomSort extends Sort
|
||||
{
|
||||
protected function parseSortParam($params)
|
||||
{
|
||||
$attributes = [];
|
||||
foreach ($params as $item) {
|
||||
$attributes[] = ($item['dir'] == 'desc') ? '-' . $item['field'] : $item['field'];
|
||||
}
|
||||
return $attributes;
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,4 +32,16 @@ class SqlDataProviderTest extends DatabaseTestCase
|
||||
]);
|
||||
$this->assertEquals(3, $dataProvider->getTotalCount());
|
||||
}
|
||||
|
||||
public function testTotalCountWithParams()
|
||||
{
|
||||
$dataProvider = new SqlDataProvider([
|
||||
'sql' => 'select * from `customer` where id > :minimum',
|
||||
'params' => [
|
||||
':minimum' => -1
|
||||
],
|
||||
'db' => $this->getConnection(),
|
||||
]);
|
||||
$this->assertEquals(3, $dataProvider->getTotalCount());
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,7 +112,6 @@ class InstanceTest extends TestCase
|
||||
$this->expectExceptionMessage('"db" refers to a yii\db\Connection component. yii\base\Widget is expected.');
|
||||
|
||||
Instance::ensure('db', 'yii\base\Widget', $container);
|
||||
Instance::ensure(['class' => 'yii\db\Connection', 'dsn' => 'test'], 'yii\base\Widget', $container);
|
||||
}
|
||||
|
||||
public function testExceptionInvalidDataType()
|
||||
@ -191,4 +190,12 @@ PHP
|
||||
|
||||
Instance::__set_state([]);
|
||||
}
|
||||
|
||||
public function testExceptionInvalidDataTypeInArray()
|
||||
{
|
||||
$this->setExpectedException('yii\base\InvalidConfigException', 'Invalid data type: yii\db\Connection. yii\base\Widget is expected.');
|
||||
Instance::ensure([
|
||||
'class' => Connection::className(),
|
||||
], 'yii\base\Widget');
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,6 @@ namespace yiiunit\framework\filters;
|
||||
use Yii;
|
||||
use yii\base\Action;
|
||||
use yii\filters\AccessRule;
|
||||
use yii\filters\HttpCache;
|
||||
use yii\web\Controller;
|
||||
use yii\web\Request;
|
||||
use yii\web\User;
|
||||
@ -21,8 +20,8 @@ class AccessRuleTest extends \yiiunit\TestCase
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$_SERVER['SCRIPT_FILENAME'] = "/index.php";
|
||||
$_SERVER['SCRIPT_NAME'] = "/index.php";
|
||||
$_SERVER['SCRIPT_FILENAME'] = '/index.php';
|
||||
$_SERVER['SCRIPT_NAME'] = '/index.php';
|
||||
|
||||
$this->mockWebApplication();
|
||||
}
|
||||
@ -42,7 +41,7 @@ class AccessRuleTest extends \yiiunit\TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string optional user id
|
||||
* @param string $userid optional user id
|
||||
* @return User
|
||||
*/
|
||||
protected function mockUser($userid = null)
|
||||
@ -292,6 +291,14 @@ class AccessRuleTest extends \yiiunit\TestCase
|
||||
$this->assertNull($rule->allows($action, $user, $request));
|
||||
$rule->allow = false;
|
||||
$this->assertNull($rule->allows($action, $user, $request));
|
||||
|
||||
// undefined IP
|
||||
$_SERVER['REMOTE_ADDR'] = null;
|
||||
$rule->ips = ['192.168.*'];
|
||||
$rule->allow = true;
|
||||
$this->assertNull($rule->allows($action, $user, $request));
|
||||
$rule->allow = false;
|
||||
$this->assertNull($rule->allows($action, $user, $request));
|
||||
}
|
||||
|
||||
public function testMatchIPWildcard()
|
||||
|
||||
@ -44,7 +44,9 @@ class ArrayHelperTest extends TestCase
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
|
||||
// destroy application, Helper must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testToArray()
|
||||
@ -267,6 +269,7 @@ class ArrayHelperTest extends TestCase
|
||||
$sort = new Sort([
|
||||
'attributes' => ['name', 'age'],
|
||||
'defaultOrder' => ['name' => SORT_ASC],
|
||||
'params' => [],
|
||||
]);
|
||||
$orders = $sort->getOrders();
|
||||
|
||||
@ -284,6 +287,7 @@ class ArrayHelperTest extends TestCase
|
||||
$sort = new Sort([
|
||||
'attributes' => ['name', 'age'],
|
||||
'defaultOrder' => ['name' => SORT_ASC, 'age' => SORT_DESC],
|
||||
'params' => [],
|
||||
]);
|
||||
$orders = $sort->getOrders();
|
||||
|
||||
|
||||
@ -12,6 +12,14 @@ use yiiunit\TestCase;
|
||||
*/
|
||||
class ConsoleTest extends TestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// destroy application, Helper must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testStripAnsiFormat()
|
||||
{
|
||||
ob_start();
|
||||
|
||||
@ -33,8 +33,14 @@ class FileHelperTest extends TestCase
|
||||
*/
|
||||
$this->markTestInComplete('Unit tests runtime directory should be local!');
|
||||
}
|
||||
|
||||
parent::setUp();
|
||||
|
||||
// destroy application, Helper must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
$this->removeDir($this->testFilePath);
|
||||
|
||||
@ -10,6 +10,14 @@ use yiiunit\TestCase;
|
||||
*/
|
||||
class InflectorTest extends TestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// destroy application, Helper must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testPluralize()
|
||||
{
|
||||
$testData = [
|
||||
|
||||
@ -14,6 +14,14 @@ use yiiunit\framework\web\Post;
|
||||
*/
|
||||
class JsonTest extends TestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// destroy application, Helper must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testEncode()
|
||||
{
|
||||
// basic data encoding
|
||||
|
||||
@ -12,6 +12,14 @@ use yii\helpers\Markdown;
|
||||
*/
|
||||
class MarkdownTest extends TestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// destroy application, Helper must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testOriginalFlavor()
|
||||
{
|
||||
$text = <<<TEXT
|
||||
|
||||
@ -10,6 +10,14 @@ use yiiunit\TestCase;
|
||||
*/
|
||||
class VarDumperTest extends TestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// destroy application, Helper must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testDumpIncompleteObject()
|
||||
{
|
||||
$serializedObj = 'O:16:"nonExistingClass":0:{}';
|
||||
|
||||
@ -14,7 +14,9 @@ class BooleanValidatorTest extends TestCase
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
|
||||
// destroy application, Validator must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testValidateValue()
|
||||
|
||||
@ -14,7 +14,9 @@ class CompareValidatorTest extends TestCase
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
|
||||
// destroy application, Validator must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testValidateValueException()
|
||||
|
||||
@ -13,7 +13,9 @@ class DefaultValueValidatorTest extends TestCase
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
|
||||
// destroy application, Validator must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testValidateAttribute()
|
||||
|
||||
@ -14,7 +14,9 @@ class EachValidatorTest extends TestCase
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
|
||||
// destroy application, Validator must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testArrayFormat()
|
||||
|
||||
@ -13,7 +13,9 @@ class EmailValidatorTest extends TestCase
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
|
||||
// destroy application, Validator must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testValidateValue()
|
||||
|
||||
@ -14,10 +14,12 @@ use yiiunit\framework\db\DatabaseTestCase;
|
||||
|
||||
abstract class ExistValidatorTest extends DatabaseTestCase
|
||||
{
|
||||
public function setUp()
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
|
||||
// destroy application, Validator must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
ActiveRecord::$db = $this->getConnection();
|
||||
}
|
||||
|
||||
|
||||
@ -14,8 +14,9 @@ use yiiunit\TestCase;
|
||||
*/
|
||||
class FileValidatorTest extends TestCase
|
||||
{
|
||||
public function setUp()
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,8 @@ class FilterValidatorTest extends TestCase
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
// destroy application, Validator must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testAssureExceptionOnInit()
|
||||
|
||||
@ -14,7 +14,8 @@ class IpValidatorTest extends TestCase
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
// destroy application, Validator must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testInitException()
|
||||
|
||||
@ -46,8 +46,11 @@ class NumberValidatorTest extends TestCase
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
|
||||
$this->oldLocale = setlocale(LC_NUMERIC, 0);
|
||||
|
||||
// destroy application, Validator must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testEnsureMessageOnInit()
|
||||
|
||||
@ -14,7 +14,9 @@ class RangeValidatorTest extends TestCase
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
|
||||
// destroy application, Validator must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testInitException()
|
||||
|
||||
@ -14,7 +14,9 @@ class RegularExpressionValidatorTest extends TestCase
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
|
||||
// destroy application, Validator must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testValidateValue()
|
||||
|
||||
@ -13,7 +13,9 @@ class RequiredValidatorTest extends TestCase
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
|
||||
// destroy application, Validator must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testValidateValueWithDefaults()
|
||||
|
||||
@ -16,11 +16,13 @@ use yiiunit\framework\db\DatabaseTestCase;
|
||||
|
||||
abstract class UniqueValidatorTest extends DatabaseTestCase
|
||||
{
|
||||
public function setUp()
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
ActiveRecord::$db = $this->getConnection();
|
||||
|
||||
// destroy application, Validator must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testAssureMessageSetOnInit()
|
||||
|
||||
@ -14,7 +14,9 @@ class UrlValidatorTest extends TestCase
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
|
||||
// destroy application, Validator must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
public function testValidateValue()
|
||||
|
||||
@ -17,7 +17,9 @@ class ValidatorTest extends TestCase
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
|
||||
// destroy application, Validator must work without Yii::$app
|
||||
$this->destroyApplication();
|
||||
}
|
||||
|
||||
protected function getTestModel($additionalAttributes = [])
|
||||
@ -240,17 +242,27 @@ class ValidatorTest extends TestCase
|
||||
$this->assertEquals('attr_msg_val::abc::param_value', $errors[0]);
|
||||
}
|
||||
|
||||
public function testGetAttributeNames()
|
||||
{
|
||||
$validator = new TestValidator();
|
||||
$validator->attributes = ['id', 'name', '!email'];
|
||||
$this->assertEquals(['id', 'name', 'email'], $validator->getAttributeNames());
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testGetAttributeNames
|
||||
*/
|
||||
public function testGetActiveValidatorsForSafeAttributes()
|
||||
{
|
||||
$model = $this->getTestModel();
|
||||
$validators = $model->getActiveValidators('safe_attr');
|
||||
$is_found = false;
|
||||
$isFound = false;
|
||||
foreach ($validators as $v) {
|
||||
if ($v instanceof NumberValidator) {
|
||||
$is_found = true;
|
||||
$isFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->assertTrue($is_found);
|
||||
$this->assertTrue($isFound);
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,6 +69,16 @@ class XmlResponseFormatterTest extends FormatterTest
|
||||
'c' => [2, '<>'],
|
||||
false,
|
||||
], "<response><a>1</a><b>abc</b><c><item>2</item><item><></item></c><item>false</item></response>\n"],
|
||||
|
||||
// Checks if empty keys and keys not valid in XML are processed.
|
||||
// See https://github.com/yiisoft/yii2/pull/10346/
|
||||
[[
|
||||
'' => 1,
|
||||
'2015-06-18' => '2015-06-18',
|
||||
'b:c' => 'b:c',
|
||||
'a b c' => 'a b c',
|
||||
'äøñ' => 'äøñ'
|
||||
], "<response><item>1</item><item>2015-06-18</item><item>b:c</item><item>a b c</item><äøñ>äøñ</äøñ></response>\n"],
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user