Browse Source

Merge branch 'master' of github.com:yiisoft/yii2 into email-swift-2

tags/2.0.0-beta
Paul Klimov 11 years ago
parent
commit
a3dd0d57b4
  1. 1
      apps/advanced/backend/config/main.php
  2. 4
      apps/advanced/composer.json
  3. 1
      apps/advanced/console/config/main.php
  4. 1
      apps/advanced/environments/dev/frontend/web/index.php
  5. 1
      apps/advanced/environments/dev/yii
  6. 1
      apps/advanced/environments/prod/frontend/web/index.php
  7. 1
      apps/advanced/environments/prod/yii
  8. 1
      apps/advanced/frontend/config/main.php
  9. 6
      apps/basic/composer.json
  10. 3
      apps/basic/config/console.php
  11. 1
      apps/basic/config/web.php
  12. 1
      apps/basic/web/index-test.php
  13. 1
      apps/basic/web/index.php
  14. 1
      apps/basic/yii
  15. 4
      docs/guide/apps-advanced.md
  16. 6
      docs/guide/apps-basic.md
  17. 2
      extensions/composer/composer.json
  18. 97
      extensions/composer/yii/composer/InstallHandler.php
  19. 41
      extensions/composer/yii/composer/Installer.php
  20. 4
      extensions/composer/yii/composer/Plugin.php
  21. 1
      extensions/jui/yii/jui/AccordionAsset.php
  22. 27
      extensions/jui/yii/jui/Extension.php
  23. 37
      framework/yii/BaseYii.php
  24. 4
      framework/yii/base/Application.php
  25. 9
      framework/yii/base/Model.php
  26. 2
      framework/yii/base/Module.php
  27. 1
      framework/yii/base/Theme.php
  28. 4
      framework/yii/bootstrap/Carousel.php
  29. 2
      framework/yii/bootstrap/Dropdown.php
  30. 2
      framework/yii/bootstrap/Nav.php
  31. 6
      framework/yii/bootstrap/Tabs.php
  32. 1
      framework/yii/bootstrap/Widget.php
  33. 13
      framework/yii/captcha/CaptchaValidator.php
  34. 2
      framework/yii/data/ArrayDataProvider.php
  35. 18
      framework/yii/db/ActiveRecord.php
  36. 1
      framework/yii/gii/generators/crud/Generator.php
  37. 2
      framework/yii/gii/generators/form/templates/action.php
  38. 8
      framework/yii/gii/generators/form/templates/form.php
  39. 8
      framework/yii/gii/generators/model/Generator.php
  40. 10
      framework/yii/gii/generators/module/templates/view.php
  41. 1
      framework/yii/gii/views/default/view.php
  42. 1
      framework/yii/gii/views/default/view/files.php
  43. 4
      framework/yii/gii/views/default/view/results.php
  44. 2
      framework/yii/grid/ActionColumn.php
  45. 8
      framework/yii/grid/DataColumn.php
  46. 2
      framework/yii/grid/GridView.php
  47. 14
      framework/yii/helpers/BaseArrayHelper.php
  48. 306
      framework/yii/i18n/FallbackMessageFormatter.php
  49. 22
      framework/yii/i18n/I18N.php
  50. 16
      framework/yii/i18n/MessageFormatter.php
  51. 2
      framework/yii/log/Logger.php
  52. 42
      framework/yii/requirements/YiiRequirementChecker.php
  53. 28
      framework/yii/requirements/requirements.php
  54. 12
      framework/yii/requirements/views/web/index.php
  55. 4
      framework/yii/validators/BooleanValidator.php
  56. 4
      framework/yii/validators/CompareValidator.php
  57. 4
      framework/yii/validators/DateValidator.php
  58. 10
      framework/yii/validators/FileValidator.php
  59. 4
      framework/yii/validators/NumberValidator.php
  60. 2
      framework/yii/validators/RequiredValidator.php
  61. 6
      framework/yii/validators/StringValidator.php
  62. 2
      framework/yii/validators/UniqueValidator.php
  63. 6
      framework/yii/validators/Validator.php
  64. 6
      framework/yii/web/AccessControl.php
  65. 11
      framework/yii/web/AssetBundle.php
  66. 6
      framework/yii/web/Request.php
  67. 9
      framework/yii/web/Session.php
  68. 3
      framework/yii/web/YiiAsset.php
  69. 1
      framework/yii/widgets/ActiveField.php
  70. 89
      framework/yii/widgets/ActiveForm.php
  71. 24
      framework/yii/widgets/BaseListView.php
  72. 6
      framework/yii/widgets/Menu.php
  73. 2
      tests/unit/data/ar/ActiveRecord.php
  74. 1
      tests/unit/framework/caching/CacheTestCase.php
  75. 1
      tests/unit/framework/caching/RedisCacheTest.php
  76. 1
      tests/unit/framework/caching/ZendDataCacheTest.php
  77. 1
      tests/unit/framework/db/ActiveRecordTest.php
  78. 3
      tests/unit/framework/db/CommandTest.php
  79. 3
      tests/unit/framework/db/QueryTest.php
  80. 1
      tests/unit/framework/db/cubrid/CubridQueryBuilderTest.php
  81. 155
      tests/unit/framework/i18n/FallbackMessageFormatterTest.php
  82. 1
      tests/unit/framework/i18n/GettextMessageSourceTest.php
  83. 7
      tests/unit/framework/i18n/I18NTest.php
  84. 6
      tests/unit/framework/validators/BooleanValidatorTest.php
  85. 5
      tests/unit/framework/validators/CompareValidatorTest.php
  86. 7
      tests/unit/framework/validators/DateValidatorTest.php
  87. 6
      tests/unit/framework/validators/DefaultValueValidatorTest.php
  88. 6
      tests/unit/framework/validators/EmailValidatorTest.php
  89. 1
      tests/unit/framework/validators/ExistValidatorTest.php
  90. 6
      tests/unit/framework/validators/FilterValidatorTest.php
  91. 6
      tests/unit/framework/validators/NumberValidatorTest.php
  92. 6
      tests/unit/framework/validators/RangeValidatorTest.php
  93. 6
      tests/unit/framework/validators/RegularExpressionValidatorTest.php
  94. 6
      tests/unit/framework/validators/RequiredValidatorTest.php
  95. 2
      tests/unit/framework/validators/UniqueValidatorTest.php
  96. 6
      tests/unit/framework/validators/UrlValidatorTest.php
  97. 7
      tests/unit/framework/validators/ValidatorTest.php

1
apps/advanced/backend/config/main.php

