From b7dfa44d84b0b00b76d3fce302e3ba55a78882d7 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Fri, 7 Feb 2025 17:02:01 +0300 Subject: [PATCH 1/7] bump --- .github/workflows/build.yml | 2 +- .github/workflows/composer-require-checker.yml | 2 +- .github/workflows/mutation.yml | 2 +- .github/workflows/rector.yml | 2 +- .github/workflows/static.yml | 2 +- CHANGELOG.md | 3 ++- composer.json | 8 ++++---- src/Inflector.php | 2 ++ src/WildcardPattern.php | 2 ++ 9 files changed, 15 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3feaeef..54dfa76 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,4 +29,4 @@ jobs: os: >- ['ubuntu-latest', 'windows-latest'] php: >- - ['8.1', '8.2', '8.3'] + ['8.1', '8.2', '8.3', '8.4'] diff --git a/.github/workflows/composer-require-checker.yml b/.github/workflows/composer-require-checker.yml index a857bce..a93390b 100644 --- a/.github/workflows/composer-require-checker.yml +++ b/.github/workflows/composer-require-checker.yml @@ -31,4 +31,4 @@ jobs: os: >- ['ubuntu-latest'] php: >- - ['8.1', '8.2', '8.3'] + ['8.1', '8.2', '8.3', '8.4'] diff --git a/.github/workflows/mutation.yml b/.github/workflows/mutation.yml index 8150499..a56769e 100644 --- a/.github/workflows/mutation.yml +++ b/.github/workflows/mutation.yml @@ -27,6 +27,6 @@ jobs: os: >- ['ubuntu-latest'] php: >- - ['8.2'] + ['8.4'] secrets: STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }} diff --git a/.github/workflows/rector.yml b/.github/workflows/rector.yml index 457772a..5d6931d 100644 --- a/.github/workflows/rector.yml +++ b/.github/workflows/rector.yml @@ -21,4 +21,4 @@ jobs: os: >- ['ubuntu-latest'] php: >- - ['8.3'] + ['8.4'] diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index e33eca8..d03874d 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -29,4 +29,4 @@ jobs: os: >- ['ubuntu-latest'] php: >- - ['8.1', '8.2', '8.3'] + ['8.1', '8.2', '8.3', '8.4'] diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f201fc..dbc9982 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ - Bug #138: Explicitly mark nullable parameters (@ferrumfist) - Chg #140: Bump minimal required PHP version to 8.1 and minor refactoring (@vjik) - +- Chg #143: Change PHP constraint in `composer.json` to `~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0` (@vjik) + ## 2.5.0 January 19, 2025 - New #137: Add `StringHelper::matchAnyRegex()` method as a facade for `CombinedRegexp` (@vjik) diff --git a/composer.json b/composer.json index a0d8b45..8141195 100644 --- a/composer.json +++ b/composer.json @@ -28,16 +28,16 @@ } ], "require": { - "php": "^8.1", + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", "ext-mbstring": "*" }, "require-dev": { "maglnet/composer-require-checker": "^4.7.1", - "phpunit/phpunit": "^10.5.44", - "rector/rector": "^2.0.7", + "phpunit/phpunit": "^10.5.45", + "rector/rector": "^2.0.8", "roave/infection-static-analysis-plugin": "^1.35", "spatie/phpunit-watcher": "^1.24", - "vimeo/psalm": "^5.26.1" + "vimeo/psalm": "^5.26.1|^6.4.1" }, "autoload": { "psr-4": { diff --git a/src/Inflector.php b/src/Inflector.php index 521fc26..279ee7a 100644 --- a/src/Inflector.php +++ b/src/Inflector.php @@ -435,6 +435,7 @@ public function toPlural(string $input): string } foreach ($this->pluralizeRules as $rule => $replacement) { if (preg_match($rule, $input)) { + /** @var string `$rule` and `$replacement` always correct, so `preg_replace` always returns string */ return preg_replace($rule, $replacement, $input); } } @@ -459,6 +460,7 @@ public function toSingular(string $input): string foreach ($this->singularizeRules as $rule => $replacement) { if (preg_match($rule, $input)) { + /** @var string `$rule` and `$replacement` always correct, so `preg_replace` always returns string */ return preg_replace($rule, $replacement, $input); } } diff --git a/src/WildcardPattern.php b/src/WildcardPattern.php index 95e5206..f5b0e27 100644 --- a/src/WildcardPattern.php +++ b/src/WildcardPattern.php @@ -80,6 +80,7 @@ public function ignoreCase(bool $flag = true): self */ public static function isDynamic(string $pattern): bool { + /** @var string $pattern `$rule` and `$replacement` always correct, so `preg_replace` always returns string */ $pattern = preg_replace('/\\\\./', '', $pattern); return preg_match('/[*{?\[]/', $pattern) === 1; } @@ -93,6 +94,7 @@ public static function isDynamic(string $pattern): bool */ public static function quote(string $string): string { + /** @var string `$rule` and `$replacement` always correct, so `preg_replace` always returns string */ return preg_replace('#([\\\\?*\\[\\]])#', '\\\\$1', $string); } From 74b55650fbb3548c5b32939bb7b6e2ec02cef014 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Fri, 7 Feb 2025 17:25:06 +0300 Subject: [PATCH 2/7] stringshelper --- CHANGELOG.md | 1 - src/StringHelper.php | 12 ++++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 060b1be..9664018 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,6 @@ - Bug #138: Explicitly mark nullable parameters (@ferrumfist) - Chg #140: Bump minimal required PHP version to 8.1 and minor refactoring (@vjik) - Chg #143: Change PHP constraint in `composer.json` to `~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0` (@vjik) - - Bug #142: Check string on a valid UTF-8 in `StringHelper` methods: `trim()`, `ltrim()` and `rtrim()` (@vjik) - Bug #141: `StringHelper::parsePath()` for empty string returns path `['']` instead of `[]` before (@vjik) diff --git a/src/StringHelper.php b/src/StringHelper.php index 70c5f8b..60a21a6 100644 --- a/src/StringHelper.php +++ b/src/StringHelper.php @@ -417,6 +417,9 @@ public static function uppercaseFirstCharacter(string $string, string $encoding */ public static function uppercaseFirstCharacterInEachWord(string $string, string $encoding = 'UTF-8'): string { + /** + * @var array $words We assume that `$string` is valid UTF-8 string, so `preg_split()` never returns `false`. + */ $words = preg_split('/\s/u', $string, -1, PREG_SPLIT_NO_EMPTY); $wordsWithUppercaseFirstCharacter = array_map( @@ -472,7 +475,16 @@ public static function base64UrlDecode(string $input): string */ public static function split(string $string, string $separator = '\R'): array { + /** + * @var string $string We assume that `$string` is valid UTF-8 string, so `preg_replace()` never returns + * `false`. + */ $string = preg_replace('(^\s*|\s*$)', '', $string); + + /** + * @var array We assume that $separator is prepared by `preg_quote()` and $string is valid UTF-8 string, + * so `preg_split()` never returns `false`. + */ return preg_split('~\s*' . $separator . '\s*~u', $string, -1, PREG_SPLIT_NO_EMPTY); } From c6833e88b8d63d92df36a570ad12a8dbbbf6f5eb Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Fri, 7 Feb 2025 17:26:00 +0300 Subject: [PATCH 3/7] numerichelper --- src/NumericHelper.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/NumericHelper.php b/src/NumericHelper.php index 9a665cd..804b7fc 100644 --- a/src/NumericHelper.php +++ b/src/NumericHelper.php @@ -69,8 +69,11 @@ public static function normalize(mixed $value): string return $value ? '1' : '0'; } - $value = str_replace([' ', ','], ['', '.'], (string)$value); + $value = str_replace([' ', ','], ['', '.'], (string) $value); + /** + * @var string We assume that `$value` is valid UTF-8 string, so `preg_replace()` never returns `false`. + */ return preg_replace('/\.(?=.*\.)/', '', $value); } From d77bf12b801caef9ae2a5d0f49520d5ca39327f0 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Fri, 7 Feb 2025 17:40:13 +0300 Subject: [PATCH 4/7] inflector --- src/Inflector.php | 62 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/src/Inflector.php b/src/Inflector.php index 279ee7a..ea13d75 100644 --- a/src/Inflector.php +++ b/src/Inflector.php @@ -496,11 +496,15 @@ public function toSentence(string $input, bool $uppercaseAll = false): string */ public function toWords(string $input): string { - return mb_strtolower(trim(str_replace([ - '-', - '_', - '.', - ], ' ', preg_replace('/(?pascalCaseToId(preg_replace('/[^\pL\pN]+/u', '_', $input), '_', $strict); + /** + * @var string $input We assume that `$input` is valid UTF-8 string, so `preg_replace()` never returns `false`. + */ + $input = preg_replace('/[^\pL\pN]+/u', '_', $input); + return $this->pascalCaseToId($input, '_', $strict); } /** @@ -646,9 +664,21 @@ public function tableToClass(string $tableName): string public function toSlug(string $input, string $replacement = '-', bool $lowercase = true): string { $quotedReplacement = preg_quote($replacement, '/'); - // replace all non words character + + /** + * Replace all non-words character + * + * @var string $input We assume that `$input` and `$replacement` are valid UTF-8 strings, so `preg_replace()` + * never returns `false`. + */ $input = preg_replace('/[^a-zA-Z0-9]+/u', $replacement, $this->toTransliterated($input)); - // remove first and last replacements + + /** + * Remove first and last replacements + * + * @var string $input We assume that `$input` and `$quotedReplacement` are valid UTF-8 strings, so + * `preg_replace()` never returns `false`. + */ $input = preg_replace( "/^(?:$quotedReplacement)+|(?:$quotedReplacement)+$/u" . ($lowercase ? 'i' : ''), '', @@ -671,8 +701,6 @@ public function toSlug(string $input, string $replacement = '-', bool $lowercase * @param string|Transliterator|null $transliterator either a {@see \Transliterator} or a string * from which a {@see \Transliterator} can be built. If null, value set with {@see withTransliterator()} * or {@see TRANSLITERATE_LOOSE} is used. - * - * @return string */ public function toTransliterated(string $input, $transliterator = null): string { @@ -681,7 +709,11 @@ public function toTransliterated(string $input, $transliterator = null): string $transliterator = $this->transliterator; } - /* @noinspection PhpComposerExtensionStubsInspection */ + /** + * @noinspection PhpComposerExtensionStubsInspection + * @var string We assume that `$input` are valid UTF-8 strings and `$transliterator` is valid, so + * `preg_replace()` never returns `false`. + */ return transliterator_transliterate($transliterator, $input); } From 8cb4e0f37a2215719be2d9655a6a895c5ddc8b1a Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sun, 9 Feb 2025 11:58:30 +0300 Subject: [PATCH 5/7] fix --- src/Inflector.php | 16 ++++++++-------- src/NumericHelper.php | 2 +- src/StringHelper.php | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Inflector.php b/src/Inflector.php index ea13d75..2ac28ca 100644 --- a/src/Inflector.php +++ b/src/Inflector.php @@ -490,7 +490,7 @@ public function toSentence(string $input, bool $uppercaseAll = false): string * Converts a string into space-separated words. * For example, 'PostTag' will be converted to 'Post Tag'. * - * @param string $input The string to be converted. + * @param string $input The string to be converted. It must be valid UTF-8 string. * * @return string The resulting words. */ @@ -513,7 +513,7 @@ public function toWords(string $input): string * For example, 'PostTag' will be converted to 'post-tag'. * * @param string $input The string to be converted. - * @param string $separator The character used to concatenate the words in the ID. + * @param string $separator The character used to concatenate the words in the ID. It must be valid UTF-8 string. * @param bool $strict Whether to insert a separator between two consecutive uppercase chars, defaults to false. * * @return string The resulting ID. @@ -544,7 +544,7 @@ public function pascalCaseToId(string $input, string $separator = '-', bool $str * will remove non alphanumeric character from the word, so * "who's online" will be converted to "WhoSOnline". * - * @param string $input The word to PascalCase. + * @param string $input The word to PascalCase. It must be valid UTF-8 string. * * @return string PascalCased string. * @@ -566,7 +566,7 @@ public function toPascalCase(string $input): string /** * Returns a human-readable string. * - * @param string $input The string to humanize. + * @param string $input The string to humanize. It must be valid UTF-8 string. * @param bool $uppercaseWords Whether to set all words to uppercase or not. */ public function toHumanReadable(string $input, bool $uppercaseWords = false): string @@ -607,7 +607,7 @@ public function toCamelCase(string $input): string * It will remove non-alphanumeric character from the word, * so "who's online" will be converted to "who_s_online". * - * @param string $input The word to convert. + * @param string $input The word to convert. It must be valid UTF-8 string. * @param bool $strict Whether to insert a separator between two consecutive uppercase chars, defaults to true. * * @return string The "snake_cased" string. @@ -655,8 +655,8 @@ public function tableToClass(string $tableName): string * and removes the rest. You may customize characters map via $transliteration property * of the helper. * - * @param string $input An arbitrary string to convert. - * @param string $replacement The replacement to use for spaces. + * @param string $input An arbitrary string to convert. It must be valid UTF-8 string. + * @param string $replacement The replacement to use for spaces. It must be valid UTF-8 string. * @param bool $lowercase whether to return the string in lowercase or not. Defaults to `true`. * * @return string The converted string. @@ -697,7 +697,7 @@ public function toSlug(string $input, string $replacement = '-', bool $lowercase * * @noinspection PhpComposerExtensionStubsInspection * - * @param string $input Input string. + * @param string $input Input string. It must be valid UTF-8 string. * @param string|Transliterator|null $transliterator either a {@see \Transliterator} or a string * from which a {@see \Transliterator} can be built. If null, value set with {@see withTransliterator()} * or {@see TRANSLITERATE_LOOSE} is used. diff --git a/src/NumericHelper.php b/src/NumericHelper.php index 804b7fc..5f99ef3 100644 --- a/src/NumericHelper.php +++ b/src/NumericHelper.php @@ -53,7 +53,7 @@ public static function toOrdinal(mixed $value): string /** * Returns string representation of a number value without thousands separators and with dot as decimal separator. * - * @param bool|float|int|string|Stringable $value + * @param bool|float|int|string|Stringable $value String in `string` or `Stringable` must be valid UTF-8 string. * * @throws InvalidArgumentException if value is not scalar. */ diff --git a/src/StringHelper.php b/src/StringHelper.php index 60a21a6..d731255 100644 --- a/src/StringHelper.php +++ b/src/StringHelper.php @@ -410,7 +410,7 @@ public static function uppercaseFirstCharacter(string $string, string $encoding /** * Uppercase the first character of each word in a string. * - * @param string $string The string to be processed. + * @param string $string The string to be processed. It must be valid UTF-8 string. * @param string $encoding The encoding to use, defaults to "UTF-8". * * @see https://php.net/manual/en/function.ucwords.php @@ -469,9 +469,9 @@ public static function base64UrlDecode(string $input): string * Split a string to array with non-empty lines. * Whitespace from the beginning and end of a each line will be stripped. * - * @param string $string The input string. + * @param string $string The input string. It must be valid UTF-8 string. * @param string $separator The boundary string. It is a part of regular expression - * so should be taken into account or properly escaped with {@see preg_quote()}. + * so should be taken into account or properly escaped with {@see preg_quote()}. It must be valid UTF-8 string. */ public static function split(string $string, string $separator = '\R'): array { From 2c87323dd3ca294ac17282d0a4be99b1f92ebdec Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sun, 9 Feb 2025 18:22:20 +0300 Subject: [PATCH 6/7] Update src/Inflector.php Co-authored-by: Sergei Tigrov --- src/Inflector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Inflector.php b/src/Inflector.php index 2ac28ca..295fcf8 100644 --- a/src/Inflector.php +++ b/src/Inflector.php @@ -490,7 +490,7 @@ public function toSentence(string $input, bool $uppercaseAll = false): string * Converts a string into space-separated words. * For example, 'PostTag' will be converted to 'Post Tag'. * - * @param string $input The string to be converted. It must be valid UTF-8 string. + * @param string $input The valid UTF-8 string to be converted. * * @return string The resulting words. */ From 0c2c2e124603b065123d3c0c2468f9c84ba8436c Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sun, 9 Feb 2025 18:25:20 +0300 Subject: [PATCH 7/7] improve --- src/Inflector.php | 4 ++-- src/StringHelper.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Inflector.php b/src/Inflector.php index 295fcf8..ef15aea 100644 --- a/src/Inflector.php +++ b/src/Inflector.php @@ -566,7 +566,7 @@ public function toPascalCase(string $input): string /** * Returns a human-readable string. * - * @param string $input The string to humanize. It must be valid UTF-8 string. + * @param string $input The valid UTF-8 string to humanize. * @param bool $uppercaseWords Whether to set all words to uppercase or not. */ public function toHumanReadable(string $input, bool $uppercaseWords = false): string @@ -655,7 +655,7 @@ public function tableToClass(string $tableName): string * and removes the rest. You may customize characters map via $transliteration property * of the helper. * - * @param string $input An arbitrary string to convert. It must be valid UTF-8 string. + * @param string $input An arbitrary valid UTF-8 string to convert. * @param string $replacement The replacement to use for spaces. It must be valid UTF-8 string. * @param bool $lowercase whether to return the string in lowercase or not. Defaults to `true`. * diff --git a/src/StringHelper.php b/src/StringHelper.php index d731255..75b7c92 100644 --- a/src/StringHelper.php +++ b/src/StringHelper.php @@ -410,7 +410,7 @@ public static function uppercaseFirstCharacter(string $string, string $encoding /** * Uppercase the first character of each word in a string. * - * @param string $string The string to be processed. It must be valid UTF-8 string. + * @param string $string The valid UTF-8 string to be processed. * @param string $encoding The encoding to use, defaults to "UTF-8". * * @see https://php.net/manual/en/function.ucwords.php