/home/bdqbpbxa/api-uniferx.goodface.com.ua/vendor/laravel/nova/src/ResolvesFields.php
<?php

namespace Laravel\Nova;

use Closure;
use Illuminate\Support\Collection;
use Laravel\Nova\Actions\Actionable;
use Laravel\Nova\Contracts\BehavesAsPanel;
use Laravel\Nova\Contracts\Cover;
use Laravel\Nova\Contracts\Deletable;
use Laravel\Nova\Contracts\Downloadable;
use Laravel\Nova\Contracts\ListableField;
use Laravel\Nova\Contracts\RelatableField;
use Laravel\Nova\Contracts\Resolvable;
use Laravel\Nova\Fields\BelongsToMany;
use Laravel\Nova\Fields\Field;
use Laravel\Nova\Fields\FieldCollection;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\MorphMany;
use Laravel\Nova\Fields\MorphTo;
use Laravel\Nova\Fields\MorphToMany;
use Laravel\Nova\Fields\Unfillable;
use Laravel\Nova\Http\Requests\NovaRequest;

trait ResolvesFields
{
    /**
     * Resolve the index fields.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    public function indexFields(NovaRequest $request)
    {
        return $this->availableFields($request)
            ->when($request->viaManyToMany(), $this->relatedFieldResolverCallback($request))
            ->filterForIndex($request, $this->resource)
            ->withoutListableFields()
            ->authorized($request)
            ->resolveForDisplay($this->resource);
    }

    /**
     * Resolve the detail fields.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    public function detailFields(NovaRequest $request)
    {
        return $this->availableFields($request)
            ->when($request->viaManyToMany(), $this->fieldResolverCallback($request))
            ->when($this->shouldAddActionsField($request), function ($fields) {
                return $fields->push($this->actionfield());
            })
            ->filterForDetail($request, $this->resource)
            ->authorized($request)
            ->resolveForDisplay($this->resource);
    }

    /**
     * Resolve the authorized preview fields.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    protected function previewFieldsCollection(NovaRequest $request)
    {
        // If the user has specified the `fieldsForPreview` method, we're going to ignore any fields
        // using `showOnPreview` inside the resource's `fields`, `fieldsForIndex`, and `fieldsForDetail` methods.
        if (method_exists($this, 'fieldsForPreview')) {
            return FieldCollection::make(array_values($this->filter($this->fieldsForPreview($request))));
        }

        return $this->buildAvailableFields($request, ['fieldsForIndex', 'fieldsForDetail'])
            ->when($request->viaManyToMany(), $this->fieldResolverCallback($request))
            ->flattenStackedFields()
            ->withoutResourceTools()
            ->withoutListableFields()
            ->filter
            ->isShownOnPreview($request, $this->resource);
    }

    /**
     * Resolve the preview fields.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    public function previewFields(NovaRequest $request)
    {
        return $this->previewFieldsCollection($request)
            ->authorized($request)
            ->resolveForDisplay($this->resource);
    }

    /**
     * Return the count of preview fields available.
     *
     * @return int
     */
    public function previewFieldsCount(NovaRequest $request)
    {
        return $this->previewFieldsCollection($request)
            ->authorized($request)
            ->count();
    }

    /**
     * Resolve the authorized preview fields.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    protected function peekableFieldsCollection(NovaRequest $request)
    {
        // If the user has specified the `fieldsForPeeking` method, we're going to ignore any fields
        // using `showWhenPeeking` inside the resource's `fields`, `fieldsForIndex`, and `fieldsForDetail` methods.
        if (method_exists($this, 'fieldsForPeeking')) {
            return FieldCollection::make(array_values($this->filter($this->fieldsForPeeking($request))));
        }

        return $this->buildAvailableFields($request, ['fieldsForIndex', 'fieldsForDetail'])
            ->when($request->viaManyToMany(), $this->fieldResolverCallback($request))
            ->flattenStackedFields()
            ->withoutResourceTools()
            ->withoutListableFields()
            ->filterForPeeking($request);
    }

    /**
     * Resolve the peekable fields.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    public function peekableFields(NovaRequest $request)
    {
        return $this->peekableFieldsCollection($request)
            ->authorized($request)
            ->resolveForDisplay($this->resource)
            ->each(function (Field $field) {
                if (property_exists($field, 'copyable')) {
                    $field->copyable = false;
                }
            });
    }

    /**
     * Return the count of peekable fields available.
     *
     * @return int
     */
    public function peekableFieldsCount(NovaRequest $request)
    {
        return $this->peekableFieldsCollection($request)
            ->authorized($request)
            ->count();
    }

