From b9cac9a08c3f07ba619d4e52ba04e7e10c2f6d07 Mon Sep 17 00:00:00 2001 From: David Cox Date: Mon, 1 Mar 2021 15:33:17 +0000 Subject: [PATCH 1/6] break out traits to fix Action vs ActionRequest usage --- README.md | 1 + src/ActionHasDependencies.php | 39 ++++++++++++ src/HasChildFields.php | 45 ++++++++++++++ src/HasDependencies.php | 74 +---------------------- src/Http/Controllers/ActionController.php | 34 +++-------- src/Http/Requests/ActionRequest.php | 31 +++++++++- 6 files changed, 126 insertions(+), 98 deletions(-) create mode 100644 src/ActionHasDependencies.php create mode 100644 src/HasChildFields.php diff --git a/README.md b/README.md index 2ad28c4..e5cc073 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ composer require epartment/nova-dependency-container 1. Add the `Epartment\NovaDependencyContainer\HasDependencies` trait to your Nova Resource. 2. Add the `Epartment\NovaDependencyContainer\NovaDependencyContainer` to your Nova Resource `fields` method. +3. Add the `Epartment\NovaDependencyContainer\ActionHasDependencies` trait to your Nova Actions that you wish to use dependencies on. ```php class Page extends Resource diff --git a/src/ActionHasDependencies.php b/src/ActionHasDependencies.php new file mode 100644 index 0000000..4947a24 --- /dev/null +++ b/src/ActionHasDependencies.php @@ -0,0 +1,39 @@ +action()->fields() as $field) { + if ($field instanceof NovaDependencyContainer) { + // do not add any fields for validation if container is not satisfied + if($field->areDependenciesSatisfied($this)) { + $availableFields[] = $field; + $this->extractChildFields($field->meta['fields']); + } + } else { + $availableFields[] = $field; + } + } + + if ($this->childFieldsArr) { + $availableFields = array_merge($availableFields, $this->childFieldsArr); + } + + $this->validate(collect($availableFields)->mapWithKeys(function ($field) { + return $field->getCreationRules($this); + })->all()); + } +} diff --git a/src/HasChildFields.php b/src/HasChildFields.php new file mode 100644 index 0000000..389ee47 --- /dev/null +++ b/src/HasChildFields.php @@ -0,0 +1,45 @@ +extractChildFields($childField->meta['fields']); + } else { + if (array_search($childField->attribute, array_column($this->childFieldsArr, 'attribute')) === false) { + // @todo: we should not randomly apply rules to child-fields. + $childField = $this->applyRulesForChildFields($childField); + $this->childFieldsArr[] = $childField; + } + } + } + } + + /** + * @param [array] $childField + * @return [array] $childField + */ + protected function applyRulesForChildFields($childField) + { + if (isset($childField->rules)) { + $childField->rules[] = "sometimes:required:".$childField->attribute; + } + if (isset($childField->creationRules)) { + $childField->creationRules[] = "sometimes:required:".$childField->attribute; + } + if (isset($childField->updateRules)) { + $childField->updateRules[] = "sometimes:required:".$childField->attribute; + } + return $childField; + } +} diff --git a/src/HasDependencies.php b/src/HasDependencies.php index d0682d6..77bcc40 100644 --- a/src/HasDependencies.php +++ b/src/HasDependencies.php @@ -2,18 +2,18 @@ namespace Epartment\NovaDependencyContainer; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\Route; use Illuminate\Support\Str; -use Illuminate\Support\Collection; use Laravel\Nova\Fields\Field; use Laravel\Nova\Fields\FieldCollection; -use Laravel\Nova\Http\Requests\NovaRequest; use Laravel\Nova\Fields\MorphTo; use Laravel\Nova\Http\Requests\ActionRequest; +use Laravel\Nova\Http\Requests\NovaRequest; trait HasDependencies { - protected $childFieldsArr = []; + use HasChildFields; /** * @param NovaRequest $request @@ -99,72 +99,4 @@ protected function doesRouteRequireChildFields() : bool 'MorphableController@index', ]); } - - /** - * @param [array] $childFields [meta fields] - * @return void - */ - protected function extractChildFields($childFields) - { - foreach ($childFields as $childField) { - if ($childField instanceof NovaDependencyContainer) { - $this->extractChildFields($childField->meta['fields']); - } else { - if (array_search($childField->attribute, array_column($this->childFieldsArr, 'attribute')) === false) { - // @todo: we should not randomly apply rules to child-fields. - $childField = $this->applyRulesForChildFields($childField); - $this->childFieldsArr[] = $childField; - } - } - } - } - - /** - * @param [array] $childField - * @return [array] $childField - */ - protected function applyRulesForChildFields($childField) - { - if (isset($childField->rules)) { - $childField->rules[] = "sometimes:required:".$childField->attribute; - } - if (isset($childField->creationRules)) { - $childField->creationRules[] = "sometimes:required:".$childField->attribute; - } - if (isset($childField->updateRules)) { - $childField->updateRules[] = "sometimes:required:".$childField->attribute; - } - return $childField; - } - - /** - * Validate action fields - * Overridden using ActionController & ActionRequest by modifying routes - * @param \Laravel\Nova\Http\Requests\ActionRequest $request - * @return void - */ - public function validateFields(ActionRequest $request = null) { - $availableFields = []; - if ( !empty( ($action_fields = $this->action()->fields()) ) ) { - foreach ($action_fields as $field) { - if ($field instanceof NovaDependencyContainer) { - // do not add any fields for validation if container is not satisfied - if($field->areDependenciesSatisfied($this)) { - $availableFields[] = $field; - $this->extractChildFields($field->meta['fields']); - } - } else { - $availableFields[] = $field; - } - } - } - - if ($this->childFieldsArr) { - $availableFields = array_merge($availableFields, $this->childFieldsArr); - } - - $this->validate(collect($availableFields)->mapWithKeys(function ($field) { - return $field->getCreationRules($this); - })->all()); - } } diff --git a/src/Http/Controllers/ActionController.php b/src/Http/Controllers/ActionController.php index f769a43..fc8c270 100644 --- a/src/Http/Controllers/ActionController.php +++ b/src/Http/Controllers/ActionController.php @@ -3,37 +3,19 @@ namespace Epartment\NovaDependencyContainer\Http\Controllers; use Epartment\NovaDependencyContainer\Http\Requests\ActionRequest; -use Illuminate\Routing\Controller; -use Laravel\Nova\Http\Requests\NovaRequest; - -class ActionController extends Controller { +use Laravel\Nova\Http\Controllers\ActionController as NovaActionController; +class ActionController extends NovaActionController +{ /** - * List the actions for the given resource. - * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request - * @return \Illuminate\Http\Response - */ - public function index(NovaRequest $request) { - return response()->json([ - 'actions' => $request->newResource()->availableActions($request), - 'pivotActions' => [ - 'name' => $request->pivotName(), - 'actions' => $request->newResource()->availablePivotActions($request), - ], - ]); - } - - /** - * Perform an action on the specified resources. + * This uses the custom ActionRequest typehint to enable + * dependency features. * * @param \Laravel\Nova\Http\Requests\ActionRequest $request * @return \Illuminate\Http\Response */ - public function store(ActionRequest $request) { - - $request->validateFields(); - - return $request->action()->handleRequest($request); + public function store(ActionRequest $request) + { + return parent::store($request); } } diff --git a/src/Http/Requests/ActionRequest.php b/src/Http/Requests/ActionRequest.php index 1c5ad38..54a70f7 100644 --- a/src/Http/Requests/ActionRequest.php +++ b/src/Http/Requests/ActionRequest.php @@ -7,5 +7,34 @@ class ActionRequest extends NovaActionRequest { - use HasDependencies; + use HasDependencies; + + /** + * Handles child fields. + * + * @return void + */ + public function validateFields() { + $availableFields = []; + + foreach ($this->action()->fields() as $field) { + if ($field instanceof NovaDependencyContainer) { + // do not add any fields for validation if container is not satisfied + if ($field->areDependenciesSatisfied($this)) { + $availableFields[] = $field; + $this->extractChildFields($field->meta['fields']); + } + } else { + $availableFields[] = $field; + } + } + + if ($this->childFieldsArr) { + $availableFields = array_merge($availableFields, $this->childFieldsArr); + } + + $this->validate(collect($availableFields)->mapWithKeys(function ($field) { + return $field->getCreationRules($this); + })->all()); + } } From e8d630851ead950b41e30040fbc388f7b10b4c14 Mon Sep 17 00:00:00 2001 From: David Cox Date: Mon, 1 Mar 2021 16:55:49 +0000 Subject: [PATCH 2/6] fix inheritence compatibility --- src/Http/Controllers/ActionController.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Http/Controllers/ActionController.php b/src/Http/Controllers/ActionController.php index fc8c270..169d948 100644 --- a/src/Http/Controllers/ActionController.php +++ b/src/Http/Controllers/ActionController.php @@ -3,6 +3,7 @@ namespace Epartment\NovaDependencyContainer\Http\Controllers; use Epartment\NovaDependencyContainer\Http\Requests\ActionRequest; +use Laravel\Nova\Http\Requests\ActionRequest as NovaActionRequest; use Laravel\Nova\Http\Controllers\ActionController as NovaActionController; class ActionController extends NovaActionController @@ -14,8 +15,10 @@ class ActionController extends NovaActionController * @param \Laravel\Nova\Http\Requests\ActionRequest $request * @return \Illuminate\Http\Response */ - public function store(ActionRequest $request) + public function store(NovaActionRequest $request) { + $request = ActionRequest::createFrom($request); + return parent::store($request); } } From 078512bcfdc54f631fea8f94fdfbf29956bb330a Mon Sep 17 00:00:00 2001 From: David Cox Date: Mon, 1 Mar 2021 19:42:34 +0000 Subject: [PATCH 3/6] update broken class reference --- src/ActionHasDependencies.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ActionHasDependencies.php b/src/ActionHasDependencies.php index 4947a24..e892980 100644 --- a/src/ActionHasDependencies.php +++ b/src/ActionHasDependencies.php @@ -2,6 +2,8 @@ namespace Epartment\NovaDependencyContainer; +use Laravel\Nova\Http\Requests\ActionRequest; + trait ActionHasDependencies { use HasChildFields; From d19ff3a25f9a3ccacd8564d87616223ef79a0e36 Mon Sep 17 00:00:00 2001 From: David Cox Date: Tue, 2 Mar 2021 19:40:47 +0000 Subject: [PATCH 4/6] style fixes/general cleanup --- src/ActionHasDependencies.php | 2 +- src/HasDependencies.php | 35 +++++++++++++---------------------- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/ActionHasDependencies.php b/src/ActionHasDependencies.php index e892980..2695301 100644 --- a/src/ActionHasDependencies.php +++ b/src/ActionHasDependencies.php @@ -18,7 +18,7 @@ public function validateFields(ActionRequest $request) { $availableFields = []; - foreach ($request->action()->fields() as $field) { + foreach ($this->fields() as $field) { if ($field instanceof NovaDependencyContainer) { // do not add any fields for validation if container is not satisfied if($field->areDependenciesSatisfied($this)) { diff --git a/src/HasDependencies.php b/src/HasDependencies.php index 77bcc40..2fd39f3 100644 --- a/src/HasDependencies.php +++ b/src/HasDependencies.php @@ -2,13 +2,9 @@ namespace Epartment\NovaDependencyContainer; -use Illuminate\Support\Collection; use Illuminate\Support\Facades\Route; use Illuminate\Support\Str; -use Laravel\Nova\Fields\Field; use Laravel\Nova\Fields\FieldCollection; -use Laravel\Nova\Fields\MorphTo; -use Laravel\Nova\Http\Requests\ActionRequest; use Laravel\Nova\Http\Requests\NovaRequest; trait HasDependencies @@ -16,8 +12,8 @@ trait HasDependencies use HasChildFields; /** - * @param NovaRequest $request - * @return FieldCollection|\Illuminate\Support\Collection + * @param NovaRequest $request + * @return FieldCollection */ public function availableFields(NovaRequest $request) { @@ -42,33 +38,36 @@ public function availableFields(NovaRequest $request) $availableFields = array_merge($availableFields, $this->childFieldsArr); } - $availableFields = new FieldCollection(array_values($this->filter($availableFields))); + return $availableFields; } /** * Check if request needs to extract child fields * - * @param NovaRequest $request - * @param $model + * @param NovaRequest $request + * @param mixed $model * @return bool */ - protected function extractableRequest(NovaRequest $request, $model) { + protected function extractableRequest(NovaRequest $request, $model) + { // if form was submitted to update (method === 'PUT') - if($request->isUpdateOrUpdateAttachedRequest() && strtoupper($request->get('_method', null)) === 'PUT') { + if ($request->isUpdateOrUpdateAttachedRequest() && $request->method() == 'PUT') { return false; } + // if form was submitted to create and new resource - if($request->isCreateOrAttachRequest() && $model->id === null) { + if ($request->isCreateOrAttachRequest() && $model->id === null) { return false; } + return true; } /** - * @param $field - * @param NovaRequest $request + * @param mixed $field + * @param NovaRequest $request * @return mixed * * @todo: implement @@ -78,14 +77,6 @@ public function filterFieldForRequest($field, NovaRequest $request) { return $field; } - /** - * @param array $availableFields - * @param NovaRequest $request - */ - public function filterFieldsForRequest(Collection $availableFields, NovaRequest $request) { - return $availableFields; - } - /** * @return bool */ From 019c0cef27f94190b76acb764c1ad1496a96401a Mon Sep 17 00:00:00 2001 From: David Cox Date: Tue, 2 Mar 2021 19:43:01 +0000 Subject: [PATCH 5/6] fix spacing --- src/Http/Controllers/ActionController.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Http/Controllers/ActionController.php b/src/Http/Controllers/ActionController.php index 169d948..c67dd46 100644 --- a/src/Http/Controllers/ActionController.php +++ b/src/Http/Controllers/ActionController.php @@ -8,17 +8,17 @@ class ActionController extends NovaActionController { - /** + /** * This uses the custom ActionRequest typehint to enable * dependency features. - * - * @param \Laravel\Nova\Http\Requests\ActionRequest $request - * @return \Illuminate\Http\Response - */ + * + * @param \Laravel\Nova\Http\Requests\ActionRequest $request + * @return \Illuminate\Http\Response + */ public function store(NovaActionRequest $request) { $request = ActionRequest::createFrom($request); return parent::store($request); - } + } } From a16b0a7955d740940a1855e1f3004a7d919efc97 Mon Sep 17 00:00:00 2001 From: David Cox Date: Tue, 2 Mar 2021 19:45:07 +0000 Subject: [PATCH 6/6] fix docblock --- src/Http/Controllers/ActionController.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Http/Controllers/ActionController.php b/src/Http/Controllers/ActionController.php index c67dd46..a113580 100644 --- a/src/Http/Controllers/ActionController.php +++ b/src/Http/Controllers/ActionController.php @@ -9,8 +9,7 @@ class ActionController extends NovaActionController { /** - * This uses the custom ActionRequest typehint to enable - * dependency features. + * create custom request from base Nova ActionRequest * * @param \Laravel\Nova\Http\Requests\ActionRequest $request * @return \Illuminate\Http\Response