From 382ba9c18af2158badf5e3a3ad6e5ee502728d1e Mon Sep 17 00:00:00 2001 From: VerburgtJimmy Date: Thu, 14 May 2026 16:01:28 +0200 Subject: [PATCH] [6.x] Fix: Modify::__toString() throwing TypeError for non-string scalar values --- src/Modifiers/Modify.php | 16 ++++++++---- tests/Modifiers/FluentModifyTest.php | 38 ++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/Modifiers/Modify.php b/src/Modifiers/Modify.php index 417ec755fdd..e0972b986e8 100644 --- a/src/Modifiers/Modify.php +++ b/src/Modifiers/Modify.php @@ -90,13 +90,19 @@ public function fetch() */ public function __toString() { - if (! is_string($this->value) && ! method_exists($this->value, '__toString')) { - throw new ModifierException( - 'Attempted to access modified value as a string, but encountered ['.get_class($this->value).']' - ); + $value = $this->value; + + if ($value === null || is_scalar($value)) { + return (string) $value; + } + + if (is_object($value) && method_exists($value, '__toString')) { + return (string) $value; } - return (string) $this->value; + throw new ModifierException( + 'Attempted to access modified value as a string, but encountered ['.get_debug_type($value).']' + ); } /** diff --git a/tests/Modifiers/FluentModifyTest.php b/tests/Modifiers/FluentModifyTest.php index ab8b01997f3..2e4d22711d6 100644 --- a/tests/Modifiers/FluentModifyTest.php +++ b/tests/Modifiers/FluentModifyTest.php @@ -2,9 +2,11 @@ namespace Tests\Modifiers; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; use Statamic\Fields\Values; use Statamic\Modifiers\Modifier; +use Statamic\Modifiers\ModifierException; use Statamic\Modifiers\Modify; use Tests\TestCase; @@ -38,6 +40,42 @@ public function passing_a_values_instance_into_it_will_not_convert_it_to_an_arra $this->assertSame($values, $result); } + #[Test] + #[DataProvider('scalarValues')] + public function it_casts_scalar_and_null_values_to_string($value, $expected) + { + $this->assertSame($expected, (string) Modify::value($value)); + } + + public static function scalarValues() + { + return [ + 'integer zero' => [0, '0'], + 'positive integer' => [42, '42'], + 'negative integer' => [-7, '-7'], + 'float' => [1.5, '1.5'], + 'true' => [true, '1'], + 'false' => [false, ''], + 'null' => [null, ''], + 'string' => ['hello', 'hello'], + ]; + } + + #[Test] + public function it_casts_a_modified_integer_chain_result_to_string() + { + $this->assertSame('5', (string) Modify::value(0)->add(5)); + } + + #[Test] + public function it_throws_when_casting_an_array_to_string() + { + $this->expectException(ModifierException::class); + $this->expectExceptionMessage('Attempted to access modified value as a string, but encountered [array]'); + + (string) Modify::value(['foo' => 'bar']); + } + #[Test] public function values_instances_get_converted_to_an_array_when_passing_to_a_modifier() {