    /**
     * Resolve the deletable fields.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field&\Laravel\Nova\Contracts\Deletable>
     */
    public function deletableFields(NovaRequest $request)
    {
        return $this->availableFieldsOnIndexOrDetail($request)
            ->when($request->viaManyToMany(), $this->fieldResolverCallback($request))
            ->reject(function ($field) {
                return $field instanceof Unfillable;
            })
            ->whereInstanceOf(Deletable::class)
            ->unique(function ($field) {
                /** @var \Laravel\Nova\Fields\Field&\Laravel\Nova\Contracts\Deletable $field */
                return $field->attribute;
            })
            ->authorized($request)
            ->resolveForDisplay($this->resource);
    }

    /**
     * Resolve the downloadable fields.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field&\Laravel\Nova\Contracts\Downloadable>
     */
    public function downloadableFields(NovaRequest $request)
    {
        return $this->availableFieldsOnIndexOrDetail($request)
            ->when($request->viaManyToMany(), $this->fieldResolverCallback($request))
            ->whereInstanceOf(Downloadable::class)
            ->unique(function ($field) {
                /** @var \Laravel\Nova\Fields\Field&\Laravel\Nova\Contracts\Downloadable $field */
                return $field->attribute;
            })
            ->authorized($request)
            ->resolveForDisplay($this->resource);
    }

    /**
     * Resolve the filterable fields.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field&\Laravel\Nova\Contracts\FilterableField>
     */
    public function filterableFields(NovaRequest $request)
    {
        return $this->availableFieldsOnIndexOrDetail($request)
            ->when($request->viaManyToMany(), function ($fields) use ($request) {
                $relatedField = $request->findParentResource()->relatableField($request, $request->viaRelationship);

                if (! is_null($relatedField)) {
                    $fields->prepend($relatedField);
                }

                return call_user_func($this->relatedFieldResolverCallback($request), $fields);
            })
            ->flattenStackedFields()
            ->withOnlyFilterableFields()
            ->unique(function ($field) {
                return $field->attribute;
            })
            ->authorized($request);
    }

    /**
     * Get related field from resource by attribute.
     *
     * @param  string  $attribute
     * @return \Laravel\Nova\Fields\Field|null
     */
    public function relatableField(NovaRequest $request, $attribute)
    {
        return $this->availableFieldsOnIndexOrDetail($request)
            ->when($request->viaManyToMany(), $this->fieldResolverCallback($request))
            ->whereInstanceOf(RelatableField::class)
            ->when($this->shouldAddActionsField($request), function ($fields) {
                return $fields->push($this->actionfield());
            })
            ->first(function ($field) use ($attribute) {
                return $field->attribute === $attribute;
            });
    }

    /**
     * Determine resource has relatable field by attribute.
     *
     * @param  string  $attribute
     * @return bool
     */
    public function hasRelatableField(NovaRequest $request, $attribute)
    {
        return $this->relatableField($request, $attribute) !== null;
    }

    /**
     * Determine if the resource should have an Action field.
     *
     * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
     * @return bool
     */
    protected function shouldAddActionsField($request)
    {
        return with($this->actionfield(), function ($actionField) use ($request) {
            return in_array(Actionable::class, class_uses_recursive(static::newModel())) && $actionField->authorizedToSee($request);
        });
    }

