PluginProbe ʕ •ᴥ•ʔ
Advanced Access Manager – Access Governance for WordPress / 5.0
Advanced Access Manager – Access Governance for WordPress v5.0
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 / Backend / Filter.php
advanced-access-manager / Application / Backend Last commit date
Feature 8 years ago View 8 years ago Widget 8 years ago phtml 8 years ago Authorization.php 8 years ago Feature.php 8 years ago Filter.php 8 years ago Manager.php 8 years ago Subject.php 8 years ago View.php 8 years ago
Filter.php
510 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 * Backend manager
12 *
13 * @package AAM
14 * @author Vasyl Martyniuk <vasyl@vasyltech.com>
15 */
16 class AAM_Backend_Filter {
17
18 /**
19 * Instance of itself
20 *
21 * @var AAM_Backend_Filter
22 *
23 * @access private
24 */
25 private static $_instance = null;
26
27 /**
28 * pre_get_posts flag
29 */
30 protected $skip = false;
31
32 /**
33 * Initialize backend filters
34 *
35 * @return void
36 *
37 * @access protected
38 */
39 protected function __construct() {
40 //menu filter
41 add_filter('parent_file', array($this, 'filterMenu'), 999, 1);
42
43 //manager WordPress metaboxes
44 add_action("in_admin_header", array($this, 'metaboxes'), 999);
45
46 //control admin area
47 add_action('admin_notices', array($this, 'adminNotices'), -1);
48 add_action('network_admin_notices', array($this, 'adminNotices'), -1);
49 add_action('user_admin_notices', array($this, 'adminNotices'), -1);
50
51 //admin bar
52 add_action('wp_before_admin_bar_render', array($this, 'filterAdminBar'), 999);
53
54 //post restrictions
55 add_filter('page_row_actions', array($this, 'postRowActions'), 10, 2);
56 add_filter('post_row_actions', array($this, 'postRowActions'), 10, 2);
57
58 //default category filder
59 add_filter('pre_option_default_category', array($this, 'filterDefaultCategory'));
60
61 //add post filter for LIST restriction
62 if (!AAM::isAAM() && AAM_Core_Config::get('check-post-visibility', true)) {
63 add_filter('found_posts', array($this, 'filterPostCount'), 999, 2);
64 add_filter('posts_fields_request', array($this, 'fieldsRequest'), 999, 2);
65 add_action('pre_get_posts', array($this, 'preparePostQuery'), 999);
66 }
67
68 add_action('pre_post_update', array($this, 'prePostUpdate'), 10, 2);
69
70 //user profile update action
71 add_action('profile_update', array($this, 'profileUpdate'), 10, 2);
72
73 //user/role filters
74 add_filter('editable_roles', array($this, 'filterRoles'));
75 add_action('pre_get_users', array($this, 'filterUserQuery'), 999);
76 add_filter('views_users', array($this, 'filterViews'));
77
78 AAM_Backend_Authorization::bootstrap(); //bootstrap backend authorization
79 }
80
81 /**
82 * Filter the Admin Menu
83 *
84 * @param string $parent_file
85 *
86 * @return string
87 *
88 * @access public
89 */
90 public function filterMenu($parent_file) {
91 //filter admin menu
92 AAM::getUser()->getObject('menu')->filter();
93
94 return $parent_file;
95 }
96
97 /**
98 * Handle metabox initialization process
99 *
100 * @return void
101 *
102 * @access public
103 */
104 public function metaboxes() {
105 global $post;
106
107 //make sure that nobody is playing with screen options
108 if (is_a($post, 'WP_Post')) {
109 $screen = $post->post_type;
110 } elseif ($screen_object = get_current_screen()) {
111 $screen = $screen_object->id;
112 } else {
113 $screen = '';
114 }
115
116 if (AAM_Core_Request::get('init') != 'metabox') {
117 AAM::getUser()->getObject('metabox')->filterBackend($screen);
118 }
119 }
120
121 /**
122 * Manage notifications visibility
123 *
124 * @return void
125 *
126 * @access public
127 */
128 public function adminNotices() {
129 if (AAM_Core_API::capabilityExists('show_admin_notices')) {
130 if (!AAM::getUser()->hasCapability('show_admin_notices')) {
131 remove_all_actions('admin_notices');
132 remove_all_actions('network_admin_notices');
133 remove_all_actions('user_admin_notices');
134 }
135 }
136 }
137
138 /**
139 * Filter top admin bar
140 *
141 * The filter will be performed based on the Backend Menu access settings
142 *
143 * @return void
144 *
145 * @access public
146 * @global WP_Admin_Bar $wp_admin_bar
147 */
148 public function filterAdminBar() {
149 global $wp_admin_bar;
150
151 $menu = AAM::getUser()->getObject('menu');
152 foreach($wp_admin_bar->get_nodes() as $id => $node) {
153 if (!empty($node->href)) {
154 $suffix = str_replace(admin_url(), '', $node->href);
155 if ($menu->has($suffix, true)) {
156 if (empty($node->parent) && $this->hasChildren($id)) { //root level
157 $node->href = '#';
158 $wp_admin_bar->add_node($node);
159 } else {
160 $wp_admin_bar->remove_menu($id);
161 }
162 }
163 }
164 }
165 }
166
167 /**
168 * Check if specified top bar item has children
169 *
170 * @param string $id
171 *
172 * @return boolean
173 *
174 * @access protected
175 * @global WP_Admin_Bar $wp_admin_bar
176 */
177 protected function hasChildren($id) {
178 global $wp_admin_bar;
179
180 $has = false;
181
182 foreach($wp_admin_bar->get_nodes() as $node) {
183 if ($node->parent == $id) {
184 $has = true;
185 break;
186 }
187 }
188
189 return $has;
190 }
191
192 /**
193 * Post Quick Menu Actions Filtering
194 *
195 * @param array $actions
196 * @param WP_Post $post
197 *
198 * @return array
199 *
200 * @access public
201 */
202 public function postRowActions($actions, $post) {
203 $object = AAM::getUser()->getObject('post', $post->ID, $post);
204
205 //filter edit menu
206 if (!$this->isAllowed('backend.edit', $object)) {
207 if (isset($actions['edit'])) {
208 unset($actions['edit']);
209 }
210 if (isset($actions['inline hide-if-no-js'])) {
211 unset($actions['inline hide-if-no-js']);
212 }
213 }
214
215 //filter delete menu
216 if (!$this->isAllowed('backend.delete', $object)) {
217 if (isset($actions['trash'])) { unset($actions['trash']); }
218 if (isset($actions['delete'])) { unset($actions['delete']); }
219 }
220
221 //filter edit menu
222 if (!$this->isAllowed('backend.publish', $object)) {
223 if (isset($actions['inline hide-if-no-js'])) {
224 unset($actions['inline hide-if-no-js']);
225 }
226 }
227
228 return $actions;
229 }
230
231 /**
232 * Check if action is allowed
233 *
234 * This method will take in consideration also *_others action
235 *
236 * @param string $action
237 * @param AAM_Core_Object_Post $object
238 *
239 * @return boolean
240 *
241 * @access protected
242 */
243 protected function isAllowed($action, $object) {
244 $edit = $object->has($action);
245 $others = $object->has("{$action}_others");
246 $author = ($object->post_author == get_current_user_id());
247
248 return ($edit || ($others && !$author)) ? false : true;
249 }
250
251 /**
252 * Override default category if defined
253 *
254 * @param type $category
255 *
256 * @return int
257 *
258 * @access public
259 * @staticvar type $default
260 */
261 public function filterDefaultCategory($category) {
262 static $default = null;
263
264 if (is_null($default)) {
265 //check if user category is defined
266 $id = get_current_user_id();
267 $default = AAM_Core_Config::get('default.category.user.' . $id , null);
268 $roles = AAM::getUser()->roles;
269
270 if (is_null($default) && count($roles)) {
271 $default = AAM_Core_Config::get(
272 'default.category.role.' . array_shift($roles), false
273 );
274 }
275 }
276
277 return ($default ? $default : $category);
278 }
279
280 /**
281 * Filter post count for pagination
282 *
283 * @param int $counter
284 * @param WP_Query $query
285 *
286 * @return array
287 *
288 * @access public
289 */
290 public function filterPostCount($counter, $query) {
291 $filtered = array();
292
293 foreach ($query->posts as $post) {
294 if (isset($post->post_type)) {
295 $type = $post->post_type;
296 } else {
297 $type = AAM_Core_API::getQueryPostType($query);
298 }
299
300 $object = (is_scalar($post) ? get_post($post) : $post);
301
302 if (!AAM_Core_API::isHiddenPost($object, $type, 'backend')) {
303 $filtered[] = $post;
304 } else {
305 $counter--;
306 $query->post_count--;
307 }
308 }
309
310 $query->posts = $filtered;
311
312 return $counter;
313 }
314
315 /**
316 * Filter pages fields
317 *
318 * @param string $fields
319 * @param WP_Query $query
320 *
321 * @return string
322 *
323 * @access public
324 * @global WPDB $wpdb
325 */
326 public function fieldsRequest($fields, $query) {
327 global $wpdb;
328
329 $qfields = (isset($query->query['fields']) ? $query->query['fields'] : '');
330
331 if ($qfields == 'id=>parent') {
332 $author = "{$wpdb->posts}.post_author";
333 if (strpos($fields, $author) === false) {
334 $fields .= ", $author";
335 }
336
337 $status = "{$wpdb->posts}.post_status";
338 if (strpos($fields, $status) === false) {
339 $fields .= ", $status";
340 }
341
342 $type = "{$wpdb->posts}.post_type";
343 if (strpos($fields, $type) === false) {
344 $fields .= ", $type";
345 }
346 }
347
348 return $fields;
349 }
350
351 /**
352 * Prepare pre post query
353 *
354 * @param WP_Query $query
355 *
356 * @return void
357 *
358 * @access public
359 */
360 public function preparePostQuery($query) {
361 if ($this->skip === false) {
362 $this->skip = true;
363 $filtered = AAM_Core_API::getFilteredPostList($query, 'backend');
364 $this->skip = false;
365
366 if (isset($query->query_vars['post__not_in'])
367 && is_array($query->query_vars['post__not_in'])) {
368 $query->query_vars['post__not_in'] = array_merge(
369 $query->query_vars['post__not_in'], $filtered
370 );
371 } else {
372 $query->query_vars['post__not_in'] = $filtered;
373 }
374 }
375 }
376
377 /**
378 * Post update hook
379 *
380 * Clear cache if post owner changed
381 *
382 * @param int $id
383 * @param array $data
384 *
385 * @return void
386 *
387 * @access public
388 */
389 public function prePostUpdate($id, $data) {
390 $post = get_post($id);
391
392 if ($post->post_author != $data['post_author']) {
393 AAM_Core_Cache::clear($id);
394 }
395 }
396
397 /**
398 * Profile updated hook
399 *
400 * Adjust expiration time and user cache if profile updated
401 *
402 * @param int $id
403 * @param WP_User $old
404 *
405 * @return void
406 *
407 * @access public
408 */
409 public function profileUpdate($id, $old) {
410 $user = get_user_by('ID', $id);
411
412 //role changed?
413 if (implode('', $user->roles) != implode('', $old->roles)) {
414 AAM_Core_Cache::clear($id);
415
416 //check if role has expiration data set
417 $role = (is_array($user->roles) ? $user->roles[0] : '');
418 $expire = AAM_Core_API::getOption("aam-role-{$role}-expiration", '');
419
420 if ($expire) {
421 update_user_option($id, "aam-original-roles", $old->roles);
422 update_user_option($id, "aam-role-expires", strtotime($expire));
423 }
424 }
425 }
426
427 /**
428 * Filter roles
429 *
430 * @param array $roles
431 *
432 * @return array
433 */
434 public function filterRoles($roles) {
435 $userLevel = AAM_Core_API::maxLevel(AAM::getUser()->allcaps);
436
437 //filter roles
438 foreach($roles as $id => $role) {
439 $roleLevel = AAM_Core_API::maxLevel($role['capabilities']);
440 if ($userLevel < $roleLevel) {
441 unset($roles[$id]);
442 }
443 }
444
445 return $roles;
446 }
447
448 /**
449 * Filter user query
450 *
451 * Exclude all users that have higher user level
452 *
453 * @param object $query
454 *
455 * @access public
456 *
457 * @return void
458 */
459 public function filterUserQuery($query) {
460 //current user max level
461 $max = AAM_Core_API::maxLevel(AAM::getUser()->allcaps);
462 $exclude = array();
463 $roles = AAM_Core_API::getRoles();
464
465 foreach($roles->role_objects as $id => $role) {
466 if (AAM_Core_API::maxLevel($role->capabilities) > $max) {
467 $exclude[] = $id;
468 }
469 }
470
471 $query->query_vars['role__not_in'] = $exclude;
472 }
473
474 /**
475 * Filter user list view options
476 *
477 * @param array $views
478 *
479 * @return array
480 *
481 * @access public
482 */
483 public function filterViews($views) {
484 $max = AAM_Core_API::maxLevel(AAM::getUser()->allcaps);
485 $roles = AAM_Core_API::getRoles();
486
487 foreach($roles->role_objects as $id => $role) {
488 if (isset($views[$id])
489 && AAM_Core_API::maxLevel($role->capabilities) > $max) {
490 unset($views[$id]);
491 }
492 }
493
494 return $views;
495 }
496
497 /**
498 * Register backend filters and actions
499 *
500 * @return void
501 *
502 * @access public
503 */
504 public static function register() {
505 if (is_null(self::$_instance)) {
506 self::$_instance = new self;
507 }
508 }
509
510 }