Skip to content

Commit

Permalink
Standalone actions. (#259)
Browse files Browse the repository at this point in the history
* Standalone actions.

* Apply fixes from StyleCI (#258)

* Docs
  • Loading branch information
binaryk authored Sep 2, 2020
1 parent da83adc commit e6ff1e9
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 7 deletions.
41 changes: 41 additions & 0 deletions docs/docs/3.0/actions/actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,44 @@ public function handle(ActionRequest $request, Post $post): JsonResponse
//
}
```

## Standalone actions

Sometimes you don't need to have an action with models. Let's say for example the authenticated user wants to disable his account. For this we have `standalone` actions:


```php
// UserRepository

public function actions(RestifyRequest $request)
{
return [
DisableProfileAction::new()->standalone(),
];
}
```

Just mark it as standalone with `->standalone` or override the property directly into the action:

```php
class DisableProfileAction extends Action
{
public $standalone = true;

//...
}
```


## URI Key

Usually the URL for the action is make based on the action name. You can use your own URI key if you want:

```php
class DisableProfileAction extends Action
{
public static $uriKey = 'disable_profile';

//...
}
```
49 changes: 46 additions & 3 deletions src/Actions/Action.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,34 @@
use Closure;
use Exception;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use JsonSerializable;

abstract class Action extends RestController implements JsonSerializable
{
use AuthorizedToSee, ProxiesCanSeeToGate, Make, Visibility;

/**
* Number of models into a chunk when action for 'all'.
*
* @var int
*/
public static int $chunkCount = 200;

/**
* Indicated if this action don't require any models.
*
* @var bool
*/
public bool $standalone = false;

/**
* Default uri key for the action.
* @var string
*/
public static $uriKey;

public static function indexQuery(RestifyRequest $request, $query)
{
return $query;
Expand All @@ -50,7 +66,7 @@ public function name()
*/
public function uriKey()
{
return Str::slug($this->name(), '-', null);
return static::$uriKey ?? Str::slug($this->name(), '-', null);
}

/**
Expand Down Expand Up @@ -88,6 +104,29 @@ public function payload(): array
return [];
}

/**
* Make current action being standalone. No model query will be performed.
*
* @param bool $standalone
* @return self
*/
public function standalone(bool $standalone = true): self
{
$this->standalone = $standalone;

return $this;
}

/**
* Check if the action is standalone.
*
* @return bool
*/
public function isStandalone(): bool
{
return $this->standalone;
}

// abstract public function handle(ActionRequest $request, Collection $models): JsonResponse;

public function handleRequest(ActionRequest $request)
Expand All @@ -96,6 +135,10 @@ public function handleRequest(ActionRequest $request)
throw new Exception('Missing handle method from the action.');
}

if ($this->isStandalone()) {
return Transaction::run(fn () => $this->handle($request));
}

$response = null;

if (! $request->isForRepositoryRequest()) {
Expand Down
10 changes: 6 additions & 4 deletions src/Http/Controllers/PerformActionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ class PerformActionController extends RepositoryController
{
public function __invoke(ActionRequest $request)
{
$request->validate([
'repositories' => 'required',
]);

$action = $request->action();

if (! $action->isStandalone()) {
$request->validate([
'repositories' => 'required',
]);
}

return $action->handleRequest(
$request,
);
Expand Down
12 changes: 12 additions & 0 deletions tests/Actions/PerformActionsControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Binaryk\LaravelRestify\Tests\Fixtures\Post\PublishPostAction;
use Binaryk\LaravelRestify\Tests\Fixtures\User\ActivateAction;
use Binaryk\LaravelRestify\Tests\Fixtures\User\DisableProfileAction;
use Binaryk\LaravelRestify\Tests\IntegrationTest;

class PerformActionsControllerTest extends IntegrationTest
Expand Down Expand Up @@ -64,4 +65,15 @@ public function test_show_action_not_need_repositories()

$this->assertEquals(1, ActivateAction::$applied[0]->id);
}

public function test_could_perform_standalone_action()
{
$this->post('/restify-api/users/action?action='.(new DisableProfileAction())->uriKey())
->assertSuccessful()
->assertJsonStructure([
'data',
]);

$this->assertEquals('foo', DisableProfileAction::$applied[0]);
}
}
21 changes: 21 additions & 0 deletions tests/Fixtures/User/DisableProfileAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Binaryk\LaravelRestify\Tests\Fixtures\User;

use Binaryk\LaravelRestify\Actions\Action;
use Binaryk\LaravelRestify\Http\Requests\ActionRequest;
use Illuminate\Http\JsonResponse;

class DisableProfileAction extends Action
{
public static $applied = [];

public static $uriKey = 'disable_profile';

public function handle(ActionRequest $request, $foo = 'foo'): JsonResponse
{
static::$applied[] = $foo;

return $this->response()->data(['succes' => 'true'])->respond();
}
}
2 changes: 2 additions & 0 deletions tests/Fixtures/User/UserRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public function actions(RestifyRequest $request)
{
return [
ActivateAction::new(),

DisableProfileAction::new()->standalone(),
];
}

Expand Down

0 comments on commit e6ff1e9

Please sign in to comment.