PluginProbe ʕ •ᴥ•ʔ
Kirki – Freeform Page Builder, Website Builder & Customizer / 6.0.13
Kirki – Freeform Page Builder, Website Builder & Customizer v6.0.13
6.1.1 6.1.0 6.0.14 6.0.13 6.0.12 6.0.11 6.0.10 6.0.9 6.0.8 6.0.7 6.0.6 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 4.0.19 4.0.20 4.0.21 4.0.22 4.0.23 4.0.24 4.1 4.2.0 5.0.0 5.1.0 5.1.1 5.2.0 5.2.1 5.2.2 5.2.3 6.0.0 trunk 3.0.40 3.0.41 3.0.42 3.0.43 3.0.44 3.0.45 3.1.0 3.1.1 3.1.2
kirki / libraries / framework / Managers / PolicyManager.php
kirki / libraries / framework / Managers Last commit date
DateManager.php 3 weeks ago EventManager.php 3 weeks ago LogManager.php 3 weeks ago OptionManager.php 3 weeks ago PolicyManager.php 3 weeks ago
PolicyManager.php
251 lines
1 <?php
2
3 /**
4 * Registers and resolves authorization policies for framework models.
5 * Maps model classes to policy handlers and evaluates user abilities through the Guard facade.
6 * Centralizes access control decisions for controllers and domain services.
7 *
8 * @package Framework
9 * @subpackage Managers
10 * @since 1.0.0
11 */
12 namespace Kirki\Framework\Managers;
13
14 \defined('ABSPATH') || exit;
15 use Kirki\Framework\Concerns\DependencyResolvable;
16 use Kirki\Framework\Database\Query\Model;
17 use Kirki\Framework\Exceptions\AuthorizationException;
18 use Kirki\Framework\Supports\Arr;
19 use InvalidArgumentException;
20 use ReflectionMethod;
21 use ReflectionNamedType;
22 use function Kirki\Framework\app;
23 use function Kirki\Framework\config_path;
24 use function Kirki\Framework\message;
25 use function Kirki\Framework\user;
26 class PolicyManager
27 {
28 use DependencyResolvable;
29 /**
30 * The array of registered policies or the policies data from cache.
31 *
32 * @var array
33 *
34 * @since 1.0.0
35 */
36 protected $policies = [];
37 /**
38 * The currently resolved user.
39 *
40 * @var mixed
41 *
42 * @since 1.0.0
43 */
44 protected $user;
45 /**
46 * PolicyManager constructor.
47 *
48 * Loads and registers policies from the cache file.
49 *
50 * @return void
51 *
52 * @since 1.0.0
53 */
54 public function __construct()
55 {
56 $this->load_policies();
57 $this->register_policies();
58 }
59 /**
60 * Load the policies from the cached policies file.
61 *
62 * @return $this|null
63 *
64 * @since 1.0.0
65 */
66 protected function load_policies()
67 {
68 $policies_cache_path = config_path('policies.cache.php');
69 if (!\file_exists($policies_cache_path)) {
70 return;
71 }
72 $this->policies = (require $policies_cache_path);
73 return $this;
74 }
75 /**
76 * Register the loaded policies for each model.
77 *
78 * @return $this
79 *
80 * @since 1.0.0
81 */
82 public function register_policies()
83 {
84 foreach ($this->policies as $policy) {
85 $this->register_policy($policy['model'], $policy['policy']);
86 }
87 return $this;
88 }
89 /**
90 * Register an individual model-policy mapping.
91 *
92 * @param string $model The model instance.
93 * @param string $policy The policy.
94 *
95 * @return void
96 *
97 * @since 1.0.0
98 */
99 public function register_policy(string $model, string $policy)
100 {
101 $this->policies[$model] = $policy;
102 }
103 /**
104 * Resolve the policy object for a given model.
105 *
106 * @param mixed $model The model instance.
107 *
108 * @return mixed|null
109 *
110 * @since 1.0.0
111 */
112 protected function resolve_policy($model)
113 {
114 $model_name = \is_object($model) ? \get_class($model) : $model;
115 if (!$this->has_policy($model_name)) {
116 return null;
117 }
118 return app()->make($this->policy($model_name));
119 }
120 /**
121 * Determine if a policy exists for the given model.
122 *
123 * @param mixed $model The model instance.
124 *
125 * @return bool
126 *
127 * @since 1.0.0
128 */
129 protected function has_policy($model)
130 {
131 return isset($this->policies[$model]);
132 }
133 /**
134 * Get the class name of the policy for the given model.
135 *
136 * @param mixed $model The model instance.
137 *
138 * @return string
139 *
140 * @since 1.0.0
141 */
142 protected function policy($model)
143 {
144 return $this->policies[$model];
145 }
146 /**
147 * Authorize an ability against a model instance or class.
148 *
149 * @param string $ability The ability.
150 * @param mixed $model The model instance.
151 * @param array $arguments The method arguments.
152 *
153 * @return bool|mixed
154 *
155 * @throws AuthorizationException
156 * @throws InvalidArgumentException
157 *
158 * @since 1.0.0
159 */
160 public function authorize(string $ability, $model = null, ...$arguments)
161 {
162 $user = $this->get_current_user();
163 if (!$user->is_logged_in()) {
164 throw new AuthorizationException(message('auth.logged_in_required'));
165 }
166 $policy = $this->resolve_policy($model);
167 if (!$policy) {
168 throw new AuthorizationException(message('auth.no_policy'));
169 }
170 if (\method_exists($policy, 'before')) {
171 $before_result = $policy->before($user, $ability);
172 if ($before_result === \true) {
173 return \true;
174 }
175 if ($before_result === \false) {
176 throw new AuthorizationException(message('auth.unauthorized_action', $ability));
177 }
178 }
179 if (!\method_exists($policy, $ability)) {
180 throw new AuthorizationException(message('auth.ability_not_defined', $ability));
181 }
182 $dependencies = $this->resolve_method_dependencies($policy, $ability, $this->build_arguments($arguments, $user, $model));
183 $can_perform = $policy->{$ability}(...$dependencies);
184 if (!$can_perform) {
185 throw new AuthorizationException(message('auth.unauthorized_action', $ability));
186 }
187 return \true;
188 }
189 /**
190 * Build the arguments for the policy method.
191 *
192 * @param array $arguments The method arguments.
193 * @param mixed $user The user instance.
194 * @param mixed $model The model instance.
195 *
196 * @return array
197 *
198 * @since 1.0.0
199 */
200 protected function build_arguments(array $arguments, $user, $model)
201 {
202 \array_unshift($arguments, $user, $model);
203 return $arguments;
204 }
205 /**
206 * Determine if the current user is allowed to perform the given ability.
207 *
208 * @param string $ability The ability.
209 * @param mixed $model The model instance.
210 * @param array $arguments The method arguments.
211 *
212 * @return bool
213 *
214 * @since 1.0.0
215 */
216 public function allows(string $ability, $model = null, array $arguments = [])
217 {
218 try {
219 return $this->authorize($ability, $model, $arguments);
220 } catch (AuthorizationException $exception) {
221 return \false;
222 }
223 }
224 /**
225 * Determine if the current user is denied from performing the given ability.
226 *
227 * @param string $ability The ability.
228 * @param mixed $model The model instance.
229 * @param array $arguments The method arguments.
230 *
231 * @return bool
232 *
233 * @since 1.0.0
234 */
235 public function denies(string $ability, $model = null, array $arguments = [])
236 {
237 return !$this->allows($ability, $model, $arguments);
238 }
239 /**
240 * Get the current user object.
241 *
242 * @return mixed
243 *
244 * @since 1.0.0
245 */
246 protected function get_current_user()
247 {
248 return user();
249 }
250 }
251