Skip to content

Commit

Permalink
Merge pull request #6 from SadeghPM/master
Browse files Browse the repository at this point in the history
Improve Searchable
  • Loading branch information
zareismail authored Apr 19, 2021
2 parents fc7d0d0 + f69eb66 commit b9bc7d8
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 72 deletions.
10 changes: 5 additions & 5 deletions resources/js/components/FormField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -226,11 +226,11 @@ export default {
this.search = search;
setTimeout(() => {
if (this.search == search && this.search.length > 0) {
_.debounce(() => {
if (this.search == search && this.search.length > 0) {
this.getAvailableResources()
}
}, 500)
}
}, Nova.config.debounce)()
},
appendToForm(object, formData, prefix) {
Expand Down Expand Up @@ -500,4 +500,4 @@ export default {
}
}
}
</script>
</script>
147 changes: 80 additions & 67 deletions src/ManyToMany.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,24 @@

use Illuminate\Http\Request;
use Laravel\Nova\Http\Requests\NovaRequest;
use Laravel\Nova\Fields\Field;
use Laravel\Nova\Fields\DetachesPivotModels;
use Laravel\Nova\Fields\ResourceRelationshipGuesser;
use Laravel\Nova\Fields\FormatsRelatableDisplayValues;
use Laravel\Nova\Fields\Field;
use Laravel\Nova\Fields\DetachesPivotModels;
use Laravel\Nova\Fields\ResourceRelationshipGuesser;
use Laravel\Nova\Fields\FormatsRelatableDisplayValues;
use Laravel\Nova\TrashedStatus;
use Illuminate\Support\Str;
use Laravel\Nova\Nova;

abstract class ManyToMany extends Field
{
{
use DetachesPivotModels, FormatsRelatableDisplayValues;

/**
* The field's component.
*
* @var string
*/
public $component = 'armincms-belongs-to-many';
public $component = 'armincms-belongs-to-many';

/**
* The class name of the related resource.
Expand Down Expand Up @@ -49,14 +49,14 @@ abstract class ManyToMany extends Field
*
* @var callable
*/
public $fieldsCallback;
public $fieldsCallback;

/**
* The column that should be displayed for the field.
*
* @var \Closure
*/
public $display;
public $display;

/**
* The label of resource selection.
Expand All @@ -70,15 +70,15 @@ abstract class ManyToMany extends Field
*
* @var string
*/
public $duplicate = false;
public $duplicate = false;


/**
* Determine if attach the pivot columns.
*
* @var string
*/
public $pivots = false;
public $pivots = false;

/**
* Indicates whether the field should display the "With Trashed" option.
Expand All @@ -87,6 +87,13 @@ abstract class ManyToMany extends Field
*/
public $displaysWithTrashed = true;

/**
* Indicates whether search results should be limited.
*
* @var bool
*/
public $searchResultLimit = false;


/**
* Create a new field.
Expand All @@ -109,12 +116,12 @@ public function __construct($name, $attribute = null, $resource = null)

$this->fieldsCallback = function () {
return [];
};
};

$this->fillCallback = function ($pivots) {
return (array) $pivots;
};
}
};
}

/**
* Determine if the field should be displayed for the given request.
Expand All @@ -137,7 +144,7 @@ public function authorize(Request $request)
* @return void
*/
public function resolve($resource, $attribute = null)
{
{
$value = null;

if ($resource->relationLoaded($this->manyToManyRelationship)) {
Expand All @@ -148,7 +155,7 @@ public function resolve($resource, $attribute = null)
$value = $resource->{$this->manyToManyRelationship}()
->withoutGlobalScopes()
->getResults();
}
}

$this->value = collect($value)->map(function($resource) {
$display = $this->formatAttachableResource(
Expand All @@ -157,7 +164,7 @@ public function resolve($resource, $attribute = null)

return array_merge(['pivotId' => $resource->pivot->id], $display);
});
}
}

/**
* Hydrate the given attribute on the model based on the incoming request.
Expand All @@ -170,47 +177,47 @@ public function resolve($resource, $attribute = null)
*/
protected function fillAttribute(NovaRequest $request, $requestAttribute, $model, $attribute)
{
if ($request->exists($requestAttribute)) {
$value = collect($request[$requestAttribute])->map([$this, 'normalize']);
if ($request->exists($requestAttribute)) {
$value = collect($request[$requestAttribute])->map([$this, 'normalize']);

$model::saved(function($model) use ($value, $request, $requestAttribute) {
$authorized = $this->removeNonAuthorizedAttachments($request, $value, $model);

$relationship = $model->{$this->manyToManyRelationship}()->withPivot('id');

$attaching = $authorized->reject->attached;
$attaching = $authorized->reject->attached;

$detaching = $this->mergeDetachments($model, $authorized);
$detaching = $this->mergeDetachments($model, $authorized);

$relationship->wherePivotIn('id', $detaching->pluck('pivotId')->all())
->detach($detaching->pluck('id')->all());

if(! $this->duplicate) {
if(! $this->duplicate) {
$attaching = $this->removeDuplicateAttachments($model, $attaching)
->keyBy('id')
->map([$this, 'fetchPivotValues'])
->map([$this, 'fetchPivotValues'])
->all();

$relationship->syncWithoutDetaching($attaching);
} else {
$attaching->each(function($attachment) use ($relationship) {
$attaching->each(function($attachment) use ($relationship) {
$relationship->attach(
$attachment['id'], $this->fetchPivotValues($attachment)
);
});
}
});
}
});
}
});
}
}

