Skip to content

Commit c8c0ea9

Browse files
authored
Fix #19899: Fixed GridView in some cases calling Model::generateAttributeLabel() to generate label values that are never used
1 parent 79c83ba commit c8c0ea9

File tree

5 files changed

+95
-8
lines changed

5 files changed

+95
-8
lines changed

framework/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Yii Framework 2 Change Log
44
2.0.49 under development
55
------------------------
66

7+
- Bug #19899: Fixed `GridView` in some cases calling `Model::generateAttributeLabel()` to generate label values that are never used (PowerGamer1)
78
- Bug #9899: Fix caching a MSSQL query with BLOB data type (terabytesoftw)
89
- Bug #16208: Fix `yii\log\FileTarget` to not export empty messages (terabytesoftw)
910
- Bug #19857: Fix AttributeTypecastBehavior::resetOldAttributes() causes "class has no attribute named" InvalidArgumentException (uaoleg)

framework/data/ActiveDataProvider.php

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -183,15 +183,11 @@ public function setSort($value)
183183
$sort->attributes[$attribute] = [
184184
'asc' => [$attribute => SORT_ASC],
185185
'desc' => [$attribute => SORT_DESC],
186-
'label' => $model->getAttributeLabel($attribute),
187186
];
188187
}
189-
} else {
190-
foreach ($sort->attributes as $attribute => $config) {
191-
if (!isset($config['label'])) {
192-
$sort->attributes[$attribute]['label'] = $model->getAttributeLabel($attribute);
193-
}
194-
}
188+
}
189+
if ($sort->modelClass === null) {
190+
$sort->modelClass = $modelClass;
195191
}
196192
}
197193
}

framework/data/Sort.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,12 @@ class Sort extends BaseObject
191191
* @since 2.0.33
192192
*/
193193
public $sortFlags = SORT_REGULAR;
194+
/**
195+
* @var string|null the name of the [[\yii\base\Model]]-based class used by the [[link()]] method to retrieve
196+
* attributes' labels. See [[link]] method for details.
197+
* @since 2.0.49
198+
*/
199+
public $modelClass;
194200

195201

196202
/**
@@ -363,7 +369,8 @@ public function getAttributeOrder($attribute)
363369
* @param array $options additional HTML attributes for the hyperlink tag.
364370
* There is one special attribute `label` which will be used as the label of the hyperlink.
365371
* If this is not set, the label defined in [[attributes]] will be used.
366-
* If no label is defined, [[\yii\helpers\Inflector::camel2words()]] will be called to get a label.
372+
* If no label is defined, it will be retrieved from the instance of [[modelClass]] (if [[modelClass]] is not null)
373+
* or generated from attribute name using [[\yii\helpers\Inflector::camel2words()]].
367374
* Note that it will not be HTML-encoded.
368375
* @return string the generated hyperlink
369376
* @throws InvalidConfigException if the attribute is unknown
@@ -388,6 +395,11 @@ public function link($attribute, $options = [])
388395
} else {
389396
if (isset($this->attributes[$attribute]['label'])) {
390397
$label = $this->attributes[$attribute]['label'];
398+
} elseif ($this->modelClass !== null) {
399+
$modelClass = $this->modelClass;
400+
/** @var \yii\base\Model $model */
401+
$model = $modelClass::instance();
402+
$label = $model->getAttributeLabel($attribute);
391403
} else {
392404
$label = Inflector::camel2words($attribute);
393405
}

tests/data/ar/NoAutoLabels.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
/**
3+
* @link https://www.yiiframework.com/
4+
* @copyright Copyright (c) 2008 Yii Software LLC
5+
* @license https://www.yiiframework.com/license/
6+
*/
7+
8+
namespace yiiunit\data\ar;
9+
10+
/**
11+
* @property int $attr1
12+
* @property int $attr2
13+
*/
14+
class NoAutoLabels extends ActiveRecord
15+
{
16+
public function attributeLabels()
17+
{
18+
return [
19+
'attr1' => 'Label for attr1',
20+
];
21+
}
22+
23+
public function generateAttributeLabel($name)
24+
{
25+
throw new \yii\base\InvalidArgumentException('Label not defined!');
26+
}
27+
}

tests/framework/grid/GridViewTest.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77

88
namespace yiiunit\framework\grid;
99

10+
use Yii;
1011
use yii\data\ArrayDataProvider;
1112
use yii\grid\DataColumn;
1213
use yii\grid\GridView;
1314
use yii\web\View;
15+
use yiiunit\data\ar\NoAutoLabels;
1416

1517
/**
1618
* @author Evgeniy Tkachenko <[email protected]>
@@ -150,4 +152,53 @@ public function testFooter() {
150152

151153
$this->assertTrue(preg_match("/<\/tbody><tfoot>/", $html) === 1);
152154
}
155+
156+
public function testHeaderLabels()
157+
{
158+
// Ensure GridView does not call Model::generateAttributeLabel() to generate labels unless the labels are explicitly used.
159+
160+
$this->mockApplication([
161+
'components' => [
162+
'db' => [
163+
'class' => \yii\db\Connection::className(),
164+
'dsn' => 'sqlite::memory:',
165+
],
166+
],
167+
]);
168+
169+
NoAutoLabels::$db = Yii::$app->getDb();
170+
Yii::$app->getDb()->createCommand()->createTable(NoAutoLabels::tableName(), ['attr1' => 'int', 'attr2' => 'int'])->execute();
171+
172+
$urlManager = new \yii\web\UrlManager([
173+
'baseUrl' => '/',
174+
'scriptUrl' => '/index.php',
175+
]);
176+
177+
$grid = new GridView([
178+
'dataProvider' => new \yii\data\ActiveDataProvider([
179+
'query' => NoAutoLabels::find(),
180+
]),
181+
'columns' => [
182+
'attr1',
183+
'attr2:text:Label for attr2',
184+
],
185+
]);
186+
187+
// NoAutoLabels::generateAttributeLabel() should not be called.
188+
$grid->dataProvider->setSort([
189+
'route' => '/',
190+
'urlManager' => $urlManager,
191+
]);
192+
$grid->renderTableHeader();
193+
194+
// NoAutoLabels::generateAttributeLabel() should not be called.
195+
$grid->dataProvider->setSort([
196+
'route' => '/',
197+
'urlManager' => $urlManager,
198+
'attributes' => ['attr1', 'attr2'],
199+
]);
200+
$grid->renderTableHeader();
201+
202+
// If NoAutoLabels::generateAttributeLabel() has not been called no exception will be thrown meaning this test passed successfully.
203+
}
153204
}

0 commit comments

Comments
 (0)