Skip to content

Commit

Permalink
Merge pull request #157 from epartment/fix-actions
Browse files Browse the repository at this point in the history
break out traits to fix Action vs ActionRequest usage
  • Loading branch information
ragingdave authored Mar 2, 2021
2 parents d0978d8 + a16b0a7 commit b432a2d
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 123 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
41 changes: 41 additions & 0 deletions src/ActionHasDependencies.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace Epartment\NovaDependencyContainer;

use Laravel\Nova\Http\Requests\ActionRequest;

trait ActionHasDependencies
{
use HasChildFields;

/**
* Validate action fields
*
* @param \Laravel\Nova\Http\Requests\ActionRequest $request
* @return void
*/
public function validateFields(ActionRequest $request)
{
$availableFields = [];

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)) {
$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());
}
}
45 changes: 45 additions & 0 deletions src/HasChildFields.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace Epartment\NovaDependencyContainer;

trait HasChildFields
{
protected $childFieldsArr = [];

/**
* @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;
}
}
105 changes: 14 additions & 91 deletions src/HasDependencies.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,16 @@

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;

trait HasDependencies
{
protected $childFieldsArr = [];
use HasChildFields;

/**
* @param NovaRequest $request
* @return FieldCollection|\Illuminate\Support\Collection
* @param NovaRequest $request
* @return FieldCollection
*/
public function availableFields(NovaRequest $request)
{
Expand All @@ -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
Expand All @@ -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
*/
Expand All @@ -99,72 +90,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());
}
}
46 changes: 15 additions & 31 deletions src/Http/Controllers/ActionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,21 @@
namespace Epartment\NovaDependencyContainer\Http\Controllers;

use Epartment\NovaDependencyContainer\Http\Requests\ActionRequest;
use Illuminate\Routing\Controller;
use Laravel\Nova\Http\Requests\NovaRequest;
use Laravel\Nova\Http\Requests\ActionRequest as NovaActionRequest;
use Laravel\Nova\Http\Controllers\ActionController as NovaActionController;

class ActionController extends Controller {
class ActionController extends NovaActionController
{
/**
* create custom request from base Nova ActionRequest
*
* @param \Laravel\Nova\Http\Requests\ActionRequest $request
* @return \Illuminate\Http\Response
*/
public function store(NovaActionRequest $request)
{
$request = ActionRequest::createFrom($request);

/**
* 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.
*
* @param \Laravel\Nova\Http\Requests\ActionRequest $request
* @return \Illuminate\Http\Response
*/
public function store(ActionRequest $request) {

$request->validateFields();

return $request->action()->handleRequest($request);
}
return parent::store($request);
}
}
31 changes: 30 additions & 1 deletion src/Http/Requests/ActionRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}

0 comments on commit b432a2d

Please sign in to comment.