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));
+ }
+}