Browse Source

Merge branch 'master'

tags/2.0.0-beta
Alexander Makarov 11 years ago
parent
commit
372220450b
  1. 4
      build/controllers/PhpDocController.php
  2. 4
      extensions/apidoc/commands/ApiController.php
  3. 4
      extensions/apidoc/commands/GuideController.php
  4. 4
      extensions/apidoc/components/BaseController.php
  5. 4
      extensions/apidoc/models/TypeDoc.php
  6. 8
      extensions/apidoc/renderers/BaseRenderer.php
  7. 1
      extensions/apidoc/templates/bootstrap/layouts/api.php
  8. 2
      extensions/debug/panels/DbPanel.php
  9. 2
      extensions/debug/panels/ProfilingPanel.php
  10. 6
      extensions/elasticsearch/Command.php
  11. 2
      extensions/elasticsearch/QueryBuilder.php
  12. 7
      extensions/faker/FixtureController.php
  13. 2
      extensions/redis/ActiveQuery.php
  14. 6
      extensions/redis/ActiveRecord.php
  15. 2
      extensions/redis/Connection.php
  16. 35
      framework/BaseYii.php
  17. 5
      framework/CHANGELOG.md
  18. 8
      framework/base/Application.php
  19. 1
      framework/base/DynamicModel.php
  20. 4
      framework/base/ErrorHandler.php
  21. 1
      framework/base/View.php
  22. 1
      framework/caching/MemCache.php
  23. 4
      framework/console/Controller.php
  24. 9
      framework/console/controllers/FixtureController.php
  25. 9
      framework/console/controllers/MigrateController.php
  26. 1
      framework/data/ArrayDataProvider.php
  27. 16
      framework/db/ActiveQuery.php
  28. 27
      framework/db/ActiveRelationTrait.php
  29. 9
      framework/db/BaseActiveRecord.php
  30. 108
      framework/db/QueryBuilder.php
  31. 8
      framework/db/Schema.php
  32. 7
      framework/db/oci/QueryBuilder.php
  33. 20
      framework/grid/Column.php
  34. 41
      framework/grid/DataColumn.php
  35. 2
      framework/helpers/BaseArrayHelper.php
  36. 4
      framework/helpers/BaseFileHelper.php
  37. 2
      framework/helpers/BaseHtml.php
  38. 2
      framework/helpers/BaseMarkdown.php
  39. 2
      framework/helpers/BaseUrl.php
  40. 4
      framework/i18n/MessageFormatter.php
  41. 142
      framework/log/Dispatcher.php
  42. 79
      framework/log/Logger.php
  43. 3
      framework/rbac/PhpManager.php
  44. 8
      framework/requirements/views/console/index.php
  45. 11
      framework/requirements/views/web/index.php
  46. 4
      framework/rest/Controller.php
  47. 3
      framework/rest/RateLimiter.php
  48. 5
      framework/validators/FileValidator.php
  49. 6
      framework/web/AccessControl.php
  50. 4
      framework/web/Request.php
  51. 1
      framework/web/Response.php
  52. 13
      framework/web/UploadedFile.php
  53. 1
      framework/web/UrlRule.php
  54. 6
      framework/web/User.php
  55. 26
      framework/widgets/BaseListView.php
  56. 13
      tests/unit/framework/db/ActiveRecordTest.php
  57. 5
      tests/unit/framework/log/TargetTest.php

4
build/controllers/PhpDocController.php

@ -115,9 +115,9 @@ class PhpDocController extends Controller
/**
* @inheritdoc
*/
public function options($id)
public function options($actionId)
{
return array_merge(parent::options($id), ['updateFiles']);
return array_merge(parent::options($actionId), ['updateFiles']);
}
protected function updateClassPropertyDocs($file, $className, $propertyDoc)

4
extensions/apidoc/commands/ApiController.php

@ -159,8 +159,8 @@ class ApiController extends BaseController
/**
* @inheritdoc
*/
public function options($id)
public function options($actionId)
{
return array_merge(parent::options($id), ['template', 'guide']);
return array_merge(parent::options($actionId), ['template', 'guide']);
}
}

4
extensions/apidoc/commands/GuideController.php

@ -114,8 +114,8 @@ class GuideController extends BaseController
/**
* @inheritdoc
*/
public function options($id)
public function options($actionId)
{
return array_merge(parent::options($id), ['apiDocs']);
return array_merge(parent::options($actionId), ['apiDocs']);
}
}

4
extensions/apidoc/components/BaseController.php

@ -126,8 +126,8 @@ abstract class BaseController extends Controller
/**
* @inheritdoc
*/
public function options($id)
public function options($actionId)
{
return array_merge(parent::options($id), ['template', 'exclude']);
return array_merge(parent::options($actionId), ['template', 'exclude']);
}
}

4
extensions/apidoc/models/TypeDoc.php

@ -86,8 +86,8 @@ class TypeDoc extends BaseDoc
}
/**
* @param null $visibility
* @param null $definedBy
* @param string|null $visibility
* @param string|null $definedBy
* @return MethodDoc[]
*/
private function getFilteredMethods($visibility = null, $definedBy = null)

8
extensions/apidoc/renderers/BaseRenderer.php

@ -53,10 +53,10 @@ abstract class BaseRenderer extends Component
/**
* creates a link to a type (class, interface or trait)
* @param ClassDoc|InterfaceDoc|TraitDoc|ClassDoc[]|InterfaceDoc[]|TraitDoc[] $types
* @param string $title a title to be used for the link TODO check whether [[yii\...|Class]] is supported
* @param BaseDoc $context
* @param array $options additional HTML attributes for the link.
* @param ClassDoc|InterfaceDoc|TraitDoc|ClassDoc[]|InterfaceDoc[]|TraitDoc[]|string|string[] $types
* @param string $title a title to be used for the link TODO check whether [[yii\...|Class]] is supported
* @param BaseDoc $context
* @param array $options additional HTML attributes for the link.
* @return string
*/
public function createTypeLink($types, $context = null, $title = null, $options = [])

1
extensions/apidoc/templates/bootstrap/layouts/api.php vendored

@ -6,6 +6,7 @@ use yii\helpers\StringHelper;
/**
* @var yii\web\View $this
* @var array $types
* @var string $content
*/

2
extensions/debug/panels/DbPanel.php

