Skip to content

Commit

Permalink
fix ArrayHelper::map() for path strings
Browse files Browse the repository at this point in the history
! don't use array_column if ArrayHelper strings are paths
+ add according tests
+ add BaseStringHelper::contains() helper function and according tests
  • Loading branch information
chriscpty committed Oct 18, 2024
1 parent facef5a commit 1fcadcd
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 15 deletions.
1 change: 1 addition & 0 deletions framework/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Yii Framework 2 Change Log
- Bug #20256: Add support for dropping views in MSSQL server when running migrate/fresh (ambrozt)
- Enh #20248: Add support for attaching behaviors in configurations with Closure (timkelty)
- Enh #20268: Minor optimisation in `\yii\helpers\BaseArrayHelper::map` (chriscpty)
- Enh #20268: Add `\yii\helpers\BaseStringHelper::contains()` as a polyfill for `str_contains` (chriscpty)

2.0.51 July 18, 2024
--------------------
Expand Down
2 changes: 1 addition & 1 deletion framework/helpers/BaseArrayHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ public static function getColumn($array, $name, $keepKeys = true)
*/
public static function map($array, $from, $to, $group = null)
{
if (is_string($from) && is_string($to) && $group === null) {
if (is_string($from) && is_string($to) && $group === null && !\yii\helpers\StringHelper::contains($from, '.') && !\yii\helpers\StringHelper::contains($to, '.')) {
return array_column($array, $to, $from);
}
$result = [];
Expand Down
56 changes: 42 additions & 14 deletions framework/helpers/BaseStringHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,29 @@ protected static function truncateHtml($string, $count, $suffix, $encoding = fal
return $generator->generateFromTokens($truncated) . ($totalCount >= $count ? $suffix : '');
}

/**
* @param string $string The input string.
* @param string $needle Part to search inside $string
* @param bool $caseSensitive Case sensitive search. Default is true. When case sensitive is enabled, `$with` must
* exactly match the starting of the string in order to get a true value.
* @return bool
*/
public static function contains($string, $needle, $caseSensitive = true)
{
$string = (string)$string;
$needle = (string)$needle;

if ($caseSensitive) {
if (function_exists('str_contains')) {
return str_contains($string, $needle);

Check warning on line 243 in framework/helpers/BaseStringHelper.php

View check run for this annotation

Codecov / codecov/patch

framework/helpers/BaseStringHelper.php#L243

Added line #L243 was not covered by tests
}
$encoding = Yii::$app ? Yii::$app->charset : 'UTF-8';
return mb_strpos($string, $needle, 0, $encoding) !== false;

Check failure on line 246 in framework/helpers/BaseStringHelper.php

View workflow job for this annotation

GitHub Actions / PHP_CodeSniffer

Expected 1 space after comma in argument list; 2 found
}
$encoding = Yii::$app ? Yii::$app->charset : 'UTF-8';
return mb_stripos($string, $needle, 0, $encoding) !== false;

Check warning on line 249 in framework/helpers/BaseStringHelper.php

View check run for this annotation

Codecov / codecov/patch

framework/helpers/BaseStringHelper.php#L248-L249

Added lines #L248 - L249 were not covered by tests
}

/**
* Check if given string starts with specified substring. Binary and multibyte safe.
*
Expand Down Expand Up @@ -313,9 +336,14 @@ public static function explode($string, $delimiter = ',', $trim = true, $skipEmp
}
if ($skipEmpty) {
// Wrapped with array_values to make array keys sequential after empty values removing
$result = array_values(array_filter($result, function ($value) {
return $value !== '';
}));
$result = array_values(
array_filter(
$result,
function ($value) {
return $value !== '';
}
)
);

Check warning on line 346 in framework/helpers/BaseStringHelper.php

View check run for this annotation

Codecov / codecov/patch

framework/helpers/BaseStringHelper.php#L339-L346

Added lines #L339 - L346 were not covered by tests
}

return $result;
Expand Down Expand Up @@ -343,7 +371,7 @@ public static function countWords($string)
*/
public static function normalizeNumber($value)
{
$value = (string) $value;
$value = (string)$value;

Check warning on line 374 in framework/helpers/BaseStringHelper.php

View check run for this annotation

Codecov / codecov/patch

framework/helpers/BaseStringHelper.php#L374

Added line #L374 was not covered by tests

$localeInfo = localeconv();
$decimalSeparator = isset($localeInfo['decimal_point']) ? $localeInfo['decimal_point'] : null;
Expand Down Expand Up @@ -396,7 +424,7 @@ public static function floatToString($number)
{
// . and , are the only decimal separators known in ICU data,
// so its safe to call str_replace here
return str_replace(',', '.', (string) $number);
return str_replace(',', '.', (string)$number);
}

/**
Expand All @@ -422,14 +450,14 @@ public static function matchWildcard($pattern, $string, $options = [])

$replacements = [
'\\\\\\\\' => '\\\\',
'\\\\\\*' => '[*]',
'\\\\\\?' => '[?]',
'\*' => '.*',
'\?' => '.',
'\[\!' => '[^',
'\[' => '[',
'\]' => ']',
'\-' => '-',
'\\\\\\*' => '[*]',
'\\\\\\?' => '[?]',
'\*' => '.*',
'\?' => '.',
'\[\!' => '[^',
'\[' => '[',
'\]' => ']',
'\-' => '-',
];

if (isset($options['escape']) && !$options['escape']) {
Expand Down Expand Up @@ -483,7 +511,7 @@ public static function mb_ucfirst($string, $encoding = 'UTF-8')
*/
public static function mb_ucwords($string, $encoding = 'UTF-8')
{
$string = (string) $string;
$string = (string)$string;
if (empty($string)) {
return $string;
}
Expand Down
13 changes: 13 additions & 0 deletions tests/framework/helpers/ArrayHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,19 @@ static function (array $group) {
],
], $result);

$array = [
['id' => '123', 'name' => 'aaa', 'class' => 'x', 'map' => ['a' => '11', 'b' => '22']],
['id' => '124', 'name' => 'bbb', 'class' => 'x', 'map' => ['a' => '33', 'b' => '44']],
['id' => '345', 'name' => 'ccc', 'class' => 'y', 'map' => ['a' => '55', 'b' => '66']],
];

$result = ArrayHelper::map($array, 'map.a', 'map.b');

$this->assertEquals([
'11' => '22',
'33' => '44',
'55' => '66'
], $result);
}

public function testKeyExists()
Expand Down
9 changes: 9 additions & 0 deletions tests/framework/helpers/StringHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,15 @@ public function testTruncateWords()
$this->assertEquals('<span><img src="image.png" />This is a test</span><strong> for</strong>...', StringHelper::truncateWords('<span><img src="image.png" />This is a test</span><strong> for a sentance</strong>', 5, '...', true));
}

public function testContains()
{
$this->assertEquals(true, StringHelper::contains('Test', 'st'));
$this->assertEquals(false, StringHelper::contains('Test', 'ts'));
$this->assertEquals(false, StringHelper::contains('Test', 'St'));
$this->assertEquals(true, StringHelper::contains('Test', 'St', false));
$this->assertEquals(false, StringHelper::contains('Test', 'Ste', false));
}

/**
* @dataProvider providerStartsWith
* @param bool $result
Expand Down

0 comments on commit 1fcadcd

Please sign in to comment.