    /**
     * Return a new Action field instance.
     *
     * @return \Laravel\Nova\Fields\MorphMany
     */
    protected function actionfield()
    {
        return MorphMany::make(Nova::__('Actions'), 'actions', Nova::actionResource())
            ->canSee(function ($request) {
                return Nova::actionResource()::authorizedToViewAny($request);
            });
    }

    /**
     * Resolve the detail fields and assign them to their associated panel.
     *
     * @param  \Laravel\Nova\Resource  $resource
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    public function detailFieldsWithinPanels(NovaRequest $request, Resource $resource)
    {
        return $this->detailFields($request)
            ->assignDefaultPanel(
                $request->viaRelationship() && $request->isResourceDetailRequest()
                    ? Panel::defaultNameForViaRelationship($resource, $request)
                    : Panel::defaultNameForDetail($resource)
            );
    }

    /**
     * Resolve the creation fields.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    public function creationFields(NovaRequest $request)
    {
        $fields = $this->availableFields($request)
            ->authorized($request)
            ->onlyCreateFields($request, $this->resource)
            ->resolve($this->resource);

        return $request->viaRelationship()
            ? $this->withPivotFields($request, $fields->all())
            : $fields;
    }

    /**
     * Return the creation fields excluding any readonly ones.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    public function creationFieldsWithoutReadonly(NovaRequest $request)
    {
        return $this->creationFields($request)
            ->withoutReadonly($request);
    }

    /**
     * Resolve the creation fields and assign them to their associated panel.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    public function creationFieldsWithinPanels(NovaRequest $request)
    {
        return $this->creationFields($request)
            ->assignDefaultPanel(Panel::defaultNameForCreate($request->newResource()));
    }

    /**
     * Resolve the creation pivot fields for a related resource.
     *
     * @param  string  $relatedResource
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    public function creationPivotFields(NovaRequest $request, $relatedResource)
    {
        return $this->resolvePivotFields($request, $relatedResource)
            ->onlyCreateFields($request, $this->resource);
    }

    /**
     * Resolve the update fields.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    public function updateFields(NovaRequest $request)
    {
        return $this->resolveFields($request)
            ->onlyUpdateFields($request, $this->resource);
    }

    /**
     * Return the update fields excluding any readonly ones.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    public function updateFieldsWithoutReadonly(NovaRequest $request)
    {
        return $this->updateFields($request)
            ->withoutReadonly($request);
    }

    /**
     * Resolve the update fields and assign them to their associated panel.
     *
     * @param  \Laravel\Nova\Resource|null  $resource
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    public function updateFieldsWithinPanels(NovaRequest $request, Resource $resource = null)
    {
        return $this->updateFields($request)
            ->assignDefaultPanel(Panel::defaultNameForUpdate($resource ?? $request->newResource()));
    }

    /**
     * Resolve the update pivot fields for a related resource.
     *
     * @param  string  $relatedResource
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    public function updatePivotFields(NovaRequest $request, $relatedResource)
    {
        return $this->resolvePivotFields($request, $relatedResource)
            ->onlyUpdateFields($request, $this->resource);
    }

    /**
     * Remove non-preview fields from the given collection.
     *
     * @return \Laravel\Nova\Fields\FieldCollection
     */
    protected function removeNonPreviewFields(NovaRequest $request, FieldCollection $fields)
    {
        return $fields->reject(function ($field) {
            return $field instanceof ListableField ||
                ($field instanceof ResourceTool || $field instanceof ResourceToolElement) ||
                $field->attribute === 'ComputedField' ||
                ($field instanceof ID && $field->attribute === $this->resource->getKeyName());
        });
    }

