Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
0b63d8b
Change `read_only` toggle in field config to `visibility` select.
jesseleite Apr 29, 2022
767faec
Normalize field visibility in `toPublishArray()`.
jesseleite Apr 29, 2022
10d8b85
Rename this method for clarity versus publish visibility.
jesseleite Apr 29, 2022
eb63c0f
Update English instruction text.
jesseleite Apr 29, 2022
1e38ca6
Use new `visibility` read only state on publish forms.
jesseleite Apr 29, 2022
5b75060
Normalize visibility in field transformer for blueprint edit form, etc.
jesseleite Apr 29, 2022
6d17e5e
Wire up `hidden` visibility state on publish forms.
jesseleite Apr 29, 2022
c084503
Clean up fallback logic for old `read_only` boolean config.
jesseleite Apr 29, 2022
29db265
Update the other references to old `read_only` field config.
jesseleite Apr 29, 2022
6e825c7
Remove old translation instructions for other languages.
jesseleite Apr 29, 2022
8eb2bd7
Pass tests again.
jesseleite Apr 29, 2022
4e480cb
Move this logic into our `showField()` handler.
jesseleite Apr 29, 2022
bd7c7d2
Be super clear in VueX state that nothing is getting omitted unless e…
jesseleite Apr 29, 2022
81a6f39
Deprecate old `read_only` field config for addon fieldtypes.
jesseleite Apr 29, 2022
068c672
Pass tests again.
jesseleite Apr 29, 2022
cced197
Add hidden state to width selector.
jesseleite Apr 29, 2022
9260eea
Merge branch '3.3' of https://github.com/statamic/cms into feature/co…
jesseleite Jun 6, 2022
85edf49
Revert `nextTick` from #6021; Everything seems to work now without it?
jesseleite Jun 7, 2022
0897273
Re-implement changes since merge conflict.
jesseleite Jun 7, 2022
dd6e88c
Re-implement styles since merge conflict.
jesseleite Jun 7, 2022
d01892f
Bring back `nextTick` to ensure revealers are properly loaded before …
jesseleite Jun 7, 2022
2d442ac
Wip.
jesseleite Jun 3, 2022
cc2cb74
Reject `computed` fields from `$fields->values()`.
jesseleite Jun 8, 2022
3f864d8
Add test coverage.
jesseleite Jun 8, 2022
1c3a634
Ensure `computed` fields are still available on `preProcess()`’d valu…
jesseleite Jun 8, 2022
5d55a4f
For JSON Varga <3.
jesseleite Jun 8, 2022
483ac82
Merge branch '3.3' of https://github.com/statamic/cms into feature/co…
jesseleite Jun 8, 2022
dd15e32
Merge changes from feature/customizable-user-listing-columns
jesseleite Jun 28, 2022
50e2209
Add ability to set and get computed field callbacks.
jesseleite Jun 28, 2022
4d7dd61
Add `computedData()` method to `ContainsData`.
jesseleite Jun 28, 2022
25ec3d5
Hook up computed fields on users.
jesseleite Jun 28, 2022
b24cbb2
Hook up computed fields on entries.
jesseleite Jun 28, 2022
0438432
Merge computed data into `values()` and `value()` on `HasOrigin`.
jesseleite Jun 28, 2022
d6587f1
Add computed value handling to `get()` on user implementations.
jesseleite Jun 28, 2022
eaaf0c4
Add `computed()` sugar to `User` facade/repository.
jesseleite Jun 28, 2022
ce0af93
Add `computed()` sugar to `Collection` facade/repository.
jesseleite Jun 28, 2022
47d95b5
Merge branch '3.3' of https://github.com/statamic/cms into feature/co…
jesseleite Jun 30, 2022
18b5542
Add test coverage for file users.
jesseleite Jun 30, 2022
b119327
Move user computed field tests to `UserContractTests` trait to test b…
jesseleite Jul 1, 2022
412e070
Remove callback storage from `Statamic\Statamic`.
jesseleite Jul 1, 2022
4e14758
Remove `computed()` setters from user and collection repositories (tr…
jesseleite Jul 1, 2022
ba46931
Remove `computedDataPrefix()` from User and Entry classes (trait inco…
jesseleite Jul 1, 2022
22cfc0e
Remove `computedData()` from ContainsData trait (new trait incoming).
jesseleite Jul 1, 2022
371ee58
Add new repository trait for storing callbacks on repositories.
jesseleite Jul 1, 2022
b10adb1
Add new trait for getting `computedData()` on data objects.
jesseleite Jul 1, 2022
21cc21a
Remove old computed data handling from `value()`.
jesseleite Jul 1, 2022
d08781d
Hook up computed data on users.
jesseleite Jul 1, 2022
4837ddd
Cannot define property on both class and trait, so just check if it e…
jesseleite Jul 1, 2022
8169e2d
Add test coverage for computed data on entries.
jesseleite Jul 1, 2022
72f5b23
Hook up computed data on entries.
jesseleite Jul 1, 2022
7e05be3
Test scoped and non-scoped field arguments on `computed()` setter in …
jesseleite Jul 1, 2022
18cb87a
Test that computed data is passed through entry `values()` as well.
jesseleite Jul 1, 2022
c2a40d7
Ensure computed fields on entries are scoped properly by collection.
jesseleite Jul 1, 2022
103840f
Merge branch '3.3' of https://github.com/statamic/cms into feature/co…
jesseleite Jul 1, 2022
5fff9f6
Merge branch '3.3' of https://github.com/statamic/cms into feature/co…
jesseleite Jul 22, 2022
d76c638
Pass these tests again.
jesseleite Jul 22, 2022
9cf4153
Move hidden logic out of width selector
jasonvarga Jun 29, 2022
e50cd62
Add tests to ensure user cannot cause recursive `computedData()` call…
jesseleite Jul 22, 2022
7818140
Move `computedValue()` logic from User classes to `ContainsComputedDa…
jesseleite Jul 22, 2022
f94c8ab
Simplify User `value()` computed logic by calling trait helpers.
jesseleite Jul 22, 2022
6f31ab3
Don’t expose these as public methods.
jesseleite Jul 22, 2022
d36c7aa
Merge `data()` with `computedData()` for publish forms as well.
jesseleite Jul 22, 2022
77a72bf
Move this method to abstract User class, since they are same.
jesseleite Jul 22, 2022
2e771d9
Make while loop handle both the entry and it’s origin(s).
jesseleite Jul 22, 2022
c1e0f56
Test we can use origin data to compose computed data.
jesseleite Jul 22, 2022
ad5da1f
Both implementations have `data()` method.
jesseleite Jul 22, 2022
841b364
Trait origin handling improvements.
jesseleite Jul 22, 2022
821c8b0
Use new `getOriginFallbackValues/Value` methods on Entry.
jesseleite Jul 22, 2022
c8d3f96
Pass these tests again.
jesseleite Jul 22, 2022
f90452f
Use reworked `getComputed()` method here.
jesseleite Jul 22, 2022
adc1d98
Fix recursion issue elsewhere in tests.
jesseleite Jul 23, 2022
37cd8ac
Also mock this.
jesseleite Jul 23, 2022
9d861b1
Ensure computed fields render as read-only on publish forms.
jesseleite Jul 23, 2022
f21986f
Rename `$attribute` to `$value` here too.
jesseleite Jul 23, 2022
4e12858
Ensure we add computed data to fields on user edit form as well.
jesseleite Jul 23, 2022
89d1cb5
Merge branch '3.3' into feature/computed-field-visibility
jasonvarga Oct 14, 2022
6faf5fd
private
jasonvarga Oct 19, 2022
319dacc
Split single magic trait into two simpler traits
jasonvarga Oct 19, 2022
d79d89d
short closures
jasonvarga Oct 19, 2022
f9741ce
No need to support the optional dot
jasonvarga Oct 19, 2022
a406454
nitpick
jasonvarga Oct 19, 2022
6236e92
add method hints to facades
jasonvarga Oct 19, 2022
95aa0b2
nitpick
jasonvarga Oct 19, 2022
283d5f5
Make the computed variables available to the create entry form
jasonvarga Oct 19, 2022
09c03f4
no longer needed
jasonvarga Oct 19, 2022
7f1f8e7
adjust test so that method_exists is only mocked in the test that nee…
jasonvarga Oct 19, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion resources/js/components/fieldtypes/Fieldtype.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ export default {
},

isReadOnly() {
return this.readOnly || this.config.visibility === 'read_only' || false;
return this.readOnly
|| this.config.visibility === 'read_only'
|| this.config.visibility === 'computed'
|| false;
},

replicatorPreview() {
Expand Down
5 changes: 0 additions & 5 deletions src/Auth/Eloquent/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -284,11 +284,6 @@ public function get($key, $default = null)
return is_null($value) ? $default : $value;
}

public function value($key)
{
return $this->get($key);
}

public function set($key, $value)
{
if ($key === 'password') {
Expand Down
5 changes: 0 additions & 5 deletions src/Auth/File/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,6 @@ public function data($data = null)
return $this;
}

public function value($key)
{
return $this->get($key);
}

public function id($id = null)
{
return $this->fluentlyGetOrSet('id')->args(func_get_args());
Expand Down
21 changes: 18 additions & 3 deletions src/Auth/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Statamic\Contracts\Data\Augmentable;
use Statamic\Contracts\Data\Augmented;
use Statamic\Contracts\GraphQL\ResolvesValues as ResolvesValuesContract;
use Statamic\Data\ContainsComputedData;
use Statamic\Data\HasAugmentedInstance;
use Statamic\Data\TracksQueriedColumns;
use Statamic\Data\TracksQueriedRelations;
Expand All @@ -42,21 +43,30 @@ abstract class User implements
ArrayAccess,
Arrayable
{
use Authorizable, Notifiable, CanResetPassword, HasAugmentedInstance, TracksQueriedColumns, TracksQueriedRelations, HasAvatar, ResolvesValues;
use Authorizable, Notifiable, CanResetPassword, HasAugmentedInstance, TracksQueriedColumns, TracksQueriedRelations, HasAvatar, ResolvesValues, ContainsComputedData;

protected $afterSaveCallbacks = [];
protected $withEvents = true;

abstract public function get($key, $fallback = null);
abstract public function data($data = null);

abstract public function value($key);
abstract public function get($key, $fallback = null);

abstract public function has($key);

abstract public function set($key, $value);

abstract public function remove($key);

public function value($key)
{
if ($this->hasComputedCallback($key)) {
return $this->getComputed($key);
}

return $this->get($key);
}

public function reference()
{
return "user::{$this->id()}";
Expand Down Expand Up @@ -285,4 +295,9 @@ public function setPreferredLocale($locale)
{
return $this->setPreference('locale', $locale);
}

protected function getComputedCallbacks()
{
return Facades\User::getComputedCallbacks();
}
}
3 changes: 3 additions & 0 deletions src/Auth/UserRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@

use Statamic\Contracts\Auth\User;
use Statamic\Contracts\Auth\UserRepository as RepositoryContract;
use Statamic\Data\StoresComputedFieldCallbacks;
use Statamic\Events\UserBlueprintFound;
use Statamic\Facades\Blueprint;
use Statamic\OAuth\Provider;

abstract class UserRepository implements RepositoryContract
{
use StoresComputedFieldCallbacks;

public function create()
{
// TODO: Factory?
Expand Down
46 changes: 46 additions & 0 deletions src/Data/ContainsComputedData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace Statamic\Data;

trait ContainsComputedData
{
protected $withComputedData = true;

public function computedData()
{
if (! method_exists($this, 'getComputedCallbacks')) {
return collect();
}

return collect($this->getComputedCallbacks())->map(function ($callback, $field) {
return $this->getComputed($field);
});
}

public function getComputed($key)
{
$instance = $this->instanceWithoutComputed();

$value = method_exists($this, 'get') ? $instance->get($key) : null;

if ($this->withComputedData && $callback = $this->getComputedCallbacks()->get($key)) {
return $callback($instance, $value);
}

return $value;
}

protected function hasComputedCallback($key)
{
return $this->getComputedCallbacks()->has($key);
}

protected function instanceWithoutComputed()
{
$clone = clone $this;

$clone->withComputedData = false;

return $clone;
}
}
22 changes: 20 additions & 2 deletions src/Data/HasOrigin.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,32 @@ trait HasOrigin

public function values()
{
$originFallbackValues = method_exists($this, 'getOriginFallbackValues') ? $this->getOriginFallbackValues() : collect();

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

return $originValues->merge($this->data);
$computedData = method_exists($this, 'computedData') ? $this->computedData() : [];

return collect()
->merge($originFallbackValues)
->merge($originValues)
->merge($this->data)
->merge($computedData);
}

public function value($key)
{
return $this->values()->get($key);
$originFallbackValue = method_exists($this, 'getOriginFallbackValue') ? $this->getOriginFallbackValue($key) : null;

$originValue = $this->hasOrigin() ? $this->origin()->value($key) : $originFallbackValue;

$value = $this->has($key) ? $this->get($key) : $originValue;

if (method_exists($this, 'hasComputedCallback') && $this->hasComputedCallback($key)) {
return $this->getComputed($key) ?? $value;
}

return $value;
}

public function origin($origin = null)
Expand Down
21 changes: 21 additions & 0 deletions src/Data/StoresComputedFieldCallbacks.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Statamic\Data;

use Closure;
use Illuminate\Support\Collection;

trait StoresComputedFieldCallbacks
{
protected $computedFieldCallbacks;

public function computed(string $field, Closure $callback)
{
$this->computedFieldCallbacks[$field] = $callback;
}

public function getComputedCallbacks(): Collection
{
return collect($this->computedFieldCallbacks);
}
}
24 changes: 24 additions & 0 deletions src/Data/StoresScopedComputedFieldCallbacks.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Statamic\Data;

use Closure;
use Illuminate\Support\Collection;
use Statamic\Support\Str;

trait StoresScopedComputedFieldCallbacks
{
protected $computedFieldCallbacks;

public function computed(string $scope, string $field, Closure $callback)
{
$this->computedFieldCallbacks["$scope.$field"] = $callback;
}

public function getComputedCallbacks(string $scope): Collection
{
return collect($this->computedFieldCallbacks)
->filter(fn ($_, $key) => Str::startsWith($key, "{$scope}."))
->keyBy(fn ($_, $key) => Str::after($key, "{$scope}."));
}
}
17 changes: 14 additions & 3 deletions src/Entries/Entry.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Statamic\Contracts\Entries\EntryRepository;
use Statamic\Contracts\GraphQL\ResolvesValues as ResolvesValuesContract;
use Statamic\Contracts\Query\ContainsQueryableValues;
use Statamic\Data\ContainsComputedData;
use Statamic\Data\ContainsData;
use Statamic\Data\ExistsAsFile;
use Statamic\Data\HasAugmentedInstance;
Expand Down Expand Up @@ -47,7 +48,7 @@ class Entry implements Contract, Augmentable, Responsable, Localization, Protect
uri as routableUri;
}

use ContainsData, ExistsAsFile, HasAugmentedInstance, FluentlyGetsAndSets, Revisable, Publishable, TracksQueriedColumns, TracksQueriedRelations, TracksLastModified;
use ContainsData, ContainsComputedData, ExistsAsFile, HasAugmentedInstance, FluentlyGetsAndSets, Revisable, Publishable, TracksQueriedColumns, TracksQueriedRelations, TracksLastModified;
use ResolvesValues {
resolveGqlValue as traitResolveGqlValue;
}
Expand Down Expand Up @@ -734,9 +735,14 @@ protected function getOriginByString($origin)
return Facades\Entry::find($origin);
}

public function values()
protected function getOriginFallbackValues()
{
return $this->collection()->cascade()->merge($this->originValues());
return $this->collection()->cascade();
}

protected function getOriginFallbackValue($key)
{
return $this->collection()->cascade()->get($key);
}

public function defaultAugmentedArrayKeys()
Expand Down Expand Up @@ -839,4 +845,9 @@ public function getQueryableValue(string $field)

return $field->fieldtype()->toQueryableValue($value);
}

protected function getComputedCallbacks()
{
return Facades\Collection::getComputedCallbacks($this->collection);
}
}
2 changes: 2 additions & 0 deletions src/Facades/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
* @method static \Illuminate\Support\Collection handles()
* @method static bool handleExists(string $handle)
* @method static \Illuminate\Support\Collection whereStructured()
* @method static \Illuminate\Support\Collection getComputedCallbacks(string $collection)
* @method static void computed(string $collection, string $field, \Closure $callback)
*
* @see \Illuminate\Support\Collection
* @see \Statamic\Entries\Collection
Expand Down
2 changes: 2 additions & 0 deletions src/Facades/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
* @method static void save(User $user);
* @method static void delete(User $user);
* @method static \Statamic\Fields\Blueprint blueprint();
* @method static \Illuminate\Support\Collection getComputedCallbacks()
* @method static void computed(string $field, \Closure $callback)
*
* @see \Statamic\Contracts\Auth\UserRepository
*/
Expand Down
33 changes: 22 additions & 11 deletions src/Fields/Fields.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class Fields
protected $parentField;
protected $filled = [];
protected $withValidatableValues = false;
protected $withComputedValues = false;

public function __construct($items = [], $parent = null, $parentField = null)
{
Expand Down Expand Up @@ -82,6 +83,13 @@ public function withValidatableValues()
return $this;
}

public function withComputedValues()
{
$this->withComputedValues = true;

return $this;
}

public function items()
{
return $this->items;
Expand Down Expand Up @@ -154,17 +162,20 @@ public function addValues(array $values)

public function values()
{
$values = $this->fields->mapWithKeys(function ($field) {
return [$field->handle() => $field->value()];
});

if ($this->withValidatableValues) {
$values = $values->filter(function ($field, $handle) {
return in_array($handle, $this->filled);
return $this->fields
->reject(function ($field) {
return $this->withComputedValues === false
? $field->visibility() === 'computed'
: false;
})
->mapWithKeys(function ($field) {
return [$field->handle() => $field->value()];
})
->filter(function ($field, $handle) {
return $this->withValidatableValues
? in_array($handle, $this->filled)
: true;
});
}

return $values;
}

public function process()
Expand All @@ -178,7 +189,7 @@ public function preProcess()
{
return $this->newInstance()->setFields(
$this->fields->map->preProcess()
);
)->withComputedValues();
}

public function preProcessValidatables()
Expand Down
8 changes: 4 additions & 4 deletions src/Http/Controllers/CP/Collections/EntriesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ public function create(Request $request, $collection, $site)
$blueprint->ensureFieldHasConfig('author', ['visibility' => 'read_only']);
}

$values = [];
$values = Entry::make()->collection($collection)->values()->all();

if ($collection->hasStructure() && $request->parent) {
$values['parent'] = $request->parent;
Expand Down Expand Up @@ -408,11 +408,11 @@ protected function extractFromFields($entry, $blueprint)
{
// The values should only be data merged with the origin data.
// We don't want injected collection values, which $entry->values() would have given us.
$values = collect();
$target = $entry;
$values = $target->data();
while ($target->hasOrigin()) {
while ($target) {
$values = $target->data()->merge($target->computedData())->merge($values);
$target = $target->origin();
$values = $target->data()->merge($values);
}
$values = $values->all();

Expand Down
1 change: 1 addition & 0 deletions src/Http/Controllers/CP/Fields/FieldsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ protected function blueprint($blueprint)
'options' => [
'visible' => __('Visible'),
'read_only' => __('Read Only'),
'computed' => __('Computed'),
'hidden' => __('Hidden'),
],
'default' => 'visible',
Expand Down
Loading