PluginProbe ʕ •ᴥ•ʔ
Advanced Access Manager – Access Governance for WordPress / trunk
Advanced Access Manager – Access Governance for WordPress vtrunk
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 6.9.27 6.9.28 6.9.29 6.9.3 6.9.30 6.9.31 6.9.32 6.9.33 6.9.34 6.9.35 6.9.36 6.9.37 6.9.38 6.9.39 6.9.4 6.9.41 6.9.42 6.9.43 6.9.44 6.9.45 6.9.46 6.9.47 6.9.48 6.9.49 6.9.5 6.9.51 6.9.6 6.9.7 6.9.8 6.9.9 7.0.0 7.0.0-alpha.6 7.0.0-alpha.7 7.0.0-beta.1 7.0.0-rc1 7.0.0-rc2 7.0.0-rc3 7.0.1 7.0.10 7.0.11 7.0.2 7.0.3 7.0.4 7.0.5 7.0.6 7.0.7 7.0.8 7.0.9 7.1.0 7.1.1 trunk 3.0 4.0 4.0.1 4.1 4.2 4.3 4.4 4.4.1 4.5 4.6 4.6.1 4.6.2 4.7 4.7.1 4.7.2 4.7.5 4.7.6 4.8 4.8.1 4.9 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 4.9.5.1 4.9.5.2 5.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1 5.1.1 5.10 5.11 5.2 5.2.1 5.2.5 5.2.6 5.2.7 5.3 5.3.1 5.3.2 5.3.3 5.3.4 5.3.5 5.4 5.4.1 5.4.2 5.4.3 5.4.3.1 5.4.3.2 5.5 5.5.1 5.5.2 5.6 5.6.1 5.6.1.1 5.7 5.7.1 5.7.2 5.7.3 5.8 5.8.1 5.8.2 5.8.3 5.9 5.9.1 5.9.1.1 5.9.2 5.9.2.1 5.9.3 5.9.4 5.9.5 5.9.6 5.9.6.1 5.9.6.2 5.9.6.3 5.9.7 5.9.7.1 5.9.7.2 5.9.7.3 5.9.8 5.9.8.1 5.9.9 5.9.9.1 6.0.0 6.0.1 6.0.2 6.0.3 6.0.4 6.0.5 6.1.0 6.1.1 6.2.0 6.2.1 6.2.2 6.3.0 6.3.1 6.3.2 6.3.3 6.4.0 6.4.1 6.4.2 6.4.3 6.5.0 6.5.1 6.5.2 6.5.3 6.5.4 6.6.0 6.6.1 6.6.2 6.6.3 6.6.4 6.7.0 6.7.1 6.7.2 6.7.3 6.7.4 6.7.5 6.7.6 6.7.7 6.7.8 6.7.9 6.8.0 6.8.1 6.8.2 6.8.3
advanced-access-manager / application / Service / Content.php
advanced-access-manager / application / Service Last commit date
Shortcode 4 months ago AccessDeniedRedirect.php 1 year ago AdminToolbar.php 1 year ago ApiRoute.php 1 year ago BackendMenu.php 1 year ago BaseTrait.php 1 year ago Capability.php 1 year ago Content.php 4 months ago Core.php 8 months ago Hooks.php 1 year ago Identity.php 1 month ago Jwt.php 1 month ago LoginRedirect.php 1 year ago LogoutRedirect.php 1 month ago Metaboxes.php 1 year ago NotFoundRedirect.php 1 year ago Policies.php 1 year ago SecureLogin.php 1 year ago SecurityAudit.php 1 year ago Shortcodes.php 4 months ago Urls.php 1 year ago Welcome.php 1 year ago Widgets.php 1 year ago
Content.php
853 lines
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 * Content (aka Posts & Terms) service
12 *
13 * @package AAM
14 * @version 7.0.0
15 */
16 class AAM_Service_Content
17 {
18
19 use AAM_Service_BaseTrait;
20
21 /**
22 * Default configurations
23 *
24 * @version 7.0.6
25 */
26 const DEFAULT_CONFIG = [
27 'service.post_types.manage_all' => false,
28 'service.taxonomies.manage_all' => false,
29 'service.posts.decorate_teaser' => true
30 ];
31
32 /**
33 * Collection of post type caps
34 *
35 * This is a collection of post type capabilities for optimization reasons. It
36 * is used by _map_meta_cap method to determine if additional check needs to be
37 * perform
38 *
39 * @var array
40 * @access private
41 *
42 * @version 7.0.0
43 */
44 private $_content_capabilities = array(
45 'edit_post', 'edit_page', 'read_post', 'read_page', 'publish_post'
46 );
47
48 /**
49 * Constructor
50 *
51 * @return void
52 * @access protected
53 *
54 * @version 7.0.4
55 */
56 protected function __construct()
57 {
58 add_filter('aam_get_config_filter', function($result, $key) {
59 if (empty($result) && array_key_exists($key, self::DEFAULT_CONFIG)) {
60 $result = self::DEFAULT_CONFIG[$key];
61 }
62
63 return $result;
64 }, 10, 2);
65
66 // Register RESTful API
67 AAM_Restful_Content::bootstrap();
68
69 add_action('init', function() {
70 $this->initialize_hooks();
71 }, PHP_INT_MAX);
72 }
73
74 /**
75 * Initialize Content service hooks
76 *
77 * @return void
78 * @access protected
79 *
80 * @version 7.0.4
81 */
82 protected function initialize_hooks()
83 {
84 if (is_admin()) {
85 // Hook that initialize the AAM UI part of the service
86 add_action('aam_initialize_ui_action', function () {
87 AAM_Backend_Feature_Main_Content::register();
88 });
89
90 // Check if Access Manager metabox feature is enabled
91 $metaboxEnabled = AAM::api()->config->get(
92 'core.settings.ui.render_access_metabox'
93 );
94
95 if ($metaboxEnabled) {
96 // Register custom access control metabox
97 add_action(
98 'add_meta_boxes',
99 function() {
100 $this->_register_access_manager_metabox();
101 }
102 );
103 }
104 }
105
106 if (!is_admin()) {
107 // Password protected filter
108 add_filter('post_password_required', function($result, $post) {
109 return $this->_is_password_protected($result, $post);
110 }, 10, 2);
111
112 // Manage password check expiration
113 add_filter('post_password_expires', function($result) {
114 return $this->_post_password_expires($result);
115 });
116
117 // Filter navigation pages & taxonomies
118 add_filter('wp_get_nav_menu_items', function($pages) {
119 return $this->_get_nav_menu_items($pages);
120 }, PHP_INT_MAX);
121
122 // Manage access to frontend posts & pages
123 add_action('wp', function() {
124 global $wp_query;
125
126 if (is_single()
127 || is_page()
128 || is_post_type_archive()
129 || $wp_query->is_posts_page
130 ) {
131 $this->_authorize_post_access();
132 }
133 }, PHP_INT_MAX);
134 }
135
136 // Control post visibility
137 add_filter('posts_clauses_request', function($clauses, $query) {
138 return $this->_posts_clauses_request($clauses, $query);
139 }, 10, 2);
140
141 // Evaluate if current user can see full content or only a teaser message
142 add_filter(
143 'the_content',
144 function($content) {
145 return $this->_the_content($content);
146 }, PHP_INT_MAX
147 );
148
149 // Evaluate if user can comment on a post
150 add_filter('comments_open', function ($open, $post_id) {
151 // If Leave Comments option is defined then override the default status.
152 // Otherwise keep it as-is
153 if (AAM::api()->posts()->is_denied_to($post_id, 'comment')) {
154 $open = false;
155 }
156
157 return $open;
158 }, 10, 2);
159
160 // Check if user has ability to perform certain task based on provided
161 // capability and meta data
162 add_filter('map_meta_cap', function($caps, $cap, $_, $args) {
163 return $this->_map_meta_cap($caps, $cap, $args);
164 }, PHP_INT_MAX, 4);
165
166 // REST API action authorization. Triggered before call is dispatched
167 add_filter(
168 'rest_request_before_callbacks',
169 function($response, $_, $request) {
170 return $this->_rest_request_before_callbacks($response, $request);
171 }, 10, 3
172 );
173
174 // Audit all registered post types and adjust access controls accordingly
175 foreach(get_post_types([], 'objects') as $post_type) {
176 // REST API. Control if user is allowed to publish content
177 add_filter("rest_pre_insert_{$post_type->name}", function ($post, $request) {
178 $status = (isset($request['status']) ? $request['status'] : null);
179
180 if (in_array($status, array('publish', 'future'), true)) {
181 $post_id = intval($request['id']);
182
183 if (AAM::api()->posts()->is_denied_to($post_id, 'publish')) {
184 $post = new WP_Error(
185 'rest_cannot_publish',
186 'You are not allowed to publish this content',
187 [ 'status' => rest_authorization_required_code() ]
188 );
189 }
190 }
191
192 return $post;
193 }, 10, 2);
194
195 // Populate the collection of post type caps
196 foreach ([ 'edit_post', 'read_post', 'delete_post', 'publish_posts' ] as $cap) {
197 $meta_cap = $post_type->cap->{$cap};
198
199 if (!empty($meta_cap)
200 && !in_array($meta_cap, $this->_content_capabilities, true)
201 && ($meta_cap !== 'do_not_allow')
202 ) {
203 $this->_content_capabilities[] = $cap;
204 }
205 }
206 }
207 }
208
209 /**
210 * Main frontend access control hook
211 *
212 * @return void
213 *
214 * @access private
215 * @global WP_Query $wp_query
216 *
217 * @version 7.0.3
218 */
219 private function _authorize_post_access()
220 {
221 $post = AAM::api()->misc->get_current_post();
222
223 if (!empty($post)) {
224 $service = AAM::api()->posts();
225
226 if ($service->is_restricted($post)) {
227 AAM::api()->redirect->do_access_denied_redirect();
228 } elseif ($service->is_redirected($post)) {
229 AAM::api()->redirect->do_redirect($service->get_redirect($post));
230 }
231 }
232 }
233
234 /**
235 * Check if post is password protected
236 *
237 * This callback is used by the Frontend to determine if current post requires
238 * password in order to see its content
239 *
240 * @param boolean $result
241 * @param WP_Post $post
242 *
243 * @return boolean
244 * @access private
245 *
246 * @version 7.0.0
247 */
248 private function _is_password_protected($result, $post)
249 {
250 // Honor the manually set password on the post
251 if (($result === false) && is_a($post, 'WP_Post')) {
252 $result = is_wp_error($this->_verify_post_password($post));
253 }
254
255 return $result;
256 }
257
258 /**
259 * Check PASSWORD PROTECTED access option
260 *
261 * If post has password set, return WP_Error so the application can do further
262 * authorization process.
263 *
264 * @param WP_Post $post
265 *
266 * @return boolean|WP_Error
267 * @access private
268 *
269 * @version 7.0.0
270 */
271 private function _verify_post_password($post)
272 {
273 $result = true;
274
275 if (AAM::api()->posts()->is_password_protected($post)) {
276 // Load hash checker
277 if (!class_exists('PasswordHash')) {
278 require_once ABSPATH . WPINC . '/class-phpass.php';
279 }
280
281 $checker = new PasswordHash(8, true);
282
283 // If password is empty or not provided, try to read it from the cookie.
284 // This is the default WordPress behavior when it comes to password
285 // protected posts/pages
286 $is_matched = $checker->CheckPassword(
287 AAM::api()->posts()->get_password($post),
288 wp_unslash(AAM::api()->misc->get(
289 $_COOKIE, 'wp-postpass_' . COOKIEHASH, ''
290 ))
291 );
292
293 if ($is_matched === false) {
294 $result = new WP_Error(
295 'rest_unauthorized',
296 'The post is password protected. Invalid password provided.',
297 array('status' => 401)
298 );
299 }
300 }
301
302 return $result;
303 }
304
305 /**
306 * Redefine entered password TTL
307 *
308 * @param int $expire
309 *
310 * @return int
311 * @access private
312 *
313 * @version 7.0.0
314 */
315 private function _post_password_expires($expire)
316 {
317 $ttl = AAM::api()->config->get(
318 'service.content.password_ttl', null
319 );
320
321 return !empty($ttl) ? time() + strtotime($ttl) : $expire;
322 }
323
324 /**
325 * Register Access Manager metabox on post edit screen
326 *
327 * @return void
328 * @access private
329 *
330 * @version 7.0.0
331 */
332 private function _register_access_manager_metabox()
333 {
334 global $post;
335
336 if (is_a($post, 'WP_Post')) {
337 add_meta_box(
338 'aam-access-manager',
339 __('Access Manager', 'advanced-access-manager'),
340 function () {
341 global $post;
342
343 echo AAM_Backend_View::renderPostMetabox($post);
344 },
345 null,
346 'advanced',
347 'high'
348 );
349 }
350 }
351
352 /**
353 * Filter traditional navigation menu
354 *
355 * @param array $pages
356 *
357 * @return array
358 * @access private
359 *
360 * @version 7.0.0
361 */
362 private function _get_nav_menu_items($pages)
363 {
364 if (is_array($pages)) {
365 $service = AAM::api()->posts();
366
367 foreach ($pages as $i => $page) {
368 if (in_array($page->type, array('post_type', 'custom'), true)) {
369 if ($service->is_hidden($page->object_id)) {
370 unset($pages[$i]);
371 }
372 }
373 }
374 }
375
376 return $pages;
377 }
378
379 /**
380 * After post SELECT query
381 *
382 * @param array $clauses
383 * @param WP_Query $wpQuery
384 *
385 * @return array
386 * @access private
387 *
388 * @version 7.0.0
389 */
390 private function _posts_clauses_request($clauses, $wp_query)
391 {
392 static $executing = false;
393
394 if (!$wp_query->is_singular && !$executing) {
395 $executing = true;
396
397 $clauses['where'] .= apply_filters(
398 'aam_posts_where_clause_filter',
399 $this->_prepare_post_query($wp_query),
400 $wp_query
401 );
402
403 $executing = false;
404 }
405
406 return $clauses;
407 }
408
409 /**
410 * Modify content query to hide posts
411 *
412 * @param WP_Query $wp_query
413 *
414 * @return string
415 * @access private
416 *
417 * @version 7.0.0
418 */
419 private function _prepare_post_query($wp_query)
420 {
421 global $wpdb;
422
423 if (!empty($wp_query->query['post_type'])) {
424 $post_type = $wp_query->query['post_type'];
425 } elseif (!empty($wp_query->query_vars['post_type'])) {
426 $post_type = $wp_query->query_vars['post_type'];
427 } elseif ($wp_query->is_attachment) {
428 $post_type = 'attachment';
429 } elseif ($wp_query->is_page) {
430 $post_type = 'page';
431 } else {
432 $post_type = 'any';
433 }
434
435 if ($post_type === 'any') {
436 $post_type = array_keys(get_post_types(array(), 'names'));
437 }
438
439 $area = AAM::api()->misc->get_current_area();
440 $post_types = (array) $post_type;
441 $not_in = [];
442
443 foreach (AAM::api()->posts()->aggregate() as $id => $perms) {
444 // Extracting post attributes
445 list($post_id, $post_type) = explode('|', $id);
446
447 // Extracting post LIST permission
448 $perm = isset($perms['list']) ? $perms['list'] : null;
449
450 if (is_array($perm)
451 && (empty($perm['on']) || in_array($area, $perm['on'], true))
452 && ($perm['effect'] !== 'allow')
453 && in_array($post_type, $post_types, true)
454 ) {
455 $not_in[] = $post_id;
456 }
457 }
458
459 if (!empty($not_in)) {
460 $query = " AND {$wpdb->posts}.ID NOT IN (" . implode(',', $not_in) . ")";
461 } else {
462 $query = '';
463 }
464
465 return $query;
466 }
467
468 /**
469 * Authorize RESTful action before it is dispatched by RESTful Server
470 *
471 * @param mixed $response
472 * @param object $request
473 *
474 * @return mixed
475 * @access private
476 *
477 * @version 7.0.3
478 */
479 private function _rest_request_before_callbacks($response, $request)
480 {
481 // Register hooks that check post access
482 foreach (get_post_types(array('show_in_rest' => true)) as $type) {
483 add_filter(
484 "rest_prepare_{$type}", function($response, $post, $request) {
485 if ($request->get_param('context') !== 'edit') {
486 $response = $this->_authorize_post_rest_access(
487 $response, $post, $request
488 );
489 }
490
491 return $response;
492 }, 10, 3
493 );
494 }
495
496 // Override the password authentication handling ONLY for posts
497 $attrs = $request->get_attributes();
498 $callback = isset($attrs['callback']) ? $attrs['callback'] : null;
499 $controller = (is_array($callback) ? array_shift($callback) : null);
500
501 if (is_a($controller, 'WP_REST_Posts_Controller')) {
502 $post = get_post($request['id']);
503 $has_pass = isset($request['password']);
504
505 // Honor the manually defined password on the post
506 if (is_a($post, 'WP_Post')
507 && empty($post->post_password)
508 && $has_pass
509 && ($request->get_method() === 'GET')
510 ) {
511 $request['_password'] = $request['password'];
512 unset($request['password']);
513 }
514 }
515
516 return $response;
517 }
518
519 /**
520 * Check if post is allowed to be viewed through RESTful
521 *
522 * @param WP_REST_Response $response
523 * @param WP_Post $post
524 * @param WP_REST_Request $request
525 *
526 * @access public
527 * @return WP_REST_Response
528 *
529 * @version 7.0.3
530 */
531 private function _authorize_post_rest_access($response, $post, $request)
532 {
533 $service = AAM::api()->posts();
534
535 if ($service->is_password_protected($post)) {
536 $password = isset($request['_password']) ? $request['_password'] : null;
537
538 if ($service->get_password($post) !== $password) {
539 $response->set_status(401);
540 $response->set_data([
541 'code' => 'rest_unauthorized',
542 'message' => 'The post is password protected. Invalid password provided.'
543 ]);
544 }
545 } elseif ($service->is_redirected($post)) {
546 $redirect = $service->get_redirect($post);
547
548 // Determine redirect HTTP status code and use it if applicable for given
549 // redirect type
550 if (!empty($redirect['http_status_code'])) {
551 $status_code = $redirect['http_status_code'];
552 } else {
553 $status_code = 307;
554 }
555
556 $response->set_status($status_code);
557 $response->set_data([
558 'code' => 'rest_redirected',
559 'message' => 'The request is redirected to a different location',
560 'data' => [
561 'redirect_url' => AAM::api()->redirect->to_redirect_url(
562 $redirect
563 )
564 ]
565 ]);
566 } elseif ($service->is_restricted($post)) {
567 $response->set_status(401);
568 $response->set_data([
569 'code' => 'rest_unauthorized',
570 'message' => 'The content is restricted.'
571 ]);
572 }
573
574 return $response;
575 }
576
577 /**
578 * Filter post content
579 *
580 * @param string $content
581 *
582 * @return string
583 * @access private
584 *
585 * @version 7.0.6
586 */
587 private function _the_content($content)
588 {
589 static $in = false;
590
591 if (!$in) {
592 $in = true;
593 $post = AAM::api()->misc->get_current_post();
594
595 if (!empty($post)){
596 if (AAM::api()->posts()->is_teaser_message_set($post)) {
597 // Replace the [excerpt] placeholder with posts excerpt and do
598 // short-code evaluation
599 $content = do_shortcode(str_replace(
600 '[excerpt]',
601 $post->post_excerpt,
602 AAM::api()->posts()->get_teaser_message($post)
603 ));
604
605 // Decorate message
606 if (AAM::api()->config->get('service.posts.decorate_teaser')) {
607 $content = apply_filters('the_content', $content);
608 }
609 }
610 }
611
612 $in = false;
613 }
614
615 return $content;
616 }
617
618 /**
619 * Check user capability
620 *
621 * This is a hack function that add additional layout on top of WordPress
622 * core functionality. Based on the capability passed in the $args array as
623 * "0" element, it performs additional check on user's capability to manage
624 * post, users etc.
625 *
626 * @param array $caps
627 * @param string $cap
628 * @param array $args
629 *
630 * @return array
631 * @access private
632 *
633 * @version 7.0.0
634 */
635 private function _map_meta_cap($caps, $cap, $args)
636 {
637 global $post;
638
639 // For optimization reasons, check only caps that belong to registered post
640 // types
641 if (in_array($cap, $this->_content_capabilities, true)) {
642 // Critical part of the implementation. We do not know ahead what
643 // capability is responsible for what action when it comes to post types.
644 if (isset($args[0]) && is_scalar($args[0])) {
645 $post_id = intval($args[0]);
646 } elseif (is_a($post, 'WP_Post')) {
647 $post_id = $post->ID;
648 } else {
649 $post_id = null;
650 }
651
652 // If post_id is not empty, then, potentially we are checking
653 // permission to perform one of the action against a post
654 if (!empty($post_id)) {
655 if (is_a($post, WP_Post::class) && $post_id === $post->ID) {
656 $p = $post;
657 } else {
658 $p = get_post($post_id);
659 }
660
661 if (is_a($p, 'WP_Post')) {
662 $post_type = get_post_type_object($p->post_type);
663
664 if (is_a($post_type, 'WP_Post_Type')) {
665 $caps = $this->__map_post_type_caps(
666 $post_type,
667 $cap,
668 $caps,
669 $p,
670 $args
671 );
672 }
673 }
674 }
675 }
676
677 return $caps;
678 }
679
680 /**
681 * Map post type capability based on set permissions
682 *
683 * @param WP_Post_Type $post_type
684 * @param string $cap
685 * @param array $caps
686 * @param WP_Post $post
687 * @param array $args
688 *
689 * @return array
690 * @access private
691 *
692 * @version 7.0.10
693 */
694 private function __map_post_type_caps(
695 WP_Post_Type $post_type,
696 $cap,
697 $caps,
698 WP_Post $post,
699 $args
700 ) {
701 // Cover the scenario when $cap is not part of the post type capabilities
702 // There is a bug in the WP core when user is checked for 'publish_post'
703 // capability
704 $primitive_cap = array_search($cap, (array) $post_type->cap);
705
706 if ($primitive_cap === false) {
707 $primitive_cap = $cap;
708 }
709
710 switch ($primitive_cap) {
711 case 'edit_post':
712 case 'edit_posts':
713 case 'edit_others_posts':
714 case 'edit_private_posts':
715 case 'edit_published_posts':
716 // Cover the scenario when user uses Bulk Action or Quick Edit to
717 // change the Status to Published and post is not allowed to be
718 // published
719 $action = AAM::api()->misc->get($_SERVER, 'action');
720 $status = AAM::api()->misc->get($_SERVER, '_status');
721
722 if (
723 in_array($action, [ 'edit', 'inline-save'] , true)
724 && $status === 'publish'
725 ) {
726 $caps = $this->_map_publish_post_caps($caps, $post->ID);
727 } else {
728 $caps = $this->_map_edit_post_caps($caps, $post->ID);
729 }
730 break;
731
732 case 'delete_post':
733 case 'delete_posts':
734 case 'delete_private_posts':
735 case 'delete_published_posts':
736 case 'delete_others_posts':
737 $caps = $this->_map_delete_post_caps($caps, $post->ID);
738 break;
739
740 case 'read_post':
741 case 'read_private_posts':
742 $password = (isset($args[1]) ? $args[1] : null);
743 $caps = $this->_map_read_post_caps($caps, $post->ID, $password);
744 break;
745
746 case 'publish_post':
747 case 'publish_posts':
748 $caps = $this->_map_publish_post_caps($caps, $post->ID);
749 break;
750
751 default:
752 break;
753 }
754
755 return $caps;
756 }
757
758 /**
759 * Mutate capability meta map based on ability to publish the post
760 *
761 * @param array $caps
762 * @param int $post_id
763 *
764 * @return array
765 * @access private
766 *
767 * @version 7.0.0
768 */
769 private function _map_publish_post_caps($caps, $post_id)
770 {
771 if (AAM::api()->posts()->is_denied_to($post_id, 'publish')) {
772 $caps[] = 'do_not_allow';
773 }
774
775 return $caps;
776 }
777
778 /**
779 * Mutate capability meta map based on ability to edit/update the post
780 *
781 * @param array $caps
782 * @param int $post_id
783 *
784 * @return array
785 * @access private
786 *
787 * @version 7.1.0
788 */
789 private function _map_edit_post_caps($caps, $post_id)
790 {
791 $post = get_post($post_id);
792
793 if (is_a($post, WP_Post::class)) {
794 $is_draft = $post->post_status === 'auto-draft';
795
796 if (!$is_draft && (AAM::api()->posts()->is_denied_to($post, 'edit'))) {
797 $caps[] = 'do_not_allow';
798 }
799 }
800
801 return $caps;
802 }
803
804 /**
805 * Mutate capability meta map based on ability to trash/delete the post
806 *
807 * @param array $caps
808 * @param int $post_id
809 *
810 * @return array
811 * @access private
812 *
813 * @version 7.0.0
814 */
815 private function _map_delete_post_caps($caps, $post_id)
816 {
817 if (AAM::api()->posts()->is_denied_to($post_id, 'delete')) {
818 $caps[] = 'do_not_allow';
819 }
820
821 return $caps;
822 }
823
824 /**
825 * Mutate capability meta map based on ability to edit/update the post
826 *
827 * @param array $caps
828 * @param int $post_id
829 * @param string|null $password
830 *
831 * @return array
832 * @access private
833 *
834 * @version 7.0.2
835 */
836 private function _map_read_post_caps($caps, $post_id, $password = null)
837 {
838 $service = AAM::api()->posts();
839
840 if ($service->is_password_protected($post_id)) {
841 if ($service->get_password($post_id) !== $password) {
842 $caps[] = 'do_not_allow';
843 }
844 } elseif ($service->is_restricted($post_id)) {
845 $caps[] = 'do_not_allow';
846 } elseif ($service->is_teaser_message_set($post_id)) {
847 $caps[] = 'do_not_allow';
848 }
849
850 return $caps;
851 }
852
853 }