From baf73009dcfba08d8f02a305cf45108a3ba75375 Mon Sep 17 00:00:00 2001 From: Theofanis Date: Thu, 6 Oct 2022 11:59:24 +0300 Subject: [PATCH] fixes --- src/Http/Controllers/ResolvesFields.php | 189 ++++++++++++------------ src/ManyToMany.php | 162 ++++++++++---------- 2 files changed, 179 insertions(+), 172 deletions(-) diff --git a/src/Http/Controllers/ResolvesFields.php b/src/Http/Controllers/ResolvesFields.php index 0cf009a..dd086a7 100644 --- a/src/Http/Controllers/ResolvesFields.php +++ b/src/Http/Controllers/ResolvesFields.php @@ -1,200 +1,203 @@ resolvePivotFields( - $request, $resource, $request->relatedResource + $request, $resource, $request->field ); - - if($request->isUpdateOrUpdateAttachedRequest()) { + + if ($request->isUpdateOrUpdateAttachedRequest()) { return $this->removeNonUpdateFields($request, $fields, $resource); } - - if($request->isCreateOrAttachRequest()) { + + if ($request->isCreateOrAttachRequest()) { return $this->removeNonCreationFields($request, $fields); } - + return $this->removeNonDetailFields($request, $fields, $resource) - ->each(function($field) use ($request, $resource) { - $relatedClass = Nova::resourceForKey($request->relatedResource); - - $relatedResource = new $relatedClass( - $this->pivotModel($request, $resource, $request->relatedResource) - ); - - $field->resolveForDisplay($relatedResource); - }); - } - + ->each(function ($field) use ($request, $resource) { + $relatedClass = Nova::resourceForKey($request->relatedResource); + + $relatedResource = new $relatedClass( + $this->pivotModel($request, $resource, $request->field) + ); + + $field->resolveForDisplay($relatedResource); + }); + } + /** * Resolve the pivot fields for the requested resource. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request - * @param \Laravel\Nova\Resource $resource - * @param string $relatedResource + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @param \Laravel\Nova\Resource $resource + * @param string $relatedResource * @return \Laravel\Nova\Fields\FieldCollection */ public function resolvePivotFields(NovaRequest $request, $resource, $relatedResource) - { + { $pivotModel = $this->pivotModel($request, $resource, $relatedResource); - + $fields = $this->pivotFieldsFor($request, $resource, $relatedResource); - + $resolveCallback = function ($field) use ($pivotModel) { - if ($field instanceof Resolvable) { + if ($field instanceof Resolvable) { $field->resolve($pivotModel); } }; - + return FieldCollection::make($this->filter($fields->each($resolveCallback)->filter->authorize($request)->values()->all()))->values(); } - + /** * Resolve the pivot model for the requested resource and requested related id. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request - * @param \Laravel\Nova\Resource $resource - * @param string $relatedResource + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @param \Laravel\Nova\Resource $resource + * @param string $relatedResource * @return \Illuminate\Database\Eloquent\Model */ public function pivotModel(NovaRequest $request, $resource, $relatedResource) - { + { $relatedField = $this->relatedFieldFor($request, $resource, $relatedResource); - + throw_unless($relatedField, \Exception::class, "Related field not found for resource " . get_class($resource) . " for field $relatedResource"); $accessor = $this->pivotAccessorFor($request, $resource, $relatedField); - - $query = $resource->{$relatedField->manyToManyRelationship}(); - - if($related = $query->wherePivot('id', $request->pivotId)->first()) { + + $query = $resource->{$relatedField->manyToManyRelationship}(); + + if ($related = $query->wherePivot('id', $request->pivotId)->first()) { return $related->{$accessor}; - } - + } + return new Pivot; } - + /** * Get the pivot fields for the resource and relation. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request - * @param string $resource + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @param Resource $resource * @return \Laravel\Nova\Fields\FieldCollection */ public function pivotFieldsFor($request, $resource) { - $field = $this->relatedFieldFor($request, $resource, $request->relatedResource); - - if($field && isset($field->fieldsCallback)) { + $field = $this->relatedFieldFor($request, $resource, $request->field); + + if ($field && isset($field->fieldsCallback)) { return FieldCollection::make(array_values( $this->filter(call_user_func($field->fieldsCallback, $request, $resource)) ))->each(function ($field) { $field->pivot = true; - }); + }); } - + return new FieldCollection; - } - + } + /** * Get the pivot fields for the resource and relation. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request - * @param string $attribute - * @return \Laravel\Nova\Fields\FieldCollection + * @param NovaRequest $request + * @param Resource $resource + * @param string $attribute + * @return Field|null */ public function relatedFieldFor(NovaRequest $request, $resource, $attribute) { return $resource->availableFields($request) - ->whereInstanceOf(ManyToMany::class) - ->where('attribute', $attribute) - ->first(); - } - + ->whereInstanceOf(ManyToMany::class) + ->where('attribute', $attribute) + ->first(); + } + /** * Get the name of the pivot accessor for the requested relationship. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request - * @param \Laravel\Nova\Resource $resource - * @param \Laravel\Nova\Field $field + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @param \Laravel\Nova\Resource $resource + * @param Field $field * @return string */ public function pivotAccessorFor(NovaRequest $request, $resource, $field) - { + { return $resource->{$field->manyToManyRelationship}()->getPivotAccessor(); } - + /** * Remove non-update fields from the given collection. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request - * @param \Laravel\Nova\Fields\FieldCollection $fields - * @param \Laravel\Nova\Resource $resource + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @param \Laravel\Nova\Fields\FieldCollection $fields + * @param \Laravel\Nova\Resource $resource * @return \Laravel\Nova\Fields\FieldCollection */ protected function removeNonUpdateFields(NovaRequest $request, FieldCollection $fields, $resource) { - return $fields->reject(function($field) use ($request, $resource) { - return $this->isNonEditableField($request, $field) || - ! $field->isShownOnUpdate($request, $resource); + return $fields->reject(function ($field) use ($request, $resource) { + return $this->isNonEditableField($request, $field) || + !$field->isShownOnUpdate($request, $resource); }); - } - + } + /** * Remove non-creation fields from the given collection. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request - * @param \Laravel\Nova\Fields\FieldCollection $fields + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @param \Laravel\Nova\Fields\FieldCollection $fields * @return \Laravel\Nova\Fields\FieldCollection */ protected function removeNonCreationFields(NovaRequest $request, FieldCollection $fields) { - return $fields->reject(function($field) use ($request) { - return $this->isNonEditableField($request, $field) || - ! $field->isShownOnCreation($request); + return $fields->reject(function ($field) use ($request) { + return $this->isNonEditableField($request, $field) || + !$field->isShownOnCreation($request); }); - } - + } + /** * Remove non-creation fields from the given collection. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request - * @param \Laravel\Nova\Fields\FieldCollection $fields + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @param \Laravel\Nova\Fields\FieldCollection $fields * @return \Laravel\Nova\Fields\FieldCollection */ protected function removeNonDetailFields(NovaRequest $request, FieldCollection $fields, $resource) { - return $fields->reject(function($field) use ($request, $resource) { - return ! $field->isShownOnDetail($request, $resource); + return $fields->reject(function ($field) use ($request, $resource) { + return !$field->isShownOnDetail($request, $resource); }); - } + } /** * Detect if the field cannot be edit. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request - * @param \Laravel\Nova\Fields\Field $field + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @param \Laravel\Nova\Fields\Field $field * @return boolean */ protected function isNonEditableField(NovaRequest $request, $field) { $resource = $request->newResource(); - - return $field instanceof ListableField || - $field instanceof ResourceToolElement || - $field->attribute === 'ComputedField' || - ($field instanceof ID && $field->attribute === $resource->getKeyName()); + + return $field instanceof ListableField || + $field instanceof ResourceToolElement || + $field->attribute === 'ComputedField' || + ($field instanceof ID && $field->attribute === $resource->getKeyName()); } } diff --git a/src/ManyToMany.php b/src/ManyToMany.php index a81674a..f4e030a 100644 --- a/src/ManyToMany.php +++ b/src/ManyToMany.php @@ -98,9 +98,9 @@ abstract class ManyToMany extends Field /** * Create a new field. * - * @param string $name - * @param string|null $attribute - * @param string|null $resource + * @param string $name + * @param string|null $attribute + * @param string|null $resource * @return void */ public function __construct($name, $attribute = null, $resource = null) @@ -119,28 +119,28 @@ public function __construct($name, $attribute = null, $resource = null) }; $this->fillCallback = function ($pivots) { - return (array) $pivots; + return (array)$pivots; }; } /** * Determine if the field should be displayed for the given request. * - * @param \Illuminate\Http\Request $request + * @param \Illuminate\Http\Request $request * @return bool */ public function authorize(Request $request) { return call_user_func( - [$this->resourceClass, 'authorizedToViewAny'], $request - ) && parent::authorize($request); + [$this->resourceClass, 'authorizedToViewAny'], $request + ) && parent::authorize($request); } /** * Resolve the field's value. * - * @param mixed $resource - * @param string|null $attribute + * @param mixed $resource + * @param string|null $attribute * @return void */ public function resolve($resource, $attribute = null) @@ -151,28 +151,30 @@ public function resolve($resource, $attribute = null) $value = $resource->getRelation($this->manyToManyRelationship); } - if (! $value) { + if (!$value) { $value = $resource->{$this->manyToManyRelationship}() - ->withoutGlobalScopes() - ->getResults(); + ->withoutGlobalScopes() + ->getResults(); } - $this->value = collect($value)->map(function($resource) { + $pivotAccessor = $resource->{$this->manyToManyRelationship}()->getPivotAccessor(); + + $this->value = collect($value)->map(function ($resource) use ($pivotAccessor) { $display = $this->formatAttachableResource( app(NovaRequest::class), new $this->resourceClass($resource) ); - return array_merge(['pivotId' => $resource->pivot->id], $display); + return array_merge(['pivotId' => $resource->{$pivotAccessor}->id], $display); }); } /** * Hydrate the given attribute on the model based on the incoming request. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request - * @param string $requestAttribute - * @param object $model - * @param string $attribute + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @param string $requestAttribute + * @param object $model + * @param string $attribute * @return mixed */ protected function fillAttribute(NovaRequest $request, $requestAttribute, $model, $attribute) @@ -180,7 +182,7 @@ protected function fillAttribute(NovaRequest $request, $requestAttribute, $model if ($request->exists($requestAttribute)) { $value = collect($request[$requestAttribute])->map([$this, 'normalize']); - $model::saved(function($model) use ($value, $request, $requestAttribute) { + $model::saved(function ($model) use ($value, $request, $requestAttribute) { $authorized = $this->removeNonAuthorizedAttachments($request, $value, $model); $relationship = $model->{$this->manyToManyRelationship}()->withPivot('id'); @@ -190,17 +192,17 @@ protected function fillAttribute(NovaRequest $request, $requestAttribute, $model $detaching = $this->mergeDetachments($model, $authorized); $relationship->wherePivotIn('id', $detaching->pluck('pivotId')->all()) - ->detach($detaching->pluck('id')->all()); + ->detach($detaching->pluck('id')->all()); - if(! $this->duplicate) { + if (!$this->duplicate) { $attaching = $this->removeDuplicateAttachments($model, $attaching) - ->keyBy('id') - ->map([$this, 'fetchPivotValues']) - ->all(); + ->keyBy('id') + ->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) ); @@ -213,13 +215,13 @@ protected function fillAttribute(NovaRequest $request, $requestAttribute, $model /** * Convert field data to correct format. * - * @param array $attachment + * @param array $attachment * @return array */ public function normalize($attachment) { $attachment['attached'] = filter_var($attachment['attached'], FILTER_VALIDATE_BOOLEAN); - $attachment['id'] = (int) $attachment['id']; + $attachment['id'] = (int)$attachment['id']; return $attachment; } @@ -227,59 +229,61 @@ public function normalize($attachment) /** * Remove non authorized attachments. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request - * @param array $attachments - * @param integer $model + * @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 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 + * @param NovaRequest $request + * @param array $attachment * @return boolean */ protected function authorizedToAttach(NovaRequest $request, $attachment) { $parentModel = $request->resourceId - ? $request->findModelOrFail() : $request->model(); + ? $request->findModelOrFail() + : $request->model(); $parentResource = Nova::resourceForModel($parentModel); return (new $parentResource($parentModel))->authorizedToAttachAny( - $request, $attachment - ) || (new $parentResource($parentModel))->authorizedToAttach( - $request, $attachment - ); + $request, $attachment + ) || (new $parentResource($parentModel))->authorizedToAttach( + $request, $attachment + ); } /** * Append database detachemnts into detachments. * - * @param \Illuminate\Database\Eloquent\Model $model - * @param array $authorized + * @param \Illuminate\Database\Eloquent\Model $model + * @param array $authorized * @return array */ protected function mergeDetachments($model, $authorized) { $pivotKeys = $authorized->filter->attached->pluck('pivotId')->all(); - + $pivotAccessor = $model->{$this->manyToManyRelationship}()->getPivotAccessor(); + $shouldDetach = $model->{$this->manyToManyRelationship}() - ->withPivot('id') - ->wherePivotNotIn('id', $pivotKeys)->get() - ->map(function($related) { - return [ - 'id' => $related->id, - 'pivotId' => $related->pivot->id, - ]; - }); + ->withPivot('id') + ->wherePivotNotIn('id', $pivotKeys)->get() + ->map(function ($related) use ($pivotAccessor) { + return [ + 'id' => $related->id, + 'pivotId' => $related->{$pivotAccessor}->id, + ]; + }); return $authorized->reject->attached->merge($shouldDetach); } @@ -287,15 +291,15 @@ protected function mergeDetachments($model, $authorized) /** * Remove related that before is attached * - * @param \Illuminate\Database\Eloquent\Model $model - * @param array $attaching + * @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 $attaching->reject(function ($attachment) use ($attachments) { return $attachments->contains($attachment['id']); }); } @@ -303,12 +307,12 @@ public function removeDuplicateAttachments($model, $attaching) /** * Apply the fillCalback into attachment pivots and fetch them. * - * @param array $attachment + * @param array $attachment * @return array */ public function fetchPivotValues($attachment) { - return (array) call_user_func( + return (array)call_user_func( $this->fillCallback, $attachment['pivots'] ?? [], $attachment['id'] ); } @@ -316,8 +320,8 @@ public function fetchPivotValues($attachment) /** * Build an attachable query for the field. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request - * @param bool $withTrashed + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @param bool $withTrashed * @return \Illuminate\Database\Eloquent\Builder */ public function buildAttachableQuery(NovaRequest $request, $withTrashed = false) @@ -330,9 +334,9 @@ public function buildAttachableQuery(NovaRequest $request, $withTrashed = false) } $query = $resourceClass::buildIndexQuery( - $request, $modelQuery, $request->search, [], [], - TrashedStatus::fromBoolean($withTrashed) - ); + $request, $modelQuery, $request->search, [], [], + TrashedStatus::fromBoolean($withTrashed) + ); return $query->tap(function ($query) use ($request, $model) { forward_static_call($this->attachableQueryCallable($request, $model), $request, $query); @@ -342,27 +346,27 @@ public function buildAttachableQuery(NovaRequest $request, $withTrashed = false) /** * Get the attachable query method name. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request - * @param \Illuminate\Database\Eloquent\Model $model + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @param \Illuminate\Database\Eloquent\Model $model * @return array */ protected function attachableQueryCallable(NovaRequest $request, $model) { return ($method = $this->attachableQueryMethod($request, $model)) - ? [$request->resource(), $method] - : [$this->resourceClass, 'relatableQuery']; + ? [$request->resource(), $method] + : [$this->resourceClass, 'relatableQuery']; } /** * Get the attachable query method name. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request - * @param \Illuminate\Database\Eloquent\Model $model + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @param \Illuminate\Database\Eloquent\Model $model * @return string */ protected function attachableQueryMethod(NovaRequest $request, $model) { - $method = 'relatable'.Str::plural(class_basename($model)); + $method = 'relatable' . Str::plural(class_basename($model)); if (method_exists($request->resource(), $method)) { return $method; @@ -372,24 +376,24 @@ protected function attachableQueryMethod(NovaRequest $request, $model) /** * Format the given attachable resource. * - * @param \Laravel\Nova\Http\Requests\NovaRequest $request - * @param mixed $resource + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @param mixed $resource * @return array */ public function formatAttachableResource(NovaRequest $request, $resource, $attached = false) { return array_filter([ - 'avatar' => $resource->resolveAvatarUrl($request), - 'text' => strval($this->formatDisplayValue($resource)), - 'id' => $resource->getKey(), - 'attached' => $attached, + 'avatar' => $resource->resolveAvatarUrl($request), + 'text' => strval($this->formatDisplayValue($resource)), + 'id' => $resource->getKey(), + 'attached' => $attached, ]); } /** * Specify the callback to be executed to retrieve the pivot fields. * - * @param callable $callback + * @param callable $callback * @return $this */ public function fields(callable $callback) @@ -452,7 +456,7 @@ public function withoutTrashed() * * @return $this */ - public function searchable(bool $searchable = true, $searchResultLimit = false ) + public function searchable(bool $searchable = true, $searchResultLimit = false) { $this->searchResultLimit = $searchResultLimit; return $this->withMeta(compact('searchable')); @@ -467,11 +471,11 @@ public function jsonSerialize() { return array_merge([ 'belongsToManyRelationship' => $this->manyToManyRelationship, - 'resourceName' => $this->resourceName, - 'placeholder' => $this->placeholder, - 'duplicate' => $this->duplicate, - 'pivots' => $this->pivots, - 'withTrashed' => $this->displaysWithTrashed, + 'resourceName' => $this->resourceName, + 'placeholder' => $this->placeholder, + 'duplicate' => $this->duplicate, + 'pivots' => $this->pivots, + 'withTrashed' => $this->displaysWithTrashed, ], parent::jsonSerialize()); } }