/**
* Convert field data to correct format.
*
* @param array $attachment
* @return array
*
* @param array $attachment
* @return array
*/
public function normalize($attachment)
{
{
$attachment['attached'] = filter_var($attachment['attached'], FILTER_VALIDATE_BOOLEAN);
$attachment['id'] = (int) $attachment['id'];

Expand All @@ -219,28 +226,28 @@ public function normalize($attachment)

/**
* Remove non authorized attachments.
*
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
* @param array $attachments
* @param integer $model
* @return array
*
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
* @param array $attachments
* @param integer $model
* @return array
*/
protected function removeNonAuthorizedAttachments(NovaRequest $request, $attachments, $model)
{
return collect($attachments)->filter(function($attachment) use ($request, $model) {
return $this->authorizedToAttach($request, $attachment['id']);
{
return collect($attachments)->filter(function($attachment) use ($request, $model) {
return $this->authorizedToAttach($request, $attachment['id']);
});
}

/**
* Detect if user can attach related resource
* @param NovaRequest $request
* @param array $attachment
* @return boolean
* @param NovaRequest $request
* @param array $attachment
* @return boolean
*/
protected function authorizedToAttach(NovaRequest $request, $attachment)
{
$parentModel = $request->resourceId
{
$parentModel = $request->resourceId
? $request->findModelOrFail() : $request->model();

$parentResource = Nova::resourceForModel($parentModel);
Expand All @@ -255,10 +262,10 @@ protected function authorizedToAttach(NovaRequest $request, $attachment)

/**
* Append database detachemnts into detachments.
*
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param array $authorized
* @return array
* @return array
*/
protected function mergeDetachments($model, $authorized)
{
Expand All @@ -274,37 +281,37 @@ protected function mergeDetachments($model, $authorized)
];
});

return $authorized->reject->attached->merge($shouldDetach);
return $authorized->reject->attached->merge($shouldDetach);
}

/**
* Remove related that before is attached
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param array $attaching
* @return array
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param array $attaching
* @return array
*/
public function removeDuplicateAttachments($model, $attaching)
{
$attachments = $model->{$this->manyToManyRelationship}()->get()->pluck('id');

return $attaching->reject(function($attachment) use ($attachments) {
return $attachments->contains($attachment['id']);
});
});
}

/**
* Apply the fillCalback into attachment pivots and fetch them.
*
* @param array $attachment
* @return array
*
* @param array $attachment
* @return array
*/
public function fetchPivotValues($attachment)
{
{
return (array) call_user_func(
$this->fillCallback, $attachment['pivots'] ?? [], $attachment['id']
);
}
);
}

/**
* Build an attachable query for the field.
Expand All @@ -317,8 +324,13 @@ public function buildAttachableQuery(NovaRequest $request, $withTrashed = false)
{
$model = forward_static_call([$resourceClass = $this->resourceClass, 'newModel']);

$modelQuery = $model->newQuery();
if ($this->searchResultLimit) {
$modelQuery = $modelQuery->limit($resourceClass::$perPageOptions[0]);
}

$query = $resourceClass::buildIndexQuery(
$request, $model->newQuery(), $request->search, [], [],
$request, $modelQuery, $request->search, [], [],
TrashedStatus::fromBoolean($withTrashed)
);

Expand Down Expand Up @@ -385,7 +397,7 @@ public function fields(callable $callback)
$this->fieldsCallback = $callback;

return $this;
}
}

/**
* Set the label of the resource selection.
Expand Down Expand Up @@ -440,8 +452,9 @@ public function withoutTrashed()
*
* @return $this
*/
public function searchable(bool $searchable = true)
public function searchable(bool $searchable = true, $searchResultLimit = false )
{
$this->searchResultLimit = $searchResultLimit;
return $this->withMeta(compact('searchable'));
}

Expand All @@ -453,12 +466,12 @@ public function searchable(bool $searchable = true)
public function jsonSerialize()
{
return array_merge([
'belongsToManyRelationship' => $this->manyToManyRelationship,
'resourceName' => $this->resourceName,
'belongsToManyRelationship' => $this->manyToManyRelationship,
'resourceName' => $this->resourceName,
'placeholder' => $this->placeholder,
'duplicate' => $this->duplicate,
'pivots' => $this->pivots,
'withTrashed' => $this->displaysWithTrashed,
'duplicate' => $this->duplicate,
'pivots' => $this->pivots,
'withTrashed' => $this->displaysWithTrashed,
], parent::jsonSerialize());
}
}

0 comments on commit b9bc7d8

Please sign in to comment.