    /**
     * Resolve the given fields to their values.
     *
     * @param  (\Closure(\Laravel\Nova\Fields\FieldCollection):(\Laravel\Nova\Fields\FieldCollection))|null  $filter
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    protected function resolveFields(NovaRequest $request, Closure $filter = null)
    {
        $fields = $this->availableFields($request)->authorized($request);

        if (! is_null($filter)) {
            $fields = $filter($fields);
        }

        $fields->resolve($this->resource);

        return $request->viaRelationship()
            ? $this->withPivotFields($request, $fields->all())
            : $fields;
    }

    /**
     * Resolve the non pivot fields for the resource.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     *
     * @deprecated 4.x
     */
    protected function resolveNonPivotFields(NovaRequest $request)
    {
        return $this->availableFields($request)
            ->resolve($this->resource)
            ->authorized($request);
    }

    /**
     * Resolve the field for the given attribute.
     *
     * @param  string  $attribute
     * @return \Laravel\Nova\Fields\Field
     */
    public function resolveFieldForAttribute(NovaRequest $request, $attribute)
    {
        return $this->resolveFields($request)->findFieldByAttribute($attribute);
    }

    /**
     * Resolve the inverse field for the given relationship attribute.
     *
     * This is primarily used for Relatable rule to check if has-one / morph-one relationships are "full".
     *
     * @param  string  $attribute
     * @param  string|null  $morphType
     * @return \Laravel\Nova\Fields\FieldCollection
     */
    public function resolveInverseFieldsForAttribute(NovaRequest $request, $attribute, $morphType = null)
    {
        $field = $this->availableFields($request)
            ->findFieldByAttribute($attribute);

        if (! (! is_null($field) && $field->authorize($request) && isset($field->resourceClass))) {
            return new FieldCollection;
        }

        /** @var class-string<\Laravel\Nova\Resource> $relatedResource */
        $relatedResource = $field instanceof MorphTo
            ? Nova::resourceForKey($morphType ?? $request->{$attribute.'_type'})
            : ($field->resourceClass ?? null);

        $relatedResource = new $relatedResource($relatedResource::newModel());

        return $relatedResource->availableFields($request)->reject(function ($f) use ($field) {
            return isset($f->attribute) &&
                isset($field->inverse) &&
                $f->attribute !== $field->inverse;
        })->filter(function ($field) use ($request) {
            return isset($field->resourceClass) &&
                $field->resourceClass == $request->resource();
        });
    }

    /**
     * Resolve the resource's avatar field.
     *
     * @return \Laravel\Nova\Contracts\Cover|null
     */
    public function resolveAvatarField(NovaRequest $request)
    {
        return tap(
            $this->availableFields($request)
                ->whereInstanceOf(Cover::class)
                ->authorized($request)
                ->first(),
            function ($field) {
                if ($field instanceof Resolvable) {
                    $field->resolve($this->resource);
                }
            }
        );
    }

    /**
     * Resolve the resource's avatar URL, if applicable.
     *
     * @return string|null
     */
    public function resolveAvatarUrl(NovaRequest $request)
    {
        $field = $this->resolveAvatarField($request);

        if ($field) {
            return $field->resolveThumbnailUrl();
        }
    }

    /**
     * Determine whether the resource's avatar should be rounded, if applicable.
     *
     * @return bool
     */
    public function resolveIfAvatarShouldBeRounded(NovaRequest $request)
    {
        $field = $this->resolveAvatarField($request);

        if ($field) {
            return $field->isRounded();
        }

        return false;
    }

    /**
     * Get the panels that are available for the given create request.
     *
     * @param  \Laravel\Nova\Http\Requests\NovaRequest  $request
     * @param  \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>|null  $fields
     * @return array<int, \Laravel\Nova\Panel>
     */
    public function availablePanelsForCreate($request, FieldCollection $fields = null)
    {
        $method = $this->fieldsMethod($request);

        $fields = $fields ?? FieldCollection::make(value(function () use ($request, $method) {
            return array_values($this->{$method}($request));
        }))->onlyCreateFields($request, $this->resource);

        return $this->resolvePanelsFromFields(
            $request,
            $fields,
            Panel::defaultNameForCreate($request->newResource())
        )->all();
    }

