diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md
index 52caf70fc3..adf431a61d 100644
--- a/framework/CHANGELOG.md
+++ b/framework/CHANGELOG.md
@@ -26,6 +26,7 @@ Yii Framework 2 Change Log
- Bug #19237: Fix OCI PHP 8.1 passing `null` to trim() (longthanhtran)
- Bug #19312: Fix PHP 8.1 error when passing null to `yii\helpers\BaseInflector` (WinterSilence)
- Bug #19368: Fix PHP 8.1 error when `$fileMimeType` is `null` in `yii\validators\FileValidator::validateMimeType()` (bizley)
+- Bug #19386: Fix recursive calling `yii\helpers\BaseArrayHelper::htmlDecode()` (WinterSilence)
2.0.45 February 11, 2022
diff --git a/framework/helpers/BaseArrayHelper.php b/framework/helpers/BaseArrayHelper.php
index d4207db92a..84e67f43b5 100644
--- a/framework/helpers/BaseArrayHelper.php
+++ b/framework/helpers/BaseArrayHelper.php
@@ -726,12 +726,14 @@ class BaseArrayHelper
/**
* Decodes HTML entities into the corresponding characters in an array of strings.
+ *
* Only array values will be decoded by default.
* If a value is an array, this method will also decode it recursively.
* Only string values will be decoded.
+ *
* @param array $data data to be decoded
- * @param bool $valuesOnly whether to decode array values only. If false,
- * both the array keys and array values will be decoded.
+ * @param bool $valuesOnly whether to decode array values only. If `false`,
+ * then both the array keys and array values will be decoded.
* @return array the decoded data
* @see https://www.php.net/manual/en/function.htmlspecialchars-decode.php
*/
@@ -740,12 +742,12 @@ class BaseArrayHelper
$d = [];
foreach ($data as $key => $value) {
if (!$valuesOnly && is_string($key)) {
- $key = htmlspecialchars_decode($key, ENT_QUOTES);
+ $key = htmlspecialchars_decode($key, ENT_QUOTES | ENT_SUBSTITUTE);
}
if (is_string($value)) {
- $d[$key] = htmlspecialchars_decode($value, ENT_QUOTES);
+ $d[$key] = htmlspecialchars_decode($value, ENT_QUOTES | ENT_SUBSTITUTE);
} elseif (is_array($value)) {
- $d[$key] = static::htmlDecode($value);
+ $d[$key] = static::htmlDecode($value, $valuesOnly);
} else {
$d[$key] = $value;
}
diff --git a/tests/framework/helpers/ArrayHelperTest.php b/tests/framework/helpers/ArrayHelperTest.php
index 57ab1bf0fa..89a047e440 100644
--- a/tests/framework/helpers/ArrayHelperTest.php
+++ b/tests/framework/helpers/ArrayHelperTest.php
@@ -1185,29 +1185,35 @@ class ArrayHelperTest extends TestCase
3 => 'blank',
[
'<>' => 'a<>b',
+ '<a>' => '<a href="index.php?a=1&b=2">link</a>',
'23' => true,
],
];
- $this->assertEquals([
+
+ $expected = [
'abc' => '123',
'<' => '>',
'cde' => false,
3 => 'blank',
[
'<>' => 'a<>b',
+ '<a>' => 'link',
'23' => true,
],
- ], ArrayHelper::htmlDecode($array));
- $this->assertEquals([
+ ];
+ $this->assertEquals($expected, ArrayHelper::htmlDecode($array));
+ $expected = [
'abc' => '123',
'<' => '>',
'cde' => false,
3 => 'blank',
[
'<>' => 'a<>b',
+ '' => 'link',
'23' => true,
],
- ], ArrayHelper::htmlDecode($array, false));
+ ];
+ $this->assertEquals($expected, ArrayHelper::htmlDecode($array, false));
}
public function testIsIn()