diff --git a/src/Concerns/HandlesRelationManyToManyOperations.php b/src/Concerns/HandlesRelationManyToManyOperations.php index 37211138..c22d97ba 100644 --- a/src/Concerns/HandlesRelationManyToManyOperations.php +++ b/src/Concerns/HandlesRelationManyToManyOperations.php @@ -632,7 +632,7 @@ protected function updatePivotWithTransaction(Request $request, $parentKey, $rel $query = $this->buildShowFetchQuery($request, $parentEntity, []); $entity = $this->runShowFetchQuery($request, $query, $parentEntity, $relatedKey); - $this->authorize('update', $entity); + $this->authorize('update', [$entity, $parentEntity]); $updateResult = $this->performUpdatePivot($request, $parentEntity, $relatedKey, $request->get('pivot', [])); diff --git a/src/Concerns/HandlesRelationOneToManyOperations.php b/src/Concerns/HandlesRelationOneToManyOperations.php index 25d105ac..b4d126d8 100644 --- a/src/Concerns/HandlesRelationOneToManyOperations.php +++ b/src/Concerns/HandlesRelationOneToManyOperations.php @@ -52,7 +52,7 @@ protected function associateWithTransaction(Request $request, $parentKey) } $this->authorize('view', $parentEntity); - $this->authorize('update', $entity); + $this->authorize('update', [$entity, $parentEntity]); $this->performAssociate($request, $parentEntity, $entity); @@ -204,7 +204,7 @@ protected function dissociateWithTransaction(Request $request, $parentKey, $rela return $beforeHookResult; } - $this->authorize('update', $entity); + $this->authorize('update', [$entity, $parentEntity]); $this->performDissociate($request, $parentEntity, $entity); diff --git a/src/Concerns/HandlesRelationStandardBatchOperations.php b/src/Concerns/HandlesRelationStandardBatchOperations.php index df569236..4f432457 100644 --- a/src/Concerns/HandlesRelationStandardBatchOperations.php +++ b/src/Concerns/HandlesRelationStandardBatchOperations.php @@ -41,13 +41,13 @@ public function batchStore(Request $request, $parentKey) */ protected function batchStoreWithTransaction(Request $request, $parentKey) { - $resourceModelClass = $this->resolveResourceModelClass(); - - $this->authorize('create', $resourceModelClass); - $parentQuery = $this->buildBatchStoreParentFetchQuery($request, $parentKey); $parentEntity = $this->runBatchStoreParentFetchQuery($request, $parentQuery, $parentKey); + $resourceModelClass = $this->resolveResourceModelClass(); + + $this->authorize('create', [$resourceModelClass, $parentEntity]); + $beforeHookResult = $this->beforeBatchStore($request, $parentEntity); if ($this->hookResponds($beforeHookResult)) { return $beforeHookResult; @@ -194,7 +194,7 @@ protected function batchUpdateWithTransaction(Request $request, $parentKey) foreach ($entities as $entity) { /** @var Model $entity */ - $this->authorize('update', $entity); + $this->authorize('update', [$entity, $parentEntity]); $resource = $request->input("resources.{$entity->{$this->keyName()}}"); @@ -393,7 +393,7 @@ protected function batchDestroyWithTransaction(Request $request, $parentKey) foreach ($entities as $entity) { /** @var Model $entity */ - $this->authorize($forceDeletes ? 'forceDelete' : 'delete', $entity); + $this->authorize($forceDeletes ? 'forceDelete' : 'delete', [$entity, $parentEntity]); $this->beforeDestroy($request, $parentEntity, $entity); @@ -560,7 +560,7 @@ protected function batchRestoreWithTransaction(Request $request, $parentKey) foreach ($entities as $entity) { /** @var Model $entity */ - $this->authorize('restore', $entity); + $this->authorize('restore', [$entity, $parentEntity]); $this->beforeRestore($request, $parentEntity, $entity); diff --git a/src/Concerns/HandlesRelationStandardOperations.php b/src/Concerns/HandlesRelationStandardOperations.php index 23e17405..a8d0ac21 100644 --- a/src/Concerns/HandlesRelationStandardOperations.php +++ b/src/Concerns/HandlesRelationStandardOperations.php @@ -32,13 +32,13 @@ trait HandlesRelationStandardOperations */ public function index(Request $request, $parentKey) { - $this->authorize('viewAny', $this->resolveResourceModelClass()); - $requestedRelations = $this->relationsResolver->requestedRelations($request); $parentQuery = $this->buildIndexParentFetchQuery($request, $parentKey); $parentEntity = $this->runIndexParentFetchQuery($request, $parentQuery, $parentKey); + $this->authorize('viewAny', [$this->resolveResourceModelClass(), $parentEntity]); + $beforeHookResult = $this->beforeIndex($request, $parentEntity); if ($this->hookResponds($beforeHookResult)) { return $beforeHookResult; @@ -251,13 +251,13 @@ public function store(Request $request, $parentKey) */ protected function storeWithTransaction(Request $request, $parentKey) { - $resourceModelClass = $this->resolveResourceModelClass(); - - $this->authorize('create', $resourceModelClass); - $parentQuery = $this->buildStoreParentFetchQuery($request, $parentKey); $parentEntity = $this->runStoreParentFetchQuery($request, $parentQuery, $parentKey); + $resourceModelClass = $this->resolveResourceModelClass(); + + $this->authorize('create', [$resourceModelClass, $parentEntity]); + /** @var Model $entity */ $entity = new $resourceModelClass; @@ -434,7 +434,7 @@ public function show(Request $request, $parentKey, $relatedKey = null) $query = $this->buildShowFetchQuery($request, $parentEntity, $requestedRelations); $entity = $this->runShowFetchQuery($request, $query, $parentEntity, $relatedKey); - $this->authorize('view', $entity); + $this->authorize('view', [$entity, $parentEntity]); $entity = $this->cleanupEntity($entity); @@ -613,7 +613,7 @@ protected function updateWithTransaction(Request $request, $parentKey, $relatedK $query = $this->buildUpdateFetchQuery($request, $parentEntity, $requestedRelations); $entity = $this->runUpdateFetchQuery($request, $query, $parentEntity, $relatedKey); - $this->authorize('update', $entity); + $this->authorize('update', [$entity, $parentEntity]); $beforeHookResult = $this->beforeUpdate($request, $parentEntity, $entity); if ($this->hookResponds($beforeHookResult)) { @@ -811,7 +811,7 @@ protected function destroyWithTransaction(Request $request, $parentKey, $related abort(404); } - $this->authorize($forceDeletes ? 'forceDelete' : 'delete', $entity); + $this->authorize($forceDeletes ? 'forceDelete' : 'delete', [$entity, $parentEntity]); $beforeHookResult = $this->beforeDestroy($request, $parentEntity, $entity); if ($this->hookResponds($beforeHookResult)) { @@ -994,7 +994,7 @@ protected function restoreWithTransaction(Request $request, $parentKey, $related $query = $this->buildRestoreFetchQuery($request, $parentEntity, $requestedRelations); $entity = $this->runRestoreFetchQuery($request, $query, $parentEntity, $relatedKey); - $this->authorize('restore', $entity); + $this->authorize('restore', [$entity, $parentEntity]); $beforeHookResult = $this->beforeRestore($request, $parentEntity, $entity); if ($this->hookResponds($beforeHookResult)) { diff --git a/src/Concerns/HandlesStandardBatchOperations.php b/src/Concerns/HandlesStandardBatchOperations.php index 2ab002c5..456782c1 100644 --- a/src/Concerns/HandlesStandardBatchOperations.php +++ b/src/Concerns/HandlesStandardBatchOperations.php @@ -62,6 +62,8 @@ protected function batchStoreWithTransaction(Request $request) $this->performStore($request, $entity, $resource); + $this->beforeStoreFresh($request, $entity); + $entity = $entity->fresh($requestedRelations); $entity->wasRecentlyCreated = true; @@ -153,6 +155,8 @@ protected function batchUpdateWithTransaction(Request $request) $request->input("resources.{$entity->{$this->keyName()}}") ); + $this->beforeUpdateFresh($request, $entity); + $entity = $entity->fresh($requestedRelations); $this->afterSave($request, $entity); @@ -296,6 +300,7 @@ protected function batchDestroyWithTransaction(Request $request) if (!$forceDeletes) { $this->performDestroy($entity); if ($softDeletes) { + $this->beforeDestroyFresh($request, $entity); $entity = $entity->fresh($requestedRelations); } } else { @@ -414,6 +419,8 @@ protected function batchRestoreWithTransaction(Request $request) $this->performRestore($entity); + $this->beforeRestoreFresh($request, $entity); + $entity = $entity->fresh($requestedRelations); $this->afterRestore($request, $entity); diff --git a/src/Concerns/HandlesStandardOperations.php b/src/Concerns/HandlesStandardOperations.php index fad4446b..8983bab1 100644 --- a/src/Concerns/HandlesStandardOperations.php +++ b/src/Concerns/HandlesStandardOperations.php @@ -174,6 +174,11 @@ protected function storeWithTransaction(Request $request) $request->all() ); + $beforeStoreFreshResult = $this->beforeStoreFresh($request, $entity); + if ($this->hookResponds($beforeStoreFreshResult)) { + return $beforeStoreFreshResult; + } + $entity = $entity->fresh($requestedRelations); $entity->wasRecentlyCreated = true; @@ -229,6 +234,18 @@ protected function performStore(Request $request, Model $entity, array $attribut $entity->save(); } + /** + * The hook is executed after creating and before refreshing the resource. + * + * @param Request $request + * @param Model $entity + * @return mixed + */ + protected function beforeStoreFresh(Request $request, Model $entity) + { + return null; + } + /** * The hook is executed after creating or updating a resource. * @@ -398,6 +415,11 @@ protected function updateWithTransaction(Request $request, $key) $request->all() ); + $beforeUpdateFreshResult = $this->beforeUpdateFresh($request, $entity); + if ($this->hookResponds($beforeUpdateFreshResult)) { + return $beforeUpdateFreshResult; + } + $entity = $entity->fresh($requestedRelations); $afterSaveHookResult = $this->afterSave($request, $entity); @@ -465,6 +487,18 @@ protected function performUpdate(Request $request, Model $entity, array $attribu $entity->save(); } + /** + * The hook is executed after updating and before refreshing the resource. + * + * @param Request $request + * @param Model $entity + * @return mixed + */ + protected function beforeUpdateFresh(Request $request, Model $entity) + { + return null; + } + /** * The hook is executed after updating a resource. * @@ -529,6 +563,11 @@ protected function destroyWithTransaction(Request $request, $key) if (!$forceDeletes) { $this->performDestroy($entity); if ($softDeletes) { + $beforeDestroyFreshResult = $this->beforeDestroyFresh($request, $entity); + if ($this->hookResponds($beforeDestroyFreshResult)) { + return $beforeDestroyFreshResult; + } + $entity = $entity->fresh($requestedRelations); } } else { @@ -610,6 +649,19 @@ protected function performForceDestroy(Model $entity): void $entity->forceDelete(); } + /** + * The hook is executed after deleting and before refreshing the resource. + * This hook is only called when not using forced deletes + * + * @param Request $request + * @param Model $entity + * @return mixed + */ + protected function beforeDestroyFresh(Request $request, Model $entity) + { + return null; + } + /** * The hook is executed after deleting a resource. * @@ -666,6 +718,11 @@ protected function restoreWithTransaction(Request $request, $key) $this->performRestore($entity); + $beforeHookResult = $this->beforeRestoreFresh($request, $entity); + if ($this->hookResponds($beforeHookResult)) { + return $beforeHookResult; + } + $entity = $entity->fresh($requestedRelations); $afterHookResult = $this->afterRestore($request, $entity); @@ -726,6 +783,19 @@ protected function performRestore(Model $entity): void $entity->restore(); } + /** + * The hook is executed after force restoring a previously deleted resource but before + * refreshing the resource. + * + * @param Request $request + * @param Model $entity + * @return mixed + */ + protected function beforeRestoreFresh(Request $request, Model $entity) + { + return null; + } + /** * The hook is executed after force restoring a previously deleted resource. * diff --git a/src/Http/Requests/Request.php b/src/Http/Requests/Request.php index cc376746..d7db9382 100644 --- a/src/Http/Requests/Request.php +++ b/src/Http/Requests/Request.php @@ -102,6 +102,60 @@ public function rules() return []; } + /** + * Get custom attributes for validator errors that apply to the request. + * + * @return array + */ + public function messages() + { + if (!$this->route()) { + return []; + } + + if ($this->route()->getActionMethod() === 'store') { + return array_merge($this->commonMessages(), $this->storeMessages()); + } + + if ($this->route()->getActionMethod() === 'batchStore') { + return array_merge($this->commonMessages(), $this->storeMessages(), $this->batchStoreMessages()); + } + + if ($this->route()->getActionMethod() === 'update') { + return array_merge($this->commonMessages(), $this->updateMessages()); + } + + if ($this->route()->getActionMethod() === 'batchUpdate') { + return array_merge($this->commonMessages(), $this->updateMessages(), $this->batchUpdateMessages()); + } + + if ($this->route()->getActionMethod() === 'associate') { + return $this->associateMessages(); + } + + if ($this->route()->getActionMethod() === 'attach') { + return $this->attachMessages(); + } + + if ($this->route()->getActionMethod() === 'detach') { + return $this->detachMessages(); + } + + if ($this->route()->getActionMethod() === 'sync') { + return $this->syncMessages(); + } + + if ($this->route()->getActionMethod() === 'toggle') { + return $this->toggleMessages(); + } + + if ($this->route()->getActionMethod() === 'updatePivot') { + return $this->updatePivotMessages(); + } + + return []; + } + /** * Default rules for the request. * @@ -226,4 +280,114 @@ public function updatePivotRules(): array { return []; } + + /** + * Default messages for the request. + * + * @return array + */ + public function commonMessages(): array + { + return []; + } + + /** + * Messages for the "store" (POST) endpoint. + * + * @return array + */ + function storeMessages(): array + { + return []; + } + + /** + * Messages for the "batchstore" (POST) endpoint. + * + * @return array + */ + function batchStoreMessages(): array + { + return []; + } + + /** + * Messages for the "update" (POST) endpoint. + * + * @return array + */ + function updateMessages(): array + { + return []; + } + + /** + * Messages for the "batchUpdate" (POST) endpoint. + * + * @return array + */ + function batchUpdateMessages(): array + { + return []; + } + + /** + * Messages for the "associate" endpoint. + * + * @return array + */ + public function associateMessages(): array + { + return []; + } + + /** + * Messages for the "attach" endpoint. + * + * @return array + */ + public function attachMessages(): array + { + return []; + } + + /** + * Messages for the "detach" endpoint. + * + * @return array + */ + public function detachMessages(): array + { + return []; + } + + /** + * Messages for the "sync" endpoint. + * + * @return array + */ + public function syncMessages(): array + { + return []; + } + + /** + * Messages for the "toggle" endpoint. + * + * @return array + */ + public function toggleMessages(): array + { + return []; + } + + /** + * Messages for the "pivot" endpoint. + * + * @return array + */ + public function updatePivotMessages(): array + { + return []; + } }