PluginProbe ʕ •ᴥ•ʔ
PublishPress Capabilities – User Role Editor, Access Permissions, User Capabilities, Admin Menus / trunk
PublishPress Capabilities – User Role Editor, Access Permissions, User Capabilities, Admin Menus vtrunk
2.45.0 2.44.0 trunk 1.10 1.10.1 1.4.1 1.4.10 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5 1.5.1 1.5.10 1.5.11 1.5.2 1.5.3 1.5.4 1.5.5 1.5.7 1.5.8 1.5.9 1.6 1.6.1 1.7 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.8.1 1.9 1.9.10 1.9.12 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.9 2.0 2.0.2 2.0.3 2.1 2.1.1 2.10.0 2.10.1 2.10.2 2.10.3 2.11.1 2.12.1 2.12.2 2.13.0 2.14.0 2.15.0 2.16.0 2.17.0 2.18.0 2.18.2 2.19.0 2.19.1 2.19.2 2.2 2.2.1 2.20.0 2.21.0 2.22.0 2.23.0 2.3 2.3.1 2.3.2 2.3.3 2.3.4 2.3.5 2.3.6 2.30.0 2.31.0 2.32.0 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.40.0 2.41.0 2.42.0 2.43.0 2.5.0 2.5.1 2.5.2 2.6.0 2.6.1 2.7.0 2.7.1 2.8.0 2.8.1 2.9.0 2.9.1
capability-manager-enhanced / includes / manager.php
capability-manager-enhanced / includes Last commit date
admin-notices 2 months ago features 2 weeks ago plugin-capabilities 2 months ago redirects 2 months ago roles 1 month ago admin-load.php 1 month ago admin.php 2 weeks ago application-passwords.php 2 weeks ago backup-handler.php 2 weeks ago backup.php 1 month ago cap-helper.php 6 months ago dashboard.php 2 months ago extractor-capabilities.php 6 months ago filters-admin.php 6 months ago filters-woocommerce.php 6 months ago filters-wp_rest_workarounds.php 6 months ago filters.php 5 months ago functions-admin.php 2 weeks ago functions.php 2 weeks ago handler.php 2 weeks ago inflect-cme.php 6 months ago manager.php 2 weeks ago network.php 6 months ago plugin-capabilities.php 2 months ago pp-handler.php 6 months ago pp-ui.php 3 months ago publishpress-roles.php 6 months ago settings-handler.php 6 months ago settings-ui.php 2 weeks ago settings.php 6 months ago test-user-ui.php 1 month ago test-user.php 5 months ago
manager.php
1664 lines
1 <?php
2 /**
3 * PublishPress Capabilities [Free]
4 *
5 * Plugin to create and manage roles and capabilities.
6 *
7 * This is the plugin's original controller module, which is due for some refactoring.
8 * It registers and handles menus, loads javascript, and processes or routes update operations from the Capabilities screen.
9 *
10 * Note: for lower overhead, this module is only loaded for Capabilities Pro URLs.
11 * For all other wp-admin URLs, menus are registered by a separate skeleton module.
12 *
13 * @author Jordi Canals, Kevin Behrens
14 * @copyright Copyright (C) 2009, 2010 Jordi Canals, (C) 2020 PublishPress
15 * @license GNU General Public License version 2
16 * @link https://publishpress.com/
17 *
18 *
19 * Copyright 2009, 2010 Jordi Canals <devel@jcanals.cat>
20 *
21 * Modifications Copyright 2020, PublishPress <help@publishpress.com>
22 *
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * version 2 as published by the Free Software Foundation.
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program. If not, see <http://www.gnu.org/licenses/>.
34 */
35
36 add_action( 'init', 'cme_update_pp_usage' ); // update early so resulting post type cap changes are applied for this request's UI construction
37
38 function cme_update_pp_usage() {
39 if ( ! empty($_REQUEST['update_filtered_types']) || ! empty($_REQUEST['update_filtered_taxonomies']) || ! empty($_REQUEST['update_detailed_taxonomies']) || ! empty($_REQUEST['SaveRole']) ) {
40 check_admin_referer('capsman-general-manager');
41
42 require_once( dirname(__FILE__).'/pp-handler.php' );
43 return _cme_update_pp_usage();
44 }
45 }
46
47 // Core WP roles to apply safeguard preventing accidental lockout from dashboard
48 function _cme_core_roles() {
49 return apply_filters( 'pp_caps_core_roles', array( 'administrator', 'editor', 'revisor', 'author', 'contributor', 'subscriber' ) );
50 }
51
52 function _cme_core_caps() {
53 $core_caps = array_fill_keys( array( 'switch_themes', 'edit_themes', 'activate_plugins', 'edit_plugins', 'edit_users', 'edit_files', 'manage_options', 'moderate_comments',
54 'manage_links', 'upload_files', 'import', 'unfiltered_html', 'read', 'delete_users', 'create_users', 'unfiltered_upload', 'edit_dashboard',
55 'update_plugins', 'delete_plugins', 'install_plugins', 'update_themes', 'install_themes',
56 'update_core', 'list_users', 'remove_users', 'promote_users', 'edit_theme_options', 'delete_themes', 'export' ), true );
57
58 ksort( $core_caps );
59 return $core_caps;
60 }
61
62 function _cme_is_read_removal_blocked( $role_name ) {
63 $role = get_role($role_name);
64
65 if (!$role || empty($role->capabilities) || !is_array($role->capabilities)) {
66 return false;
67 }
68
69 $rcaps = $role->capabilities;
70
71 $core_caps = array_diff_key( _cme_core_caps(), array_fill_keys( array( 'unfiltered_html', 'unfiltered_upload', 'upload_files', 'edit_files', 'read' ), true ) );
72
73 if ( empty( $rcaps['dashboard_lockout_ok'] ) ) {
74 $edit_caps = array();
75 foreach ( get_post_types( array( 'public' => true ), 'object' ) as $type_obj ) {
76 $edit_caps = array_merge( $edit_caps, array_values( array_diff_key( (array) $type_obj->cap, array( 'read_private_posts' => true ) ) ) );
77 }
78
79 $edit_caps = array_fill_keys( $edit_caps, true );
80 unset( $edit_caps['read'] );
81 unset( $edit_caps['upload_files'] );
82 unset( $edit_caps['edit_files'] );
83
84 if ( $role_has_admin_caps = in_array( $role_name, _cme_core_roles() ) && ( array_intersect_key( $rcaps, array_diff_key( $core_caps, array( 'read' => true ) ) ) || array_intersect_key( $rcaps, $edit_caps ) ) ) {
85 return true;
86 }
87 }
88
89 return false;
90 }
91
92 /**
93 * Class CapabilityManager.
94 * Sets the main environment for all Capability Manager components.
95 *
96 * @author Jordi Canals, Kevin Behrens
97 * @link https://publishpress.com/
98 */
99 class CapabilityManager
100 {
101 /**
102 * Array with all capabilities to be managed. (Depends on user caps).
103 * The array keys are the capability, the value is its screen name.
104 * @var array
105 */
106 var $capabilities = array();
107
108 /**
109 * Array with roles that can be managed. (Depends on user roles).
110 * The array keys are the role name, the value is its translated name.
111 * @var array
112 */
113 var $roles = array();
114
115 /**
116 * Current role we are managing
117 * @var string
118 */
119 var $current;
120
121 /**
122 * Maximum level current manager can assign to a user.
123 * @var int
124 */
125 private $max_level;
126
127 private $log_db_role_objects = array();
128
129 var $message;
130
131 var $network_sync_token;
132
133 /**
134 * Module ID. Is the module internal short name.
135 *
136 * @var string
137 */
138 public $ID;
139
140 /**
141 * Module URL.
142 *
143 * @var string
144 */
145 public $mod_url;
146
147 public function __construct()
148 {
149 $this->ID = 'capsman';
150 $this->mod_url = plugins_url( '', CME_FILE );
151
152 if (is_admin() && !empty($_REQUEST['page']) && ('pp-capabilities-settings' == $_REQUEST['page']) && !empty($_POST['all_options'])) {
153 add_action('init', function() {
154 if (isset($_REQUEST['_wpnonce']) && wp_verify_nonce($_REQUEST['_wpnonce'], 'pp-capabilities-settings') && current_user_can('manage_capabilities_settings')) {
155 require_once (dirname(CME_FILE) . '/includes/settings-handler.php');
156 }
157 }, 1);
158 }
159
160 $this->moduleLoad();
161
162 add_action('admin_menu', array($this, 'adminMenus'), 5); // execute prior to PP, to use menu hook
163
164 // Load styles
165 add_action('admin_print_styles', array($this, 'adminStyles'));
166
167 if ( isset($_REQUEST['page']) && ( 'pp-capabilities' == $_REQUEST['page'] ) ) {
168 add_action('admin_enqueue_scripts', array($this, 'adminScriptsPP'));
169 }
170
171 add_action('init', [$this, 'initRolesAdmin']);
172
173 add_action('wp_ajax_pp-roles-add-role', [$this, 'handleRolesAjax']);
174 add_action('wp_ajax_pp-roles-delete-role', [$this, 'handleRolesAjax']);
175
176 if (defined('PRESSPERMIT_VERSION')) {
177 add_action('wp_ajax_pp-roles-hide-role', [$this, 'handleRolesAjax']);
178 add_action('wp_ajax_pp-roles-unhide-role', [$this, 'handleRolesAjax']);
179 }
180
181 //process export
182 add_action( 'admin_init', [$this, 'processExport']);
183
184 //redirect for profile features capturing
185 add_action('admin_init', [$this, 'profileFeaturesCaptureRedirect']);
186
187 //Initialize plugin capabilities class
188 add_action('admin_init', [$this, 'initPluginCapabilities']);
189 }
190
191 /**
192 * Enqueues administration styles.
193 *
194 * @hook action 'admin_print_styles'
195 *
196 * @return void
197 */
198 function adminStyles()
199 {
200 if (empty($_REQUEST['page'])
201 || !in_array(
202 $_REQUEST['page'],
203 ['pp-capabilities', 'pp-capabilities-backup', 'pp-capabilities-roles', 'pp-capabilities-admin-menus', 'pp-capabilities-editor-features', 'pp-capabilities-nav-menus', 'pp-capabilities-settings', 'pp-capabilities-admin-features', 'pp-capabilities-profile-features', 'pp-capabilities-dashboard', 'pp-capabilities-frontend-features', 'pp-capabilities-redirects', 'pp-capabilities-admin-styles', 'pp-capabilities-admin-notices']
204 )
205 ) {
206 return;
207 }
208
209 wp_enqueue_style('cme-admin-common', $this->mod_url . '/common/css/pressshack-admin.css', [], PUBLISHPRESS_CAPS_VERSION);
210
211 wp_register_style( $this->ID . 'framework_admin', $this->mod_url . '/framework/styles/admin.css', false, PUBLISHPRESS_CAPS_VERSION);
212 wp_enqueue_style( $this->ID . 'framework_admin');
213
214 if ('pp-capabilities' == $_REQUEST['page']) {
215 // search script and css
216 wp_enqueue_script(
217 'capabilities-search',
218 $this->mod_url . '/common/js/capabilities-search.js',
219 ['jquery'],
220 PUBLISHPRESS_CAPS_VERSION,
221 true
222 );
223
224 wp_enqueue_style(
225 'capabilities-search',
226 $this->mod_url . '/common/css/capabilities-search.css',
227 [],
228 PUBLISHPRESS_CAPS_VERSION
229 );
230 // cap admin css
231 wp_register_style( $this->ID . '_admin', $this->mod_url . '/common/css/admin-caps.css', false, PUBLISHPRESS_CAPS_VERSION);
232 } else {
233 // @todo: remove Capabilities-specific styles from admin.css
234 wp_register_style( $this->ID . '_admin', $this->mod_url . '/common/css/admin.css', false, PUBLISHPRESS_CAPS_VERSION);
235 }
236 wp_enqueue_style( $this->ID . '_admin');
237
238 wp_enqueue_script('jquery-ui-sortable');
239
240 $suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '.dev' : '';
241 $url = $this->mod_url . "/common/js/admin{$suffix}.js";
242 wp_enqueue_script( 'cme_admin', $url, array('jquery', 'wp-i18n', 'jquery-ui-sortable'), PUBLISHPRESS_CAPS_VERSION, true );
243
244 $capNegated = '<span class="tool-tip-text">
245 <p>'. __( 'This capability is explicitly negated. Click to add/remove normally.', 'capability-manager-enhanced' ) .'</p>
246 <i></i>
247 </span>
248 X';
249
250 wp_localize_script( 'cme_admin', 'cmeAdmin', [
251 'ajaxurl' => admin_url('admin-ajax.php'),
252 'nonce' => wp_create_nonce('pp-capabilities-dashboard-nonce'),
253 'negationCaption' => __( 'Explicity negate this capability by storing as disabled', 'capability-manager-enhanced' ),
254 'typeCapsNegationCaption' => __( 'Explicitly negate these capabilities by storing as disabled', 'capability-manager-enhanced' ),
255 'typeCapUnregistered' => __( 'Post type registration does not define this capability distinctly', 'capability-manager-enhanced' ),
256 'capNegated' => $capNegated,
257 'chkCaption' => __( 'Add or remove this capability from the WordPress role', 'capability-manager-enhanced' ),
258 'switchableCaption' => __( 'Add or remove capability from the role normally', 'capability-manager-enhanced' ),
259 'deleteWarning' => __( 'Are you sure you want to delete this item ?', 'capability-manager-enhanced' ),
260 'saveWarning' => __( 'Add or clear custom item entry before saving changes.', 'capability-manager-enhanced' )
261 ]
262 );
263 }
264
265 function adminScriptsPP() {
266 wp_enqueue_style( 'plugin-install' );
267 wp_enqueue_script( 'plugin-install' );
268 add_thickbox();
269 }
270
271 /**
272 * Creates some filters at module load time.
273 *
274 * @return void
275 */
276 protected function moduleLoad ()
277 {
278 $old_version = get_option($this->ID . '_version');
279 if ( version_compare( $old_version, PUBLISHPRESS_CAPS_VERSION, 'ne') ) {
280 update_option($this->ID . '_version', PUBLISHPRESS_CAPS_VERSION);
281 $this->pluginUpdate();
282 }
283
284 // Only roles that a user can administer can be assigned to others.
285 add_filter('editable_roles', array($this, 'filterEditRoles'));
286
287 // Users with roles that cannot be managed, are not allowed to be edited.
288 add_filter('map_meta_cap', array(&$this, 'filterUserEdit'), 10, 4);
289
290 // ensure storage, retrieval of db-stored customizations to dynamic roles
291 if ( isset($_REQUEST['page']) && in_array( $_REQUEST['page'], array( 'pp-capabilities', 'pp-capabilities-backup' ) ) ) {
292 global $wpdb;
293 $role_key = $wpdb->prefix . 'user_roles';
294 $this->log_db_roles();
295 add_filter( 'option_' . $role_key, array( &$this, 'reinstate_db_roles' ), PHP_INT_MAX );
296 }
297
298 $action = (defined('PP_CAPABILITIES_COMPAT_MODE')) ? 'init' : 'publishpress_capabilities_loaded';
299 add_action( $action, array( &$this, 'processRoleUpdate' ) );
300 }
301
302 public function set_current_role($role_name) {
303 global $current_user;
304
305 if ($role_name && !empty($current_user) && !empty($current_user->ID)) {
306 update_option("capsman_last_role_{$current_user->ID}", $role_name);
307 }
308 }
309
310 public function get_last_role() {
311 global $current_user;
312
313 $role_name = get_option("capsman_last_role_{$current_user->ID}");
314
315 if ($role_name && function_exists('pp_capabilities_is_application_password_subject') && pp_capabilities_is_application_password_subject($role_name)) {
316 $current_page = (!empty($_REQUEST['page']) && is_scalar($_REQUEST['page']))
317 ? sanitize_key(wp_unslash($_REQUEST['page']))
318 : '';
319
320 if (
321 ('pp-capabilities' === $current_page)
322 && function_exists('pp_capabilities_can_manage_application_password_subject')
323 && pp_capabilities_can_manage_application_password_subject($role_name)
324 ) {
325 return sanitize_key($role_name);
326 }
327
328 $role_name = '';
329 }
330
331 if (!$role_name || !get_role($role_name)) {
332 $role_name = get_option('default_role');
333 }
334
335 return $role_name;
336 }
337
338 // Direct query of stored role definitions
339 function log_db_roles( $legacy_arg = '' ) {
340 global $wpdb;
341
342 $results = (array) maybe_unserialize( $wpdb->get_var("SELECT option_value FROM $wpdb->options WHERE option_name = '{$wpdb->prefix}user_roles' LIMIT 1") );
343 foreach( $results as $_role_name => $_role ) {
344 $this->log_db_role_objects[$_role_name] = (object) $_role;
345 }
346
347 return $legacy_arg;
348 }
349
350 // note: this is only applied when accessing the cme role edit form
351 function reinstate_db_roles( $passthru_roles = array() ) {
352 global $wp_roles;
353
354 if ( isset($wp_roles) && $this->log_db_role_objects ) {
355 $intersect = array_intersect_key( $wp_roles->role_objects, $this->log_db_role_objects );
356 foreach( array_keys( $intersect ) as $key ) {
357 if ( ! empty( $this->log_db_role_objects[$key]->capabilities ) )
358 $wp_roles->role_objects[$key]->capabilities = $this->log_db_role_objects[$key]->capabilities;
359 }
360 }
361
362 return $passthru_roles;
363 }
364
365 /**
366 * Updates Capability Manager to a new version
367 *
368 * @return void
369 */
370 protected function pluginUpdate ()
371 {
372 global $wpdb;
373
374 $backup = get_option($this->ID . '_backup');
375 if ( false === $backup ) { // No previous backup found. Save it!
376 $roles = get_option($wpdb->prefix . 'user_roles');
377 update_option( $this->ID . '_backup', $roles, false );
378 update_option( $this->ID . '_backup_datestamp', current_time( 'timestamp' ), false );
379 }
380
381 if (!pp_capabilities_get_auto_backup_option_names()) {
382 pp_capabilities_autobackup();
383 }
384 }
385
386 /**
387 * Adds admin panel menus.
388 * User needs to have 'manage_capabilities' to access this menus.
389 * This is set as an action in the parent class constructor.
390 *
391 * @hook action admin_menu
392 * @return void
393 */
394 public function adminMenus ()
395 {
396 add_action( 'admin_menu', array( &$this, 'cme_menu' ), 18 );
397 }
398
399 public function cme_menu() {
400
401 global $menu, $submenu, $capabilities_toplevel_page;
402
403 //we need to set primary menu capability to the first menu user has access to
404 $sub_menu_pages = pp_capabilities_sub_menu_lists();
405 $user_menu_caps = pp_capabilities_user_can_caps();
406 $menu_cap = false;
407 $cap_callback = false;
408 $cap_page_slug = false;
409 $cap_title = 'Capabilities'; // Pass title into add_menu_page() untranslated so hook name, body class and current_screen are not translated
410 $cap_title_i8n = __('Capabilities', 'capability-manager-enhanced');
411 $cap_name = false;
412
413 //remove caps that doesn't have menu
414 if (in_array('manage_capabilities_user_testing', $user_menu_caps)) {
415 $cap_key = array_search('manage_capabilities_user_testing', $user_menu_caps);
416 if ($cap_key !== false) {
417 unset($user_menu_caps[$cap_key]);
418 $user_menu_caps = array_filter($user_menu_caps);
419 }
420 }
421
422 if (is_multisite() && is_super_admin()) {
423 $cap_name = 'read';
424 $cap_callback = [$this, 'dashboardPage'];
425 $cap_page_slug = 'pp-capabilities-dashboard';
426 } elseif (count($user_menu_caps) > 0) {
427 $cap_name = $user_menu_caps[0];
428 $cap_index = str_replace(['manage_capabilities_', 'manage_', '_'], ['', '', '-'], $cap_name);
429 if (($cap_index !== 'capabilities') && (count($user_menu_caps) === 1)) {
430 $cap_title = $sub_menu_pages[$cap_index]['title'];
431 $using_submenu_title = true;
432 }
433 $cap_page_slug = $sub_menu_pages[$cap_index]['page'];
434 $cap_callback = $sub_menu_pages[$cap_index]['callback'];
435 }
436
437 $capabilities_toplevel_page = $cap_page_slug;
438
439 if (!$cap_name) {
440 return;
441 }
442
443 $menu_order = 72;
444
445 if (defined('PUBLISHPRESS_PERMISSIONS_MENU_GROUPING')) {
446 foreach ((array)get_option('active_plugins') as $plugin_file) {
447 if ( false !== strpos($plugin_file, 'publishpress.php') ) {
448 $menu_order = 27;
449 }
450 }
451 }
452
453 add_menu_page(
454 $cap_title,
455 $cap_title,
456 $cap_name,
457 $cap_page_slug,
458 $cap_callback,
459 'dashicons-admin-network',
460 $menu_order
461 );
462
463 // Translate plugin menu title if needed. Title was passed untranslated to avoid translating hook name, body class, current screen
464 if (($cap_title != $cap_title_i8n) && empty($using_submenu_title)) {
465 if (!empty($menu) && is_array($menu) && !defined('PP_CAPABILITIES_DISABLE_MENU_TRANSLATION_SUPPORT')) {
466 foreach ($menu as $k => $m) {
467 if (is_array($m) && isset($m[5]) && ('toplevel_page_pp-capabilities-dashboard' == $m[5])) {
468 $menu[$k][0] = $cap_title_i8n;
469 }
470 }
471 }
472 }
473
474 $dashboard_screen = (isset($_GET['page']) && $_GET['page'] === $cap_page_slug) ? true : false;
475 $submenu_slugs = [];
476 $submenu_slugs_conditions = [];
477
478 foreach ($sub_menu_pages as $feature => $subpage_option) {
479 if ($subpage_option['dashboard_control'] === false
480 || pp_capabilities_feature_enabled($feature)
481 //we'll be using css to hide menu on dashboard control screen to enable dynamic menu control
482 || $dashboard_screen
483 ) {
484 //register the menu if enabled
485 $hook = add_submenu_page($cap_page_slug, $subpage_option['title'], $subpage_option['title'], $subpage_option['capabilities'], $subpage_option['page'], $subpage_option['callback']);
486 if ($feature === 'roles' && !empty($hook)) {
487 add_action(
488 "load-$hook",
489 function () {
490 require_once(dirname(CME_FILE) . '/includes/roles/roles-functions.php');
491 admin_roles_page_load();
492 }
493 );
494 }
495 }
496 if ($dashboard_screen) {
497 $submenu_slugs[] = $subpage_option['page'];
498 $submenu_slugs_conditions[] = [ $subpage_option['page'], pp_capabilities_feature_enabled($feature)];
499 }
500 }
501
502 if ($dashboard_screen) {
503 /**
504 * Add CSS classes to these submenus to dynamically show/hide them
505 * through dashboard page enable/disable features.
506 * Copied from PublishPress Blocks
507 */
508 foreach ($submenu[$cap_page_slug] as $key => $value) {
509 if (in_array($submenu[$cap_page_slug][$key][2], $submenu_slugs)) {
510 $slug_ = $submenu[$cap_page_slug][$key][2];
511
512 // Add a class to hide menu if feature is disabled on Dashboard
513 foreach ($submenu_slugs_conditions as $item) {
514 if ($item[0] === $slug_) {
515 $showHide = $item[1] === false ? ' ppc-hide-menu-item' : '';
516 break;
517 }
518 }
519
520 $submenu[$cap_page_slug][$key][4] = $slug_ . '-menu-item' . $showHide;
521 }
522 }
523 }
524
525 }
526
527 function initRolesAdmin() {
528 // @todo: solve order of execution issue so this column headers definition is not duplicated
529 if (!empty($_REQUEST['page']) && ('pp-capabilities-roles' == $_REQUEST['page'])) {
530 add_filter(
531 "manage_capabilities_page_pp-capabilities-roles_columns",
532
533 function($arr) {
534 return [
535 'cb' => '<input type="checkbox"/>',
536 'name' => esc_html__('Role Name', 'capability-manager-enhanced'),
537 'count' => esc_html__('Users'),
538 'role_type' => esc_html__('Role Type', 'capability-manager-enhanced'),
539 'default_role' => esc_html__('Default Role', 'capability-manager-enhanced'),
540 'admin_access' => esc_html__('Admin Access', 'capability-manager-enhanced'),
541 ];
542 }
543 );
544 }
545 }
546
547 function handleRolesAjax() {
548 require_once (dirname(CME_FILE) . '/includes/roles/roles-functions.php');
549
550 if (!class_exists('PP_Capabilities_Roles')) {
551 require_once (dirname(CME_FILE) . '/includes/roles/class/class-pp-roles.php');
552 }
553
554 $roles = pp_capabilities_roles()->run();
555 }
556
557 /**
558 * Manages roles
559 *
560 * @hook add_management_page
561 * @return void
562 */
563 public function ManageRoles ()
564 {
565 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities_roles')) {
566 // TODO: Implement exceptions.
567 wp_die('<strong>' . esc_html__('You do not have permission to manage roles.', 'capability-manager-enhanced') . '</strong>');
568 }
569
570 require_once (dirname(CME_FILE) . '/includes/roles/roles-functions.php');
571
572 if (!class_exists('PP_Capabilities_Roles')) {
573 require_once (dirname(CME_FILE) . '/includes/roles/class/class-pp-roles.php');
574 }
575
576 $roles = pp_capabilities_roles()->run();
577
578 require_once ( dirname(CME_FILE) . '/includes/roles/roles.php' );
579 }
580
581
582 /**
583 * Manages Editor Features
584 *
585 * @return void
586 */
587 public function ManageEditorFeatures() {
588 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities_editor_features')) {
589 // TODO: Implement exceptions.
590 wp_die('<strong>' . esc_html__('You do not have permission to manage editor features.', 'capability-manager-enhanced') . '</strong>');
591 }
592
593 $this->generateNames();
594 $roles = array_keys($this->roles);
595
596 if (!isset($this->current)) {
597 if ('POST' !== $_SERVER['REQUEST_METHOD'] && !empty($_REQUEST['role'])) {
598 $this->set_current_role(sanitize_key($_REQUEST['role']));
599 }
600 }
601
602 if (!isset($this->current) || !get_role($this->current)) {
603 $this->current = get_option('default_role');
604 }
605
606 if (!in_array($this->current, $roles)) {
607 $this->current = array_shift($roles);
608 }
609
610 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && isset($_POST['ppc-editor-features-role']) && !empty($_REQUEST['_wpnonce'])) {
611 if (!wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'pp-capabilities-editor-features')) {
612 wp_die('<strong>' . esc_html__('You do not have permission to manage editor features.', 'capability-manager-enhanced') . '</strong>');
613 } else {
614 $this->set_current_role(sanitize_key($_POST['ppc-editor-features-role']));
615
616 $classic_editor = pp_capabilities_is_classic_editor_available();
617
618 $def_post_types = array_unique(apply_filters('pp_capabilities_feature_post_types', ['post', 'page']));
619
620 $active_tab = isset($_POST['pp_caps_tab']) ? sanitize_key($_POST['pp_caps_tab']) : 'post';
621
622 foreach ($def_post_types as $post_type) {
623 if ($classic_editor) {
624
625 if (isset($_POST['editor-features-all-submit'])){
626 $posted_settings = (isset($_POST["capsman_feature_restrict_classic_{$active_tab}"])) ? array_map('sanitize_text_field', $_POST["capsman_feature_restrict_classic_{$active_tab}"]) : [];
627 } else {
628 $posted_settings = (isset($_POST["capsman_feature_restrict_classic_{$post_type}"])) ? array_map('sanitize_text_field', $_POST["capsman_feature_restrict_classic_{$post_type}"]) : [];
629 }
630
631 $post_features_option = (array)get_option("capsman_feature_restrict_classic_{$post_type}", []);
632 $post_features_option[sanitize_key($_POST['ppc-editor-features-role'])] = $posted_settings;
633 update_option("capsman_feature_restrict_classic_{$post_type}", $post_features_option, false);
634 }
635
636 if (isset($_POST['editor-features-all-submit'])){
637 $posted_settings = (isset($_POST["capsman_feature_restrict_{$active_tab}"])) ? array_map('sanitize_text_field', $_POST["capsman_feature_restrict_{$active_tab}"]) : [];
638 }else {
639 $posted_settings = (isset($_POST["capsman_feature_restrict_{$post_type}"])) ? array_map('sanitize_text_field', $_POST["capsman_feature_restrict_{$post_type}"]) : [];
640 }
641
642 $post_features_option = (array)get_option("capsman_feature_restrict_{$post_type}", []);
643 $post_features_option[sanitize_key($_POST['ppc-editor-features-role'])] = $posted_settings;
644 update_option("capsman_feature_restrict_{$post_type}", $post_features_option, false);
645 }
646
647 ak_admin_notify(__('Settings updated.', 'capability-manager-enhanced'));
648 }
649 }
650
651 do_action('pp_capabilities_editor_features');
652 include(dirname(CME_FILE) . '/includes/features/editor-features.php');
653 }
654
655 /**
656 * Manages Admin Features
657 *
658 * @return void
659 */
660 public function ManageAdminFeatures() {
661 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities_admin_features')) {
662 // TODO: Implement exceptions.
663 wp_die('<strong>' . esc_html__('You do not have permission to manage admin features.', 'capability-manager-enhanced') . '</strong>');
664 }
665
666 $this->generateNames();
667 $roles = array_keys($this->roles);
668
669 if (!isset($this->current)) {
670 if ('POST' !== $_SERVER['REQUEST_METHOD'] && !empty($_REQUEST['role'])) {
671 $this->set_current_role(sanitize_key($_REQUEST['role']));
672 }
673 }
674
675 if (!isset($this->current) || !get_role($this->current)) {
676 $this->current = get_option('default_role');
677 }
678
679 if (!in_array($this->current, $roles)) {
680 $this->current = array_shift($roles);
681 }
682
683 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && isset($_POST['ppc-admin-features-role']) && !empty($_REQUEST['_wpnonce'])) {
684 if (!wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'pp-capabilities-admin-features')) {
685 wp_die('<strong>' . esc_html__('You do not have permission to manage admin features.', 'capability-manager-enhanced') . '</strong>');
686 } else {
687 $features_role = sanitize_key($_POST['ppc-admin-features-role']);
688
689 $this->set_current_role($features_role);
690
691 $disabled_admin_items = !empty(get_option('capsman_disabled_admin_features')) ? (array)get_option('capsman_disabled_admin_features') : [];
692 $disabled_admin_items[$features_role] = isset($_POST['capsman_disabled_admin_features']) ? array_map('sanitize_text_field', $_POST['capsman_disabled_admin_features']) : '';
693
694 update_option('capsman_disabled_admin_features', $disabled_admin_items, false);
695
696 //set reload option for instant reflection if user is updating own role
697 if (in_array($features_role, wp_get_current_user()->roles)){
698 $ppc_page_reload = '1';
699 }
700
701 ak_admin_notify(__('Settings updated.', 'capability-manager-enhanced'));
702 }
703 }
704
705 include(dirname(CME_FILE) . '/includes/features/admin-features.php');
706 }
707
708 /**
709 * Manages Frontend Features
710 *
711 * @return void
712 */
713 public function ManageFrontendFeatures() {
714 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities_frontend_features')) {
715 // TODO: Implement exceptions.
716 wp_die('<strong>' . esc_html__('You do not have permission to manage frontend features.', 'capability-manager-enhanced') . '</strong>');
717 }
718
719 $this->generateNames();
720 $roles = array_keys($this->roles);
721
722 if (!isset($this->current)) {
723 if ('POST' !== $_SERVER['REQUEST_METHOD'] && !empty($_REQUEST['role'])) {
724 $this->set_current_role(sanitize_key($_REQUEST['role']));
725 }
726 }
727
728 if (!isset($this->current) || !get_role($this->current)) {
729 $this->current = get_option('default_role');
730 }
731
732 if (!in_array($this->current, $roles)) {
733 $this->current = array_shift($roles);
734 }
735
736 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && isset($_POST['ppc-frontend-features-role']) && !empty($_REQUEST['_wpnonce'])) {
737 if (!wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'pp-capabilities-frontend-features')) {
738 wp_die('<strong>' . esc_html__('You do not have permission to manage frontend features.', 'capability-manager-enhanced') . '</strong>');
739 } else {
740 $features_role = sanitize_key($_POST['ppc-frontend-features-role']);
741
742 $this->set_current_role($features_role);
743
744 $disabled_frontend_items = !empty(get_option('capsman_disabled_frontend_features')) ? (array)get_option('capsman_disabled_frontend_features') : [];
745 $disabled_frontend_items[$features_role] = isset($_POST['capsman_disabled_frontend_features']) ? array_map('sanitize_text_field', $_POST['capsman_disabled_frontend_features']) : '';
746
747 update_option('capsman_disabled_frontend_features', $disabled_frontend_items, false);
748
749 ak_admin_notify(__('Settings updated.', 'capability-manager-enhanced'));
750 }
751 }
752
753 include(dirname(CME_FILE) . '/includes/features/frontend-features/frontend-features.php');
754 }
755
756 /**
757 * Manages Admin Styles
758 *
759 * @return void
760 */
761 public function ManageAdminStyles() {
762 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities_admin_styles')) {
763 // TODO: Implement exceptions.
764 wp_die('<strong>' . esc_html__('You do not have permission to manage admin styles.', 'capability-manager-enhanced') . '</strong>');
765 }
766
767 $this->generateNames();
768 $roles = array_keys($this->roles);
769
770 if (!isset($this->current)) {
771 if ('POST' !== $_SERVER['REQUEST_METHOD'] && !empty($_REQUEST['role'])) {
772 $this->set_current_role(sanitize_key($_REQUEST['role']));
773 }
774 }
775
776 if (!isset($this->current) || !get_role($this->current)) {
777 $this->current = get_option('default_role');
778 }
779
780 if (!in_array($this->current, $roles)) {
781 $this->current = array_shift($roles);
782 }
783
784 include(dirname(CME_FILE) . '/includes/features/admin-styles/admin-styles-ui.php');
785 }
786
787 /**
788 * Manages Admin Notices
789 *
790 * @return void
791 */
792 public function ManageAdminNotices() {
793 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities_admin_notices')) {
794 wp_die('<strong>' . esc_html__('You do not have permission to manage admin notices.', 'capability-manager-enhanced') . '</strong>');
795 }
796
797 $this->generateNames();
798 $roles = array_keys($this->roles);
799
800 if (!isset($this->current)) {
801 if ('POST' !== $_SERVER['REQUEST_METHOD'] && !empty($_REQUEST['role'])) {
802 $this->set_current_role(sanitize_key($_REQUEST['role']));
803 }
804 }
805
806 if (!isset($this->current) || !get_role($this->current)) {
807 $this->current = get_option('default_role');
808 }
809
810 if (!in_array($this->current, $roles)) {
811 $this->current = array_shift($roles);
812 }
813
814 $all_roles = wp_roles()->roles;
815
816 if ('POST' === $_SERVER['REQUEST_METHOD'] && (isset($_POST['ppc-admin-notices-submit']) || isset($_POST['ppc-admin-notices-all-submit']))) {
817 if (!wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce'] ?? ''), 'pp-capabilities-admin-notices')) {
818 wp_die('<strong>' . esc_html__('You do not have permission to manage admin notices.', 'capability-manager-enhanced') . '</strong>');
819 }
820
821 $notices_role = !empty($_POST['ppc-admin-notices-role']) ? sanitize_key($_POST['ppc-admin-notices-role']) : $this->current;
822
823 if (isset($all_roles[$notices_role])) {
824 $this->set_current_role($notices_role);
825 }
826
827 $submitted_options = isset($_POST['cme_admin_notice_options']) ? map_deep($_POST['cme_admin_notice_options'], 'sanitize_text_field') : [];
828 if (!is_array($submitted_options)) {
829 $submitted_options = [];
830 }
831
832 $all_notice_options = (array) get_option('cme_admin_notice_options', []);
833
834 if (isset($_POST['ppc-admin-notices-all-submit'])) {
835 foreach (array_keys($all_roles) as $role_key) {
836 $all_notice_options[$role_key] = $submitted_options;
837 }
838 } else {
839 $all_notice_options[$notices_role] = $submitted_options;
840 }
841
842 update_option('cme_admin_notice_options', $all_notice_options, false);
843 ak_admin_notify(__('Settings updated.', 'capability-manager-enhanced'));
844 }
845
846 include(dirname(CME_FILE) . '/includes/admin-notices/admin-notices-settings.php');
847 }
848
849 /**
850 * Manage Nave Menus
851 *
852 * @return void
853 */
854 public function ManageNavMenus() {
855 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities_nav_menus')) {
856 // TODO: Implement exceptions.
857 wp_die('<strong>' . esc_html__('You do not have permission to manage admin features.', 'capability-manager-enhanced') . '</strong>');
858 }
859
860 $this->generateNames();
861 $roles = array_keys($this->roles);
862
863 if (!isset($this->current)) {
864 if ('POST' !== $_SERVER['REQUEST_METHOD'] && !empty($_REQUEST['role'])) {
865 $this->set_current_role(sanitize_key($_REQUEST['role']));
866 }
867 }
868
869 if (!isset($this->current) || !get_role($this->current)) {
870 $this->current = get_option('default_role');
871 }
872
873 if (!in_array($this->current, $roles)) {
874 $this->current = array_shift($roles);
875 }
876
877 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && isset($_POST['ppc-nav-menu-role']) && !empty($_REQUEST['_wpnonce'])) {
878 if (!wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'pp-capabilities-nav-menus')) {
879 wp_die('<strong>' . esc_html__('You do not have permission to manage navigation menus.', 'capability-manager-enhanced') . '</strong>');
880 } else {
881 $menu_role = sanitize_key($_POST['ppc-nav-menu-role']);
882
883 $this->set_current_role($menu_role);
884
885 //set role nav child menu
886 $nav_item_menu_option = !empty(get_option('capsman_nav_item_menus')) ? get_option('capsman_nav_item_menus') : [];
887
888 $nav_item_menu_option[$menu_role] = isset($_POST['pp_cababilities_restricted_items']) ? array_map('sanitize_text_field', $_POST['pp_cababilities_restricted_items']) : '';
889
890 update_option('capsman_nav_item_menus', $nav_item_menu_option, false);
891
892 ak_admin_notify(__('Settings updated.', 'capability-manager-enhanced'));
893 }
894 }
895
896 include(dirname(CME_FILE) . '/includes/features/nav-menus.php');
897 }
898
899
900 /**
901 * Manages Profile Features
902 *
903 * @return void
904 */
905 public function ManageProfileFeatures() {
906 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities_profile_features')) {
907 // TODO: Implement exceptions.
908 wp_die('<strong>' . esc_html__('You do not have permission to manage admin features.', 'capability-manager-enhanced') . '</strong>');
909 }
910
911 $this->generateNames();
912 $roles = array_keys($this->roles);
913
914 if (!isset($this->current)) {
915 if ('POST' !== $_SERVER['REQUEST_METHOD'] && !empty($_REQUEST['role'])) {
916 $this->set_current_role(sanitize_key($_REQUEST['role']));
917 }
918 }
919
920 if (!isset($this->current) || !get_role($this->current)) {
921 $this->current = get_option('default_role');
922 }
923
924 if (!in_array($this->current, $roles)) {
925 $this->current = array_shift($roles);
926 }
927
928 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && isset($_POST['ppc-profile-features-role']) && !empty($_REQUEST['_wpnonce'])) {
929 if (!wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'pp-capabilities-profile-features')) {
930 wp_die('<strong>' . esc_html__('You do not have permission to manage profile features.', 'capability-manager-enhanced') . '</strong>');
931 } else {
932 $features_role = sanitize_key($_POST['ppc-profile-features-role']);
933
934 $this->set_current_role($features_role);
935
936 $previous_elements = !empty(get_option('capsman_profile_features_elements')) ? (array)get_option('capsman_profile_features_elements') : [];
937 $previous_disabled_profile_items = !empty(get_option('capsman_disabled_profile_features')) ? (array)get_option('capsman_disabled_profile_features') : [];
938 $new_disabled_element = isset($_POST['capsman_disabled_profile_features']) ? array_map('sanitize_text_field', $_POST['capsman_disabled_profile_features']) : [];
939 $previous_role_disabled_element = !empty($previous_disabled_profile_items[$features_role]) ? (array)$previous_disabled_profile_items[$features_role] : [];
940 $previous_role_element = !empty($previous_elements[$features_role]) ? (array)$previous_elements[$features_role] : [];
941
942 if (!empty($previous_role_element)) {
943 $previous_role_element_items = array_column($previous_role_element, 'elements');
944 } else {
945 $previous_role_element_items = [];
946 }
947
948
949 $disabled_element_differences = array_diff($previous_role_disabled_element, $previous_role_element_items);
950 $new_disabled_element_items = array_merge($new_disabled_element, $disabled_element_differences);
951 $new_disabled_element_items = array_filter($new_disabled_element_items);
952
953 $previous_disabled_profile_items[$features_role] = $new_disabled_element_items;
954
955 update_option('capsman_disabled_profile_features', $previous_disabled_profile_items, false);
956
957 //update element sort
958 $profile_features_elements_order = !empty($_POST['capsman_profile_features_elements_order']) ? sanitize_text_field($_POST['capsman_profile_features_elements_order']) : false;
959 if ($profile_features_elements_order) {
960 $profile_features_elements_order = explode(",", $profile_features_elements_order);
961 $profile_features_elements_order = array_filter($profile_features_elements_order);
962 if (!empty($profile_features_elements_order)) {
963 $new_elements = [];
964 foreach($profile_features_elements_order as $element_key) {
965 if (isset($previous_role_element[$element_key])) {
966 $new_elements[$element_key] = $previous_role_element[$element_key];
967 }
968 }
969 $previous_elements[$features_role] = $new_elements;
970 update_option('capsman_profile_features_elements', $previous_elements, false);
971 }
972 }
973
974 ak_admin_notify(__('Settings updated.', 'capability-manager-enhanced'));
975 }
976 }
977
978 include(dirname(CME_FILE) . '/includes/features/profile-features.php');
979 }
980
981
982 /**
983 * Manage Redirect
984 *
985 * @return void
986 */
987 public function ManageRedirects() {
988 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities_redirects')) {
989 // TODO: Implement exceptions.
990 wp_die('<strong>' . esc_html__('You do not have permission to manage redirect.', 'capability-manager-enhanced') . '</strong>');
991 }
992
993 $this->generateNames();
994 $roles = array_keys($this->roles);
995
996 if (!isset($this->current)) {
997 if ('POST' !== $_SERVER['REQUEST_METHOD'] && !empty($_REQUEST['role'])) {
998 $this->set_current_role(sanitize_key($_REQUEST['role']));
999 }
1000 }
1001
1002 if (!isset($this->current) || !get_role($this->current)) {
1003 $this->current = get_option('default_role');
1004 }
1005
1006 if (!in_array($this->current, $roles)) {
1007 $this->current = array_shift($roles);
1008 }
1009
1010 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && (isset($_POST['redirects-features-submit']) || isset($_POST['redirects-features-all-submit'])) && !empty($_REQUEST['_wpnonce'])) {
1011 if (!wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'pp-capabilities-redirects-features')) {
1012 wp_die('<strong>' . esc_html__('Invalid form. Reload this page and try again.', 'capability-manager-enhanced') . '</strong>');
1013 } else {
1014 $features_role = sanitize_key($_POST['ppc-redirects-features-role']);
1015
1016 $this->set_current_role($features_role);
1017
1018 $custom_redirect = !empty($_POST['custom_redirect']) ? (int) $_POST['custom_redirect'] : 0;
1019 $referer_redirect = !empty($_POST['referer_redirect']) ? (int) $_POST['referer_redirect'] : 0;
1020 $login_redirect = !empty($_POST['login_redirect']) ? home_url(str_replace(home_url(), '', sanitize_text_field($_POST['login_redirect']))) : '';
1021 $logout_redirect = !empty($_POST['logout_redirect']) ? home_url(str_replace(home_url(), '', sanitize_text_field($_POST['logout_redirect']))) : '';
1022 $registration_redirect = !empty($_POST['registration_redirect']) ? home_url(str_replace(home_url(), '', sanitize_text_field($_POST['registration_redirect']))) : '';
1023 $first_login_redirect = !empty($_POST['first_login_redirect']) ? home_url(str_replace(home_url(), '', sanitize_text_field($_POST['first_login_redirect']))) : '';
1024
1025 $role_redirects = !empty(get_option('capsman_role_redirects')) ? (array)get_option('capsman_role_redirects') : [];
1026
1027 if (isset($_POST['redirects-features-all-submit'])) {
1028 // Save for all roles
1029 $all_roles = array_keys($this->roles);
1030
1031 foreach ($all_roles as $role) {
1032 $role_redirects[$role] = [
1033 'custom_redirect' => $custom_redirect,
1034 'referer_redirect' => $referer_redirect,
1035 'login_redirect' => $login_redirect,
1036 'logout_redirect' => $logout_redirect,
1037 'registration_redirect' => $registration_redirect,
1038 'first_login_redirect' => $first_login_redirect
1039 ];
1040 }
1041 } else {
1042 // Save for current role only
1043 $role_redirects[$features_role] = [
1044 'custom_redirect' => $custom_redirect,
1045 'referer_redirect' => $referer_redirect,
1046 'login_redirect' => $login_redirect,
1047 'logout_redirect' => $logout_redirect,
1048 'registration_redirect' => $registration_redirect,
1049 'first_login_redirect' => $first_login_redirect
1050 ];
1051 }
1052
1053 update_option('capsman_role_redirects', $role_redirects);
1054
1055 ak_admin_notify(__('Settings updated.', 'capability-manager-enhanced'));
1056 }
1057 }
1058
1059 include(dirname(CME_FILE) . '/includes/redirects/redirects.php');
1060 }
1061
1062
1063
1064 /**
1065 * Manages Dashboard
1066 *
1067 * @return void
1068 */
1069 public function dashboardPage() {
1070 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities_dashboard')) {
1071 // TODO: Implement exceptions.
1072 wp_die('<strong>' . esc_html__('You do not have permission to manage admin features.', 'capability-manager-enhanced') . '</strong>');
1073 }
1074
1075 include(dirname(CME_FILE) . '/includes/dashboard.php');
1076 }
1077
1078 /**
1079 * Filters roles that can be shown in roles list.
1080 * This is mainly used to prevent an user admin to create other users with
1081 * higher capabilities.
1082 *
1083 * @hook 'editable_roles' filter.
1084 *
1085 * @param $roles List of roles to check.
1086 * @return array Restircted roles list
1087 */
1088 function filterEditRoles ( $roles )
1089 {
1090 global $current_user;
1091
1092 if (function_exists('wp_get_current_user') || defined('PP_CAPABILITIES_ROLES_FILTER_EARLY_EXECUTION')) { // Avoid downstream fatal error from premature current_user_can() call if get_editable_roles() is called too early
1093 $this->generateNames();
1094 $valid = array_keys($this->roles);
1095
1096 foreach ( $roles as $role => $caps ) {
1097 if ( ! in_array($role, $valid) ) {
1098 unset($roles[$role]);
1099 }
1100 }
1101 }
1102
1103 return $roles;
1104 }
1105
1106 /**
1107 * Checks if a user can be edited or not by current administrator.
1108 * Returns array('do_not_allow') if user cannot be edited.
1109 *
1110 * @hook 'map_meta_cap' filter
1111 *
1112 * @param array $caps Current user capabilities
1113 * @param string $cap Capability to check
1114 * @param int $user_id Current user ID
1115 * @param array $args For our purpose, we receive edited user id at $args[0]
1116 * @return array Allowed capabilities.
1117 */
1118 function filterUserEdit ( $caps, $cap, $user_id, $args )
1119 {
1120 if ( ! in_array( $cap, array( 'edit_user', 'delete_user', 'promote_user', 'remove_user' ) ) || ( ! isset($args[0]) ) || $user_id == (int) $args[0] ) {
1121 return $caps;
1122 }
1123
1124 $user = new WP_User( (int) $args[0] );
1125
1126 $this->generateNames();
1127
1128 if ( defined( 'CME_LEGACY_USER_EDIT_FILTER' ) && CME_LEGACY_USER_EDIT_FILTER ) {
1129 $valid = array_keys($this->roles);
1130
1131 foreach ( $user->roles as $role ) {
1132 if ( ! in_array($role, $valid) ) {
1133 $caps = array('do_not_allow');
1134 break;
1135 }
1136 }
1137 } else {
1138 global $wp_roles;
1139
1140 foreach ( $user->roles as $role ) {
1141 $r = get_role( $role );
1142 $level = ak_caps2level($r->capabilities);
1143
1144 if ( ( ! $level ) && ( 'administrator' == $role ) )
1145 $level = 10;
1146
1147 if ( $level > $this->max_level ) {
1148 $caps = array('do_not_allow');
1149 break;
1150 }
1151 }
1152
1153 }
1154
1155 return $caps;
1156 }
1157
1158 function processRoleUpdate() {
1159 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && ( ! empty($_REQUEST['SaveRole']) || ! empty($_REQUEST['AddCap']) ) ) {
1160 check_admin_referer('capsman-general-manager');
1161
1162 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
1163 // TODO: Implement exceptions.
1164 wp_die('<strong>' . esc_html__('You do not have permission to manage capabilities.', 'capability-manager-enhanced') . '</strong>');
1165 }
1166
1167 if ( ! empty($_REQUEST['current']) ) { // don't process role update unless form variable is received
1168 $current_subject = sanitize_key($_REQUEST['current']);
1169 $is_application_password = function_exists('pp_capabilities_can_manage_application_password_subject') && pp_capabilities_can_manage_application_password_subject($current_subject);
1170 $role = $is_application_password ? false : get_role($current_subject);
1171 $current_level = ($role) ? ak_caps2level($role->capabilities) : 0;
1172
1173 $this->processAdminGeneral();
1174
1175 $set_level = (isset($_POST['level'])) ? (int) $_POST['level'] : 0;
1176
1177 if (!$is_application_password && ($set_level != $current_level)) {
1178 global $wp_roles, $wp_version;
1179
1180 if ( version_compare($wp_version, '4.9', '>=') ) {
1181 $wp_roles->for_site();
1182 } else {
1183 $wp_roles->reinit();
1184 }
1185
1186 foreach( get_users(array('role' => $current_subject, 'fields' => 'ID')) as $ID ) {
1187 $user = new WP_User($ID);
1188 $user->get_role_caps();
1189 $user->update_user_level_from_caps();
1190 }
1191 }
1192
1193 if (!empty($this->network_sync_token)) {
1194 $redirect_args = [
1195 'page' => 'pp-capabilities',
1196 'role' => sanitize_key($_REQUEST['current']),
1197 'cme_network_sync_token' => $this->network_sync_token,
1198 ];
1199
1200 if (!empty($_REQUEST['pp_caps_tab'])) {
1201 $redirect_args['pp_caps_tab'] = sanitize_key($_REQUEST['pp_caps_tab']);
1202 }
1203
1204 wp_redirect(add_query_arg($redirect_args, admin_url('admin.php')));
1205 exit;
1206 }
1207 }
1208 }
1209
1210 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && ( ! empty($_REQUEST['RenameRole']) ) ) {
1211 check_admin_referer('capsman-general-manager');
1212
1213 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
1214 // TODO: Implement exceptions.
1215 wp_die('<strong>' . esc_html__('You do not have permission to manage capabilities.', 'capability-manager-enhanced') . '</strong>');
1216 }
1217
1218 if ( ! empty($_REQUEST['current']) ) { // don't process role update unless form variable is received
1219 $this->processAdminGeneral();
1220 }
1221 }
1222 }
1223
1224 /**
1225 * Manages global settings admin.
1226 *
1227 * @hook add_submenu_page
1228 * @return void
1229 */
1230 function generalManager () {
1231 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
1232 // TODO: Implement exceptions.
1233 wp_die('<strong>' . esc_html__('You do not have permission to manage capabilities.', 'capability-manager-enhanced') . '</strong>');
1234 }
1235
1236 if (isset($_REQUEST['cme_network_sync_token']) && is_scalar($_REQUEST['cme_network_sync_token'])) {
1237 $token = sanitize_key(wp_unslash($_REQUEST['cme_network_sync_token']));
1238
1239 if ('' !== $token) {
1240 if (get_site_transient('cme_network_sync_done_' . $token)) {
1241 delete_site_transient('cme_network_sync_done_' . $token);
1242 ak_admin_notify(__('Network sync completed.', 'capability-manager-enhanced'));
1243 } else {
1244 ak_admin_notify(__('Network sync has been queued and will continue in the background.', 'capability-manager-enhanced'));
1245 }
1246 }
1247 }
1248
1249 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD'])) {
1250 if ( empty($_REQUEST['SaveRole']) && empty($_REQUEST['AddCap']) && empty($_REQUEST['RenameRole']) ) {
1251 check_admin_referer('capsman-general-manager');
1252 $this->processAdminGeneral();
1253 } elseif ( ! empty($_REQUEST['SaveRole']) ) {
1254 ak_admin_notify( $this->message ); // moved update operation to earlier action to avoid UI refresh issues. But outputting notification there breaks styling.
1255 } elseif ( ! empty($_REQUEST['AddCap']) ) {
1256 ak_admin_notify( $this->message );
1257 }
1258 } else {
1259 if (!empty($_REQUEST['added'])) {
1260 ak_admin_notify(__('New capability added to role.', 'capability-manager-enhanced'));
1261 }
1262 }
1263
1264 $this->generateNames();
1265 $roles = array_keys($this->roles);
1266 $application_password_subjects = function_exists('pp_capabilities_get_application_password_subjects')
1267 ? pp_capabilities_get_application_password_subjects()
1268 : [];
1269
1270 if ( ! isset($this->current) ) { // By default, we manage the default role
1271 if ('POST' !== $_SERVER['REQUEST_METHOD'] && !empty($_REQUEST['role'])) {
1272 $subject = sanitize_key($_REQUEST['role']);
1273
1274 if (isset($application_password_subjects[$subject])) {
1275 $this->set_current_role($subject);
1276 } elseif (!pp_capabilities_is_editable_role($subject)) {
1277 wp_die(esc_html__('The selected role is not editable.', 'capability-manager-enhanced'));
1278 } else {
1279 $this->set_current_role($subject);
1280 }
1281 }
1282 }
1283
1284 if (!isset($this->current) || (!get_role($this->current) && !isset($application_password_subjects[$this->current]))) {
1285 $this->current = $this->get_last_role();
1286 }
1287
1288 if (!in_array($this->current, $roles) && !isset($application_password_subjects[$this->current])) { // Current role has been deleted.
1289 $this->current = array_shift($roles);
1290 }
1291
1292 include ( dirname(CME_FILE) . '/includes/admin.php' );
1293 }
1294
1295 /**
1296 * Processes and saves the changes in the general capabilities form.
1297 *
1298 * @return void
1299 */
1300 private function processAdminGeneral ()
1301 {
1302 check_admin_referer('capsman-general-manager');
1303
1304 if (! isset($_POST['action']) || 'update' != $_POST['action'] ) {
1305 // TODO: Implement exceptions. This must be a fatal error.
1306 ak_admin_error(__('Bad form Received', 'capability-manager-enhanced'));
1307 return;
1308 }
1309
1310 // Select a new role.
1311 if ( ! empty($post['LoadRole']) && !empty($_POST['role']) ) {
1312 $this->set_current_role(sanitize_key($_POST['role']));
1313 } elseif (!empty($_POST['current'])) {
1314 $this->set_current_role(sanitize_key($_POST['current']));
1315
1316 require_once( dirname(__FILE__).'/handler.php' );
1317 $capsman_modify = new CapsmanHandler( $this );
1318 $capsman_modify->processAdminGeneral();
1319 }
1320
1321 //save user sidebar panel state
1322 if (!empty($_POST['ppc_metabox_state'])) {
1323 $metabox_state = map_deep($_POST['ppc_metabox_state'], 'sanitize_text_field');
1324 update_user_meta(get_current_user_id(), 'ppc_sidebar_metabox_state', $metabox_state);
1325 }
1326 }
1327
1328 /**
1329 * Callback function to create names.
1330 * Replaces underscores by spaces and uppercases the first letter.
1331 *
1332 * @access private
1333 * @param string $cap Capability name.
1334 * @return string The generated name.
1335 */
1336 function _capNamesCB ( $cap )
1337 {
1338 $cap = str_replace('_', ' ', $cap);
1339
1340 return $cap;
1341 }
1342
1343 /**
1344 * Generates an array with the system capability names.
1345 * The key is the capability and the value the created screen name.
1346 *
1347 * @uses self::_capNamesCB()
1348 * @return void
1349 */
1350 function generateSysNames ()
1351 {
1352 $this->max_level = 10;
1353
1354 if ( ! function_exists( 'ak_get_roles' ) ) {
1355 require_once dirname( CME_FILE ) . '/framework/lib/users.php';
1356 }
1357
1358 $this->roles = ak_get_roles(true);
1359 $caps = array();
1360
1361 foreach ( array_keys($this->roles) as $role ) {
1362 $role_caps = get_role($role);
1363 $caps = array_merge( $caps, (array) $role_caps->capabilities ); // user reported PHP 5.3.3 error without array cast
1364 }
1365
1366 $keys = array_keys($caps);
1367 $names = array_map(array($this, '_capNamesCB'), $keys);
1368 $this->capabilities = array_combine($keys, $names);
1369
1370 asort($this->capabilities);
1371 }
1372
1373 /**
1374 * Generates an array with the user capability names.
1375 * If user has 'administrator' role, system roles are generated.
1376 * The key is the capability and the value the created screen name.
1377 * A user cannot manage more capabilities that has himself (Except for administrators).
1378 *
1379 * @uses self::_capNamesCB()
1380 * @return void
1381 */
1382 function generateNames ()
1383 {
1384 if ( current_user_can('administrator') || ( is_multisite() && is_super_admin() ) ) {
1385 $this->generateSysNames();
1386 } else {
1387 global $user_ID;
1388 $user = new WP_User($user_ID);
1389 $this->max_level = ak_caps2level($user->allcaps);
1390
1391 $keys = array_keys($user->allcaps);
1392 $names = array_map(array($this, '_capNamesCB'), $keys);
1393
1394 $this->capabilities = ( $keys ) ? array_combine($keys, $names) : array();
1395
1396 if ( ! function_exists( 'ak_get_roles' ) ) {
1397 require_once dirname( CME_FILE ) . '/framework/lib/users.php';
1398 }
1399
1400 $roles = ak_get_roles(true);
1401 unset($roles['administrator']);
1402
1403 if ( ( defined( 'CME_LEGACY_USER_EDIT_FILTER' ) && CME_LEGACY_USER_EDIT_FILTER ) || ( ! empty( $_REQUEST['page'] ) && 'pp-capabilities' == $_REQUEST['page'] ) ) {
1404 foreach ( $user->roles as $role ) { // Unset the roles from capability list.
1405 unset ( $this->capabilities[$role] );
1406 unset ( $roles[$role]); // User cannot manage his roles.
1407 }
1408 }
1409
1410 asort($this->capabilities);
1411
1412 foreach ( array_keys($roles) as $role ) {
1413 $r = get_role($role);
1414 $level = ak_caps2level($r->capabilities);
1415
1416 if ( $level > $this->max_level ) {
1417 unset($roles[$role]);
1418 }
1419 }
1420
1421 $this->roles = $roles;
1422 }
1423 }
1424
1425 /**
1426 * Manages backup, restore and resset roles and capabilities
1427 *
1428 * @hook add_management_page
1429 * @return void
1430 */
1431 function backupTool ()
1432 {
1433 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities_backup')) {
1434 // TODO: Implement exceptions.
1435 wp_die('<strong>' . esc_html__('You do not have permission to restore roles.', 'capability-manager-enhanced') . '</strong>');
1436 }
1437
1438 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD'])) {
1439 check_admin_referer('pp-capabilities-backup');
1440 require_once( dirname(__FILE__).'/backup-handler.php' );
1441 $cme_backup_handler = new Capsman_BackupHandler( $this );
1442 $cme_backup_handler->processBackupTool();
1443 }
1444
1445 if ( isset($_GET['action']) && 'reset-defaults' == $_GET['action']) {
1446 check_admin_referer('capsman-reset-defaults');
1447 require_once( dirname(__FILE__).'/backup-handler.php' );
1448 $cme_backup_handler = new Capsman_BackupHandler( $this );
1449 $cme_backup_handler->backupToolReset();
1450 }
1451
1452 include ( dirname(CME_FILE) . '/includes/backup.php' );
1453 }
1454
1455
1456 /**
1457 * Processes export.
1458 *
1459 * This function need to run in admin init
1460 * to enable clean download.
1461 *
1462 * @return void
1463 */
1464 function processExport()
1465 {
1466 global $wpdb;
1467
1468 if ( isset($_POST['export_backup']) && isset($_POST['pp_capabilities_export_section']) && !empty($_POST['pp_capabilities_export_section'])) {
1469 check_admin_referer('pp-capabilities-backup');
1470
1471 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities_backup')) {
1472 // TODO: Implement exceptions.
1473 wp_die('<strong>' . esc_html__('You do not have permission to perform this action.', 'capability-manager-enhanced') . '</strong>');
1474 }
1475
1476 $export_option = array_map('sanitize_text_field', $_POST['pp_capabilities_export_section']);
1477 $backup_sections = pp_capabilities_backup_sections();
1478 $charset = get_option( 'blog_charset' );
1479 $data = [];
1480
1481 //add role
1482 if(in_array('user_roles', $export_option)){
1483 $data['user_roles'] = get_option($wpdb->prefix . 'user_roles');
1484 }
1485
1486 //other section
1487 foreach($backup_sections as $backup_key => $backup_section){
1488
1489 if(!in_array($backup_key, $export_option)){
1490 continue;
1491 }
1492 $section_options = $backup_section['options'];
1493 if(is_array($section_options) && !empty($section_options)){
1494 foreach($section_options as $section_option){
1495 $active_backup[] = $backup_section['label'];
1496 $data[$section_option] = get_option($section_option);
1497 }
1498 }
1499 }
1500
1501 // Set the download headers.
1502 nocache_headers();
1503 header( 'Content-Type: application/json; charset=' . $charset );
1504 header( 'Content-Disposition: attachment; filename=capabilities-export-' . current_time('Y-m-d_g-i-s_a') . '.json' );
1505 header( "Expires: 0" );
1506
1507 // encode the export data.
1508 echo json_encode($data);
1509
1510 // Start the download.
1511 die();
1512
1513 }
1514 }
1515
1516 function settingsPage() {
1517 include ( dirname(CME_FILE) . '/includes/settings.php' );
1518 }
1519
1520 /**
1521 * Initialize plugin capabilities class
1522 *
1523 * @return void
1524 */
1525 public function initPluginCapabilities() {
1526 require_once dirname(CME_FILE) . '/includes/plugin-capabilities.php';
1527 \PublishPress\Capabilities\Plugin_Capabilities::instance();
1528 }
1529
1530 /**
1531 * Redirect for profile features capturing
1532 *
1533 * @return void
1534 */
1535 function profileFeaturesCaptureRedirect() {
1536
1537 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities_profile_features')) {
1538 return;
1539 }
1540
1541 if (is_admin() && pp_capabilities_feature_enabled('profile-features') && !empty($_REQUEST['page']) && 'pp-capabilities-profile-features' === $_REQUEST['page']) {
1542 global $capsman, $role_has_user;
1543 $default_role = $capsman->get_last_role();
1544
1545 if (!empty($_REQUEST['role'])) {
1546 $default_role = sanitize_key($_REQUEST['role']);
1547 $this->set_current_role($default_role);
1548 }
1549
1550 $profile_element_updated = (array) get_option("capsman_profile_features_updated", []);
1551 $refresh_element = isset($_REQUEST['refresh_element']) ? (int) $_REQUEST['refresh_element'] : 0;
1552 $role_refresh = isset($_REQUEST['role_refresh']) ? (int) $_REQUEST['role_refresh'] : 0;
1553
1554 //get user in current role
1555 $role_user = get_users(
1556 [
1557 'role' => $default_role,
1558 'exclude' => [get_current_user_id()],
1559 'number' => 1,
1560 ]
1561 );
1562
1563 $role_has_user = true;
1564 if (empty($role_user) && $default_role !== 'administrator') {
1565 $role_has_user = false;
1566 }
1567
1568 // Check if role is enabled for profile features editing
1569 if (!\PublishPress\Capabilities\PP_Capabilities_Profile_Features::isRoleEnabledForProfileFeatures($default_role)) {
1570 return;
1571 }
1572
1573 if (
1574 is_array($profile_element_updated)
1575 && isset($profile_element_updated[$default_role])
1576 && (int)$profile_element_updated[$default_role] > 0
1577 ) {
1578 if ($refresh_element === 0 && $role_refresh === 0) {
1579 return;
1580 }
1581 }
1582
1583 if (!get_option('cme_profile_features_auto_redirect') && !$role_refresh) {
1584 return;
1585 }
1586
1587 if (empty($role_user) && $default_role !== 'administrator') {
1588 return;
1589 }
1590
1591 $can_redirect = true;
1592
1593 if (!empty($role_user)) {
1594 $testing_user = $role_user[0];
1595 if (!user_can($testing_user->ID, 'read')) {
1596 $can_redirect = false;
1597 }
1598
1599 }
1600
1601 if ($can_redirect) {
1602 //redirect user to test link for validation and redirection
1603 if (empty($role_user)) {
1604 $test_link = admin_url('profile.php?ppc_profile_element=1');
1605 } else {
1606 $test_as_user = $role_user[0];
1607 $test_link = add_query_arg(
1608 [
1609 'ppc_test_user' => base64_encode($test_as_user->ID),
1610 'profile_feature_action' => 1,
1611 '_wpnonce' => wp_create_nonce('ppc-test-user')
1612 ],
1613 admin_url('users.php')
1614 );
1615 }
1616 if ($refresh_element > 0) {
1617 delete_option('capsman_profile_features_updated');
1618 }
1619 update_option('capsman_profile_features_elements_testing_role', $default_role, false);
1620 wp_safe_redirect($test_link);
1621 exit();
1622 }
1623 }
1624 }
1625 }
1626
1627 function cme_publishpressFooter() {
1628 ?>
1629 <footer>
1630
1631 <div class="pp-rating">
1632 <a href="https://wordpress.org/support/plugin/capability-manager-enhanced/reviews/#new-post" target="_blank" rel="noopener noreferrer">
1633 <?php printf(
1634 esc_html__('If you like %s, please leave us a %s rating. Thank you!', 'capability-manager-enhanced'),
1635 '<strong>PublishPress Capabilities</strong>',
1636 '<span class="dashicons dashicons-star-filled"></span><span class="dashicons dashicons-star-filled"></span><span class="dashicons dashicons-star-filled"></span><span class="dashicons dashicons-star-filled"></span><span class="dashicons dashicons-star-filled"></span>'
1637 );
1638 ?>
1639 </a>
1640 </div>
1641
1642 <hr>
1643 <nav>
1644 <ul>
1645 <li><a href="https://publishpress.com/capability-manager/" target="_blank" rel="noopener noreferrer" title="<?php esc_attr_e('About PublishPress Capabilities', 'capability-manager-enhanced');?>"><?php esc_html_e('About', 'capability-manager-enhanced');?>
1646 </a></li>
1647 <li><a href="https://publishpress.com/knowledge-base/how-to-use-capability-manager/" target="_blank" rel="noopener noreferrer" title="<?php esc_attr_e('Capabilites Documentation', 'capability-manager-enhanced');?>"><?php esc_html_e('Documentation', 'capability-manager-enhanced');?>
1648 </a></li>
1649 <li><a href="https://publishpress.com/contact" target="_blank" rel="noopener noreferrer" title="<?php esc_attr_e('Contact the PublishPress team', 'capability-manager-enhanced');?>"><?php esc_html_e('Contact', 'capability-manager-enhanced');?>
1650 </a></li>
1651 </ul>
1652 </nav>
1653
1654 <div class="pp-pressshack-logo">
1655 <a href="https://publishpress.com" target="_blank" rel="noopener noreferrer">
1656
1657 <img src="<?php echo esc_url_raw(plugins_url('', CME_FILE) . '/common/img/publishpress-logo.png');?>" />
1658 </a>
1659 </div>
1660
1661 </footer>
1662 <?php
1663 }
1664