Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes duplicate classes in BaseHtml::renderTagAttributes() #19098

Merged
merged 10 commits into from
Dec 27, 2021
1 change: 1 addition & 0 deletions framework/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Yii Framework 2 Change Log
- Bug #19031: Fix displaying console help for parameters with declared types (WinterSilence)
- Bug #19030: Add DI container usage to `yii\base\Widget::end()` (papppeter)
- Bug #19096: Fix `Request::getIsConsoleRequest()` may return erroneously when testing a Web application in Codeception (WinterSilence)
- Enh #19098: Add `yii\helper\BaseHtml::$normalizeClassAttribute` to fix duplicate classes (WinterSilence)
- Enh #19108: Optimize `Component::hasEventHandlers()` and `Component::trigger()` (WinterSilence)


Expand Down
18 changes: 15 additions & 3 deletions framework/helpers/BaseHtml.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,15 @@ class BaseHtml
* @since 2.0.3
*/
public static $dataAttributes = ['aria', 'data', 'data-ng', 'ng'];


/**
* @var bool whether to removes duplicate class names in tag attribute `class`
* @see mergeCssClasses()
* @see renderTagAttributes()
* @since 2.0.44
*/
public static $normalizeClassAttribute = false;


/**
* Encodes special characters into HTML entities.
* The [[\yii\base\Application::charset|application charset]] will be used for encoding.
Expand Down Expand Up @@ -1981,6 +1988,11 @@ public static function renderTagAttributes($attributes)
if (empty($value)) {
continue;
}
if (static::$normalizeClassAttribute === true && count($value) > 1) {
// removes duplicate classes
$value = explode(' ', implode(' ', $value));
WinterSilence marked this conversation as resolved.
Show resolved Hide resolved
$value = array_unique($value);
}
$html .= " $name=\"" . static::encode(implode(' ', $value)) . '"';
} elseif ($name === 'style') {
if (empty($value)) {
Expand Down Expand Up @@ -2047,7 +2059,7 @@ private static function mergeCssClasses(array $existingClasses, array $additiona
}
}

return array_unique($existingClasses);
return static::$normalizeClassAttribute ? array_unique($existingClasses) : $existingClasses;
}

/**
Expand Down
4 changes: 3 additions & 1 deletion tests/framework/helpers/HtmlTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1082,12 +1082,14 @@ public function testRenderOptions()
$this->assertEqualsWithoutLE($expected, Html::renderSelectOptions(['1.10'], $data, $attributes));
}

public function testRenderAttributes()
public function testRenderTagAttributes()
{
$this->assertEquals('', Html::renderTagAttributes([]));
$this->assertEquals(' name="test" value="1&lt;&gt;"', Html::renderTagAttributes(['name' => 'test', 'empty' => null, 'value' => '1<>']));
$this->assertEquals(' checked disabled', Html::renderTagAttributes(['checked' => true, 'disabled' => true, 'hidden' => false]));
$this->assertEquals(' class="first second"', Html::renderTagAttributes(['class' => ['first', 'second']]));
Html::$normalizeClassAttribute = true;
$this->assertEquals(' class="first second"', Html::renderTagAttributes(['class' => ['first second', 'first']]));
$this->assertEquals('', Html::renderTagAttributes(['class' => []]));
$this->assertEquals(' style="width: 100px; height: 200px;"', Html::renderTagAttributes(['style' => ['width' => '100px', 'height' => '200px']]));
$this->assertEquals('', Html::renderTagAttributes(['style' => []]));
Expand Down