    /**
     * Get the panels that are available for the given update request.
     *
     * @param  \Laravel\Nova\Resource  $resource
     * @param  \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>|null  $fields
     * @return array<int, \Laravel\Nova\Panel>
     */
    public function availablePanelsForUpdate(NovaRequest $request, Resource $resource = null, FieldCollection $fields = null)
    {
        $method = $this->fieldsMethod($request);

        $fields = $fields ?? FieldCollection::make(value(function () use ($request, $method) {
            return array_values($this->{$method}($request));
        }))->onlyUpdateFields($request, $this->resource);

        return $this->resolvePanelsFromFields(
            $request,
            $fields,
            Panel::defaultNameForUpdate($resource ?? $request->newResource())
        )->all();
    }

    /**
     * Get the panels that are available for the given detail request.
     *
     * @param  \Laravel\Nova\Resource  $resource
     * @param  \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>  $fields
     * @return array<int, \Laravel\Nova\Panel>
     */
    public function availablePanelsForDetail(NovaRequest $request, Resource $resource, FieldCollection $fields)
    {
        return $this->resolvePanelsFromFields(
            $request,
            $fields,
            $request->viaRelationship() && $request->isResourceDetailRequest()
                ? Panel::defaultNameForViaRelationship($resource, $request)
                : Panel::defaultNameForDetail($resource)
        )->all();
    }

    /**
     * Get the fields that are available for the given request.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    public function availableFields(NovaRequest $request)
    {
        $method = $this->fieldsMethod($request);

        return FieldCollection::make(array_values($this->filter($this->{$method}($request))));
    }

    /**
     * Get the fields that are available on "index" or "detail" for the given request.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    public function availableFieldsOnIndexOrDetail(NovaRequest $request)
    {
        return $this->buildAvailableFields($request, ['fieldsForIndex', 'fieldsForDetail']);
    }

    /**
     * Get the fields that are available for the given request.
     *
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    public function buildAvailableFields(NovaRequest $request, array $methods)
    {
        $fields = collect([
            method_exists($this, 'fields') ? $this->fields($request) : [],
        ]);

        collect($methods)
            ->filter(function ($method) {
                return $method != 'fields' && method_exists($this, $method);
            })->each(function ($method) use ($request, $fields) {
                $fields->push([$this->{$method}($request)]);
            });

        return FieldCollection::make(array_values($this->filter($fields->flatten()->all())));
    }

    /**
     * Compute the method to use to get the available fields.
     *
     * @return string
     */
    protected function fieldsMethod(NovaRequest $request)
    {
        if ($request->isInlineCreateRequest() && method_exists($this, 'fieldsForInlineCreate')) {
            return 'fieldsForInlineCreate';
        }

        if ($request->isResourceIndexRequest() && method_exists($this, 'fieldsForIndex')) {
            return 'fieldsForIndex';
        }

        if ($request->isResourceDetailRequest() && method_exists($this, 'fieldsForDetail')) {
            return 'fieldsForDetail';
        }

        if ($request->isCreateOrAttachRequest() && method_exists($this, 'fieldsForCreate')) {
            return 'fieldsForCreate';
        }

        if ($request->isUpdateOrUpdateAttachedRequest() && method_exists($this, 'fieldsForUpdate')) {
            return 'fieldsForUpdate';
        }

        return 'fields';
    }

    /**
     * Merge the available pivot fields with the given fields.
     *
     * @param  array<int, \Laravel\Nova\Fields\Field>  $fields
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    protected function withPivotFields(NovaRequest $request, array $fields)
    {
        $pivotFields = $this->resolvePivotFields($request, $request->viaResource)->all();

        if ($index = $this->indexToInsertPivotFields($request, $fields)) {
            array_splice($fields, $index + 1, 0, $pivotFields);
        } else {
            $fields = array_merge($fields, $pivotFields);
        }

        return FieldCollection::make($fields);
    }

    /**
     * Resolve the pivot fields for the requested resource.
     *
     * @param  string  $relatedResource
     * @return \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>
     */
    public function resolvePivotFields(NovaRequest $request, $relatedResource)
    {
        $fields = $this->pivotFieldsFor($request, $relatedResource);

        return FieldCollection::make($this->filter($fields->each(function ($field) {
            if ($field instanceof Resolvable) {
                $field->resolve(
                    $this->{$field->pivotAccessor} ?? $field->pivotRelation->newPivot($field->pivotRelation->getDefaultPivotAttributes(), false)
                );
            }
        })->authorized($request)->all()))->values();
    }

