Merge branch 'master' of https://github.com/yiisoft/yii2 into schema-cache-fixes

This commit is contained in:
brandonkelly
2017-04-27 10:35:30 -07:00
48 changed files with 380 additions and 97 deletions

View File

@ -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`.

View File

@ -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
--------------------------

View File

@ -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;
}

View File

@ -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"
},

View File

@ -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";
}
}

View File

@ -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();
}

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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.');
}

View File

@ -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;
}
}

View File

@ -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}".',

View File

@ -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) {

View File

@ -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);
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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)
{

View File

@ -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;
}
}
}

View File

@ -225,4 +225,36 @@ class SortTest extends TestCase
$this->assertEquals('<a class="asc" href="/index.php?r=site%2Findex&amp;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;
}
}

View File

@ -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());
}
}

View File

@ -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');
}
}

View File

@ -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()

View File

@ -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();

View File

@ -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();

View File

@ -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);

View File

@ -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 = [

View File

@ -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

View File

@ -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

View File

@ -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:{}';

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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();
}

View File

@ -14,8 +14,9 @@ use yiiunit\TestCase;
*/
class FileValidatorTest extends TestCase
{
public function setUp()
protected function setUp()
{
parent::setUp();
$this->mockApplication();
}

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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);
}
}

View File

@ -69,6 +69,16 @@ class XmlResponseFormatterTest extends FormatterTest
'c' => [2, '<>'],
false,
], "<response><a>1</a><b>abc</b><c><item>2</item><item>&lt;&gt;</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"],
]);
}