MapResolver   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 123
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 17
eloc 32
c 1
b 0
f 0
dl 0
loc 123
ccs 40
cts 40
cp 1
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A resourceClassExists() 0 5 2
A policyClassExists() 0 5 3
A validatePolicyObject() 0 8 4
A __construct() 0 4 2
A map() 0 8 1
A getPolicy() 0 24 5
1
<?php
2
3
/**
4
 * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
5
 * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
6
 *
7
 * Licensed under The MIT License
8
 * For full copyright and license information, please see the LICENSE.txt
9
 * Redistributions of files must retain the above copyright notice.
10
 *
11
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
12
 * @link          https://cakephp.org CakePHP(tm) Project
13
 * @since         1.0.0
14
 * @license       https://opensource.org/licenses/mit-license.php MIT License
15
 */
16
17
namespace Phauthentic\Authorization\Policy;
18
19
use Phauthentic\Authorization\Policy\Exception\MissingPolicyException;
20
use InvalidArgumentException;
21
22
/**
23
 * Policy resolver that allows to map policy classes, objects or factories to
24
 * individual resource classes.
25
 */
26
class MapResolver implements ResolverInterface
27
{
28
    /**
29
     * Resource to policy class name map.
30
     *
31
     * @var array
32
     */
33
    protected $map = [];
34
35
    /**
36
     * Constructor.
37
     *
38
     * Takes a resource class name as a key and a policy as a value, for example:
39
     * ```
40
     * [
41
     *     \App\Service\Resource1::class => \App\Policy\ResourcePolicy::class,
42
     *     \App\Service\Resource2::class => $policyObject,
43
     *     \App\Service\Resource3::class => function() {},
44
     * ]
45
     * ```
46
     *
47
     * @param array $map Resource class name to policy map.
48
     */
49 50
    public function __construct(array $map = [])
50
    {
51 50
        foreach ($map as $resourceClass => $policy) {
52 30
            $this->map($resourceClass, $policy);
53
        }
54 50
    }
55
56
    /**
57
     * Maps a resource class to the policy class name.
58
     *
59
     * @param string $resourceClass A resource class name.
60
     * @param string|object|callable $policy A policy class name, an object or a callable factory.
61
     * @return $this
62
     * @throws \InvalidArgumentException When a resource class does not exist or policy is invalid.
63
     */
64 42
    public function map($resourceClass, $policy): ResolverInterface
65
    {
66 42
        $this->resourceClassExists($resourceClass);
67 40
        $this->validatePolicyObject($policy);
68 38
        $this->policyClassExists($policy);
69 36
        $this->map[$resourceClass] = $policy;
70
71 36
        return $this;
72
    }
73
74
    /**
75
     * Checks if the policy class exists
76
     *
77
     * @param string|object|callable $policy A policy class name, an object or a callable factory.
78
     * @return void
79
     */
80 38
    protected function policyClassExists($policy): void
81
    {
82 38
        if (is_string($policy) && !class_exists($policy)) {
83 2
            $message = sprintf('Policy class `%s` does not exist.', $policy);
84 2
            throw new InvalidArgumentException($message);
85
        }
86 36
    }
87
88
    /**
89
     * Checks if the resource class exists
90
     *
91
     * @param string $resourceClass A resource class name.
92
     * @return void
93
     */
94 42
    protected function resourceClassExists($resourceClass): void
95
    {
96 42
        if (!class_exists($resourceClass)) {
97 2
            $message = sprintf('Resource class `%s` does not exist.', $resourceClass);
98 2
            throw new InvalidArgumentException($message);
99
        }
100 40
    }
101
102
    /**
103
     * Checks if the policy variable is of a valid type
104
     *
105
     * @param string|object|callable $policy
106
     * @return void
107
     */
108 40
    protected function validatePolicyObject($policy): void
109
    {
110 40
        if (!is_string($policy) && !is_object($policy) && !is_callable($policy)) {
111 2
            $message = sprintf(
112 2
                'Policy must be a valid class name, an object or a callable, `%s` given.',
113 2
                gettype($policy)
114
            );
115 2
            throw new InvalidArgumentException($message);
116
        }
117 38
    }
118
119
    /**
120
     * {@inheritDoc}
121
     *
122
     * @throws \InvalidArgumentException When a resource is not an object.
123
     * @throws \Phauthentic\Authorization\Policy\Exception\MissingPolicyException When a policy for a resource has not been defined.
124
     */
125 40
    public function getPolicy($resource)
126
    {
127 40
        if (!is_object($resource)) {
128 2
            $message = sprintf('Resource must be an object, `%s` given.', gettype($resource));
129 2
            throw new InvalidArgumentException($message);
130
        }
131
132 38
        $class = get_class($resource);
133
134 38
        if (!isset($this->map[$class])) {
135 4
            throw new MissingPolicyException(sprintf('Policy for `%s` has not been defined.', $class));
136
        }
137
138 36
        $policy = $this->map[$class];
139
140 36
        if (is_callable($policy)) {
141 2
            return $policy($resource, $this);
142
        }
143
144 34
        if (is_object($policy)) {
145 14
            return $policy;
146
        }
147
148 20
        return new $policy();
149
    }
150
}
151