Skip to content

Commit c2dd983

Browse files
authored
Fix model serialization on anonymous components (#39319)
* Fix model serialization on anonymous components * Apply fixes from StyleCI * no need to pass value * renaming Co-authored-by: Taylor Otwell <[email protected]>
1 parent c3fab4a commit c2dd983

File tree

7 files changed

+75
-5
lines changed

7 files changed

+75
-5
lines changed

src/Illuminate/Collections/Collection.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44

55
use ArrayAccess;
66
use ArrayIterator;
7+
use Illuminate\Contracts\Support\CanBeEscapedWhenCastToString;
78
use Illuminate\Support\Traits\EnumeratesValues;
89
use Illuminate\Support\Traits\Macroable;
910
use stdClass;
1011

11-
class Collection implements ArrayAccess, Enumerable
12+
class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerable
1213
{
1314
use EnumeratesValues, Macroable;
1415

src/Illuminate/Collections/LazyCollection.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
use ArrayIterator;
66
use Closure;
77
use DateTimeInterface;
8+
use Illuminate\Contracts\Support\CanBeEscapedWhenCastToString;
89
use Illuminate\Support\Traits\EnumeratesValues;
910
use Illuminate\Support\Traits\Macroable;
1011
use IteratorAggregate;
1112
use stdClass;
1213

13-
class LazyCollection implements Enumerable
14+
class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable
1415
{
1516
use EnumeratesValues, Macroable;
1617

src/Illuminate/Collections/Traits/EnumeratesValues.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@
4646
*/
4747
trait EnumeratesValues
4848
{
49+
/**
50+
* Indicates that the object's string representation should be escaped when __toString is invoked.
51+
*
52+
* @var bool
53+
*/
54+
protected $escapeWhenCastingToString = false;
55+
4956
/**
5057
* The methods that can be proxied.
5158
*
@@ -900,7 +907,22 @@ public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING)
900907
*/
901908
public function __toString()
902909
{
903-
return $this->toJson();
910+
return $this->escapeWhenCastingToString
911+
? e($this->toJson())
912+
: $this->toJson();
913+
}
914+
915+
/**
916+
* Indicate that the model's string representation should be escaped when __toString is invoked.
917+
*
918+
* @param bool $escape
919+
* @return $this
920+
*/
921+
public function escapeWhenCastingToString($escape = true)
922+
{
923+
$this->escapeWhenCastingToString = $escape;
924+
925+
return $this;
904926
}
905927

906928
/**
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Illuminate\Contracts\Support;
4+
5+
interface CanBeEscapedWhenCastToString
6+
{
7+
/**
8+
* Indicate that the object's string representation should be escaped when __toString is invoked.
9+
*
10+
* @param bool $escape
11+
* @return $this
12+
*/
13+
public function escapeWhenCastingToString($escape = true);
14+
}

src/Illuminate/Database/Eloquent/Model.php

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Illuminate\Contracts\Queue\QueueableEntity;
99
use Illuminate\Contracts\Routing\UrlRoutable;
1010
use Illuminate\Contracts\Support\Arrayable;
11+
use Illuminate\Contracts\Support\CanBeEscapedWhenCastToString;
1112
use Illuminate\Contracts\Support\Jsonable;
1213
use Illuminate\Database\ConnectionResolverInterface as Resolver;
1314
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
@@ -22,7 +23,7 @@
2223
use JsonSerializable;
2324
use LogicException;
2425

25-
abstract class Model implements Arrayable, ArrayAccess, HasBroadcastChannel, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable
26+
abstract class Model implements Arrayable, ArrayAccess, CanBeEscapedWhenCastToString, HasBroadcastChannel, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable
2627
{
2728
use Concerns\HasAttributes,
2829
Concerns\HasEvents,
@@ -110,6 +111,13 @@ abstract class Model implements Arrayable, ArrayAccess, HasBroadcastChannel, Jso
110111
*/
111112
public $wasRecentlyCreated = false;
112113

114+
/**
115+
* Indicates that the object's string representation should be escaped when __toString is invoked.
116+
*
117+
* @var bool
118+
*/
119+
protected $escapeWhenCastingToString = false;
120+
113121
/**
114122
* The connection resolver instance.
115123
*
@@ -2128,7 +2136,22 @@ public static function __callStatic($method, $parameters)
21282136
*/
21292137
public function __toString()
21302138
{
2131-
return $this->toJson();
2139+
return $this->escapeWhenCastingToString
2140+
? e($this->toJson())
2141+
: $this->toJson();
2142+
}
2143+
2144+
/**
2145+
* Indicate that the object's string representation should be escaped when __toString is invoked.
2146+
*
2147+
* @param bool $escape
2148+
* @return $this
2149+
*/
2150+
public function escapeWhenCastingToString($escape = true)
2151+
{
2152+
$this->escapeWhenCastingToString = $escape;
2153+
2154+
return $this;
21322155
}
21332156

21342157
/**

src/Illuminate/View/Compilers/Concerns/CompilesComponents.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Illuminate\View\Compilers\Concerns;
44

5+
use Illuminate\Contracts\Support\CanBeEscapedWhenCastToString;
56
use Illuminate\Support\Str;
67
use Illuminate\View\ComponentAttributeBag;
78

@@ -183,6 +184,10 @@ protected function compileAware($expression)
183184
*/
184185
public static function sanitizeComponentAttribute($value)
185186
{
187+
if (is_object($value) && $value instanceof CanBeEscapedWhenCastToString) {
188+
return $value->escapeWhenCastingToString();
189+
}
190+
186191
return is_string($value) ||
187192
(is_object($value) && ! $value instanceof ComponentAttributeBag && method_exists($value, '__toString'))
188193
? e($value)

tests/View/Blade/BladeComponentTagCompilerTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Container\Container;
66
use Illuminate\Contracts\Foundation\Application;
77
use Illuminate\Contracts\View\Factory;
8+
use Illuminate\Database\Eloquent\Model;
89
use Illuminate\View\Compilers\BladeCompiler;
910
use Illuminate\View\Compilers\ComponentTagCompiler;
1011
use Illuminate\View\Component;
@@ -291,10 +292,13 @@ public function __toString()
291292
}
292293
};
293294

295+
$model = new class extends Model {};
296+
294297
$this->assertEquals(e('<hi>'), BladeCompiler::sanitizeComponentAttribute('<hi>'));
295298
$this->assertEquals(e('1'), BladeCompiler::sanitizeComponentAttribute('1'));
296299
$this->assertEquals(1, BladeCompiler::sanitizeComponentAttribute(1));
297300
$this->assertEquals(e('<hi>'), BladeCompiler::sanitizeComponentAttribute($class));
301+
$this->assertSame($model, BladeCompiler::sanitizeComponentAttribute($model));
298302
}
299303

300304
public function testItThrowsAnExceptionForNonExistingAliases()

0 commit comments

Comments
 (0)