Skip to content

Commit a46e538

Browse files
Merge pull request #12 from kirschbaum-development/static-analysis-and-return-type-updates
Improves action handling and static analysis
2 parents c1248b3 + 88401f7 commit a46e538

18 files changed

+92
-149
lines changed

.github/workflows/run-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ jobs:
167167
composer require "laravel/framework:${{ matrix.laravel }}" --no-interaction --no-update
168168
composer require "phpunit/phpunit:${{ matrix.phpunit }}" --no-interaction --no-update
169169
composer require "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update
170-
composer require "nunomaduro/larastan:${{ matrix.larastan }}" --no-interaction --no-update
170+
composer require "larastan/larastan:${{ matrix.larastan }}" --no-interaction --no-update
171171
composer update --prefer-dist --no-interaction
172172
composer dump
173173

composer.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
},
2222
"require-dev": {
2323
"laravel/pint": "^1.2",
24-
"nunomaduro/larastan": "^2.0",
24+
"larastan/larastan": "^2.0",
2525
"orchestra/testbench": "^7.11.0",
2626
"phpunit/phpunit": "^9.5.10"
2727
},
@@ -41,13 +41,16 @@
4141
},
4242
"scripts": {
4343
"larastan": [
44-
"./vendor/bin/phpstan analyse"
44+
"./vendor/bin/phpstan analyse src"
4545
],
4646
"pint": [
4747
"./vendor/bin/pint"
4848
],
4949
"pint-check": [
5050
"./vendor/bin/pint --test"
51+
],
52+
"test": [
53+
"./vendor/bin/phpunit tests"
5154
]
5255
},
5356
"config": {

phpstan.neon.dist

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
includes:
2+
- vendor/larastan/larastan/extension.neon
3+
4+
parameters:
5+
paths:
6+
- config
7+
- src
8+
9+
level: max
10+
11+
checkMissingIterableValueType: true
12+
treatPhpDocTypesAsCertain: false

src/Action.php

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Kirschbaum\Actions;
44

5+
use Exception;
56
use Illuminate\Support\Traits\Macroable;
67
use Kirschbaum\Actions\Contracts\Actionable;
78
use Kirschbaum\Actions\Exceptions\ActionableInterfaceNotFoundException;
@@ -13,6 +14,8 @@ class Action
1314

1415
/**
1516
* Arguments to pass into the action's constructor.
17+
*
18+
* @var array<int|string, mixed>
1619
*/
1720
protected array $arguments;
1821

@@ -21,7 +24,7 @@ class Action
2124
*
2225
* @param mixed ...$arguments
2326
*
24-
* @return mixed
27+
* @return mixed|void
2528
*
2629
* @throws Throwable
2730
*/
@@ -35,6 +38,9 @@ public function act(string $action, ...$arguments)
3538
/**
3639
* Initiate the given action if the given condition is true.
3740
*
41+
* @template TValue
42+
*
43+
* @param TValue $condition
3844
* @param mixed ...$arguments
3945
*
4046
* @return mixed|void
@@ -53,6 +59,9 @@ public function actWhen($condition, string $action, ...$arguments)
5359
/**
5460
* Initiate the action if the given condition is false.
5561
*
62+
* @template TValue
63+
*
64+
* @param TValue $condition
5665
* @param mixed ...$arguments
5766
*
5867
* @return mixed|void
@@ -80,7 +89,11 @@ protected function handle(string $action)
8089
{
8190
$action = new $action(...$this->arguments);
8291

83-
$this->checkActionForInterface($action);
92+
throw_unless(
93+
$action instanceof Actionable,
94+
ActionableInterfaceNotFoundException::class
95+
);
96+
8497
$this->raiseBeforeActionEvent($action);
8598

8699
try {
@@ -103,20 +116,7 @@ protected function actionHasFailedMethod(Actionable $action): bool
103116
}
104117

105118
/**
106-
* Determine if the action has the proper interface.
107-
*
108-
* @throws Throwable
109-
*/
110-
protected function checkActionForInterface($action): void
111-
{
112-
throw_unless(
113-
$action instanceof Actionable,
114-
ActionableInterfaceNotFoundException::class
115-
);
116-
}
117-
118-
/**
119-
* Dispatch appropriate action event.
119+
* Dispatch the appropriate action event.
120120
*/
121121
protected function dispatchEvent(string $event, Actionable $action): void
122122
{
@@ -140,19 +140,28 @@ protected function eventExists(Actionable $action, string $event): bool
140140
/**
141141
* Fire failure event and/or call failed action method if they exist.
142142
*
143-
*
144-
* @return mixed
143+
* @return mixed|void
145144
*
146145
* @throws Throwable
147146
*/
148147
protected function handleFailure(Actionable $action, Throwable $exception)
149148
{
150149
if ($this->actionHasFailedMethod($action)) {
151-
return $action->failed($exception);
150+
/**
151+
* @var callable $callback
152+
*/
153+
$callback = [$action, 'failed'];
154+
155+
return call_user_func($callback, $exception);
152156
}
153157

154158
if ($this->hasCustomException($action)) {
155-
$exception = $action->exception;
159+
$properties = get_object_vars($action);
160+
161+
/**
162+
* @var Exception $exception
163+
*/
164+
$exception = $properties['exception'];
156165

157166
throw new $exception();
158167
}
@@ -161,7 +170,7 @@ protected function handleFailure(Actionable $action, Throwable $exception)
161170
}
162171

163172
/**
164-
* Check if action has a custom exception.
173+
* Check if the action has a custom exception.
165174
*/
166175
protected function hasCustomException(Actionable $action): bool
167176
{
@@ -170,15 +179,15 @@ protected function hasCustomException(Actionable $action): bool
170179
}
171180

172181
/**
173-
* Raise the before action event.
182+
* Raise the "before" action event.
174183
*/
175184
protected function raiseBeforeActionEvent(Actionable $action): void
176185
{
177186
$this->dispatchEvent('before', $action);
178187
}
179188

180189
/**
181-
* Raise the after action event.
190+
* Raise the "after" action event.
182191
*/
183192
protected function raiseAfterActionEvent(Actionable $action): void
184193
{

src/ActionsServiceProvider.php

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
class ActionsServiceProvider extends ServiceProvider
1414
{
1515
/**
16-
* All of the container bindings that should be registered.
16+
* All the container bindings that should be registered.
1717
*
18-
* @var array
18+
* @var array<class-string<Action>|string,class-string<Action>>
1919
*/
20-
public $bindings = [
20+
public array $bindings = [
2121
'actions' => Action::class,
2222
Action::class => Action::class,
2323
];
@@ -49,6 +49,8 @@ public function boot(): void
4949

5050
/**
5151
* Get the services provided by the provider.
52+
*
53+
* @return list<class-string<Action>>
5254
*/
5355
public function provides(): array
5456
{
@@ -61,6 +63,9 @@ public function provides(): array
6163
protected function bootActionMacro(): void
6264
{
6365
Action::macro('getMacro', function (string $name): callable|object {
66+
/**
67+
* @phpstan-ignore-next-line
68+
*/
6469
return static::$macros[$name];
6570
});
6671
}
@@ -72,17 +77,27 @@ protected function bootActionMacro(): void
7277
*/
7378
protected function bootAutoDiscoverActions(): void
7479
{
75-
$paths = collect(config('laravel-actions.paths'))
80+
/**
81+
* @var list<string> $configPaths
82+
*/
83+
$configPaths = config('laravel-actions.paths');
84+
85+
$paths = collect($configPaths)
7686
->unique()
77-
->filter(function ($path) {
87+
->filter(function (string $path): bool {
7888
return is_dir($path);
7989
});
8090

8191
if ($paths->isEmpty()) {
8292
return;
8393
}
8494

85-
foreach ((new Finder())->in($paths->toArray())->files() as $action) {
95+
/**
96+
* @var list<string> $dirs
97+
*/
98+
$dirs = $paths->toArray();
99+
100+
foreach ((new Finder())->in($dirs)->files() as $action) {
86101
if (preg_match('#(namespace)(\\s+)([A-Za-z0-9\\\\]+?)(\\s*);#sm', $action->getContents(), $namespaceMatches)) {
87102
$action = (string) Str::of($namespaceMatches[3])
88103
->finish('\\')

src/Commands/stubs/Action.stub

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,16 @@ class DummyClass implements Actionable
1111

1212
/**
1313
* Event to dispatch before action starts.
14-
*
15-
* @var string
1614
*/
17-
public $before = '';
15+
public string $before = '';
1816

1917
/**
2018
* Event to dispatch after action completes.
21-
*
22-
* @var string
2319
*/
24-
public $after = '';
20+
public string $after = '';
2521

2622
/**
2723
* Create a new action instance.
28-
*
29-
* @return void
3024
*/
3125
public function __construct()
3226
{
@@ -35,8 +29,6 @@ class DummyClass implements Actionable
3529

3630
/**
3731
* Execute the action.
38-
*
39-
* @return mixed
4032
*/
4133
public function __invoke()
4234
{

src/Traits/CanAct.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ trait CanAct
1111
/**
1212
* Handles static method calls by passing them to the Action class.
1313
*
14-
*
1514
* @return mixed|void
1615
*/
1716
public static function __callStatic(string $name, array $arguments)

src/helpers.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
* @param mixed ...$arguments
1010
*
11-
* @return mixed
11+
* @return mixed|void
1212
*
1313
* @throws Throwable
1414
*/
@@ -22,9 +22,12 @@ function act(string $action, ...$arguments)
2222
/**
2323
* Initiate the given action if the given condition is true.
2424
*
25+
* @template TValue
26+
*
27+
* @param TValue $condition
2528
* @param mixed ...$arguments
2629
*
27-
* @return mixed
30+
* @return mixed|void
2831
*
2932
* @throws Throwable
3033
*/
@@ -38,9 +41,12 @@ function act_when($condition, string $action, ...$arguments)
3841
/**
3942
* Initiate the given action if the given condition is false.
4043
*
44+
* @template TValue
45+
*
46+
* @param TValue $condition
4147
* @param mixed ...$arguments
4248
*
43-
* @return mixed
49+
* @return mixed|void
4450
*
4551
* @throws Throwable
4652
*/

tests/Fixtures/Actions/ActionWithAllEvents.php

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,34 +6,25 @@
66
use Kirschbaum\Actions\Traits\CanAct;
77
use Tests\Fixtures\Events\AfterEvent;
88
use Tests\Fixtures\Events\BeforeEvent;
9-
use Throwable;
109

1110
class ActionWithAllEvents implements Actionable
1211
{
1312
use CanAct;
1413

1514
/**
1615
* Event to dispatch before action starts.
17-
*
18-
* @var string
1916
*/
20-
public $before = BeforeEvent::class;
17+
public string $before = BeforeEvent::class;
2118

2219
/**
2320
* Event to dispatch after action completes.
24-
*
25-
* @var string
2621
*/
27-
public $after = AfterEvent::class;
22+
public string $after = AfterEvent::class;
2823

2924
/**
3025
* Execute the action.
31-
*
32-
* @return mixed
33-
*
34-
* @throws Throwable
3526
*/
36-
public function __invoke()
27+
public function __invoke(): bool
3728
{
3829
return true;
3930
}

tests/Fixtures/Actions/ActionWithCustomException.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,12 @@ class ActionWithCustomException implements Actionable
1414

1515
/**
1616
* Event to dispatch if action throws an exception.
17-
*
18-
* @var string
1917
*/
20-
public $exception = CustomFailedException::class;
18+
public string $exception = CustomFailedException::class;
2119

2220
/**
2321
* Execute the action.
2422
*
25-
* @return mixed
26-
*
2723
* @throws Throwable
2824
*/
2925
public function __invoke()

0 commit comments

Comments
 (0)