    /**
     * Get the pivot fields for the resource and relation.
     *
     * @param  string  $relatedResource
     * @return \Laravel\Nova\Fields\FieldCollection
     */
    protected function pivotFieldsFor(NovaRequest $request, $relatedResource)
    {
        $fields = $this->availableFields($request)->filter(function ($field) use ($relatedResource) {
            return ($field instanceof BelongsToMany || $field instanceof MorphToMany) &&
                isset($field->resourceName) && $field->resourceName == $relatedResource;
        });

        /** @var \Laravel\Nova\Fields\BelongsToMany|\Laravel\Nova\Fields\MorphToMany|null $field */
        $field = $fields->count() === 1
            ? $fields->first(function ($field) {
                return $field;
            }) : $fields->first(function ($field) use ($request) {
                return $field->manyToManyRelationship === $request->viaRelationship;
            });

        if ($field && isset($field->fieldsCallback)) {
            $model = $this->model() ?? static::newModel();
            $pivotRelation = $model->{$field->manyToManyRelationship}();
            $field->pivotAccessor = $pivotAccessor = $pivotRelation->getPivotAccessor();

            return FieldCollection::make(array_values(
                $this->filter(call_user_func($field->fieldsCallback, $request, $this->resource))
            ))->each(function ($field) use ($pivotAccessor, $pivotRelation) {
                $field->pivot = true;
                $field->pivotAccessor = $pivotAccessor;
                $field->pivotRelation = $pivotRelation;
            });
        }

        return FieldCollection::make();
    }

    /**
     * Get the pivot fields for the resource and relation from related relationship.
     *
     * @param  string  $relatedResource
     * @return \Laravel\Nova\Fields\FieldCollection
     */
    protected function relatedPivotFieldsFor(NovaRequest $request, $relatedResource)
    {
        $resource = Nova::resourceInstanceForKey($relatedResource);

        $fields = $resource->availableFields($request)->filter(function ($field) {
            return ($field instanceof BelongsToMany || $field instanceof MorphToMany) &&
                isset($field->resourceName) && $field->resourceName == $this->uriKey();
        });

        /** @var \Laravel\Nova\Fields\BelongsToMany|\Laravel\Nova\Fields\MorphToMany|null $field */
        $field = $fields->count() === 1
            ? $fields->first(function ($field) {
                return $field;
            }) : $fields->first(function ($field) use ($request) {
                return $field->manyToManyRelationship === $request->viaRelationship;
            });

        if ($field && isset($field->fieldsCallback)) {
            $pivotRelation = $resource->model()->{$field->manyToManyRelationship}();
            $field->pivotAccessor = $pivotAccessor = $pivotRelation->getPivotAccessor();

            return FieldCollection::make(array_values(
                $this->filter(call_user_func($field->fieldsCallback, $request, $this->resource))
            ))->each(function ($field) use ($pivotAccessor, $pivotRelation) {
                $field->pivot = true;
                $field->pivotAccessor = $pivotAccessor;
                $field->pivotRelation = $pivotRelation;
            });
        }

        return FieldCollection::make();
    }

    /**
     * Get the index where the pivot fields should be spliced into the field array.
     *
     * @param  array<int, \Laravel\Nova\Fields\Field>  $fields
     * @return int|null
     */
    protected function indexToInsertPivotFields(NovaRequest $request, array $fields)
    {
        foreach ($fields as $index => $field) {
            if (
                isset($field->resourceName) &&
                $field->resourceName == $request->viaResource
            ) {
                return $index;
            }
        }
    }