@ -15,6 +15,7 @@ return [
'preload' => ['log'], 'preload' => ['log'],
'controllerNamespace' => 'backend\controllers', 'controllerNamespace' => 'backend\controllers',
'modules' => [], 'modules' => [],
'extensions' => require(__DIR__ . '/../../vendor/yii-extensions.php'),
'components' => [ 'components' => [
'request' => [ 'request' => [
'enableCsrfValidation' => true, 'enableCsrfValidation' => true,

4
apps/advanced/composer.json

@ -20,12 +20,12 @@
}, },
"scripts": { "scripts": {
"post-create-project-cmd": [ "post-create-project-cmd": [
"yii\\composer\\InstallHandler::setPermissions", "yii\\composer\\Installer::setPermission",
"./init" "./init"
] ]
}, },
"extra": { "extra": {
"yii-install-writable": [ "writable": [
"backend/runtime", "backend/runtime",
"backend/web/assets", "backend/web/assets",

1
apps/advanced/console/config/main.php

@ -15,6 +15,7 @@ return [
'controllerNamespace' => 'console\controllers', 'controllerNamespace' => 'console\controllers',
'modules' => [ 'modules' => [
], ],
'extensions' => require(__DIR__ . '/../../vendor/yii-extensions.php'),
'components' => [ 'components' => [
'db' => $params['components.db'], 'db' => $params['components.db'],
'cache' => $params['components.cache'], 'cache' => $params['components.cache'],

1
apps/advanced/environments/dev/frontend/web/index.php

@ -4,7 +4,6 @@ defined('YII_ENV') or define('YII_ENV', 'dev');
require(__DIR__ . '/../../vendor/autoload.php'); require(__DIR__ . '/../../vendor/autoload.php');
require(__DIR__ . '/../../vendor/yiisoft/yii2/yii/Yii.php'); require(__DIR__ . '/../../vendor/yiisoft/yii2/yii/Yii.php');
Yii::importNamespaces(require(__DIR__ . '/../../vendor/composer/autoload_namespaces.php'));
$config = yii\helpers\ArrayHelper::merge( $config = yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/../config/main.php'), require(__DIR__ . '/../config/main.php'),

1
apps/advanced/environments/dev/yii

@ -16,7 +16,6 @@ defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
require(__DIR__ . '/vendor/autoload.php'); require(__DIR__ . '/vendor/autoload.php');
require(__DIR__ . '/vendor/yiisoft/yii2/yii/Yii.php'); require(__DIR__ . '/vendor/yiisoft/yii2/yii/Yii.php');
Yii::importNamespaces(require(__DIR__ . '/vendor/composer/autoload_namespaces.php'));
$config = yii\helpers\ArrayHelper::merge( $config = yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/console/config/main.php'), require(__DIR__ . '/console/config/main.php'),

1
apps/advanced/environments/prod/frontend/web/index.php

@ -4,7 +4,6 @@ defined('YII_ENV') or define('YII_ENV', 'prod');
require(__DIR__ . '/../../vendor/autoload.php'); require(__DIR__ . '/../../vendor/autoload.php');
require(__DIR__ . '/../../vendor/yiisoft/yii2/yii/Yii.php'); require(__DIR__ . '/../../vendor/yiisoft/yii2/yii/Yii.php');
Yii::importNamespaces(require(__DIR__ . '/../../vendor/composer/autoload_namespaces.php'));
$config = yii\helpers\ArrayHelper::merge( $config = yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/../config/main.php'), require(__DIR__ . '/../config/main.php'),

1
apps/advanced/environments/prod/yii

@ -16,7 +16,6 @@ defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
require(__DIR__ . '/vendor/autoload.php'); require(__DIR__ . '/vendor/autoload.php');
require(__DIR__ . '/vendor/yiisoft/yii2/yii/Yii.php'); require(__DIR__ . '/vendor/yiisoft/yii2/yii/Yii.php');
Yii::importNamespaces(require(__DIR__ . '/vendor/composer/autoload_namespaces.php'));
$config = yii\helpers\ArrayHelper::merge( $config = yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/console/config/main.php'), require(__DIR__ . '/console/config/main.php'),

1
apps/advanced/frontend/config/main.php

@ -16,6 +16,7 @@ return [
'modules' => [ 'modules' => [
'gii' => 'yii\gii\Module' 'gii' => 'yii\gii\Module'
], ],
'extensions' => require(__DIR__ . '/../../vendor/yii-extensions.php'),
'components' => [ 'components' => [
'request' => [ 'request' => [
'enableCsrfValidation' => true, 'enableCsrfValidation' => true,

6
apps/basic/composer.json

@ -20,15 +20,15 @@
}, },
"scripts": { "scripts": {
"post-create-project-cmd": [ "post-create-project-cmd": [
"yii\\composer\\InstallHandler::setPermissions" "yii\\composer\\Installer::setPermission"
] ]
}, },
"extra": { "extra": {
"yii-install-writable": [ "writable": [
"runtime", "runtime",
"web/assets" "web/assets"
], ],
"yii-install-executable": [ "executable": [
"yii" "yii"
] ]
} }

3
apps/basic/config/console.php

@ -6,8 +6,7 @@ return [
'preload' => ['log'], 'preload' => ['log'],
'controllerPath' => dirname(__DIR__) . '/commands', 'controllerPath' => dirname(__DIR__) . '/commands',
'controllerNamespace' => 'app\commands', 'controllerNamespace' => 'app\commands',
'modules' => [ 'extensions' => require(__DIR__ . '/../vendor/yii-extensions.php'),
],
'components' => [ 'components' => [
'cache' => [ 'cache' => [
'class' => 'yii\caching\FileCache', 'class' => 'yii\caching\FileCache',

1
apps/basic/config/web.php

@ -3,6 +3,7 @@ $params = require(__DIR__ . '/params.php');
$config = [ $config = [
'id' => 'bootstrap', 'id' => 'bootstrap',
'basePath' => dirname(__DIR__), 'basePath' => dirname(__DIR__),
'extensions' => require(__DIR__ . '/../vendor/yii-extensions.php'),
'components' => [ 'components' => [
'request' => [ 'request' => [
'enableCsrfValidation' => true, 'enableCsrfValidation' => true,

1
apps/basic/web/index-test.php

@ -10,7 +10,6 @@ defined('YII_ENV') or define('YII_ENV', 'test');
require_once(__DIR__ . '/../vendor/autoload.php'); require_once(__DIR__ . '/../vendor/autoload.php');
require_once(__DIR__ . '/../vendor/yiisoft/yii2/yii/Yii.php'); require_once(__DIR__ . '/../vendor/yiisoft/yii2/yii/Yii.php');
Yii::importNamespaces(require(__DIR__ . '/../vendor/composer/autoload_namespaces.php'));
$config = require(__DIR__ . '/../config/web-test.php'); $config = require(__DIR__ . '/../config/web-test.php');

1
apps/basic/web/index.php

@ -6,7 +6,6 @@ defined('YII_ENV') or define('YII_ENV', 'dev');
require(__DIR__ . '/../vendor/autoload.php'); require(__DIR__ . '/../vendor/autoload.php');
require(__DIR__ . '/../vendor/yiisoft/yii2/yii/Yii.php'); require(__DIR__ . '/../vendor/yiisoft/yii2/yii/Yii.php');
Yii::importNamespaces(require(__DIR__ . '/../vendor/composer/autoload_namespaces.php'));
$config = require(__DIR__ . '/../config/web.php'); $config = require(__DIR__ . '/../config/web.php');

1
apps/basic/yii

@ -15,7 +15,6 @@ defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
require(__DIR__ . '/vendor/autoload.php'); require(__DIR__ . '/vendor/autoload.php');
require(__DIR__ . '/vendor/yiisoft/yii2/yii/Yii.php'); require(__DIR__ . '/vendor/yiisoft/yii2/yii/Yii.php');
Yii::importNamespaces(require(__DIR__ . '/vendor/composer/autoload_namespaces.php'));
$config = require(__DIR__ . '/config/console.php'); $config = require(__DIR__ . '/config/console.php');

4
docs/guide/apps-advanced.md

@ -144,11 +144,11 @@ directory:
}, },
"scripts": { "scripts": {
"post-create-project-cmd": [ "post-create-project-cmd": [
"yii\\composer\\InstallHandler::setPermissions" "yii\\composer\\Installer::setPermission"
] ]
}, },
"extra": { "extra": {
"yii-install-writable": [ "writable": [
"backend/runtime", "backend/runtime",
"backend/web/assets", "backend/web/assets",

6
docs/guide/apps-basic.md

@ -134,15 +134,15 @@ directory:
}, },
"scripts": { "scripts": {
"post-create-project-cmd": [ "post-create-project-cmd": [
"yii\\composer\\InstallHandler::setPermissions" "yii\\composer\\Installer::setPermission"
] ]
}, },
"extra": { "extra": {
"yii-install-writable": [ "writable": [
"runtime", "runtime",
"web/assets" "web/assets"
], ],
"yii-install-executable": [ "executable": [
"yii" "yii"
] ]
} }

2
extensions/composer/composer.json

@ -22,7 +22,7 @@
"psr-0": { "yii\\composer\\": "" } "psr-0": { "yii\\composer\\": "" }
}, },
"extra": { "extra": {
"class": "yii\\composer\\InstallerPlugin" "class": "yii\\composer\\Plugin"
}, },
"require": { "require": {
"composer-plugin-api": "1.0.0" "composer-plugin-api": "1.0.0"

97
extensions/composer/yii/composer/InstallHandler.php

@ -1,97 +0,0 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\composer;
use Composer\Script\CommandEvent;
use yii\console\Application;
use yii\console\Exception;
defined('YII_DEBUG') or define('YII_DEBUG', true);
// fcgi doesn't have STDIN defined by default
defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
/**
* InstallHandler is called by Composer after it installs/updates the current package.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Tobias Munk <schmunk@usrbin.de>
* @since 2.0
*/
class InstallHandler
{
const PARAM_WRITABLE = 'yii-install-writable';
const PARAM_EXECUTABLE = 'yii-install-executable';
const PARAM_CONFIG = 'yii-install-config';
const PARAM_COMMANDS = 'yii-install-commands';
/**
* Sets the correct permissions of files and directories.
* @param CommandEvent $event
*/
public static function setPermissions($event)
{
$options = array_merge([
self::PARAM_WRITABLE => [],
self::PARAM_EXECUTABLE => [],
], $event->getComposer()->getPackage()->getExtra());
foreach ((array)$options[self::PARAM_WRITABLE] as $path) {
echo "Setting writable: $path ...";
if (is_dir($path)) {
chmod($path, 0777);
echo "done\n";
} else {
echo "The directory was not found: " . getcwd() . DIRECTORY_SEPARATOR . $path;
return;
}
}
foreach ((array)$options[self::PARAM_EXECUTABLE] as $path) {
echo "Setting executable: $path ...";
if (is_file($path)) {
chmod($path, 0755);
echo "done\n";
} else {
echo "\n\tThe file was not found: " . getcwd() . DIRECTORY_SEPARATOR . $path . "\n";
return;
}
}
}
/**
* Executes a yii command.
* @param CommandEvent $event
*/
public static function run($event)
{
$options = array_merge([
self::PARAM_COMMANDS => [],
], $event->getComposer()->getPackage()->getExtra());
if (!isset($options[self::PARAM_CONFIG])) {
throw new Exception('Please specify the "' . self::PARAM_CONFIG . '" parameter in composer.json.');
}
$configFile = getcwd() . '/' . $options[self::PARAM_CONFIG];
if (!is_file($configFile)) {
throw new Exception("Config file does not exist: $configFile");
}
require_once(__DIR__ . '/../../../yii2/yii/Yii.php');
$application = new Application(require($configFile));
$request = $application->getRequest();
foreach ((array)$options[self::PARAM_COMMANDS] as $command) {
$params = str_getcsv($command, ' '); // see http://stackoverflow.com/a/6609509/291573
$request->setParams($params);
list($route, $params) = $request->resolve();
echo "Running command: yii {$command}\n";
$application->runAction($route, $params);
}
}
}

41
extensions/composer/yii/composer/Installer.php

@ -11,8 +11,6 @@ use Composer\Package\PackageInterface;
use Composer\Installer\LibraryInstaller; use Composer\Installer\LibraryInstaller;
use Composer\Repository\InstalledRepositoryInterface; use Composer\Repository\InstalledRepositoryInterface;
use Composer\Script\CommandEvent; use Composer\Script\CommandEvent;
use yii\console\Application;
use yii\console\Exception;
/** /**
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
@ -20,11 +18,9 @@ use yii\console\Exception;
*/ */
class Installer extends LibraryInstaller class Installer extends LibraryInstaller
{ {
const EXTRA_BOOTSTRAP = 'bootstrap';
const EXTRA_WRITABLE = 'writable'; const EXTRA_WRITABLE = 'writable';
const EXTRA_EXECUTABLE = 'executable'; const EXTRA_EXECUTABLE = 'executable';
const EXTRA_CONFIG = 'yii-config';
const EXTRA_COMMANDS = 'yii-commands';
const EXTRA_BOOTSTRAP = 'bootstrap';
/** /**
* @inheritdoc * @inheritdoc
@ -101,10 +97,10 @@ class Installer extends LibraryInstaller
/** /**
* Sets the correct permissions of files and directories. * Sets the correct permission for the files and directories listed in the extra section.
* @param CommandEvent $event * @param CommandEvent $event
*/ */
public static function setPermissions($event) public static function setPermission($event)
{ {
$options = array_merge([ $options = array_merge([
self::EXTRA_WRITABLE => [], self::EXTRA_WRITABLE => [],
@ -133,35 +129,4 @@ class Installer extends LibraryInstaller
} }
} }
} }
/**
* Executes a yii command.
* @param CommandEvent $event
*/
public static function run($event)
{
$options = array_merge([
self::EXTRA_COMMANDS => [],
], $event->getComposer()->getPackage()->getExtra());
if (!isset($options[self::EXTRA_CONFIG])) {
throw new Exception('Please specify the "' . self::EXTRA_CONFIG . '" parameter in composer.json.');
}
$configFile = getcwd() . '/' . $options[self::EXTRA_CONFIG];
if (!is_file($configFile)) {
throw new Exception("Config file does not exist: $configFile");
}
require_once(__DIR__ . '/../../../yii2/yii/Yii.php');
$application = new Application(require($configFile));
$request = $application->getRequest();
foreach ((array)$options[self::EXTRA_COMMANDS] as $command) {
$params = str_getcsv($command, ' '); // see http://stackoverflow.com/a/6609509/291573
$request->setParams($params);
list($route, $params) = $request->resolve();
echo "Running command: yii {$command}\n";
$application->runAction($route, $params);
}
}
} }

4
extensions/composer/yii/composer/InstallerPlugin.php → extensions/composer/yii/composer/Plugin.php

@ -12,12 +12,12 @@ use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface; use Composer\Plugin\PluginInterface;
/** /**
* InstallerPlugin is the composer plugin that registers the Yii composer installer. * Plugin is the composer plugin that registers the Yii composer installer.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
class InstallerPlugin implements PluginInterface class Plugin implements PluginInterface
{ {
/** /**
* @inheritdoc * @inheritdoc

1
extensions/jui/yii/jui/AccordionAsset.php

@ -6,6 +6,7 @@
*/ */
namespace yii\jui; namespace yii\jui;
use yii\web\AssetBundle; use yii\web\AssetBundle;
/** /**

27
extensions/jui/yii/jui/Extension.php

@ -0,0 +1,27 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use Yii;
/**
* This is the bootstrap class for the Yii JUI extension.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Extension extends \yii\base\Extension
{
/**
* @inheritdoc
*/
public static function init()
{
Yii::setAlias('@yii/jui', __DIR__);
}
}

37
framework/yii/BaseYii.php

@ -6,7 +6,6 @@
*/ */
namespace yii; namespace yii;
use yii\base\Exception;
use yii\base\InvalidConfigException; use yii\base\InvalidConfigException;
use yii\base\InvalidParamException; use yii\base\InvalidParamException;
use yii\base\UnknownClassException; use yii\base\UnknownClassException;
@ -110,33 +109,6 @@ class BaseYii
} }
/** /**
* Imports a set of namespaces.
*
* By importing a namespace, the method will create an alias for the directory corresponding
* to the namespace. For example, if "foo\bar" is a namespace associated with the directory
* "path/to/foo/bar", then an alias "@foo/bar" will be created for this directory.
*
* This method is typically invoked in the bootstrap file to import the namespaces of
* the installed extensions. By default, Composer, when installing new extensions, will
* generate such a mapping file which can be loaded and passed to this method.
*
* @param array $namespaces the namespaces to be imported. The keys are the namespaces,
* and the values are the corresponding directories.
*/
public static function importNamespaces($namespaces)
{
foreach ($namespaces as $name => $path) {
if ($name !== '') {
$name = trim(strtr($name, ['\\' => '/', '_' => '/']), '/');
if (is_array($path)) {
$path = reset($path);
}
static::setAlias('@' . $name, rtrim($path, '/\\') . '/' . $name);
}
}
}
/**
* Translates a path alias into an actual path. * Translates a path alias into an actual path.
* *
* The translation is done according to the following procedure: * The translation is done according to the following procedure:
@ -335,8 +307,7 @@ class BaseYii
include($classFile); include($classFile);
if (YII_DEBUG && !class_exists($className, false) && !interface_exists($className, false) && if (YII_DEBUG && !class_exists($className, false) && !interface_exists($className, false) && !trait_exists($className, false)) {
(!function_exists('trait_exists') || !trait_exists($className, false))) {
throw new UnknownClassException("Unable to find '$className' in file: $classFile"); throw new UnknownClassException("Unable to find '$className' in file: $classFile");
} }
} }
@ -543,7 +514,11 @@ class BaseYii
if (self::$app !== null) { if (self::$app !== null) {
return self::$app->getI18n()->translate($category, $message, $params, $language ?: self::$app->language); return self::$app->getI18n()->translate($category, $message, $params, $language ?: self::$app->language);
} else { } else {
return is_array($params) ? strtr($message, $params) : $message; $p = [];
foreach((array) $params as $name => $value) {
$p['{' . $name . '}'] = $value;
}
return ($p === []) ? $message : strtr($message, $p);
} }
} }

4
framework/yii/base/Application.php

@ -85,10 +85,6 @@ abstract class Application extends Module
*/ */
public $sourceLanguage = 'en_US'; public $sourceLanguage = 'en_US';
/** /**
* @var array IDs of the components that need to be loaded when the application starts.
*/
public $preload = [];
/**
* @var Controller the currently active controller instance * @var Controller the currently active controller instance
*/ */
public $controller; public $controller;

9
framework/yii/base/Model.php

@ -748,16 +748,21 @@ class Model extends Component implements IteratorAggregate, ArrayAccess
/** /**
* Validates multiple models. * Validates multiple models.
* This method will validate every model. The models being validated may
* be of the same or different types.
* @param array $models the models to be validated * @param array $models the models to be validated
* @param array $attributes list of attributes that should be validated.
* If this parameter is empty, it means any attribute listed in the applicable
* validation rules should be validated.
* @return boolean whether all models are valid. False will be returned if one * @return boolean whether all models are valid. False will be returned if one
* or multiple models have validation error. * or multiple models have validation error.
*/ */
public static function validateMultiple($models) public static function validateMultiple($models, $attributes = null)
{ {
$valid = true; $valid = true;
/** @var Model $model */ /** @var Model $model */
foreach ($models as $model) { foreach ($models as $model) {
$valid = $model->validate() && $valid; $valid = $model->validate($attributes) && $valid;
} }
return $valid; return $valid;
} }

2
framework/yii/base/Module.php

@ -41,7 +41,7 @@ abstract class Module extends Component
*/ */
public $params = []; public $params = [];
/** /**
* @var array the IDs of the components or modules that should be preloaded when this module is created. * @var array the IDs of the components or modules that should be preloaded right after initialization.
*/ */
public $preload = []; public $preload = [];
/** /**

1
framework/yii/base/Theme.php

@ -8,7 +8,6 @@
namespace yii\base; namespace yii\base;
use Yii; use Yii;
use yii\base\InvalidConfigException;
use yii\helpers\FileHelper; use yii\helpers\FileHelper;
/** /**

4
framework/yii/bootstrap/Carousel.php

@ -29,8 +29,8 @@ use yii\helpers\Html;
* 'caption' => '<h4>This is title</h4><p>This is the caption text</p>', * 'caption' => '<h4>This is title</h4><p>This is the caption text</p>',
* 'options' => [...], * 'options' => [...],
* ], * ],
* ) * ]
* )); * ]);
* ``` * ```
* *
* @see http://twitter.github.io/bootstrap/javascript.html#carousel * @see http://twitter.github.io/bootstrap/javascript.html#carousel

2
framework/yii/bootstrap/Dropdown.php

@ -29,6 +29,8 @@ class Dropdown extends Widget
* - visible: boolean, optional, whether this menu item is visible. Defaults to true. * - visible: boolean, optional, whether this menu item is visible. Defaults to true.
* - linkOptions: array, optional, the HTML attributes of the item link. * - linkOptions: array, optional, the HTML attributes of the item link.
* - options: array, optional, the HTML attributes of the item. * - options: array, optional, the HTML attributes of the item.
*
* To insert divider use `<li role="presentation" class="divider"></li>`.
*/ */
public $items = []; public $items = [];
/** /**

2
framework/yii/bootstrap/Nav.php

@ -24,7 +24,7 @@ use yii\helpers\Html;
* 'label' => 'Home', * 'label' => 'Home',
* 'url' => ['site/index'], * 'url' => ['site/index'],
* 'linkOptions' => [...], * 'linkOptions' => [...],
* ), * ],
* [ * [
* 'label' => 'Dropdown', * 'label' => 'Dropdown',
* 'items' => [ * 'items' => [

6
framework/yii/bootstrap/Tabs.php

@ -85,6 +85,10 @@ class Tabs extends Widget
* @var boolean whether the labels for header items should be HTML-encoded. * @var boolean whether the labels for header items should be HTML-encoded.
*/ */
public $encodeLabels = true; public $encodeLabels = true;
/**
* @var string, specifies the Bootstrap tab styling.
*/
public $navType = 'nav-tabs';
/** /**
@ -93,7 +97,7 @@ class Tabs extends Widget
public function init() public function init()
{ {
parent::init(); parent::init();
Html::addCssClass($this->options, 'nav nav-tabs'); Html::addCssClass($this->options, 'nav ' . $this->navType);
} }
/** /**

1
framework/yii/bootstrap/Widget.php

@ -8,7 +8,6 @@
namespace yii\bootstrap; namespace yii\bootstrap;
use Yii; use Yii;
use yii\base\View;
use yii\helpers\Json; use yii\helpers\Json;
/** /**

13
framework/yii/captcha/CaptchaValidator.php

@ -18,8 +18,6 @@ use yii\validators\Validator;
* *
* CaptchaValidator should be used together with [[CaptchaAction]]. * CaptchaValidator should be used together with [[CaptchaAction]].
* *
* @property \yii\captcha\CaptchaAction $captchaAction The action object. This property is read-only.
*
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
@ -71,16 +69,16 @@ class CaptchaValidator extends Validator
*/ */
public function validateValue($value) public function validateValue($value)
{ {
$captcha = $this->getCaptchaAction(); $captcha = $this->createCaptchaAction();
return !is_array($value) && $captcha->validate($value, $this->caseSensitive); return !is_array($value) && $captcha->validate($value, $this->caseSensitive);
} }
/** /**
* Returns the CAPTCHA action object. * Creates the CAPTCHA action object from the route specified by [[captchaAction]].
* @throws InvalidConfigException
* @return \yii\captcha\CaptchaAction the action object * @return \yii\captcha\CaptchaAction the action object
* @throws InvalidConfigException
*/ */
public function getCaptchaAction() public function createCaptchaAction()
{ {
$ca = Yii::$app->createController($this->captchaAction); $ca = Yii::$app->createController($this->captchaAction);
if ($ca !== false) { if ($ca !== false) {
@ -104,7 +102,7 @@ class CaptchaValidator extends Validator
*/ */
public function clientValidateAttribute($object, $attribute, $view) public function clientValidateAttribute($object, $attribute, $view)
{ {
$captcha = $this->getCaptchaAction(); $captcha = $this->createCaptchaAction();
$code = $captcha->getVerifyCode(false); $code = $captcha->getVerifyCode(false);
$hash = $captcha->generateValidationHash($this->caseSensitive ? $code : strtolower($code)); $hash = $captcha->generateValidationHash($this->caseSensitive ? $code : strtolower($code));
$options = [ $options = [
@ -113,7 +111,6 @@ class CaptchaValidator extends Validator
'caseSensitive' => $this->caseSensitive, 'caseSensitive' => $this->caseSensitive,
'message' => Html::encode(strtr($this->message, [ 'message' => Html::encode(strtr($this->message, [
'{attribute}' => $object->getAttributeLabel($attribute), '{attribute}' => $object->getAttributeLabel($attribute),
'{value}' => $object->$attribute,
])), ])),
]; ];
if ($this->skipOnEmpty) { if ($this->skipOnEmpty) {

2
framework/yii/data/ArrayDataProvider.php

@ -33,7 +33,7 @@ use yii\helpers\ArrayHelper;
* 'allModels' => $query->from('tbl_post')->all(), * 'allModels' => $query->from('tbl_post')->all(),
* 'sort' => [ * 'sort' => [
* 'attributes' => ['id', 'username', 'email'], * 'attributes' => ['id', 'username', 'email'],
* ), * ],
* 'pagination' => [ * 'pagination' => [
* 'pageSize' => 10, * 'pageSize' => 10,
* ], * ],

18
framework/yii/db/ActiveRecord.php

@ -1125,26 +1125,20 @@ class ActiveRecord extends Model
/** /**
* Repopulates this active record with the latest data. * Repopulates this active record with the latest data.
* @param array $attributes
* @return boolean whether the row still exists in the database. If true, the latest data * @return boolean whether the row still exists in the database. If true, the latest data
* will be populated to this active record. * will be populated to this active record. Otherwise, this record will remain unchanged.
*/ */
public function refresh($attributes = null) public function refresh()
{ {
$record = $this->find($this->getPrimaryKey(true)); $record = $this->find($this->getPrimaryKey(true));
if ($record === null) { if ($record === null) {
return false; return false;
} }
if ($attributes === null) { foreach ($this->attributes() as $name) {
foreach ($this->attributes() as $name) { $this->_attributes[$name] = $record->_attributes[$name];
$this->_attributes[$name] = $record->_attributes[$name];
}
$this->_oldAttributes = $this->_attributes;
} else {
foreach ($attributes as $name) {
$this->_oldAttributes[$name] = $this->_attributes[$name] = $record->_attributes[$name];
}
} }
$this->_oldAttributes = $this->_attributes;
$this->_related = null;
return true; return true;
} }

1
framework/yii/gii/generators/crud/Generator.php

@ -8,7 +8,6 @@
namespace yii\gii\generators\crud; namespace yii\gii\generators\crud;
use Yii; use Yii;
use yii\base\Model;
use yii\db\ActiveRecord; use yii\db\ActiveRecord;
use yii\db\Schema; use yii\db\Schema;
use yii\gii\CodeFile; use yii\gii\CodeFile;

2
framework/yii/gii/generators/form/templates/action.php

@ -14,7 +14,7 @@ echo "<?php\n";
public function action<?= Inflector::id2camel(trim(basename($generator->viewName), '_')) ?>() public function action<?= Inflector::id2camel(trim(basename($generator->viewName), '_')) ?>()
{ {
$model = new <?= $generator->modelClass ?><?= empty($generator->scenarioName) ? '' : "(['scenario' => '{$generator->scenarioName}'])" ?>; $model = new <?= $generator->modelClass ?><?= empty($generator->scenarioName) ? "" : "(['scenario' => '{$generator->scenarioName}'])" ?>;
if ($model->load($_POST)) { if ($model->load($_POST)) {
if($model->validate()) { if($model->validate()) {

8
framework/yii/gii/generators/form/templates/form.php

@ -21,15 +21,15 @@ use yii\widgets\ActiveForm;
<div class="<?= str_replace('/', '-', trim($generator->viewName, '_')) ?>"> <div class="<?= str_replace('/', '-', trim($generator->viewName, '_')) ?>">
<?= '<?php' ?> $form = ActiveForm::begin(); ?> <?= "<?php " ?>$form = ActiveForm::begin(); ?>
<?php foreach ($generator->getModelAttributes() as $attribute): ?> <?php foreach ($generator->getModelAttributes() as $attribute): ?>
<?= '<?php' ?> echo $form->field($model, '<?= $attribute ?>'); ?> <?= "<?= " ?>$form->field($model, '<?= $attribute ?>') ?>
<?php endforeach; ?> <?php endforeach; ?>
<div class="form-group"> <div class="form-group">
<?= '<?php' ?> echo Html::submitButton('Submit', ['class' => 'btn btn-primary']); ?> <?= "<?= " ?>Html::submitButton('Submit', ['class' => 'btn btn-primary']) ?>
</div> </div>
<?= '<?php' ?> ActiveForm::end(); ?> <?= "<?php " ?>ActiveForm::end(); ?>
</div><!-- <?= str_replace('/', '-', trim($generator->viewName, '-')) ?> --> </div><!-- <?= str_replace('/', '-', trim($generator->viewName, '-')) ?> -->

8
framework/yii/gii/generators/model/Generator.php

@ -265,7 +265,7 @@ class Generator extends \yii\gii\Generator
$link = $this->generateRelationLink(array_flip($refs)); $link = $this->generateRelationLink(array_flip($refs));
$relationName = $this->generateRelationName($relations, $className, $table, $fks[0], false); $relationName = $this->generateRelationName($relations, $className, $table, $fks[0], false);
$relations[$className][$relationName] = [ $relations[$className][$relationName] = [
"return \$this->hasOne('$refClassName', $link);", "return \$this->hasOne($refClassName::className(), $link);",
$refClassName, $refClassName,
false, false,
]; ];
@ -281,7 +281,7 @@ class Generator extends \yii\gii\Generator
$link = $this->generateRelationLink($refs); $link = $this->generateRelationLink($refs);
$relationName = $this->generateRelationName($relations, $refClassName, $refTable, $className, $hasMany); $relationName = $this->generateRelationName($relations, $refClassName, $refTable, $className, $hasMany);
$relations[$refClassName][$relationName] = [ $relations[$refClassName][$relationName] = [
"return \$this->" . ($hasMany ? 'hasMany' : 'hasOne') . "('$className', $link);", "return \$this->" . ($hasMany ? 'hasMany' : 'hasOne') . "($refClassName::className(), $link);",
$className, $className,
$hasMany, $hasMany,
]; ];
@ -299,7 +299,7 @@ class Generator extends \yii\gii\Generator
$viaLink = $this->generateRelationLink([$table->primaryKey[0] => $fks[$table->primaryKey[0]][1]]); $viaLink = $this->generateRelationLink([$table->primaryKey[0] => $fks[$table->primaryKey[0]][1]]);
$relationName = $this->generateRelationName($relations, $className0, $db->getTableSchema($table0), $table->primaryKey[1], true); $relationName = $this->generateRelationName($relations, $className0, $db->getTableSchema($table0), $table->primaryKey[1], true);
$relations[$className0][$relationName] = [ $relations[$className0][$relationName] = [
"return \$this->hasMany('$className1', $link)->viaTable('{$table->name}', $viaLink);", "return \$this->hasMany($className1::className(), $link)->viaTable('{$table->name}', $viaLink);",
$className0, $className0,
true, true,
]; ];
@ -308,7 +308,7 @@ class Generator extends \yii\gii\Generator
$viaLink = $this->generateRelationLink([$table->primaryKey[1] => $fks[$table->primaryKey[1]][1]]); $viaLink = $this->generateRelationLink([$table->primaryKey[1] => $fks[$table->primaryKey[1]][1]]);
$relationName = $this->generateRelationName($relations, $className1, $db->getTableSchema($table1), $table->primaryKey[0], true); $relationName = $this->generateRelationName($relations, $className1, $db->getTableSchema($table1), $table->primaryKey[0], true);
$relations[$className1][$relationName] = [ $relations[$className1][$relationName] = [
"return \$this->hasMany('$className0', $link)->viaTable('{$table->name}', $viaLink);", "return \$this->hasMany($className0::className(), $link)->viaTable('{$table->name}', $viaLink);",
$className1, $className1,
true, true,
]; ];

10
framework/yii/gii/generators/module/templates/view.php

@ -5,14 +5,14 @@
*/ */
?> ?>
<div class="<?= $generator->moduleID . '-default-index' ?>"> <div class="<?= $generator->moduleID . '-default-index' ?>">
<h1><?= "<?php" ?> echo $this->context->action->uniqueId; ?></h1> <h1><?= "<?= " ?>$this->context->action->uniqueId ?></h1>
<p> <p>
This is the view content for action "<?= "<?php" ?> echo $this->context->action->id; ?>". This is the view content for action "<?= "<?= " ?>$this->context->action->id ?>".
The action belongs to the controller "<?= "<?php" ?> echo get_class($this->context); ?>" The action belongs to the controller "<?= "<?= " ?>get_class($this->context) ?>"
in the "<?= "<?php" ?> echo $this->context->module->id; ?>" module. in the "<?= "<?= " ?>$this->context->module->id ?>" module.
</p> </p>
<p> <p>
You may customize this page by editing the following file:<br> You may customize this page by editing the following file:<br>
<code><?= "<?php" ?> echo __FILE__; ?></code> <code><?= "<?= " ?>__FILE__ ?></code>
</p> </p>
</div> </div>

1
framework/yii/gii/views/default/view.php

@ -1,6 +1,5 @@
<?php <?php
use yii\gii\Generator;
use yii\helpers\Html; use yii\helpers\Html;
use yii\widgets\ActiveForm; use yii\widgets\ActiveForm;
use yii\gii\components\ActiveField; use yii\gii\components\ActiveField;

1
framework/yii/gii/views/default/view/files.php

@ -1,6 +1,5 @@
<?php <?php
use yii\gii\Generator;
use yii\helpers\Html; use yii\helpers\Html;
use yii\gii\CodeFile; use yii\gii\CodeFile;

4
framework/yii/gii/views/default/view/results.php

@ -1,8 +1,4 @@
<?php <?php
use yii\gii\Generator;
use yii\gii\CodeFile;
/** /**
* @var yii\base\View $this * @var yii\base\View $this
* @var yii\gii\Generator $generator * @var yii\gii\Generator $generator

2
framework/yii/grid/ActionColumn.php

@ -10,8 +10,6 @@ namespace yii\grid;
use Yii; use Yii;
use Closure; use Closure;
use yii\helpers\Html; use yii\helpers\Html;
use yii\helpers\Inflector;
use yii\helpers\StringHelper;
/** /**
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>

8
framework/yii/grid/DataColumn.php

@ -41,10 +41,10 @@ class DataColumn extends Column
*/ */
public $value; public $value;
/** /**
* @var string in which format should the value of each data model be displayed as (e.g. "text", "html"). * @var string|array in which format should the value of each data model be displayed as (e.g. "text", "html",
* Supported formats are determined by the [[GridView::formatter|formatter]] used by the [[GridView]]. * ['date', 'Y-m-d']). Supported formats are determined by the [[GridView::formatter|formatter]] used by
* Default format is "text" which will format the value as an HTML-encoded plain text when * the [[GridView]]. Default format is "text" which will format the value as an HTML-encoded plain text when
* [[\yii\base\Formatter]] or [[\yii\i18n\Formatter]] is used. * [[\yii\base\Formatter::format()]] or [[\yii\i18n\Formatter::format()]] is used.
*/ */
public $format = 'text'; public $format = 'text';
/** /**

2
framework/yii/grid/GridView.php

@ -11,8 +11,6 @@ use Yii;
use Closure; use Closure;
use yii\base\Formatter; use yii\base\Formatter;
use yii\base\InvalidConfigException; use yii\base\InvalidConfigException;
use yii\base\Widget;
use yii\db\ActiveRecord;
use yii\helpers\Html; use yii\helpers\Html;
use yii\helpers\Json; use yii\helpers\Json;
use yii\widgets\BaseListView; use yii\widgets\BaseListView;

14
framework/yii/helpers/BaseArrayHelper.php

@ -336,7 +336,7 @@ class BaseArrayHelper
* @param boolean|array $descending whether to sort in descending or ascending order. When * @param boolean|array $descending whether to sort in descending or ascending order. When
* sorting by multiple keys with different descending orders, use an array of descending flags. * sorting by multiple keys with different descending orders, use an array of descending flags.
* @param integer|array $sortFlag the PHP sort flag. Valid values include * @param integer|array $sortFlag the PHP sort flag. Valid values include
* `SORT_REGULAR`, `SORT_NUMERIC`, `SORT_STRING` and `SORT_LOCALE_STRING`. * `SORT_REGULAR`, `SORT_NUMERIC`, `SORT_STRING`, `SORT_LOCALE_STRING`, `SORT_NATURAL` and `SORT_FLAG_CASE`.
* Please refer to [PHP manual](http://php.net/manual/en/function.sort.php) * Please refer to [PHP manual](http://php.net/manual/en/function.sort.php)
* for more details. When sorting by multiple keys with different sort flags, use an array of sort flags. * for more details. When sorting by multiple keys with different sort flags, use an array of sort flags.
* @param boolean|array $caseSensitive whether to sort string in case-sensitive manner. This parameter * @param boolean|array $caseSensitive whether to sort string in case-sensitive manner. This parameter
@ -372,16 +372,8 @@ class BaseArrayHelper
$flag = $sortFlag[$i]; $flag = $sortFlag[$i];
$cs = $caseSensitive[$i]; $cs = $caseSensitive[$i];
if (!$cs && ($flag === SORT_STRING)) { if (!$cs && ($flag === SORT_STRING)) {
if (defined('SORT_FLAG_CASE')) { $flag = $flag | SORT_FLAG_CASE;
$flag = $flag | SORT_FLAG_CASE; $args[] = static::getColumn($array, $key);
$args[] = static::getColumn($array, $key);
} else {
$column = [];
foreach (static::getColumn($array, $key) as $k => $value) {
$column[$k] = mb_strtolower($value);
}
$args[] = $column;
}
} else { } else {
$args[] = static::getColumn($array, $key); $args[] = static::getColumn($array, $key);
} }

306
framework/yii/i18n/FallbackMessageFormatter.php

@ -0,0 +1,306 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\i18n;
use yii\base\NotSupportedException;
/**
* FallbackMessageFormatter is a fallback implementation for the PHP intl MessageFormatter that is
* used in case PHP intl extension is not installed.
*
* Do not use this class directly. Use [[MessageFormatter]] instead, which will automatically detect
* installed version of PHP intl and use the fallback if it is not installed.
*
* It is highly recommended that you install [PHP intl extension](http://php.net/manual/en/book.intl.php) if you want to use
* MessageFormatter features.
*
* This implementation only supports to following message formats:
* - plural formatting for english
* - select format
* - simple parameters
*
* The pattern also does NOT support the ['apostrophe-friendly' syntax](http://www.php.net/manual/en/messageformatter.formatmessage.php).
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
class FallbackMessageFormatter
{
private $_locale;
private $_pattern;
private $_errorMessage = '';
private $_errorCode = 0;
/**
* Constructs a new Message Formatter
* @link http://php.net/manual/en/messageformatter.create.php
* @param string $locale The locale to use when formatting arguments
* @param string $pattern The pattern string to stick arguments into.
*/
public function __construct($locale, $pattern)
{
$this->_locale = $locale;
$this->_pattern = $pattern;
}
/**
* Constructs a new Message Formatter
* @link http://php.net/manual/en/messageformatter.create.php
* @param string $locale The locale to use when formatting arguments
* @param string $pattern The pattern string to stick arguments into.
* @return MessageFormatter The formatter object
*/
public static function create($locale, $pattern)
{
return new static($locale, $pattern);
}
/**
* Format the message
* @link http://php.net/manual/en/messageformatter.format.php
* @param array $args Arguments to insert into the format string
* @return string The formatted string, or `FALSE` if an error occurred
*/
public function format(array $args)
{
return static::formatMessage($this->_locale, $this->_pattern, $args);
}
/**
* Quick format message
* @link http://php.net/manual/en/messageformatter.formatmessage.php
* @param string $locale The locale to use for formatting locale-dependent parts
* @param string $pattern The pattern string to insert things into.
* @param array $args The array of values to insert into the format string
* @return string The formatted pattern string or `FALSE` if an error occurred
*/
public static function formatMessage($locale, $pattern, array $args)
{
if (($tokens = static::tokenizePattern($pattern)) === false) {
return false;
}
foreach($tokens as $i => $token) {
if (is_array($token)) {
if (($tokens[$i] = static::parseToken($token, $args, $locale)) === false) {
return false;
}
}
}
return implode('', $tokens);
}
/**
* Tokenizes a pattern by separating normal text from replaceable patterns
* @param string $pattern patter to tokenize
* @return array|bool array of tokens or false on failure
*/
private static function tokenizePattern($pattern)
{
$depth = 1;
if (($start = $pos = mb_strpos($pattern, '{')) === false) {
return [$pattern];
}
$tokens = [mb_substr($pattern, 0, $pos)];
while(true) {
$open = mb_strpos($pattern, '{', $pos + 1);
$close = mb_strpos($pattern, '}', $pos + 1);
if ($open === false && $close === false) {
break;
}
if ($open === false) {
$open = mb_strlen($pattern);
}
if ($close > $open) {
$depth++;
$pos = $open;
} else {
$depth--;
$pos = $close;
}
if ($depth == 0) {
$tokens[] = explode(',', mb_substr($pattern, $start + 1, $pos - $start - 1), 3);
$start = $pos + 1;
$tokens[] = mb_substr($pattern, $start, $open - $start);
$start = $open;
}
}
if ($depth != 0) {
return false;
}
return $tokens;
}
/**
* Parses a token
* @param array $token the token to parse
* @param array $args arguments to replace
* @param string $locale the locale
* @return bool|string parsed token or false on failure
* @throws \yii\base\NotSupportedException when unsupported formatting is used.
*/
private static function parseToken($token, $args, $locale)
{
$param = trim($token[0]);
if (isset($args[$param])) {
$arg = $args[$param];
} else {
return '{' . implode(',', $token) . '}';
}
$type = isset($token[1]) ? trim($token[1]) : 'none';
switch($type)
{
case 'number':
case 'date':
case 'time':
case 'spellout':
case 'ordinal':
case 'duration':
case 'choice':
case 'selectordinal':
throw new NotSupportedException("Message format '$type' is not supported. You have to install PHP intl extension to use this feature.");
case 'none': return $arg;
case 'select':
/* http://icu-project.org/apiref/icu4c/classicu_1_1SelectFormat.html
selectStyle = (selector '{' message '}')+
*/
$select = static::tokenizePattern($token[2]);
$c = count($select);
$message = false;
for($i = 0; $i + 1 < $c; $i++) {
if (is_array($select[$i]) || !is_array($select[$i + 1])) {
return false;
}
$selector = trim($select[$i++]);
if ($message === false && $selector == 'other' || $selector == $arg) {
$message = implode(',', $select[$i]);
}
}
if ($message !== false) {
return static::formatMessage($locale, $message, $args);
}
break;
case 'plural':
/* http://icu-project.org/apiref/icu4c/classicu_1_1PluralFormat.html
pluralStyle = [offsetValue] (selector '{' message '}')+
offsetValue = "offset:" number
selector = explicitValue | keyword
explicitValue = '=' number // adjacent, no white space in between
keyword = [^[[:Pattern_Syntax:][:Pattern_White_Space:]]]+
message: see MessageFormat
*/
$plural = static::tokenizePattern($token[2]);
$c = count($plural);
$message = false;
$offset = 0;
for($i = 0; $i + 1 < $c; $i++) {
if (is_array($plural[$i]) || !is_array($plural[$i + 1])) {
return false;
}
$selector = trim($plural[$i++]);
if ($i == 1 && substr($selector, 0, 7) == 'offset:') {
$offset = (int) trim(mb_substr($selector, 7, ($pos = mb_strpos(str_replace(["\n", "\r", "\t"], ' ', $selector), ' ', 7)) - 7));
$selector = trim(mb_substr($selector, $pos + 1));
}
if ($message === false && $selector == 'other' ||
$selector[0] == '=' && (int) mb_substr($selector, 1) == $arg ||
$selector == 'zero' && $arg - $offset == 0 ||
$selector == 'one' && $arg - $offset == 1 ||
$selector == 'two' && $arg - $offset == 2
) {
$message = implode(',', str_replace('#', $arg - $offset, $plural[$i]));
}
}
if ($message !== false) {
return static::formatMessage($locale, $message, $args);
}
break;
}
return false;
}
/**
* Parse input string according to pattern
* @link http://php.net/manual/en/messageformatter.parse.php
* @param string $value The string to parse
* @return array An array containing the items extracted, or `FALSE` on error
*/
public function parse($value)
{
throw new NotSupportedException('You have to install PHP intl extension to use this feature.');
}
/**
* Quick parse input string
* @link http://php.net/manual/en/messageformatter.parsemessage.php
* @param string $locale The locale to use for parsing locale-dependent parts
* @param string $pattern The pattern with which to parse the `value`.
* @param string $source The string to parse, conforming to the `pattern`.
* @return array An array containing items extracted, or `FALSE` on error
*/
public static function parseMessage($locale, $pattern, $source)
{
throw new NotSupportedException('You have to install PHP intl extension to use this feature.');
}
/**
* Set the pattern used by the formatter
* @link http://php.net/manual/en/messageformatter.setpattern.php
* @param string $pattern The pattern string to use in this message formatter.
* @return bool `TRUE` on success or `FALSE` on failure.
*/
public function setPattern($pattern)
{
$this->_pattern = $pattern;
return true;
}
/**
* Get the pattern used by the formatter
* @link http://php.net/manual/en/messageformatter.getpattern.php
* @return string The pattern string for this message formatter
*/
public function getPattern()
{
return $this->_pattern;
}
/**
* Get the locale for which the formatter was created.
* @link http://php.net/manual/en/messageformatter.getlocale.php
* @return string The locale name
*/
public function getLocale()
{
return $this->_locale;
}
/**
* Get the error code from last operation
* @link http://php.net/manual/en/messageformatter.geterrorcode.php
* @return int The error code, one of UErrorCode values. Initial value is U_ZERO_ERROR.
*/
public function getErrorCode()
{
return $this->_errorCode;
}
/**
* Get the error text from the last operation
* @link http://php.net/manual/en/messageformatter.geterrormessage.php
* @return string Description of the last error.
*/
public function getErrorMessage()
{
return $this->_errorMessage;
}
}
if (!class_exists('MessageFormatter', false)) {
class_alias('yii\\i18n\\FallbackMessageFormatter', 'MessageFormatter');
define('YII_INTL_MESSAGE_FALLBACK', true);
}

22
framework/yii/i18n/I18N.php

@ -10,7 +10,6 @@ namespace yii\i18n;
use Yii; use Yii;
use yii\base\Component; use yii\base\Component;
use yii\base\InvalidConfigException; use yii\base\InvalidConfigException;
use yii\log\Logger;
/** /**
* I18N provides features related with internationalization (I18N) and localization (L10N). * I18N provides features related with internationalization (I18N) and localization (L10N).
@ -63,6 +62,9 @@ class I18N extends Component
/** /**
* Translates a message to the specified language. * Translates a message to the specified language.
* *
* After translation the message will be formatted using [[MessageFormatter]] if it contains
* ICU message format and `$params` are not empty.
*
* @param string $category the message category. * @param string $category the message category.
* @param string $message the message to be translated. * @param string $message the message to be translated.
* @param array $params the parameters that will be used to replace the corresponding placeholders in the message. * @param array $params the parameters that will be used to replace the corresponding placeholders in the message.
@ -72,22 +74,34 @@ class I18N extends Component
public function translate($category, $message, $params, $language) public function translate($category, $message, $params, $language)
{ {
$message = $this->getMessageSource($category)->translate($category, $message, $language); $message = $this->getMessageSource($category)->translate($category, $message, $language);
return $this->format($message, $params, $language);
}
/**
* Formats a message using using [[MessageFormatter]].
*
* @param string $message the message to be formatted.
* @param array $params the parameters that will be used to replace the corresponding placeholders in the message.
* @param string $language the language code (e.g. `en_US`, `en`).
* @return string the formatted message.
*/
public function format($message, $params, $language)
{
$params = (array)$params; $params = (array)$params;
if ($params === []) { if ($params === []) {
return $message; return $message;
} }
if (class_exists('MessageFormatter', false) && preg_match('~{\s*[\d\w]+\s*,~u', $message)) { if (preg_match('~{\s*[\d\w]+\s*,~u', $message)) {
$formatter = new MessageFormatter($language, $message); $formatter = new MessageFormatter($language, $message);
if ($formatter === null) { if ($formatter === null) {
Yii::warning("$language message from category $category is invalid. Message is: $message."); Yii::warning("Unable to format message in language '$language': $message.");
return $message; return $message;
} }
$result = $formatter->format($params); $result = $formatter->format($params);
if ($result === false) { if ($result === false) {
$errorMessage = $formatter->getErrorMessage(); $errorMessage = $formatter->getErrorMessage();
Yii::warning("$language message from category $category failed with error: $errorMessage. Message is: $message."); Yii::warning("Formatting message for language '$language' failed with error: $errorMessage. The message being formatted was: $message.");
return $message; return $message;
} else { } else {
return $result; return $result;

16
framework/yii/i18n/MessageFormatter.php

@ -7,13 +7,23 @@
namespace yii\i18n; namespace yii\i18n;
if (!class_exists('MessageFormatter', false)) {
require_once(__DIR__ . '/FallbackMessageFormatter.php');
}
defined('YII_INTL_MESSAGE_FALLBACK') || define('YII_INTL_MESSAGE_FALLBACK', false);
/** /**
* MessageFormatter is an enhanced version of PHP intl class that no matter which PHP and ICU versions are used: * MessageFormatter enhances the message formatter class provided by PHP intl extension.
*
* The following enhancements are provided:
* *
* - Accepts named arguments and mixed numeric and named arguments. * - Accepts named arguments and mixed numeric and named arguments.
* - Issues no error when an insufficient number of arguments have been provided. Instead, the placeholders will not be * - Issues no error when an insufficient number of arguments have been provided. Instead, the placeholders will not be
* substituted. * substituted.
* - Fixes PHP 5.5 weird placeholder replacement in case no arguments are provided at all (https://bugs.php.net/bug.php?id=65920). * - Fixes PHP 5.5 weird placeholder replacement in case no arguments are provided at all (https://bugs.php.net/bug.php?id=65920).
* - Offers limited support for message formatting in case PHP intl extension is not installed.
* However it is highly recommended that you install [PHP intl extension](http://php.net/manual/en/book.intl.php) if you want
* to use MessageFormatter features.
* *
* @author Alexander Makarov <sam@rmcreative.ru> * @author Alexander Makarov <sam@rmcreative.ru>
* @author Carsten Brandt <mail@cebe.cc> * @author Carsten Brandt <mail@cebe.cc>
@ -34,7 +44,7 @@ class MessageFormatter extends \MessageFormatter
return $this->getPattern(); return $this->getPattern();
} }
if (version_compare(PHP_VERSION, '5.5.0', '<')) { if (version_compare(PHP_VERSION, '5.5.0', '<') && !YII_INTL_MESSAGE_FALLBACK) {
$pattern = self::replaceNamedArguments($this->getPattern(), $args); $pattern = self::replaceNamedArguments($this->getPattern(), $args);
$this->setPattern($pattern); $this->setPattern($pattern);
$args = array_values($args); $args = array_values($args);
@ -57,7 +67,7 @@ class MessageFormatter extends \MessageFormatter
return $pattern; return $pattern;
} }
if (version_compare(PHP_VERSION, '5.5.0', '<')) { if (version_compare(PHP_VERSION, '5.5.0', '<') && !YII_INTL_MESSAGE_FALLBACK) {
$pattern = self::replaceNamedArguments($pattern, $args); $pattern = self::replaceNamedArguments($pattern, $args);
$args = array_values($args); $args = array_values($args);
} }

2
framework/yii/log/Logger.php

@ -39,7 +39,7 @@ use yii\base\InvalidConfigException;
* 'class' => 'yii\log\FileTarget', * 'class' => 'yii\log\FileTarget',
* 'levels' => ['trace', 'info'], * 'levels' => ['trace', 'info'],
* 'categories' => ['yii\*'], * 'categories' => ['yii\*'],
* ), * ],
* 'email' => [ * 'email' => [
* 'class' => 'yii\log\EmailTarget', * 'class' => 'yii\log\EmailTarget',
* 'levels' => ['error', 'warning'], * 'levels' => ['error', 'warning'],

42
framework/yii/requirements/YiiRequirementChecker.php

@ -19,15 +19,15 @@ if (version_compare(PHP_VERSION, '4.3', '<')) {
* ~~~php * ~~~php
* require_once('path/to/YiiRequirementChecker.php'); * require_once('path/to/YiiRequirementChecker.php');
* $requirementsChecker = new YiiRequirementChecker(); * $requirementsChecker = new YiiRequirementChecker();
* $requirements = [ * $requirements = array(
* [ * array(
* 'name' => 'PHP Some Extension', * 'name' => 'PHP Some Extension',
* 'mandatory' => true, * 'mandatory' => true,
* 'condition' => extension_loaded('some_extension'), * 'condition' => extension_loaded('some_extension'),
* 'by' => 'Some application feature', * 'by' => 'Some application feature',
* 'memo' => 'PHP extension "some_extension" required', * 'memo' => 'PHP extension "some_extension" required',
* ], * ),
* ]; * );
* $requirementsChecker->checkYii()->check($requirements)->render(); * $requirementsChecker->checkYii()->check($requirements)->render();
* ~~~ * ~~~
* *
@ -38,12 +38,12 @@ if (version_compare(PHP_VERSION, '4.3', '<')) {
* For example: * For example:
* *
* ~~~ * ~~~
* $requirements = [ * $requirements = array(
* [ * array(
* 'name' => 'Upload max file size', * 'name' => 'Upload max file size',
* 'condition' => 'eval:$this->checkUploadMaxFileSize("5M")', * 'condition' => 'eval:$this->checkUploadMaxFileSize("5M")',
* ], * ),
* ]; * );
* ~~~ * ~~~
* *
* Note: this class definition does not match ordinary Yii style, because it should match PHP 4.3 * Note: this class definition does not match ordinary Yii style, because it should match PHP 4.3
@ -74,14 +74,14 @@ class YiiRequirementChecker
$this->usageError('Requirements must be an array, "' . gettype($requirements) . '" has been given!'); $this->usageError('Requirements must be an array, "' . gettype($requirements) . '" has been given!');
} }
if (!isset($this->result) || !is_array($this->result)) { if (!isset($this->result) || !is_array($this->result)) {
$this->result = [ $this->result = array(
'summary' => [ 'summary' => array(
'total' => 0, 'total' => 0,
'errors' => 0, 'errors' => 0,
'warnings' => 0, 'warnings' => 0,
], ),
'requirements' => [], 'requirements' => array(),
]; );
} }
foreach ($requirements as $key => $rawRequirement) { foreach ($requirements as $key => $rawRequirement) {
$requirement = $this->normalizeRequirement($rawRequirement, $key); $requirement = $this->normalizeRequirement($rawRequirement, $key);
@ -118,21 +118,21 @@ class YiiRequirementChecker
* Return the check results. * Return the check results.
* @return array|null check results in format: * @return array|null check results in format:
* <code> * <code>
* [ * array(
* 'summary' => [ * 'summary' => array(
* 'total' => total number of checks, * 'total' => total number of checks,
* 'errors' => number of errors, * 'errors' => number of errors,
* 'warnings' => number of warnings, * 'warnings' => number of warnings,
* ], * ),
* 'requirements' => [ * 'requirements' => array(
* [ * array(
* ... * ...
* 'error' => is there an error, * 'error' => is there an error,
* 'warning' => is there a warning, * 'warning' => is there a warning,
* ], * ),
* ... * ...
* ], * ),
* ] * )
* </code> * </code>
*/ */
function getResult() function getResult()

28
framework/yii/requirements/requirements.php

@ -5,40 +5,40 @@
* *
* @var $this YiiRequirementChecker * @var $this YiiRequirementChecker
*/ */
return [ return array(
[ array(
'name' => 'PHP version', 'name' => 'PHP version',
'mandatory' => true, 'mandatory' => true,
'condition' => version_compare(PHP_VERSION, '5.4.0', '>='), 'condition' => version_compare(PHP_VERSION, '5.4.0', '>='),
'by' => '<a href="http://www.yiiframework.com">Yii Framework</a>', 'by' => '<a href="http://www.yiiframework.com">Yii Framework</a>',
'memo' => 'PHP 5.4.0 or higher is required.', 'memo' => 'PHP 5.4.0 or higher is required.',
], ),
[ array(
'name' => 'Reflection extension', 'name' => 'Reflection extension',
'mandatory' => true, 'mandatory' => true,
'condition' => class_exists('Reflection', false), 'condition' => class_exists('Reflection', false),
'by' => '<a href="http://www.yiiframework.com">Yii Framework</a>', 'by' => '<a href="http://www.yiiframework.com">Yii Framework</a>',
], ),
[ array(
'name' => 'PCRE extension', 'name' => 'PCRE extension',
'mandatory' => true, 'mandatory' => true,
'condition' => extension_loaded('pcre'), 'condition' => extension_loaded('pcre'),
'by' => '<a href="http://www.yiiframework.com">Yii Framework</a>', 'by' => '<a href="http://www.yiiframework.com">Yii Framework</a>',
], ),
[ array(
'name' => 'SPL extension', 'name' => 'SPL extension',
'mandatory' => true, 'mandatory' => true,
'condition' => extension_loaded('SPL'), 'condition' => extension_loaded('SPL'),
'by' => '<a href="http://www.yiiframework.com">Yii Framework</a>', 'by' => '<a href="http://www.yiiframework.com">Yii Framework</a>',
], ),
[ array(
'name' => 'MBString extension', 'name' => 'MBString extension',
'mandatory' => true, 'mandatory' => true,
'condition' => extension_loaded('mbstring'), 'condition' => extension_loaded('mbstring'),
'by' => '<a href="http://www.php.net/manual/en/book.mbstring.php">Multibyte string</a> processing', 'by' => '<a href="http://www.php.net/manual/en/book.mbstring.php">Multibyte string</a> processing',
'memo' => 'Required for multibyte encoding string processing.' 'memo' => 'Required for multibyte encoding string processing.'
], ),
[ array(
'name' => 'Intl extension', 'name' => 'Intl extension',
'mandatory' => false, 'mandatory' => false,
'condition' => $this->checkPhpExtensionVersion('intl', '1.0.2', '>='), 'condition' => $this->checkPhpExtensionVersion('intl', '1.0.2', '>='),
@ -46,5 +46,5 @@ return [
'memo' => 'PHP Intl extension 1.0.2 or higher is required when you want to use advanced parameters formatting 'memo' => 'PHP Intl extension 1.0.2 or higher is required when you want to use advanced parameters formatting
in <code>\Yii::t()</code>, <abbr title="Internationalized domain names">IDN</abbr>-feature of in <code>\Yii::t()</code>, <abbr title="Internationalized domain names">IDN</abbr>-feature of
<code>EmailValidator</code> or <code>UrlValidator</code> or the <code>yii\i18n\Formatter</code> class.' <code>EmailValidator</code> or <code>UrlValidator</code> or the <code>yii\i18n\Formatter</code> class.'
], ),
]; );

12
framework/yii/requirements/views/web/index.php

@ -52,18 +52,18 @@
<table class="table table-bordered"> <table class="table table-bordered">
<tr><th>Name</th><th>Result</th><th>Required By</th><th>Memo</th></tr> <tr><th>Name</th><th>Result</th><th>Required By</th><th>Memo</th></tr>
<?php foreach($requirements as $requirement): ?> <?php foreach($requirements as $requirement): ?>
<tr class="<?= $requirement['condition'] ? 'success' : ($requirement['mandatory'] ? 'error' : 'warning') ?>"> <tr class="<?php echo $requirement['condition'] ? 'success' : ($requirement['mandatory'] ? 'error' : 'warning') ?>">
<td> <td>
<?= $requirement['name'] ?> <?php echo $requirement['name'] ?>
</td> </td>
<td> <td>
<span class="result"><?= $requirement['condition'] ? 'Passed' : ($requirement['mandatory'] ? 'Failed' : 'Warning') ?></span> <span class="result"><?php echo $requirement['condition'] ? 'Passed' : ($requirement['mandatory'] ? 'Failed' : 'Warning') ?></span>
</td> </td>
<td> <td>
<?= $requirement['by'] ?> <?php echo $requirement['by'] ?>
</td> </td>
<td> <td>
<?= $requirement['memo'] ?> <?php echo $requirement['memo'] ?>
</td> </td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
@ -74,7 +74,7 @@
<hr> <hr>
<div class="footer"> <div class="footer">
<p>Server: <?= $this->getServerInfo() . ' ' . $this->getNowDate() ?></p> <p>Server: <?php echo $this->getServerInfo() . ' ' . $this->getNowDate() ?></p>
<p>Powered by <a href="http://www.yiiframework.com/" rel="external">Yii Framework</a></p> <p>Powered by <a href="http://www.yiiframework.com/" rel="external">Yii Framework</a></p>
</div> </div>
</div> </div>

4
framework/yii/validators/BooleanValidator.php

@ -58,8 +58,8 @@ class BooleanValidator extends Validator
$value = $object->$attribute; $value = $object->$attribute;
if (!$this->validateValue($value)) { if (!$this->validateValue($value)) {
$this->addError($object, $attribute, $this->message, [ $this->addError($object, $attribute, $this->message, [
'{true}' => $this->trueValue, 'true' => $this->trueValue,
'{false}' => $this->falseValue, 'false' => $this->falseValue,
]); ]);
} }
} }

4
framework/yii/validators/CompareValidator.php

@ -143,8 +143,8 @@ class CompareValidator extends Validator
} }
if (!$valid) { if (!$valid) {
$this->addError($object, $attribute, $this->message, [ $this->addError($object, $attribute, $this->message, [
'{compareAttribute}' => $compareLabel, 'compareAttribute' => $compareLabel,
'{compareValue}' => $compareValue, 'compareValue' => $compareValue,
]); ]);
} }
} }

4
framework/yii/validators/DateValidator.php

@ -70,6 +70,8 @@ class DateValidator extends Validator
*/ */
public function validateValue($value) public function validateValue($value)
{ {
return DateTime::createFromFormat($this->format, $value) !== false; DateTime::createFromFormat($this->format, $value);
$errors = DateTime::getLastErrors();
return $errors['error_count'] === 0 && $errors['warning_count'] === 0;
} }
} }

10
framework/yii/validators/FileValidator.php

@ -144,7 +144,7 @@ class FileValidator extends Validator
$this->addError($object, $attribute, $this->uploadRequired); $this->addError($object, $attribute, $this->uploadRequired);
} }
if (count($files) > $this->maxFiles) { if (count($files) > $this->maxFiles) {
$this->addError($object, $attribute, $this->tooMany, ['{attribute}' => $attribute, '{limit}' => $this->maxFiles]); $this->addError($object, $attribute, $this->tooMany, ['limit' => $this->maxFiles]);
} else { } else {
foreach ($files as $file) { foreach ($files as $file) {
$this->validateFile($object, $attribute, $file); $this->validateFile($object, $attribute, $file);
@ -171,18 +171,18 @@ class FileValidator extends Validator
switch ($file->error) { switch ($file->error) {
case UPLOAD_ERR_OK: case UPLOAD_ERR_OK:
if ($this->maxSize !== null && $file->size > $this->maxSize) { if ($this->maxSize !== null && $file->size > $this->maxSize) {
$this->addError($object, $attribute, $this->tooBig, ['{file}' => $file->name, '{limit}' => $this->getSizeLimit()]); $this->addError($object, $attribute, $this->tooBig, ['file' => $file->name, 'limit' => $this->getSizeLimit()]);
} }
if ($this->minSize !== null && $file->size < $this->minSize) { if ($this->minSize !== null && $file->size < $this->minSize) {
$this->addError($object, $attribute, $this->tooSmall, ['{file}' => $file->name, '{limit}' => $this->minSize]); $this->addError($object, $attribute, $this->tooSmall, ['file' => $file->name, 'limit' => $this->minSize]);
} }
if (!empty($this->types) && !in_array(strtolower(pathinfo($file->name, PATHINFO_EXTENSION)), $this->types, true)) { if (!empty($this->types) && !in_array(strtolower(pathinfo($file->name, PATHINFO_EXTENSION)), $this->types, true)) {
$this->addError($object, $attribute, $this->wrongType, ['{file}' => $file->name, '{extensions}' => implode(', ', $this->types)]); $this->addError($object, $attribute, $this->wrongType, ['file' => $file->name, 'extensions' => implode(', ', $this->types)]);
} }
break; break;
case UPLOAD_ERR_INI_SIZE: case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE: case UPLOAD_ERR_FORM_SIZE:
$this->addError($object, $attribute, $this->tooBig, ['{file}' => $file->name, '{limit}' => $this->getSizeLimit()]); $this->addError($object, $attribute, $this->tooBig, ['file' => $file->name, 'limit' => $this->getSizeLimit()]);
break; break;
case UPLOAD_ERR_PARTIAL: case UPLOAD_ERR_PARTIAL:
$this->addError($object, $attribute, $this->message); $this->addError($object, $attribute, $this->message);

4
framework/yii/validators/NumberValidator.php

@ -91,10 +91,10 @@ class NumberValidator extends Validator
$this->addError($object, $attribute, $this->message); $this->addError($object, $attribute, $this->message);
} }
if ($this->min !== null && $value < $this->min) { if ($this->min !== null && $value < $this->min) {
$this->addError($object, $attribute, $this->tooSmall, ['{min}' => $this->min]); $this->addError($object, $attribute, $this->tooSmall, ['min' => $this->min]);
} }
if ($this->max !== null && $value > $this->max) { if ($this->max !== null && $value > $this->max) {
$this->addError($object, $attribute, $this->tooBig, ['{max}' => $this->max]); $this->addError($object, $attribute, $this->tooBig, ['max' => $this->max]);
} }
} }

2
framework/yii/validators/RequiredValidator.php

@ -75,7 +75,7 @@ class RequiredValidator extends Validator
$this->addError($object, $attribute, $this->message); $this->addError($object, $attribute, $this->message);
} else { } else {
$this->addError($object, $attribute, $this->message, [ $this->addError($object, $attribute, $this->message, [
'{requiredValue}' => $this->requiredValue, 'requiredValue' => $this->requiredValue,
]); ]);
} }
} }

6
framework/yii/validators/StringValidator.php

@ -112,13 +112,13 @@ class StringValidator extends Validator
$length = mb_strlen($value, $this->encoding); $length = mb_strlen($value, $this->encoding);
if ($this->min !== null && $length < $this->min) { if ($this->min !== null && $length < $this->min) {
$this->addError($object, $attribute, $this->tooShort, ['{min}' => $this->min]); $this->addError($object, $attribute, $this->tooShort, ['min' => $this->min]);
} }
if ($this->max !== null && $length > $this->max) { if ($this->max !== null && $length > $this->max) {
$this->addError($object, $attribute, $this->tooLong, ['{max}' => $this->max]); $this->addError($object, $attribute, $this->tooLong, ['max' => $this->max]);
} }
if ($this->length !== null && $length !== $this->length) { if ($this->length !== null && $length !== $this->length) {
$this->addError($object, $attribute, $this->notEqual, ['{length}' => $this->length]); $this->addError($object, $attribute, $this->notEqual, ['length' => $this->length]);
} }
} }

2
framework/yii/validators/UniqueValidator.php

@ -12,7 +12,7 @@ use yii\base\InvalidConfigException;
use yii\db\ActiveRecord; use yii\db\ActiveRecord;
/** /**
* CUniqueValidator validates that the attribute value is unique in the corresponding database table. * UniqueValidator validates that the attribute value is unique in the corresponding database table.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0

6
framework/yii/validators/Validator.php

@ -251,9 +251,9 @@ abstract class Validator extends Component
public function addError($object, $attribute, $message, $params = []) public function addError($object, $attribute, $message, $params = [])
{ {
$value = $object->$attribute; $value = $object->$attribute;
$params['{attribute}'] = $object->getAttributeLabel($attribute); $params['attribute'] = $object->getAttributeLabel($attribute);
$params['{value}'] = is_array($value) ? 'array()' : $value; $params['value'] = is_array($value) ? 'array()' : $value;
$object->addError($attribute, strtr($message, $params)); $object->addError($attribute, Yii::$app->getI18n()->format($message, $params, Yii::$app->language));
} }
/** /**

6
framework/yii/web/AccessControl.php

@ -42,9 +42,9 @@ use yii\base\ActionFilter;
* 'roles' => ['@'], * 'roles' => ['@'],
* ], * ],
* // everything else is denied * // everything else is denied
* ), * ],
* ), * ],
* ); * ];
* } * }
* ~~~ * ~~~
* *

11
framework/yii/web/AssetBundle.php

@ -68,7 +68,16 @@ class AssetBundle extends Object
*/ */
public $baseUrl; public $baseUrl;
/** /**
* @var array list of the bundle names that this bundle depends on * @var array list of bundle class names that this bundle depends on.
*
* For example:
*
* ```php
* public $depends = [
* 'yii\web\YiiAsset',
* 'yii\bootstrap\BootstrapAsset',
* ];
* ```
*/ */
public $depends = []; public $depends = [];
/** /**

6
framework/yii/web/Request.php

@ -246,11 +246,7 @@ class Request extends \yii\base\Request
$this->_restParams = $_POST; $this->_restParams = $_POST;
} else { } else {
$this->_restParams = []; $this->_restParams = [];
if (function_exists('mb_parse_str')) { mb_parse_str($this->getRawBody(), $this->_restParams);
mb_parse_str($this->getRawBody(), $this->_restParams);
} else {
parse_str($this->getRawBody(), $this->_restParams);
}
} }
} }
return $this->_restParams; return $this->_restParams;

9
framework/yii/web/Session.php

@ -118,12 +118,9 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
*/ */
public function open() public function open()
{ {
// this is available in PHP 5.4.0+ if (session_status() == PHP_SESSION_ACTIVE) {
if (function_exists('session_status')) { $this->_opened = true;
if (session_status() == PHP_SESSION_ACTIVE) { return;
$this->_opened = true;
return;
}
} }
if (!$this->_opened) { if (!$this->_opened) {

3
framework/yii/web/YiiAsset.php

@ -7,9 +7,6 @@
namespace yii\web; namespace yii\web;
use Yii;
use yii\base\View;
/** /**
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0

1
framework/yii/widgets/ActiveField.php

@ -8,7 +8,6 @@ namespace yii\widgets;
use Yii; use Yii;
use yii\base\Component; use yii\base\Component;
use yii\db\ActiveRecord;
use yii\helpers\ArrayHelper; use yii\helpers\ArrayHelper;
use yii\helpers\Html; use yii\helpers\Html;
use yii\base\Model; use yii\base\Model;

89
framework/yii/widgets/ActiveForm.php

@ -265,4 +265,93 @@ class ActiveForm extends Widget
'form' => $this, 'form' => $this,
])); ]));
} }
/**
* Validates one or several models and returns an error message array indexed by the attribute IDs.
* This is a helper method that simplifies the way of writing AJAX validation code.
*
* For example, you may use the following code in a controller action to respond
* to an AJAX validation request:
*
* ~~~
* $model = new Post;
* $model->load($_POST);
* if (Yii::$app->request->isAjax) {
* Yii::$app->response->format = Response::FORMAT_JSON;
* return ActiveForm::validate($model);
* }
* // ... respond to non-AJAX request ...
* ~~~
*
* To validate multiple models, simply pass each model as a parameter to this method, like
* the following:
*
* ~~~
* ActiveForm::validate($model1, $model2, ...);
* ~~~
*
* @param Model $model the model to be validated
* @param mixed $attributes list of attributes that should be validated.
* If this parameter is empty, it means any attribute listed in the applicable
* validation rules should be validated.
*
* When this method is used to validate multiple models, this parameter will be interpreted
* as a model.
*
* @return array the error message array indexed by the attribute IDs.
*/
public static function validate($model, $attributes = null)
{
$result = [];
if ($attributes instanceof Model) {
// validating multiple models
$models = func_get_args();
$attributes = null;
} else {
$models = [$model];
}
/** @var Model $model */
foreach ($models as $model) {
$model->validate($attributes);
foreach ($model->getErrors() as $attribute => $errors) {
$result[Html::getInputId($model, $attribute)] = $errors;
}
}
return $result;
}
/**
* Validates an array of model instances and returns an error message array indexed by the attribute IDs.
* This is a helper method that simplifies the way of writing AJAX validation code for tabular input.
*
* For example, you may use the following code in a controller action to respond
* to an AJAX validation request:
*
* ~~~
* // ... load $models ...
* if (Yii::$app->request->isAjax) {
* Yii::$app->response->format = Response::FORMAT_JSON;
* return ActiveForm::validateMultiple($models);
* }
* // ... respond to non-AJAX request ...
* ~~~
*
* @param array $models an array of models to be validated.
* @param mixed $attributes list of attributes that should be validated.
* If this parameter is empty, it means any attribute listed in the applicable
* validation rules should be validated.
* @return array the error message array indexed by the attribute IDs.
*/
public static function validateMultiple($models, $attributes = null)
{
$result = [];
/** @var Model $model */
foreach ($models as $i => $model) {
$model->validate($attributes);
foreach ($model->getErrors() as $attribute => $errors) {
$result[Html::getInputId($model, "[$i]" . $attribute)] = $errors;
}
}
return $result;
}
} }

24
framework/yii/widgets/BaseListView.php

@ -131,30 +131,32 @@ abstract class BaseListView extends Widget
public function renderSummary() public function renderSummary()
{ {
$count = $this->dataProvider->getCount(); $count = $this->dataProvider->getCount();
if (($pagination = $this->dataProvider->getPagination()) !== false && $count > 0) { if (($pagination = $this->dataProvider->getPagination()) !== false) {
$totalCount = $this->dataProvider->getTotalCount(); $totalCount = $this->dataProvider->getTotalCount();
$begin = $pagination->getPage() * $pagination->pageSize + 1; $begin = $pagination->getPage() * $pagination->pageSize + 1;
$end = $begin + $count - 1; $end = $begin + $count - 1;
$page = $pagination->getPage() + 1; $page = $pagination->getPage() + 1;
$pageCount = $pagination->pageCount; $pageCount = $pagination->pageCount;
if (($summaryContent = $this->summary) === null) { if (($summaryContent = $this->summary) === null) {
$summaryContent = '<div class="summary">' . Yii::t('yii', 'Showing <b>{begin}-{end}</b> of <b>{totalCount}</b> {0, plural, =1{item} other{items}}.', $totalCount) . '</div>'; $summaryContent = '<div class="summary">'
. Yii::t('yii', 'Showing <b>{totalCount, plural, =0{0} other{{begin}-{end}}}</b> of <b>{totalCount}</b> {totalCount, plural, one{item} other{items}}.')
. '</div>';
} }
} else { } else {
$begin = $page = $pageCount = 1; $begin = $page = $pageCount = 1;
$end = $totalCount = $count; $end = $totalCount = $count;
if (($summaryContent = $this->summary) === null) { if (($summaryContent = $this->summary) === null) {
$summaryContent = '<div class="summary">' . Yii::t('yii', 'Total <b>{count}</b> {0, plural, =1{item} other{items}}.', $count) . '</div>'; $summaryContent = '<div class="summary">' . Yii::t('yii', 'Total <b>{count}</b> {count, plural, one{item} other{items}}.') . '</div>';
} }
} }
return strtr($summaryContent, [ return Yii::$app->getI18n()->format($summaryContent, [
'{begin}' => $begin, 'begin' => $begin,
'{end}' => $end, 'end' => $end,
'{count}' => $count, 'count' => $count,
'{totalCount}' => $totalCount, 'totalCount' => $totalCount,
'{page}' => $page, 'page' => $page,
'{pageCount}' => $pageCount, 'pageCount' => $pageCount,
]); ], Yii::$app->language);
} }
/** /**

6
framework/yii/widgets/Menu.php

@ -33,13 +33,13 @@ use yii\helpers\Html;
* // not just as 'controller' even if default action is used. * // not just as 'controller' even if default action is used.
* ['label' => 'Home', 'url' => ['site/index']], * ['label' => 'Home', 'url' => ['site/index']],
* // 'Products' menu item will be selected as long as the route is 'product/index' * // 'Products' menu item will be selected as long as the route is 'product/index'
* ['label' => 'Products', 'url' => ['product/index'), 'items' => [ * ['label' => 'Products', 'url' => ['product/index'], 'items' => [
* ['label' => 'New Arrivals', 'url' => ['product/index', 'tag' => 'new']], * ['label' => 'New Arrivals', 'url' => ['product/index', 'tag' => 'new']],
* ['label' => 'Most Popular', 'url' => ['product/index', 'tag' => 'popular']], * ['label' => 'Most Popular', 'url' => ['product/index', 'tag' => 'popular']],
* ]], * ]],
* ['label' => 'Login', 'url' => ['site/login'], 'visible' => Yii::$app->user->isGuest], * ['label' => 'Login', 'url' => ['site/login'], 'visible' => Yii::$app->user->isGuest],
* ), * ],
* )); * ]);
* ~~~ * ~~~
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>

2
tests/unit/data/ar/ActiveRecord.php

@ -7,8 +7,6 @@
namespace yiiunit\data\ar; namespace yiiunit\data\ar;
use yii\db\Connection;
/** /**
* ActiveRecord is ... * ActiveRecord is ...
* *

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

@ -13,7 +13,6 @@ function time()
namespace yiiunit\framework\caching; namespace yiiunit\framework\caching;
use yii\helpers\StringHelper;
use yiiunit\TestCase; use yiiunit\TestCase;
use yii\caching\Cache; use yii\caching\Cache;

1
tests/unit/framework/caching/RedisCacheTest.php

@ -2,7 +2,6 @@
namespace yiiunit\framework\caching; namespace yiiunit\framework\caching;
use yii\caching\MemCache; use yii\caching\MemCache;
use yii\caching\RedisCache; use yii\caching\RedisCache;
use yiiunit\TestCase;
/** /**
* Class for testing redis cache backend * Class for testing redis cache backend

1
tests/unit/framework/caching/ZendDataCacheTest.php

@ -1,7 +1,6 @@
<?php <?php
namespace yiiunit\framework\caching; namespace yiiunit\framework\caching;
use yii\caching\Cache;
use yii\caching\ZendDataCache; use yii\caching\ZendDataCache;
/** /**

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

@ -1,7 +1,6 @@
<?php <?php
namespace yiiunit\framework\db; namespace yiiunit\framework\db;
use yii\db\Query;
use yii\db\ActiveQuery; use yii\db\ActiveQuery;
use yiiunit\data\ar\ActiveRecord; use yiiunit\data\ar\ActiveRecord;
use yiiunit\data\ar\Customer; use yiiunit\data\ar\Customer;

3
tests/unit/framework/db/CommandTest.php

@ -2,9 +2,6 @@
namespace yiiunit\framework\db; namespace yiiunit\framework\db;
use yii\db\Connection;
use yii\db\Command;
use yii\db\Query;
use yii\db\DataReader; use yii\db\DataReader;
/** /**

3
tests/unit/framework/db/QueryTest.php

@ -2,10 +2,7 @@
namespace yiiunit\framework\db; namespace yiiunit\framework\db;
use yii\db\Connection;
use yii\db\Command;
use yii\db\Query; use yii\db\Query;
use yii\db\DataReader;
/** /**
* @group db * @group db

1
tests/unit/framework/db/cubrid/CubridQueryBuilderTest.php

@ -2,7 +2,6 @@
namespace yiiunit\framework\db\cubrid; namespace yiiunit\framework\db\cubrid;
use yii\base\NotSupportedException;
use yii\db\sqlite\Schema; use yii\db\sqlite\Schema;
use yiiunit\framework\db\QueryBuilderTest; use yiiunit\framework\db\QueryBuilderTest;

155
tests/unit/framework/i18n/FallbackMessageFormatterTest.php

@ -0,0 +1,155 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yiiunit\framework\i18n;
use yii\i18n\FallbackMessageFormatter;
use yiiunit\TestCase;
/**
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
* @group i18n
*/
class FallbackMessageFormatterTest extends TestCase
{
const N = 'n';
const N_VALUE = 42;
const SUBJECT = 'сабж';
const SUBJECT_VALUE = 'Answer to the Ultimate Question of Life, the Universe, and Everything';
public function patterns()
{
return [
[
'{'.self::SUBJECT.'} is {'.self::N.'}', // pattern
self::SUBJECT_VALUE.' is '.self::N_VALUE, // expected
[ // params
self::N => self::N_VALUE,
self::SUBJECT => self::SUBJECT_VALUE,
]
],
// This one was provided by Aura.Intl. Thanks!
[<<<_MSG_
{gender_of_host, select,
female {{num_guests, plural, offset:1
=0 {{host} does not give a party.}
=1 {{host} invites {guest} to her party.}
=2 {{host} invites {guest} and one other person to her party.}
other {{host} invites {guest} and # other people to her party.}}}
male {{num_guests, plural, offset:1
=0 {{host} does not give a party.}
=1 {{host} invites {guest} to his party.}
=2 {{host} invites {guest} and one other person to his party.}
other {{host} invites {guest} and # other people to his party.}}}
other {{num_guests, plural, offset:1
=0 {{host} does not give a party.}
=1 {{host} invites {guest} to their party.}
=2 {{host} invites {guest} and one other person to their party.}
other {{host} invites {guest} and # other people to their party.}}}}
_MSG_
,
'ralph invites beep and 3 other people to his party.',
[
'gender_of_host' => 'male',
'num_guests' => 4,
'host' => 'ralph',
'guest' => 'beep'
]
],
[
'{name} is {gender} and {gender, select, female{she} male{he} other{it}} loves Yii!',
'Alexander is male and he loves Yii!',
[
'name' => 'Alexander',
'gender' => 'male',
],
],
// verify pattern in select does not get replaced
[
'{name} is {gender} and {gender, select, female{she} male{he} other{it}} loves Yii!',
'Alexander is male and he loves Yii!',
[
'name' => 'Alexander',
'gender' => 'male',
// following should not be replaced
'he' => 'wtf',
'she' => 'wtf',
'it' => 'wtf',
]
],
// verify pattern in select message gets replaced
[
'{name} is {gender} and {gender, select, female{she} male{{he}} other{it}} loves Yii!',
'Alexander is male and wtf loves Yii!',
[
'name' => 'Alexander',
'gender' => 'male',
'he' => 'wtf',
'she' => 'wtf',
],
],
// some parser specific verifications
[
'{gender} and {gender, select, female{she} male{{he}} other{it}} loves {nr} is {gender}!',
'male and wtf loves 42 is male!',
[
'nr' => 42,
'gender' => 'male',
'he' => 'wtf',
'she' => 'wtf',
],
],
];
}
/**
* @dataProvider patterns
*/
public function testNamedArgumentsStatic($pattern, $expected, $args)
{
$result = FallbackMessageFormatter::formatMessage('en_US', $pattern, $args);
$this->assertEquals($expected, $result);
}
/**
* @dataProvider patterns
*/
public function testNamedArgumentsObject($pattern, $expected, $args)
{
$formatter = new FallbackMessageFormatter('en_US', $pattern);
$result = $formatter->format($args);
$this->assertEquals($expected, $result, $formatter->getErrorMessage());
}
public function testInsufficientArguments()
{
$expected = '{'.self::SUBJECT.'} is '.self::N_VALUE;
$result = FallbackMessageFormatter::formatMessage('en_US', '{'.self::SUBJECT.'} is {'.self::N.'}', [
self::N => self::N_VALUE,
]);
$this->assertEquals($expected, $result);
}
public function testNoParams()
{
$pattern = '{'.self::SUBJECT.'} is '.self::N;
$result = FallbackMessageFormatter::formatMessage('en_US', $pattern, []);
$this->assertEquals($pattern, $result);
$formatter = new FallbackMessageFormatter('en_US', $pattern);
$result = $formatter->format([]);
$this->assertEquals($pattern, $result, $formatter->getErrorMessage());
}
}

1
tests/unit/framework/i18n/GettextMessageSourceTest.php

@ -2,7 +2,6 @@
namespace yiiunit\framework\i18n; namespace yiiunit\framework\i18n;
use yii\i18n\GettextMessageSource;
use yiiunit\TestCase; use yiiunit\TestCase;
/** /**

7
tests/unit/framework/i18n/I18NTest.php

@ -9,7 +9,6 @@ namespace yiiunit\framework\i18n;
use yii\base\Model; use yii\base\Model;
use yii\i18n\I18N; use yii\i18n\I18N;
use yii\i18n\MessageFormatter;
use yii\i18n\PhpMessageSource; use yii\i18n\PhpMessageSource;
use yiiunit\TestCase; use yiiunit\TestCase;
@ -51,7 +50,13 @@ class I18NTest extends TestCase
$params = ['n' => 42]; $params = ['n' => 42];
$this->assertEquals('His speed is about 42 km/h.', $this->i18n->translate('test', $msg, $params, 'en_US')); $this->assertEquals('His speed is about 42 km/h.', $this->i18n->translate('test', $msg, $params, 'en_US'));
$this->assertEquals('Seine Geschwindigkeit beträgt 42 km/h.', $this->i18n->translate('test', $msg, $params, 'de_DE')); $this->assertEquals('Seine Geschwindigkeit beträgt 42 km/h.', $this->i18n->translate('test', $msg, $params, 'de_DE'));
}
public function testTranslateParams2()
{
if (!extension_loaded("intl")) {
$this->markTestSkipped("intl not installed. Skipping.");
}
$msg = 'His name is {name} and his speed is about {n, number} km/h.'; $msg = 'His name is {name} and his speed is about {n, number} km/h.';
$params = [ $params = [
'n' => 42, 'n' => 42,

6
tests/unit/framework/validators/BooleanValidatorTest.php

@ -10,6 +10,12 @@ use yiiunit\TestCase;
*/ */
class BooleanValidatorTest extends TestCase class BooleanValidatorTest extends TestCase
{ {
protected function setUp()
{
parent::setUp();
$this->mockApplication();
}
public function testValidateValue() public function testValidateValue()
{ {
$val = new BooleanValidator; $val = new BooleanValidator;

5
tests/unit/framework/validators/CompareValidatorTest.php

@ -10,6 +10,11 @@ use yiiunit\TestCase;
class CompareValidatorTest extends TestCase class CompareValidatorTest extends TestCase
{ {
protected function setUp()
{
parent::setUp();
$this->mockApplication();
}
public function testValidateValueException() public function testValidateValueException()
{ {

7
tests/unit/framework/validators/DateValidatorTest.php

@ -10,6 +10,12 @@ use yiiunit\TestCase;
class DateValidatorTest extends TestCase class DateValidatorTest extends TestCase
{ {
protected function setUp()
{
parent::setUp();
$this->mockApplication();
}
public function testEnsureMessageIsSet() public function testEnsureMessageIsSet()
{ {
$val = new DateValidator; $val = new DateValidator;
@ -19,6 +25,7 @@ class DateValidatorTest extends TestCase
public function testValidateValue() public function testValidateValue()
{ {
$val = new DateValidator; $val = new DateValidator;
$this->assertFalse($val->validateValue('3232-32-32'));
$this->assertTrue($val->validateValue('2013-09-13')); $this->assertTrue($val->validateValue('2013-09-13'));
$this->assertFalse($val->validateValue('31.7.2013')); $this->assertFalse($val->validateValue('31.7.2013'));
$this->assertFalse($val->validateValue('31-7-2013')); $this->assertFalse($val->validateValue('31-7-2013'));

6
tests/unit/framework/validators/DefaultValueValidatorTest.php

@ -8,6 +8,12 @@ use yiiunit\TestCase;
*/ */
class DefaultValueValidatorTest extends TestCase class DefaultValueValidatorTest extends TestCase
{ {
protected function setUp()
{
parent::setUp();
$this->mockApplication();
}
public function testValidateAttribute() public function testValidateAttribute()
{ {
$val = new DefaultValueValidator; $val = new DefaultValueValidator;

6
tests/unit/framework/validators/EmailValidatorTest.php

@ -11,6 +11,12 @@ use yiiunit\TestCase;
*/ */
class EmailValidatorTest extends TestCase class EmailValidatorTest extends TestCase
{ {
protected function setUp()
{
parent::setUp();
$this->mockApplication();
}
public function testValidateValue() public function testValidateValue()
{ {
$validator = new EmailValidator(); $validator = new EmailValidator();

1
tests/unit/framework/validators/ExistValidatorTest.php

@ -18,6 +18,7 @@ class ExistValidatorTest extends DatabaseTestCase
public function setUp() public function setUp()
{ {
parent::setUp(); parent::setUp();
$this->mockApplication();
ActiveRecord::$db = $this->getConnection(); ActiveRecord::$db = $this->getConnection();
} }

6
tests/unit/framework/validators/FilterValidatorTest.php

@ -9,6 +9,12 @@ use yiiunit\TestCase;
class FilterValidatorTest extends TestCase class FilterValidatorTest extends TestCase
{ {
protected function setUp()
{
parent::setUp();
$this->mockApplication();
}
public function testAssureExceptionOnInit() public function testAssureExceptionOnInit()
{ {
$this->setExpectedException('yii\base\InvalidConfigException'); $this->setExpectedException('yii\base\InvalidConfigException');

6
tests/unit/framework/validators/NumberValidatorTest.php

@ -9,6 +9,12 @@ use yiiunit\TestCase;
class NumberValidatorTest extends TestCase class NumberValidatorTest extends TestCase
{ {
protected function setUp()
{
parent::setUp();
$this->mockApplication();
}
public function testEnsureMessageOnInit() public function testEnsureMessageOnInit()
{ {
$val = new NumberValidator; $val = new NumberValidator;

6
tests/unit/framework/validators/RangeValidatorTest.php

@ -9,6 +9,12 @@ use yiiunit\TestCase;
class RangeValidatorTest extends TestCase class RangeValidatorTest extends TestCase
{ {
protected function setUp()
{
parent::setUp();
$this->mockApplication();
}
public function testInitException() public function testInitException()
{ {
$this->setExpectedException('yii\base\InvalidConfigException', 'The "range" property must be set.'); $this->setExpectedException('yii\base\InvalidConfigException', 'The "range" property must be set.');

6
tests/unit/framework/validators/RegularExpressionValidatorTest.php

@ -9,6 +9,12 @@ use yiiunit\TestCase;
class RegularExpressionValidatorTest extends TestCase class RegularExpressionValidatorTest extends TestCase
{ {
protected function setUp()
{
parent::setUp();
$this->mockApplication();
}
public function testValidateValue() public function testValidateValue()
{ {
$val = new RegularExpressionValidator(['pattern' => '/^[a-zA-Z0-9](\.)?([^\/]*)$/m']); $val = new RegularExpressionValidator(['pattern' => '/^[a-zA-Z0-9](\.)?([^\/]*)$/m']);

6
tests/unit/framework/validators/RequiredValidatorTest.php

@ -8,6 +8,12 @@ use yiiunit\TestCase;
class RequiredValidatorTest extends TestCase class RequiredValidatorTest extends TestCase
{ {
protected function setUp()
{
parent::setUp();
$this->mockApplication();
}
public function testValidateValueWithDefaults() public function testValidateValueWithDefaults()
{ {
$val = new RequiredValidator(); $val = new RequiredValidator();

2
tests/unit/framework/validators/UniqueValidatorTest.php

@ -10,7 +10,6 @@ use yiiunit\data\validators\models\FakedValidationModel;
use yiiunit\data\validators\models\ValidatorTestMainModel; use yiiunit\data\validators\models\ValidatorTestMainModel;
use yiiunit\data\validators\models\ValidatorTestRefModel; use yiiunit\data\validators\models\ValidatorTestRefModel;
use yiiunit\framework\db\DatabaseTestCase; use yiiunit\framework\db\DatabaseTestCase;
use yiiunit\TestCase;
class UniqueValidatorTest extends DatabaseTestCase class UniqueValidatorTest extends DatabaseTestCase
{ {
@ -19,6 +18,7 @@ class UniqueValidatorTest extends DatabaseTestCase
public function setUp() public function setUp()
{ {
parent::setUp(); parent::setUp();
$this->mockApplication();
ActiveRecord::$db = $this->getConnection(); ActiveRecord::$db = $this->getConnection();
} }

6
tests/unit/framework/validators/UrlValidatorTest.php

@ -9,6 +9,12 @@ use yiiunit\TestCase;
*/ */
class UrlValidatorTest extends TestCase class UrlValidatorTest extends TestCase
{ {
protected function setUp()
{
parent::setUp();
$this->mockApplication();
}
public function testValidateValue() public function testValidateValue()
{ {
$val = new UrlValidator; $val = new UrlValidator;

7
tests/unit/framework/validators/ValidatorTest.php

@ -12,6 +12,11 @@ use yiiunit\TestCase;
class ValidatorTest extends TestCase class ValidatorTest extends TestCase
{ {
protected function setUp()
{
parent::setUp();
$this->mockApplication();
}
protected function getTestModel($additionalAttributes = []) protected function getTestModel($additionalAttributes = [])
{ {
@ -220,7 +225,7 @@ class ValidatorTest extends TestCase
$errors = $m->getErrors('attr_msg_val'); $errors = $m->getErrors('attr_msg_val');
$this->assertEquals('attr_msg_val::array()', $errors[0]); $this->assertEquals('attr_msg_val::array()', $errors[0]);
$m = $this->getTestModel(['attr_msg_val' => 'abc']); $m = $this->getTestModel(['attr_msg_val' => 'abc']);
$val->addError($m, 'attr_msg_val', '{attribute}::{value}::{param}', ['{param}' => 'param_value']); $val->addError($m, 'attr_msg_val', '{attribute}::{value}::{param}', ['param' => 'param_value']);
$errors = $m->getErrors('attr_msg_val'); $errors = $m->getErrors('attr_msg_val');
$this->assertEquals('attr_msg_val::abc::param_value', $errors[0]); $this->assertEquals('attr_msg_val::abc::param_value', $errors[0]);
} }

Loading…
Cancel
Save