Skip to content

Commit 38a6099

Browse files
[5.x] Allow passing computed fields via an associative array (#11528)
1 parent c576bcc commit 38a6099

8 files changed

+123
-4
lines changed

src/Data/StoresComputedFieldCallbacks.php

+12-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,19 @@ trait StoresComputedFieldCallbacks
99
{
1010
protected $computedFieldCallbacks;
1111

12-
public function computed(string $field, Closure $callback)
12+
/**
13+
* @param string|array $field
14+
*/
15+
public function computed($field, ?Closure $callback = null)
1316
{
17+
if (is_array($field)) {
18+
foreach ($field as $field_name => $field_callback) {
19+
$this->computedFieldCallbacks[$field_name] = $field_callback;
20+
}
21+
22+
return;
23+
}
24+
1425
$this->computedFieldCallbacks[$field] = $callback;
1526
}
1627

src/Data/StoresScopedComputedFieldCallbacks.php

+10-1
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,19 @@ trait StoresScopedComputedFieldCallbacks
1414

1515
/**
1616
* @param string|array $scopes
17+
* @param string|array $field
1718
*/
18-
public function computed($scopes, string $field, Closure $callback)
19+
public function computed($scopes, $field, ?Closure $callback = null)
1920
{
2021
foreach (Arr::wrap($scopes) as $scope) {
22+
if (is_array($field)) {
23+
foreach ($field as $field_name => $field_callback) {
24+
$this->computedFieldCallbacks["$scope.$field_name"] = $field_callback;
25+
}
26+
27+
continue;
28+
}
29+
2130
$this->computedFieldCallbacks["$scope.$field"] = $callback;
2231
}
2332
}

src/Facades/Collection.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* @method static void delete(\Statamic\Entries\Collection $collection)
1919
* @method static \Illuminate\Support\Collection whereStructured()
2020
* @method static \Illuminate\Support\Collection additionalPreviewTargets(string $handle)
21-
* @method static void computed(string|array $scopes, string $field, \Closure $callback)
21+
* @method static void computed(string|array $scopes, string|array $field, ?\Closure $callback = null)
2222
* @method static \Illuminate\Support\Collection getComputedCallbacks($collection)
2323
*
2424
* @see CollectionRepository

src/Facades/User.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
* @method static void delete(\Statamic\Contracts\Auth\User $user);
2222
* @method static \Statamic\Fields\Blueprint blueprint();
2323
* @method static \Illuminate\Support\Collection getComputedCallbacks()
24-
* @method static void computed(string $field, \Closure $callback)
24+
* @method static void computed(string|array $field, ?\Closure $callback = null)
2525
*
2626
* @see \Statamic\Contracts\Auth\UserRepository
2727
* @see \Statamic\Auth\User

tests/Auth/UserContractTests.php

+11
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,15 @@ public function it_gets_custom_computed_data()
9494
return $user->name().'\'s balance is $25 owing.';
9595
});
9696

97+
Facades\User::computed([
98+
'ocupation' => function ($user) {
99+
return 'Smuggler';
100+
},
101+
'vehicle' => function ($user) {
102+
return 'Millennium Falcon';
103+
},
104+
]);
105+
97106
$user = $this->makeUser()->data(['name' => 'Han Solo']);
98107

99108
$expectedData = [
@@ -102,6 +111,8 @@ public function it_gets_custom_computed_data()
102111

103112
$expectedComputedData = [
104113
'balance' => 'Han Solo\'s balance is $25 owing.',
114+
'ocupation' => 'Smuggler',
115+
'vehicle' => 'Millennium Falcon',
105116
];
106117

107118
$expectedValues = array_merge($expectedData, $expectedComputedData);

tests/Data/Entries/EntryTest.php

+11
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,15 @@ public function it_gets_custom_computed_data()
392392
return $entry->get('title').' AND MORE!';
393393
});
394394

395+
Facades\Collection::computed('articles', [
396+
'tags' => function ($entry) {
397+
return ['music', 'pop'];
398+
},
399+
'featured' => function ($entry) {
400+
return true;
401+
},
402+
]);
403+
395404
$collection = tap(Collection::make('articles'))->save();
396405
$entry = (new Entry)->collection($collection)->data(['title' => 'Pop Rocks']);
397406

@@ -401,6 +410,8 @@ public function it_gets_custom_computed_data()
401410

402411
$expectedComputedData = [
403412
'description' => 'Pop Rocks AND MORE!',
413+
'tags' => ['music', 'pop'],
414+
'featured' => true,
404415
];
405416

406417
$expectedValues = array_merge($expectedData, $expectedComputedData);

tests/Data/StoresComputedFieldCallbacksTest.php

+20
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,26 @@ public function it_can_store_computed_callback()
2626
'another_field' => $closureB,
2727
], $repository->getComputedCallbacks()->all());
2828
}
29+
30+
#[Test]
31+
public function it_can_store_multiple_computed_callbacks()
32+
{
33+
$repository = new FakeRepository;
34+
35+
$repository->computed([
36+
'some_field' => $closureA = function ($item, $value) {
37+
//
38+
},
39+
'another_field' => $closureB = function ($item, $value) {
40+
//
41+
},
42+
]);
43+
44+
$this->assertEquals([
45+
'some_field' => $closureA,
46+
'another_field' => $closureB,
47+
], $repository->getComputedCallbacks()->all());
48+
}
2949
}
3050

3151
class FakeRepository

tests/Data/StoresScopedComputedFieldCallbacksTest.php

+57
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,63 @@ public function it_can_store_scoped_computed_callbacks_for_multiple_scopes()
5454
'some_field' => $closure,
5555
], $repository->getComputedCallbacks('articles')->all());
5656
}
57+
58+
#[Test]
59+
public function it_can_store_multiple_scoped_computed_callbacks()
60+
{
61+
$repository = new FakeRepositoryWithScopedCallbacks;
62+
63+
$repository->computed('events', [
64+
'some_field' => $closureA = function ($item, $value) {
65+
//
66+
},
67+
]);
68+
69+
$repository->computed('articles', [
70+
'some_field' => $closureB = function ($item, $value) {
71+
//
72+
},
73+
'another_field' => $closureC = function ($item, $value) {
74+
//
75+
},
76+
]);
77+
78+
$this->assertEquals([
79+
'some_field' => $closureA,
80+
], $repository->getComputedCallbacks('events')->all());
81+
82+
$this->assertEquals([
83+
'some_field' => $closureB,
84+
'another_field' => $closureC,
85+
], $repository->getComputedCallbacks('articles')->all());
86+
87+
$this->assertEquals([], $repository->getComputedCallbacks('products')->all());
88+
}
89+
90+
#[Test]
91+
public function it_can_store_multiple_scoped_computed_callbacks_for_multiple_scopes()
92+
{
93+
$repository = new FakeRepositoryWithScopedCallbacks;
94+
95+
$repository->computed(['events', 'articles'], [
96+
'some_field' => $closureA = function ($item, $value) {
97+
//
98+
},
99+
'another_field' => $closureB = function ($item, $value) {
100+
//
101+
},
102+
]);
103+
104+
$this->assertEquals([
105+
'some_field' => $closureA,
106+
'another_field' => $closureB,
107+
], $repository->getComputedCallbacks('events')->all());
108+
109+
$this->assertEquals([
110+
'some_field' => $closureA,
111+
'another_field' => $closureB,
112+
], $repository->getComputedCallbacks('articles')->all());
113+
}
57114
}
58115

59116
class FakeRepositoryWithScopedCallbacks

0 commit comments

Comments
 (0)