Completed
Branch feature/pre-split (197e7e)
by Anton
03:26
created

Rule   A

Complexity

Total Complexity 4

Size/Duplication

Total Lines 58
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 0
loc 58
c 0
b 0
f 0
rs 10
wmc 4
lcom 1
cbo 2

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A allows() 0 23 3
1
<?php
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
namespace Spiral\Security;
9
10
use Spiral\Core\ResolverInterface;
11
use Spiral\Security\Exceptions\RuleException;
12
13
/**
14
 * Rule class provides ability to route check request to a specified method (by default "check")
15
 * using resolver interface. As side effect check method will support method injections.
16
 *
17
 * Example:
18
 *
19
 * class MyRule extends Rule
20
 * {
21
 *      public function allows($actor, $post)
22
 *      {
23
 *          return $post->author_id == $actor->id;
24
 *      }
25
 * }
26
 */
27
abstract class Rule implements RuleInterface
28
{
29
    /**
30
     * Method to be used for checking.
31
     */
32
    const CHECK_METHOD = 'check';
33
34
    /**
35
     * Set of aliases to be used for method injection.
36
     *
37
     * @var array
38
     */
39
    protected $aliases = [
40
        'user' => 'actor'
41
    ];
42
43
    /**
44
     * @var ResolverInterface
45
     */
46
    protected $resolver = null;
47
48
    /**
49
     * @param ResolverInterface $resolver
50
     */
51
    public function __construct(ResolverInterface $resolver)
52
    {
53
        $this->resolver = $resolver;
54
    }
55
56
    /**
57
     * {@inheritdoc}
58
     *
59
     * @throws RuleException
60
     */
61
    public function allows(ActorInterface $actor, string $permission, array $context): bool
62
    {
63
        $parameters = compact('actor', 'permission', 'context') + $context;
64
65
        //Mounting aliases
66
        foreach ($this->aliases as $target => $alias) {
67
            $parameters[$target] = $parameters[$alias];
68
        }
69
70
        $method = new \ReflectionMethod($this, static::CHECK_METHOD);
71
        $method->setAccessible(true);
72
73
        try {
74
            return $method->invokeArgs($this,
75
                $this->resolver->resolveArguments($method, $parameters));
76
        } catch (\Throwable $e) {
77
            throw new RuleException(
78
                '[' . get_class($this) . '] ' . $e->getMessage(),
79
                $e->getCode(),
80
                $e
81
            );
82
        }
83
    }
84
}