    /**
     * Get the displayable pivot model name from a field.
     *
     * @param  string  $field
     * @return string|null
     */
    public function pivotNameForField(NovaRequest $request, $field)
    {
        $field = $this->availableFields($request)->findFieldByAttribute($field);

        if (! ($field instanceof BelongsToMany || $field instanceof MorphToMany)) {
            return self::DEFAULT_PIVOT_NAME;
        }

        if (isset($field->pivotName)) {
            return $field->pivotName;
        }
    }

    /**
     * Resolve available panels from fields.
     *
     * @param  \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>  $fields
     * @param  string  $label
     * @return \Illuminate\Support\Collection<int, \Laravel\Nova\Panel>
     */
    protected function resolvePanelsFromFields(NovaRequest $request, FieldCollection $fields, $label)
    {
        [$defaultFields, $fieldsWithPanels] = $fields->each(function ($field) {
            if ($field instanceof BehavesAsPanel) {
                $field->asPanel();
            }
        })->partition(function ($field) {
            return ! isset($field->panel) || blank($field->panel);
        });

        $panels = $fieldsWithPanels->groupBy(function ($field) {
            return (string) $field->panel;
        })->transform(function ($fields, $name) {
            return Panel::mutate($name, $fields);
        })->toBase();

        return $this->panelsWithDefaultLabel(
            $panels,
            $defaultFields->values(),
            $label
        );
    }

    /**
     * Return the panels for this request with the default label.
     *
     * @param  \Illuminate\Support\Collection<int, \Laravel\Nova\Panel>  $panels
     * @param  \Laravel\Nova\Fields\FieldCollection<int, \Laravel\Nova\Fields\Field>  $fields
     * @param  string  $label
     * @return \Illuminate\Support\Collection<int, \Laravel\Nova\Panel>
     */
    protected function panelsWithDefaultLabel(Collection $panels, FieldCollection $fields, $label)
    {
        return $panels->values()
            ->when($panels->where('name', $label)->isEmpty(), function ($panels) use ($label, $fields) {
                return $fields->isNotEmpty()
                    ? $panels->prepend(Panel::make($label, $fields)->withMeta(['fields' => $fields]))
                    : $panels;
            })->tap(function ($panels) {
                tap($panels->first(), function ($panel) {
                    if (! is_null($panel)) {
                        $panel->withToolbar();
                    }
                });
            });
    }

    /**
     * Return the callback used for resolving fields.
     *
     * @return \Closure(\Laravel\Nova\Fields\FieldCollection):\Laravel\Nova\Fields\FieldCollection
     */
    protected function fieldResolverCallback(NovaRequest $request)
    {
        return function ($fields) use ($request) {
            $fields = $fields->values()->all();
            $pivotFields = $this->pivotFieldsFor($request, $request->viaResource)->all();

            if (! is_null($index = $this->indexToInsertPivotFields($request, $fields))) {
                array_splice($fields, $index + 1, 0, $pivotFields);
            } else {
                $fields = array_merge($fields, $pivotFields);
            }

            return FieldCollection::make($fields);
        };
    }

    /**
     * Return the callback used for resolving fields with pivot from related relationship.
     *
     * @return \Closure(\Laravel\Nova\Fields\FieldCollection):\Laravel\Nova\Fields\FieldCollection
     */
    protected function relatedFieldResolverCallback(NovaRequest $request)
    {
        return function ($fields) use ($request) {
            $fields = $fields->values()->all();
            $pivotFields = $this->relatedPivotFieldsFor($request, $request->viaResource)->all();

            if (! is_null($index = $this->indexToInsertPivotFields($request, $fields))) {
                array_splice($fields, $index + 1, 0, $pivotFields);
            } else {
                $fields = array_merge($fields, $pivotFields);
            }

            return FieldCollection::make($fields);
        };
    }
}