Skip to content

Commit

Permalink
Fix #19899: Fixed GridView in some cases calling `Model::generateAt…
Browse files Browse the repository at this point in the history
…tributeLabel()` to generate label values that are never used
  • Loading branch information
PowerGamer1 committed Jul 24, 2023
1 parent 79c83ba commit c8c0ea9
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 8 deletions.
1 change: 1 addition & 0 deletions framework/CHANGELOG.md
Expand Up @@ -4,6 +4,7 @@ Yii Framework 2 Change Log
2.0.49 under development
------------------------

- Bug #19899: Fixed `GridView` in some cases calling `Model::generateAttributeLabel()` to generate label values that are never used (PowerGamer1)
- Bug #9899: Fix caching a MSSQL query with BLOB data type (terabytesoftw)
- Bug #16208: Fix `yii\log\FileTarget` to not export empty messages (terabytesoftw)
- Bug #19857: Fix AttributeTypecastBehavior::resetOldAttributes() causes "class has no attribute named" InvalidArgumentException (uaoleg)
Expand Down
10 changes: 3 additions & 7 deletions framework/data/ActiveDataProvider.php
Expand Up @@ -183,15 +183,11 @@ public function setSort($value)
$sort->attributes[$attribute] = [
'asc' => [$attribute => SORT_ASC],
'desc' => [$attribute => SORT_DESC],
'label' => $model->getAttributeLabel($attribute),
];
}
} else {
foreach ($sort->attributes as $attribute => $config) {
if (!isset($config['label'])) {
$sort->attributes[$attribute]['label'] = $model->getAttributeLabel($attribute);
}
}
}
if ($sort->modelClass === null) {
$sort->modelClass = $modelClass;
}
}
}
Expand Down
14 changes: 13 additions & 1 deletion framework/data/Sort.php
Expand Up @@ -191,6 +191,12 @@ class Sort extends BaseObject
* @since 2.0.33
*/
public $sortFlags = SORT_REGULAR;
/**
* @var string|null the name of the [[\yii\base\Model]]-based class used by the [[link()]] method to retrieve
* attributes' labels. See [[link]] method for details.
* @since 2.0.49
*/
public $modelClass;


/**
Expand Down Expand Up @@ -363,7 +369,8 @@ public function getAttributeOrder($attribute)
* @param array $options additional HTML attributes for the hyperlink tag.
* There is one special attribute `label` which will be used as the label of the hyperlink.
* If this is not set, the label defined in [[attributes]] will be used.
* If no label is defined, [[\yii\helpers\Inflector::camel2words()]] will be called to get a label.
* If no label is defined, it will be retrieved from the instance of [[modelClass]] (if [[modelClass]] is not null)
* or generated from attribute name using [[\yii\helpers\Inflector::camel2words()]].
* Note that it will not be HTML-encoded.
* @return string the generated hyperlink
* @throws InvalidConfigException if the attribute is unknown
Expand All @@ -388,6 +395,11 @@ public function link($attribute, $options = [])
} else {
if (isset($this->attributes[$attribute]['label'])) {
$label = $this->attributes[$attribute]['label'];
} elseif ($this->modelClass !== null) {
$modelClass = $this->modelClass;
/** @var \yii\base\Model $model */
$model = $modelClass::instance();
$label = $model->getAttributeLabel($attribute);
} else {
$label = Inflector::camel2words($attribute);
}
Expand Down
27 changes: 27 additions & 0 deletions tests/data/ar/NoAutoLabels.php
@@ -0,0 +1,27 @@
<?php
/**
* @link https://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license https://www.yiiframework.com/license/
*/

namespace yiiunit\data\ar;

/**
* @property int $attr1
* @property int $attr2
*/
class NoAutoLabels extends ActiveRecord
{
public function attributeLabels()
{
return [
'attr1' => 'Label for attr1',
];
}

public function generateAttributeLabel($name)
{
throw new \yii\base\InvalidArgumentException('Label not defined!');
}
}
51 changes: 51 additions & 0 deletions tests/framework/grid/GridViewTest.php
Expand Up @@ -7,10 +7,12 @@

namespace yiiunit\framework\grid;

use Yii;
use yii\data\ArrayDataProvider;
use yii\grid\DataColumn;
use yii\grid\GridView;
use yii\web\View;
use yiiunit\data\ar\NoAutoLabels;

/**
* @author Evgeniy Tkachenko <et.coder@gmail.com>
Expand Down Expand Up @@ -150,4 +152,53 @@ public function testFooter() {

$this->assertTrue(preg_match("/<\/tbody><tfoot>/", $html) === 1);
}

public function testHeaderLabels()
{
// Ensure GridView does not call Model::generateAttributeLabel() to generate labels unless the labels are explicitly used.

$this->mockApplication([
'components' => [
'db' => [
'class' => \yii\db\Connection::className(),
'dsn' => 'sqlite::memory:',
],
],
]);

NoAutoLabels::$db = Yii::$app->getDb();
Yii::$app->getDb()->createCommand()->createTable(NoAutoLabels::tableName(), ['attr1' => 'int', 'attr2' => 'int'])->execute();

$urlManager = new \yii\web\UrlManager([
'baseUrl' => '/',
'scriptUrl' => '/index.php',
]);

$grid = new GridView([
'dataProvider' => new \yii\data\ActiveDataProvider([
'query' => NoAutoLabels::find(),
]),
'columns' => [
'attr1',
'attr2:text:Label for attr2',
],
]);

// NoAutoLabels::generateAttributeLabel() should not be called.
$grid->dataProvider->setSort([
'route' => '/',
'urlManager' => $urlManager,
]);
$grid->renderTableHeader();

// NoAutoLabels::generateAttributeLabel() should not be called.
$grid->dataProvider->setSort([
'route' => '/',
'urlManager' => $urlManager,
'attributes' => ['attr1', 'attr2'],
]);
$grid->renderTableHeader();

// If NoAutoLabels::generateAttributeLabel() has not been called no exception will be thrown meaning this test passed successfully.
}
}

0 comments on commit c8c0ea9

Please sign in to comment.