PluginProbe
Advanced Access Manager – Access Governance for WordPress / 6.9.26
Advanced Access Manager – Access Governance for WordPress v6.9.26
7.1.4 7.1.2 7.1.3 6.8.4 6.8.5 6.9.0 6.9.1 6.9.10 6.9.11 6.9.12 6.9.13 6.9.14 6.9.15 6.9.16 6.9.17 6.9.18 6.9.19 6.9.2 6.9.20 6.9.21 6.9.22 6.9.23 6.9.24 6.9.25 6.9.26 All 210 releases
advanced-access-manager / application / Core / Object.php
Object.php
506 lines 11.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * ======================================================================
5 * LICENSE: This file is subject to the terms and conditions defined in *
6 * file 'license.txt', which is part of this source code package. *
7 * ======================================================================
8 */
9
10 /**
11 * Abstract class that represents AAM object concept
12 *
13 * AAM Object is a website resource that you manage access to for users, roles or
14 * visitors. For example, it can be any website post, page, term, backend menu etc.
15 *
16 * On another hand, AAM Object is a “container” with specific settings for any user,
17 * role or visitor. For example login, logout redirect, default category or access
18 * denied redirect rules.
19 *
20 * @since 6.9.12 https://github.com/aamplugin/advanced-access-manager/issues/285
21 * @since 6.3.3 Change visibility level for the setExplicitOption method
22 * @since 6.1.0 Significant improvement to the inheritance mechanism. Documented
23 * the class
24 * @since 6.0.5 Added `getExplicitOption` method
25 * @since 6.0.0 Initial implementation of the class
26 *
27 * @package AAM
28 * @version 6.9.12
29 */
30 abstract class AAM_Core_Object
31 {
32
33 /**
34 * Core object slug
35 *
36 * The slug should be unique identifier for the type of object (e.g. menu, post)
37 *
38 * @version 6.0.0
39 */
40 const OBJECT_TYPE = null;
41
42 /**
43 * Subject
44 *
45 * Current subject access settings belong to
46 *
47 * @var AAM_Core_Subject
48 *
49 * @access private
50 * @version 6.0.0
51 */
52 private $_subject = null;
53
54 /**
55 * Object Id
56 *
57 * Some objects may have unique identifier like each post or term has unique
58 * auto-incremented ID, or post type - unique slug. Other objects, like menu,
59 * toolbar, do not have unique.
60 *
61 * @var int|string|null
62 *
63 * @access private
64 * @version 6.0.0
65 */
66 private $_id = null;
67
68 /**
69 * Object access options
70 *
71 * Array of access options or settings. Depending on object, the structure of
72 * options may vary. Typically it is an associated array of key/value pairs,
73 * however in some cases it is multi-dimensional array of settings.
74 *
75 * @var array
76 *
77 * @access private
78 * @version 6.0.0
79 */
80 private $_option = array();
81
82 /**
83 * Explicit options (not inherited from parent subjects)
84 *
85 * When object is obtained through AAM_Core_Subject::getObject method, it already
86 * contains the final set of the settings, inherited from the parent subjects.
87 * This properly contains access settings that are explicitly defined for current
88 * subject.
89 *
90 * @var array
91 *
92 * @access private
93 * @version 6.0.0
94 */
95 private $_explicitOption = array();
96
97 /**
98 * Overwritten indicator
99 *
100 * If settings for specific object were detected before inheritance mechanism
101 * kicked off, then it is considered overwritten
102 *
103 * @var boolean
104 *
105 * @access private
106 * @version 6.0.0
107 */
108 private $_overwritten = false;
109
110 /**
111 * Constructor
112 *
113 * @param AAM_Core_Subject $subject Requested subject
114 * @param mixed $id Object ID if applicable
115 *
116 * @return void
117 *
118 * @since 6.1.0 Removed $suppressFilters param
119 * @since 6.0.0 Initial implementation of the method
120 *
121 * @access public
122 * @version 6.0.0
123 */
124 public function __construct(AAM_Core_Subject $subject, $id = null)
125 {
126 $this->setSubject($subject);
127 $this->setId($id);
128 $this->initialize();
129 }
130
131 /**
132 * Initialize access options
133 *
134 * @return void
135 *
136 * @access protected
137 * @version 6.0.0
138 */
139 abstract protected function initialize();
140
141 /**
142 * Fallback to avoid any issues with previous versions
143 *
144 * If DEBUG mode is enabled, the error message states that invoking method does
145 * not exist
146 *
147 * @param string $function Invoking method
148 * @param array $args Method's arguments
149 *
150 * @return void
151 *
152 * @since 6.1.0 Do not localize internal error message
153 * @since 6.0.0 Initial implementation of the method
154 *
155 * @see _doing_it_wrong
156 * @access public
157 * @version 6.1.0
158 */
159 public function __call($function, $args)
160 {
161 _doing_it_wrong(
162 $function,
163 sprintf('AAM object function %s is not defined', $function),
164 AAM_VERSION
165 );
166 }
167
168 /**
169 * Set current subject
170 *
171 * Either it is User, Role, Visitor or Default
172 *
173 * @param AAM_Core_Subject $subject
174 *
175 * @return void
176 *
177 * @access public
178 * @version 6.0.0
179 */
180 public function setSubject(AAM_Core_Subject $subject)
181 {
182 $this->_subject = $subject;
183 }
184
185 /**
186 * Get current Subject
187 *
188 * @return AAM_Core_Subject
189 *
190 * @access public
191 * @version 6.0.0
192 */
193 public function getSubject()
194 {
195 return $this->_subject;
196 }
197
198 /**
199 * Set current object Id
200 *
201 * @param int|string $id
202 *
203 * @return void
204 *
205 * @access public
206 * @version 6.0.0
207 */
208 public function setId($id)
209 {
210 $this->_id = $id;
211 }
212
213 /**
214 * Get current object Id
215 *
216 * @return int|string
217 *
218 * @access public
219 * @version 6.0.0
220 */
221 public function getId()
222 {
223 return $this->_id;
224 }
225
226 /**
227 * Set object options
228 *
229 * @param array $option
230 *
231 * @return AAM_Core_Object
232 *
233 * @access public
234 * @version 6.0.0
235 */
236 public function setOption(array $option)
237 {
238 $this->_option = $option;
239
240 return $this;
241 }
242
243 /**
244 * Get object options
245 *
246 * @return array
247 *
248 * @access public
249 * @version 6.0.0
250 */
251 public function getOption()
252 {
253 return $this->_option;
254 }
255
256 /**
257 * Get specific access property
258 *
259 * @param string $property
260 * @param mixed $default
261 *
262 * @return mixed
263 *
264 * @access public
265 * @version 6.0.0
266 */
267 public function get($property, $default = null)
268 {
269 $option = $this->getOption();
270
271 $chunks = explode('.', $property);
272 $value = (isset($option[$chunks[0]]) ? $option[$chunks[0]] : null);
273
274 foreach (array_slice($chunks, 1) as $chunk) {
275 if (isset($value[$chunk])) {
276 $value = $value[$chunk];
277 } else {
278 $value = $default;
279 break;
280 }
281 }
282
283 return (is_null($value) ? $default : $value);
284 }
285
286 /**
287 * Merge options based on merging preferences
288 *
289 * @param array $options
290 *
291 * @return array
292 *
293 * @access public
294 * @version 6.0.0
295 */
296 public function mergeOption($options)
297 {
298 return AAM::api()->mergeSettings(
299 $options,
300 $this->getOption(),
301 static::OBJECT_TYPE
302 );
303 }
304
305 /**
306 * Update single option item
307 *
308 * @param string $item
309 * @param mixed $value
310 *
311 * @return AAM_Core_Object
312 *
313 * @since 6.1.0 Using explicitOptions to add new access setting instead of
314 * final options
315 * @since 6.0.0 Initial implementation of the method
316 *
317 * @access public
318 * @version 6.1.0
319 */
320 public function updateOptionItem($item, $value)
321 {
322 $option = $this->getExplicitOption();
323
324 if (isset($option[$item]) && is_array($option[$item])) {
325 $option[$item] = array_replace_recursive($option[$item], $value);
326 } else {
327 $option[$item] = $value;
328 }
329
330 // Override current set of final options to keep consistency
331 $this->setOption(array_replace_recursive($this->getOption(), $option));
332
333 $this->setExplicitOption($option);
334
335 return $this;
336 }
337
338 /**
339 * Set overwritten flat
340 *
341 * @param array $option
342 *
343 * @return void
344 *
345 * @since 6.1.0 Using explicitOptions to determine override flag instead of
346 * final options
347 * @since 6.0.0 Initial implementation of the method
348 *
349 * @access public
350 * @version 6.1.0
351 */
352 public function determineOverwritten($option)
353 {
354 $this->_overwritten = !empty($option);
355 $this->setExplicitOption(is_array($option) ? $option : array());
356 }
357
358 /**
359 * Determine if access settings are set explicitly for current subject
360 *
361 * @param string $property
362 *
363 * @return boolean
364 *
365 * @since 6.0.5 Changed the way explicit option is fetched
366 * @since 6.0.0 Initial implementation of the method
367 *
368 * @access public
369 * @version 6.0.5
370 */
371 public function isExplicit($property)
372 {
373 $option = $this->getExplicitOption();
374 $explicit = true;
375
376 $chunks = explode('.', $property);
377 $value = (isset($option[$chunks[0]]) ? $option[$chunks[0]] : null);
378
379 foreach (array_slice($chunks, 1) as $chunk) {
380 if (isset($value[$chunk])) {
381 $value = $value[$chunk];
382 } else {
383 $explicit = false;
384 break;
385 }
386 }
387
388 return $explicit;
389 }
390
391 /**
392 * Get explicit option
393 *
394 * @return array
395 *
396 * @access public
397 * @version 6.0.5
398 */
399 public function getExplicitOption()
400 {
401 return $this->_explicitOption;
402 }
403
404 /**
405 * Set explicit object option
406 *
407 * @param array $option
408 *
409 * @return object
410 *
411 * @since 6.9.12 https://github.com/aamplugin/advanced-access-manager/issues/285
412 * @since 6.3.3 Changed the method to be public
413 * @since 6.1.0 Initial implementation of the method
414 *
415 * @access protected
416 * @version 6.9.12
417 */
418 public function setExplicitOption(array $option)
419 {
420 $this->_explicitOption = $option;
421
422 return $this;
423 }
424
425 /**
426 * Check if options are overwritten
427 *
428 * @return boolean
429 *
430 * @access public
431 * @version 6.0.0
432 */
433 public function isOverwritten()
434 {
435 return $this->_overwritten;
436 }
437
438 /**
439 * Save access settings
440 *
441 * @return boolean
442 *
443 * @since 6.1.0 Using explicitOptions to save access setting instead of
444 * final options
445 * @since 6.0.0 Initial implementation of the method
446 *
447 * @access public
448 * @version 6.1.0
449 */
450 public function save()
451 {
452 return $this->getSubject()->updateOption(
453 $this->getExplicitOption(),
454 static::OBJECT_TYPE,
455 $this->getId()
456 );
457 }
458
459 /**
460 * Store access settings
461 *
462 * Facadę that combines explicit options update and persisting them in DB
463 *
464 * @param string $item
465 * @param mixed $value
466 *
467 * @return boolean
468 *
469 * @access public
470 * @version 6.4.0
471 */
472 public function store($item, $value)
473 {
474 return static::updateOptionItem($item, $value)->save();
475 }
476
477 /**
478 * Reset access settings
479 *
480 * @return boolean
481 *
482 * @access public
483 * @version 6.0.0
484 */
485 public function reset()
486 {
487 return $this->getSubject()->deleteOption(
488 static::OBJECT_TYPE,
489 $this->getId()
490 );
491 }
492
493 /**
494 * Alias for the `getOption` method
495 *
496 * @return array
497 *
498 * @access public
499 * @version 6.4.0
500 */
501 public function toArray()
502 {
503 return $this->getOption();
504 }
505
506 }