diff --git a/framework/helpers/BaseHtml.php b/framework/helpers/BaseHtml.php
index 2213e16..0c408ce 100644
--- a/framework/helpers/BaseHtml.php
+++ b/framework/helpers/BaseHtml.php
@@ -1752,8 +1752,17 @@ class BaseHtml
}
/**
- * Adds a CSS class to the specified options.
+ * Adds a CSS class (or several classes) to the specified options.
* If the CSS class is already in the options, it will not be added again.
+ * If class specification at given options is an array, and some class placed there with the named (string) key,
+ * overriding of such key will have no effect. For example:
+ *
+ * ~~~php
+ * $options = ['class' => ['persistent' => 'initial']];
+ * Html::addCssClass($options, ['persistent' => 'override']);
+ * var_dump($options['class']); // outputs: array('persistent' => 'initial');
+ * ~~~
+ *
* @param array $options the options to be modified.
* @param string|array $class the CSS class(es) to be added
*/
@@ -1761,12 +1770,10 @@ class BaseHtml
{
if (isset($options['class'])) {
if (is_array($options['class'])) {
- $classes = array_merge($options['class'], (array)$class);
- $options['class'] = array_unique($classes);
+ $options['class'] = self::mergeCssClasses($options['class'], (array)$class);
} else {
$classes = preg_split('/\s+/', $options['class'], -1, PREG_SPLIT_NO_EMPTY);
- $classes = array_unique(array_merge($classes, (array)$class));
- $options['class'] = implode(' ', $classes);
+ $options['class'] = implode(' ', self::mergeCssClasses($classes, (array)$class));
}
} else {
$options['class'] = $class;
@@ -1774,6 +1781,25 @@ class BaseHtml
}
/**
+ * Merges already existing CSS classes with new one.
+ * This method provides the priority for named existing classes over additional.
+ * @param array $existingClasses already existing CSS classes.
+ * @param array $additionalClasses CSS classes to be added.
+ * @return array merge result.
+ */
+ private static function mergeCssClasses(array $existingClasses, array $additionalClasses)
+ {
+ foreach ($additionalClasses as $key => $class) {
+ if (is_int($key) && !in_array($class, $existingClasses)) {
+ $existingClasses[] = $class;
+ } elseif (!isset($existingClasses[$key])) {
+ $existingClasses[$key] = $class;
+ }
+ }
+ return array_unique($existingClasses);
+ }
+
+ /**
* Removes a CSS class from the specified options.
* @param array $options the options to be modified.
* @param string|array $class the CSS class(es) to be removed
diff --git a/tests/framework/helpers/HtmlTest.php b/tests/framework/helpers/HtmlTest.php
index 614a11f..bd71da6 100644
--- a/tests/framework/helpers/HtmlTest.php
+++ b/tests/framework/helpers/HtmlTest.php
@@ -578,6 +578,22 @@ EOD;
$this->assertEquals(['class' => 'test test1 test2'], $options);
}
+ /**
+ * @depends testAddCssClass
+ */
+ public function testMergeCssClass()
+ {
+ $options = [
+ 'class' => [
+ 'persistent' => 'test1'
+ ]
+ ];
+ Html::addCssClass($options, ['persistent' => 'test2']);
+ $this->assertEquals(['persistent' => 'test1'], $options['class']);
+ Html::addCssClass($options, ['additional' => 'test2']);
+ $this->assertEquals(['persistent' => 'test1', 'additional' => 'test2'], $options['class']);
+ }
+
public function testRemoveCssClass()
{
$options = ['class' => 'test test2 test3'];