From ef9113e722af1e2e7bbcee48c68fdb5596e9c26e Mon Sep 17 00:00:00 2001 From: Maxime Tassy Date: Fri, 27 Sep 2024 16:53:18 +0200 Subject: [PATCH] [11.x] Fix crash of method PreventsCircularRecursion::withoutRecursion() on mocked models (#52943) * fix: verify that onceable return is not null before accessing attribute * chore: fix code style --- .../Eloquent/Concerns/PreventsCircularRecursion.php | 4 ++++ ...atabaseConcernsPreventsCircularRecursionTest.php | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/Illuminate/Database/Eloquent/Concerns/PreventsCircularRecursion.php b/src/Illuminate/Database/Eloquent/Concerns/PreventsCircularRecursion.php index 27d69a98b1ae..85aa66d9cedc 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/PreventsCircularRecursion.php +++ b/src/Illuminate/Database/Eloquent/Concerns/PreventsCircularRecursion.php @@ -28,6 +28,10 @@ protected function withoutRecursion($callback, $default = null) $onceable = Onceable::tryFromTrace($trace, $callback); + if (is_null($onceable)) { + return call_user_func($callback); + } + $stack = static::getRecursiveCallStack($this); if (array_key_exists($onceable->hash, $stack)) { diff --git a/tests/Database/DatabaseConcernsPreventsCircularRecursionTest.php b/tests/Database/DatabaseConcernsPreventsCircularRecursionTest.php index c04e85957718..a35a6cd19447 100644 --- a/tests/Database/DatabaseConcernsPreventsCircularRecursionTest.php +++ b/tests/Database/DatabaseConcernsPreventsCircularRecursionTest.php @@ -3,6 +3,7 @@ namespace Illuminate\Tests\Database; use Illuminate\Database\Eloquent\Concerns\PreventsCircularRecursion; +use Mockery; use PHPUnit\Framework\TestCase; class DatabaseConcernsPreventsCircularRecursionTest extends TestCase @@ -172,6 +173,18 @@ public function testRecursiveCallsToCircularLinkedListCallsEachInstanceOnce() $this->assertEquals(3, $second->instanceStack); $this->assertEquals(3, $third->instanceStack); } + + public function testMockedModelCallToWithoutRecursionMethodWorks(): void + { + $mock = Mockery::mock(TestModel::class)->makePartial(); + + // Model toArray method implementation + $toArray = $mock->withoutRecursion( + fn () => array_merge($mock->attributesToArray(), $mock->relationsToArray()), + fn () => $mock->attributesToArray(), + ); + $this->assertEquals([], $toArray); + } } class PreventsCircularRecursionWithRecursiveMethod