Skip to content

Commit 6f2a5fb

Browse files
[5.x] Detect recursion when augmenting Entries (#11854)
1 parent 6aa6081 commit 6f2a5fb

3 files changed

Lines changed: 49 additions & 0 deletions

File tree

src/Data/HasOrigin.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
namespace Statamic\Data;
44

5+
use Statamic\Exceptions\RecursiveAugmentationException;
56
use Statamic\Facades\Blink;
67

78
trait HasOrigin
89
{
10+
private $resolvingValues = false;
11+
912
/**
1013
* @var string
1114
*/
@@ -31,14 +34,33 @@ public function keys()
3134
->merge($computedKeys);
3235
}
3336

37+
private function guardRecursiveAugmentation()
38+
{
39+
if ($this->resolvingValues) {
40+
$className = get_class($this);
41+
throw new RecursiveAugmentationException("Recursion detected while augmenting [{$className}] with ID [{$this->id}].");
42+
}
43+
44+
$this->resolvingValues = true;
45+
}
46+
47+
private function ungardRecursiveAugmentation()
48+
{
49+
$this->resolvingValues = false;
50+
}
51+
3452
public function values()
3553
{
54+
$this->guardRecursiveAugmentation();
55+
3656
$originFallbackValues = method_exists($this, 'getOriginFallbackValues') ? $this->getOriginFallbackValues() : collect();
3757

3858
$originValues = $this->hasOrigin() ? $this->origin()->values() : collect();
3959

4060
$computedData = method_exists($this, 'computedData') ? $this->computedData() : [];
4161

62+
$this->ungardRecursiveAugmentation();
63+
4264
return collect()
4365
->merge($originFallbackValues)
4466
->merge($originValues)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Statamic\Exceptions;
4+
5+
class RecursiveAugmentationException extends \Exception
6+
{
7+
}

tests/Data/Entries/EntryTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
use Statamic\Events\EntryDeleting;
3030
use Statamic\Events\EntrySaved;
3131
use Statamic\Events\EntrySaving;
32+
use Statamic\Exceptions\RecursiveAugmentationException;
3233
use Statamic\Facades;
3334
use Statamic\Facades\Blink;
3435
use Statamic\Fields\Blueprint;
@@ -2678,4 +2679,23 @@ public function it_clones_internal_collections()
26782679
$this->assertEquals('A', $entry->getSupplement('bar'));
26792680
$this->assertEquals('B', $clone->getSupplement('bar'));
26802681
}
2682+
2683+
#[Test]
2684+
public function it_detects_recursive_augmentation()
2685+
{
2686+
$this->expectException(RecursiveAugmentationException::class);
2687+
$this->expectExceptionMessage('Recursion detected while augmenting [Statamic\Entries\Entry] with ID [entry-id]');
2688+
2689+
\Statamic\Facades\Collection::computed('test', 'the_value', function ($entry) {
2690+
// Trigger recursion that will bypass without computed values.
2691+
return $entry->routeData();
2692+
});
2693+
2694+
$entry = EntryFactory::id('entry-id')
2695+
->collection('test')
2696+
->slug('entry-slug')
2697+
->create();
2698+
2699+
$entry->values();
2700+
}
26812701
}

0 commit comments

Comments
 (0)