Skip to content

Commit

Permalink
Gives more granular control over customising resourceful action class…
Browse files Browse the repository at this point in the history
… names
  • Loading branch information
CWAscend committed Feb 10, 2025
1 parent 8dc62dd commit 33a40d5
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 36 deletions.
24 changes: 12 additions & 12 deletions src/Routing/ActionResourceRegistrar.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@

class ActionResourceRegistrar extends ResourceRegistrar
{
private static ?Closure $actionResolver = null;
/**
* @var array<string, Closure>
*/
private static array $actionResolver = [];

protected function getResourceAction($resource, $controller, $method, $options): array
{
Expand All @@ -17,8 +20,8 @@ protected function getResourceAction($resource, $controller, $method, $options):
$resource = Str::camel(str_replace('.', '_', $resource));
$actionName = Str::singular($resource);

if (static::$actionResolver) {
$actionClass = call_user_func(static::$actionResolver, $resource, $method);
if (! empty(static::$actionResolver[$method])) {
$actionClass = call_user_func(static::$actionResolver[$method], $resource);
}

if (empty($actionClass)) {
Expand All @@ -44,19 +47,16 @@ protected function getResourceAction($resource, $controller, $method, $options):
*
* @example
*
* ActionResourceRegistrar::resolveActionClassNameUsing(
* function ($resource, $method): ?string {
* return ucfirst($method)
* .ucfirst(Str::camel(str_replace('.', '-', $resource)))
* .'Action';
* }
* );
* ActionResourceRegistrar::resolveResourceAction('index', function (string $resource) {
* return 'GetAll'.ucfirst($resource); // e.g. GetAllUsers
* });
*
* @param string $method
* @param Closure $resolver
* @return void
*/
public static function resolveActionClassNameUsing(Closure $resolver): void
public static function resolveResourceAction(string $method, Closure $resolver): void
{
static::$actionResolver = $resolver;
static::$actionResolver[$method] = $resolver;
}
}
65 changes: 41 additions & 24 deletions tests/ResourcefulRouteRegistrarTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Lorisleiva\Actions\Tests;

use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str;
use Lorisleiva\Actions\Routing\ActionResourceRegistrar;

beforeEach(function () {
Expand Down Expand Up @@ -290,42 +291,58 @@
expect($route->gatherMiddleware())->toContain('auth');
});

it('allows you to customise the name of each action class, but falls back to the default behaviour if unresolved', function () {
ActionResourceRegistrar::resolveActionClassNameUsing(function (string $resource, string $method) {
return match ($method) {
'index' => 'ShowIndexPage',
'create' => 'ShowCreatePage',
'show' => 'ShowPage',
'edit' => 'ShowEditPage',
'store' => 'Store',
'update' => 'Update',
default => null,
};
it('allows you to override the default action naming conventions', function () {
ActionResourceRegistrar::resolveResourceAction('index', function (string $resource) {
return 'GetAll'.ucfirst($resource);
});

ActionResourceRegistrar::resolveResourceAction('create', function (string $resource) {
return 'Create'.Str::singular(ucfirst($resource));
});

ActionResourceRegistrar::resolveResourceAction('show', function (string $resource) {
return 'Get'.Str::singular(ucfirst($resource));
});

ActionResourceRegistrar::resolveResourceAction('edit', function (string $resource) {
return 'Edit'.Str::singular(ucfirst($resource));
});

ActionResourceRegistrar::resolveResourceAction('store', function (string $resource) {
return 'Store'.Str::singular(ucfirst($resource));
});

ActionResourceRegistrar::resolveResourceAction('update', function (string $resource) {
return 'Patch'.Str::singular(ucfirst($resource));
});

ActionResourceRegistrar::resolveResourceAction('destroy', function (string $resource) {
return 'Destroy'.Str::singular(ucfirst($resource));
});

Route::resourceActions('addresses');

$route = Route::getRoutes()->getByName('addresses.index');
expect($route->getAction()['uses'])->toEqual('App\Actions\ShowIndexPage@__invoke');
expect($route->getAction()['uses'])->toEqual('App\Actions\GetAllAddresses@__invoke');

$route = Route::getRoutes()->getByName('addresses.create');
expect($route->getAction()['uses'])->toEqual('App\Actions\ShowCreatePage@__invoke');
expect($route->getAction()['uses'])->toEqual('App\Actions\CreateAddress@__invoke');

$route = Route::getRoutes()->getByName('addresses.show');
expect($route->getAction()['uses'])->toEqual('App\Actions\ShowPage@__invoke');
expect($route->getAction()['uses'])->toEqual('App\Actions\GetAddress@__invoke');

$route = Route::getRoutes()->getByName('addresses.edit');
expect($route->getAction()['uses'])->toEqual('App\Actions\ShowEditPage@__invoke');
expect($route->getAction()['uses'])->toEqual('App\Actions\EditAddress@__invoke');

$route = Route::getRoutes()->getByName('addresses.store');
expect($route->getAction()['uses'])->toEqual('App\Actions\Store@__invoke');
expect($route->getAction()['uses'])->toEqual('App\Actions\StoreAddress@__invoke');

$route = Route::getRoutes()->getByName('addresses.update');
expect($route->getAction()['uses'])->toEqual('App\Actions\Update@__invoke');
expect($route->getAction()['uses'])->toEqual('App\Actions\PatchAddress@__invoke');

// This one uses the default definition because it was never overridden
$route = Route::getRoutes()->getByName('addresses.destroy');
expect($route->getAction()['uses'])->toEqual('App\Actions\DeleteAddress@__invoke');
expect($route->getAction()['uses'])->toEqual('App\Actions\DestroyAddress@__invoke');
});

namespace App\Actions;
Expand All @@ -348,12 +365,12 @@ class DeletePhotosComment { use AsAction; }
class ShowPhotosComment { use AsAction; }
class ShowEditPhotosComment { use AsAction; }

class ShowIndexPage { use AsAction; }
class ShowCreatePage { use AsAction; }
class ShowPage { use AsAction; }
class ShowEditPage { use AsAction; }
class Store { use AsAction; }
class Update { use AsAction; }
class GetAllAddresses { use AsAction; }
class StoreAddress { use AsAction; }
class GetAddress { use AsAction; }
class EditAddress { use AsAction; }
class PatchAddress { use AsAction; }
class DestroyAddress { use AsAction; }

class GetOrderItems { use AsAction; }
class ShowCreateOrderItem { use AsAction; }
Expand Down

0 comments on commit 33a40d5

Please sign in to comment.