Test Failed
Push — master ( 5671e4...328bde )
by Florian
02:21
created

MapResolver::resourceClassExists()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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