Skip to content

Commit 0fda4d0

Browse files
committed
feat: add trait AllowToExecute
1 parent ec7b694 commit 0fda4d0

File tree

3 files changed

+152
-0
lines changed

3 files changed

+152
-0
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ Check MD [online][check-online].
99

1010
## [unreleased]
1111

12+
## [1.10.0] - 2021-11-14
13+
14+
### Added
15+
16+
- Add trait `AllowToExecute`
17+
1218
## [1.9.0] - 2021-10-16
1319

1420
### Added
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Php\Support\Laravel\Traits\Models;
6+
7+
use Illuminate\Database\Eloquent\Model;
8+
use Php\Support\Exceptions\MethodNotAllowedException;
9+
10+
/**
11+
* @mixin Model
12+
*/
13+
trait AllowToExecute
14+
{
15+
protected static array $disallowMethodsMap = [];
16+
protected array $allowList = [];
17+
18+
public function addMethodToAllowList(string $method): void
19+
{
20+
$this->allowList[$method] = true;
21+
}
22+
23+
private function rejectMethodFromAllowList(string $method): void
24+
{
25+
unset($this->allowList[$method]);
26+
}
27+
28+
protected function isAllowToExecute(string $method): bool
29+
{
30+
return !array_key_exists($method, static::$disallowMethodsMap) || isset($this->allowList[$method]);
31+
}
32+
33+
protected function checkPossibilityAndExecute(string $method, ...$arguments): mixed
34+
{
35+
if ($this->isAllowToExecute($method)) {
36+
return parent::$method(...$arguments);
37+
}
38+
$hint = static::$disallowMethodsMap[$method];
39+
40+
if ($hint instanceof \Closure) {
41+
return $hint($this);
42+
}
43+
44+
if (is_string($hint)) {
45+
$text = "You should call this method like this: $hint";
46+
}
47+
48+
throw new MethodNotAllowedException($text ?? 'You don\'t allow to execute this method!');
49+
}
50+
51+
protected static function addMethodToDisallowMap(string $method, string|\Closure $hint = null): void
52+
{
53+
static::$disallowMethodsMap[$method] = $hint;
54+
}
55+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Php\Support\Laravel\Tests\Traits\Models;
6+
7+
use Illuminate\Database\Eloquent\Model;
8+
use Php\Support\Exceptions\MethodNotAllowedException;
9+
use Php\Support\Laravel\Tests\AbstractTestCase;
10+
use Php\Support\Laravel\Traits\Models\AllowToExecute;
11+
12+
class AllowToExecuteTest extends AbstractTestCase
13+
{
14+
15+
/** @test */
16+
public function callBase()
17+
{
18+
$class = $this->buildClass();
19+
20+
$this->expectException(MethodNotAllowedException::class);
21+
$this->expectExceptionMessage(
22+
'Method Not Allowed: You should call this method like this: Remover::exec($model)'
23+
);
24+
25+
$class->delete();
26+
}
27+
28+
/** @test */
29+
public function callWithDisablePossibility()
30+
{
31+
$class = $this->buildClass();
32+
33+
$this->expectException(MethodNotAllowedException::class);
34+
$this->expectExceptionMessage('Method Not Allowed: You should call this method like this: new Query($model)');
35+
36+
$class->newQuery();
37+
}
38+
39+
/** @test */
40+
public function callWithPossibility()
41+
{
42+
$class = $this->buildClass();
43+
$class->addMethodToAllowList('newQuery');
44+
45+
$class->newQuery();
46+
47+
static::assertNotNull($class);
48+
}
49+
50+
/** @test */
51+
public function callFn()
52+
{
53+
$class = $this->buildClass();
54+
55+
$this->expectException(MethodNotAllowedException::class);
56+
$this->expectExceptionMessage("QQ");
57+
$class->handle(1, 2);
58+
}
59+
60+
private function buildClass(): Model
61+
{
62+
return new class extends Model {
63+
use AllowToExecute;
64+
65+
protected static function booting(): void
66+
{
67+
static::addMethodToDisallowMap('delete', 'Remover::exec($model)');
68+
static::addMethodToDisallowMap('newQuery', 'new Query($model)');
69+
static::addMethodToDisallowMap(
70+
'handle',
71+
static fn() => throw new MethodNotAllowedException("QQ")
72+
);
73+
}
74+
75+
public function delete()
76+
{
77+
return $this->checkPossibilityAndExecute(__FUNCTION__);
78+
}
79+
80+
public function handle($value, $value2)
81+
{
82+
return $this->checkPossibilityAndExecute(__FUNCTION__, $value, $value2);
83+
}
84+
85+
public function newQuery()
86+
{
87+
return $this->checkPossibilityAndExecute(__FUNCTION__);
88+
}
89+
};
90+
}
91+
}

0 commit comments

Comments
 (0)