diff --git a/composer.json b/composer.json index 05e120ce..f2d5b4d8 100644 --- a/composer.json +++ b/composer.json @@ -38,9 +38,9 @@ "laminas/laminas-stdlib": "^3.19.0" }, "require-dev": { - "laminas/laminas-coding-standard": "~3.0", + "laminas/laminas-coding-standard": "^3.0.1", "pear/archive_tar": "^1.5.0", - "phpunit/phpunit": "^10.5.36", + "phpunit/phpunit": "^10.5.38", "psalm/plugin-phpunit": "^0.19.0", "psr/http-factory": "^1.1.0", "vimeo/psalm": "^5.26.1" diff --git a/composer.lock b/composer.lock index 49d3af3b..8f09121d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a11f92d6c05080b1c3efb2cf1d5c5f47", + "content-hash": "43703f8533bfcdad21cac935edc7c54f", "packages": [ { "name": "brick/varexporter", @@ -57,16 +57,16 @@ }, { "name": "laminas/laminas-servicemanager", - "version": "4.2.0", + "version": "4.2.1", "source": { "type": "git", "url": "https://github.com/laminas/laminas-servicemanager.git", - "reference": "a8489e352de3ce3f1eaf34a354b1e5f2ad2db85c" + "reference": "e18a45410d6f4ecb6253ade3ba42131ef2d4a883" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/a8489e352de3ce3f1eaf34a354b1e5f2ad2db85c", - "reference": "a8489e352de3ce3f1eaf34a354b1e5f2ad2db85c", + "url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/e18a45410d6f4ecb6253ade3ba42131ef2d4a883", + "reference": "e18a45410d6f4ecb6253ade3ba42131ef2d4a883", "shasum": "" }, "require": { @@ -132,7 +132,7 @@ "chat": "https://laminas.dev/chat", "forum": "https://discourse.laminas.dev", "issues": "https://github.com/laminas/laminas-servicemanager/issues", - "source": "https://github.com/laminas/laminas-servicemanager/tree/4.2.0" + "source": "https://github.com/laminas/laminas-servicemanager/tree/4.2.1" }, "funding": [ { @@ -140,34 +140,34 @@ "type": "community_bridge" } ], - "time": "2024-07-04T09:40:44+00:00" + "time": "2024-10-22T13:30:53+00:00" }, { "name": "laminas/laminas-stdlib", - "version": "3.19.0", + "version": "3.20.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-stdlib.git", - "reference": "6a192dd0882b514e45506f533b833b623b78fff3" + "reference": "8974a1213be42c3e2f70b2c27b17f910291ab2f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/6a192dd0882b514e45506f533b833b623b78fff3", - "reference": "6a192dd0882b514e45506f533b833b623b78fff3", + "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/8974a1213be42c3e2f70b2c27b17f910291ab2f4", + "reference": "8974a1213be42c3e2f70b2c27b17f910291ab2f4", "shasum": "" }, "require": { - "php": "~8.1.0 || ~8.2.0 || ~8.3.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "conflict": { "zendframework/zend-stdlib": "*" }, "require-dev": { - "laminas/laminas-coding-standard": "^2.5", - "phpbench/phpbench": "^1.2.15", - "phpunit/phpunit": "^10.5.8", - "psalm/plugin-phpunit": "^0.18.4", - "vimeo/psalm": "^5.20.0" + "laminas/laminas-coding-standard": "^3.0", + "phpbench/phpbench": "^1.3.1", + "phpunit/phpunit": "^10.5.38", + "psalm/plugin-phpunit": "^0.19.0", + "vimeo/psalm": "^5.26.1" }, "type": "library", "autoload": { @@ -199,7 +199,7 @@ "type": "community_bridge" } ], - "time": "2024-01-19T12:39:49+00:00" + "time": "2024-10-29T13:46:07+00:00" }, { "name": "nikic/php-parser", @@ -2151,16 +2151,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.36", + "version": "10.5.38", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "aa0a8ce701ea7ee314b0dfaa8970dc94f3f8c870" + "reference": "a86773b9e887a67bc53efa9da9ad6e3f2498c132" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/aa0a8ce701ea7ee314b0dfaa8970dc94f3f8c870", - "reference": "aa0a8ce701ea7ee314b0dfaa8970dc94f3f8c870", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a86773b9e887a67bc53efa9da9ad6e3f2498c132", + "reference": "a86773b9e887a67bc53efa9da9ad6e3f2498c132", "shasum": "" }, "require": { @@ -2181,7 +2181,7 @@ "phpunit/php-timer": "^6.0.0", "sebastian/cli-parser": "^2.0.1", "sebastian/code-unit": "^2.0.0", - "sebastian/comparator": "^5.0.2", + "sebastian/comparator": "^5.0.3", "sebastian/diff": "^5.1.1", "sebastian/environment": "^6.1.0", "sebastian/exporter": "^5.1.2", @@ -2232,7 +2232,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.36" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.38" }, "funding": [ { @@ -2248,7 +2248,7 @@ "type": "tidelift" } ], - "time": "2024-10-08T15:36:51+00:00" + "time": "2024-10-28T13:06:21+00:00" }, { "name": "psalm/plugin-phpunit", @@ -2638,16 +2638,16 @@ }, { "name": "sebastian/comparator", - "version": "5.0.2", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53" + "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53", - "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", + "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", "shasum": "" }, "require": { @@ -2658,7 +2658,7 @@ "sebastian/exporter": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^10.4" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { @@ -2703,7 +2703,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.2" + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.3" }, "funding": [ { @@ -2711,7 +2711,7 @@ "type": "github" } ], - "time": "2024-08-12T06:03:08+00:00" + "time": "2024-10-18T14:56:07+00:00" }, { "name": "sebastian/complexity", @@ -3599,16 +3599,16 @@ }, { "name": "symfony/console", - "version": "v6.4.12", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "72d080eb9edf80e36c19be61f72c98ed8273b765" + "reference": "f793dd5a7d9ae9923e35d0503d08ba734cec1d79" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/72d080eb9edf80e36c19be61f72c98ed8273b765", - "reference": "72d080eb9edf80e36c19be61f72c98ed8273b765", + "url": "https://api.github.com/repos/symfony/console/zipball/f793dd5a7d9ae9923e35d0503d08ba734cec1d79", + "reference": "f793dd5a7d9ae9923e35d0503d08ba734cec1d79", "shasum": "" }, "require": { @@ -3673,7 +3673,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.12" + "source": "https://github.com/symfony/console/tree/v6.4.13" }, "funding": [ { @@ -3689,7 +3689,7 @@ "type": "tidelift" } ], - "time": "2024-09-20T08:15:52+00:00" + "time": "2024-10-09T08:40:40+00:00" }, { "name": "symfony/deprecation-contracts", @@ -3760,16 +3760,16 @@ }, { "name": "symfony/filesystem", - "version": "v6.4.12", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "f810e3cbdf7fdc35983968523d09f349fa9ada12" + "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/f810e3cbdf7fdc35983968523d09f349fa9ada12", - "reference": "f810e3cbdf7fdc35983968523d09f349fa9ada12", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/4856c9cf585d5a0313d8d35afd681a526f038dd3", + "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3", "shasum": "" }, "require": { @@ -3806,7 +3806,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.12" + "source": "https://github.com/symfony/filesystem/tree/v6.4.13" }, "funding": [ { @@ -3822,7 +3822,7 @@ "type": "tidelift" } ], - "time": "2024-09-16T16:01:33+00:00" + "time": "2024-10-25T15:07:50+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4227,16 +4227,16 @@ }, { "name": "symfony/string", - "version": "v6.4.12", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "f8a1ccebd0997e16112dfecfd74220b78e5b284b" + "reference": "38371c60c71c72b3d64d8d76f6b1bb81a2cc3627" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f8a1ccebd0997e16112dfecfd74220b78e5b284b", - "reference": "f8a1ccebd0997e16112dfecfd74220b78e5b284b", + "url": "https://api.github.com/repos/symfony/string/zipball/38371c60c71c72b3d64d8d76f6b1bb81a2cc3627", + "reference": "38371c60c71c72b3d64d8d76f6b1bb81a2cc3627", "shasum": "" }, "require": { @@ -4293,7 +4293,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.12" + "source": "https://github.com/symfony/string/tree/v6.4.13" }, "funding": [ { @@ -4309,7 +4309,7 @@ "type": "tidelift" } ], - "time": "2024-09-20T08:15:52+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "theseer/tokenizer", diff --git a/docs/book/v2/standard-filters.md b/docs/book/v2/standard-filters.md index 09cbce30..7fc5e2b1 100644 --- a/docs/book/v2/standard-filters.md +++ b/docs/book/v2/standard-filters.md @@ -1440,6 +1440,27 @@ instead. Users pulling their `Null` filter instance from the filter plugin manager receive a `ToNull` instance instead starting in 2.4.0. +## ToString + +The `ToString` filter casts `Stringable` objects or scalar values to `string`. +This filter has no runtime options. + +### Basic Usage + +```php +$filter = new \Laminas\Filter\ToString(); + +$filter->filter(123); // "123" +``` + +Non-scalar input will be returned un-filtered: + +```php +$filter = new \Laminas\Filter\ToString(); + +$filter->filter(['muppet' => 'Kermit']); // ['muppet' => 'Kermit'] +``` + ## NumberFormat The `NumberFormat` filter can be used to return locale-specific number and percentage strings. It diff --git a/docs/book/v3/standard-filters.md b/docs/book/v3/standard-filters.md index 2a41d743..df554c3b 100644 --- a/docs/book/v3/standard-filters.md +++ b/docs/book/v3/standard-filters.md @@ -969,6 +969,27 @@ $filter = new Laminas\Filter\ToNull([ It is best practice is to use the `TYPE_*` constants rather than the human-readable strings. Modern IDEs will autocomplete these for you and usage and refactoring is easier. +## ToString + +The `ToString` filter casts `Stringable` objects or scalar values to `string`. +This filter has no runtime options. + +### Basic Usage + +```php +$filter = new \Laminas\Filter\ToString(); + +$filter->filter(123); // "123" +``` + +Non-scalar input will be returned un-filtered: + +```php +$filter = new \Laminas\Filter\ToString(); + +$filter->filter(['muppet' => 'Kermit']); // ['muppet' => 'Kermit'] +``` + ## NumberFormat The `NumberFormat` filter can be used to return locale-specific number and percentage strings. It diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 9e89f811..c27a83a3 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -581,6 +581,10 @@ + + + + @@ -954,6 +958,12 @@ + + + + + + diff --git a/src/FilterPluginManager.php b/src/FilterPluginManager.php index a2310ee8..bbdc10e3 100644 --- a/src/FilterPluginManager.php +++ b/src/FilterPluginManager.php @@ -62,6 +62,7 @@ final class FilterPluginManager extends AbstractPluginManager StripTags::class => InvokableFactory::class, ToInt::class => InvokableFactory::class, ToNull::class => InvokableFactory::class, + ToString::class => InvokableFactory::class, Word\CamelCaseToDash::class => InvokableFactory::class, Word\CamelCaseToSeparator::class => InvokableFactory::class, Word\CamelCaseToUnderscore::class => InvokableFactory::class, diff --git a/src/ToString.php b/src/ToString.php new file mode 100644 index 00000000..ffebd9de --- /dev/null +++ b/src/ToString.php @@ -0,0 +1,35 @@ + */ +final class ToString implements FilterInterface +{ + /** + * Returns (string) $value + * + * If the value provided is non-scalar, the value will remain unfiltered + */ + public function filter(mixed $value): mixed + { + if ( + ! is_scalar($value) + && ! $value instanceof Stringable + ) { + return $value; + } + + return (string) $value; + } + + public function __invoke(mixed $value): mixed + { + return $this->filter($value); + } +} diff --git a/src/Word/AbstractSeparator.php b/src/Word/AbstractSeparator.php index 969e4f7f..2f925e4a 100644 --- a/src/Word/AbstractSeparator.php +++ b/src/Word/AbstractSeparator.php @@ -34,13 +34,20 @@ public function __construct(string|array $separator = ' ') $this->setSeparator($separator); } - /** @return $this */ + /** + * @deprecated Since 2.39.0 All option setters and getters will be removed in version 3.0 + * + * @return $this + */ public function setSeparator(string $separator): self { $this->separator = $separator; return $this; } + /** + * @deprecated Since 2.39.0 All option setters and getters will be removed in version 3.0 + */ public function getSeparator(): string { return $this->separator; diff --git a/test/TestAsset/StringClass.php b/test/TestAsset/StringClass.php new file mode 100644 index 00000000..86a03ea0 --- /dev/null +++ b/test/TestAsset/StringClass.php @@ -0,0 +1,20 @@ +string; + } +} diff --git a/test/ToStringTest.php b/test/ToStringTest.php new file mode 100644 index 00000000..e5b0cffc --- /dev/null +++ b/test/ToStringTest.php @@ -0,0 +1,65 @@ + */ + public static function returnBasicDataProvider(): array + { + return [ + [0, '0'], + ['string', 'string'], + [false, ''], + [-1.1, '-1.1'], + [new StringClass('test'), 'test'], + ]; + } + + #[DataProvider('returnBasicDataProvider')] + public function testBasic(mixed $input, string $output): void + { + $filter = new ToString(); + + self::assertSame($output, $filter->filter($input)); + } + + #[DataProvider('returnBasicDataProvider')] + public function testInvoke(mixed $input, string $output): void + { + $filter = new ToString(); + + self::assertSame($output, $filter->__invoke($input)); + } + + /** @return list */ + public static function returnUnfilteredDataProvider(): array + { + return [ + [null], + [new stdClass()], + [ + [ + 'foo', + false, + ], + ], + ]; + } + + #[DataProvider('returnUnfilteredDataProvider')] + public function testReturnUnfiltered(mixed $input): void + { + $filter = new ToString(); + + self::assertSame($input, $filter($input)); + } +}