From 10b4efe0de492e8cf8443ce9d0ca5055e09376ea Mon Sep 17 00:00:00 2001 From: michael Date: Thu, 18 Nov 2021 10:27:31 +0100 Subject: [PATCH 01/19] Fixed file validation rules (issues #112, #238) --- src/Http/ScopedRequest.php | 16 +++++++++++++++- src/Layouts/Layout.php | 4 ++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Http/ScopedRequest.php b/src/Http/ScopedRequest.php index 6ff0e669..37ca65e8 100644 --- a/src/Http/ScopedRequest.php +++ b/src/Http/ScopedRequest.php @@ -6,6 +6,7 @@ class ScopedRequest extends NovaRequest { + protected $fileAttributes; /** * Create a copy of the given request, only containing the group's input @@ -30,7 +31,7 @@ public static function scopeFrom(NovaRequest $from, $attributes, $group) public function scopeInto($group, $attributes) { [$input, $files] = $this->getScopeState($group, $attributes); - + $input['_method'] = $this->input('_method'); $input['_retrieved_at'] = $this->input('_retrieved_at'); @@ -118,6 +119,9 @@ protected function getNestedFiles($iterable, $group = null) protected function handleScopeFiles(&$files, &$input, $group) { $attributes = collect($files)->keyBy('original'); + $this->fileAttributes = $attributes->mapWithKeys(function ($attribute, $key) { + return [$attribute->name => $key]; + }); $scope = []; foreach ($this->getFlattenedFiles() as $attribute => $file) { @@ -178,4 +182,14 @@ protected function isFlexibleStructure($iterable) && in_array('key', $keys, true) && in_array('attributes', $keys, true); } + + public function isFileAttribute($name) + { + return $this->fileAttributes->has($name); + } + + public function getFileAttribute($name) + { + return $this->fileAttributes->get($name); + } } diff --git a/src/Layouts/Layout.php b/src/Layouts/Layout.php index 68a949ac..d8919a74 100644 --- a/src/Layouts/Layout.php +++ b/src/Layouts/Layout.php @@ -380,8 +380,8 @@ protected function getScopedFieldRules($field, ScopedRequest $request, $specific $rules = call_user_func([$field, $method], $request); - return collect($rules)->mapWithKeys(function($validatorRules, $attribute) use ($key, $field) { - $key = $key . '.attributes.' . $attribute; + return collect($rules)->mapWithKeys(function($validatorRules, $attribute) use ($key, $field, $request) { + $key = $request->isFileAttribute($attribute) ? $request->getFileAttribute($attribute) : $key . '.attributes.' . $attribute; return [$key => $this->wrapScopedFieldRules($field, $validatorRules)]; }) ->filter() From 0384e310cd85ecaf44aa1aeb4f3cc22ec3734a72 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Nov 2022 06:46:00 +0000 Subject: [PATCH 02/19] Bump engine.io from 6.2.0 to 6.2.1 Bumps [engine.io](https://github.com/socketio/engine.io) from 6.2.0 to 6.2.1. - [Release notes](https://github.com/socketio/engine.io/releases) - [Changelog](https://github.com/socketio/engine.io/blob/main/CHANGELOG.md) - [Commits](https://github.com/socketio/engine.io/compare/6.2.0...6.2.1) --- updated-dependencies: - dependency-name: engine.io dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6eb52f66..60e3613c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2760,9 +2760,9 @@ engine.io-parser@~5.0.3: integrity sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg== engine.io@~6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.2.0.tgz#003bec48f6815926f2b1b17873e576acd54f41d0" - integrity sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg== + version "6.2.1" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.2.1.tgz#e3f7826ebc4140db9bbaa9021ad6b1efb175878f" + integrity sha512-ECceEFcAaNRybd3lsGQKas3ZlMVjN3cyWwMP25D2i0zWfyiytVbTpRPa34qrr+FHddtpBVOmq4H/DCv1O0lZRA== dependencies: "@types/cookie" "^0.4.1" "@types/cors" "^2.8.12" From f62a2976f8422b75f72ab1c443ccf0952deab3dc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 8 Jan 2023 15:57:39 +0000 Subject: [PATCH 03/19] Bump json5 from 1.0.1 to 1.0.2 Bumps [json5](https://github.com/json5/json5) from 1.0.1 to 1.0.2. - [Release notes](https://github.com/json5/json5/releases) - [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md) - [Commits](https://github.com/json5/json5/compare/v1.0.1...v1.0.2) --- updated-dependencies: - dependency-name: json5 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6eb52f66..6ff898a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3621,9 +3621,9 @@ json-schema-traverse@^1.0.0: integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" From 3f8266bdb55cc47c3d8ed76579e31eb45db94013 Mon Sep 17 00:00:00 2001 From: Alies Lapatsin Date: Tue, 24 Jan 2023 11:21:11 +0100 Subject: [PATCH 04/19] Change file ext for stubs .php files should have a valid syntax --- src/Commands/CreateCast.php | 2 +- src/Commands/CreateLayout.php | 2 +- src/Commands/CreatePreset.php | 2 +- src/Commands/CreateResolver.php | 2 +- src/Stubs/{Cast.php => Cast.stub} | 0 src/Stubs/{Layout.php => Layout.stub} | 0 src/Stubs/{Preset.php => Preset.stub} | 0 src/Stubs/{Resolver.php => Resolver.stub} | 0 8 files changed, 4 insertions(+), 4 deletions(-) rename src/Stubs/{Cast.php => Cast.stub} (100%) rename src/Stubs/{Layout.php => Layout.stub} (100%) rename src/Stubs/{Preset.php => Preset.stub} (100%) rename src/Stubs/{Resolver.php => Resolver.stub} (100%) diff --git a/src/Commands/CreateCast.php b/src/Commands/CreateCast.php index b5b17e16..7c7904e8 100644 --- a/src/Commands/CreateCast.php +++ b/src/Commands/CreateCast.php @@ -117,7 +117,7 @@ protected function buildClass() ], [ $this->classname, ], - $this->files->get(__DIR__.'/../Stubs/Cast.php') + $this->files->get(__DIR__.'/../Stubs/Cast.stub') ); } } diff --git a/src/Commands/CreateLayout.php b/src/Commands/CreateLayout.php index 1083e0e5..d09d38b4 100644 --- a/src/Commands/CreateLayout.php +++ b/src/Commands/CreateLayout.php @@ -141,7 +141,7 @@ protected function buildClass() $this->classname, $this->name, ], - $this->files->get(__DIR__.'/../Stubs/Layout.php') + $this->files->get(__DIR__.'/../Stubs/Layout.stub') ); } } diff --git a/src/Commands/CreatePreset.php b/src/Commands/CreatePreset.php index 36d167ab..b0f2267f 100644 --- a/src/Commands/CreatePreset.php +++ b/src/Commands/CreatePreset.php @@ -115,7 +115,7 @@ protected function buildClass() return str_replace( ':classname', $this->classname, - $this->files->get(__DIR__.'/../Stubs/Preset.php') + $this->files->get(__DIR__.'/../Stubs/Preset.stub') ); } } diff --git a/src/Commands/CreateResolver.php b/src/Commands/CreateResolver.php index 2dfa6a2d..eb529c2d 100644 --- a/src/Commands/CreateResolver.php +++ b/src/Commands/CreateResolver.php @@ -115,7 +115,7 @@ protected function buildClass() return str_replace( ':classname', $this->classname, - $this->files->get(__DIR__.'/../Stubs/Resolver.php') + $this->files->get(__DIR__.'/../Stubs/Resolver.stub') ); } } diff --git a/src/Stubs/Cast.php b/src/Stubs/Cast.stub similarity index 100% rename from src/Stubs/Cast.php rename to src/Stubs/Cast.stub diff --git a/src/Stubs/Layout.php b/src/Stubs/Layout.stub similarity index 100% rename from src/Stubs/Layout.php rename to src/Stubs/Layout.stub diff --git a/src/Stubs/Preset.php b/src/Stubs/Preset.stub similarity index 100% rename from src/Stubs/Preset.php rename to src/Stubs/Preset.stub diff --git a/src/Stubs/Resolver.php b/src/Stubs/Resolver.stub similarity index 100% rename from src/Stubs/Resolver.php rename to src/Stubs/Resolver.stub From 837f5d612ecaf56b78cc2247976805721210de63 Mon Sep 17 00:00:00 2001 From: Alies Lapatsin Date: Tue, 24 Jan 2023 12:08:58 +0100 Subject: [PATCH 05/19] Fix some type issues detected by Psalm --- composer.json | 1 + docs/README.md | 6 +++--- src/Concerns/HasFlexible.php | 10 ++++----- src/Flexible.php | 41 ++++++++++++++++++------------------ src/Layouts/Collection.php | 9 +++++++- src/Layouts/Layout.php | 11 ++++++++-- src/Value/FlexibleCast.php | 2 +- src/Value/Resolver.php | 18 ++++++++++------ 8 files changed, 59 insertions(+), 39 deletions(-) diff --git a/composer.json b/composer.json index 8fc2c2dc..9718ab9f 100644 --- a/composer.json +++ b/composer.json @@ -19,6 +19,7 @@ ], "require": { "php": "^7.3|^8.0", + "ext-json": "*", "laravel/framework": "^8.0|^9.0", "laravel/nova": "^4.0", "nova-kit/nova-packages-tool": "^1.3.1" diff --git a/docs/README.md b/docs/README.md index 4e531502..87433e7e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -412,8 +412,8 @@ The `get` method is used to resolve the field's content. It is responsible to re * * @param mixed $resource * @param string $attribute - * @param Whitecube\NovaFlexibleContent\Layouts\Collection $layouts - * @return Illuminate\Support\Collection + * @param \Whitecube\NovaFlexibleContent\Layouts\Collection $layouts + * @return \Illuminate\Support\Collection */ public function get($resource, $attribute, $layouts) { $blocks = $resource->blocks()->orderBy('order')->get(); @@ -438,7 +438,7 @@ The `set` method is responsible for saving the Flexible's content somewhere the * * @param mixed $model * @param string $attribute - * @param Illuminate\Support\Collection $groups + * @param \Illuminate\Support\Collection $groups * @return void */ public function set($model, $attribute, $groups) diff --git a/src/Concerns/HasFlexible.php b/src/Concerns/HasFlexible.php index 0ae1a335..ff357cde 100644 --- a/src/Concerns/HasFlexible.php +++ b/src/Concerns/HasFlexible.php @@ -27,7 +27,7 @@ public function flexible($attribute, $layoutMapping = []) /** * Cast a Flexible Content value * - * @param array $value + * @param mixed $value * @param array $layoutMapping * @return \Whitecube\NovaFlexibleContent\Layouts\Collection */ @@ -43,7 +43,7 @@ public function cast($value, $layoutMapping = []) /** * Parse a Flexible Content from value * - * @param mixed $value + * @param array|string|BaseCollection|null $value * @param array $layoutMapping * @return \Whitecube\NovaFlexibleContent\Layouts\Collection */ @@ -63,7 +63,7 @@ public function toFlexible($value, $layoutMapping = []) /** * Transform incoming value into an array of usable layouts * - * @param mixed $value + * @param array|string|BaseCollection|null $value * @return array|null */ protected function getFlexibleArrayFromValue($value) @@ -104,7 +104,7 @@ protected function getMappedFlexibleLayouts(array $flexible, array $layoutMappin * * @param mixed $item * @param array $layoutMapping - * @return null|Whitecube\NovaFlexibleContent\Layouts\LayoutInterface + * @return null|\Whitecube\NovaFlexibleContent\Layouts\LayoutInterface */ protected function getMappedLayout($item, array $layoutMapping) { @@ -131,7 +131,7 @@ protected function getMappedLayout($item, array $layoutMapping) } if (is_null($name)) { - return; + return null; } return $this->createMappedLayout($name, $key, $attributes, $layoutMapping); diff --git a/src/Flexible.php b/src/Flexible.php index ceba13b1..903855fb 100644 --- a/src/Flexible.php +++ b/src/Flexible.php @@ -2,6 +2,7 @@ namespace Whitecube\NovaFlexibleContent; +use Illuminate\Support\Collection; use Laravel\Nova\Fields\Field; use Laravel\Nova\Fields\SupportsDependentFields; use Laravel\Nova\Http\Requests\NovaRequest; @@ -27,21 +28,21 @@ class Flexible extends Field /** * The available layouts collection * - * @var Whitecube\NovaFlexibleContent\Layouts\Collection + * @var \Whitecube\NovaFlexibleContent\Layouts\Collection */ protected $layouts; /** * The currently defined layout groups * - * @var Illuminate\Support\Collection + * @var \Illuminate\Support\Collection */ protected $groups; /** * The field's value setter & getter * - * @var Whitecube\NovaFlexibleContent\Value\ResolverInterface + * @var \Whitecube\NovaFlexibleContent\Value\ResolverInterface */ protected $resolver; @@ -229,7 +230,7 @@ public function collapsed(bool $value = true) /** * Push a layout instance into the layouts collection * - * @param Whitecube\NovaFlexibleContent\Layouts\LayoutInterface $layout + * @param \Whitecube\NovaFlexibleContent\Layouts\LayoutInterface $layout * @return void */ protected function registerLayout(LayoutInterface $layout) @@ -301,7 +302,7 @@ public function isShownOnDetail(NovaRequest $request, $resource): bool * @param string $requestAttribute * @param object $model * @param string $attribute - * @return null|Closure + * @return void|\Closure */ protected function fillAttribute(NovaRequest $request, $requestAttribute, $model, $attribute) { @@ -335,26 +336,26 @@ protected function fillAttribute(NovaRequest $request, $requestAttribute, $model * @param string $requestAttribute * @return array */ - protected function syncAndFillGroups(NovaRequest $request, $requestAttribute) + protected function syncAndFillGroups(NovaRequest $request, $requestAttribute): array { if (! ($raw = $this->extractValue($request, $requestAttribute))) { $this->fireRemoveCallbacks(collect()); $this->groups = collect(); - return; + return []; } $callbacks = []; - $new_groups = collect($raw)->map(function ($item, $key) use ($request, &$callbacks) { + $new_groups = collect($raw)->map(function ($item) use ($request, &$callbacks) { $layout = $item['layout']; $key = $item['key']; $attributes = $item['attributes']; $group = $this->findGroup($key) ?? $this->newGroup($layout, $key); - if (! $group) { - return; + if (! $group instanceof Layout) { + return []; } $scope = ScopedRequest::scopeFrom($request, $attributes, $key); @@ -373,9 +374,9 @@ protected function syncAndFillGroups(NovaRequest $request, $requestAttribute) /** * Fire's the remove callbacks on the layouts * - * @param $new_groups This should be (all) the new groups to bne compared against to find the removed groups + * @param Collection $new_groups This should be (all) the new groups to bne compared against to find the removed groups */ - protected function fireRemoveCallbacks($new_groups) + protected function fireRemoveCallbacks(Collection $new_groups) { $new_group_keys = $new_groups->map(function ($item) { return $item->inUseKey(); @@ -414,8 +415,8 @@ protected function extractValue(NovaRequest $request, $attribute) /** * Resolve all contained groups and their fields * - * @param Illuminate\Support\Collection $groups - * @return Illuminate\Support\Collection + * @param \Illuminate\Support\Collection $groups + * @return \Illuminate\Support\Collection */ protected function resolveGroups($groups) { @@ -428,8 +429,8 @@ protected function resolveGroups($groups) * Resolve all contained groups and their fields for display on index and * detail views. * - * @param Illuminate\Support\Collection $groups - * @return Illuminate\Support\Collection + * @param \Illuminate\Support\Collection $groups + * @return \Illuminate\Support\Collection */ protected function resolveGroupsForDisplay($groups) { @@ -444,7 +445,7 @@ protected function resolveGroupsForDisplay($groups) * * @param mixed $resource * @param string $attribute - * @return Illuminate\Support\Collection + * @return \Illuminate\Support\Collection */ protected function buildGroups($resource, $attribute) { @@ -473,14 +474,14 @@ protected function findGroup($key) * * @param string $layout * @param string $key - * @return \Whitecube\NovaFlexibleContent\Layouts\Layout + * @return null|\Whitecube\NovaFlexibleContent\Layouts\Layout */ protected function newGroup($layout, $key) { $layout = $this->layouts->find($layout); - if (! $layout) { - return; + if (! $layout instanceof Layout) { + return null; } return $layout->duplicate($key); diff --git a/src/Layouts/Collection.php b/src/Layouts/Collection.php index f54ffb5a..fe85bb81 100644 --- a/src/Layouts/Collection.php +++ b/src/Layouts/Collection.php @@ -4,13 +4,20 @@ use Illuminate\Support\Collection as BaseCollection; +/** + * @template TKey of array-key + * @template TLayout of \Whitecube\NovaFlexibleContent\Layouts\Layout + * + * @extends \Illuminate\Support\Collection + */ class Collection extends BaseCollection { /** * Find a layout based on its name * * @param string $name - * @return mixed + * @return \Whitecube\NovaFlexibleContent\Layouts\Layout|null + * @psalm-return TLayout|null */ public function find($name) { diff --git a/src/Layouts/Layout.php b/src/Layouts/Layout.php index f5e6f226..f27021b5 100644 --- a/src/Layouts/Layout.php +++ b/src/Layouts/Layout.php @@ -16,6 +16,13 @@ use Whitecube\NovaFlexibleContent\Http\FlexibleAttribute; use Whitecube\NovaFlexibleContent\Http\ScopedRequest; +/** + * @template TKey of array-key + * @template TValue + * + * @implements \ArrayAccess + * @implements \Illuminate\Contracts\Support\Arrayable + */ class Layout implements LayoutInterface, JsonSerializable, ArrayAccess, Arrayable { use HasAttributes; @@ -85,7 +92,7 @@ class Layout implements LayoutInterface, JsonSerializable, ArrayAccess, Arrayabl /** * The parent model instance * - * @var Illuminate\Database\Eloquent\Model + * @var \Illuminate\Database\Eloquent\Model */ protected $model; @@ -440,7 +447,7 @@ public function fireRemoveCallback(Flexible $flexible) * The default behaviour when removed * * @param Flexible $flexible - * @param Whitecube\NovaFlexibleContent\Layout $layout + * @param \Whitecube\NovaFlexibleContent\Layout $layout * @return mixed */ protected function removeCallback(Flexible $flexible, $layout) diff --git a/src/Value/FlexibleCast.php b/src/Value/FlexibleCast.php index 0ececae6..b2fca3a4 100644 --- a/src/Value/FlexibleCast.php +++ b/src/Value/FlexibleCast.php @@ -15,7 +15,7 @@ class FlexibleCast implements CastsAttributes protected $layouts = []; /** - * @var Illuminate\Database\Eloquent\Model + * @var \Illuminate\Database\Eloquent\Model */ protected $model; diff --git a/src/Value/Resolver.php b/src/Value/Resolver.php index 65615e3c..c8a7dfa2 100644 --- a/src/Value/Resolver.php +++ b/src/Value/Resolver.php @@ -11,11 +11,13 @@ class Resolver implements ResolverInterface * * @param mixed $model * @param string $attribute - * @param Illuminate\Support\Collection $groups + * @param \Illuminate\Support\Collection $value * @return string */ - public function set($model, $attribute, $groups) + public function set($model, $attribute, $value) { + $groups = $value; // to avoid Named Arguments issue but keep using better var name; + return $model->$attribute = $groups->map(function ($group) { return [ 'layout' => $group->name(), @@ -28,20 +30,22 @@ public function set($model, $attribute, $groups) /** * get the field's value * - * @param mixed $resource + * @param mixed $model * @param string $attribute - * @param Whitecube\NovaFlexibleContent\Layouts\Collection $layouts - * @return Illuminate\Support\Collection + * @param \Whitecube\NovaFlexibleContent\Layouts\Collection $layouts + * @return \Illuminate\Support\Collection|null */ - public function get($resource, $attribute, $layouts) + public function get($model, $attribute, $layouts) { + $resource = $model; // to avoid Named Arguments issue but keep using better var name; + $value = $this->extractValueFromResource($resource, $attribute); return collect($value)->map(function ($item) use ($layouts) { $layout = $layouts->find($item->layout); if (! $layout) { - return; + return null; } return $layout->duplicateAndHydrate($item->key, (array) $item->attributes); From de9beaf36c0da2483652f47a91700389b64ccd30 Mon Sep 17 00:00:00 2001 From: Alies Lapatsin Date: Tue, 24 Jan 2023 12:17:07 +0100 Subject: [PATCH 06/19] Fix coding style issues --- src/Flexible.php | 2 +- src/Layouts/Collection.php | 1 + src/Layouts/Layout.php | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Flexible.php b/src/Flexible.php index 903855fb..256a5579 100644 --- a/src/Flexible.php +++ b/src/Flexible.php @@ -374,7 +374,7 @@ protected function syncAndFillGroups(NovaRequest $request, $requestAttribute): a /** * Fire's the remove callbacks on the layouts * - * @param Collection $new_groups This should be (all) the new groups to bne compared against to find the removed groups + * @param Collection $new_groups This should be (all) the new groups to bne compared against to find the removed groups */ protected function fireRemoveCallbacks(Collection $new_groups) { diff --git a/src/Layouts/Collection.php b/src/Layouts/Collection.php index fe85bb81..26d356ad 100644 --- a/src/Layouts/Collection.php +++ b/src/Layouts/Collection.php @@ -17,6 +17,7 @@ class Collection extends BaseCollection * * @param string $name * @return \Whitecube\NovaFlexibleContent\Layouts\Layout|null + * * @psalm-return TLayout|null */ public function find($name) diff --git a/src/Layouts/Layout.php b/src/Layouts/Layout.php index f27021b5..057ba9ff 100644 --- a/src/Layouts/Layout.php +++ b/src/Layouts/Layout.php @@ -115,7 +115,7 @@ class Layout implements LayoutInterface, JsonSerializable, ArrayAccess, Arrayabl * * @var array */ - protected $relationResolvers = []; + protected $relationResolvers = []; /** * The loaded relationships for the Layout. @@ -452,7 +452,6 @@ public function fireRemoveCallback(Flexible $flexible) */ protected function removeCallback(Flexible $flexible, $layout) { - } /** From 996cce473f63647d13f377e0ae07b9405bd34730 Mon Sep 17 00:00:00 2001 From: Alies Lapatsin Date: Tue, 24 Jan 2023 12:17:22 +0100 Subject: [PATCH 07/19] Add Psalm to project and CI --- .github/workflows/psalm.yml | 45 +++++++++++++++++++++++++++++++++++++ composer.json | 5 ++++- psalm-baseline.xml | 29 ++++++++++++++++++++++++ psalm.xml | 20 +++++++++++++++++ 4 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/psalm.yml create mode 100644 psalm-baseline.xml create mode 100644 psalm.xml diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml new file mode 100644 index 00000000..f8f4af2b --- /dev/null +++ b/.github/workflows/psalm.yml @@ -0,0 +1,45 @@ +name: Psalm + +on: + workflow_dispatch: + push: + paths: + - '**.php' + - 'composer*' + - 'psalm*' + +jobs: + psalm: + name: Psalm + runs-on: ubuntu-latest + timeout-minutes: 6 + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.head_ref }} + + # mtime needs to be restored for Psalm cache to work correctly + - name: Restore mtimes + uses: chetan/git-restore-mtime-action@v1 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.1 + coverage: none + + - name: Install composer dependencies + run: | + composer config --ansi -- http-basic.nova.laravel.com ${{ secrets.NOVA_USERNAME }} ${{ secrets.NOVA_LICENSE_KEY }} + composer install --no-interaction --no-progress --no-scripts + + # the way cache keys are set up will always cause a cache miss + # but will restore the cache generated during the previous run based on partial match + - name: Retrieve Psalm’s cache + uses: actions/cache@v3 + with: + path: ./cache/psalm + key: ${{ runner.os }}-psalm-cache-${{ hashFiles('psalm.xml', 'psalm-baseline.xml', './composer.json') }} + + - name: Run Psalm + run: ./vendor/bin/psalm --find-unused-psalm-suppress --output-format=github diff --git a/composer.json b/composer.json index 8fc2c2dc..971d531e 100644 --- a/composer.json +++ b/composer.json @@ -52,10 +52,13 @@ "minimum-stability": "dev", "prefer-stable": true, "require-dev": { + "laravel/pint": "^1.2", "phpunit/phpunit": "^9.5", - "laravel/pint": "^1.2" + "psalm/plugin-laravel": "^2.0" }, "scripts": { + "psalm": "psalm --find-unused-psalm-suppress --output-format=phpstorm", + "psalm-update-baseline": "psalm --set-baseline=psalm-baseline.xml", "test": "phpunit --colors=always tests", "fix-style": "./vendor/bin/pint" } diff --git a/psalm-baseline.xml b/psalm-baseline.xml new file mode 100644 index 00000000..c322567d --- /dev/null +++ b/psalm-baseline.xml @@ -0,0 +1,29 @@ + + + + + OriginalFileAdder + + + + + OriginalFileAdderFactory + + + + + $model + \Whitecube\NovaPage\Pages\Template + + + + + Collection + + + + + HasAttributes + + + diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 00000000..d5854603 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + From 713a2f88b95e6d21e23706cbb5ea298bbe75ec87 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 15 Feb 2023 09:28:19 +0800 Subject: [PATCH 08/19] Update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 8fc2c2dc..4f9daac8 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ ], "require": { "php": "^7.3|^8.0", - "laravel/framework": "^8.0|^9.0", + "laravel/framework": "^8.0|^9.0|^10.0", "laravel/nova": "^4.0", "nova-kit/nova-packages-tool": "^1.3.1" }, From 337c9e743a4b810c4d79eb4c554b7ec509c01f01 Mon Sep 17 00:00:00 2001 From: Matthias Lotze Date: Wed, 22 Feb 2023 10:04:07 +0100 Subject: [PATCH 09/19] fix undefined array key warning --- src/Concerns/HasFlexible.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Concerns/HasFlexible.php b/src/Concerns/HasFlexible.php index 0ae1a335..812de900 100644 --- a/src/Concerns/HasFlexible.php +++ b/src/Concerns/HasFlexible.php @@ -119,7 +119,7 @@ protected function getMappedLayout($item, array $layoutMapping) if (is_array($item)) { $name = $item['layout'] ?? null; $key = $item['key'] ?? null; - $attributes = (array) $item['attributes'] ?? []; + $attributes = (array) ($item['attributes'] ?? []); } elseif (is_a($item, \stdClass::class)) { $name = $item->layout ?? null; $key = $item->key ?? null; From 9ecfc596bff32e0942db4dd7b9812df17209ef33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Mar 2023 08:12:00 +0000 Subject: [PATCH 10/19] Bump webpack from 5.75.0 to 5.76.1 Bumps [webpack](https://github.com/webpack/webpack) from 5.75.0 to 5.76.1. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](https://github.com/webpack/webpack/compare/v5.75.0...v5.76.1) --- updated-dependencies: - dependency-name: webpack dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6eb52f66..e341a3c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5735,9 +5735,9 @@ webpack-sources@^3.2.3: integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== webpack@^5.60.0: - version "5.75.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.75.0.tgz#1e440468647b2505860e94c9ff3e44d5b582c152" - integrity sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ== + version "5.76.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.76.1.tgz#7773de017e988bccb0f13c7d75ec245f377d295c" + integrity sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ== dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^0.0.51" From fb48ef406b49b83b487d9ff12469786ed005958c Mon Sep 17 00:00:00 2001 From: Alies Lapatsin Date: Mon, 26 Jun 2023 19:34:30 +0200 Subject: [PATCH 11/19] Rename vars for (better consistency) --- src/Value/Resolver.php | 22 +++++++++------------- src/Value/ResolverInterface.php | 22 ++++++++++++++++++++-- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/Value/Resolver.php b/src/Value/Resolver.php index c8a7dfa2..de4fcd7e 100644 --- a/src/Value/Resolver.php +++ b/src/Value/Resolver.php @@ -7,18 +7,16 @@ class Resolver implements ResolverInterface { /** - * Set the field's value + * Save the Flexible field's content somewhere the get method will be able to access it. * - * @param mixed $model + * @param mixed $resource * @param string $attribute - * @param \Illuminate\Support\Collection $value + * @param \Illuminate\Support\Collection $groups * @return string */ - public function set($model, $attribute, $value) + public function set($resource, $attribute, $groups) { - $groups = $value; // to avoid Named Arguments issue but keep using better var name; - - return $model->$attribute = $groups->map(function ($group) { + return $resource->$attribute = $groups->map(function ($group) { return [ 'layout' => $group->name(), 'key' => $group->key(), @@ -28,17 +26,15 @@ public function set($model, $attribute, $value) } /** - * get the field's value + * Resolve the Flexible field's content. * - * @param mixed $model + * @param mixed $resource * @param string $attribute * @param \Whitecube\NovaFlexibleContent\Layouts\Collection $layouts - * @return \Illuminate\Support\Collection|null + * @return \Illuminate\Support\Collection */ - public function get($model, $attribute, $layouts) + public function get($resource, $attribute, $layouts) { - $resource = $model; // to avoid Named Arguments issue but keep using better var name; - $value = $this->extractValueFromResource($resource, $attribute); return collect($value)->map(function ($item) use ($layouts) { diff --git a/src/Value/ResolverInterface.php b/src/Value/ResolverInterface.php index c8bcc8c9..bf56b639 100644 --- a/src/Value/ResolverInterface.php +++ b/src/Value/ResolverInterface.php @@ -4,7 +4,25 @@ interface ResolverInterface { - public function set($model, $attribute, $value); + /** + * Resolve the Flexible field's content. + * @see https://whitecube.github.io/nova-flexible-content/#/?id=resolving-the-field + * + * @param mixed $resource + * @param string $attribute + * @param \Whitecube\NovaFlexibleContent\Layouts\Collection $layouts + * @return \Illuminate\Support\Collection + */ + public function get($resource, $attribute, $layouts); - public function get($model, $attribute, $layouts); + /** + * Save the Flexible field's content somewhere the get method will be able to access it. + * @see https://whitecube.github.io/nova-flexible-content/#/?id=filling-the-field + * + * @param mixed $resource + * @param string $attribute Attribute name set for a Flexible field. + * @param \Illuminate\Support\Collection $groups + * @return mixed + */ + public function set($resource, $attribute, $groups); } From 119acc9396e0c7f0f60da635ceacf9058cb75bf2 Mon Sep 17 00:00:00 2001 From: Alies Lapatsin Date: Mon, 26 Jun 2023 19:35:07 +0200 Subject: [PATCH 12/19] Update stub for Resolver --- src/Stubs/Resolver.stub | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Stubs/Resolver.stub b/src/Stubs/Resolver.stub index d7224afc..dec72fb2 100644 --- a/src/Stubs/Resolver.stub +++ b/src/Stubs/Resolver.stub @@ -7,12 +7,12 @@ use Whitecube\NovaFlexibleContent\Value\ResolverInterface; class :classname implements ResolverInterface { /** - * get the field's value + * Resolve the Flexible field's content. * * @param mixed $resource - * @param string $attribute - * @param \Whitecube\NovaFlexibleContent\Layouts\Collection $layouts - * @return \Illuminate\Support\Collection + * @param string $attribute + * @param \Whitecube\NovaFlexibleContent\Layouts\Collection $layouts + * @return \Illuminate\Support\Collection */ public function get($resource, $attribute, $layouts) { @@ -20,14 +20,14 @@ class :classname implements ResolverInterface } /** - * Set the field's value + * Save the Flexible field's content somewhere the get method will be able to access it. * - * @param mixed $model - * @param string $attribute - * @param \Illuminate\Support\Collection $groups - * @return string + * @param mixed $resource + * @param string $attribute Attribute name set for a Flexible field. + * @param \Illuminate\Support\Collection $groups + * @return mixed */ - public function set($model, $attribute, $groups) + public function set($resource, $attribute, $groups) { } From c2b97e5467d660923633fb587cf719fae73eca69 Mon Sep 17 00:00:00 2001 From: Alies Lapatsin Date: Mon, 26 Jun 2023 19:35:25 +0200 Subject: [PATCH 13/19] Fix more PHPDoc --- src/Concerns/HasFlexible.php | 4 ++-- src/Http/FlexibleAttribute.php | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Concerns/HasFlexible.php b/src/Concerns/HasFlexible.php index cc2c0345..7ba08898 100644 --- a/src/Concerns/HasFlexible.php +++ b/src/Concerns/HasFlexible.php @@ -43,7 +43,7 @@ public function cast($value, $layoutMapping = []) /** * Parse a Flexible Content from value * - * @param array|string|BaseCollection|null $value + * @param array|string|\Illuminate\Support\Collection|null $value * @param array $layoutMapping * @return \Whitecube\NovaFlexibleContent\Layouts\Collection */ @@ -63,7 +63,7 @@ public function toFlexible($value, $layoutMapping = []) /** * Transform incoming value into an array of usable layouts * - * @param array|string|BaseCollection|null $value + * @param array|string|\Illuminate\Support\Collection|null $value * @return array|null */ protected function getFlexibleArrayFromValue($value) diff --git a/src/Http/FlexibleAttribute.php b/src/Http/FlexibleAttribute.php index b03b71e6..b6782c97 100644 --- a/src/Http/FlexibleAttribute.php +++ b/src/Http/FlexibleAttribute.php @@ -262,7 +262,6 @@ public function nest($key) /** * Check attribute is an "upload" attribute and define it on the object * - * @param mixed $group * @return void */ protected function setUpload() From 7898b4972bd8cee2b986f47f6b904d2bf899d6b5 Mon Sep 17 00:00:00 2001 From: Toon Van den Bos Date: Tue, 27 Jun 2023 15:05:10 +0200 Subject: [PATCH 14/19] Added file attribute docblocks --- src/Http/ScopedRequest.php | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/Http/ScopedRequest.php b/src/Http/ScopedRequest.php index 9744b9c5..eb0404b5 100644 --- a/src/Http/ScopedRequest.php +++ b/src/Http/ScopedRequest.php @@ -6,9 +6,20 @@ class ScopedRequest extends NovaRequest { - protected $fileAttributes; + /** + * The group's key. + * + * @var string + */ public $group; + /** + * The original file input attributes. + * + * @var array + */ + protected $fileAttributes = []; + /** * Create a copy of the given request, only containing the group's input * @@ -125,9 +136,11 @@ protected function getNestedFiles($iterable, $group = null) protected function handleScopeFiles(&$files, &$input, $group) { $attributes = collect($files)->keyBy('original'); - $this->fileAttributes = $attributes->mapWithKeys(function ($attribute, $key) { + + $this->fileAttributes = $attributes->mapWithKeys(function($attribute, $key) { return [$attribute->name => $key]; }); + $scope = []; foreach ($this->getFlattenedFiles() as $attribute => $file) { @@ -191,11 +204,23 @@ protected function isFlexibleStructure($iterable) && in_array('attributes', $keys, true); } + /** + * Check if the given argument is a defined file attribute. + * + * @param string $name + * @return bool + */ public function isFileAttribute($name) { return $this->fileAttributes->has($name); } + /** + * Return the actual file input attribute + * + * @param string $name + * @return string + */ public function getFileAttribute($name) { return $this->fileAttributes->get($name); From 48f2e0ad36399411e0daf035abf4807b3725546a Mon Sep 17 00:00:00 2001 From: Lorenzo Sapora Date: Wed, 5 Jul 2023 15:20:06 +0100 Subject: [PATCH 15/19] Fix forceFill issue --- src/Concerns/HasFlexible.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Concerns/HasFlexible.php b/src/Concerns/HasFlexible.php index 7ba08898..50302e4f 100644 --- a/src/Concerns/HasFlexible.php +++ b/src/Concerns/HasFlexible.php @@ -4,10 +4,12 @@ use Illuminate\Support\Collection as BaseCollection; use Laravel\Nova\NovaServiceProvider; +use Laravel\Nova\Support\Fluent; use Whitecube\NovaFlexibleContent\Layouts\Collection; use Whitecube\NovaFlexibleContent\Layouts\Layout; use Whitecube\NovaFlexibleContent\Value\FlexibleCast; + trait HasFlexible { /** @@ -120,7 +122,7 @@ protected function getMappedLayout($item, array $layoutMapping) $name = $item['layout'] ?? null; $key = $item['key'] ?? null; $attributes = (array) ($item['attributes'] ?? []); - } elseif (is_a($item, \stdClass::class)) { + } elseif (is_a($item, Fluent::class)) { $name = $item->layout ?? null; $key = $item->key ?? null; $attributes = (array) ($item->attributes ?? []); From f4e12791af4e3bb65a583d723341b988c3c68d74 Mon Sep 17 00:00:00 2001 From: Lars Kort <2412670+LTKort@users.noreply.github.com> Date: Thu, 6 Jul 2023 13:26:00 +0200 Subject: [PATCH 16/19] Add forceFill method to Layout class --- src/Layouts/Layout.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Layouts/Layout.php b/src/Layouts/Layout.php index e8ab597b..4195af8c 100644 --- a/src/Layouts/Layout.php +++ b/src/Layouts/Layout.php @@ -387,6 +387,22 @@ public function fill(ScopedRequest $request) ->all(); } + /** + * Force Fill the layout with an array of attributes. + * + * @param array $attributes + * @return $this + */ + public function forceFill(array $attributes) + { + foreach ($attributes as $key => $value) { + $attribute = Str::replace('->', '.', $key); + Arr::set($this->attributes, $attribute, $value); + } + + return $this; + } + /** * Get validation rules for fields concerned by given request * From e2be82a739c836d448729d2597db3d3ca0afdc73 Mon Sep 17 00:00:00 2001 From: Adrien Leloup Date: Thu, 6 Jul 2023 13:38:43 +0200 Subject: [PATCH 17/19] Added missing imports --- src/Layouts/Layout.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Layouts/Layout.php b/src/Layouts/Layout.php index 4195af8c..069f1073 100644 --- a/src/Layouts/Layout.php +++ b/src/Layouts/Layout.php @@ -3,6 +3,8 @@ namespace Whitecube\NovaFlexibleContent\Layouts; use ArrayAccess; +use Illuminate\Support\Arr; +use Illuminate\Support\Str; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Database\Eloquent\Concerns\HasAttributes; use Illuminate\Database\Eloquent\Concerns\HidesAttributes; From 42a30f11bcb857b9e1352769f09fa69aa3dc736a Mon Sep 17 00:00:00 2001 From: Lars Kort <2412670+LTKort@users.noreply.github.com> Date: Thu, 6 Jul 2023 13:39:02 +0200 Subject: [PATCH 18/19] Add imports --- src/Layouts/Layout.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Layouts/Layout.php b/src/Layouts/Layout.php index 4195af8c..069f1073 100644 --- a/src/Layouts/Layout.php +++ b/src/Layouts/Layout.php @@ -3,6 +3,8 @@ namespace Whitecube\NovaFlexibleContent\Layouts; use ArrayAccess; +use Illuminate\Support\Arr; +use Illuminate\Support\Str; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Database\Eloquent\Concerns\HasAttributes; use Illuminate\Database\Eloquent\Concerns\HidesAttributes; From efa5d5d2e099d7264432458d2a1a123f243cd905 Mon Sep 17 00:00:00 2001 From: Muhammed Sari Date: Thu, 6 Jul 2023 14:55:17 +0200 Subject: [PATCH 19/19] Fix existing layouts breaking #469 broke existing layouts. This PR rectifies that. --- src/Concerns/HasFlexible.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Concerns/HasFlexible.php b/src/Concerns/HasFlexible.php index 50302e4f..82930620 100644 --- a/src/Concerns/HasFlexible.php +++ b/src/Concerns/HasFlexible.php @@ -9,7 +9,6 @@ use Whitecube\NovaFlexibleContent\Layouts\Layout; use Whitecube\NovaFlexibleContent\Value\FlexibleCast; - trait HasFlexible { /** @@ -122,7 +121,7 @@ protected function getMappedLayout($item, array $layoutMapping) $name = $item['layout'] ?? null; $key = $item['key'] ?? null; $attributes = (array) ($item['attributes'] ?? []); - } elseif (is_a($item, Fluent::class)) { + } elseif (is_a($item, \stdClass::class) || is_a($item, Fluent::class)) { $name = $item->layout ?? null; $key = $item->key ?? null; $attributes = (array) ($item->attributes ?? []);