add nova
This commit is contained in:
306
nova/src/Http/Requests/ActionRequest.php
Normal file
306
nova/src/Http/Requests/ActionRequest.php
Normal file
@@ -0,0 +1,306 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Arr;
|
||||
use Laravel\Nova\Actions\ActionModelCollection;
|
||||
use Laravel\Nova\Fields\ActionFields;
|
||||
use Laravel\Nova\Fields\FieldCollection;
|
||||
use Laravel\Nova\Support\Fluent;
|
||||
|
||||
/**
|
||||
* @property-read string|null $resources
|
||||
* @property-read string|null $pivotAction
|
||||
*/
|
||||
class ActionRequest extends NovaRequest
|
||||
{
|
||||
use QueriesResources;
|
||||
|
||||
/**
|
||||
* Get the action instance specified by the request.
|
||||
*
|
||||
* @return \Laravel\Nova\Actions\Action|\Laravel\Nova\Actions\DestructiveAction
|
||||
*/
|
||||
public function action()
|
||||
{
|
||||
return once(function () {
|
||||
$hasResources = ! empty($this->resources);
|
||||
|
||||
return $this->availableActions()
|
||||
->filter(function ($action) use ($hasResources) {
|
||||
return $hasResources ? true : $action->isStandalone();
|
||||
})->first(function ($action) {
|
||||
return $action->uriKey() == $this->query('action');
|
||||
}) ?: abort($this->actionExists() ? 403 : 404);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the all actions for the request.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function resolveActions()
|
||||
{
|
||||
return $this->isPivotAction()
|
||||
? $this->newResource()->resolvePivotActions($this)
|
||||
: $this->newResource()->resolveActions($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the possible actions for the request.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function availableActions()
|
||||
{
|
||||
return $this->resolveActions()->filter->authorizedToSee($this)->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the specified action exists at all.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function actionExists()
|
||||
{
|
||||
return $this->resolveActions()->contains(function ($action) {
|
||||
return $action->uriKey() == $this->query('action');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the action being executed is a pivot action.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isPivotAction()
|
||||
{
|
||||
return $this->pivotAction === 'true';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the selected models for the action in chunks.
|
||||
*
|
||||
* @param int $count
|
||||
* @param \Closure(\Laravel\Nova\Actions\ActionModelCollection):mixed $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function chunks($count, Closure $callback)
|
||||
{
|
||||
$output = [];
|
||||
|
||||
$this->toSelectedResourceQuery()
|
||||
->cursor()
|
||||
->chunk($count)
|
||||
->each(function ($chunk) use ($callback, &$output) {
|
||||
$output[] = $callback($this->mapChunk($chunk));
|
||||
});
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query for the models that were selected by the user.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function toSelectedResourceQuery()
|
||||
{
|
||||
if ($this->allResourcesSelected()) {
|
||||
return $this->toQuery();
|
||||
}
|
||||
|
||||
$query = $this->viaRelationship()
|
||||
? $this->modelsViaRelationship()
|
||||
: $this->toQueryWithoutScopes()->whereKey(Arr::wrap($this->resources));
|
||||
|
||||
return $query->tap(function ($query) {
|
||||
$query->latest($this->model()->getQualifiedKeyName());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the request into a query without scope.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function toQueryWithoutScopes()
|
||||
{
|
||||
return tap($this->newQueryWithoutScopes(), function ($query) {
|
||||
$resource = $this->resource();
|
||||
$query->with($resource::$with);
|
||||
|
||||
if (! $this->allResourcesSelected() && $this->selectedResourceIds()->count() === 1) {
|
||||
$resource::detailQuery($this, $query);
|
||||
} else {
|
||||
$resource::indexQuery($this, $query);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query for the related models that were selected by the user.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function modelsViaRelationship()
|
||||
{
|
||||
$relation = tap($this->findParentResource(), function ($resource) {
|
||||
abort_unless($resource->hasRelatableField($this, $this->viaRelationship), 404);
|
||||
})->model()->{$this->viaRelationship}()->withoutGlobalScopes();
|
||||
|
||||
if (isset($this->pivots) && ! empty($this->pivots)) {
|
||||
/** @var class-string<\Illuminate\Database\Eloquent\Relations\Pivot> $pivotClass */
|
||||
$pivotClass = $relation->getPivotClass();
|
||||
|
||||
$relation->wherePivotIn((new $pivotClass())->getKeyName(), Arr::wrap($this->pivots));
|
||||
}
|
||||
|
||||
return $relation->whereIn($this->model()->getQualifiedKeyName(), Arr::wrap($this->resources));
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the chunk of models into an appropriate state.
|
||||
*
|
||||
* @param \Illuminate\Support\LazyCollection|\Illuminate\Database\Eloquent\Collection $chunk
|
||||
* @return \Laravel\Nova\Actions\ActionModelCollection
|
||||
*/
|
||||
protected function mapChunk($chunk)
|
||||
{
|
||||
return ActionModelCollection::make(
|
||||
$this->isPivotAction()
|
||||
? $chunk->map->{$this->pivotRelation()->getPivotAccessor()}
|
||||
: $chunk
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the given fields.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
*/
|
||||
public function validateFields()
|
||||
{
|
||||
$this->action()->validateFields($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the fields for database storage using the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function resolveFieldsForStorage()
|
||||
{
|
||||
return collect($this->resolveFields()->getAttributes())->map(function ($attribute) {
|
||||
return $attribute instanceof UploadedFile ? $attribute->hashName() : $attribute;
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the fields using the request.
|
||||
*
|
||||
* @return \Laravel\Nova\Fields\ActionFields
|
||||
*/
|
||||
public function resolveFields()
|
||||
{
|
||||
return once(function () {
|
||||
$fields = new Fluent;
|
||||
|
||||
$results = FieldCollection::make($this->action()->fields($this))
|
||||
->authorized($this)
|
||||
->applyDependsOn($this)
|
||||
->withoutReadonly($this)
|
||||
->withoutUnfillable()
|
||||
->mapWithKeys(function ($field) use ($fields) {
|
||||
return [$field->attribute => $field->fillForAction($this, $fields)];
|
||||
});
|
||||
|
||||
return new ActionFields(collect($fields->getAttributes()), $results->filter(function ($field) {
|
||||
return is_callable($field);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key of model that lists the action on its dashboard.
|
||||
*
|
||||
* When running pivot actions, this is the key of the owning model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return int
|
||||
*/
|
||||
public function actionableKey($model)
|
||||
{
|
||||
return $this->isPivotAction()
|
||||
? $model->{$this->pivotRelation()->getForeignPivotKeyName()}
|
||||
: $model->getKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model instance that lists the action on its dashboard.
|
||||
*
|
||||
* When running pivot actions, this is the owning model.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function actionableModel()
|
||||
{
|
||||
return $this->isPivotAction()
|
||||
? $this->newViaResource()->model()
|
||||
: $this->model();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key of model that is the target of the action.
|
||||
*
|
||||
* When running pivot actions, this is the key of the target model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return int
|
||||
*/
|
||||
public function targetKey($model)
|
||||
{
|
||||
return $this->isPivotAction()
|
||||
? $model->{$this->pivotRelation()->getRelatedPivotKeyName()}
|
||||
: $model->getKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of the target model of the action.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function targetModel()
|
||||
{
|
||||
return $this->isPivotAction() ? $this->pivotRelation()->newPivot() : $this->model();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the many-to-many relationship for a pivot action.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany|\Illuminate\Database\Eloquent\Relations\BelongsToMany|null
|
||||
*/
|
||||
public function pivotRelation()
|
||||
{
|
||||
if ($this->isPivotAction()) {
|
||||
return tap($this->newViaResource(), function ($resource) {
|
||||
abort_unless($resource->hasRelatableField($this, $this->viaRelationship), 404);
|
||||
})->model()->{$this->viaRelationship}();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this request is an action request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isActionRequest()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
22
nova/src/Http/Requests/CardRequest.php
Normal file
22
nova/src/Http/Requests/CardRequest.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
class CardRequest extends NovaRequest
|
||||
{
|
||||
/**
|
||||
* Get all of the possible metrics for the request.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function availableCards()
|
||||
{
|
||||
$resource = $this->newResource();
|
||||
|
||||
if ($this->resourceId) {
|
||||
return $this->newResource()->availableCardsForDetail($this);
|
||||
}
|
||||
|
||||
return $this->newResource()->availableCards($this);
|
||||
}
|
||||
}
|
||||
31
nova/src/Http/Requests/CountsResources.php
Normal file
31
nova/src/Http/Requests/CountsResources.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
trait CountsResources
|
||||
{
|
||||
/**
|
||||
* Build a new count query for the given query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function buildCountQuery($query)
|
||||
{
|
||||
$baseQuery = $query->toBase();
|
||||
|
||||
if (empty($baseQuery->groups)) {
|
||||
return $baseQuery;
|
||||
}
|
||||
|
||||
$subQuery = $baseQuery->cloneWithout(
|
||||
$baseQuery->unions ? ['orders', 'limit', 'offset'] : ['columns', 'orders', 'limit', 'offset']
|
||||
)->cloneWithoutBindings(
|
||||
$baseQuery->unions ? ['order'] : ['select', 'order']
|
||||
)->selectRaw('1 as exists_temp');
|
||||
|
||||
return $query->getConnection()
|
||||
->query()
|
||||
->fromSub($subQuery, 'count_temp');
|
||||
}
|
||||
}
|
||||
16
nova/src/Http/Requests/CreateResourceRequest.php
Normal file
16
nova/src/Http/Requests/CreateResourceRequest.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
class CreateResourceRequest extends NovaRequest
|
||||
{
|
||||
/**
|
||||
* Determine if this request is a create or attach request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isCreateOrAttachRequest()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
34
nova/src/Http/Requests/DashboardMetricRequest.php
Normal file
34
nova/src/Http/Requests/DashboardMetricRequest.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Laravel\Nova\Metrics\Metric;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
/**
|
||||
* @property-read string $metric
|
||||
*/
|
||||
class DashboardMetricRequest extends NovaRequest
|
||||
{
|
||||
/**
|
||||
* Get the metric instance for the given request.
|
||||
*
|
||||
* @return \Laravel\Nova\Metrics\Metric
|
||||
*/
|
||||
public function metric()
|
||||
{
|
||||
return $this->availableMetrics()->first(function ($metric) {
|
||||
return $this->metric === $metric->uriKey();
|
||||
}) ?: abort(404);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the possible metrics for the request.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function availableMetrics()
|
||||
{
|
||||
return Nova::allAvailableDashboardCards($this)->whereInstanceOf(Metric::class);
|
||||
}
|
||||
}
|
||||
19
nova/src/Http/Requests/DashboardRequest.php
Normal file
19
nova/src/Http/Requests/DashboardRequest.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class DashboardRequest extends NovaRequest
|
||||
{
|
||||
/**
|
||||
* Get all of the possible cards for the request.
|
||||
*
|
||||
* @param string $dashboard
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function availableCards($dashboard)
|
||||
{
|
||||
return Nova::availableDashboardCardsForDashboard($dashboard, $this);
|
||||
}
|
||||
}
|
||||
31
nova/src/Http/Requests/DecodesFilters.php
Normal file
31
nova/src/Http/Requests/DecodesFilters.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Laravel\Nova\Filters\FilterDecoder;
|
||||
|
||||
/**
|
||||
* @property-read string $filters
|
||||
*/
|
||||
trait DecodesFilters
|
||||
{
|
||||
/**
|
||||
* Get the filters for the request.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function filters()
|
||||
{
|
||||
return (new FilterDecoder($this->filters, $this->availableFilters()))->filters();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the possibly available filters for the request.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function availableFilters()
|
||||
{
|
||||
return $this->newResource()->availableFilters($this);
|
||||
}
|
||||
}
|
||||
37
nova/src/Http/Requests/DeleteLensResourceRequest.php
Normal file
37
nova/src/Http/Requests/DeleteLensResourceRequest.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class DeleteLensResourceRequest extends LensResourceDeletionRequest
|
||||
{
|
||||
/**
|
||||
* Get the selected models for the action in chunks.
|
||||
*
|
||||
* @param int $count
|
||||
* @param \Closure(\Illuminate\Support\Collection):void $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function chunks($count, Closure $callback)
|
||||
{
|
||||
return $this->chunkWithAuthorization($count, $callback, function ($models) {
|
||||
return $this->deletableModels($models);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the models that may be deleted.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $models
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function deletableModels(Collection $models)
|
||||
{
|
||||
return $models->mapInto($this->resource())
|
||||
->filter
|
||||
->authorizedToDelete($this)
|
||||
->map->model();
|
||||
}
|
||||
}
|
||||
50
nova/src/Http/Requests/DeleteResourceRequest.php
Normal file
50
nova/src/Http/Requests/DeleteResourceRequest.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* @property-read string|array<int, mixed> $resources
|
||||
*/
|
||||
class DeleteResourceRequest extends DeletionRequest
|
||||
{
|
||||
/**
|
||||
* Get the selected models for the action in chunks.
|
||||
*
|
||||
* @param int $count
|
||||
* @param \Closure(\Illuminate\Support\Collection):void $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function chunks($count, Closure $callback)
|
||||
{
|
||||
return $this->chunkWithAuthorization($count, $callback, function ($models) {
|
||||
return $this->deletableModels($models);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the models that may be deleted.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $models
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function deletableModels(Collection $models)
|
||||
{
|
||||
return $models->mapInto($this->resource())
|
||||
->filter
|
||||
->authorizedToDelete($this)
|
||||
->map->model();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the request is for a single resource only.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isForSingleResource()
|
||||
{
|
||||
return $this->resources !== 'all' && count($this->resources) == 1;
|
||||
}
|
||||
}
|
||||
52
nova/src/Http/Requests/DeletionRequest.php
Normal file
52
nova/src/Http/Requests/DeletionRequest.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Closure;
|
||||
|
||||
/**
|
||||
* @property-read string|array<int, mixed> $resources
|
||||
*/
|
||||
class DeletionRequest extends NovaRequest
|
||||
{
|
||||
use QueriesResources;
|
||||
|
||||
/**
|
||||
* Get the selected models for the action in chunks.
|
||||
*
|
||||
* @param int $count
|
||||
* @param \Closure(\Illuminate\Support\Collection):void $callback
|
||||
* @param \Closure(\Illuminate\Support\Collection):\Illuminate\Support\Collection $authCallback
|
||||
* @return mixed
|
||||
*/
|
||||
protected function chunkWithAuthorization($count, Closure $callback, Closure $authCallback)
|
||||
{
|
||||
$model = $this->model();
|
||||
|
||||
$this->toSelectedResourceQuery()->when(! $this->allResourcesSelected(), function ($query) {
|
||||
$query->whereKey($this->resources);
|
||||
})->tap(function ($query) {
|
||||
$query->getQuery()->orders = [];
|
||||
})->chunkById($count, function ($models) use ($callback, $authCallback) {
|
||||
$models = $authCallback($models);
|
||||
|
||||
if ($models->isNotEmpty()) {
|
||||
$callback($models);
|
||||
}
|
||||
}, $model->getQualifiedKeyName(), $model->getKeyName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query for the models that were selected by the user.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function toSelectedResourceQuery()
|
||||
{
|
||||
if ($this->allResourcesSelected()) {
|
||||
return $this->toQuery();
|
||||
}
|
||||
|
||||
return $this->newQueryWithoutScopes();
|
||||
}
|
||||
}
|
||||
46
nova/src/Http/Requests/DetachResourceRequest.php
Normal file
46
nova/src/Http/Requests/DetachResourceRequest.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class DetachResourceRequest extends DeletionRequest
|
||||
{
|
||||
/**
|
||||
* Get the selected models for the action in chunks.
|
||||
*
|
||||
* @param int $count
|
||||
* @param \Closure(\Illuminate\Support\Collection):void $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function chunks($count, Closure $callback)
|
||||
{
|
||||
$parentResource = $this->findParentResourceOrFail();
|
||||
$model = $this->model();
|
||||
|
||||
$this->toSelectedResourceQuery()->when(! $this->allResourcesSelected(), function ($query) {
|
||||
$query->whereKey($this->resources);
|
||||
})->chunkById($count, function ($models) use ($callback, $parentResource) {
|
||||
$models = $this->detachableModels($models, $parentResource);
|
||||
|
||||
if ($models->isNotEmpty()) {
|
||||
$callback($models);
|
||||
}
|
||||
}, $model->getQualifiedKeyName(), $model->getKeyName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the models that may be detached.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $models
|
||||
* @param \Laravel\Nova\Resource $parentResource
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function detachableModels(Collection $models, $parentResource)
|
||||
{
|
||||
return $models->filter(function ($model) use ($parentResource) {
|
||||
return $parentResource->authorizedToDetach($this, $model, $this->viaRelationship);
|
||||
});
|
||||
}
|
||||
}
|
||||
37
nova/src/Http/Requests/ForceDeleteLensResourceRequest.php
Normal file
37
nova/src/Http/Requests/ForceDeleteLensResourceRequest.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class ForceDeleteLensResourceRequest extends LensResourceDeletionRequest
|
||||
{
|
||||
/**
|
||||
* Get the selected models for the action in chunks.
|
||||
*
|
||||
* @param int $count
|
||||
* @param \Closure(\Illuminate\Support\Collection):void $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function chunks($count, Closure $callback)
|
||||
{
|
||||
return $this->chunkWithAuthorization($count, $callback, function ($models) {
|
||||
return $this->deletableModels($models);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the models that may be deleted.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $models
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function deletableModels(Collection $models)
|
||||
{
|
||||
return $models->mapInto($this->resource())
|
||||
->filter
|
||||
->authorizedToForceDelete($this)
|
||||
->map->model();
|
||||
}
|
||||
}
|
||||
47
nova/src/Http/Requests/ForceDeleteResourceRequest.php
Normal file
47
nova/src/Http/Requests/ForceDeleteResourceRequest.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class ForceDeleteResourceRequest extends DeletionRequest
|
||||
{
|
||||
/**
|
||||
* Get the selected models for the action in chunks.
|
||||
*
|
||||
* @param int $count
|
||||
* @param \Closure(\Illuminate\Support\Collection):void $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function chunks($count, Closure $callback)
|
||||
{
|
||||
return $this->chunkWithAuthorization($count, $callback, function ($models) {
|
||||
return $this->deletableModels($models);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the models that may be deleted.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $models
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function deletableModels(Collection $models)
|
||||
{
|
||||
return $models->mapInto($this->resource())
|
||||
->filter
|
||||
->authorizedToForceDelete($this)
|
||||
->map->model();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the request is for a single resource only.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isForSingleResource()
|
||||
{
|
||||
return $this->resources !== 'all' && count($this->resources) == 1;
|
||||
}
|
||||
}
|
||||
8
nova/src/Http/Requests/GlobalSearchRequest.php
Normal file
8
nova/src/Http/Requests/GlobalSearchRequest.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
class GlobalSearchRequest extends NovaRequest
|
||||
{
|
||||
//
|
||||
}
|
||||
63
nova/src/Http/Requests/InteractsWithLenses.php
Normal file
63
nova/src/Http/Requests/InteractsWithLenses.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Laravel\Nova\Query\Search;
|
||||
|
||||
/**
|
||||
* @property-read string|null $lens
|
||||
*/
|
||||
trait InteractsWithLenses
|
||||
{
|
||||
/**
|
||||
* Get the lens instance for the given request.
|
||||
*
|
||||
* @return \Laravel\Nova\Lenses\Lens
|
||||
*/
|
||||
public function lens()
|
||||
{
|
||||
return $this->availableLenses()->first(function ($lens) {
|
||||
return $this->lens === $lens->uriKey();
|
||||
}) ?: abort($this->lensExists() ? 403 : 404);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the possible lenses for the request.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function availableLenses()
|
||||
{
|
||||
return transform($this->newResource(), function ($resource) {
|
||||
abort_unless($resource::authorizedToViewAny($this), 403);
|
||||
|
||||
return $resource->availableLenses($this);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the request into a search query.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function newSearchQuery()
|
||||
{
|
||||
$lens = $this->lens();
|
||||
|
||||
return $lens::searchable() && ! empty($this->search)
|
||||
? (new Search($this->newQuery(), $this->search))->handle($this->resource(), $lens->searchableColumns())
|
||||
: $this->newQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the specified action exists at all.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function lensExists()
|
||||
{
|
||||
return $this->newResource()->resolveLenses($this)->contains(function ($lens) {
|
||||
return $this->lens === $lens->uriKey();
|
||||
});
|
||||
}
|
||||
}
|
||||
230
nova/src/Http/Requests/InteractsWithRelatedResources.php
Normal file
230
nova/src/Http/Requests/InteractsWithRelatedResources.php
Normal file
@@ -0,0 +1,230 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Laravel\Nova\Nova;
|
||||
use Laravel\Nova\Resource;
|
||||
|
||||
trait InteractsWithRelatedResources
|
||||
{
|
||||
/**
|
||||
* Find the parent resource model instance for the request.
|
||||
*
|
||||
* @param string|int|null $resourceId
|
||||
* @return \Laravel\Nova\Resource
|
||||
*/
|
||||
public function findParentResource($resourceId = null)
|
||||
{
|
||||
$resource = $this->viaResource();
|
||||
|
||||
return new $resource($this->findParentModel($resourceId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the parent resource model instance for the request.
|
||||
*
|
||||
* @param string|int|null $resourceId
|
||||
* @return \Laravel\Nova\Resource<\Illuminate\Database\Eloquent\Model>
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function findParentResourceOrFail($resourceId = null)
|
||||
{
|
||||
$resource = $this->viaResource();
|
||||
|
||||
return new $resource($this->findParentModelOrFail($resourceId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the parent resource model instance for the request.
|
||||
*
|
||||
* @param string|int|null $resourceId
|
||||
* @return \Illuminate\Database\Eloquent\Model|null
|
||||
*/
|
||||
public function findParentModel($resourceId = null)
|
||||
{
|
||||
if (! $this->viaRelationship()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return rescue(function () use ($resourceId) {
|
||||
return $this->findParentModelOrFail($resourceId);
|
||||
}, Nova::modelInstanceForKey($this->viaResource), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the parent resource model instance for the request or abort.
|
||||
*
|
||||
* @param string|int|null $resourceId
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function findParentModelOrFail($resourceId = null)
|
||||
{
|
||||
$query = Nova::modelInstanceForKey($this->viaResource)->newQueryWithoutScopes();
|
||||
|
||||
if (! is_null($resourceId)) {
|
||||
return $query->whereKey($resourceId)->firstOrFail();
|
||||
}
|
||||
|
||||
return once(function () use ($query) {
|
||||
return $query->findOrFail($this->viaResourceId);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the related resource instance for the request.
|
||||
*
|
||||
* @param string|int|null $resourceId
|
||||
* @return \Laravel\Nova\Resource
|
||||
*/
|
||||
public function findRelatedResource($resourceId = null)
|
||||
{
|
||||
$resource = $this->relatedResource();
|
||||
|
||||
return new $resource($this->findRelatedModel($resourceId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the related resource instance for the request or abort.
|
||||
*
|
||||
* @param string|int|null $resourceId
|
||||
* @return \Laravel\Nova\Resource<\Illuminate\Database\Eloquent\Model>
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function findRelatedResourceOrFail($resourceId = null)
|
||||
{
|
||||
$resource = $this->relatedResource();
|
||||
|
||||
return new $resource($this->findRelatedModelOrFail($resourceId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the related resource model instance for the request.
|
||||
*
|
||||
* @param string|int|null $resourceId
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function findRelatedModel($resourceId = null)
|
||||
{
|
||||
return rescue(function () use ($resourceId) {
|
||||
return $this->findRelatedModelOrFail($resourceId);
|
||||
}, Nova::modelInstanceForKey($this->relatedResource), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the parent resource model instance for the request or abort.
|
||||
*
|
||||
* @param string|int|null $resourceId
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function findRelatedModelOrFail($resourceId = null)
|
||||
{
|
||||
$query = Nova::modelInstanceForKey($this->relatedResource)->newQueryWithoutScopes();
|
||||
|
||||
if (! is_null($resourceId)) {
|
||||
return $query->whereKey($resourceId)->firstOrFail();
|
||||
}
|
||||
|
||||
return once(function () use ($query) {
|
||||
return $query->findOrFail($this->input($this->relatedResource));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the displayable pivot model name for a "via relationship" request.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function pivotName()
|
||||
{
|
||||
if (! $this->viaRelationship()) {
|
||||
return Resource::DEFAULT_PIVOT_NAME;
|
||||
}
|
||||
|
||||
$resource = Nova::resourceInstanceForKey($this->viaResource);
|
||||
|
||||
if ($name = $resource->pivotNameForField($this, $this->viaRelationship)) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
$parentResource = $this->findParentResource();
|
||||
|
||||
$parent = $parentResource->model();
|
||||
|
||||
return ($parent && $parentResource->hasRelatableField($this, $this->viaRelationship))
|
||||
? class_basename($parent->{$this->viaRelationship}()->getPivotClass())
|
||||
: Resource::DEFAULT_PIVOT_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name of the "related" resource being requested.
|
||||
*
|
||||
* @return class-string<\Laravel\Nova\Resource>
|
||||
*/
|
||||
public function relatedResource()
|
||||
{
|
||||
return Nova::resourceForKey($this->relatedResource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new instance of the "related" resource being requested.
|
||||
*
|
||||
* @return \Laravel\Nova\Resource<\Illuminate\Database\Eloquent\Model>
|
||||
*/
|
||||
public function newRelatedResource()
|
||||
{
|
||||
$resource = $this->relatedResource();
|
||||
|
||||
return new $resource($resource::newModel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name of the "via" resource being requested.
|
||||
*
|
||||
* @return class-string<\Laravel\Nova\Resource>
|
||||
*/
|
||||
public function viaResource()
|
||||
{
|
||||
return Nova::resourceForKey($this->viaResource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new instance of the "via" resource being requested.
|
||||
*
|
||||
* @return \Laravel\Nova\Resource<\Illuminate\Database\Eloquent\Model>
|
||||
*/
|
||||
public function newViaResource()
|
||||
{
|
||||
$resource = $this->viaResource();
|
||||
|
||||
return new $resource($resource::newModel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the request is via a relationship.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function viaRelationship()
|
||||
{
|
||||
return filled($this->viaResource) && filled($this->viaResourceId) && $this->viaRelationship;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this request is via a many-to-many relationship.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function viaManyToMany()
|
||||
{
|
||||
return in_array(
|
||||
$this->relationshipType,
|
||||
['belongsToMany', 'morphToMany']
|
||||
);
|
||||
}
|
||||
}
|
||||
187
nova/src/Http/Requests/InteractsWithResources.php
Normal file
187
nova/src/Http/Requests/InteractsWithResources.php
Normal file
@@ -0,0 +1,187 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Laravel\Nova\Contracts\QueryBuilder;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
trait InteractsWithResources
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the requested resource is soft deleting.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function resourceSoftDeletes()
|
||||
{
|
||||
$resource = $this->resource();
|
||||
|
||||
return $resource::softDeletes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name of the resource being requested.
|
||||
*
|
||||
* @return class-string<\Laravel\Nova\Resource>
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
public function resource()
|
||||
{
|
||||
return tap(once(function () {
|
||||
return Nova::resourceForKey($this->route('resource'));
|
||||
}), function ($resource) {
|
||||
abort_if(is_null($resource), 404);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new instance of the resource being requested.
|
||||
*
|
||||
* @return \Laravel\Nova\Resource<\Illuminate\Database\Eloquent\Model>
|
||||
*/
|
||||
public function newResource()
|
||||
{
|
||||
$resource = $this->resource();
|
||||
|
||||
return new $resource($this->model());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the resource instance for the request or abort.
|
||||
*
|
||||
* @param string|int|null $resourceId
|
||||
* @return \Laravel\Nova\Resource<\Illuminate\Database\Eloquent\Model>
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function findResourceOrFail($resourceId = null)
|
||||
{
|
||||
return $this->newResourceWith($this->findModelOrFail($resourceId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the resource instance for the request.
|
||||
*
|
||||
* @param string|int|null $resourceId
|
||||
* @return \Laravel\Nova\Resource
|
||||
*/
|
||||
public function findResource($resourceId = null)
|
||||
{
|
||||
return $this->newResourceWith($this->findModel($resourceId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the model instance for the request or throw an exception.
|
||||
*
|
||||
* @param string|int|null $resourceId
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function findModelOrFail($resourceId = null)
|
||||
{
|
||||
if (! is_null($resourceId)) {
|
||||
return $this->findModelQuery($resourceId)->firstOrFail();
|
||||
}
|
||||
|
||||
return once(function () {
|
||||
return $this->findModelQuery()->firstOrFail();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the model instance for the request.
|
||||
*
|
||||
* @param string|int|null $resourceId
|
||||
* @return \Illuminate\Database\Eloquent\Model|null
|
||||
*/
|
||||
public function findModel($resourceId = null)
|
||||
{
|
||||
return rescue(function () use ($resourceId) {
|
||||
return $this->findModelOrFail($resourceId);
|
||||
}, $this->model(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query to find the model instance for the request.
|
||||
*
|
||||
* @param mixed|null $resourceId
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function findModelQuery($resourceId = null)
|
||||
{
|
||||
return app()->make(QueryBuilder::class, [$this->resource()])
|
||||
->whereKey(
|
||||
$this->newQueryWithoutScopes(),
|
||||
$resourceId ?? $this->resourceId
|
||||
)->toBase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new instance of the resource being requested.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return \Laravel\Nova\Resource<\Illuminate\Database\Eloquent\Model>
|
||||
*/
|
||||
public function newResourceWith($model)
|
||||
{
|
||||
$resource = $this->resource();
|
||||
|
||||
return new $resource($model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new query builder for the underlying model.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function newQuery()
|
||||
{
|
||||
return $this->model()->newQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new, scopeless query builder for the underlying model.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function newQueryWithoutScopes()
|
||||
{
|
||||
return $this->model()->newQueryWithoutScopes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new instance of the underlying model.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function model()
|
||||
{
|
||||
$resource = $this->resource();
|
||||
|
||||
return $resource::newModel();
|
||||
}
|
||||
}
|
||||
67
nova/src/Http/Requests/InteractsWithResourcesSelection.php
Normal file
67
nova/src/Http/Requests/InteractsWithResourcesSelection.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
/**
|
||||
* @property-read int|null $resourceId
|
||||
* @property-read array|string|null $resources
|
||||
*/
|
||||
trait InteractsWithResourcesSelection
|
||||
{
|
||||
/**
|
||||
* Determine if currently all resources is selected.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function allResourcesSelected()
|
||||
{
|
||||
return $this->resources === 'all';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get selected resource IDs.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection<int, string|int>|null
|
||||
*/
|
||||
public function selectedResourceIds()
|
||||
{
|
||||
if ($this->allResourcesSelected()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$resourceIds = array_filter(! empty($this->resources) ? Arr::wrap($this->resources) : [$this->resourceId]);
|
||||
|
||||
if (count($resourceIds) < 1) {
|
||||
return collect(
|
||||
$this->resource instanceof Model ? [$this->resource->getKey()] : []
|
||||
);
|
||||
}
|
||||
|
||||
return collect($resourceIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get selected resources.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection|\Illuminate\Support\Collection|null
|
||||
*/
|
||||
public function selectedResources()
|
||||
{
|
||||
if ($this->allResourcesSelected()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$resourceIds = array_filter(! empty($this->resources) ? Arr::wrap($this->resources) : [$this->resourceId]);
|
||||
|
||||
if (count($resourceIds) < 1) {
|
||||
return $this->resource instanceof Model ? $this->resource->newCollection() : collect();
|
||||
}
|
||||
|
||||
return $this->newQueryWithoutScopes()
|
||||
->whereKey($resourceIds)
|
||||
->get();
|
||||
}
|
||||
}
|
||||
47
nova/src/Http/Requests/LensActionRequest.php
Normal file
47
nova/src/Http/Requests/LensActionRequest.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use LogicException;
|
||||
|
||||
class LensActionRequest extends ActionRequest
|
||||
{
|
||||
use InteractsWithLenses;
|
||||
|
||||
/**
|
||||
* Transform the request into a query.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function toQuery()
|
||||
{
|
||||
return tap($this->lens()->query(LensRequest::createFrom($this), $this->newSearchQuery()), function ($query) {
|
||||
if (! $query instanceof Builder) {
|
||||
throw new LogicException('Lens must return an Eloquent query instance in order to apply actions.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the request into a query without scope.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function toQueryWithoutScopes()
|
||||
{
|
||||
return $this->toQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the all actions for the request.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function resolveActions()
|
||||
{
|
||||
return $this->isPivotAction()
|
||||
? $this->lens()->resolvePivotActions($this)
|
||||
: $this->lens()->resolveActions($this);
|
||||
}
|
||||
}
|
||||
18
nova/src/Http/Requests/LensCardRequest.php
Normal file
18
nova/src/Http/Requests/LensCardRequest.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
class LensCardRequest extends CardRequest
|
||||
{
|
||||
use InteractsWithLenses;
|
||||
|
||||
/**
|
||||
* Get all of the possible metrics for the request.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function availableCards()
|
||||
{
|
||||
return $this->lens()->availableCards($this);
|
||||
}
|
||||
}
|
||||
38
nova/src/Http/Requests/LensCountRequest.php
Normal file
38
nova/src/Http/Requests/LensCountRequest.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Laravel\Nova\Exceptions\LensCountException;
|
||||
|
||||
class LensCountRequest extends NovaRequest
|
||||
{
|
||||
use CountsResources;
|
||||
use InteractsWithLenses;
|
||||
|
||||
/**
|
||||
* Get the count of the lens resources.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function toCount()
|
||||
{
|
||||
return rescue(function () {
|
||||
return $this->toQuery()->toBase()->getCountForPagination();
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the request into a query.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function toQuery()
|
||||
{
|
||||
return tap($this->lens()->query(LensRequest::createFrom($this), $this->newSearchQuery()), function ($query) {
|
||||
if (! $query instanceof Builder) {
|
||||
throw new LensCountException('Lens must return an Eloquent query instance in order to count lens resources.');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
21
nova/src/Http/Requests/LensMetricRequest.php
Normal file
21
nova/src/Http/Requests/LensMetricRequest.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Laravel\Nova\Metrics\Metric;
|
||||
|
||||
class LensMetricRequest extends MetricRequest
|
||||
{
|
||||
use InteractsWithLenses;
|
||||
|
||||
/**
|
||||
* Get all of the possible metrics for the request.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function availableMetrics()
|
||||
{
|
||||
return $this->lens()->availableCards($this)
|
||||
->whereInstanceOf(Metric::class);
|
||||
}
|
||||
}
|
||||
182
nova/src/Http/Requests/LensRequest.php
Normal file
182
nova/src/Http/Requests/LensRequest.php
Normal file
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use Illuminate\Support\Collection;
|
||||
use Laravel\Nova\Contracts\RelatableField;
|
||||
|
||||
/**
|
||||
* @property-read string|null $orderBy
|
||||
* @property-read string|null $orderByDirection
|
||||
*/
|
||||
class LensRequest extends NovaRequest
|
||||
{
|
||||
use DecodesFilters;
|
||||
use InteractsWithLenses;
|
||||
|
||||
/**
|
||||
* Whether to include the table order prefix.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $tableOrderPrefix = true;
|
||||
|
||||
/**
|
||||
* Apply the specified filters to the given query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function withFilters($query)
|
||||
{
|
||||
return $this->filter($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the specified filters to the given query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function filter($query)
|
||||
{
|
||||
$this->filters()->each->__invoke($this, $query);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the specified ordering to the given query.
|
||||
*
|
||||
* @template TValue of \Illuminate\Database\Eloquent\Builder
|
||||
*
|
||||
* @param TValue $query
|
||||
* @param (callable(TValue): (TValue))|null $defaultCallback
|
||||
* @return TValue
|
||||
*/
|
||||
public function withOrdering($query, $defaultCallback = null)
|
||||
{
|
||||
if (! $this->orderBy || ! $this->orderByDirection) {
|
||||
with($query, $defaultCallback);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
$model = $this->model();
|
||||
|
||||
$fieldExists = $this->lens()->availableFields($this)
|
||||
->transform(function ($field) use ($model) {
|
||||
return $field instanceof RelatableField
|
||||
? $this->getRelationForeignKeyName($model->{$field->attribute}())
|
||||
: $field->attribute ?? null;
|
||||
})->filter()
|
||||
->first(function ($attribute) {
|
||||
return $attribute == $this->orderBy;
|
||||
});
|
||||
|
||||
if ($fieldExists) {
|
||||
return $query->orderBy(
|
||||
($this->tableOrderPrefix ? $query->getModel()->getTable().'.' : '').$this->orderBy,
|
||||
$this->orderByDirection === 'asc' ? 'asc' : 'desc'
|
||||
);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable prepending of the table order.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withoutTableOrderPrefix()
|
||||
{
|
||||
$this->tableOrderPrefix = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the possibly available filters for the request.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function availableFilters()
|
||||
{
|
||||
return $this->lens()->availableFilters($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the given models to the appropriate resource for the request.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $models
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function toResources(Collection $models)
|
||||
{
|
||||
$resource = $this->resource();
|
||||
|
||||
return $models->map(function ($model) use ($resource) {
|
||||
$lensResource = $this->lens()->setResource($model);
|
||||
|
||||
return transform((new $resource($model))->serializeForIndex(
|
||||
$this, $lensResource->resolveFields($this)
|
||||
), function ($payload) use ($model, $lensResource) {
|
||||
$hasId = ! is_null($payload['id']->value);
|
||||
|
||||
$payload['actions'] = collect(
|
||||
$hasId === true ? array_values($lensResource->actions($this)) : []
|
||||
)->filter(function ($action) {
|
||||
return $action->shownOnIndex() || $action->shownOnTableRow();
|
||||
})
|
||||
->filter->authorizedToSee($this)
|
||||
->filter->authorizedToRun($this, $model)
|
||||
->values();
|
||||
|
||||
return $payload;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get foreign key name for relation.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Relations\Relation $relation
|
||||
* @return string
|
||||
*/
|
||||
protected function getRelationForeignKeyName(Relation $relation)
|
||||
{
|
||||
return method_exists($relation, 'getForeignKeyName')
|
||||
? $relation->getForeignKeyName()
|
||||
: $relation->getForeignKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get per page.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function perPage()
|
||||
{
|
||||
$resource = $this->resource();
|
||||
|
||||
$perPageOptions = $resource::perPageOptions();
|
||||
|
||||
if (empty($perPageOptions)) {
|
||||
$perPageOptions = [$resource::newModel()->getPerPage()];
|
||||
}
|
||||
|
||||
return (int) in_array($this->perPage, $perPageOptions) ? $this->perPage : $perPageOptions[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this request is an action request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isActionRequest()
|
||||
{
|
||||
return $this->segment(5) == 'actions';
|
||||
}
|
||||
}
|
||||
65
nova/src/Http/Requests/LensResourceDeletionRequest.php
Normal file
65
nova/src/Http/Requests/LensResourceDeletionRequest.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use LogicException;
|
||||
|
||||
/**
|
||||
* @property-read string|array<int, mixed> $resources
|
||||
*/
|
||||
class LensResourceDeletionRequest extends NovaRequest
|
||||
{
|
||||
use InteractsWithLenses;
|
||||
use QueriesResources;
|
||||
|
||||
/**
|
||||
* Get the selected models for the action in chunks.
|
||||
*
|
||||
* @param int $count
|
||||
* @param \Closure(\Illuminate\Support\Collection):void $callback
|
||||
* @param \Closure(\Illuminate\Support\Collection):\Illuminate\Support\Collection $authCallback
|
||||
* @return mixed
|
||||
*/
|
||||
protected function chunkWithAuthorization($count, Closure $callback, Closure $authCallback)
|
||||
{
|
||||
$this->toSelectedResourceQuery()->when(! $this->allResourcesSelected(), function ($query) {
|
||||
$query->whereKey($this->resources);
|
||||
})->tap(function ($query) {
|
||||
$query->getQuery()->orders = [];
|
||||
})->chunkById($count, function ($models) use ($callback, $authCallback) {
|
||||
$models = $authCallback($models);
|
||||
|
||||
if ($models->isNotEmpty()) {
|
||||
$callback($models);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query for the models that were selected by the user.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function toSelectedResourceQuery()
|
||||
{
|
||||
return $this->allResourcesSelected()
|
||||
? $this->toQuery()
|
||||
: $this->newQueryWithoutScopes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the request into a query.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function toQuery()
|
||||
{
|
||||
return tap($this->lens()->query(LensRequest::createFrom($this), $this->newSearchQuery()), function ($query) {
|
||||
if (! $query instanceof Builder) {
|
||||
throw new LogicException('Lens must return an Eloquent query instance in order to perform this action.');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
87
nova/src/Http/Requests/MetricRequest.php
Normal file
87
nova/src/Http/Requests/MetricRequest.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Laravel\Nova\Metrics\Metric;
|
||||
|
||||
/**
|
||||
* @property-read string $metric
|
||||
*/
|
||||
class MetricRequest extends NovaRequest
|
||||
{
|
||||
/**
|
||||
* Get the metric instance for the given request.
|
||||
*
|
||||
* @return \Laravel\Nova\Metrics\Metric
|
||||
*/
|
||||
public function metric()
|
||||
{
|
||||
return $this->availableMetrics()->first(function ($metric) {
|
||||
return $this->metric === $metric->uriKey();
|
||||
}) ?: abort(404);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the metric instance for the given detail request.
|
||||
*
|
||||
* @return \Laravel\Nova\Metrics\Metric
|
||||
*/
|
||||
public function detailMetric()
|
||||
{
|
||||
return $this->availableMetricsForDetail()->first(function ($metric) {
|
||||
return $this->metric === $metric->uriKey();
|
||||
}) ?: abort(404);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the possible metrics for the request.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection<int, \Laravel\Nova\Metrics\Metric>
|
||||
*/
|
||||
public function availableMetrics()
|
||||
{
|
||||
$resource = $this->newResource();
|
||||
|
||||
abort_unless($resource::authorizedToViewAny($this), 403);
|
||||
|
||||
return $resource->availableCards($this)
|
||||
->whereInstanceOf(Metric::class)
|
||||
->map(function ($metric) use ($resource) {
|
||||
/** @var \Laravel\Nova\Metrics\Metric $metric */
|
||||
if ($metric->refreshWhenFiltersChange === true) {
|
||||
$request = isset($this->resourceId)
|
||||
? ResourceDetailRequest::createFromBase($this)
|
||||
: ResourceIndexRequest::createFromBase($this);
|
||||
|
||||
return $metric->setAvailableFilters($resource->availableFilters($request));
|
||||
}
|
||||
|
||||
return $metric;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the possible metrics for a detail request.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection<int, \Laravel\Nova\Metrics\Metric>
|
||||
*/
|
||||
public function availableMetricsForDetail()
|
||||
{
|
||||
$resource = $this->newResource();
|
||||
|
||||
abort_unless($resource::authorizedToViewAny($this), 403);
|
||||
|
||||
return $resource->availableCardsForDetail($this)
|
||||
->whereInstanceOf(Metric::class)
|
||||
->map(function ($metric) use ($resource) {
|
||||
/** @var \Laravel\Nova\Metrics\Metric $metric */
|
||||
if ($metric->refreshWhenFiltersChange === true) {
|
||||
return $metric->setAvailableFilters(
|
||||
$resource->availableFilters(ResourceDetailRequest::createFromBase($this))
|
||||
);
|
||||
}
|
||||
|
||||
return $metric;
|
||||
});
|
||||
}
|
||||
}
|
||||
31
nova/src/Http/Requests/NotificationRequest.php
Normal file
31
nova/src/Http/Requests/NotificationRequest.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use Laravel\Nova\Http\Resources\NotificationResource;
|
||||
use Laravel\Nova\Notifications\Notification;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class NotificationRequest extends NovaRequest
|
||||
{
|
||||
/**
|
||||
* @return AnonymousResourceCollection
|
||||
*/
|
||||
public function notifications()
|
||||
{
|
||||
return NotificationResource::collection(
|
||||
Notification::whereNotifiableId(Nova::user($this)->getKey())
|
||||
->latest()
|
||||
->take(100)
|
||||
->get()
|
||||
);
|
||||
}
|
||||
|
||||
public function unreadCount(): int
|
||||
{
|
||||
return Notification::unread()->whereNotifiableId(
|
||||
Nova::user($this)->getKey()
|
||||
)->count();
|
||||
}
|
||||
}
|
||||
157
nova/src/Http/Requests/NovaRequest.php
Normal file
157
nova/src/Http/Requests/NovaRequest.php
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
|
||||
|
||||
/**
|
||||
* @property-read \Illuminate\Database\Eloquent\Model|string|null $resource
|
||||
* @property-read mixed|null $resourceId
|
||||
* @property-read string|null $relatedResource
|
||||
* @property-read mixed|null $relatedResourceId
|
||||
* @property-read string|null $viaResource
|
||||
* @property-read mixed|null $viaResourceId
|
||||
* @property-read string|null $viaRelationship
|
||||
* @property-read string|null $relationshipType
|
||||
*/
|
||||
class NovaRequest extends FormRequest
|
||||
{
|
||||
use InteractsWithRelatedResources;
|
||||
use InteractsWithResources;
|
||||
use InteractsWithResourcesSelection;
|
||||
|
||||
/**
|
||||
* Determine if this request is an inline create or attach request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isInlineCreateRequest()
|
||||
{
|
||||
return $this->isCreateOrAttachRequest() && $this->inline === 'true';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this request is a create or attach request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isCreateOrAttachRequest()
|
||||
{
|
||||
return $this instanceof ResourceCreateOrAttachRequest
|
||||
|| ($this->editing === 'true' && in_array($this->editMode, ['create', 'attach']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this request is an update or update-attached request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isUpdateOrUpdateAttachedRequest()
|
||||
{
|
||||
return $this instanceof ResourceUpdateOrUpdateAttachedRequest
|
||||
|| ($this->editing === 'true' && in_array($this->editMode, ['update', 'update-attached']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this request is a resource index request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isResourceIndexRequest()
|
||||
{
|
||||
return $this instanceof ResourceIndexRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this request is a resource detail request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isResourceDetailRequest()
|
||||
{
|
||||
return $this instanceof ResourceDetailRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this request is a resource preview request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isResourcePreviewRequest()
|
||||
{
|
||||
return $this instanceof ResourcePreviewRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this request is a resource peeking request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isResourcePeekingRequest()
|
||||
{
|
||||
return $this instanceof ResourcePeekRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this request is a lens request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isLensRequest()
|
||||
{
|
||||
return $this instanceof LensRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this request is an action request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isActionRequest()
|
||||
{
|
||||
return $this->segment(3) == 'actions';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this request is either create, attach, update, update-attached or action request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isFormRequest()
|
||||
{
|
||||
return $this->isCreateOrAttachRequest()
|
||||
|| $this->isUpdateOrUpdateAttachedRequest()
|
||||
|| $this->isActionRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this request is an index or detail request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isPresentationRequest()
|
||||
{
|
||||
return $this->isResourceIndexRequest()
|
||||
|| $this->isResourceDetailRequest()
|
||||
|| $this->isLensRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an Illuminate request from a Symfony instance.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* @return static
|
||||
*/
|
||||
public static function createFromBase(SymfonyRequest $request)
|
||||
{
|
||||
$newRequest = parent::createFromBase($request);
|
||||
|
||||
if ($request instanceof Request) {
|
||||
$newRequest->setUserResolver($request->getUserResolver());
|
||||
}
|
||||
|
||||
return $newRequest;
|
||||
}
|
||||
}
|
||||
98
nova/src/Http/Requests/PivotFieldDestroyRequest.php
Normal file
98
nova/src/Http/Requests/PivotFieldDestroyRequest.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Laravel\Nova\Fields\File;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class PivotFieldDestroyRequest extends NovaRequest
|
||||
{
|
||||
/**
|
||||
* Authorize that the user may attach resources of the given type.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
|
||||
*/
|
||||
public function authorizeForAttachment()
|
||||
{
|
||||
if (! $this->newResourceWith($this->findModelOrFail())->authorizedToAttach(
|
||||
$this, $this->findRelatedModel()
|
||||
)) {
|
||||
abort(403);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pivot model for the relationship.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function findPivotModel()
|
||||
{
|
||||
$resource = $this->findResourceOrFail();
|
||||
|
||||
abort_unless($resource->hasRelatableField($this, $this->viaRelationship), 404);
|
||||
|
||||
return once(function () use ($resource) {
|
||||
return $this->findRelatedModel()->{
|
||||
$resource->model()->{$this->viaRelationship}()->getPivotAccessor()
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the related resource for the operation.
|
||||
*
|
||||
* @param string|int|null $resourceId
|
||||
* @return \Laravel\Nova\Resource<\Illuminate\Database\Eloquent\Model>
|
||||
*/
|
||||
public function findRelatedResource($resourceId = null)
|
||||
{
|
||||
return Nova::newResourceFromModel(
|
||||
$this->findRelatedModel($resourceId)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the related model for the operation.
|
||||
*
|
||||
* @param string|int|null $resourceId
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function findRelatedModel($resourceId = null)
|
||||
{
|
||||
$resource = $this->findResourceOrFail();
|
||||
|
||||
abort_unless($resource->hasRelatableField($this, $this->viaRelationship), 404);
|
||||
|
||||
$query = $resource->model()->{$this->viaRelationship}()
|
||||
->withoutGlobalScopes();
|
||||
|
||||
if (! is_null($resourceId)) {
|
||||
return $query->lockForUpdate()->findOrFail($resourceId);
|
||||
}
|
||||
|
||||
return once(function () use ($query) {
|
||||
return $query->lockForUpdate()->findOrFail($this->relatedResourceId);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the field being deleted or fail if it is not found.
|
||||
*
|
||||
* @return \Laravel\Nova\Fields\Field&\Laravel\Nova\Fields\File
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
public function findFieldOrFail()
|
||||
{
|
||||
return $this->findRelatedResource()->resolvePivotFields($this, $this->resource)
|
||||
->whereInstanceOf(File::class)
|
||||
->findFieldByAttribute($this->field, function () {
|
||||
abort(404);
|
||||
});
|
||||
}
|
||||
}
|
||||
83
nova/src/Http/Requests/QueriesResources.php
Normal file
83
nova/src/Http/Requests/QueriesResources.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
trait QueriesResources
|
||||
{
|
||||
use DecodesFilters;
|
||||
|
||||
/**
|
||||
* Transform the request into a query.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function toQuery()
|
||||
{
|
||||
$resource = $this->resource();
|
||||
|
||||
return $resource::buildIndexQuery(
|
||||
$this, $this->newQuery(), $this->search,
|
||||
$this->filters()->all(), $this->orderings(), $this->trashed()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new query builder for the underlying model.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function newQuery()
|
||||
{
|
||||
if (! $this->viaRelationship()) {
|
||||
return $this->model()->newQuery();
|
||||
}
|
||||
|
||||
abort_unless($this->newViaResource()->hasRelatableField($this, $this->viaRelationship), 409);
|
||||
|
||||
return forward_static_call([$this->viaResource(), 'newModel'])
|
||||
->newQueryWithoutScopes()->findOrFail(
|
||||
$this->viaResourceId
|
||||
)->{$this->viaRelationship}();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new query builder for the underlying model.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function newQueryWithoutScopes()
|
||||
{
|
||||
if (! $this->viaRelationship()) {
|
||||
return $this->model()->newQueryWithoutScopes();
|
||||
}
|
||||
|
||||
abort_unless($this->newViaResource()->hasRelatableField($this, $this->viaRelationship), 409);
|
||||
|
||||
return forward_static_call([$this->viaResource(), 'newModel'])
|
||||
->newQueryWithoutScopes()->findOrFail(
|
||||
$this->viaResourceId
|
||||
)->{$this->viaRelationship}()->withoutGlobalScopes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the orderings for the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function orderings()
|
||||
{
|
||||
return ! empty($this->orderBy)
|
||||
? [$this->orderBy => $this->orderByDirection]
|
||||
: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the trashed status of the request.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function trashed()
|
||||
{
|
||||
return $this->trashed;
|
||||
}
|
||||
}
|
||||
8
nova/src/Http/Requests/ResourceCreateOrAttachRequest.php
Normal file
8
nova/src/Http/Requests/ResourceCreateOrAttachRequest.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
class ResourceCreateOrAttachRequest extends NovaRequest
|
||||
{
|
||||
//
|
||||
}
|
||||
8
nova/src/Http/Requests/ResourceDetailRequest.php
Normal file
8
nova/src/Http/Requests/ResourceDetailRequest.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
class ResourceDetailRequest extends NovaRequest
|
||||
{
|
||||
//
|
||||
}
|
||||
59
nova/src/Http/Requests/ResourceIndexRequest.php
Normal file
59
nova/src/Http/Requests/ResourceIndexRequest.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Laravel\Nova\Contracts\QueryBuilder;
|
||||
|
||||
class ResourceIndexRequest extends NovaRequest
|
||||
{
|
||||
use CountsResources;
|
||||
use QueriesResources;
|
||||
|
||||
/**
|
||||
* Get the paginator instance for the index request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function searchIndex()
|
||||
{
|
||||
return app()->make(QueryBuilder::class, [$this->resource()])->search(
|
||||
$this, $this->newQuery(), $this->search,
|
||||
$this->filters()->all(), $this->orderings(), $this->trashed()
|
||||
)->paginate((int) $this->perPage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the count of the resources.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function toCount()
|
||||
{
|
||||
return app()->make(QueryBuilder::class, [$this->resource()])->search(
|
||||
$this, $this->newQuery(), $this->search,
|
||||
$this->filters()->all(), $this->orderings(), $this->trashed()
|
||||
)->toBaseQueryBuilder()->getCountForPagination();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get per page.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function perPage()
|
||||
{
|
||||
$resource = $this->resource();
|
||||
|
||||
if ($this->viaRelationship()) {
|
||||
return (int) $resource::$perPageViaRelationship;
|
||||
}
|
||||
|
||||
$perPageOptions = $resource::perPageOptions();
|
||||
|
||||
if (empty($perPageOptions)) {
|
||||
$perPageOptions = [$resource::newModel()->getPerPage()];
|
||||
}
|
||||
|
||||
return (int) in_array($this->perPage, $perPageOptions) ? $this->perPage : $perPageOptions[0];
|
||||
}
|
||||
}
|
||||
8
nova/src/Http/Requests/ResourcePeekRequest.php
Normal file
8
nova/src/Http/Requests/ResourcePeekRequest.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
class ResourcePeekRequest extends NovaRequest
|
||||
{
|
||||
//
|
||||
}
|
||||
8
nova/src/Http/Requests/ResourcePreviewRequest.php
Normal file
8
nova/src/Http/Requests/ResourcePreviewRequest.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
class ResourcePreviewRequest extends NovaRequest
|
||||
{
|
||||
//
|
||||
}
|
||||
36
nova/src/Http/Requests/ResourceSearchRequest.php
Normal file
36
nova/src/Http/Requests/ResourceSearchRequest.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Laravel\Nova\Contracts\QueryBuilder;
|
||||
|
||||
class ResourceSearchRequest extends NovaRequest
|
||||
{
|
||||
use QueriesResources;
|
||||
|
||||
/**
|
||||
* Get the paginator instance for the index request.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function searchIndex()
|
||||
{
|
||||
$resource = $this->resource();
|
||||
$model = $this->model();
|
||||
|
||||
$limit = $resource::usesScout()
|
||||
? $resource::$scoutSearchResults
|
||||
: $resource::$relatableSearchResults;
|
||||
|
||||
$query = app()->make(QueryBuilder::class, [$resource]);
|
||||
|
||||
$this->first === 'true'
|
||||
? $query->whereKey($model->newQueryWithoutScopes(), $this->current)
|
||||
: $query->search(
|
||||
$this, $this->newQuery(), $this->search,
|
||||
$this->filters()->all(), $this->orderings(), $this->trashed()
|
||||
);
|
||||
|
||||
return $query->take($limit)->get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
class ResourceUpdateOrUpdateAttachedRequest extends NovaRequest
|
||||
{
|
||||
//
|
||||
}
|
||||
49
nova/src/Http/Requests/RestoreLensResourceRequest.php
Normal file
49
nova/src/Http/Requests/RestoreLensResourceRequest.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class RestoreLensResourceRequest extends LensResourceDeletionRequest
|
||||
{
|
||||
/**
|
||||
* Get the selected models for the action in chunks.
|
||||
*
|
||||
* @param int $count
|
||||
* @param \Closure(\Illuminate\Support\Collection):void $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function chunks($count, Closure $callback)
|
||||
{
|
||||
return $this->chunkWithAuthorization($count, $callback, function ($models) {
|
||||
return $this->restorableModels($models);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the models that may be restored.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $models
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function restorableModels(Collection $models)
|
||||
{
|
||||
return $models->mapInto($this->resource())
|
||||
->filter
|
||||
->isSoftDeleted()
|
||||
->filter
|
||||
->authorizedToRestore($this)
|
||||
->map->model();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the trashed status of the request.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function trashed()
|
||||
{
|
||||
return 'with';
|
||||
}
|
||||
}
|
||||
49
nova/src/Http/Requests/RestoreResourceRequest.php
Normal file
49
nova/src/Http/Requests/RestoreResourceRequest.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class RestoreResourceRequest extends DeletionRequest
|
||||
{
|
||||
/**
|
||||
* Get the selected models for the action in chunks.
|
||||
*
|
||||
* @param int $count
|
||||
* @param \Closure(\Illuminate\Support\Collection):void $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public function chunks($count, Closure $callback)
|
||||
{
|
||||
return $this->chunkWithAuthorization($count, $callback, function ($models) {
|
||||
return $this->restorableModels($models);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the models that may be restored.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $models
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function restorableModels(Collection $models)
|
||||
{
|
||||
return $models->mapInto($this->resource())
|
||||
->filter
|
||||
->isSoftDeleted()
|
||||
->filter
|
||||
->authorizedToRestore($this)
|
||||
->map->model();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the trashed status of the request.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function trashed()
|
||||
{
|
||||
return 'with';
|
||||
}
|
||||
}
|
||||
16
nova/src/Http/Requests/UpdateResourceRequest.php
Normal file
16
nova/src/Http/Requests/UpdateResourceRequest.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Requests;
|
||||
|
||||
class UpdateResourceRequest extends NovaRequest
|
||||
{
|
||||
/**
|
||||
* Determine if this request is an update or update-attached request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isUpdateOrUpdateAttachedRequest()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user