mirror of
https://github.com/yiisoft/yii2.git
synced 2025-08-26 14:26:54 +08:00
Merge branch '6043-html-arrays'
Conflicts: framework/CHANGELOG.md
This commit is contained in:
@ -5,20 +5,15 @@ Yii Framework 2 Change Log
|
||||
-----------------------
|
||||
|
||||
- Bug #7305: Logging of Exception objects resulted in failure of the logger i.e. no logs being written (cebe)
|
||||
- Bug #7374: Use proper INSERT syntax with default values when no values are specified (nineinchnick)
|
||||
- Bug #7707: client-side `trim` validator now passes the trimmed value to subsequent validators (nkovacs)
|
||||
- Bug #8322: `yii\behaviors\TimestampBehavior::touch()` now throws an exception if owner is new record (klimov-paul)
|
||||
- Bug #8451: `yii\i18n\Formatter` did not allow negative unix timestamps as input for date formatting (cebe)
|
||||
- Bug #8483: sequence name in `Schema::getLastInsertId()` was not properly quoted (nineinchnick)
|
||||
- Bug #8506: Cleaning of output buffer in `Widget::run()` conflicts with `Pjax` widget which did the cleanup itself (cebe, joester89)
|
||||
- Bug #8544: Fixed `yii\db\ActiveRecord` does not updates attribute specified at `optimisticLock()` after save (klimov-paul)
|
||||
- Bug: Fixed string comparison in `BaseActiveRecord::unlink()` which may result in wrong comparison result for hash valued primary keys starting with `0e` (cebe)
|
||||
- Enh #7169: `yii\widgets\ActiveField` now uses corresponding methods for default parts rendering (klimov-paul)
|
||||
- Enh #6043: Specification for 'class' and 'style' in array format added to `yii\helpers\Html` (klimov-paul)
|
||||
- Enh #8070: `yii\console\controllers\MessageController` now sorts created messages, even if there is no new one, while saving to PHP file (klimov-paul)
|
||||
- Enh #8286: `yii\console\controllers\MessageController` improved allowing extraction of nested translator calls (klimov-paul)
|
||||
- Enh #8415: `yii\helpers\Html` allows correct rendering of conditional comments containing `!IE` (salaros, klimov-paul)
|
||||
- Enh #8444: Added `yii\widgets\LinkPager::$linkOptions` to allow configuring HTML attributes of the `a` tags (zinzinday)
|
||||
- Enh #8486: Added support to automatically set the `maxlength` attribute for `Html::activeTextArea()` and `Html::activePassword()` (klimov-paul)
|
||||
- Chg #6354: `ErrorHandler::logException()` will now log the whole exception object instead of only its string representation (cebe)
|
||||
|
||||
|
||||
|
@ -1756,6 +1756,16 @@ class BaseHtml
|
||||
$html .= " $name-$n=\"" . static::encode($v) . '"';
|
||||
}
|
||||
}
|
||||
} elseif ($name === 'class') {
|
||||
if (empty($value)) {
|
||||
continue;
|
||||
}
|
||||
$html .= " $name=\"" . static::encode(implode(' ', $value)) . '"';
|
||||
} elseif ($name === 'style') {
|
||||
if (empty($value)) {
|
||||
continue;
|
||||
}
|
||||
$html .= " $name=\"" . static::encode(static::cssStyleFromArray($value)) . '"';
|
||||
} else {
|
||||
$html .= " $name='" . Json::htmlEncode($value) . "'";
|
||||
}
|
||||
@ -1768,35 +1778,71 @@ 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 $class the CSS class to be added
|
||||
* @param string|array $class the CSS class(es) to be added
|
||||
*/
|
||||
public static function addCssClass(&$options, $class)
|
||||
{
|
||||
if (isset($options['class'])) {
|
||||
$classes = ' ' . $options['class'] . ' ';
|
||||
if (strpos($classes, ' ' . $class . ' ') === false) {
|
||||
$options['class'] .= ' ' . $class;
|
||||
if (is_array($options['class'])) {
|
||||
$options['class'] = self::mergeCssClasses($options['class'], (array)$class);
|
||||
} else {
|
||||
$classes = preg_split('/\s+/', $options['class'], -1, PREG_SPLIT_NO_EMPTY);
|
||||
$options['class'] = implode(' ', self::mergeCssClasses($classes, (array)$class));
|
||||
}
|
||||
} else {
|
||||
$options['class'] = $class;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 $class the CSS class to be removed
|
||||
* @param string|array $class the CSS class(es) to be removed
|
||||
*/
|
||||
public static function removeCssClass(&$options, $class)
|
||||
{
|
||||
if (isset($options['class'])) {
|
||||
$classes = array_unique(preg_split('/\s+/', $options['class'] . ' ' . $class, -1, PREG_SPLIT_NO_EMPTY));
|
||||
if (($index = array_search($class, $classes)) !== false) {
|
||||
unset($classes[$index]);
|
||||
if (is_array($options['class'])) {
|
||||
$classes = array_diff($options['class'], (array)$class);
|
||||
if (empty($classes)) {
|
||||
unset($options['class']);
|
||||
} else {
|
||||
$options['class'] = $classes;
|
||||
}
|
||||
} else {
|
||||
$classes = preg_split('/\s+/', $options['class'], -1, PREG_SPLIT_NO_EMPTY);
|
||||
$classes = array_diff($classes, (array)$class);
|
||||
if (empty($classes)) {
|
||||
unset($options['class']);
|
||||
} else {
|
||||
@ -1804,6 +1850,7 @@ class BaseHtml
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified CSS style to the HTML options.
|
||||
@ -1830,7 +1877,7 @@ class BaseHtml
|
||||
public static function addCssStyle(&$options, $style, $overwrite = true)
|
||||
{
|
||||
if (!empty($options['style'])) {
|
||||
$oldStyle = static::cssStyleToArray($options['style']);
|
||||
$oldStyle = is_array($options['style']) ? $options['style'] : static::cssStyleToArray($options['style']);
|
||||
$newStyle = is_array($style) ? $style : static::cssStyleToArray($style);
|
||||
if (!$overwrite) {
|
||||
foreach ($newStyle as $property => $value) {
|
||||
@ -1861,7 +1908,7 @@ class BaseHtml
|
||||
public static function removeCssStyle(&$options, $properties)
|
||||
{
|
||||
if (!empty($options['style'])) {
|
||||
$style = static::cssStyleToArray($options['style']);
|
||||
$style = is_array($options['style']) ? $options['style'] : static::cssStyleToArray($options['style']);
|
||||
foreach ((array) $properties as $property) {
|
||||
unset($style[$property]);
|
||||
}
|
||||
|
@ -64,15 +64,15 @@ class HtmlTest extends TestCase
|
||||
public function testStyle()
|
||||
{
|
||||
$content = 'a <>';
|
||||
$this->assertEquals("<style>$content</style>", Html::style($content));
|
||||
$this->assertEquals("<style type=\"text/less\">$content</style>", Html::style($content, ['type' => 'text/less']));
|
||||
$this->assertEquals("<style>{$content}</style>", Html::style($content));
|
||||
$this->assertEquals("<style type=\"text/less\">{$content}</style>", Html::style($content, ['type' => 'text/less']));
|
||||
}
|
||||
|
||||
public function testScript()
|
||||
{
|
||||
$content = 'a <>';
|
||||
$this->assertEquals("<script>$content</script>", Html::script($content));
|
||||
$this->assertEquals("<script type=\"text/js\">$content</script>", Html::script($content, ['type' => 'text/js']));
|
||||
$this->assertEquals("<script>{$content}</script>", Html::script($content));
|
||||
$this->assertEquals("<script type=\"text/js\">{$content}</script>", Html::script($content, ['type' => 'text/js']));
|
||||
}
|
||||
|
||||
public function testCssFile()
|
||||
@ -538,6 +538,10 @@ EOD;
|
||||
$this->assertEquals('', Html::renderTagAttributes([]));
|
||||
$this->assertEquals(' name="test" value="1<>"', 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']]));
|
||||
$this->assertEquals('', Html::renderTagAttributes(['class' => []]));
|
||||
$this->assertEquals(' style="width: 100px; height: 200px;"', Html::renderTagAttributes(['style' => ['width' => '100px', 'height' => '200px']]));
|
||||
$this->assertEquals('', Html::renderTagAttributes(['style' => []]));
|
||||
}
|
||||
|
||||
public function testAddCssClass()
|
||||
@ -557,6 +561,38 @@ EOD;
|
||||
$this->assertEquals(['class' => 'test test2 test3'], $options);
|
||||
Html::addCssClass($options, 'test2');
|
||||
$this->assertEquals(['class' => 'test test2 test3'], $options);
|
||||
|
||||
$options = [
|
||||
'class' => ['test']
|
||||
];
|
||||
Html::addCssClass($options, 'test2');
|
||||
$this->assertEquals(['class' => ['test', 'test2']], $options);
|
||||
Html::addCssClass($options, 'test2');
|
||||
$this->assertEquals(['class' => ['test', 'test2']], $options);
|
||||
Html::addCssClass($options, ['test3']);
|
||||
$this->assertEquals(['class' => ['test', 'test2', 'test3']], $options);
|
||||
|
||||
$options = [
|
||||
'class' => 'test'
|
||||
];
|
||||
Html::addCssClass($options, ['test1', 'test2']);
|
||||
$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()
|
||||
@ -570,6 +606,19 @@ EOD;
|
||||
$this->assertEquals(['class' => 'test3'], $options);
|
||||
Html::removeCssClass($options, 'test3');
|
||||
$this->assertEquals([], $options);
|
||||
|
||||
$options = ['class' => ['test', 'test2', 'test3']];
|
||||
Html::removeCssClass($options, 'test2');
|
||||
$this->assertEquals(['class' => ['test', 2 => 'test3']], $options);
|
||||
Html::removeCssClass($options, 'test');
|
||||
Html::removeCssClass($options, 'test3');
|
||||
$this->assertEquals([], $options);
|
||||
|
||||
$options = [
|
||||
'class' => 'test test1 test2'
|
||||
];
|
||||
Html::removeCssClass($options, ['test1', 'test2']);
|
||||
$this->assertEquals(['class' => 'test'], $options);
|
||||
}
|
||||
|
||||
public function testCssStyleFromArray()
|
||||
@ -611,6 +660,14 @@ EOD;
|
||||
$options = [];
|
||||
Html::addCssStyle($options, 'width: 110px; color: red;', false);
|
||||
$this->assertEquals('width: 110px; color: red;', $options['style']);
|
||||
|
||||
$options = [
|
||||
'style' => [
|
||||
'width' => '100px'
|
||||
],
|
||||
];
|
||||
Html::addCssStyle($options, ['color' => 'red'], false);
|
||||
$this->assertEquals('width: 100px; color: red;', $options['style']);
|
||||
}
|
||||
|
||||
public function testRemoveCssStyle()
|
||||
@ -626,6 +683,14 @@ EOD;
|
||||
$options = [];
|
||||
Html::removeCssStyle($options, ['color', 'background']);
|
||||
$this->assertTrue(!array_key_exists('style', $options));
|
||||
$options = [
|
||||
'style' => [
|
||||
'color' => 'red',
|
||||
'width' => '100px',
|
||||
],
|
||||
];
|
||||
Html::removeCssStyle($options, ['color']);
|
||||
$this->assertEquals('width: 100px;', $options['style']);
|
||||
}
|
||||
|
||||
public function testBooleanAttributes()
|
||||
|
Reference in New Issue
Block a user