Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix proper deletion of files/images within Flexible layouts #108

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
"autoload": {
"psr-4": {
"Whitecube\\NovaFlexibleContent\\": "src/"
}
},
"files": [
"src/Helper.php"
]
},
"extra": {
"laravel": {
Expand Down
114 changes: 114 additions & 0 deletions src/Collections/FieldCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?php

namespace Whitecube\NovaFlexibleContent\Collections;

use Laravel\Nova\Fields\Field;
use Laravel\Nova\Fields\FieldCollection as NovaFieldCollection;
use Laravel\Nova\Http\Requests\NovaRequest;
use Whitecube\NovaFlexibleContent\Flexible;

class FieldCollection extends NovaFieldCollection
{
/**
* Find a given field by its attribute.
*
* @param string $attribute
* @param mixed $default
* @return \Laravel\Nova\Fields\Field|null
*/
public function findFieldByAttribute($attribute, $default = null)
{
if (strpos($attribute, '__') !== false) {
$request = resolve(NovaRequest::class);
$resource = $request->findResourceOrFail();
$fields = $resource->updateFields($request);

$attribute_parts = explode('__', $attribute, 2);

$groups = [];
foreach ($fields as $i => $field) {
if ($field instanceof Flexible) {
$field->index = $i;
$groups = array_merge($groups, $this->flattenGroups($field));
}
}

foreach ($groups as $group) {
if ($group->inUseKey() !== $attribute_parts[0]) {
continue;
}

$field = $group->collectionFields()->first(function ($field) use ($attribute_parts, $group) {
$field->group = $group;

return isset($field->attribute) &&
$field->attribute == $attribute_parts[1];
}, $default);

return $this->addDeleteCallback($field);
}
}

return $this->first(function ($field) use ($attribute) {
return isset($field->attribute) &&
$field->attribute == $attribute;
}, $default);
}

/**
* Flatten all groups into a single array
*
* @param Field $field
* @param $parentGroup
* @return array
*/
private function flattenGroups(Field $field, $parentGroup = null)
{
if (!$field->groups()) {
return [];
}

$flattened = [];

foreach ($field->groups() as $groupIndex => $group) {
$group->originalField = ($parentGroup ? $parentGroup->originalField . (isset($field->index) ? '.' . $field->index : '') . '.attributes.' : '') . $field->attribute . '.' . $groupIndex;

foreach ($group->collectionFields() as $groupField) {
if ($groupField instanceof Flexible) {
$flattened = array_merge($flattened, $this->flattenGroups($groupField, $group));
}
}

$flattened[] = $group;
}
return $flattened;
}

/**
* Add the delete callback helper
*
* @param Field|null $field
* @return Field|null
*/
private function addDeleteCallback(?Field $field)
{
if (!$field || !isset($field->deleteCallback)) {
return $field;
}

$callback = false;
if (is_callable($field->deleteCallback)) {
$callback = $field->deleteCallback;
}

$field->delete(function(NovaRequest $request, $model) use ($callback, $field) {
if ($callback && $callback->call($field, ...func_get_args()) === true) {
return true;
}

return \Whitecube\NovaFlexibleContent\deleteFile($request, $model, $field);
});

return $field;
}
}
20 changes: 20 additions & 0 deletions src/Flexible.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,26 @@ public function __construct($name, $attribute = null, $resolveCallback = null)
$this->hideFromIndex();
}

/**
* Get the field layouts
*
* @return Collection
*/
public function layouts()
{
return $this->layouts;
}

/**
* Get the field groups
*
* @return Collection
*/
public function groups()
{
return $this->groups;
}

/**
* Set the button's label
*
Expand Down
29 changes: 29 additions & 0 deletions src/Helper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Whitecube\NovaFlexibleContent;

use Illuminate\Support\Arr;
use Laravel\Nova\Http\Requests\NovaRequest;

/**
* Correctly removes a file inside of a flexible layout
*
* @param Laravel\Nova\Http\Requests\NovaRequest $request
* @param $model
* @return boolean
*/
function deleteFile(NovaRequest $request, $model, $field)
{
$path = explode('.', $field->group->originalField);
$path[] = 'attributes';
$path[] = $field->attribute;

$mainField = array_shift($path);
$data = $model->{$mainField};

Arr::set($data, implode('.', $path), '');

$model->{$mainField} = $data;
$model->save();
return true;
}
10 changes: 10 additions & 0 deletions src/Layouts/Layout.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,16 @@ public function fields()
return $this->fields ? $this->fields->all() : [];
}

/**
* Retrieve the layout's fields as a collection
*
* @return \Illuminate\Support\Collection
*/
public function collectionFields()
{
return $this->fields;
}

/**
* Retrieve the layout's unique key
*
Expand Down
21 changes: 21 additions & 0 deletions src/Traits/AvailableFields.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Whitecube\NovaFlexibleContent\Traits;

use Laravel\Nova\Http\Requests\NovaRequest;
use Whitecube\NovaFlexibleContent\Collections\FieldCollection;
use Whitecube\NovaFlexibleContent\Flexible;

trait AvailableFields
{
/**
* Get the fields that are available for the given request.
*
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
* @return \Laravel\Nova\Fields\FieldCollection
*/
public function availableFields(NovaRequest $request)
{
return new FieldCollection(array_values($this->filter($this->fields($request))));
}
}