diff --git a/docs/internals-ru/getting-started.md b/docs/internals-ru/getting-started.md new file mode 100644 index 0000000000..bec4223934 --- /dev/null +++ b/docs/internals-ru/getting-started.md @@ -0,0 +1,45 @@ +Подготовка к разработке Yii2 +============================ + +1. Создаём клон своего форка yii2 `git clone git@github.com:<ваше имя>/yii2.git`. +2. Переходим в папку репозитория `cd yii2`. +3. Запускаем `./build/build app/link basic` для установки composer зависимостей приложения basic. + *Эта команда установит сторонние пакеты composer как обычно, но создаст ссылку с репозитория yii2 + на только что загуженный репозиторий. Таким образом у вас будет только один экземпляр кода.* +4. При необходимости делаем тоже самое для приложения advanced: `./build/build app/link advanced` + Внутри эта команда использует `composer update` для обновления кода. +5. Теперь у нас есть рабочая площадка для экспериментов с Yii 2. + +Можно так же добавить репозиторий yii2 upstream для получения последних изменений: + +``` +git remote add upstream https://github.com/yiisoft/yii2.git +``` + +Пожалуйста ознакомьтесь с разделом «[рабочий процесс Git для разработчиков Yii 2](git-workflow.md)» +для получения подробной информации о создании pull request-ов. + +Модульные тесты +--------------- + +Для запуска модульных тестов нужно установить composer пакеты для dev-репозитория. +В корневой директории делаем `composer update` для получения последней версии пакетов. + +Теперь можно выполнить модульные тесты, запустив `phpunit`. + +Можно ограничиться группой тестов, над которыми вы работаете. Например, следующая команда запустит тесты только для +валидаторов и redis `phpunit --group=validators,redis`. + +Расширения +---------- + +Для работы над расширениями необходимо установить их в приложение. Добавляем их в `composer.json` как обычно. Например, +добавим `"yiisoft/yii2-redis": "*"` в секцию `require` для приложения basic. +Запускаем `./build/build app/link basic` для установки расширения, его зависимостей и создания символической +ссылки на `extensions/redis`. Теперь вы работаете с репозиторием yii2, а не с директорией vendor. + +Функциональные и приёмочные тесты для приложений +------------------------------------------------ + +Cмотрите `apps/advanced/tests/README.md` и `apps/basic/tests/README.md`, чтобы узнать о том как запускать +тесты Codeception. diff --git a/extensions/elasticsearch/ActiveRecord.php b/extensions/elasticsearch/ActiveRecord.php index 805f80d9c7..d4793a18db 100644 --- a/extensions/elasticsearch/ActiveRecord.php +++ b/extensions/elasticsearch/ActiveRecord.php @@ -575,7 +575,7 @@ class ActiveRecord extends BaseActiveRecord { $pkName = static::primaryKey()[0]; if (count($condition) == 1 && isset($condition[$pkName])) { - $primaryKeys = is_array($condition[$pkName]) ? $condition[$pkName] : [$condition[$pkName]]; + $primaryKeys = (array)$condition[$pkName]; } else { $primaryKeys = static::find()->where($condition)->column($pkName); // TODO check whether this works with default pk _id } @@ -635,7 +635,7 @@ class ActiveRecord extends BaseActiveRecord { $pkName = static::primaryKey()[0]; if (count($condition) == 1 && isset($condition[$pkName])) { - $primaryKeys = is_array($condition[$pkName]) ? $condition[$pkName] : [$condition[$pkName]]; + $primaryKeys = (array)$condition[$pkName]; } else { $primaryKeys = static::find()->where($condition)->column($pkName); // TODO check whether this works with default pk _id } @@ -771,7 +771,7 @@ class ActiveRecord extends BaseActiveRecord { $pkName = static::primaryKey()[0]; if (count($condition) == 1 && isset($condition[$pkName])) { - $primaryKeys = is_array($condition[$pkName]) ? $condition[$pkName] : [$condition[$pkName]]; + $primaryKeys = (array)$condition[$pkName]; } else { $primaryKeys = static::find()->where($condition)->column($pkName); // TODO check whether this works with default pk _id } diff --git a/extensions/jui/AutoComplete.php b/extensions/jui/AutoComplete.php index 0712350637..d2d2bc5f48 100644 --- a/extensions/jui/AutoComplete.php +++ b/extensions/jui/AutoComplete.php @@ -35,6 +35,17 @@ use yii\helpers\Html; * ]); * ``` * + * You can also use this widget in an [[yii\widgets\ActiveForm|ActiveForm]] using the [[yii\widgets\ActiveField::widget()|widget()]] + * method, for example like this: + * + * ```php + * field($model, 'from_date')->widget(\yii\jui\AutoComplete::classname(), [ + * 'clientOptions' => [ + * 'source' => ['USA', 'RUS'], + * ], + * ]) ?> + * ``` + * * @see http://api.jqueryui.com/autocomplete/ * @author Alexander Kochetov * @since 2.0 diff --git a/extensions/jui/DatePicker.php b/extensions/jui/DatePicker.php index c705cb4349..f4e4be2e9c 100644 --- a/extensions/jui/DatePicker.php +++ b/extensions/jui/DatePicker.php @@ -38,8 +38,19 @@ use yii\helpers\Json; * ]); * ``` * - * Note that empty values like empty strings and 0 will result in a date displayed as `1970-01-01`. - * So to make sure empty values result in an empty text field in the datepicker you need to add a + * You can also use this widget in an [[yii\widgets\ActiveForm|ActiveForm]] using the [[yii\widgets\ActiveField::widget()|widget()]] + * method, for example like this: + * + * ```php + * field($model, 'from_date')->widget(\yii\jui\DatePicker::classname(), [ + * //'language' => 'ru', + * //'dateFormat' => 'yyyy-MM-dd', + * ]) ?> + * ``` + * + * Note that and empty string (`''`) and `null` will result in an empty text field while `0` will be + * interpreted as a UNIX timestamp and result in a date displayed as `1970-01-01`. + * It is recommended to add a * validation filter in your model that sets the value to `null` in case when no date has been entered: * * ```php diff --git a/extensions/jui/InputWidget.php b/extensions/jui/InputWidget.php index 2d2570a890..fdff0a4d4d 100644 --- a/extensions/jui/InputWidget.php +++ b/extensions/jui/InputWidget.php @@ -14,6 +14,15 @@ use yii\helpers\Html; /** * InputWidget is the base class for all jQuery UI input widgets. * + * Classes extending from this widget can be used in an [[yii\widgets\ActiveForm|ActiveForm]] + * using the [[yii\widgets\ActiveField::widget()|widget()]] method, for example like this: + * + * ```php + * field($model, 'from_date')->widget('WidgetClassName', [ + * // configure additional widget properties here + * ]) ?> + * ``` + * * @author Alexander Kochetov * @since 2.0 */ diff --git a/extensions/jui/SliderInput.php b/extensions/jui/SliderInput.php index fce66a299a..ec6c324ce3 100644 --- a/extensions/jui/SliderInput.php +++ b/extensions/jui/SliderInput.php @@ -37,6 +37,18 @@ use yii\helpers\Html; * ]); * ``` * + * You can also use this widget in an [[yii\widgets\ActiveForm|ActiveForm]] using the [[yii\widgets\ActiveField::widget()|widget()]] + * method, for example like this: + * + * ```php + * field($model, 'from_date')->widget(\yii\jui\SliderInput::classname(), [ + * 'clientOptions' => [ + * 'min' => 1, + * 'max' => 10, + * ], + * ]) ?> + * ``` + * * @see http://api.jqueryui.com/slider/ * @author Alexander Makarov * @since 2.0 diff --git a/extensions/jui/Spinner.php b/extensions/jui/Spinner.php index 83f804e0d9..164c17fac8 100644 --- a/extensions/jui/Spinner.php +++ b/extensions/jui/Spinner.php @@ -31,6 +31,15 @@ use yii\helpers\Html; * ]); * ``` * + * You can also use this widget in an [[yii\widgets\ActiveForm|ActiveForm]] using the [[yii\widgets\ActiveField::widget()|widget()]] + * method, for example like this: + * + * ```php + * field($model, 'from_date')->widget(\yii\jui\Spinner::classname(), [ + * 'clientOptions' => ['step' => 2], + * ]) ?> + * ``` + * * @see http://api.jqueryui.com/spinner/ * @author Alexander Kochetov * @since 2.0 diff --git a/extensions/mongodb/Collection.php b/extensions/mongodb/Collection.php index c287bc9ada..1f1c6aeca0 100644 --- a/extensions/mongodb/Collection.php +++ b/extensions/mongodb/Collection.php @@ -213,9 +213,7 @@ class Collection extends Object */ public function createIndex($columns, $options = []) { - if (!is_array($columns)) { - $columns = [$columns]; - } + $columns = (array)$columns; $keys = $this->normalizeIndexKeys($columns); $token = $this->composeLogToken('createIndex', [$keys, $options]); $options = array_merge(['w' => 1], $options); @@ -258,9 +256,7 @@ class Collection extends Object */ public function dropIndex($columns) { - if (!is_array($columns)) { - $columns = [$columns]; - } + $columns = (array)$columns; $keys = $this->normalizeIndexKeys($columns); $token = $this->composeLogToken('dropIndex', [$keys]); Yii::info($token, __METHOD__); diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 124a45730c..59e30ade78 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -17,6 +17,7 @@ Yii Framework 2 Change Log - Enh #6697: Added `yii\helpers\Url::current()` method that allows adding or removing parameters from current URL (samdark, callmez) - Enh #6852: Added `yii\helpers\BaseHtmlPurifier::helpers()` in order to be able to configure `HtmlPurifier` helper globally via subclassing (Alex-Code) - Enh #6882: Added `yii\web\ErrorHandler::getTypeUrl()` in order to allow providing custom types/classes/methods URLs for subclasses (brandonkelly) +- Enh #6883: `yii\base\ErrorHandler::logException()` is now public (samdark) - Enh #6896: Added `yii\log\FileTarget::$enableRotation` to allow disabling log rotation when external tools are configured for this (cebe) - Enh #7008: Removed extra white space in GridView filter cell (uran1980) - Enh #7051: Added support for preventing swapping values between different cookies (pavimus, qiangxue) diff --git a/framework/base/ErrorHandler.php b/framework/base/ErrorHandler.php index a7e659b78b..ba8278eab8 100644 --- a/framework/base/ErrorHandler.php +++ b/framework/base/ErrorHandler.php @@ -197,7 +197,7 @@ abstract class ErrorHandler extends Component * Logs the given exception * @param \Exception $exception the exception to be logged */ - protected function logException($exception) + public function logException($exception) { $category = get_class($exception); if ($exception instanceof HttpException) { diff --git a/framework/captcha/Captcha.php b/framework/captcha/Captcha.php index 334398a6dc..b04fd05aba 100644 --- a/framework/captcha/Captcha.php +++ b/framework/captcha/Captcha.php @@ -17,8 +17,8 @@ use yii\widgets\InputWidget; /** * Captcha renders a CAPTCHA image and an input field that takes user-entered verification code. * - * Captcha is used together with [[CaptchaAction]] provide [CAPTCHA](http://en.wikipedia.org/wiki/Captcha) - * - a way of preventing Website spamming. + * Captcha is used together with [[CaptchaAction]] provide [CAPTCHA](http://en.wikipedia.org/wiki/Captcha) - a way + * of preventing Website spamming. * * The image element rendered by Captcha will display a CAPTCHA image generated by * an action whose route is specified by [[captchaAction]]. This action must be an instance of [[CaptchaAction]]. @@ -29,6 +29,32 @@ use yii\widgets\InputWidget; * You may use [[\yii\captcha\CaptchaValidator]] to validate the user input matches * the current CAPTCHA verification code. * + * The following example shows how to use this widget with a model attribute: + * + * ```php + * echo Captcha::widget([ + * 'model' => $model, + * 'attribute' => 'captcha', + * ]); + * ``` + * + * The following example will use the name property instead: + * + * ```php + * echo Captcha::widget([ + * 'name' => 'captcha', + * ]); + * ``` + * + * You can also use this widget in an [[yii\widgets\ActiveForm|ActiveForm]] using the [[yii\widgets\ActiveField::widget()|widget()]] + * method, for example like this: + * + * ```php + * field($model, 'captcha')->widget(\yii\widgets\Captcha::classname(), [ + * // configure additional widget properties here + * ]) ?> + * ``` + * * @author Qiang Xue * @since 2.0 */ diff --git a/framework/console/controllers/BaseMigrateController.php b/framework/console/controllers/BaseMigrateController.php index ff4acdfd44..03ba4b39ec 100644 --- a/framework/console/controllers/BaseMigrateController.php +++ b/framework/console/controllers/BaseMigrateController.php @@ -615,7 +615,7 @@ abstract class BaseMigrateController extends Controller continue; } $path = $this->migrationPath . DIRECTORY_SEPARATOR . $file; - if (preg_match('/^(m(\d{6}_\d{6})_.*?)\.php$/', $file, $matches) && is_file($path) && !isset($applied[$matches[2]])) { + if (preg_match('/^(m(\d{6}_\d{6})_.*?)\.php$/', $file, $matches) && !isset($applied[$matches[2]]) && is_file($path)) { $migrations[] = $matches[1]; } } diff --git a/framework/console/controllers/HelpController.php b/framework/console/controllers/HelpController.php index 889b8181ea..c24cf97be4 100644 --- a/framework/console/controllers/HelpController.php +++ b/framework/console/controllers/HelpController.php @@ -113,7 +113,7 @@ class HelpController extends Controller $class = new \ReflectionClass($controller); foreach ($class->getMethods() as $method) { $name = $method->getName(); - if ($method->isPublic() && !$method->isStatic() && strpos($name, 'action') === 0 && $name !== 'actions') { + if ($name !== 'actions' && $method->isPublic() && !$method->isStatic() && strpos($name, 'action') === 0) { $actions[] = Inflector::camel2id(substr($name, 6), '-', true); } } diff --git a/framework/console/controllers/MessageController.php b/framework/console/controllers/MessageController.php index 0d0496cf8d..60c8db05c4 100644 --- a/framework/console/controllers/MessageController.php +++ b/framework/console/controllers/MessageController.php @@ -248,10 +248,7 @@ class MessageController extends Controller $this->stdout("Extracting messages from $coloredFileName...\n"); $subject = file_get_contents($fileName); $messages = []; - if (!is_array($translator)) { - $translator = [$translator]; - } - foreach ($translator as $currentTranslator) { + foreach ((array)$translator as $currentTranslator) { $translatorTokens = token_get_all(' $translation) { - if (!isset($merged[$message]) && !isset($todo[$message]) && !$removeUnused) { + if (!$removeUnused && !isset($merged[$message]) && !isset($todo[$message])) { if (!empty($translation) && strncmp($translation, '@@', 2) === 0 && substr_compare($translation, '@@', -2, 2) === 0) { $todo[$message] = $translation; } else { @@ -515,7 +512,7 @@ EOD; // add obsolete unused messages foreach ($existingMessages as $message => $translation) { - if (!isset($merged[$category . chr(4) . $message]) && !isset($todos[$category . chr(4) . $message]) && !$removeUnused) { + if (!$removeUnused && !isset($merged[$category . chr(4) . $message]) && !isset($todos[$category . chr(4) . $message])) { if (!empty($translation) && substr($translation, 0, 2) === '@@' && substr($translation, -2) === '@@') { $todos[$category . chr(4) . $message] = $translation; } else { diff --git a/framework/data/Pagination.php b/framework/data/Pagination.php index 4f519f0958..09f551b95d 100644 --- a/framework/data/Pagination.php +++ b/framework/data/Pagination.php @@ -232,7 +232,7 @@ class Pagination extends Object implements Linkable $this->_pageSize = null; } else { $value = (int) $value; - if ($validatePageSize && count($this->pageSizeLimit) === 2 && isset($this->pageSizeLimit[0], $this->pageSizeLimit[1])) { + if ($validatePageSize && isset($this->pageSizeLimit[0], $this->pageSizeLimit[1]) && count($this->pageSizeLimit) === 2) { if ($value < $this->pageSizeLimit[0]) { $value = $this->pageSizeLimit[0]; } elseif ($value > $this->pageSizeLimit[1]) { diff --git a/framework/db/ActiveRelationTrait.php b/framework/db/ActiveRelationTrait.php index 70eb649b90..17a5e97c3e 100644 --- a/framework/db/ActiveRelationTrait.php +++ b/framework/db/ActiveRelationTrait.php @@ -215,7 +215,7 @@ trait ActiveRelationTrait $this->filterByModels($primaryModels); } - if (count($primaryModels) === 1 && !$this->multiple) { + if (!$this->multiple && count($primaryModels) === 1) { $model = $this->one(); foreach ($primaryModels as $i => $primaryModel) { if ($primaryModel instanceof ActiveRecordInterface) { diff --git a/framework/db/BaseActiveRecord.php b/framework/db/BaseActiveRecord.php index 673d222532..2243b4464b 100644 --- a/framework/db/BaseActiveRecord.php +++ b/framework/db/BaseActiveRecord.php @@ -980,7 +980,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface public function getPrimaryKey($asArray = false) { $keys = $this->primaryKey(); - if (count($keys) === 1 && !$asArray) { + if (!$asArray && count($keys) === 1) { return isset($this->_attributes[$keys[0]]) ? $this->_attributes[$keys[0]] : null; } else { $values = []; @@ -1014,7 +1014,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface if (empty($keys)) { throw new Exception(get_class($this) . ' does not have a primary key. You should either define a primary key for the corresponding table or override the primaryKey() method.'); } - if (count($keys) === 1 && !$asArray) { + if (!$asArray && count($keys) === 1) { return isset($this->_oldAttributes[$keys[0]]) ? $this->_oldAttributes[$keys[0]] : null; } else { $values = []; diff --git a/framework/db/QueryBuilder.php b/framework/db/QueryBuilder.php index d90238c2a5..da2c511a00 100644 --- a/framework/db/QueryBuilder.php +++ b/framework/db/QueryBuilder.php @@ -189,7 +189,7 @@ class QueryBuilder extends \yii\base\Object foreach ($rows as $row) { $vs = []; foreach ($row as $i => $value) { - if (!is_array($value) && isset($columns[$i]) && isset($columnSchemas[$columns[$i]])) { + if (isset($columns[$i], $columnSchemas[$columns[$i]]) && !is_array($value)) { $value = $columnSchemas[$columns[$i]]->dbTypecast($value); } if (is_string($value)) { diff --git a/framework/db/TableSchema.php b/framework/db/TableSchema.php index 311c68a1a1..d83bc6b0c4 100644 --- a/framework/db/TableSchema.php +++ b/framework/db/TableSchema.php @@ -87,9 +87,7 @@ class TableSchema extends Object */ public function fixPrimaryKey($keys) { - if (!is_array($keys)) { - $keys = [$keys]; - } + $keys = (array)$keys; $this->primaryKey = $keys; foreach ($this->columns as $column) { $column->isPrimaryKey = false; diff --git a/framework/helpers/BaseFileHelper.php b/framework/helpers/BaseFileHelper.php index a12101b81a..3a425c451c 100644 --- a/framework/helpers/BaseFileHelper.php +++ b/framework/helpers/BaseFileHelper.php @@ -305,7 +305,7 @@ class BaseFileHelper if (!is_dir($dir)) { return; } - if (!is_link($dir) || isset($options['traverseSymlinks']) && $options['traverseSymlinks']) { + if (isset($options['traverseSymlinks']) && $options['traverseSymlinks'] || !is_link($dir)) { if (!($handle = opendir($dir))) { return; } @@ -424,7 +424,7 @@ class BaseFileHelper } } - if (!is_dir($path) && !empty($options['only'])) { + if (!empty($options['only']) && !is_dir($path)) { if (($except = self::lastExcludeMatchingFromList($options['basePath'], $path, $options['only'])) !== null) { // don't check PATTERN_NEGATIVE since those entries are not prefixed with ! return true; diff --git a/framework/i18n/GettextMoFile.php b/framework/i18n/GettextMoFile.php index 300d486186..6946425150 100644 --- a/framework/i18n/GettextMoFile.php +++ b/framework/i18n/GettextMoFile.php @@ -109,8 +109,7 @@ class GettextMoFile extends GettextFile $separatorPosition = strpos($id, chr(4)); - if (($context && $separatorPosition !== false && strncmp($id, $context, $separatorPosition) === 0) || - (!$context && $separatorPosition === false)) { + if ((!$context && $separatorPosition === false) || ($context && $separatorPosition !== false && strncmp($id, $context, $separatorPosition) === 0)) { if ($separatorPosition !== false) { $id = substr($id, $separatorPosition+1); } diff --git a/framework/log/Logger.php b/framework/log/Logger.php index aeb5fef5b4..a6ef2ae671 100644 --- a/framework/log/Logger.php +++ b/framework/log/Logger.php @@ -209,7 +209,7 @@ class Logger extends Component $matched = empty($categories); foreach ($categories as $category) { $prefix = rtrim($category, '*'); - if (strpos($timing['category'], $prefix) === 0 && ($timing['category'] === $category || $prefix !== $category)) { + if (($timing['category'] === $category || $prefix !== $category) && strpos($timing['category'], $prefix) === 0) { $matched = true; break; } @@ -219,7 +219,7 @@ class Logger extends Component foreach ($excludeCategories as $category) { $prefix = rtrim($category, '*'); foreach ($timings as $i => $timing) { - if (strpos($timing['category'], $prefix) === 0 && ($timing['category'] === $category || $prefix !== $category)) { + if (($timing['category'] === $category || $prefix !== $category) && strpos($timing['category'], $prefix) === 0) { $matched = false; break; } diff --git a/framework/log/Target.php b/framework/log/Target.php index 8d4ca6083b..75179b0468 100644 --- a/framework/log/Target.php +++ b/framework/log/Target.php @@ -213,7 +213,7 @@ abstract class Target extends Component if ($matched) { foreach ($except as $category) { $prefix = rtrim($category, '*'); - if (strpos($message[2], $prefix) === 0 && ($message[2] === $category || $prefix !== $category)) { + if (($message[2] === $category || $prefix !== $category) && strpos($message[2], $prefix) === 0) { $matched = false; break; } diff --git a/framework/rbac/DbManager.php b/framework/rbac/DbManager.php index 056185f60e..11eed82c13 100644 --- a/framework/rbac/DbManager.php +++ b/framework/rbac/DbManager.php @@ -203,7 +203,7 @@ class DbManager extends BaseManager */ protected function updateItem($name, $item) { - if (!$this->supportsCascadeUpdate() && $item->name !== $name) { + if ($item->name !== $name && !$this->supportsCascadeUpdate()) { $this->db->createCommand() ->update($this->itemChildTable, ['parent' => $item->name], ['parent' => $name]) ->execute(); @@ -259,7 +259,7 @@ class DbManager extends BaseManager */ protected function updateRule($name, $rule) { - if (!$this->supportsCascadeUpdate() && $rule->name !== $name) { + if ($rule->name !== $name && !$this->supportsCascadeUpdate()) { $this->db->createCommand() ->update($this->itemTable, ['rule_name' => $rule->name], ['rule_name' => $name]) ->execute(); diff --git a/framework/views/errorHandler/callStackItem.php b/framework/views/errorHandler/callStackItem.php index e86f44f3b9..0f30012a1e 100644 --- a/framework/views/errorHandler/callStackItem.php +++ b/framework/views/errorHandler/callStackItem.php @@ -9,7 +9,7 @@ /* @var $end integer */ /* @var $handler \yii\web\ErrorHandler */ ?> -
  • diff --git a/framework/web/AssetManager.php b/framework/web/AssetManager.php index 876ff53447..a67ac93da1 100644 --- a/framework/web/AssetManager.php +++ b/framework/web/AssetManager.php @@ -470,7 +470,7 @@ class AssetManager extends Component if (!is_dir($dstDir)) { symlink($src, $dstDir); } - } elseif (!is_dir($dstDir) || !empty($options['forceCopy']) || (!isset($options['forceCopy']) && $this->forceCopy)) { + } elseif (!empty($options['forceCopy']) || ($this->forceCopy && !isset($options['forceCopy'])) || !is_dir($dstDir)) { $opts = [ 'dirMode' => $this->dirMode, 'fileMode' => $this->fileMode, diff --git a/framework/web/Controller.php b/framework/web/Controller.php index 7d3d67c1dd..21ec396588 100644 --- a/framework/web/Controller.php +++ b/framework/web/Controller.php @@ -73,7 +73,7 @@ class Controller extends \yii\base\Controller $name = $param->getName(); if (array_key_exists($name, $params)) { if ($param->isArray()) { - $args[] = $actionParams[$name] = is_array($params[$name]) ? $params[$name] : [$params[$name]]; + $args[] = $actionParams[$name] = (array)$params[$name]; } elseif (!is_array($params[$name])) { $args[] = $actionParams[$name] = $params[$name]; } else { diff --git a/framework/web/ErrorHandler.php b/framework/web/ErrorHandler.php index 06cac50ee4..9759a93def 100644 --- a/framework/web/ErrorHandler.php +++ b/framework/web/ErrorHandler.php @@ -84,7 +84,7 @@ class ErrorHandler extends \yii\base\ErrorHandler $response->data = $result; } } elseif ($response->format === Response::FORMAT_HTML) { - if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest' || YII_ENV_TEST) { + if (YII_ENV_TEST || isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest') { // AJAX request $response->data = '
    ' . $this->htmlEncode($this->convertExceptionToString($exception)) . '
    '; } else { diff --git a/framework/web/Session.php b/framework/web/Session.php index 424e2327c2..0187072931 100644 --- a/framework/web/Session.php +++ b/framework/web/Session.php @@ -205,7 +205,7 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co if ($this->_hasSessionId === null) { $name = $this->getName(); $request = Yii::$app->getRequest(); - if (ini_get('session.use_cookies') && !empty($_COOKIE[$name])) { + if (!empty($_COOKIE[$name]) && ini_get('session.use_cookies')) { $this->_hasSessionId = true; } elseif (!ini_get('session.use_only_cookies') && ini_get('session.use_trans_sid')) { $this->_hasSessionId = $request->get($name) !== null; diff --git a/framework/widgets/BaseListView.php b/framework/widgets/BaseListView.php index 40fe191eb6..5b752b8ad9 100644 --- a/framework/widgets/BaseListView.php +++ b/framework/widgets/BaseListView.php @@ -121,7 +121,7 @@ abstract class BaseListView extends Widget */ public function run() { - if ($this->dataProvider->getCount() > 0 || $this->showOnEmpty) { + if ($this->showOnEmpty || $this->dataProvider->getCount() > 0) { $content = preg_replace_callback("/{\\w+}/", function ($matches) { $content = $this->renderSection($matches[0]); diff --git a/framework/widgets/InputWidget.php b/framework/widgets/InputWidget.php index 50bcd9eb4c..fb37601ba5 100644 --- a/framework/widgets/InputWidget.php +++ b/framework/widgets/InputWidget.php @@ -20,6 +20,15 @@ use yii\helpers\Html; * or a name and a value. If the former, the name and the value will * be generated automatically. * + * Classes extending from this widget can be used in an [[yii\widgets\ActiveForm|ActiveForm]] + * using the [[yii\widgets\ActiveField::widget()|widget()]] method, for example like this: + * + * ```php + * field($model, 'from_date')->widget('WidgetClassName', [ + * // configure additional widget properties here + * ]) ?> + * ``` + * * @author Qiang Xue * @since 2.0 */ @@ -54,7 +63,7 @@ class InputWidget extends Widget */ public function init() { - if (!$this->hasModel() && $this->name === null) { + if ($this->name === null && !$this->hasModel()) { throw new InvalidConfigException("Either 'name', or 'model' and 'attribute' properties must be specified."); } if (!isset($this->options['id'])) { diff --git a/framework/widgets/MaskedInput.php b/framework/widgets/MaskedInput.php index 0d49a8271e..21ed7a36dc 100644 --- a/framework/widgets/MaskedInput.php +++ b/framework/widgets/MaskedInput.php @@ -29,6 +29,15 @@ use yii\web\View; * ]); * ``` * + * You can also use this widget in an [[yii\widgets\ActiveForm|ActiveForm]] using the [[yii\widgets\ActiveField::widget()|widget()]] + * method, for example like this: + * + * ```php + * field($model, 'from_date')->widget(\yii\jui\MaskedInput::classname(), [ + * 'mask' => '999-999-9999', + * ]) ?> + * ``` + * * The masked text field is implemented based on the * [jQuery input masked plugin](https://github.com/RobinHerbots/jquery.inputmask). * @@ -143,8 +152,8 @@ class MaskedInput extends InputWidget { $options = $this->clientOptions; foreach ($options as $key => $value) { - if (in_array($key, ['oncomplete', 'onincomplete', 'oncleared', 'onKeyUp', 'onKeyDown', 'onBeforeMask', - 'onBeforePaste', 'onUnMask', 'isComplete', 'determineActiveMasksetIndex']) && !$value instanceof JsExpression + if (!$value instanceof JsExpression && in_array($key, ['oncomplete', 'onincomplete', 'oncleared', 'onKeyUp', + 'onKeyDown', 'onBeforeMask', 'onBeforePaste', 'onUnMask', 'isComplete', 'determineActiveMasksetIndex']) ) { $options[$key] = new JsExpression($value); }