add nova
This commit is contained in:
110
nova/src/Http/Controllers/ActionController.php
Normal file
110
nova/src/Http/Controllers/ActionController.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Actions\Action;
|
||||
use Laravel\Nova\Actions\ActionCollection;
|
||||
use Laravel\Nova\Http\Requests\ActionRequest;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
use Laravel\Nova\Resource;
|
||||
|
||||
class ActionController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the actions for the given resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index(NovaRequest $request)
|
||||
{
|
||||
$resourceId = with($request->input('resources'), function ($resourceIds) {
|
||||
return is_array($resourceIds) && count($resourceIds) === 1 ? $resourceIds[0] : null;
|
||||
});
|
||||
|
||||
$resource = $request->newResourceWith(
|
||||
$request->findModel($resourceId) ?? $request->model()
|
||||
);
|
||||
|
||||
return response()->json(with([
|
||||
'actions' => $this->availableActions($request, $resource),
|
||||
'pivotActions' => [
|
||||
'name' => Nova::humanize($request->pivotName()),
|
||||
'actions' => $resource->availablePivotActions($request),
|
||||
],
|
||||
], function ($payload) use ($resource, $request) {
|
||||
$actionCounts = ($request->display !== 'detail' ? $payload['actions'] : $resource->resolveActions($request))->countsByTypeOnIndex();
|
||||
$pivotActionCounts = ActionCollection::make($payload['pivotActions']['actions'])->countsByTypeOnIndex();
|
||||
|
||||
$payload['counts'] = [
|
||||
'standalone' => $actionCounts['standalone'] + $pivotActionCounts['standalone'],
|
||||
'resource' => $actionCounts['resource'] + $pivotActionCounts['resource'],
|
||||
];
|
||||
|
||||
return $payload;
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an action on the specified resources.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ActionRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(ActionRequest $request)
|
||||
{
|
||||
$request->validateFields();
|
||||
|
||||
return $request->action()->handleRequest($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync an action field on the specified resources.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ActionRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function sync(ActionRequest $request)
|
||||
{
|
||||
$action = $this->availableActions($request, $request->newResource())
|
||||
->first(function ($action) use ($request) {
|
||||
return $action->uriKey() === $request->query('action');
|
||||
});
|
||||
|
||||
abort_unless($action instanceof Action, 404);
|
||||
|
||||
return response()->json(
|
||||
collect($action->fields($request))
|
||||
->filter(function ($field) use ($request) {
|
||||
return $request->query('field') === $field->attribute &&
|
||||
$request->query('component') === $field->dependentComponentKey();
|
||||
})->each->syncDependsOn($request)
|
||||
->first()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the available actions for the request.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param \Laravel\Nova\Resource $resource
|
||||
* @return \Laravel\Nova\Actions\ActionCollection<int, \Laravel\Nova\Actions\Action>
|
||||
*/
|
||||
protected function availableActions(NovaRequest $request, Resource $resource)
|
||||
{
|
||||
switch ($request->display) {
|
||||
case 'index':
|
||||
$method = 'availableActionsOnIndex';
|
||||
break;
|
||||
case 'detail':
|
||||
$method = 'availableActionsOnDetail';
|
||||
break;
|
||||
default:
|
||||
$method = 'availableActions';
|
||||
}
|
||||
|
||||
return $resource->{$method}($request);
|
||||
}
|
||||
}
|
||||
75
nova/src/Http/Controllers/AssociatableController.php
Normal file
75
nova/src/Http/Controllers/AssociatableController.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Contracts\RelatableField;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
class AssociatableController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the available related resources for a given resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return array
|
||||
*/
|
||||
public function __invoke(NovaRequest $request)
|
||||
{
|
||||
$field = $request->newResource()
|
||||
->availableFields($request)
|
||||
->whereInstanceOf(RelatableField::class)
|
||||
->findFieldByAttribute($request->field, function () {
|
||||
abort(404);
|
||||
})->applyDependsOn($request);
|
||||
|
||||
$withTrashed = $this->shouldIncludeTrashed(
|
||||
$request, $associatedResource = $field->resourceClass
|
||||
);
|
||||
|
||||
$limit = $associatedResource::usesScout()
|
||||
? $associatedResource::$scoutSearchResults
|
||||
: $associatedResource::$relatableSearchResults;
|
||||
|
||||
$shouldReorderAssociatableValues = $field->shouldReorderAssociatableValues($request) && ! $associatedResource::usesScout();
|
||||
|
||||
return [
|
||||
'resources' => $field->buildAssociatableQuery($request, $withTrashed)
|
||||
->take($limit)
|
||||
->get()
|
||||
->mapInto($field->resourceClass)
|
||||
->filter->authorizedToAdd($request, $request->model())
|
||||
->map(function ($resource) use ($request, $field) {
|
||||
return $field->formatAssociatableResource($request, $resource);
|
||||
})->when($shouldReorderAssociatableValues, function ($collection) {
|
||||
return $collection->sortBy('display');
|
||||
})->values(),
|
||||
'softDeletes' => $associatedResource::softDeletes(),
|
||||
'withTrashed' => $withTrashed,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the query should include trashed models.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param string $associatedResource
|
||||
* @return bool
|
||||
*/
|
||||
protected function shouldIncludeTrashed(NovaRequest $request, $associatedResource)
|
||||
{
|
||||
if ($request->withTrashed === 'true') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$associatedModel = $associatedResource::newModel();
|
||||
|
||||
if ($request->current && empty($request->search) && $associatedResource::softDeletes()) {
|
||||
$associatedModel = $associatedModel->newQueryWithoutScopes()->find($request->current);
|
||||
|
||||
return $associatedModel ? $associatedModel->trashed() : false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
104
nova/src/Http/Controllers/AttachableController.php
Normal file
104
nova/src/Http/Controllers/AttachableController.php
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Contracts\PivotableField;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
class AttachableController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the available related resources for a given resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return array
|
||||
*/
|
||||
public function __invoke(NovaRequest $request)
|
||||
{
|
||||
$field = $request->newResource()
|
||||
->availableFields($request)
|
||||
->filterForManyToManyRelations()
|
||||
->filter(function ($field) use ($request) {
|
||||
return $field->resourceName === $request->field &&
|
||||
$field->attribute === $request->viaRelationship;
|
||||
})->first();
|
||||
|
||||
$withTrashed = $this->shouldIncludeTrashed(
|
||||
$request, $associatedResource = $field->resourceClass
|
||||
);
|
||||
|
||||
$parentResource = $request->findResourceOrFail();
|
||||
|
||||
$shouldReorderAttachableValues = $field->shouldReorderAttachableValues($request) && ! $associatedResource::usesScout();
|
||||
|
||||
return [
|
||||
'resources' => $field->buildAttachableQuery($request, $withTrashed)
|
||||
->tap($this->getAttachableQueryResolver($request, $field))
|
||||
->get()
|
||||
->mapInto($field->resourceClass)
|
||||
->filter(function ($resource) use ($request, $parentResource) {
|
||||
return $parentResource->authorizedToAttach($request, $resource->resource);
|
||||
})
|
||||
->map(function ($resource) use ($request, $field) {
|
||||
return $field->formatAttachableResource($request, $resource);
|
||||
})->when($shouldReorderAttachableValues, function ($collection) {
|
||||
return $collection->sortBy('display', SORT_NATURAL | SORT_FLAG_CASE);
|
||||
})->values(),
|
||||
'withTrashed' => $withTrashed,
|
||||
'softDeletes' => $associatedResource::softDeletes(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the query should include trashed models.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param string $associatedResource
|
||||
* @return bool
|
||||
*/
|
||||
protected function shouldIncludeTrashed(NovaRequest $request, $associatedResource)
|
||||
{
|
||||
if ($request->withTrashed === 'true') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$associatedModel = $associatedResource::newModel();
|
||||
|
||||
if ($request->current && $associatedResource::softDeletes()) {
|
||||
$associatedModel = $associatedModel->newQueryWithoutScopes()->find($request->current);
|
||||
|
||||
return $associatedModel ? $associatedModel->trashed() : false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get attachable query resolver.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param \Laravel\Nova\Fields\Field&\Laravel\Nova\Contracts\PivotableField $field
|
||||
* @return callable(\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder):void
|
||||
*/
|
||||
protected function getAttachableQueryResolver(NovaRequest $request, PivotableField $field)
|
||||
{
|
||||
return function ($query) use ($request, $field) {
|
||||
if (
|
||||
$request->first === 'true'
|
||||
|| $field->allowDuplicateRelations
|
||||
|| is_null($relatedModel = $request->findModel())
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$query->whereNotExists(function ($query) use ($field, $relatedModel) {
|
||||
$relation = $relatedModel->{$field->manyToManyRelationship}();
|
||||
|
||||
return $relation->applyDefaultPivotQuery($query)
|
||||
->select($relation->getRelatedPivotKeyName())
|
||||
->whereColumn($relation->getQualifiedRelatedKeyName(), $relation->getQualifiedRelatedPivotKeyName());
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
155
nova/src/Http/Controllers/AttachedResourceUpdateController.php
Normal file
155
nova/src/Http/Controllers/AttachedResourceUpdateController.php
Normal file
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Nova\Actions\ActionEvent;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
use Throwable;
|
||||
|
||||
class AttachedResourceUpdateController extends Controller
|
||||
{
|
||||
use HandlesCustomRelationKeys;
|
||||
|
||||
/**
|
||||
* The action event for the action.
|
||||
*
|
||||
* @var \Laravel\Nova\Actions\ActionEvent|null
|
||||
*/
|
||||
protected $actionEvent;
|
||||
|
||||
/**
|
||||
* Update an attached resource pivot record.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function __invoke(NovaRequest $request)
|
||||
{
|
||||
$resource = $request->resource();
|
||||
|
||||
$model = $request->findModelOrFail();
|
||||
|
||||
tap(new $resource($model), function ($resource) use ($request) {
|
||||
abort_unless($resource->hasRelatableField($request, $request->viaRelationship), 404);
|
||||
});
|
||||
|
||||
$this->validate($request, $model, $resource);
|
||||
|
||||
try {
|
||||
return DB::connection($model->getConnectionName())->transaction(function () use ($request, $resource, $model) {
|
||||
$model->setRelation(
|
||||
$model->{$request->viaRelationship}()->getPivotAccessor(),
|
||||
$pivot = $this->findPivot($request, $model)
|
||||
);
|
||||
|
||||
if ($this->modelHasBeenUpdatedSinceRetrieval($request, $pivot)) {
|
||||
return response('', 409);
|
||||
}
|
||||
|
||||
[$pivot, $callbacks] = $resource::fillPivotForUpdate($request, $model, $pivot);
|
||||
|
||||
DB::transaction(function () use ($request, $model, $pivot) {
|
||||
Nova::usingActionEvent(function (ActionEvent $actionEvent) use ($request, $model, $pivot) {
|
||||
$this->actionEvent = $actionEvent->forAttachedResourceUpdate($request, $model, $pivot);
|
||||
$this->actionEvent->save();
|
||||
});
|
||||
});
|
||||
|
||||
$pivot->save();
|
||||
|
||||
collect($callbacks)->each->__invoke();
|
||||
});
|
||||
} catch (Throwable $e) {
|
||||
optional($this->actionEvent)->delete();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the attachment request.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param class-string<\Laravel\Nova\Resource> $resourceClass
|
||||
* @return void
|
||||
*/
|
||||
protected function validate(NovaRequest $request, $model, $resourceClass)
|
||||
{
|
||||
$attribute = $resourceClass::validationAttachableAttributeFor($request, $request->relatedResource);
|
||||
|
||||
tap($this->updateRulesFor($request, $resourceClass), function ($rules) use ($resourceClass, $request, $attribute) {
|
||||
Validator::make($request->all(), $rules, [], $this->customRulesKeys($request, $attribute))->validate();
|
||||
|
||||
$resourceClass::validateForAttachmentUpdate($request);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get update rules for request from the resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param class-string<\Laravel\Nova\Resource> $resourceClass
|
||||
* @return array
|
||||
*/
|
||||
protected function updateRulesFor(NovaRequest $request, $resourceClass)
|
||||
{
|
||||
$rules = $resourceClass::updateRulesFor($request, $this->getRuleKey($request));
|
||||
|
||||
if ($this->usingCustomRelationKey($request)) {
|
||||
$rules[$request->relatedResource] = $rules[$request->viaRelationship];
|
||||
unset($rules[$request->viaRelationship]);
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the pivot model for the operation.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Pivot
|
||||
*/
|
||||
protected function findPivot(NovaRequest $request, $model)
|
||||
{
|
||||
$relation = $model->{$request->viaRelationship}();
|
||||
|
||||
if ($request->viaPivotId) {
|
||||
tap($relation->getPivotClass(), function ($pivotClass) use ($relation, $request) {
|
||||
$relation->wherePivot((new $pivotClass())->getKeyName(), $request->viaPivotId);
|
||||
});
|
||||
}
|
||||
|
||||
$accessor = $relation->getPivotAccessor();
|
||||
|
||||
return $relation
|
||||
->withoutGlobalScopes()
|
||||
->lockForUpdate()
|
||||
->findOrFail($request->relatedResourceId)->{$accessor};
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the model has been updated since it was retrieved.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return bool
|
||||
*/
|
||||
protected function modelHasBeenUpdatedSinceRetrieval(NovaRequest $request, $model)
|
||||
{
|
||||
$column = $model->getUpdatedAtColumn();
|
||||
|
||||
if (! ($model->usesTimestamps() && $model->{$column})) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $request->input('_retrieved_at') && $model->{$column}->gt(
|
||||
Carbon::createFromTimestamp($request->input('_retrieved_at'))
|
||||
);
|
||||
}
|
||||
}
|
||||
22
nova/src/Http/Controllers/CardController.php
Normal file
22
nova/src/Http/Controllers/CardController.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\CardRequest;
|
||||
|
||||
class CardController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the cards for the given resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\CardRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(CardRequest $request)
|
||||
{
|
||||
return response()->json(
|
||||
$request->availableCards()
|
||||
);
|
||||
}
|
||||
}
|
||||
28
nova/src/Http/Controllers/CreationFieldController.php
Normal file
28
nova/src/Http/Controllers/CreationFieldController.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\ResourceCreateOrAttachRequest;
|
||||
use Laravel\Nova\Http\Resources\CreateViewResource;
|
||||
use Laravel\Nova\Http\Resources\ReplicateViewResource;
|
||||
|
||||
class CreationFieldController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the creation fields for the given resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceCreateOrAttachRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function __invoke(ResourceCreateOrAttachRequest $request)
|
||||
{
|
||||
if ($request->has('fromResourceId')) {
|
||||
return ReplicateViewResource::make($request->fromResourceId)->toResponse($request);
|
||||
}
|
||||
|
||||
return CreateViewResource::make()->toResponse($request);
|
||||
}
|
||||
}
|
||||
33
nova/src/Http/Controllers/CreationFieldSyncController.php
Normal file
33
nova/src/Http/Controllers/CreationFieldSyncController.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\ResourceCreateOrAttachRequest;
|
||||
use Laravel\Nova\Http\Resources\CreateViewResource;
|
||||
use Laravel\Nova\Http\Resources\ReplicateViewResource;
|
||||
|
||||
class CreationFieldSyncController extends Controller
|
||||
{
|
||||
/**
|
||||
* Synchronize the field for creation view.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceCreateOrAttachRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(ResourceCreateOrAttachRequest $request)
|
||||
{
|
||||
$resource = $request->has('fromResourceId')
|
||||
? ReplicateViewResource::make($request->fromResourceId)->newResourceWith($request)
|
||||
: CreateViewResource::make()->newResourceWith($request);
|
||||
|
||||
return response()->json(
|
||||
$resource->creationFields($request)
|
||||
->filter(function ($field) use ($request) {
|
||||
return $request->query('field') === $field->attribute &&
|
||||
$request->query('component') === $field->dependentComponentKey();
|
||||
})->each->syncDependsOn($request)
|
||||
->first()
|
||||
);
|
||||
}
|
||||
}
|
||||
42
nova/src/Http/Controllers/CreationPivotFieldController.php
Normal file
42
nova/src/Http/Controllers/CreationPivotFieldController.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\ResourceCreateOrAttachRequest;
|
||||
use Laravel\Nova\Http\Resources\CreationPivotFieldResource;
|
||||
|
||||
class CreationPivotFieldController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the pivot fields for the given resource and relation.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceCreateOrAttachRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(ResourceCreateOrAttachRequest $request)
|
||||
{
|
||||
return CreationPivotFieldResource::make()->toResponse($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize the pivot field for creation.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceCreateOrAttachRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function sync(ResourceCreateOrAttachRequest $request)
|
||||
{
|
||||
$resource = CreationPivotFieldResource::make()->newResourceWith($request);
|
||||
|
||||
return response()->json(
|
||||
$resource->creationPivotFields(
|
||||
$request, $request->relatedResource
|
||||
)->filter(function ($field) use ($request) {
|
||||
return $request->query('field') === $field->attribute &&
|
||||
$request->query('component') === $field->dependentComponentKey();
|
||||
})->applyDependsOn($request)
|
||||
->first()
|
||||
);
|
||||
}
|
||||
}
|
||||
23
nova/src/Http/Controllers/DashboardCardController.php
Normal file
23
nova/src/Http/Controllers/DashboardCardController.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\DashboardRequest;
|
||||
|
||||
class DashboardCardController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the cards for the dashboard.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\DashboardRequest $request
|
||||
* @param string $dashboard
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(DashboardRequest $request, $dashboard = 'main')
|
||||
{
|
||||
return response()->json(
|
||||
$request->availableCards($dashboard)
|
||||
);
|
||||
}
|
||||
}
|
||||
22
nova/src/Http/Controllers/DashboardController.php
Normal file
22
nova/src/Http/Controllers/DashboardController.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\DashboardRequest;
|
||||
use Laravel\Nova\Http\Resources\DashboardViewResource;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
/**
|
||||
* Return the details for the Dashboard.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\DashboardRequest $request
|
||||
* @param string $dashboard
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(DashboardRequest $request, $dashboard = 'main')
|
||||
{
|
||||
return DashboardViewResource::make($dashboard)->toResponse($request);
|
||||
}
|
||||
}
|
||||
22
nova/src/Http/Controllers/DashboardMetricController.php
Normal file
22
nova/src/Http/Controllers/DashboardMetricController.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\DashboardMetricRequest;
|
||||
|
||||
class DashboardMetricController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get the specified metric's value.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\DashboardMetricRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(DashboardMetricRequest $request)
|
||||
{
|
||||
return response()->json([
|
||||
'value' => $request->metric()->resolve($request),
|
||||
]);
|
||||
}
|
||||
}
|
||||
43
nova/src/Http/Controllers/DeletesFields.php
Normal file
43
nova/src/Http/Controllers/DeletesFields.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Laravel\Nova\DeleteField;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
trait DeletesFields
|
||||
{
|
||||
/**
|
||||
* Delete the deletable fields on the given model / resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return void
|
||||
*/
|
||||
protected function forceDeleteFields(NovaRequest $request, $model)
|
||||
{
|
||||
$this->deleteFields($request, $model, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the deletable fields on the given model / resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param bool $skipSoftDeletes
|
||||
* @return void
|
||||
*/
|
||||
protected function deleteFields(NovaRequest $request, $model, $skipSoftDeletes = true)
|
||||
{
|
||||
if ($skipSoftDeletes && $request->newResourceWith($model)->softDeletes()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$request->newResourceWith($model)
|
||||
->deletableFields($request)
|
||||
->filter->isPrunable()
|
||||
->each(function ($field) use ($request, $model) {
|
||||
DeleteField::forRequest($request, $field, $model);
|
||||
});
|
||||
}
|
||||
}
|
||||
22
nova/src/Http/Controllers/DetailMetricController.php
Normal file
22
nova/src/Http/Controllers/DetailMetricController.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\MetricRequest;
|
||||
|
||||
class DetailMetricController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get the specified metric's value.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\MetricRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(MetricRequest $request)
|
||||
{
|
||||
return response()->json([
|
||||
'value' => $request->detailMetric()->resolve($request),
|
||||
]);
|
||||
}
|
||||
}
|
||||
95
nova/src/Http/Controllers/FieldAttachmentController.php
Normal file
95
nova/src/Http/Controllers/FieldAttachmentController.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
class FieldAttachmentController extends Controller
|
||||
{
|
||||
/**
|
||||
* Store an attachment for a Trix field.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function store(NovaRequest $request)
|
||||
{
|
||||
/** @var \Laravel\Nova\Fields\Field&\Laravel\Nova\Contracts\Storable $field */
|
||||
$field = $request->newResource()
|
||||
->availableFields($request)
|
||||
->filter(function ($field) {
|
||||
return optional($field)->withFiles === true;
|
||||
})
|
||||
->findFieldByAttribute($request->field, function () {
|
||||
abort(404);
|
||||
});
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$payload = call_user_func($field->attachCallback, $request);
|
||||
|
||||
return response()->json($payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a single, persisted attachment for a Trix field by URL.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroyAttachment(NovaRequest $request)
|
||||
{
|
||||
/** @var \Laravel\Nova\Fields\Field&\Laravel\Nova\Contracts\Storable $field */
|
||||
$field = $request->newResource()
|
||||
->availableFields($request)
|
||||
->filter(function ($field) {
|
||||
return optional($field)->withFiles === true;
|
||||
})
|
||||
->findFieldByAttribute($request->field, function () {
|
||||
abort(404);
|
||||
});
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
call_user_func($field->detachCallback, $request);
|
||||
|
||||
return response()->noContent(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Purge all pending attachments for a Trix field.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroyPending(NovaRequest $request)
|
||||
{
|
||||
/** @var \Laravel\Nova\Fields\Field&\Laravel\Nova\Contracts\Storable $field */
|
||||
$field = $request->newResource()
|
||||
->availableFields($request)
|
||||
->filter(function ($field) {
|
||||
return optional($field)->withFiles === true;
|
||||
})
|
||||
->findFieldByAttribute($request->field, function () {
|
||||
abort(404);
|
||||
});
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
call_user_func($field->discardCallback, $request);
|
||||
|
||||
return response()->noContent(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new draft ID for the field.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function draftId(NovaRequest $request)
|
||||
{
|
||||
return response()->json([
|
||||
'draftId' => Str::uuid(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
31
nova/src/Http/Controllers/FieldController.php
Normal file
31
nova/src/Http/Controllers/FieldController.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Contracts\RelatableField;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
class FieldController extends Controller
|
||||
{
|
||||
/**
|
||||
* Retrieve the given field for the given resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(NovaRequest $request)
|
||||
{
|
||||
$resource = $request->newResource();
|
||||
|
||||
$fields = $request->relatable
|
||||
? $resource->availableFieldsOnIndexOrDetail($request)->whereInstanceOf(RelatableField::class)
|
||||
: $resource->availableFields($request);
|
||||
|
||||
return response()->json(
|
||||
$fields->findFieldByAttribute($request->field, function () {
|
||||
abort(404);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
43
nova/src/Http/Controllers/FieldDestroyController.php
Normal file
43
nova/src/Http/Controllers/FieldDestroyController.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Contracts\Downloadable;
|
||||
use Laravel\Nova\DeleteField;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class FieldDestroyController extends Controller
|
||||
{
|
||||
/**
|
||||
* Delete the file at the given field.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function __invoke(NovaRequest $request)
|
||||
{
|
||||
$resource = $request->findResourceOrFail();
|
||||
|
||||
$resource->authorizeToUpdate($request);
|
||||
|
||||
$field = $resource->updateFields($request)
|
||||
->whereInstanceOf(Downloadable::class)
|
||||
->findFieldByAttribute($request->field, function () {
|
||||
abort(404);
|
||||
});
|
||||
|
||||
DeleteField::forRequest(
|
||||
$request, $field, $resource->resource
|
||||
)->save();
|
||||
|
||||
Nova::usingActionEvent(function ($actionEvent) use ($request, $resource) {
|
||||
$actionEvent->forResourceUpdate(
|
||||
Nova::user($request), $resource->resource
|
||||
)->save();
|
||||
});
|
||||
|
||||
return response()->noContent(200);
|
||||
}
|
||||
}
|
||||
28
nova/src/Http/Controllers/FieldDownloadController.php
Normal file
28
nova/src/Http/Controllers/FieldDownloadController.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
class FieldDownloadController extends Controller
|
||||
{
|
||||
/**
|
||||
* Download the given field's contents.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function __invoke(NovaRequest $request)
|
||||
{
|
||||
$resource = $request->findResourceOrFail();
|
||||
|
||||
$resource->authorizeToView($request);
|
||||
|
||||
return $resource->downloadableFields($request)
|
||||
->findFieldByAttribute($request->field, function () {
|
||||
abort(404);
|
||||
})
|
||||
->toDownloadResponse($request, $resource);
|
||||
}
|
||||
}
|
||||
34
nova/src/Http/Controllers/FieldPreviewController.php
Normal file
34
nova/src/Http/Controllers/FieldPreviewController.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Contracts\Previewable;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
class FieldPreviewController extends Controller
|
||||
{
|
||||
/**
|
||||
* Delete the file at the given field.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(NovaRequest $request)
|
||||
{
|
||||
$request->validate(['value' => ['nullable', 'string']]);
|
||||
|
||||
$resource = $request->newResource();
|
||||
|
||||
/** @var \Laravel\Nova\Fields\Field&\Laravel\Nova\Contracts\Previewable $field */
|
||||
$field = $resource->availableFields($request)
|
||||
->whereInstanceOf(Previewable::class)
|
||||
->findFieldByAttribute($request->field, function () {
|
||||
abort(404);
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'preview' => $field->previewFor($request->value),
|
||||
]);
|
||||
}
|
||||
}
|
||||
20
nova/src/Http/Controllers/FilterController.php
Normal file
20
nova/src/Http/Controllers/FilterController.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
class FilterController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the filters for the given resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(NovaRequest $request)
|
||||
{
|
||||
return response()->json($request->newResource()->availableFilters($request));
|
||||
}
|
||||
}
|
||||
67
nova/src/Http/Controllers/ForgotPasswordController.php
Normal file
67
nova/src/Http/Controllers/ForgotPasswordController.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Auth\Notifications\ResetPassword;
|
||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Inertia\Inertia;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class ForgotPasswordController extends Controller
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Reset Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller is responsible for handling password reset emails and
|
||||
| includes a trait which assists in sending these notifications from
|
||||
| your application to your users. Feel free to explore this trait.
|
||||
|
|
||||
*/
|
||||
|
||||
use SendsPasswordResetEmails;
|
||||
use ValidatesRequests;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('nova.guest:'.config('nova.guard'));
|
||||
|
||||
ResetPassword::toMailUsing(function ($notifiable, $token) {
|
||||
return (new MailMessage)
|
||||
->subject(Nova::__('Reset Password Notification'))
|
||||
->line(Nova::__('You are receiving this email because we received a password reset request for your account.'))
|
||||
->action(Nova::__('Reset Password'), route('nova.pages.password.reset', ['token' => $token]))
|
||||
->line(Nova::__('If you did not request a password reset, no further action is required.'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the form to request a password reset link.
|
||||
*
|
||||
* @return \Inertia\Response
|
||||
*/
|
||||
public function showLinkRequestForm()
|
||||
{
|
||||
return Inertia::render('Nova.ForgotPassword');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the broker to be used during password reset.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Auth\PasswordBroker
|
||||
*/
|
||||
public function broker()
|
||||
{
|
||||
return Password::broker(config('nova.passwords'));
|
||||
}
|
||||
}
|
||||
44
nova/src/Http/Controllers/HandlesCustomRelationKeys.php
Normal file
44
nova/src/Http/Controllers/HandlesCustomRelationKeys.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
trait HandlesCustomRelationKeys
|
||||
{
|
||||
/**
|
||||
* Determine if the user has set a custom relation key for the field.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return bool
|
||||
*/
|
||||
protected function usingCustomRelationKey(NovaRequest $request)
|
||||
{
|
||||
return $request->relatedResource !== $request->viaRelationship;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rule key used for fetching the field's validation rules.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getRuleKey(NovaRequest $request)
|
||||
{
|
||||
return $this->usingCustomRelationKey($request)
|
||||
? $request->viaRelationship
|
||||
: $request->relatedResource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the custom field attributes names for validation.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param string $attribute
|
||||
* @return array
|
||||
*/
|
||||
protected function customRulesKeys(NovaRequest $request, $attribute)
|
||||
{
|
||||
return [$this->getRuleKey($request) => $attribute];
|
||||
}
|
||||
}
|
||||
73
nova/src/Http/Controllers/ImpersonateController.php
Normal file
73
nova/src/Http/Controllers/ImpersonateController.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Laravel\Nova\Contracts\ImpersonatesUsers;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
use Laravel\Nova\Util;
|
||||
|
||||
class ImpersonateController extends Controller
|
||||
{
|
||||
/**
|
||||
* Start impersonating a user.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param \Laravel\Nova\Contracts\ImpersonatesUsers $impersonator
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function startImpersonating(NovaRequest $request, ImpersonatesUsers $impersonator)
|
||||
{
|
||||
if ($impersonator->impersonating($request)) {
|
||||
return $this->stopImpersonating($request, $impersonator);
|
||||
}
|
||||
|
||||
/** @var class-string<\Illuminate\Contracts\Auth\Authenticatable&\Illuminate\Database\Eloquent\Model> $userModel */
|
||||
$userModel = with(Nova::modelInstanceForKey($request->input('resource')), function ($model) {
|
||||
return ! is_null($model) ? get_class($model) : Util::userModel();
|
||||
});
|
||||
|
||||
$authGuard = Util::sessionAuthGuardForModel($userModel);
|
||||
|
||||
$currentUser = Nova::user($request);
|
||||
|
||||
/** @var \Illuminate\Contracts\Auth\Authenticatable&\Illuminate\Database\Eloquent\Model $user */
|
||||
$user = $userModel::findOrFail($request->input('resourceId'));
|
||||
|
||||
// Now that we're guaranteed to be a 'real' user, we'll make sure we're
|
||||
// actually trying to impersonate someone besides ourselves, as that
|
||||
// would be unnecessary.
|
||||
if (! $currentUser->is($user)) {
|
||||
abort_unless(optional($currentUser)->canImpersonate() ?? false, 403);
|
||||
abort_unless(optional($user)->canBeImpersonated() ?? false, 403);
|
||||
|
||||
$impersonator->impersonate(
|
||||
$request,
|
||||
Auth::guard($authGuard),
|
||||
$user
|
||||
);
|
||||
}
|
||||
|
||||
return $impersonator->redirectAfterStartingImpersonation($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop impersonating a user.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param \Laravel\Nova\Contracts\ImpersonatesUsers $impersonator
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function stopImpersonating(NovaRequest $request, ImpersonatesUsers $impersonator)
|
||||
{
|
||||
$impersonator->stopImpersonating(
|
||||
$request,
|
||||
Auth::guard(config('nova.guard', config('auth.defaults.guard'))),
|
||||
Util::userModel()
|
||||
);
|
||||
|
||||
return $impersonator->redirectAfterStoppingImpersonation($request);
|
||||
}
|
||||
}
|
||||
81
nova/src/Http/Controllers/LensActionController.php
Normal file
81
nova/src/Http/Controllers/LensActionController.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Actions\Action;
|
||||
use Laravel\Nova\Actions\ActionCollection;
|
||||
use Laravel\Nova\Http\Requests\LensActionRequest;
|
||||
use Laravel\Nova\Http\Requests\LensRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class LensActionController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the actions for the given resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\LensRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index(LensRequest $request)
|
||||
{
|
||||
$lens = $request->lens();
|
||||
|
||||
return response()->json(with([
|
||||
'actions' => $lens->availableActionsOnIndex($request),
|
||||
'pivotActions' => [
|
||||
'name' => Nova::humanize($request->pivotName()),
|
||||
'actions' => $lens->availablePivotActions($request),
|
||||
],
|
||||
'counts' => $lens->resolveActions($request)->countsByTypeOnIndex(),
|
||||
], function ($payload) use ($lens, $request) {
|
||||
$actionCounts = $lens->resolveActions($request)->countsByTypeOnIndex();
|
||||
$pivotActionCounts = ActionCollection::make($payload['pivotActions']['actions'])->countsByTypeOnIndex();
|
||||
|
||||
$payload['counts'] = [
|
||||
'standalone' => $actionCounts['standalone'] + $pivotActionCounts['standalone'],
|
||||
'resource' => $actionCounts['resource'] + $pivotActionCounts['resource'],
|
||||
];
|
||||
|
||||
return $payload;
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an action on the specified resources.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\LensActionRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(LensActionRequest $request)
|
||||
{
|
||||
$request->validateFields();
|
||||
|
||||
return $request->action()->handleRequest($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync an action field on the specified resources.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\LensActionRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function sync(LensActionRequest $request)
|
||||
{
|
||||
$action = $request->lens()->availableActions($request)
|
||||
->first(function ($action) use ($request) {
|
||||
return $action->uriKey() === $request->query('action');
|
||||
});
|
||||
|
||||
abort_unless($action instanceof Action, 404);
|
||||
|
||||
return response()->json(
|
||||
collect($action->fields($request))
|
||||
->filter(function ($field) use ($request) {
|
||||
return $request->query('field') === $field->attribute &&
|
||||
$request->query('component') === $field->dependentComponentKey();
|
||||
})->each->syncDependsOn($request)
|
||||
->first()
|
||||
);
|
||||
}
|
||||
}
|
||||
22
nova/src/Http/Controllers/LensCardController.php
Normal file
22
nova/src/Http/Controllers/LensCardController.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\LensCardRequest;
|
||||
|
||||
class LensCardController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the cards for the given lens.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\LensCardRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(LensCardRequest $request)
|
||||
{
|
||||
return response()->json(
|
||||
$request->availableCards()
|
||||
);
|
||||
}
|
||||
}
|
||||
34
nova/src/Http/Controllers/LensController.php
Normal file
34
nova/src/Http/Controllers/LensController.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\LensRequest;
|
||||
use Laravel\Nova\Http\Resources\LensViewResource;
|
||||
|
||||
class LensController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the lenses for the given resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\LensRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index(LensRequest $request)
|
||||
{
|
||||
return response()->json(
|
||||
$request->availableLenses()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified lens and its resources.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\LensRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function show(LensRequest $request)
|
||||
{
|
||||
return LensViewResource::make()->toResponse($request);
|
||||
}
|
||||
}
|
||||
26
nova/src/Http/Controllers/LensFilterController.php
Normal file
26
nova/src/Http/Controllers/LensFilterController.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
class LensFilterController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the lenses for the given resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index(NovaRequest $request)
|
||||
{
|
||||
$lenses = $request->newResource()->availableLenses($request);
|
||||
|
||||
$lens = $lenses->first(function ($lens) use ($request) {
|
||||
return $lens->uriKey() === $request->lens;
|
||||
});
|
||||
|
||||
return response()->json($lens->availableFilters($request));
|
||||
}
|
||||
}
|
||||
35
nova/src/Http/Controllers/LensMetricController.php
Normal file
35
nova/src/Http/Controllers/LensMetricController.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\LensMetricRequest;
|
||||
|
||||
class LensMetricController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the metrics for the given resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\LensMetricRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index(LensMetricRequest $request)
|
||||
{
|
||||
return response()->json(
|
||||
$request->availableMetrics()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified metric's value.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\LensMetricRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function show(LensMetricRequest $request)
|
||||
{
|
||||
return response()->json([
|
||||
'value' => $request->metric()->resolve($request),
|
||||
]);
|
||||
}
|
||||
}
|
||||
20
nova/src/Http/Controllers/LensResourceCountController.php
Normal file
20
nova/src/Http/Controllers/LensResourceCountController.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\LensCountRequest;
|
||||
|
||||
class LensResourceCountController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get the resource count for a given query.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\LensCountRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(LensCountRequest $request)
|
||||
{
|
||||
return response()->json(['count' => $request->toCount()]);
|
||||
}
|
||||
}
|
||||
43
nova/src/Http/Controllers/LensResourceDestroyController.php
Normal file
43
nova/src/Http/Controllers/LensResourceDestroyController.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Actions\Actionable;
|
||||
use Laravel\Nova\Http\Requests\DeleteLensResourceRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class LensResourceDestroyController extends Controller
|
||||
{
|
||||
use DeletesFields;
|
||||
|
||||
/**
|
||||
* Destroy the given resource(s).
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\DeleteLensResourceRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function __invoke(DeleteLensResourceRequest $request)
|
||||
{
|
||||
$request->chunks(150, function ($models) use ($request) {
|
||||
$models->each(function ($model) use ($request) {
|
||||
$this->deleteFields($request, $model);
|
||||
|
||||
if (in_array(Actionable::class, class_uses_recursive($model))) {
|
||||
$model->actions()->delete();
|
||||
}
|
||||
|
||||
$model->delete();
|
||||
|
||||
Nova::usingActionEvent(function ($actionEvent) use ($model, $request) {
|
||||
$actionEvent->insert(
|
||||
$actionEvent->forResourceDelete(Nova::user($request), collect([$model]))
|
||||
->map->getAttributes()->all()
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return response()->noContent(200);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Actions\Actionable;
|
||||
use Laravel\Nova\Http\Requests\ForceDeleteLensResourceRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class LensResourceForceDeleteController extends Controller
|
||||
{
|
||||
use DeletesFields;
|
||||
|
||||
/**
|
||||
* Force delete the given resource(s).
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ForceDeleteLensResourceRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function __invoke(ForceDeleteLensResourceRequest $request)
|
||||
{
|
||||
$request->chunks(150, function ($models) use ($request) {
|
||||
$models->each(function ($model) use ($request) {
|
||||
$this->forceDeleteFields($request, $model);
|
||||
|
||||
if (in_array(Actionable::class, class_uses_recursive($model))) {
|
||||
$model->actions()->delete();
|
||||
}
|
||||
|
||||
$model->forceDelete();
|
||||
|
||||
Nova::usingActionEvent(function ($actionEvent) use ($model, $request) {
|
||||
$actionEvent->insert(
|
||||
$actionEvent->forResourceDelete(Nova::user($request), collect([$model]))
|
||||
->map->getAttributes()->all()
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return response()->noContent(200);
|
||||
}
|
||||
}
|
||||
34
nova/src/Http/Controllers/LensResourceRestoreController.php
Normal file
34
nova/src/Http/Controllers/LensResourceRestoreController.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\RestoreLensResourceRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class LensResourceRestoreController extends Controller
|
||||
{
|
||||
/**
|
||||
* Force delete the given resource(s).
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\RestoreLensResourceRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function __invoke(RestoreLensResourceRequest $request)
|
||||
{
|
||||
$request->chunks(150, function ($models) use ($request) {
|
||||
$models->each(function ($model) use ($request) {
|
||||
$model->restore();
|
||||
|
||||
Nova::usingActionEvent(function ($actionEvent) use ($model, $request) {
|
||||
$actionEvent->insert(
|
||||
$actionEvent->forResourceRestore(Nova::user($request), collect([$model]))
|
||||
->map->getAttributes()->all()
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return response()->noContent(200);
|
||||
}
|
||||
}
|
||||
107
nova/src/Http/Controllers/LoginController.php
Normal file
107
nova/src/Http/Controllers/LoginController.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Inertia\Inertia;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class LoginController extends Controller
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Login Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller handles authenticating users for the application and
|
||||
| redirecting them to your home screen. The controller uses a trait
|
||||
| to conveniently provide its functionality to your applications.
|
||||
|
|
||||
*/
|
||||
|
||||
use AuthenticatesUsers;
|
||||
use ValidatesRequests;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('nova.guest:'.config('nova.guard'))->except('logout');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the application's login form.
|
||||
*
|
||||
* @return \Inertia\Response|\Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function showLoginForm()
|
||||
{
|
||||
if ($loginPath = config('nova.routes.login', false)) {
|
||||
return Inertia::location($loginPath);
|
||||
}
|
||||
|
||||
return Inertia::render('Nova.Login', []);
|
||||
}
|
||||
|
||||
/**
|
||||
* The user has been authenticated.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param mixed $user
|
||||
* @return mixed
|
||||
*/
|
||||
protected function authenticated(Request $request, $user)
|
||||
{
|
||||
$redirect = redirect()->intended($this->redirectPath($request));
|
||||
|
||||
return $request->wantsJson()
|
||||
? new JsonResponse([
|
||||
'redirect' => $redirect->getTargetUrl(),
|
||||
], 200)
|
||||
: $redirect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the user out of the application.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function logout(Request $request)
|
||||
{
|
||||
$this->guard()->logout();
|
||||
|
||||
$request->session()->invalidate();
|
||||
|
||||
return redirect()->intended($this->redirectPath($request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the post register / login redirect path.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return string
|
||||
*/
|
||||
public function redirectPath(Request $request)
|
||||
{
|
||||
return Nova::url(Nova::resolveInitialPath($request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the guard to be used during authentication.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Auth\StatefulGuard
|
||||
*/
|
||||
protected function guard()
|
||||
{
|
||||
return Auth::guard(config('nova.guard'));
|
||||
}
|
||||
}
|
||||
35
nova/src/Http/Controllers/MetricController.php
Normal file
35
nova/src/Http/Controllers/MetricController.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\MetricRequest;
|
||||
|
||||
class MetricController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the metrics for the given resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\MetricRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index(MetricRequest $request)
|
||||
{
|
||||
return response()->json(
|
||||
$request->availableMetrics()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified metric's value.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\MetricRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function show(MetricRequest $request)
|
||||
{
|
||||
return response()->json([
|
||||
'value' => $request->metric()->resolve($request),
|
||||
]);
|
||||
}
|
||||
}
|
||||
80
nova/src/Http/Controllers/MorphableController.php
Normal file
80
nova/src/Http/Controllers/MorphableController.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Contracts\RelatableField;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class MorphableController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the available morphable resources for a given resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return array
|
||||
*/
|
||||
public function __invoke(NovaRequest $request)
|
||||
{
|
||||
$relatedResource = Nova::resourceForKey($request->type);
|
||||
|
||||
abort_if(is_null($relatedResource), 403);
|
||||
|
||||
$field = $request->newResource()
|
||||
->availableFieldsOnIndexOrDetail($request)
|
||||
->whereInstanceOf(RelatableField::class)
|
||||
->findFieldByAttribute($request->field, function () {
|
||||
abort(404);
|
||||
})->applyDependsOn($request);
|
||||
|
||||
$withTrashed = $this->shouldIncludeTrashed(
|
||||
$request, $relatedResource
|
||||
);
|
||||
|
||||
$limit = $relatedResource::usesScout()
|
||||
? $relatedResource::$scoutSearchResults
|
||||
: $relatedResource::$relatableSearchResults;
|
||||
|
||||
$shouldReorderAssociatableValues = $field->shouldReorderAssociatableValues($request) && ! $relatedResource::usesScout();
|
||||
|
||||
return [
|
||||
'resources' => $field->buildMorphableQuery($request, $relatedResource, $withTrashed)
|
||||
->take($limit)
|
||||
->get()
|
||||
->mapInto($relatedResource)
|
||||
->filter->authorizedToAdd($request, $request->model())
|
||||
->map(function ($resource) use ($request, $field, $relatedResource) {
|
||||
return $field->formatMorphableResource($request, $resource, $relatedResource);
|
||||
})->when($shouldReorderAssociatableValues, function ($collection) {
|
||||
return $collection->sortBy('display');
|
||||
})->values(),
|
||||
'withTrashed' => $withTrashed,
|
||||
'softDeletes' => $relatedResource::softDeletes(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the query should include trashed models.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param string $associatedResource
|
||||
* @return bool
|
||||
*/
|
||||
protected function shouldIncludeTrashed(NovaRequest $request, $associatedResource)
|
||||
{
|
||||
if ($request->withTrashed === 'true') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$associatedModel = $associatedResource::newModel();
|
||||
|
||||
if ($request->current && empty($request->search) && $associatedResource::softDeletes()) {
|
||||
$associatedModel = $associatedModel->newQueryWithoutScopes()->find($request->current);
|
||||
|
||||
return $associatedModel ? $associatedModel->trashed() : false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use DateTime;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
class MorphedResourceAttachController extends ResourceAttachController
|
||||
{
|
||||
/**
|
||||
* Initialize a fresh pivot model for the relationship.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param \Illuminate\Database\Eloquent\Relations\MorphToMany $relationship
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Pivot
|
||||
*/
|
||||
protected function initializePivot(NovaRequest $request, $relationship)
|
||||
{
|
||||
$model = tap($request->findResourceOrFail(), function ($resource) use ($request) {
|
||||
abort_unless($resource->hasRelatableField($request, $request->viaRelationship), 404);
|
||||
})->model();
|
||||
|
||||
$parentKey = $request->resourceId;
|
||||
$relatedKey = $request->input($request->relatedResource);
|
||||
|
||||
$parentKeyName = $relationship->getParentKeyName();
|
||||
$relatedKeyName = $relationship->getRelatedKeyName();
|
||||
|
||||
if ($parentKeyName !== $request->model()->getKeyName()) {
|
||||
$parentKey = $request->findModelOrFail()->{$parentKeyName};
|
||||
}
|
||||
|
||||
if ($relatedKeyName !== $request->newRelatedResource()::newModel()->getKeyName()) {
|
||||
$relatedKey = $request->findRelatedModelOrFail()->{$relatedKeyName};
|
||||
}
|
||||
|
||||
($pivot = $relationship->newPivot($relationship->getDefaultPivotAttributes(), false))->forceFill([
|
||||
$relationship->getForeignPivotKeyName() => $parentKey,
|
||||
$relationship->getRelatedPivotKeyName() => $relatedKey,
|
||||
$relationship->getMorphType() => $model->{$request->viaRelationship}()->getMorphClass(),
|
||||
]);
|
||||
|
||||
if ($relationship->withTimestamps) {
|
||||
$pivot->forceFill([
|
||||
$relationship->createdAt() => new DateTime,
|
||||
$relationship->updatedAt() => new DateTime,
|
||||
]);
|
||||
}
|
||||
|
||||
return $pivot;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\NotificationRequest;
|
||||
use Laravel\Nova\Notifications\Notification;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class NotificationDeleteAllController extends Controller
|
||||
{
|
||||
/**
|
||||
* Delete all notifications.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(NotificationRequest $request)
|
||||
{
|
||||
Notification::whereNotifiableId(Nova::user($request)->getKey())->delete();
|
||||
|
||||
return response()->json();
|
||||
}
|
||||
}
|
||||
26
nova/src/Http/Controllers/NotificationDeleteController.php
Normal file
26
nova/src/Http/Controllers/NotificationDeleteController.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\NotificationRequest;
|
||||
use Laravel\Nova\Notifications\Notification;
|
||||
|
||||
class NotificationDeleteController extends Controller
|
||||
{
|
||||
/**
|
||||
* Mark the given notification as read.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NotificationRequest $request
|
||||
* @param int|string $notification
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(NotificationRequest $request, $notification)
|
||||
{
|
||||
$notification = Notification::findOrFail($notification);
|
||||
$notification->update(['read_at' => now()]);
|
||||
$notification->delete();
|
||||
|
||||
return response()->json();
|
||||
}
|
||||
}
|
||||
23
nova/src/Http/Controllers/NotificationIndexController.php
Normal file
23
nova/src/Http/Controllers/NotificationIndexController.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\NotificationRequest;
|
||||
|
||||
class NotificationIndexController extends Controller
|
||||
{
|
||||
/**
|
||||
* Return the details for the Dashboard.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NotificationRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(NotificationRequest $request)
|
||||
{
|
||||
return response()->json([
|
||||
'notifications' => $request->notifications(),
|
||||
'unread' => $request->unreadCount(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
24
nova/src/Http/Controllers/NotificationReadAllController.php
Normal file
24
nova/src/Http/Controllers/NotificationReadAllController.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\NotificationRequest;
|
||||
use Laravel\Nova\Notifications\Notification;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class NotificationReadAllController extends Controller
|
||||
{
|
||||
/**
|
||||
* Mark the given notification as read.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NotificationRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(NotificationRequest $request)
|
||||
{
|
||||
Notification::unread()->whereNotifiableId(Nova::user($request)->getKey())->update(['read_at' => now()]);
|
||||
|
||||
return response()->json();
|
||||
}
|
||||
}
|
||||
25
nova/src/Http/Controllers/NotificationReadController.php
Normal file
25
nova/src/Http/Controllers/NotificationReadController.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\NotificationRequest;
|
||||
use Laravel\Nova\Notifications\Notification;
|
||||
|
||||
class NotificationReadController extends Controller
|
||||
{
|
||||
/**
|
||||
* Mark the given notification as read.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NotificationRequest $request
|
||||
* @param int|string $notification
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(NotificationRequest $request, $notification)
|
||||
{
|
||||
$notification = Notification::findOrFail($notification);
|
||||
$notification->update(['read_at' => now()]);
|
||||
|
||||
return response()->json();
|
||||
}
|
||||
}
|
||||
25
nova/src/Http/Controllers/NotificationUnreadController.php
Normal file
25
nova/src/Http/Controllers/NotificationUnreadController.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\NotificationRequest;
|
||||
use Laravel\Nova\Notifications\Notification;
|
||||
|
||||
class NotificationUnreadController extends Controller
|
||||
{
|
||||
/**
|
||||
* Mark the given notification as unread.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NotificationRequest $request
|
||||
* @param int|string $notification
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(NotificationRequest $request, $notification)
|
||||
{
|
||||
$notification = Notification::findOrFail($notification);
|
||||
$notification->update(['read_at' => null]);
|
||||
|
||||
return response()->json();
|
||||
}
|
||||
}
|
||||
64
nova/src/Http/Controllers/Pages/AttachableController.php
Normal file
64
nova/src/Http/Controllers/Pages/AttachableController.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers\Pages;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Inertia\Inertia;
|
||||
use Laravel\Nova\Http\Requests\ResourceCreateOrAttachRequest;
|
||||
use Laravel\Nova\Menu\Breadcrumb;
|
||||
use Laravel\Nova\Menu\Breadcrumbs;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class AttachableController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show Resource Attach page using Inertia.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceCreateOrAttachRequest $request
|
||||
* @return \Inertia\Response
|
||||
*/
|
||||
public function __invoke(ResourceCreateOrAttachRequest $request)
|
||||
{
|
||||
$resourceClass = $request->resource();
|
||||
|
||||
$isPolymorphic = function ($query) {
|
||||
return is_null($query) || in_array($query, [true, 1, '1']);
|
||||
};
|
||||
|
||||
$parentResource = $request->findResourceOrFail();
|
||||
|
||||
return Inertia::render('Nova.Attach', [
|
||||
'breadcrumbs' => $this->breadcrumbs($request),
|
||||
'resourceName' => $resourceClass::uriKey(),
|
||||
'resourceId' => $request->resourceId,
|
||||
'relatedResourceName' => $request->relatedResource,
|
||||
'viaRelationship' => $request->query('viaRelationship'),
|
||||
'polymorphic' => $isPolymorphic($request->query('polymorphic')),
|
||||
'viaResource' => $parentResource::uriKey(),
|
||||
'viaResourceId' => $parentResource->resource->getKey(),
|
||||
'parentResource' => [
|
||||
'name' => $parentResource->singularLabel(),
|
||||
'display' => $parentResource->title(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get breadcrumb menu for the page.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceCreateOrAttachRequest $request
|
||||
* @return \Laravel\Nova\Menu\Breadcrumbs
|
||||
*/
|
||||
protected function breadcrumbs(ResourceCreateOrAttachRequest $request)
|
||||
{
|
||||
$resourceClass = $request->resource();
|
||||
$relatedResourceClass = $request->relatedResource();
|
||||
|
||||
return Breadcrumbs::make([
|
||||
Breadcrumb::make(Nova::__('Resources')),
|
||||
Breadcrumb::resource($resourceClass),
|
||||
Breadcrumb::resource($request->findResourceOrFail()),
|
||||
Breadcrumb::make(Nova::__('Attach :resource', ['resource' => $relatedResourceClass::singularLabel()])),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers\Pages;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Inertia\Inertia;
|
||||
use Laravel\Nova\Http\Requests\ResourceUpdateOrUpdateAttachedRequest;
|
||||
use Laravel\Nova\Menu\Breadcrumb;
|
||||
use Laravel\Nova\Menu\Breadcrumbs;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class AttachedResourceUpdateController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show Resource Update Attached page using Inertia.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceUpdateOrUpdateAttachedRequest $request
|
||||
* @return \Inertia\Response
|
||||
*/
|
||||
public function __invoke(ResourceUpdateOrUpdateAttachedRequest $request)
|
||||
{
|
||||
$resourceClass = $request->resource();
|
||||
|
||||
$isPolymorphic = function ($query) {
|
||||
return is_null($query) || in_array($query, [true, 1, '1']);
|
||||
};
|
||||
|
||||
$parentResource = $request->findResourceOrFail();
|
||||
|
||||
return Inertia::render('Nova.UpdateAttached', [
|
||||
'breadcrumbs' => $this->breadcrumbs($request),
|
||||
'resourceName' => $resourceClass::uriKey(),
|
||||
'resourceId' => $request->resourceId,
|
||||
'relatedResourceName' => $request->relatedResource,
|
||||
'relatedResourceId' => $request->relatedResourceId,
|
||||
'viaRelationship' => $request->query('viaRelationship'),
|
||||
'viaPivotId' => $request->query('viaPivotId'),
|
||||
'polymorphic' => $isPolymorphic($request->query('polymorphic')),
|
||||
'viaResource' => $parentResource::uriKey(),
|
||||
'viaResourceId' => $parentResource->resource->getKey(),
|
||||
'parentResource' => [
|
||||
'name' => $parentResource->singularLabel(),
|
||||
'display' => $parentResource->title(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get breadcrumb menu for the page.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceUpdateOrUpdateAttachedRequest $request
|
||||
* @return \Laravel\Nova\Menu\Breadcrumbs
|
||||
*/
|
||||
protected function breadcrumbs(ResourceUpdateOrUpdateAttachedRequest $request)
|
||||
{
|
||||
$resourceClass = $request->resource();
|
||||
$resource = $request->findResourceOrFail();
|
||||
$relatedResource = $request->findRelatedResourceOrFail($request->relatedResourceId);
|
||||
|
||||
return Breadcrumbs::make([
|
||||
Breadcrumb::make(Nova::__('Resources')),
|
||||
Breadcrumb::resource($resourceClass),
|
||||
Breadcrumb::resource($resource),
|
||||
Breadcrumb::make(Nova::__('Update attached :resource: :title', [
|
||||
'resource' => $relatedResource::singularLabel(),
|
||||
'title' => $relatedResource->title(),
|
||||
])),
|
||||
]);
|
||||
}
|
||||
}
|
||||
48
nova/src/Http/Controllers/Pages/DashboardController.php
Normal file
48
nova/src/Http/Controllers/Pages/DashboardController.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers\Pages;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Inertia\Inertia;
|
||||
use Laravel\Nova\Http\Requests\DashboardRequest;
|
||||
use Laravel\Nova\Http\Resources\DashboardViewResource;
|
||||
use Laravel\Nova\Menu\Breadcrumb;
|
||||
use Laravel\Nova\Menu\Breadcrumbs;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show Resource Create page using Inertia.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\DashboardRequest $request
|
||||
* @param string $name
|
||||
* @return \Illuminate\Http\RedirectResponse|\Inertia\Response
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
public function __invoke(DashboardRequest $request, $name = 'main')
|
||||
{
|
||||
DashboardViewResource::make($name)->authorizedDashboardForRequest($request);
|
||||
|
||||
return Inertia::render('Nova.Dashboard', [
|
||||
'breadcrumbs' => $this->breadcrumbs($request, $name),
|
||||
'name' => $name,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get breadcrumb menu for the page.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\DashboardRequest $request
|
||||
* @param string $name
|
||||
* @return \Laravel\Nova\Menu\Breadcrumbs
|
||||
*/
|
||||
protected function breadcrumbs(DashboardRequest $request, string $name)
|
||||
{
|
||||
return Breadcrumbs::make([
|
||||
Breadcrumb::make(Nova::__('Dashboards')),
|
||||
Breadcrumb::make(Nova::dashboardForKey($name, $request)->label()),
|
||||
]);
|
||||
}
|
||||
}
|
||||
20
nova/src/Http/Controllers/Pages/Error403Controller.php
Normal file
20
nova/src/Http/Controllers/Pages/Error403Controller.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers\Pages;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
|
||||
class Error403Controller extends Controller
|
||||
{
|
||||
/**
|
||||
* Show Nova 403 page using Inertia.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
|
||||
*/
|
||||
public function __invoke()
|
||||
{
|
||||
abort(403);
|
||||
}
|
||||
}
|
||||
20
nova/src/Http/Controllers/Pages/Error404Controller.php
Normal file
20
nova/src/Http/Controllers/Pages/Error404Controller.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers\Pages;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
|
||||
class Error404Controller extends Controller
|
||||
{
|
||||
/**
|
||||
* Show Nova 404 page using Inertia.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
public function __invoke()
|
||||
{
|
||||
abort(404);
|
||||
}
|
||||
}
|
||||
21
nova/src/Http/Controllers/Pages/HomeController.php
Normal file
21
nova/src/Http/Controllers/Pages/HomeController.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers\Pages;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class HomeController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show Nova homepage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function __invoke(Request $request)
|
||||
{
|
||||
return redirect(Nova::url(Nova::resolveInitialPath($request)));
|
||||
}
|
||||
}
|
||||
47
nova/src/Http/Controllers/Pages/LensController.php
Normal file
47
nova/src/Http/Controllers/Pages/LensController.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers\Pages;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Inertia\Inertia;
|
||||
use Laravel\Nova\Http\Requests\LensRequest;
|
||||
use Laravel\Nova\Http\Resources\LensViewResource;
|
||||
use Laravel\Nova\Menu\Breadcrumb;
|
||||
use Laravel\Nova\Menu\Breadcrumbs;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class LensController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show Resource Lens page using Inertia.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\LensRequest $request
|
||||
* @return \Inertia\Response
|
||||
*/
|
||||
public function __invoke(LensRequest $request)
|
||||
{
|
||||
$lens = LensViewResource::make()->authorizedLensForRequest($request);
|
||||
|
||||
return Inertia::render('Nova.Lens', [
|
||||
'breadcrumbs' => $this->breadcrumbs($request),
|
||||
'resourceName' => $request->route('resource'),
|
||||
'lens' => $lens->uriKey(),
|
||||
'searchable' => $lens::searchable(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get breadcrumb menu for the page.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\LensRequest $request
|
||||
* @return \Laravel\Nova\Menu\Breadcrumbs
|
||||
*/
|
||||
protected function breadcrumbs(LensRequest $request)
|
||||
{
|
||||
return Breadcrumbs::make([
|
||||
Breadcrumb::make(Nova::__('Resources')),
|
||||
Breadcrumb::resource($request->resource()),
|
||||
Breadcrumb::make($request->lens()->name()),
|
||||
]);
|
||||
}
|
||||
}
|
||||
58
nova/src/Http/Controllers/Pages/ResourceCreateController.php
Normal file
58
nova/src/Http/Controllers/Pages/ResourceCreateController.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers\Pages;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Inertia\Inertia;
|
||||
use Laravel\Nova\Http\Requests\ResourceCreateOrAttachRequest;
|
||||
use Laravel\Nova\Menu\Breadcrumb;
|
||||
use Laravel\Nova\Menu\Breadcrumbs;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class ResourceCreateController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show Resource Create page using Inertia.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceCreateOrAttachRequest $request
|
||||
* @return \Inertia\Response
|
||||
*/
|
||||
public function __invoke(ResourceCreateOrAttachRequest $request)
|
||||
{
|
||||
$resourceClass = $request->resource();
|
||||
|
||||
$resourceClass::authorizeToCreate($request);
|
||||
|
||||
return Inertia::render('Nova.Create', [
|
||||
'breadcrumbs' => $this->breadcrumbs($request),
|
||||
'resourceName' => $resourceClass::uriKey(),
|
||||
'viaResource' => $request->query('viaResource') ?? '',
|
||||
'viaResourceId' => $request->query('viaResourceId') ?? '',
|
||||
'viaRelationship' => $request->query('viaRelationship') ?? '',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get breadcrumb menu for the page.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceCreateOrAttachRequest $request
|
||||
* @return \Laravel\Nova\Menu\Breadcrumbs
|
||||
*/
|
||||
protected function breadcrumbs(ResourceCreateOrAttachRequest $request)
|
||||
{
|
||||
$resourceClass = $request->resource();
|
||||
|
||||
return Breadcrumbs::make(
|
||||
collect([Breadcrumb::make(Nova::__('Resources'))])->when($request->viaRelationship(), function ($breadcrumbs) use ($request) {
|
||||
return $breadcrumbs->push(
|
||||
Breadcrumb::resource($request->viaResource()),
|
||||
Breadcrumb::resource($request->findParentResourceOrFail())
|
||||
);
|
||||
}, function ($breadcrumbs) use ($resourceClass) {
|
||||
return $breadcrumbs->push(Breadcrumb::resource($resourceClass));
|
||||
})->push(
|
||||
Breadcrumb::make(Nova::__('Create :resource', ['resource' => $resourceClass::singularLabel()]))
|
||||
)->all()
|
||||
);
|
||||
}
|
||||
}
|
||||
54
nova/src/Http/Controllers/Pages/ResourceDetailController.php
Normal file
54
nova/src/Http/Controllers/Pages/ResourceDetailController.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers\Pages;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Inertia\Inertia;
|
||||
use Laravel\Nova\Http\Requests\ResourceDetailRequest;
|
||||
use Laravel\Nova\Http\Resources\DetailViewResource;
|
||||
use Laravel\Nova\Menu\Breadcrumb;
|
||||
use Laravel\Nova\Menu\Breadcrumbs;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class ResourceDetailController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show Resource Detail page using Inertia.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceDetailRequest $request
|
||||
* @return \Inertia\Response
|
||||
*/
|
||||
public function __invoke(ResourceDetailRequest $request)
|
||||
{
|
||||
$resourceClass = $request->resource();
|
||||
|
||||
return Inertia::render('Nova.Detail', [
|
||||
'breadcrumbs' => $this->breadcrumbs($request),
|
||||
'resourceName' => $resourceClass::uriKey(),
|
||||
'resourceId' => $request->resourceId,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get breadcrumb menu for the page.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceDetailRequest $request
|
||||
* @return \Laravel\Nova\Menu\Breadcrumbs
|
||||
*
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
protected function breadcrumbs(ResourceDetailRequest $request)
|
||||
{
|
||||
$resource = DetailViewResource::make()->authorizedResourceForRequest($request);
|
||||
|
||||
return Breadcrumbs::make([
|
||||
Breadcrumb::make(Nova::__('Resources')),
|
||||
Breadcrumb::resource($request->resource()),
|
||||
Breadcrumb::make(Nova::__(':resource Details: :title', [
|
||||
'resource' => $resource::singularLabel(),
|
||||
'title' => $resource->title(),
|
||||
])),
|
||||
]);
|
||||
}
|
||||
}
|
||||
44
nova/src/Http/Controllers/Pages/ResourceIndexController.php
Normal file
44
nova/src/Http/Controllers/Pages/ResourceIndexController.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers\Pages;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Inertia\Inertia;
|
||||
use Laravel\Nova\Http\Requests\ResourceIndexRequest;
|
||||
use Laravel\Nova\Http\Resources\IndexViewResource;
|
||||
use Laravel\Nova\Menu\Breadcrumb;
|
||||
use Laravel\Nova\Menu\Breadcrumbs;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class ResourceIndexController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show Resource Index page using Inertia.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceIndexRequest $request
|
||||
* @return \Inertia\Response
|
||||
*/
|
||||
public function __invoke(ResourceIndexRequest $request)
|
||||
{
|
||||
$resourceClass = IndexViewResource::make()->authorizedResourceForRequest($request);
|
||||
|
||||
return Inertia::render('Nova.Index', [
|
||||
'breadcrumbs' => $this->breadcrumbs($request),
|
||||
'resourceName' => $resourceClass::uriKey(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get breadcrumb menu for the page.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceIndexRequest $request
|
||||
* @return \Laravel\Nova\Menu\Breadcrumbs
|
||||
*/
|
||||
protected function breadcrumbs(ResourceIndexRequest $request)
|
||||
{
|
||||
return Breadcrumbs::make([
|
||||
Breadcrumb::make(Nova::__('Resources')),
|
||||
Breadcrumb::resource($request->resource()),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers\Pages;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Inertia\Inertia;
|
||||
use Laravel\Nova\Http\Requests\ResourceCreateOrAttachRequest;
|
||||
use Laravel\Nova\Menu\Breadcrumb;
|
||||
use Laravel\Nova\Menu\Breadcrumbs;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class ResourceReplicateController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show Resource Replicate page using Inertia.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceCreateOrAttachRequest $request
|
||||
* @return \Inertia\Response
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
public function __invoke(ResourceCreateOrAttachRequest $request)
|
||||
{
|
||||
abort_unless($request->findModelQuery()->exists(), 404);
|
||||
|
||||
$resourceClass = $request->resource();
|
||||
|
||||
return Inertia::render('Nova.Replicate', [
|
||||
'breadcrumbs' => $this->breadcrumbs($request),
|
||||
'resourceName' => $resourceClass::uriKey(),
|
||||
'resourceId' => $request->resourceId,
|
||||
'viaResource' => $request->query('viaResource') ?? '',
|
||||
'viaResourceId' => $request->query('viaResourceId') ?? '',
|
||||
'viaRelationship' => $request->query('viaRelationship') ?? '',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get breadcrumb menu for the page.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceCreateOrAttachRequest $request
|
||||
* @return \Laravel\Nova\Menu\Breadcrumbs
|
||||
*/
|
||||
protected function breadcrumbs(ResourceCreateOrAttachRequest $request)
|
||||
{
|
||||
$resourceClass = $request->resource();
|
||||
|
||||
return Breadcrumbs::make([
|
||||
Breadcrumb::make(Nova::__('Resources')),
|
||||
Breadcrumb::resource($resourceClass),
|
||||
Breadcrumb::resource($request->findResourceOrFail()),
|
||||
Breadcrumb::make(Nova::__('Replicate :resource', ['resource' => $resourceClass::singularLabel()])),
|
||||
]);
|
||||
}
|
||||
}
|
||||
67
nova/src/Http/Controllers/Pages/ResourceUpdateController.php
Normal file
67
nova/src/Http/Controllers/Pages/ResourceUpdateController.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers\Pages;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Inertia\Inertia;
|
||||
use Laravel\Nova\Http\Requests\ResourceUpdateOrUpdateAttachedRequest;
|
||||
use Laravel\Nova\Http\Resources\UpdateViewResource;
|
||||
use Laravel\Nova\Menu\Breadcrumb;
|
||||
use Laravel\Nova\Menu\Breadcrumbs;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class ResourceUpdateController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show Resource Update page using Inertia.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceUpdateOrUpdateAttachedRequest $request
|
||||
* @return \Inertia\Response
|
||||
*/
|
||||
public function __invoke(ResourceUpdateOrUpdateAttachedRequest $request)
|
||||
{
|
||||
abort_unless($request->findModelQuery()->exists(), 404);
|
||||
|
||||
$resourceClass = $request->resource();
|
||||
|
||||
return Inertia::render('Nova.Update', [
|
||||
'breadcrumbs' => $this->breadcrumb($request),
|
||||
'resourceName' => $resourceClass::uriKey(),
|
||||
'resourceId' => $request->resourceId,
|
||||
'viaResource' => $request->query('viaResource') ?? '',
|
||||
'viaResourceId' => $request->query('viaResourceId') ?? '',
|
||||
'viaRelationship' => $request->query('viaRelationship') ?? '',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get breadcrumb menu for the page.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceUpdateOrUpdateAttachedRequest $request
|
||||
* @return \Laravel\Nova\Menu\Breadcrumbs
|
||||
*
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
protected function breadcrumb(ResourceUpdateOrUpdateAttachedRequest $request)
|
||||
{
|
||||
$resourceClass = $request->resource();
|
||||
$resource = UpdateViewResource::make()->newResourceWith($request);
|
||||
|
||||
return Breadcrumbs::make(
|
||||
collect([Breadcrumb::make(Nova::__('Resources'))])->when($request->viaRelationship(), function ($breadcrumbs) use ($request) {
|
||||
return $breadcrumbs->push(
|
||||
Breadcrumb::resource($request->viaResource()),
|
||||
Breadcrumb::resource($request->findParentResource())
|
||||
);
|
||||
}, function ($breadcrumbs) use ($resourceClass, $resource) {
|
||||
return $breadcrumbs->push(
|
||||
Breadcrumb::resource($resourceClass),
|
||||
Breadcrumb::resource($resource),
|
||||
);
|
||||
})->push(
|
||||
Breadcrumb::make(Nova::__('Update :resource', ['resource' => $resourceClass::singularLabel()]))
|
||||
)->all()
|
||||
);
|
||||
}
|
||||
}
|
||||
35
nova/src/Http/Controllers/PivotFieldDestroyController.php
Normal file
35
nova/src/Http/Controllers/PivotFieldDestroyController.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\DeleteField;
|
||||
use Laravel\Nova\Http\Requests\PivotFieldDestroyRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class PivotFieldDestroyController extends Controller
|
||||
{
|
||||
/**
|
||||
* Delete the file at the given field.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\PivotFieldDestroyRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function __invoke(PivotFieldDestroyRequest $request)
|
||||
{
|
||||
$request->authorizeForAttachment();
|
||||
|
||||
DeleteField::forRequest(
|
||||
$request, $request->findFieldOrFail(),
|
||||
$pivot = $request->findPivotModel()
|
||||
)->save();
|
||||
|
||||
Nova::usingActionEvent(function ($actionEvent) use ($request, $pivot) {
|
||||
$actionEvent->forAttachedResourceUpdate(
|
||||
$request, $request->findModelOrFail(), $pivot
|
||||
)->save();
|
||||
});
|
||||
|
||||
return response()->noContent(200);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
class RelatableAuthorizationController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get the relatable authorization status for the resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return array
|
||||
*/
|
||||
public function __invoke(NovaRequest $request)
|
||||
{
|
||||
$parentResource = $request->findParentResourceOrFail();
|
||||
$resource = $request->resource();
|
||||
|
||||
if ($request->viaManyToMany()) {
|
||||
return ['authorized' => $parentResource->authorizedToAttachAny(
|
||||
$request, $request->model()
|
||||
)];
|
||||
}
|
||||
|
||||
return ['authorized' => $parentResource->authorizedToAdd(
|
||||
$request, $request->model()
|
||||
) && $resource::authorizedToCreate($request)];
|
||||
}
|
||||
}
|
||||
87
nova/src/Http/Controllers/ResetPasswordController.php
Normal file
87
nova/src/Http/Controllers/ResetPasswordController.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Inertia\Inertia;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class ResetPasswordController extends Controller
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Reset Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller is responsible for handling password reset requests
|
||||
| and uses a simple trait to include this behavior. You're free to
|
||||
| explore this trait and override any methods you wish to tweak.
|
||||
|
|
||||
*/
|
||||
|
||||
use ResetsPasswords;
|
||||
use ValidatesRequests;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('nova.guest:'.config('nova.guard'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the password reset view for the given token.
|
||||
*
|
||||
* If no token is present, display the link request form.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Inertia\Response
|
||||
*/
|
||||
public function showResetForm(Request $request)
|
||||
{
|
||||
$token = $request->route()->parameter('token');
|
||||
|
||||
return Inertia::render('Nova.ResetPassword', [
|
||||
'token' => $token,
|
||||
'email' => $request->email,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URI the user should be redirected to after resetting their password.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function redirectPath()
|
||||
{
|
||||
return Nova::path();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the broker to be used during password reset.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Auth\PasswordBroker
|
||||
*/
|
||||
public function broker()
|
||||
{
|
||||
return Password::broker(config('nova.passwords'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the guard to be used during password reset.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Auth\StatefulGuard
|
||||
*/
|
||||
protected function guard()
|
||||
{
|
||||
return Auth::guard(config('nova.guard'));
|
||||
}
|
||||
}
|
||||
150
nova/src/Http/Controllers/ResourceAttachController.php
Normal file
150
nova/src/Http/Controllers/ResourceAttachController.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use DateTime;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
use Throwable;
|
||||
|
||||
class ResourceAttachController extends Controller
|
||||
{
|
||||
use HandlesCustomRelationKeys;
|
||||
|
||||
/**
|
||||
* The action event for the action.
|
||||
*
|
||||
* @var \Laravel\Nova\Actions\ActionEvent|null
|
||||
*/
|
||||
protected $actionEvent;
|
||||
|
||||
/**
|
||||
* Attach a related resource to the given resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function __invoke(NovaRequest $request)
|
||||
{
|
||||
$resource = $request->resource();
|
||||
|
||||
$model = $request->findModelOrFail();
|
||||
|
||||
tap(new $resource($model), function ($resource) use ($request) {
|
||||
abort_unless($resource->hasRelatableField($request, $request->viaRelationship), 404);
|
||||
});
|
||||
|
||||
$this->validate($request, $model, $resource);
|
||||
|
||||
try {
|
||||
DB::connection($model->getConnectionName())->transaction(function () use ($request, $resource, $model) {
|
||||
[$pivot, $callbacks] = $resource::fillPivot(
|
||||
$request,
|
||||
$model,
|
||||
$this->initializePivot(
|
||||
$request,
|
||||
$model->{$request->viaRelationship}()
|
||||
)
|
||||
);
|
||||
|
||||
DB::transaction(function () use ($request, $model, $pivot) {
|
||||
Nova::usingActionEvent(function ($actionEvent) use ($request, $model, $pivot) {
|
||||
$this->actionEvent = $actionEvent->forAttachedResource($request, $model, $pivot);
|
||||
$this->actionEvent->save();
|
||||
});
|
||||
});
|
||||
|
||||
$pivot->save();
|
||||
|
||||
collect($callbacks)->each->__invoke();
|
||||
});
|
||||
|
||||
return response()->noContent(200);
|
||||
} catch (Throwable $e) {
|
||||
optional($this->actionEvent)->delete();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the attachment request.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param class-string<\Laravel\Nova\Resource> $resourceClass
|
||||
* @return void
|
||||
*/
|
||||
protected function validate(NovaRequest $request, $model, $resourceClass)
|
||||
{
|
||||
$attribute = $resourceClass::validationAttachableAttributeFor($request, $request->relatedResource);
|
||||
|
||||
tap($this->creationRules($request, $resourceClass), function ($rules) use ($resourceClass, $request, $attribute) {
|
||||
Validator::make($request->all(), $rules, [], $this->customRulesKeys($request, $attribute))->validate();
|
||||
|
||||
$resourceClass::validateForAttachment($request);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the validation rules used for the request. Correctly aasign the rules used
|
||||
* to the main attribute if the user has defined a custom relation key.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param class-string<\Laravel\Nova\Resource> $resourceClass
|
||||
* @return mixed
|
||||
*/
|
||||
protected function creationRules(NovaRequest $request, $resourceClass)
|
||||
{
|
||||
$rules = $resourceClass::creationRulesFor($request, $this->getRuleKey($request));
|
||||
|
||||
if ($this->usingCustomRelationKey($request)) {
|
||||
$rules[$request->relatedResource] = $rules[$request->viaRelationship];
|
||||
unset($rules[$request->viaRelationship]);
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a fresh pivot model for the relationship.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param \Illuminate\Database\Eloquent\Relations\BelongsToMany $relationship
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Pivot
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function initializePivot(NovaRequest $request, $relationship)
|
||||
{
|
||||
$parentKey = $request->resourceId;
|
||||
$relatedKey = $request->input($request->relatedResource);
|
||||
|
||||
$parentKeyName = $relationship->getParentKeyName();
|
||||
$relatedKeyName = $relationship->getRelatedKeyName();
|
||||
|
||||
if ($parentKeyName !== $request->model()->getKeyName()) {
|
||||
$parentKey = $request->findModelOrFail()->{$parentKeyName};
|
||||
}
|
||||
|
||||
if ($relatedKeyName !== $request->newRelatedResource()::newModel()->getKeyName()) {
|
||||
$relatedKey = $request->findRelatedModelOrFail()->{$relatedKeyName};
|
||||
}
|
||||
|
||||
($pivot = $relationship->newPivot($relationship->getDefaultPivotAttributes(), false))->forceFill([
|
||||
$relationship->getForeignPivotKeyName() => $parentKey,
|
||||
$relationship->getRelatedPivotKeyName() => $relatedKey,
|
||||
]);
|
||||
|
||||
if ($relationship->withTimestamps) {
|
||||
$pivot->forceFill([
|
||||
$relationship->createdAt() => new DateTime,
|
||||
$relationship->updatedAt() => new DateTime,
|
||||
]);
|
||||
}
|
||||
|
||||
return $pivot;
|
||||
}
|
||||
}
|
||||
20
nova/src/Http/Controllers/ResourceCountController.php
Normal file
20
nova/src/Http/Controllers/ResourceCountController.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\ResourceIndexRequest;
|
||||
|
||||
class ResourceCountController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get the resource count for a given query.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceIndexRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(ResourceIndexRequest $request)
|
||||
{
|
||||
return response()->json(['count' => $request->toCount()]);
|
||||
}
|
||||
}
|
||||
55
nova/src/Http/Controllers/ResourceDestroyController.php
Normal file
55
nova/src/Http/Controllers/ResourceDestroyController.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Actions\Actionable;
|
||||
use Laravel\Nova\Http\Requests\DeleteResourceRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
use Laravel\Nova\URL;
|
||||
|
||||
class ResourceDestroyController extends Controller
|
||||
{
|
||||
use DeletesFields;
|
||||
|
||||
/**
|
||||
* Destroy the given resource(s).
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\DeleteResourceRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
|
||||
*/
|
||||
public function __invoke(DeleteResourceRequest $request)
|
||||
{
|
||||
$request->chunks(150, function ($models) use ($request) {
|
||||
$models->each(function ($model) use ($request) {
|
||||
$this->deleteFields($request, $model);
|
||||
|
||||
$uses = class_uses_recursive($model);
|
||||
|
||||
if (in_array(Actionable::class, $uses) && ! in_array(SoftDeletes::class, $uses)) {
|
||||
$model->actions()->delete();
|
||||
}
|
||||
|
||||
$model->delete();
|
||||
|
||||
$request->resource()::afterDelete($request, $model);
|
||||
|
||||
Nova::usingActionEvent(function ($actionEvent) use ($model, $request) {
|
||||
$actionEvent->insert(
|
||||
$actionEvent->forResourceDelete(Nova::user($request), collect([$model]))
|
||||
->map->getAttributes()->all()
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
if ($request->isForSingleResource() && ! is_null($redirect = $request->resource()::redirectAfterDelete($request))) {
|
||||
return response()->json([
|
||||
'redirect' => URL::make($redirect),
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->noContent(200);
|
||||
}
|
||||
}
|
||||
94
nova/src/Http/Controllers/ResourceDetachController.php
Normal file
94
nova/src/Http/Controllers/ResourceDetachController.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Contracts\Deletable;
|
||||
use Laravel\Nova\DeleteField;
|
||||
use Laravel\Nova\Http\Requests\DetachResourceRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class ResourceDetachController extends Controller
|
||||
{
|
||||
/**
|
||||
* Detach the given resource(s).
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\DetachResourceRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function __invoke(DetachResourceRequest $request)
|
||||
{
|
||||
$parent = tap($request->findParentResourceOrFail(), function ($resource) use ($request) {
|
||||
abort_unless($resource->hasRelatableField($request, $request->viaRelationship), 409);
|
||||
})->model();
|
||||
|
||||
$relation = $parent->{$request->viaRelationship}();
|
||||
|
||||
$accessor = $relation->getPivotAccessor();
|
||||
|
||||
$accessorKeyName = transform($relation->getPivotClass(), function ($pivotClass) {
|
||||
return (new $pivotClass())->getKeyName();
|
||||
});
|
||||
|
||||
$inPivots = $request->resources !== 'all' ? $request->pivots : null;
|
||||
|
||||
$request->chunks(150, function ($models) use ($accessor, $accessorKeyName, $inPivots, $parent, $request) {
|
||||
foreach ($models as $model) {
|
||||
$pivot = $model->{$accessor};
|
||||
|
||||
if (empty($inPivots) || in_array($pivot->getAttribute($accessorKeyName), $inPivots)) {
|
||||
$this->deletePivot(
|
||||
$request, $pivot, $model, $parent
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return response()->noContent(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete pivot relations from model.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\DetachResourceRequest $request
|
||||
* @param \Illuminate\Database\Eloquent\Model $pivot
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @return void
|
||||
*/
|
||||
protected function deletePivot(DetachResourceRequest $request, $pivot, $model, $parent)
|
||||
{
|
||||
$this->deletePivotFields(
|
||||
$request, $resource = $request->newResourceWith($model), $pivot
|
||||
);
|
||||
|
||||
$pivot->delete();
|
||||
|
||||
Nova::usingActionEvent(function ($actionEvent) use ($pivot, $model, $parent, $request) {
|
||||
$actionEvent->insert(
|
||||
$actionEvent->forResourceDetach(
|
||||
Nova::user($request), $parent, collect([$model]), $pivot->getMorphClass()
|
||||
)->map->getAttributes()->all()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the pivot fields on the given pivot model.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\DetachResourceRequest $request
|
||||
* @param \Laravel\Nova\Resource $resource
|
||||
* @param \Illuminate\Database\Eloquent\Model $pivot
|
||||
* @return void
|
||||
*/
|
||||
protected function deletePivotFields(DetachResourceRequest $request, $resource, $pivot)
|
||||
{
|
||||
$resource->resolvePivotFields($request, $request->viaResource)
|
||||
->whereInstanceOf(Deletable::class)
|
||||
->filter->isPrunable()
|
||||
->each(function ($field) use ($request, $pivot) {
|
||||
/** @var \Laravel\Nova\Fields\Field&\Laravel\Nova\Contracts\Deletable $field */
|
||||
DeleteField::forRequest($request, $field, $pivot)->save();
|
||||
});
|
||||
}
|
||||
}
|
||||
51
nova/src/Http/Controllers/ResourceForceDeleteController.php
Normal file
51
nova/src/Http/Controllers/ResourceForceDeleteController.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Actions\Actionable;
|
||||
use Laravel\Nova\Http\Requests\ForceDeleteResourceRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class ResourceForceDeleteController extends Controller
|
||||
{
|
||||
use DeletesFields;
|
||||
|
||||
/**
|
||||
* Force delete the given resource(s).
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ForceDeleteResourceRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
|
||||
*/
|
||||
public function __invoke(ForceDeleteResourceRequest $request)
|
||||
{
|
||||
$request->chunks(150, function ($models) use ($request) {
|
||||
$models->each(function ($model) use ($request) {
|
||||
$this->forceDeleteFields($request, $model);
|
||||
|
||||
if (in_array(Actionable::class, class_uses_recursive($model))) {
|
||||
$model->actions()->delete();
|
||||
}
|
||||
|
||||
$model->forceDelete();
|
||||
|
||||
$request->resource()::afterForceDelete($request, $model);
|
||||
|
||||
Nova::usingActionEvent(function ($actionEvent) use ($model, $request) {
|
||||
$actionEvent->insert(
|
||||
$actionEvent->forResourceDelete(Nova::user($request), collect([$model]))
|
||||
->map->getAttributes()->all()
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
if ($request->isForSingleResource() && ! is_null($redirect = $request->resource()::redirectAfterDelete($request))) {
|
||||
return response()->json([
|
||||
'redirect' => $redirect,
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->noContent(200);
|
||||
}
|
||||
}
|
||||
21
nova/src/Http/Controllers/ResourceIndexController.php
Normal file
21
nova/src/Http/Controllers/ResourceIndexController.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\ResourceIndexRequest;
|
||||
use Laravel\Nova\Http\Resources\IndexViewResource;
|
||||
|
||||
class ResourceIndexController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the resources for administration.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceIndexRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(ResourceIndexRequest $request)
|
||||
{
|
||||
return IndexViewResource::make()->toResponse($request);
|
||||
}
|
||||
}
|
||||
30
nova/src/Http/Controllers/ResourcePeekController.php
Normal file
30
nova/src/Http/Controllers/ResourcePeekController.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\ResourcePeekRequest;
|
||||
|
||||
class ResourcePeekController extends Controller
|
||||
{
|
||||
/**
|
||||
* Preview the resource for administration.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourcePeekRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(ResourcePeekRequest $request)
|
||||
{
|
||||
$resource = $request->newResourceWith(tap($request->findModelQuery(), function ($query) use ($request) {
|
||||
$resource = $request->resource();
|
||||
$resource::detailQuery($request, $query);
|
||||
})->firstOrFail());
|
||||
|
||||
$resource->authorizeToView($request);
|
||||
|
||||
return response()->json([
|
||||
'title' => (string) $resource->title(),
|
||||
'resource' => $resource->serializeForPeeking($request),
|
||||
]);
|
||||
}
|
||||
}
|
||||
30
nova/src/Http/Controllers/ResourcePreviewController.php
Normal file
30
nova/src/Http/Controllers/ResourcePreviewController.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\ResourcePreviewRequest;
|
||||
|
||||
class ResourcePreviewController extends Controller
|
||||
{
|
||||
/**
|
||||
* Preview the resource for administration.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourcePreviewRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(ResourcePreviewRequest $request)
|
||||
{
|
||||
$resource = $request->newResourceWith(tap($request->findModelQuery(), function ($query) use ($request) {
|
||||
$resource = $request->resource();
|
||||
$resource::detailQuery($request, $query);
|
||||
})->firstOrFail());
|
||||
|
||||
$resource->authorizeToView($request);
|
||||
|
||||
return response()->json([
|
||||
'title' => (string) $resource->title(),
|
||||
'resource' => $resource->serializeForPreview($request),
|
||||
]);
|
||||
}
|
||||
}
|
||||
36
nova/src/Http/Controllers/ResourceRestoreController.php
Normal file
36
nova/src/Http/Controllers/ResourceRestoreController.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\RestoreResourceRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class ResourceRestoreController extends Controller
|
||||
{
|
||||
/**
|
||||
* Restore the given resource(s).
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\RestoreResourceRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function __invoke(RestoreResourceRequest $request)
|
||||
{
|
||||
$request->chunks(150, function ($models) use ($request) {
|
||||
$models->each(function ($model) use ($request) {
|
||||
$model->restore();
|
||||
|
||||
$request->resource()::afterRestore($request, $model);
|
||||
|
||||
Nova::usingActionEvent(function ($actionEvent) use ($model, $request) {
|
||||
$actionEvent->insert(
|
||||
$actionEvent->forResourceRestore(Nova::user($request), collect([$model]))
|
||||
->map->getAttributes()->all()
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return response()->noContent(200);
|
||||
}
|
||||
}
|
||||
78
nova/src/Http/Controllers/ResourceSearchController.php
Normal file
78
nova/src/Http/Controllers/ResourceSearchController.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Http\Requests\ResourceSearchRequest;
|
||||
use Laravel\Nova\Resource;
|
||||
use Laravel\Nova\Util;
|
||||
|
||||
class ResourceSearchController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the resources for administration.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceSearchRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(ResourceSearchRequest $request)
|
||||
{
|
||||
$resource = $request->resource();
|
||||
|
||||
$withTrashed = $this->shouldIncludeTrashed(
|
||||
$request, $resource
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'resources' => $request->searchIndex()
|
||||
->mapInto($resource)
|
||||
->map(function ($resource) use ($request) {
|
||||
return $this->transformResult($request, $resource);
|
||||
})->values(),
|
||||
'softDeletes' => $resource::softDeletes(),
|
||||
'withTrashed' => $withTrashed,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the query should include trashed models.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param string $resource
|
||||
* @return bool
|
||||
*/
|
||||
protected function shouldIncludeTrashed(NovaRequest $request, $resource)
|
||||
{
|
||||
if ($request->withTrashed === 'true') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$model = $resource::newModel();
|
||||
|
||||
if ($request->current && empty($request->search) && $resource::softDeletes()) {
|
||||
$model = $model->newQueryWithoutScopes()->find($request->current);
|
||||
|
||||
return $model ? $model->trashed() : false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the result from resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @param \Laravel\Nova\Resource $resource
|
||||
* @return array
|
||||
*/
|
||||
protected function transformResult(NovaRequest $request, Resource $resource)
|
||||
{
|
||||
return array_filter([
|
||||
'avatar' => $resource->resolveAvatarUrl($request),
|
||||
'display' => (string) $resource->title(),
|
||||
'subtitle' => $resource->subtitle(),
|
||||
'value' => Util::safeInt($resource->getKey()),
|
||||
]);
|
||||
}
|
||||
}
|
||||
21
nova/src/Http/Controllers/ResourceShowController.php
Normal file
21
nova/src/Http/Controllers/ResourceShowController.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\ResourceDetailRequest;
|
||||
use Laravel\Nova\Http\Resources\DetailViewResource;
|
||||
|
||||
class ResourceShowController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the resource for administration.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceDetailRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(ResourceDetailRequest $request)
|
||||
{
|
||||
return DetailViewResource::make()->toResponse($request);
|
||||
}
|
||||
}
|
||||
98
nova/src/Http/Controllers/ResourceStoreController.php
Normal file
98
nova/src/Http/Controllers/ResourceStoreController.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Laravel\Nova\Actions\ActionEvent;
|
||||
use Laravel\Nova\Exceptions\ResourceSaveCancelledException;
|
||||
use Laravel\Nova\Http\Requests\CreateResourceRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
use Laravel\Nova\URL;
|
||||
use Throwable;
|
||||
|
||||
class ResourceStoreController extends Controller
|
||||
{
|
||||
/**
|
||||
* The action event for the action.
|
||||
*
|
||||
* @var \Laravel\Nova\Actions\ActionEvent|null
|
||||
*/
|
||||
protected $actionEvent;
|
||||
|
||||
/**
|
||||
* Create a new resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\CreateResourceRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(CreateResourceRequest $request)
|
||||
{
|
||||
/** @var \Laravel\Nova\Resource $resource */
|
||||
$resource = $request->resource();
|
||||
|
||||
$resource::authorizeToCreate($request);
|
||||
|
||||
$resource::validateForCreation($request);
|
||||
|
||||
try {
|
||||
$model = DB::connection($resource::newModel()->getConnectionName())->transaction(function () use ($request, $resource) {
|
||||
[$model, $callbacks] = $resource::fill(
|
||||
$request, $resource::newModel()
|
||||
);
|
||||
|
||||
if ($this->storeResource($request, $model) === false) {
|
||||
throw new ResourceSaveCancelledException();
|
||||
}
|
||||
|
||||
DB::transaction(function () use ($request, $model) {
|
||||
Nova::usingActionEvent(function (ActionEvent $actionEvent) use ($request, $model) {
|
||||
$this->actionEvent = $actionEvent->forResourceCreate(Nova::user($request), $model);
|
||||
$this->actionEvent->save();
|
||||
});
|
||||
});
|
||||
|
||||
collect($callbacks)->each->__invoke();
|
||||
|
||||
$resource::afterCreate($request, $model);
|
||||
|
||||
return $model;
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'id' => $model->getKey(),
|
||||
'resource' => $model->attributesToArray(),
|
||||
'redirect' => URL::make($resource::redirectAfterCreate($request, $request->newResourceWith($model))),
|
||||
], 201);
|
||||
} catch (Throwable $e) {
|
||||
optional($this->actionEvent)->delete();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\CreateResourceRequest $request
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return bool
|
||||
*/
|
||||
protected function storeResource(CreateResourceRequest $request, Model $model)
|
||||
{
|
||||
if (! $request->viaRelationship()) {
|
||||
return $model->save();
|
||||
}
|
||||
|
||||
$relation = tap($request->findParentResourceOrFail(), function ($resource) use ($request) {
|
||||
abort_unless($resource->hasRelatableField($request, $request->viaRelationship), 404);
|
||||
})->model()->{$request->viaRelationship}();
|
||||
|
||||
if ($relation instanceof HasManyThrough) {
|
||||
return $model->save();
|
||||
}
|
||||
|
||||
return $relation->save($model);
|
||||
}
|
||||
}
|
||||
109
nova/src/Http/Controllers/ResourceUpdateController.php
Normal file
109
nova/src/Http/Controllers/ResourceUpdateController.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Laravel\Nova\Exceptions\ResourceSaveCancelledException;
|
||||
use Laravel\Nova\Http\Requests\UpdateResourceRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
use Laravel\Nova\URL;
|
||||
use Laravel\Nova\Util;
|
||||
use Throwable;
|
||||
|
||||
class ResourceUpdateController extends Controller
|
||||
{
|
||||
/**
|
||||
* The action event for the action.
|
||||
*
|
||||
* @var \Laravel\Nova\Actions\ActionEvent|null
|
||||
*/
|
||||
protected $actionEvent;
|
||||
|
||||
/**
|
||||
* Create a new resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\UpdateResourceRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Illuminate\Http\Exceptions\HttpResponseException
|
||||
*/
|
||||
public function __invoke(UpdateResourceRequest $request)
|
||||
{
|
||||
$model = $request->findModelQuery()->lockForUpdate()->firstOrFail();
|
||||
|
||||
try {
|
||||
[$model, $resource] = DB::connection($model->getConnectionName())->transaction(function () use ($request, $model) {
|
||||
$resource = $request->newResourceWith($model);
|
||||
$resource->authorizeToUpdate($request);
|
||||
$resource::validateForUpdate($request, $resource);
|
||||
|
||||
if ($this->modelHasBeenUpdatedSinceRetrieval($request, $model)) {
|
||||
response('', 409)->throwResponse();
|
||||
}
|
||||
|
||||
[$model, $callbacks] = $resource::fillForUpdate($request, $model);
|
||||
|
||||
DB::transaction(function () use ($request, $model) {
|
||||
Nova::usingActionEvent(function ($actionEvent) use ($request, $model) {
|
||||
$this->actionEvent = $actionEvent->forResourceUpdate(Nova::user($request), $model);
|
||||
$this->actionEvent->save();
|
||||
});
|
||||
});
|
||||
|
||||
if ($model->save() === false) {
|
||||
throw new ResourceSaveCancelledException;
|
||||
}
|
||||
|
||||
collect($callbacks)->each->__invoke();
|
||||
|
||||
$resource::afterUpdate($request, $model);
|
||||
|
||||
return [$model, $resource];
|
||||
});
|
||||
|
||||
tap(Nova::user($request), function ($user) use ($model) {
|
||||
if (get_class($model) === Util::userModel() && $model->is($user)) {
|
||||
$user->refresh();
|
||||
}
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'id' => $model->getKey(),
|
||||
'resource' => $model->attributesToArray(),
|
||||
'redirect' => URL::make($resource::redirectAfterUpdate($request, $resource)),
|
||||
]);
|
||||
} catch (Throwable $e) {
|
||||
optional($this->actionEvent)->delete();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the model has been updated since it was retrieved.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\UpdateResourceRequest $request
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return bool
|
||||
*/
|
||||
protected function modelHasBeenUpdatedSinceRetrieval(UpdateResourceRequest $request, $model)
|
||||
{
|
||||
$resource = $request->newResource();
|
||||
|
||||
// Check to see whether Traffic Cop is enabled for this resource...
|
||||
if ($resource::trafficCop($request) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$column = $model->getUpdatedAtColumn();
|
||||
|
||||
if (! ($model->usesTimestamps() && $model->{$column})) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $request->input('_retrieved_at') && $model->{$column}->gt(
|
||||
Carbon::createFromTimestamp($request->input('_retrieved_at'))
|
||||
);
|
||||
}
|
||||
}
|
||||
30
nova/src/Http/Controllers/ScriptController.php
Normal file
30
nova/src/Http/Controllers/ScriptController.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class ScriptController extends Controller
|
||||
{
|
||||
/**
|
||||
* Serve the requested script.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return \Laravel\Nova\Script
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
public function __invoke(NovaRequest $request)
|
||||
{
|
||||
$asset = collect(Nova::allScripts())
|
||||
->filter(function ($asset) use ($request) {
|
||||
return $asset->name() === $request->script;
|
||||
})->first();
|
||||
|
||||
abort_if(is_null($asset), 404);
|
||||
|
||||
return $asset;
|
||||
}
|
||||
}
|
||||
24
nova/src/Http/Controllers/SearchController.php
Normal file
24
nova/src/Http/Controllers/SearchController.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\GlobalSearch;
|
||||
use Laravel\Nova\Http\Requests\GlobalSearchRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class SearchController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get the global search results for the given query.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\GlobalSearchRequest $request
|
||||
* @return array
|
||||
*/
|
||||
public function __invoke(GlobalSearchRequest $request)
|
||||
{
|
||||
return (new GlobalSearch(
|
||||
$request, Nova::globallySearchableResources($request)
|
||||
))->get();
|
||||
}
|
||||
}
|
||||
22
nova/src/Http/Controllers/SoftDeleteStatusController.php
Normal file
22
nova/src/Http/Controllers/SoftDeleteStatusController.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
class SoftDeleteStatusController extends Controller
|
||||
{
|
||||
/**
|
||||
* Determine if the resource is soft deleting.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(NovaRequest $request)
|
||||
{
|
||||
$resource = $request->resource();
|
||||
|
||||
return response()->json(['softDeletes' => $resource::softDeletes()]);
|
||||
}
|
||||
}
|
||||
30
nova/src/Http/Controllers/StyleController.php
Normal file
30
nova/src/Http/Controllers/StyleController.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class StyleController extends Controller
|
||||
{
|
||||
/**
|
||||
* Serve the requested stylesheet.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
|
||||
* @return \Laravel\Nova\Style
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
public function __invoke(NovaRequest $request)
|
||||
{
|
||||
$asset = collect(Nova::allStyles())
|
||||
->filter(function ($asset) use ($request) {
|
||||
return $asset->name() === $request->style;
|
||||
})->first();
|
||||
|
||||
abort_if(is_null($asset), 404);
|
||||
|
||||
return $asset;
|
||||
}
|
||||
}
|
||||
41
nova/src/Http/Controllers/UpdateFieldController.php
Normal file
41
nova/src/Http/Controllers/UpdateFieldController.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\ResourceUpdateOrUpdateAttachedRequest;
|
||||
use Laravel\Nova\Http\Resources\UpdateViewResource;
|
||||
|
||||
class UpdateFieldController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the update fields for the given resource.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceUpdateOrUpdateAttachedRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(ResourceUpdateOrUpdateAttachedRequest $request)
|
||||
{
|
||||
return UpdateViewResource::make()->toResponse($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize the field for updating.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceUpdateOrUpdateAttachedRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function sync(ResourceUpdateOrUpdateAttachedRequest $request)
|
||||
{
|
||||
$resource = UpdateViewResource::make()->newResourceWith($request);
|
||||
|
||||
return response()->json(
|
||||
$resource->updateFields($request)
|
||||
->filter(function ($field) use ($request) {
|
||||
return $request->query('field') === $field->attribute &&
|
||||
$request->query('component') === $field->dependentComponentKey();
|
||||
})->each->syncDependsOn($request)
|
||||
->first()
|
||||
);
|
||||
}
|
||||
}
|
||||
42
nova/src/Http/Controllers/UpdatePivotFieldController.php
Normal file
42
nova/src/Http/Controllers/UpdatePivotFieldController.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller;
|
||||
use Laravel\Nova\Http\Requests\ResourceUpdateOrUpdateAttachedRequest;
|
||||
use Laravel\Nova\Http\Resources\UpdatePivotFieldResource;
|
||||
|
||||
class UpdatePivotFieldController extends Controller
|
||||
{
|
||||
/**
|
||||
* List the pivot fields for the given resource and relation.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceUpdateOrUpdateAttachedRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(ResourceUpdateOrUpdateAttachedRequest $request)
|
||||
{
|
||||
return UpdatePivotFieldResource::make()->toResponse($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize the pivot field for updating.
|
||||
*
|
||||
* @param \Laravel\Nova\Http\Requests\ResourceUpdateOrUpdateAttachedRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function sync(ResourceUpdateOrUpdateAttachedRequest $request)
|
||||
{
|
||||
$resource = UpdatePivotFieldResource::make()->newResourceWith($request);
|
||||
|
||||
return response()->json(
|
||||
$resource->updatePivotFields(
|
||||
$request, $request->relatedResource
|
||||
)->filter(function ($field) use ($request) {
|
||||
return $request->query('field') === $field->attribute &&
|
||||
$request->query('component') === $field->dependentComponentKey();
|
||||
})->applyDependsOn($request)
|
||||
->first()
|
||||
);
|
||||
}
|
||||
}
|
||||
36
nova/src/Http/Middleware/Authenticate.php
Normal file
36
nova/src/Http/Middleware/Authenticate.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use Illuminate\Auth\Middleware\Authenticate as BaseAuthenticationMiddleware;
|
||||
use Laravel\Nova\Exceptions\AuthenticationException as NovaAuthenticationException;
|
||||
|
||||
class Authenticate extends BaseAuthenticationMiddleware
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure(\Illuminate\Http\Request):mixed $next
|
||||
* @param string[] ...$guards
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Auth\AuthenticationException
|
||||
*/
|
||||
public function handle($request, Closure $next, ...$guards)
|
||||
{
|
||||
try {
|
||||
$guard = config('nova.guard');
|
||||
|
||||
if (! empty($guard)) {
|
||||
$guards[] = $guard;
|
||||
}
|
||||
|
||||
return parent::handle($request, $next, ...$guards);
|
||||
} catch (AuthenticationException $e) {
|
||||
throw new NovaAuthenticationException('Unauthenticated.', $e->guards());
|
||||
}
|
||||
}
|
||||
}
|
||||
20
nova/src/Http/Middleware/Authorize.php
Normal file
20
nova/src/Http/Middleware/Authorize.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Middleware;
|
||||
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class Authorize
|
||||
{
|
||||
/**
|
||||
* Handle the incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure(\Illuminate\Http\Request):mixed $next
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function handle($request, $next)
|
||||
{
|
||||
return Nova::check($request) ? $next($request) : abort(403);
|
||||
}
|
||||
}
|
||||
22
nova/src/Http/Middleware/BootTools.php
Normal file
22
nova/src/Http/Middleware/BootTools.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Middleware;
|
||||
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class BootTools
|
||||
{
|
||||
/**
|
||||
* Handle the incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure(\Illuminate\Http\Request):mixed $next
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function handle($request, $next)
|
||||
{
|
||||
Nova::bootTools($request);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
41
nova/src/Http/Middleware/DispatchServingNovaEvent.php
Normal file
41
nova/src/Http/Middleware/DispatchServingNovaEvent.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Middleware;
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Laravel\Nova\Events\ServingNova;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
|
||||
class DispatchServingNovaEvent
|
||||
{
|
||||
/**
|
||||
* Handle the incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure(\Illuminate\Http\Request):mixed $next
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function handle($request, $next)
|
||||
{
|
||||
$preventsAccessingMissingAttributes = method_exists(Model::class, 'preventsAccessingMissingAttributes')
|
||||
? Model::preventsAccessingMissingAttributes()
|
||||
: null;
|
||||
|
||||
if ($preventsAccessingMissingAttributes === true) {
|
||||
Model::preventAccessingMissingAttributes(false);
|
||||
}
|
||||
|
||||
ServingNova::dispatch($request);
|
||||
|
||||
Container::getInstance()->forgetInstance(NovaRequest::class);
|
||||
|
||||
$response = $next($request);
|
||||
|
||||
if ($preventsAccessingMissingAttributes === true) {
|
||||
Model::preventAccessingMissingAttributes(true);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
75
nova/src/Http/Middleware/HandleInertiaRequests.php
Normal file
75
nova/src/Http/Middleware/HandleInertiaRequests.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Inertia\Middleware;
|
||||
use Laravel\Nova\Http\Resources\UserResource;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class HandleInertiaRequests extends Middleware
|
||||
{
|
||||
/**
|
||||
* The root template that's loaded on the first page visit.
|
||||
*
|
||||
* @see https://inertiajs.com/server-side-setup#root-template
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rootView = 'nova::layout';
|
||||
|
||||
/**
|
||||
* Determines the current asset version.
|
||||
*
|
||||
* @see https://inertiajs.com/asset-versioning
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return string|null
|
||||
*/
|
||||
public function version(Request $request)
|
||||
{
|
||||
return sprintf('%s:%s', $this->rootView, parent::version($request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the props that are shared by default.
|
||||
*
|
||||
* @see https://inertiajs.com/shared-data
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function share(Request $request)
|
||||
{
|
||||
return array_merge(parent::share($request), [
|
||||
'novaConfig' => function () use ($request) {
|
||||
return Nova::jsonVariables($request);
|
||||
},
|
||||
'currentUser' => function () use ($request) {
|
||||
return with(Nova::user($request), function ($user) use ($request) {
|
||||
return ! is_null($user) ? UserResource::make($user)->toArray($request) : null;
|
||||
});
|
||||
},
|
||||
'validLicense' => function () use ($request) {
|
||||
return with(Nova::user($request), function ($user) {
|
||||
return ! is_null($user) ? Nova::checkLicenseValidity() : Cache::get('nova_valid_license_key');
|
||||
});
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the incoming request.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
Config::set('inertia.ssr.enabled', false);
|
||||
|
||||
return parent::handle($request, $next);
|
||||
}
|
||||
}
|
||||
27
nova/src/Http/Middleware/RedirectIfAuthenticated.php
Normal file
27
nova/src/Http/Middleware/RedirectIfAuthenticated.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
class RedirectIfAuthenticated
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure(\Illuminate\Http\Request):mixed $next
|
||||
* @param string|null $guard
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next, $guard = null)
|
||||
{
|
||||
if (Auth::guard($guard)->check()) {
|
||||
return redirect(Nova::path());
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
25
nova/src/Http/Middleware/ServeNova.php
Normal file
25
nova/src/Http/Middleware/ServeNova.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Nova\Http\Middleware;
|
||||
|
||||
use Laravel\Nova\Events\NovaServiceProviderRegistered;
|
||||
use Laravel\Nova\Util;
|
||||
|
||||
class ServeNova
|
||||
{
|
||||
/**
|
||||
* Handle the incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure(\Illuminate\Http\Request):mixed $next
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function handle($request, $next)
|
||||
{
|
||||
if (Util::isNovaRequest($request)) {
|
||||
NovaServiceProviderRegistered::dispatch();
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user