diff --git a/CHANGELOG.md b/CHANGELOG.md index 611d627..557f51e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,22 @@ Common and useful classes, methods, exceptions etc. } ``` +5. Change of `Meritoo\Common\Utilities\Regex::arrayFilter()` method signature: + 1. 3rd argument, the filter, is now a `\Closure|string`. Previously it was `string`. + 2. 4th argument has been removed (not necessary). + + Before: + + ```php + public static function arrayFilter(array $array, string $arrayColumnKey, string $filterExpression, bool $itsRegularExpression = false): array + ``` + + After: + + ```php + public static function arrayFilter(array $array, string $arrayColumnKey, \Closure|string $filter): array + ``` + # 1.2.2 1. Refactor the `Reflection` class for PHP `8.0`+ diff --git a/TODO.md b/TODO.md index f67d794..7e39901 100644 --- a/TODO.md +++ b/TODO.md @@ -4,7 +4,7 @@ ### Fix PHPStan errors -- [ ] `Undefined variable: $isEqual` - replace `eval()` with callable +- [x] `Undefined variable: $isEqual` - replace `eval()` with callable in [src/Utilities/Regex.php:151](./src/Utilities/Regex.php) - [x] `Unsafe usage of new static()` - chose one of [possible solutions](https://phpstan.org/blog/solving-phpstan-error-unsafe-usage-of-new-static) - @@ -12,7 +12,7 @@ - [x] `Unsafe usage of new static()` - chose one of [possible solutions](https://phpstan.org/blog/solving-phpstan-error-unsafe-usage-of-new-static) - in [src/Exception/Base/UnknownTypeException.php:40](./src/Exception/Base/UnknownTypeException.php) -- [ ] Clean and remove the [phpstan-baseline.neon](phpstan-baseline.neon) file finally +- [x] Clean and remove the [phpstan-baseline.neon](phpstan-baseline.neon) file finally ### Refactoring diff --git a/phpstan.neon b/phpstan.neon index 30b1537..31f6166 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,6 +1,3 @@ -includes: - - phpstan-baseline.neon - parameters: level: 1 paths: diff --git a/src/Utilities/Regex.php b/src/Utilities/Regex.php index ef8777a..2f4499b 100644 --- a/src/Utilities/Regex.php +++ b/src/Utilities/Regex.php @@ -102,19 +102,15 @@ public static function areValidHtmlAttributes(string $htmlAttributes): bool * Expression can be simple compare expression, like " == 2", or regular expression. * Returns filtered array. * - * @param array $array The 2-dimensional array that should be filtered - * @param string $arrayColumnKey Column name - * @param string $filterExpression Simple filter expression (e.g. "== 2" or "!= \'home\'") or regular - * expression (e.g. "/\d+/" or "/[a-z]+[,;]{2,}/") - * @param bool $itsRegularExpression (optional) If is set to true, means that filter expression is a regular - * expression. Otherwise - not (default behaviour). + * @param array $array The 2-dimensional array that should be filtered + * @param string $arrayColumnKey Column name which value is verified by the filter + * @param \Closure|string $filter A filter that might be regular expression (string) or anonymous function (closure) * @return array */ public static function arrayFilter( array $array, string $arrayColumnKey, - string $filterExpression, - bool $itsRegularExpression = false + \Closure|string $filter, ): array { /* * No elements? @@ -132,25 +128,13 @@ public static function arrayFilter( } $value = $item[$arrayColumnKey]; + $itsRegularExpression = \is_string($filter); if ($itsRegularExpression) { - $matchesCount = preg_match($filterExpression, $value); + $matchesCount = preg_match($filter, $value); $remove = 0 === $matchesCount; } else { - if (is_string($value)) { - $value = sprintf('\'%s\'', $value); - } elseif (is_bool($value)) { - if (true === $value) { - $value = 'true'; - } else { - $value = 'false'; - } - } - - eval(sprintf('$isEqual = %s%s;', $value, $filterExpression)); - - /** @var bool $isEqual */ - $remove = !$isEqual; + $remove = !$filter($value); } if ($remove) { diff --git a/tests/Utilities/RegexTest.php b/tests/Utilities/RegexTest.php index d656b35..648bc2a 100644 --- a/tests/Utilities/RegexTest.php +++ b/tests/Utilities/RegexTest.php @@ -8,7 +8,6 @@ namespace Meritoo\Test\Common\Utilities; -use Generator; use Meritoo\Common\Exception\Regex\IncorrectColorHexLengthException; use Meritoo\Common\Exception\Regex\InvalidColorHexValueException; use Meritoo\Common\Test\Base\BaseTestCase; @@ -32,9 +31,9 @@ class RegexTest extends BaseTestCase /** * Provides value to verify if it is a binary value * - * @return Generator + * @return \Generator */ - public function provideBinaryValue() + public function provideBinaryValue(): \Generator { $file1Path = $this->getFilePathForTesting('lorem-ipsum.txt'); $file2Path = $this->getFilePathForTesting('minion.jpg'); @@ -78,9 +77,9 @@ public function provideBinaryValue() /** * Provides name of bundle and information if it's valid name * - * @return Generator + * @return \Generator */ - public function provideBundleName() + public function provideBundleName(): \Generator { yield [ 'something', @@ -121,9 +120,9 @@ public function provideBundleName() /** * Provides value of color * - * @return Generator + * @return \Generator */ - public function provideColor() + public function provideColor(): \Generator { yield [ '#1b0', @@ -154,9 +153,9 @@ public function provideColor() /** * Provides empty non color-related value * - * @return Generator + * @return \Generator */ - public function provideColorEmptyValue() + public function provideColorEmptyValue(): \Generator { yield [ '', @@ -178,9 +177,9 @@ public function provideColorEmptyValue() /** * Provides value of color with incorrect length * - * @return Generator + * @return \Generator */ - public function provideColorIncorrectLength() + public function provideColorIncorrectLength(): \Generator { yield [ '12', @@ -210,9 +209,9 @@ public function provideColorIncorrectLength() /** * Provides invalid value of color * - * @return Generator + * @return \Generator */ - public function provideColorInvalidValue() + public function provideColorInvalidValue(): \Generator { yield [ '#qwerty', @@ -226,9 +225,9 @@ public function provideColorInvalidValue() /** * Provides e-mail and information if it's valid * - * @return Generator + * @return \Generator */ - public function provideEmail() + public function provideEmail(): \Generator { yield [ '1', @@ -264,9 +263,9 @@ public function provideEmail() /** * Provides empty non money-related value * - * @return Generator + * @return \Generator */ - public function provideEmptyNonMoneyValue() + public function provideEmptyNonMoneyValue(): \Generator { yield ['']; yield [' ']; @@ -275,7 +274,7 @@ public function provideEmptyNonMoneyValue() yield [[]]; } - public function provideFileName(): ?Generator + public function provideFileName(): \Generator { yield [ 'An empty string', @@ -311,9 +310,9 @@ public function provideFileName(): ?Generator /** * Provides html attribute and information if it's valid * - * @return Generator + * @return \Generator */ - public function provideHtmlAttribute() + public function provideHtmlAttribute(): \Generator { yield [ 'abc = def', @@ -349,9 +348,9 @@ public function provideHtmlAttribute() /** * Provides html attribute and information if attributes are valid * - * @return Generator + * @return \Generator */ - public function provideHtmlAttributes() + public function provideHtmlAttributes(): \Generator { yield [ 'abc = def', @@ -397,9 +396,9 @@ public function provideHtmlAttributes() /** * Provides money-related value and information if the value is valid * - * @return Generator + * @return \Generator */ - public function provideMoneyValue() + public function provideMoneyValue(): \Generator { yield [ 'abc', @@ -495,9 +494,9 @@ public function provideMoneyValue() /** * Provides pattern and array with keys that should match that pattern * - * @return Generator + * @return \Generator */ - public function providePatternForArrayKeys() + public function providePatternForArrayKeys(): \Generator { yield [ '/\d/', @@ -537,9 +536,9 @@ public function providePatternForArrayKeys() /** * Provides pattern and array with values that should match that pattern * - * @return Generator + * @return \Generator */ - public function providePatternForArrayValues() + public function providePatternForArrayValues(): \Generator { yield [ '/\d/', @@ -580,9 +579,9 @@ public function providePatternForArrayValues() /** * Provides patterns and subject for the pregMultiMatch() method * - * @return Generator + * @return \Generator */ - public function providePatternsAndSubjectForPregMultiMatch() + public function providePatternsAndSubjectForPregMultiMatch(): \Generator { yield [ '', @@ -630,9 +629,9 @@ public function providePatternsAndSubjectForPregMultiMatch() /** * Provides patterns and subject for the pregMultiMatch() method when must match all patterns * - * @return Generator + * @return \Generator */ - public function providePatternsAndSubjectForPregMultiMatchWhenMustMatchAllPatterns() + public function providePatternsAndSubjectForPregMultiMatchWhenMustMatchAllPatterns(): \Generator { yield [ '', @@ -680,9 +679,9 @@ public function providePatternsAndSubjectForPregMultiMatchWhenMustMatchAllPatter /** * Provides phone number and information if it's valid * - * @return Generator + * @return \Generator */ - public function providePhoneNumber() + public function providePhoneNumber(): \Generator { yield [ 'abc', @@ -711,11 +710,11 @@ public function providePhoneNumber() } /** - * Provides regular expression for array filtering and the array + * Provides regular expression for array filtering * - * @return Generator + * @return \Generator */ - public function provideRegularExpressionForArrayFiltering() + public function provideRegularExpressionForArrayFiltering(): \Generator { yield [ [], @@ -876,20 +875,20 @@ public function provideRegularExpressionForArrayFiltering() } /** - * Provides simple compare expression for array filtering and the array + * Provides Closure for array filtering * - * @return Generator + * @return \Generator */ - public function provideSimpleExpressionForArrayFiltering() + public function provideClosureForArrayFiltering(): \Generator { - yield [ + yield 'an empty array' => [ [], 'id', - ' == 2', + fn($value) => $value == 2, [], ]; - yield [ + yield 'not existing column' => [ [ [ 'id' => 1, @@ -911,7 +910,7 @@ public function provideSimpleExpressionForArrayFiltering() ], ], 'birth_date', - ' == 2', + fn($value) => $value == 2, [ [ 'id' => 1, @@ -934,7 +933,7 @@ public function provideSimpleExpressionForArrayFiltering() ], ]; - yield [ + yield 'non-strict equals 2' => [ [ [ 'id' => 1, @@ -943,7 +942,7 @@ public function provideSimpleExpressionForArrayFiltering() 'is_active' => true, ], [ - 'id' => 2, + 'id' => '2', 'first_name' => 'George', 'last_name' => 'Brown', 'is_active' => true, @@ -954,20 +953,71 @@ public function provideSimpleExpressionForArrayFiltering() 'last_name' => 'Green', 'is_active' => false, ], + [ + 'id' => 2, + 'first_name' => 'Kate', + 'last_name' => 'Ryan', + 'is_active' => false, + ], ], 'id', - ' == 2', + fn($value) => $value == 2, [ 1 => [ + 'id' => '2', + 'first_name' => 'George', + 'last_name' => 'Brown', + 'is_active' => true, + ], + 3 => [ 'id' => 2, + 'first_name' => 'Kate', + 'last_name' => 'Ryan', + 'is_active' => false, + ], + ], + ]; + + yield 'strict equals 2' => [ + [ + [ + 'id' => 1, + 'first_name' => 'Jane', + 'last_name' => 'Scott', + 'is_active' => true, + ], + [ + 'id' => '2', 'first_name' => 'George', 'last_name' => 'Brown', 'is_active' => true, ], + [ + 'id' => 3, + 'first_name' => 'Mike', + 'last_name' => 'Green', + 'is_active' => false, + ], + [ + 'id' => 2, + 'first_name' => 'Kate', + 'last_name' => 'Ryan', + 'is_active' => false, + ], + ], + 'id', + fn($value) => $value === 2, + [ + 3 => [ + 'id' => 2, + 'first_name' => 'Kate', + 'last_name' => 'Ryan', + 'is_active' => false, + ], ], ]; - yield [ + yield 'greater than or equals 2' => [ [ [ 'id' => 1, @@ -989,7 +1039,7 @@ public function provideSimpleExpressionForArrayFiltering() ], ], 'id', - ' >= 2', + fn($value) => $value >= 2, [ 1 => [ 'id' => 2, @@ -1006,7 +1056,7 @@ public function provideSimpleExpressionForArrayFiltering() ], ]; - yield [ + yield 'strict not equals `true`' => [ [ [ 'id' => 1, @@ -1028,7 +1078,7 @@ public function provideSimpleExpressionForArrayFiltering() ], ], 'is_active', - ' !== true', + fn($value) => $value !== true, [ 2 => [ 'id' => 3, @@ -1039,7 +1089,40 @@ public function provideSimpleExpressionForArrayFiltering() ], ]; - yield [ + yield 'not `true`' => [ + [ + [ + 'id' => 1, + 'first_name' => 'Jane', + 'last_name' => 'Scott', + 'is_active' => true, + ], + [ + 'id' => 2, + 'first_name' => 'George', + 'last_name' => 'Brown', + 'is_active' => true, + ], + [ + 'id' => 3, + 'first_name' => 'Mike', + 'last_name' => 'Green', + 'is_active' => false, + ], + ], + 'is_active', + fn($value) => !$value, + [ + 2 => [ + 'id' => 3, + 'first_name' => 'Mike', + 'last_name' => 'Green', + 'is_active' => false, + ], + ], + ]; + + yield 'equals `Mike`' => [ [ [ 'id' => 1, @@ -1061,7 +1144,7 @@ public function provideSimpleExpressionForArrayFiltering() ], ], 'first_name', - ' == \'Mike\'', + fn($value) => $value === 'Mike', [ 2 => [ 'id' => 3, @@ -1258,7 +1341,7 @@ public function provideSizeToVerify() ]; } - public function provideStringToClearBeginningSlash(): ?Generator + public function provideStringToClearBeginningSlash(): \Generator { yield [ '', @@ -1361,7 +1444,7 @@ public function provideStringToClearBeginningSlash(): ?Generator ]; } - public function provideStringToClearEndingSlash(): ?Generator + public function provideStringToClearEndingSlash(): \Generator { yield [ '', @@ -1467,9 +1550,9 @@ public function provideStringToClearEndingSlash(): ?Generator /** * Provides tax ID and information if it's valid * - * @return Generator + * @return \Generator */ - public function provideTaxId() + public function provideTaxId(): \Generator { yield [ '123', @@ -1512,9 +1595,9 @@ public function provideTaxId() /** * Provide value to create slug * - * @return Generator + * @return \Generator */ - public function provideValueSlug() + public function provideValueSlug(): \Generator { yield [ '', @@ -1602,30 +1685,24 @@ public static function testAreValidHtmlAttributesUsingEmptyValue($emptyValue) self::assertFalse(Regex::areValidHtmlAttributes($emptyValue)); } - /** - * @param array $array The array that should be filtered - * @param string $arrayColumnKey Column name - * @param string $filterExpression Regular expression, e.g. "/\d+/" or "/[a-z]+[,;]{2,}/" - * @param array $expected Expected array - * - * @dataProvider provideRegularExpressionForArrayFiltering - */ - public function testArrayFilterUsingRegularExpression($array, $arrayColumnKey, $filterExpression, $expected) - { - self::assertEquals($expected, Regex::arrayFilter($array, $arrayColumnKey, $filterExpression, true)); + /** @dataProvider provideRegularExpressionForArrayFiltering */ + public function testArrayFilterUsingRegularExpression( + array $array, + string $arrayColumnKey, + string $filterExpression, + array $expected, + ): void { + self::assertEquals($expected, Regex::arrayFilter($array, $arrayColumnKey, $filterExpression)); } - /** - * @param array $array The array that should be filtered - * @param string $arrayColumnKey Column name - * @param string $filterExpression Simple filter expression, e.g. "== 2" or "!= \'home\'" - * @param array $expected Expected array - * - * @dataProvider provideSimpleExpressionForArrayFiltering - */ - public function testArrayFilterUsingSimpleExpression($array, $arrayColumnKey, $filterExpression, $expected) - { - self::assertEquals($expected, Regex::arrayFilter($array, $arrayColumnKey, $filterExpression)); + /** @dataProvider provideClosureForArrayFiltering */ + public function testArrayFilterUsingSimpleExpression( + array $array, + string $arrayColumnKey, + \Closure $filter, + array $expected, + ): void { + self::assertEquals($expected, Regex::arrayFilter($array, $arrayColumnKey, $filter)); } public function testCamelCase2humanReadable()