@ -86,7 +86,7 @@ class DbPanel extends Panel
protected function calculateTimings()
{
if ($this->_timings === null) {
$this->_timings = Yii::$app->getLog()->calculateTimings($this->data['messages']);
$this->_timings = Yii::getLogger()->calculateTimings($this->data['messages']);
}
return $this->_timings;

2
extensions/debug/panels/ProfilingPanel.php

@ -85,7 +85,7 @@ class ProfilingPanel extends Panel
{
if ($this->_models === null) {
$this->_models = [];
$timings = Yii::$app->getLog()->calculateTimings($this->data['messages']);
$timings = Yii::getLogger()->calculateTimings($this->data['messages']);
foreach ($timings as $seq => $profileTiming) {
$this->_models[] = [

6
extensions/elasticsearch/Command.php

@ -95,7 +95,7 @@ class Command extends Component
*/
public function get($index, $type, $id, $options = [])
{
return $this->db->get([$index, $type, $id], $options, null);
return $this->db->get([$index, $type, $id], $options);
}
/**
@ -184,7 +184,7 @@ class Command extends Component
{
$body = $configuration !== null ? Json::encode($configuration) : null;
return $this->db->put([$index], $body);
return $this->db->put([$index], [], $body);
}
/**
@ -381,7 +381,7 @@ class Command extends Component
'mappings' => (object) $mappings,
]);
return $this->db->put(['_template', $name], $body);
return $this->db->put(['_template', $name], [], $body);
}

2
extensions/elasticsearch/QueryBuilder.php

@ -203,6 +203,8 @@ class QueryBuilder extends \yii\base\Object
return count($parts) === 1 ? $parts[0] : ['and' => $parts];
}
// TODO implement these methods correctly
private function buildNotCondition($operator, $operands, &$params)
{
if (count($operands) != 1) {

7
extensions/faker/FixtureController.php

@ -171,12 +171,11 @@ class FixtureController extends \yii\console\controllers\FixtureController
/**
* Returns the names of the global options for this command.
* @return array the names of the global options for this command.
* @inheritdoc
*/
public function options($id)
public function options($actionId)
{
return array_merge(parent::options($id), [
return array_merge(parent::options($actionId), [
'templatePath', 'language', 'fixtureDataPath'
]);
}

2
extensions/redis/ActiveQuery.php

@ -270,7 +270,7 @@ class ActiveQuery extends \yii\base\Component implements ActiveQueryInterface
/**
* Executes a script created by [[LuaScriptBuilder]]
* @param Connection $db the database connection used to execute the query.
* @param Connection|null $db the database connection used to execute the query.
* If this parameter is not given, the `db` application component will be used.
* @param string $type the type of the script to generate
* @param string $columnName

6
extensions/redis/ActiveRecord.php

@ -175,7 +175,7 @@ class ActiveRecord extends BaseActiveRecord
}
$db = static::getDb();
$n = 0;
foreach (static::fetchPks($condition) as $pk) {
foreach (self::fetchPks($condition) as $pk) {
$newPk = $pk;
$pk = static::buildKey($pk);
$key = static::keyPrefix() . ':a:' . $pk;
@ -228,7 +228,7 @@ class ActiveRecord extends BaseActiveRecord
}
$db = static::getDb();
$n = 0;
foreach (static::fetchPks($condition) as $pk) {
foreach (self::fetchPks($condition) as $pk) {
$key = static::keyPrefix() . ':a:' . static::buildKey($pk);
foreach ($counters as $attribute => $value) {
$db->executeCommand('HINCRBY', [$key, $attribute, $value]);
@ -257,7 +257,7 @@ class ActiveRecord extends BaseActiveRecord
{
$db = static::getDb();
$attributeKeys = [];
$pks = static::fetchPks($condition);
$pks = self::fetchPks($condition);
$db->executeCommand('MULTI');
foreach ($pks as $pk) {
$pk = static::buildKey($pk);

2
extensions/redis/Connection.php

@ -65,7 +65,6 @@ class Connection extends Component
* @var float timeout to use for redis socket when reading and writing data. If not set the php default value will be used.
*/
public $dataTimeout = null;
/**
* @var array List of available redis commands http://redis.io/commands
*/
@ -215,6 +214,7 @@ class Connection extends Component
*/
private $_socket;
/**
* Closes the connection when this component is being serialized.
* @return array

35
framework/BaseYii.php

@ -348,6 +348,29 @@ class BaseYii
}
}
private static $_logger;
/**
* @return Logger message logger
*/
public static function getLogger()
{
if (self::$_logger !== null) {
return self::$_logger;
} else {
return self::$_logger = static::createObject('yii\log\Logger');
}
}
/**
* Sets the logger object.
* @param Logger $logger the logger object.
*/
public static function setLogger($logger)
{
self::$_logger = $logger;
}
/**
* Logs a trace message.
* Trace messages are logged mainly for development purpose to see
@ -358,7 +381,7 @@ class BaseYii
public static function trace($message, $category = 'application')
{
if (YII_DEBUG) {
static::$app->getLog()->log($message, Logger::LEVEL_TRACE, $category);
static::getLogger()->log($message, Logger::LEVEL_TRACE, $category);
}
}
@ -371,7 +394,7 @@ class BaseYii
*/
public static function error($message, $category = 'application')
{
static::$app->getLog()->log($message, Logger::LEVEL_ERROR, $category);
static::getLogger()->log($message, Logger::LEVEL_ERROR, $category);
}
/**
@ -383,7 +406,7 @@ class BaseYii
*/
public static function warning($message, $category = 'application')
{
static::$app->getLog()->log($message, Logger::LEVEL_WARNING, $category);
static::getLogger()->log($message, Logger::LEVEL_WARNING, $category);
}
/**
@ -395,7 +418,7 @@ class BaseYii
*/
public static function info($message, $category = 'application')
{
static::$app->getLog()->log($message, Logger::LEVEL_INFO, $category);
static::getLogger()->log($message, Logger::LEVEL_INFO, $category);
}
/**
@ -417,7 +440,7 @@ class BaseYii
*/
public static function beginProfile($token, $category = 'application')
{
static::$app->getLog()->log($token, Logger::LEVEL_PROFILE_BEGIN, $category);
static::getLogger()->log($token, Logger::LEVEL_PROFILE_BEGIN, $category);
}
/**
@ -429,7 +452,7 @@ class BaseYii
*/
public static function endProfile($token, $category = 'application')
{
static::$app->getLog()->log($token, Logger::LEVEL_PROFILE_END, $category);
static::getLogger()->log($token, Logger::LEVEL_PROFILE_END, $category);
}
/**

5
framework/CHANGELOG.md

@ -62,6 +62,7 @@ Yii Framework 2 Change Log
- Bug #2760: Fixed GridView `filterUrl` parameters (qiangxue, AlexGx)
- Bug #2834: When overriding i18n translation sources from config using `app*` or `yii*` default `app` and `yii` sources were not removed (samdark)
- Bug #2848: Individual queries should be enclosed within parenthesis in a UNION query (qiangxue)
- Bug #2862: Using `DbCache` while enabling schema caching may cause infinite loops (qiangxue)
- Bug: Fixed `Call to a member function registerAssetFiles() on a non-object` in case of wrong `sourcePath` for an asset bundle (samdark)
- Bug: Fixed incorrect event name for `yii\jui\Spinner` (samdark)
- Bug: Json::encode() did not handle objects that implement JsonSerializable interface correctly (cebe)
@ -73,6 +74,7 @@ Yii Framework 2 Change Log
- Bug: Fixed `$model->load($data)` returned `true` if `$data` and `formName` were empty (samdark)
- Bug: Fixed issue with `ActiveRelationTrait` preventing `ActiveQuery` from clearing events and behaviors on clone (jom)
- Bug: `Query::queryScalar` wasn't making `SELECT DISTINCT` queries subqueries (jom)
- Bug: Fixed use `$files` instead of `self::$_files[$key]` to allow inheritance (pgaultier)
- Enh #46: Added Image extension based on [Imagine library](http://imagine.readthedocs.org) (tonydspaniard)
- Enh #364: Improve Inflector::slug with `intl` transliteration. Improved transliteration char map. (tonydspaniard)
- Enh #497: Removed `\yii\log\Target::logUser` and added `\yii\log\Target::prefix` to support customizing message prefix (qiangxue)
@ -177,6 +179,7 @@ Yii Framework 2 Change Log
- Enh: LinkPager can now register relational link tags in the html header for prev, next, first and last page (cebe)
- Enh: Added `yii\web\UrlRuleInterface` and `yii\web\CompositeUrlRule` (qiangxue)
- Enh: Added `yii\web\Request::getAuthUser()` and `getAuthPassword()` (qiangxue)
- Enh: Added summaryOptions and emptyTextOptions to BaseListView (johonunu)
- Chg #47: Changed Markdown library to cebe/markdown and adjusted Markdown helper API (cebe)
- Chg #735: Added back `ActiveField::hiddenInput()` (qiangxue)
- Chg #1186: Changed `Sort` to use comma to separate multiple sort fields and use negative sign to indicate descending sort (qiangxue)
@ -255,6 +258,8 @@ Yii Framework 2 Change Log
- Chg: `getComponent()` and `setComponent()` in `Application` and `Module` are renamed to `get()` and `set()` respectively. (qiangxue)
- Chg: The signature of `Yii::createObject()` is changed. Constructor parameters must be passed as the second parameter. (qiangxue)
- Chg: `Yii::$objectConfig` is removed. You should use `Yii::$container->set()` to configure default settings of classes. (qiangxue)
- Chg: Removed `yii\grid\Column::getDataCellContent()` and renamed `yii\grid\DataColumn::getDataCellContent()` to `yii\grid\DataColumn::getDataCellValue()` (cebe)
- Chg: `yii\log\Logger` is split into `yii\log\Logger` and `yii\log\Dispatcher`. (qiangxue)
- New #66: [Auth client library](https://github.com/yiisoft/yii2-authclient) OpenId, OAuth1, OAuth2 clients (klimov-paul)
- New #503: Added `yii\di\Container` and `yii\di\ServiceLocator` (qiangxue)
- New #706: Added `yii\widgets\Pjax` and enhanced `GridView` to work with `Pjax` to support AJAX-update (qiangxue)

8
framework/base/Application.php

@ -23,7 +23,7 @@ use yii\web\HttpException;
* @property ErrorHandler $errorHandler The error handler application component. This property is read-only.
* @property \yii\base\Formatter $formatter The formatter application component. This property is read-only.
* @property \yii\i18n\I18N $i18n The internationalization component. This property is read-only.
* @property \yii\log\Logger $log The log component. This property is read-only.
* @property \yii\log\Dispatcher $log The log dispatcher component. This property is read-only.
* @property \yii\mail\MailerInterface $mail The mailer interface. This property is read-only.
* @property \yii\web\Request|\yii\console\Request $request The request component. This property is read-only.
* @property string $runtimePath The directory that stores runtime files. Defaults to the "runtime"
@ -415,8 +415,8 @@ abstract class Application extends Module
}
/**
* Returns the log component.
* @return \yii\log\Logger the log component
* Returns the log dispatcher component.
* @return \yii\log\Dispatcher the log dispatcher component
*/
public function getLog()
{
@ -512,7 +512,7 @@ abstract class Application extends Module
public function coreComponents()
{
return [
'log' => ['class' => 'yii\log\Logger'],
'log' => ['class' => 'yii\log\Dispatcher'],
'errorHandler' => ['class' => 'yii\base\ErrorHandler'],
'formatter' => ['class' => 'yii\base\Formatter'],
'i18n' => ['class' => 'yii\i18n\I18N'],

1
framework/base/DynamicModel.php

@ -71,6 +71,7 @@ class DynamicModel extends Model
$this->_attributes[$name] = $value;
}
}
parent::__construct($config);
}
/**

4
framework/base/ErrorHandler.php

@ -89,7 +89,6 @@ class ErrorHandler extends Component
if (!YII_ENV_TEST) {
exit(1);
}
return;
}
@ -145,6 +144,9 @@ class ErrorHandler extends Component
'message' => $exception->getMessage(),
'code' => $exception->getCode(),
];
if (YII_DEBUG) {
$array['stack-trace'] = explode("\n", $exception->getTraceAsString());
}
if ($exception instanceof HttpException) {
$array['status'] = $exception->statusCode;
}

1
framework/base/View.php

@ -141,7 +141,6 @@ class View extends Component
public function render($view, $params = [], $context = null)
{
$viewFile = $this->findViewFile($view, $context);
return $this->renderFile($viewFile, $params, $context);
}

1
framework/caching/MemCache.php

@ -78,6 +78,7 @@ class MemCache extends Cache
*/
private $_servers = [];
/**
* Initializes this application component.
* It creates the memcache instance and adds memcache servers.

4
framework/console/Controller.php

@ -264,10 +264,10 @@ class Controller extends \yii\base\Controller
* Note that the values setting via options are not available
* until [[beforeAction()]] is being called.
*
* @param string $id action name
* @param string $actionId the action id of the current request
* @return array the names of the options valid for the action
*/
public function options($id)
public function options($actionId)
{
// $id might be used in subclass to provide options specific to action id
return ['color', 'interactive'];

9
framework/console/controllers/FixtureController.php

@ -33,7 +33,6 @@ use yii\test\FixtureTrait;
*/
class FixtureController extends Controller
{
use FixtureTrait;
/**
@ -57,13 +56,13 @@ class FixtureController extends Controller
'yii\test\InitDb',
];
/**
* Returns the names of the global options for this command.
* @return array the names of the global options for this command.
* @inheritdoc
*/
public function options($id)
public function options($actionId)
{
return array_merge(parent::options($id), [
return array_merge(parent::options($actionId), [
'namespace', 'globalFixtures'
]);
}

9
framework/console/controllers/MigrateController.php

@ -92,14 +92,13 @@ class MigrateController extends Controller
public $db = 'db';
/**
* Returns the names of the global options for this command.
* @return array the names of the global options for this command.
* @inheritdoc
*/
public function options($id)
public function options($actionId)
{
return array_merge(parent::options($id),
return array_merge(parent::options($actionId),
['migrationPath', 'migrationTable', 'db'], // global for all actions
($id == 'create') ? ['templateFile'] : [] // action create
($actionId == 'create') ? ['templateFile'] : [] // action create
);
}

1
framework/data/ArrayDataProvider.php

@ -64,6 +64,7 @@ class ArrayDataProvider extends BaseDataProvider
*/
public $allModels;
/**
* @inheritdoc
*/

16
framework/db/ActiveQuery.php

@ -91,6 +91,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface
*/
public $joinWith;
/**
* Executes query and returns all results as an array.
* @param Connection $db the DB connection used to create the DB command.
@ -232,7 +233,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface
/**
* Creates a DB command that can be used to execute this query.
* @param Connection $db the DB connection used to create the DB command.
* @param Connection|null $db the DB connection used to create the DB command.
* If null, the DB connection returned by [[modelClass]] will be used.
* @return Command the created DB command instance.
*/
@ -260,7 +261,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface
/**
* Creates a command for lazy loading of a relation.
* @param Connection $db the DB connection used to create the DB command.
* @param Connection|null $db the DB connection used to create the DB command.
* @return Command the created DB command instance.
*/
private function createRelationalCommand($db = null)
@ -348,6 +349,9 @@ class ActiveQuery extends Query implements ActiveQueryInterface
private function buildJoinWith()
{
$join = $this->join;
$this->join = [];
foreach ($this->joinWith as $config) {
list ($with, $eagerLoading, $joinType) = $config;
$this->joinWithRelations(new $this->modelClass, $with, $joinType);
@ -368,6 +372,12 @@ class ActiveQuery extends Query implements ActiveQueryInterface
$this->with($with);
}
if (!empty($join)) {
// append explicit join to joinWith()
// https://github.com/yiisoft/yii2/issues/2880
$this->join = empty($this->join) ? $join : array_merge($this->join, $join);
}
}
/**
@ -524,7 +534,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface
} else {
$on = $child->on;
}
$this->join($joinType, $childTable, $on);
$this->join($joinType, empty($child->from) ? $childTable : $child->from, $on);
if (!empty($child->where)) {
$this->andWhere($child->where);

27
framework/db/ActiveRelationTrait.php

@ -356,12 +356,39 @@ trait ActiveRelationTrait
return $buckets;
}
private function prefixKeyColumns($attributes)
{
if ($this instanceof ActiveQuery && (!empty($this->join) || !empty($this->joinWith))) {
if (empty($this->from)) {
/** @var ActiveRecord $modelClass */
$modelClass = $this->modelClass;
$alias = $modelClass::tableName();
} else {
foreach ($this->from as $alias => $table) {
if (!is_string($alias)) {
$alias = $table;
}
break;
}
}
if (isset($alias)) {
foreach ($attributes as $i => $attribute) {
$attributes[$i] = "$alias.$attribute";
}
}
}
return $attributes;
}
/**
* @param array $models
*/
private function filterByModels($models)
{
$attributes = array_keys($this->link);
$attributes = $this->prefixKeyColumns($attributes);
$values = [];
if (count($attributes) === 1) {
// single key

9
framework/db/BaseActiveRecord.php

@ -81,7 +81,8 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
*/
private $_attributes = [];
/**
* @var array old attribute values indexed by attribute names.
* @var array|null old attribute values indexed by attribute names.
* This is `null` if the record [[isNewRecord|is new]].
*/
private $_oldAttributes;
/**
@ -475,7 +476,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
/**
* Sets the old attribute values.
* All existing old attribute values will be discarded.
* @param array $values old attribute values to be set.
* @param array|null $values old attribute values to be set.
*/
public function setOldAttributes($values)
{
@ -1304,8 +1305,8 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
/**
* @param array $link
* @param BaseActiveRecord $foreignModel
* @param BaseActiveRecord $primaryModel
* @param ActiveRecordInterface $foreignModel
* @param ActiveRecordInterface $primaryModel
* @throws InvalidCallException
*/
private function bindModels($link, $foreignModel, $primaryModel)

108
framework/db/QueryBuilder.php

@ -65,18 +65,7 @@ class QueryBuilder extends \yii\base\Object
public function build($query, $params = [])
{
$params = empty($params) ? $query->params : array_merge($params, $query->params);
$select = $query->select;
$from = $query->from;
if ($from === null && $query instanceof ActiveQuery) {
/** @var ActiveRecord $modelClass */
$modelClass = $query->modelClass;
$tableName = $modelClass::tableName();
$from = [$tableName];
if ($select === null && !empty($query->join)) {
$select = ["$tableName.*"];
}
}
list ($select, $from) = $this->adjustSelectFrom($query);
$clauses = [
$this->buildSelect($select, $params, $query->distinct, $query->selectOption),
@ -100,6 +89,44 @@ class QueryBuilder extends \yii\base\Object
}
/**
* Adjusts the select and from parts of the query when it is an ActiveQuery.
* When ActiveQuery does not specify "from", or if it is a join query without explicit "select",
* certain adjustments need to be made. This method is put here so that QueryBuilder can
* support sub-queries.
* @param Query $query
* @return array the select and from parts.
*/
protected function adjustSelectFrom($query)
{
$select = $query->select;
$from = $query->from;
if ($query instanceof ActiveQuery && (empty($select) || empty($from))) {
/** @var ActiveRecord $modelClass */
$modelClass = $query->modelClass;
$tableName = $modelClass::tableName();
if (empty($from)) {
$from = [$tableName];
}
if (empty($select) && !empty($query->join)) {
foreach ((array)$from as $alias => $table) {
if (is_string($alias)) {
$select = ["$alias.*"];
} elseif (is_string($table)) {
if (preg_match('/^(.*?)\s+({{\w+}}|\w+)$/', $table, $matches)) {
$alias = $matches[2];
} else {
$alias = $tableName;
}
$select = ["$alias.*"];
}
break;
}
}
}
return [$select, $from];
}
/**
* Creates an INSERT SQL statement.
* For example,
*
@ -642,23 +669,7 @@ class QueryBuilder extends \yii\base\Object
return '';
}
foreach ($tables as $i => $table) {
if ($table instanceof Query) {
list($sql, $params) = $this->build($table, $params);
$tables[$i] = "($sql) " . $this->db->quoteTableName($i);
} elseif (is_string($i)) {
if (strpos($table, '(') === false) {
$table = $this->db->quoteTableName($table);
}
$tables[$i] = "$table " . $this->db->quoteTableName($i);
} elseif (strpos($table, '(') === false) {
if (preg_match('/^(.*?)(?i:\s+as|)\s+([^ ]+)$/', $table, $matches)) { // with alias
$tables[$i] = $this->db->quoteTableName($matches[1]) . ' ' . $this->db->quoteTableName($matches[2]);
} else {
$tables[$i] = $this->db->quoteTableName($table);
}
}
}
$tables = $this->quoteTableNames($tables, $params);
return 'FROM ' . implode(', ', $tables);
}
@ -681,21 +692,8 @@ class QueryBuilder extends \yii\base\Object
}
// 0:join type, 1:join table, 2:on-condition (optional)
list ($joinType, $table) = $join;
if (is_array($table)) {
$query = reset($table);
if (!$query instanceof Query) {
throw new Exception('The sub-query for join must be an instance of yii\db\Query.');
}
$alias = $this->db->quoteTableName(key($table));
list ($sql, $params) = $this->build($query, $params);
$table = "($sql) $alias";
} elseif (strpos($table, '(') === false) {
if (preg_match('/^(.*?)(?i:\s+as|)\s+([^ ]+)$/', $table, $matches)) { // with alias
$table = $this->db->quoteTableName($matches[1]) . ' ' . $this->db->quoteTableName($matches[2]);
} else {
$table = $this->db->quoteTableName($table);
}
}
$tables = $this->quoteTableNames((array)$table, $params);
$table = reset($tables);
$joins[$i] = "$joinType $table";
if (isset($join[2])) {
$condition = $this->buildCondition($join[2], $params);
@ -708,6 +706,28 @@ class QueryBuilder extends \yii\base\Object
return implode($this->separator, $joins);
}
private function quoteTableNames($tables, &$params)
{
foreach ($tables as $i => $table) {
if ($table instanceof Query) {
list($sql, $params) = $this->build($table, $params);
$tables[$i] = "($sql) " . $this->db->quoteTableName($i);
} elseif (is_string($i)) {
if (strpos($table, '(') === false) {
$table = $this->db->quoteTableName($table);
}
$tables[$i] = "$table " . $this->db->quoteTableName($i);
} elseif (strpos($table, '(') === false) {
if (preg_match('/^(.*?)(?i:\s+as|)\s+([^ ]+)$/', $table, $matches)) { // with alias
$tables[$i] = $this->db->quoteTableName($matches[1]) . ' ' . $this->db->quoteTableName($matches[2]);
} else {
$tables[$i] = $this->db->quoteTableName($table);
}
}
}
return $tables;
}
/**
* @param string|array $condition
* @param array $params the binding parameters to be populated

8
framework/db/Schema.php

@ -87,7 +87,7 @@ abstract class Schema extends Object
*/
public function getTableSchema($name, $refresh = false)
{
if (isset($this->_tables[$name]) && !$refresh) {
if (array_key_exists($name, $this->_tables) && !$refresh) {
return $this->_tables[$name];
}
@ -100,15 +100,17 @@ abstract class Schema extends Object
if ($cache instanceof Cache) {
$key = $this->getCacheKey($name);
if ($refresh || ($table = $cache->get($key)) === false) {
$table = $this->loadTableSchema($realName);
$this->_tables[$name] = $table = $this->loadTableSchema($realName);
if ($table !== null) {
$cache->set($key, $table, $db->schemaCacheDuration, new GroupDependency([
'group' => $this->getCacheGroup(),
]));
}
} else {
$this->_tables[$name] = $table;
}
return $this->_tables[$name] = $table;
return $this->_tables[$name];
}
}

7
framework/db/oci/QueryBuilder.php

@ -8,6 +8,8 @@
namespace yii\db\oci;
use yii\base\InvalidParamException;
use yii\db\ActiveQuery;
use yii\db\ActiveRecord;
/**
* QueryBuilder is the query builder for Oracle databases.
@ -26,10 +28,11 @@ class QueryBuilder extends \yii\db\QueryBuilder
public function build($query, $params = [])
{
$params = empty($params) ? $query->params : array_merge($params, $query->params);
list ($select, $from) = $this->adjustSelectFrom($query);
$clauses = [
$this->buildSelect($query->select, $params, $query->distinct, $query->selectOption),
$this->buildFrom($query->from, $params),
$this->buildSelect($select, $params, $query->distinct, $query->selectOption),
$this->buildFrom($from, $params),
$this->buildJoin($query->join, $params),
$this->buildWhere($query->where, $params),
$this->buildGroupBy($query->groupBy),

20
framework/grid/Column.php

@ -99,7 +99,6 @@ class Column extends Object
} else {
$options = $this->contentOptions;
}
return Html::tag('td', $this->renderDataCellContent($model, $key, $index), $options);
}
@ -134,35 +133,22 @@ class Column extends Object
}
/**
* Returns the raw data cell content.
* This method is called by [[renderDataCellContent()]] when rendering the content of a data cell.
* Renders the data cell content.
* @param mixed $model the data model
* @param mixed $key the key associated with the data model
* @param integer $index the zero-based index of the data model among the models array returned by [[GridView::dataProvider]].
* @return string the rendering result
*/
protected function getDataCellContent($model, $key, $index)
protected function renderDataCellContent($model, $key, $index)
{
if ($this->content !== null) {
return call_user_func($this->content, $model, $key, $index, $this);
} else {
return null;
return $this->grid->emptyCell;
}
}
/**
* Renders the data cell content.
* @param mixed $model the data model
* @param mixed $key the key associated with the data model
* @param integer $index the zero-based index of the data model among the models array returned by [[GridView::dataProvider]].
* @return string the rendering result
*/
protected function renderDataCellContent($model, $key, $index)
{
return $this->content !== null ? $this->getDataCellContent($model, $key, $index) : $this->grid->emptyCell;
}
/**
* Renders the filter cell content.
* The default implementation simply renders a space.
* This method may be overridden to customize the rendering of the filter cell (if any).

41
framework/grid/DataColumn.php

@ -17,7 +17,17 @@ use yii\helpers\Inflector;
/**
* DataColumn is the default column type for the [[GridView]] widget.
*
* It is used to show data columns and allows sorting them.
* It is used to show data columns and allows [[enableSorting|sorting]] and [[filter|filtering]] them.
*
* A simple data column definition refers to an attribute in the data model of the
* GridView's data provider. The name of the attribute is specified by [[attribute]].
*
* By setting [[value]] and [[label]], the header and cell content can be customized.
*
* A data column differentiates between the [[getDataCellValue|data cell value]] and the
* [[renderDataCellContent|data cell content]]. The cell value is an un-formatted value that
* may be used for calculation, while the actual cell content is a [[format|formatted]] version of that
* value which may contain HTML markup.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
@ -40,10 +50,13 @@ class DataColumn extends Column
*/
public $label;
/**
* @var string|\Closure the attribute name to be displayed in this column or an anonymous function that returns
* the value to be displayed for every data model.
* @var string|\Closure an anonymous function that returns the value to be displayed for every data model.
* The signature of this function is `function ($model, $index, $widget)`.
* If this is not set, `$model[$attribute]` will be used to obtain the value.
*
* You may also set this property to a string representing the attribute name to be displayed in this column.
* This can be used when the attribute to be displayed is different from the [[attribute]] that is used for
* sorting and filtering.
*/
public $value;
/**
@ -133,7 +146,6 @@ class DataColumn extends Column
{
if (is_array($this->filter)) {
$options = array_merge(['prompt' => ''], $this->filterInputOptions);
return Html::activeDropDownList($this->grid->filterModel, $this->attribute, $this->filter, $options);
} else {
return Html::activeTextInput($this->grid->filterModel, $this->attribute, $this->filterInputOptions);
@ -146,21 +158,18 @@ class DataColumn extends Column
/**
* @inheritdoc
*/
protected function getDataCellContent($model, $key, $index)
protected function getDataCellValue($model, $key, $index)
{
if ($this->value !== null) {
if (is_string($this->value)) {
$value = ArrayHelper::getValue($model, $this->value);
return ArrayHelper::getValue($model, $this->value);
} else {
$value = call_user_func($this->value, $model, $index, $this);
return call_user_func($this->value, $model, $index, $this);
}
} elseif ($this->content === null && $this->attribute !== null) {
$value = ArrayHelper::getValue($model, $this->attribute);
} else {
return parent::getDataCellContent($model, $key, $index);
} elseif ($this->attribute !== null) {
return ArrayHelper::getValue($model, $this->attribute);
}
return $value;
return null;
}
/**
@ -168,6 +177,10 @@ class DataColumn extends Column
*/
protected function renderDataCellContent($model, $key, $index)
{
return $this->grid->formatter->format($this->getDataCellContent($model, $key, $index), $this->format);
if ($this->content === null) {
return $this->grid->formatter->format($this->getDataCellValue($model, $key, $index), $this->format);
} else {
return parent::renderDataCellContent($model, $key, $index);
}
}
}

2
framework/helpers/BaseArrayHelper.php

@ -62,7 +62,7 @@ class BaseArrayHelper
if ($recursive) {
foreach ($object as $key => $value) {
if (is_array($value) || is_object($value)) {
$object[$key] = static::toArray($value, true);
$object[$key] = static::toArray($value, $properties, true);
}
}
}

4
framework/helpers/BaseFileHelper.php

@ -285,14 +285,14 @@ class BaseFileHelper
if (isset($options['except'])) {
foreach ($options['except'] as $key => $value) {
if (is_string($value)) {
$options['except'][$key] = static::parseExcludePattern($value);
$options['except'][$key] = self::parseExcludePattern($value);
}
}
}
if (isset($options['only'])) {
foreach ($options['only'] as $key => $value) {
if (is_string($value)) {
$options['only'][$key] = static::parseExcludePattern($value);
$options['only'][$key] = self::parseExcludePattern($value);
}
}
}

2
framework/helpers/BaseHtml.php

@ -342,7 +342,7 @@ class BaseHtml
/**
* Generates an image tag.
* @param string $src the image URL. This parameter will be processed by [[yii\helpers\Url::to()]].
* @param array|string $src the image URL. This parameter will be processed by [[yii\helpers\Url::to()]].
* @param array $options the tag options in terms of name-value pairs. These will be rendered as
* the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
* If a value is null, the corresponding attribute will not be rendered.

2
framework/helpers/BaseMarkdown.php

@ -82,7 +82,7 @@ class BaseMarkdown
* @return \cebe\markdown\Parser
* @throws \yii\base\InvalidParamException when an undefined flavor is given.
*/
private static function getParser($flavor)
protected static function getParser($flavor)
{
/** @var \cebe\markdown\Markdown $parser */
if (!isset(static::$flavors[$flavor])) {

2
framework/helpers/BaseUrl.php

@ -108,7 +108,7 @@ class BaseUrl
* @return string normalized route suitable for UrlManager
* @throws InvalidParamException a relative route is given while there is no active controller
*/
private static function normalizeRoute($route)
protected static function normalizeRoute($route)
{
$route = (string) $route;
if (strncmp($route, '/', 1) === 0) {

4
framework/i18n/MessageFormatter.php

@ -220,7 +220,9 @@ class MessageFormatter extends Component
if (!isset($token[2])) {
return false;
}
$subtokens = self::tokenizePattern($token[2]);
if (($subtokens = self::tokenizePattern($token[2])) === false) {
return false;
}
$c = count($subtokens);
for ($k = 0; $k + 1 < $c; $k++) {
if (is_array($subtokens[$k]) || !is_array($subtokens[++$k])) {

142
framework/log/Dispatcher.php

@ -0,0 +1,142 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\log;
use Yii;
use yii\base\Component;
/**
* Dispatcher manages a set of [[Target|log targets]].
*
* Dispatcher implements [[dispatch()]] that forwards the log messages from [[Logger]] to
* the registered log [[targets]].
*
* Dispatcher is registered as a core application component and can be accessed using `Yii::$app->log`.
*
* You may configure the targets in application configuration, like the following:
*
* ~~~
* [
* 'components' => [
* 'log' => [
* 'targets' => [
* 'file' => [
* 'class' => 'yii\log\FileTarget',
* 'levels' => ['trace', 'info'],
* 'categories' => ['yii\*'],
* ],
* 'email' => [
* 'class' => 'yii\log\EmailTarget',
* 'levels' => ['error', 'warning'],
* 'message' => [
* 'to' => 'admin@example.com',
* ],
* ],
* ],
* ],
* ],
* ]
* ~~~
*
* Each log target can have a name and can be referenced via the [[targets]] property
* as follows:
*
* ~~~
* Yii::$app->log->targets['file']->enabled = false;
* ~~~
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Dispatcher extends Component
{
/**
* @var array|Target[] the log targets. Each array element represents a single [[Target|log target]] instance
* or the configuration for creating the log target instance.
*/
public $targets = [];
/**
* @var Logger the logger. If not set, [[\Yii::getLogger()]] will be used.
*/
public $logger;
/**
* Initializes the logger by registering [[flush()]] as a shutdown function.
*/
public function init()
{
parent::init();
foreach ($this->targets as $name => $target) {
if (!$target instanceof Target) {
$this->targets[$name] = Yii::createObject($target);
}
}
if ($this->logger === null) {
$this->logger = Yii::getLogger();
}
$this->logger->dispatcher = $this;
}
/**
* @return integer how many application call stacks should be logged together with each message.
* This method returns the value of [[Logger::traceLevel]]. Defaults to 0.
*/
public function getTraceLevel()
{
return $this->logger->traceLevel;
}
/**
* @param integer $value how many application call stacks should be logged together with each message.
* This method will set the value of [[Logger::traceLevel]]. If the value is greater than 0,
* at most that number of call stacks will be logged. Note that only application call stacks are counted.
* Defaults to 0.
*/
public function setTraceLevel($value)
{
$this->logger->traceLevel = $value;
}
/**
* @return integer how many messages should be logged before they are sent to targets.
* This method returns the value of [[Logger::flushInterval]].
*/
public function getFlushInterval()
{
return $this->logger->flushInterval;
}
/**
* @param integer $value how many messages should be logged before they are sent to targets.
* This method will set the value of [[Logger::flushInterval]].
* Defaults to 1000, meaning the [[Logger::flush()]] method will be invoked once every 1000 messages logged.
* Set this property to be 0 if you don't want to flush messages until the application terminates.
* This property mainly affects how much memory will be taken by the logged messages.
* A smaller value means less memory, but will increase the execution time due to the overhead of [[Logger::flush()]].
*/
public function setFlushInterval($value)
{
$this->logger->flushInterval = $value;
}
/**
* Dispatches the logged messages to [[targets]].
* @param array $messages the logged messages
* @param boolean $final whether this method is called at the end of the current application
*/
public function dispatch($messages, $final)
{
foreach ($this->targets as $target) {
if ($target->enabled) {
$target->collect($messages, $final);
}
}
}
}

79
framework/log/Logger.php

@ -11,11 +11,11 @@ use Yii;
use yii\base\Component;
/**
* Logger records logged messages in memory and sends them to different targets as needed.
* Logger records logged messages in memory and sends them to different targets if [[dispatcher]] is set.
*
* Logger is registered as a core application component and can be accessed using `Yii::$app->log`.
* You can call the method [[log()]] to record a single log message. For convenience, a set of shortcut
* methods are provided for logging messages of various severity levels via the [[Yii]] class:
* Logger can be accessed via `Yii::getLogger()`. You can call the method [[log()]] to record a single log message.
* For convenience, a set of shortcut methods are provided for logging messages of various severity levels
* via the [[Yii]] class:
*
* - [[Yii::trace()]]
* - [[Yii::error()]]
@ -24,43 +24,8 @@ use yii\base\Component;
* - [[Yii::beginProfile()]]
* - [[Yii::endProfile()]]
*
* When enough messages are accumulated in the logger, or when the current request finishes,
* the logged messages will be sent to different [[targets]], such as log files, emails.
*
* You may configure the targets in application configuration, like the following:
*
* ~~~
* [
* 'components' => [
* 'log' => [
* 'targets' => [
* 'file' => [
* 'class' => 'yii\log\FileTarget',
* 'levels' => ['trace', 'info'],
* 'categories' => ['yii\*'],
* ],
* 'email' => [
* 'class' => 'yii\log\EmailTarget',
* 'levels' => ['error', 'warning'],
* 'message' => [
* 'to' => 'admin@example.com',
* ],
* ],
* ],
* ],
* ],
* ]
* ~~~
*
* Each log target can have a name and can be referenced via the [[targets]] property
* as follows:
*
* ~~~
* Yii::$app->log->targets['file']->enabled = false;
* ~~~
*
* When the application ends or [[flushInterval]] is reached, Logger will call [[flush()]]
* to send logged messages to different log targets, such as file, email, Web.
* to send logged messages to different log targets, such as file, email, Web, with the help of [[dispatcher]].
*
* @property array $dbProfiling The first element indicates the number of SQL statements executed, and the
* second element the total time spent in SQL execution. This property is read-only.
@ -125,16 +90,6 @@ class Logger extends Component
*/
public $messages = [];
/**
* @var array debug data. This property stores various types of debug data reported at
* different instrument places.
*/
public $data = [];
/**
* @var array|Target[] the log targets. Each array element represents a single [[Target|log target]] instance
* or the configuration for creating the log target instance.
*/
public $targets = [];
/**
* @var integer how many messages should be logged before they are flushed from memory and sent to targets.
* Defaults to 1000, meaning the [[flush]] method will be invoked once every 1000 messages logged.
* Set this property to be 0 if you don't want to flush messages until the application terminates.
@ -146,10 +101,13 @@ class Logger extends Component
* @var integer how much call stack information (file name and line number) should be logged for each message.
* If it is greater than 0, at most that number of call stacks will be logged. Note that only application
* call stacks are counted.
*
* If not set, it will default to 3 when `YII_ENV` is set as "dev", and 0 otherwise.
*/
public $traceLevel;
public $traceLevel = 0;
/**
* @var Dispatcher the message dispatcher
*/
public $dispatcher;
/**
* Initializes the logger by registering [[flush()]] as a shutdown function.
@ -157,14 +115,6 @@ class Logger extends Component
public function init()
{
parent::init();
if ($this->traceLevel === null) {
$this->traceLevel = YII_ENV_DEV ? 3 : 0;
}
foreach ($this->targets as $name => $target) {
if (!$target instanceof Target) {
$this->targets[$name] = Yii::createObject($target);
}
}
register_shutdown_function([$this, 'flush'], true);
}
@ -208,11 +158,8 @@ class Logger extends Component
*/
public function flush($final = false)
{
/** @var Target $target */
foreach ($this->targets as $target) {
if ($target->enabled) {
$target->collect($this->messages, $final);
}
if ($this->dispatcher instanceof Dispatcher) {
$this->dispatcher->dispatch($this->messages, $final);
}
$this->messages = [];
}

3
framework/rbac/PhpManager.php

@ -44,6 +44,7 @@ class PhpManager extends Manager
private $_children = []; // itemName, childName => child
private $_assignments = []; // userId, itemName => assignment
/**
* Initializes the application component.
* This method overrides parent implementation by loading the authorization data
@ -158,7 +159,7 @@ class PhpManager extends Manager
/**
* Returns the children of the specified item.
* @param mixed $names the parent item name. This can be either a string or an array.
* @param string|array $names the parent item name. This can be either a string or an array.
* The latter represents a list of item names.
* @return Item[] all child items of the parent
*/

8
framework/requirements/views/console/index.php

@ -1,7 +1,9 @@
<?php
/* @var YiiRequirementChecker $this */
/* @var array $summary */
/* @var array[] $requirements */
/**
* @var YiiRequirementChecker $this
* @var array $summary
* @var array[] $requirements
*/
echo "\nYii Application Requirement Checker\n\n";

11
framework/requirements/views/web/index.php

@ -1,9 +1,10 @@
<?php
/* @var YiiRequirementChecker $this */
/* @var array $summary */
/* @var array[] $requirements */
?>
<!DOCTYPE html>
/**
* @var YiiRequirementChecker $this
* @var array $summary
* @var array[] $requirements
*/
?><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>

4
framework/rest/Controller.php

@ -105,10 +105,9 @@ class Controller extends \yii\web\Controller
*/
public function beforeAction($action)
{
$this->authenticate($action);
if (parent::beforeAction($action)) {
$this->authenticate($action);
$this->checkRateLimit($action);
return true;
} else {
return false;
@ -121,7 +120,6 @@ class Controller extends \yii\web\Controller
public function afterAction($action, $result)
{
$result = parent::afterAction($action, $result);
return $this->serializeData($result);
}

3
framework/rest/RateLimiter.php

@ -8,7 +8,6 @@
namespace yii\rest;
use yii\base\Component;
use yii\base\Action;
use yii\web\Request;
use yii\web\Response;
use yii\web\TooManyRequestsHttpException;
@ -37,7 +36,7 @@ class RateLimiter extends Component
* @param RateLimitInterface $user the current user
* @param Request $request
* @param Response $response
* @param Action $action the action to be executed
* @param \yii\base\Action $action the action to be executed
* @throws TooManyRequestsHttpException if rate limit exceeds
*/
public function check($user, $request, $response, $action)

5
framework/validators/FileValidator.php

@ -232,9 +232,8 @@ class FileValidator extends Validator
*/
public function isEmpty($value, $trim = false)
{
$value = is_array($value) && !empty($value) ? $value[0] : $value;
return !$value instanceof UploadedFile || $value->error == UPLOAD_ERR_NO_FILE;
$value = is_array($value) && !empty($value) ? $value[0] : $value;
return !($value instanceof UploadedFile) || $value->error == UPLOAD_ERR_NO_FILE;
}
/**

6
framework/web/AccessControl.php

@ -64,6 +64,7 @@ class AccessControl extends ActionFilter
* ~~~
*
* where `$rule` is this rule, and `$action` is the current [[Action|action]] object.
* `$rule` will be `null` if access is denied because none of the rules matched.
*/
public $denyCallback;
/**
@ -79,6 +80,7 @@ class AccessControl extends ActionFilter
*/
public $rules = [];
/**
* Initializes the [[rules]] array by instantiating rule objects from configurations.
*/
@ -114,16 +116,14 @@ class AccessControl extends ActionFilter
} else {
$this->denyAccess($user);
}
return false;
}
}
if (isset($this->denyCallback)) {
call_user_func($this->denyCallback, $rule, $action);
call_user_func($this->denyCallback, null, $action);
} else {
$this->denyAccess($user);
}
return false;
}

4
framework/web/Request.php

@ -124,8 +124,8 @@ class Request extends \yii\base\Request
*/
public $enableCookieValidation = true;
/**
* @var string|boolean the name of the POST parameter that is used to indicate if a request is a PUT, PATCH or DELETE
* request tunneled through POST. Default to '_method'.
* @var string the name of the POST parameter that is used to indicate if a request is a PUT, PATCH or DELETE
* request tunneled through POST. Defaults to '_method'.
* @see getMethod()
* @see getBodyParams()
*/

1
framework/web/Response.php

@ -738,7 +738,6 @@ class Response extends \yii\base\Response
if ($this->_cookies === null) {
$this->_cookies = new CookieCollection;
}
return $this->_cookies;
}

13
framework/web/UploadedFile.php

@ -56,6 +56,7 @@ class UploadedFile extends Object
*/
public $error;
/**
* String output.
* This is PHP magic method that returns string representation of an object.
@ -80,7 +81,6 @@ class UploadedFile extends Object
public static function getInstance($model, $attribute)
{
$name = Html::getInputName($model, $attribute);
return static::getInstanceByName($name);
}
@ -95,7 +95,6 @@ class UploadedFile extends Object
public static function getInstances($model, $attribute)
{
$name = Html::getInputName($model, $attribute);
return static::getInstancesByName($name);
}
@ -108,8 +107,7 @@ class UploadedFile extends Object
*/
public static function getInstanceByName($name)
{
$files = static::loadFiles();
$files = self::loadFiles();
return isset($files[$name]) ? $files[$name] : null;
}
@ -124,17 +122,16 @@ class UploadedFile extends Object
*/
public static function getInstancesByName($name)
{
$files = static::loadFiles();
$files = self::loadFiles();
if (isset($files[$name])) {
return [$files[$name]];
}
$results = [];
foreach ($files as $key => $file) {
if (strpos($key, "{$name}[") === 0) {
$results[] = self::$_files[$key];
$results[] = $file;
}
}
return $results;
}
@ -166,7 +163,6 @@ class UploadedFile extends Object
return copy($this->tempName, $file);
}
}
return false;
}
@ -209,7 +205,6 @@ class UploadedFile extends Object
}
}
}
return self::$_files;
}

1
framework/web/UrlRule.php

@ -101,6 +101,7 @@ class UrlRule extends Object implements UrlRuleInterface
*/
private $_routeParams = [];
/**
* Initializes this rule.
*/

6
framework/web/User.php

@ -141,8 +141,8 @@ class User extends Component
* @param boolean $checkSession whether to check the session if the identity has never been determined before.
* If the identity is already determined (e.g., by calling [[setIdentity()]] or [[login()]]),
* then this parameter has no effect.
* @return IdentityInterface the identity object associated with the currently logged-in user.
* Null is returned if the user is not logged in (not authenticated).
* @return IdentityInterface|null the identity object associated with the currently logged-in user.
* `null` is returned if the user is not logged in (not authenticated).
* @see login()
* @see logout()
*/
@ -170,7 +170,7 @@ class User extends Component
* [[switchIdentity()]]. Those methods will try to use session and cookie to maintain the user authentication
* status.
*
* @param IdentityInterface $identity the identity object associated with the currently logged user.
* @param IdentityInterface|null $identity the identity object associated with the currently logged user.
*/
public function setIdentity($identity)
{

26
framework/widgets/BaseListView.php

@ -54,6 +54,12 @@ abstract class BaseListView extends Widget
*/
public $summary;
/**
* @var array the HTML attributes for the summary of the list view.
* The "tag" element specifies the tag name of the summary element and defaults to "div".
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $summaryOptions = ['class' => 'summary'];
/**
* @var boolean whether to show the list view if [[dataProvider]] returns no data.
*/
public $showOnEmpty = false;
@ -62,6 +68,12 @@ abstract class BaseListView extends Widget
*/
public $emptyText;
/**
* @var array the HTML attributes for the emptyText of the list view.
* The "tag" element specifies the tag name of the emptyText element and defaults to "div".
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $emptyTextOptions = ['class' => 'empty'];
/**
* @var string the layout that determines how different sections of the list view should be organized.
* The following tokens will be replaced with the corresponding section contents:
*
@ -139,7 +151,8 @@ abstract class BaseListView extends Widget
*/
public function renderEmpty()
{
return '<div class="empty">' . ($this->emptyText === null ? Yii::t('yii', 'No results found.') : $this->emptyText) . '</div>';
$tag = ArrayHelper::remove($this->emptyTextOptions, 'tag', 'div');
return Html::tag($tag, ($this->emptyText === null ? Yii::t('yii', 'No results found.') : $this->emptyText), $this->emptyTextOptions);
}
/**
@ -151,6 +164,7 @@ abstract class BaseListView extends Widget
if ($count <= 0) {
return '';
}
$tag = ArrayHelper::remove($this->summaryOptions, 'tag', 'div');
if (($pagination = $this->dataProvider->getPagination()) !== false) {
$totalCount = $this->dataProvider->getTotalCount();
$begin = $pagination->getPage() * $pagination->pageSize + 1;
@ -161,29 +175,27 @@ abstract class BaseListView extends Widget
$page = $pagination->getPage() + 1;
$pageCount = $pagination->pageCount;
if (($summaryContent = $this->summary) === null) {
return '<div class="summary">'
. Yii::t('yii', 'Showing <b>{begin, number}-{end, number}</b> of <b>{totalCount, number}</b> {totalCount, plural, one{item} other{items}}.', [
return Html::tag($tag, Yii::t('yii', 'Showing <b>{begin, number}-{end, number}</b> of <b>{totalCount, number}</b> {totalCount, plural, one{item} other{items}}.', [
'begin' => $begin,
'end' => $end,
'count' => $count,
'totalCount' => $totalCount,
'page' => $page,
'pageCount' => $pageCount,
])
. '</div>';
]), $this->summaryOptions);
}
} else {
$begin = $page = $pageCount = 1;
$end = $totalCount = $count;
if (($summaryContent = $this->summary) === null) {
return '<div class="summary">' . Yii::t('yii', 'Total <b>{count, number}</b> {count, plural, one{item} other{items}}.', [
return Html::tag($tag, Yii::t('yii', 'Total <b>{count, number}</b> {count, plural, one{item} other{items}}.', [
'begin' => $begin,
'end' => $end,
'count' => $count,
'totalCount' => $totalCount,
'page' => $page,
'pageCount' => $pageCount,
]) . '</div>';
]), $this->summaryOptions);
}
}

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

@ -402,6 +402,19 @@ class ActiveRecordTest extends DatabaseTestCase
$this->assertEquals(3, $count);
$orders = $query->all();
$this->assertEquals(3, count($orders));
// https://github.com/yiisoft/yii2/issues/2880
$query = Order::find(1);
$customer = $query->getCustomer()->joinWith([
'orders' => function ($q) { $q->orderBy([]); }
])->one();
$this->assertEquals(1, $customer->id);
$order = Order::find()->joinWith([
'items' => function ($q) {
$q->from(['items' => 'tbl_item'])
->orderBy('items.id');
},
])->orderBy('tbl_order.id')->one();
}
public function testJoinWithAndScope()

5
tests/unit/framework/log/TargetTest.php

@ -5,6 +5,7 @@
namespace yiiunit\framework\log;
use yii\log\Dispatcher;
use yii\log\Logger;
use yii\log\Target;
use yiiunit\TestCase;
@ -50,7 +51,9 @@ class TargetTest extends TestCase
{
static::$messages = [];
$logger = new Logger([
$logger = new Logger;
$dispatcher = new Dispatcher([
'logger' => $logger,
'targets' => [new TestTarget(array_merge($filter, ['logVars' => []]))],
'flushInterval' => 1,
]);

Loading…
Cancel
Save