diff --git a/src/Illuminate/Collections/Collection.php b/src/Illuminate/Collections/Collection.php index b00c0074e3a7..a6e3e9349e97 100644 --- a/src/Illuminate/Collections/Collection.php +++ b/src/Illuminate/Collections/Collection.php @@ -4,11 +4,12 @@ use ArrayAccess; use ArrayIterator; +use Illuminate\Contracts\Support\CanBeEscapedWhenCastToString; use Illuminate\Support\Traits\EnumeratesValues; use Illuminate\Support\Traits\Macroable; use stdClass; -class Collection implements ArrayAccess, Enumerable +class Collection implements ArrayAccess, CanBeEscapedWhenCastToString, Enumerable { use EnumeratesValues, Macroable; diff --git a/src/Illuminate/Collections/LazyCollection.php b/src/Illuminate/Collections/LazyCollection.php index 5036772b7087..70f107061898 100644 --- a/src/Illuminate/Collections/LazyCollection.php +++ b/src/Illuminate/Collections/LazyCollection.php @@ -5,12 +5,13 @@ use ArrayIterator; use Closure; use DateTimeInterface; +use Illuminate\Contracts\Support\CanBeEscapedWhenCastToString; use Illuminate\Support\Traits\EnumeratesValues; use Illuminate\Support\Traits\Macroable; use IteratorAggregate; use stdClass; -class LazyCollection implements Enumerable +class LazyCollection implements CanBeEscapedWhenCastToString, Enumerable { use EnumeratesValues, Macroable; diff --git a/src/Illuminate/Collections/Traits/EnumeratesValues.php b/src/Illuminate/Collections/Traits/EnumeratesValues.php index d2944ffeb4db..9eb31ea851c5 100644 --- a/src/Illuminate/Collections/Traits/EnumeratesValues.php +++ b/src/Illuminate/Collections/Traits/EnumeratesValues.php @@ -46,6 +46,13 @@ */ trait EnumeratesValues { + /** + * Indicates that the object's string representation should be escaped when __toString is invoked. + * + * @var bool + */ + protected $escapeWhenCastingToString = false; + /** * The methods that can be proxied. * @@ -900,7 +907,22 @@ public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING) */ public function __toString() { - return $this->toJson(); + return $this->escapeWhenCastingToString + ? e($this->toJson()) + : $this->toJson(); + } + + /** + * Indicate that the model's string representation should be escaped when __toString is invoked. + * + * @param bool $escape + * @return $this + */ + public function escapeWhenCastingToString($escape = true) + { + $this->escapeWhenCastingToString = $escape; + + return $this; } /** diff --git a/src/Illuminate/Contracts/Support/CanBeEscapedWhenCastToString.php b/src/Illuminate/Contracts/Support/CanBeEscapedWhenCastToString.php new file mode 100644 index 000000000000..e1be6fefac16 --- /dev/null +++ b/src/Illuminate/Contracts/Support/CanBeEscapedWhenCastToString.php @@ -0,0 +1,14 @@ +toJson(); + return $this->escapeWhenCastingToString + ? e($this->toJson()) + : $this->toJson(); + } + + /** + * Indicate that the object's string representation should be escaped when __toString is invoked. + * + * @param bool $escape + * @return $this + */ + public function escapeWhenCastingToString($escape = true) + { + $this->escapeWhenCastingToString = $escape; + + return $this; } /** diff --git a/src/Illuminate/View/Compilers/Concerns/CompilesComponents.php b/src/Illuminate/View/Compilers/Concerns/CompilesComponents.php index 143594acebaf..706e1b393c40 100644 --- a/src/Illuminate/View/Compilers/Concerns/CompilesComponents.php +++ b/src/Illuminate/View/Compilers/Concerns/CompilesComponents.php @@ -2,6 +2,7 @@ namespace Illuminate\View\Compilers\Concerns; +use Illuminate\Contracts\Support\CanBeEscapedWhenCastToString; use Illuminate\Support\Str; use Illuminate\View\ComponentAttributeBag; @@ -183,6 +184,10 @@ protected function compileAware($expression) */ public static function sanitizeComponentAttribute($value) { + if (is_object($value) && $value instanceof CanBeEscapedWhenCastToString) { + return $value->escapeWhenCastingToString(); + } + return is_string($value) || (is_object($value) && ! $value instanceof ComponentAttributeBag && method_exists($value, '__toString')) ? e($value) diff --git a/tests/View/Blade/BladeComponentTagCompilerTest.php b/tests/View/Blade/BladeComponentTagCompilerTest.php index eafec7d047d7..e3a055ba8d99 100644 --- a/tests/View/Blade/BladeComponentTagCompilerTest.php +++ b/tests/View/Blade/BladeComponentTagCompilerTest.php @@ -5,6 +5,7 @@ use Illuminate\Container\Container; use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\View\Factory; +use Illuminate\Database\Eloquent\Model; use Illuminate\View\Compilers\BladeCompiler; use Illuminate\View\Compilers\ComponentTagCompiler; use Illuminate\View\Component; @@ -291,10 +292,13 @@ public function __toString() } }; + $model = new class extends Model {}; + $this->assertEquals(e(''), BladeCompiler::sanitizeComponentAttribute('')); $this->assertEquals(e('1'), BladeCompiler::sanitizeComponentAttribute('1')); $this->assertEquals(1, BladeCompiler::sanitizeComponentAttribute(1)); $this->assertEquals(e(''), BladeCompiler::sanitizeComponentAttribute($class)); + $this->assertSame($model, BladeCompiler::sanitizeComponentAttribute($model)); } public function testItThrowsAnExceptionForNonExistingAliases()