PluginProbe ʕ •ᴥ•ʔ
PublishPress Capabilities – User Role Editor, Access Permissions, User Capabilities, Admin Menus / 2.3.6
PublishPress Capabilities – User Role Editor, Access Permissions, User Capabilities, Admin Menus v2.3.6
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
features 4 years ago roles 4 years ago admin-load.php 4 years ago admin.php 4 years ago backup-handler.php 4 years ago backup.php 4 years ago cap-helper.php 4 years ago filters-admin.php 4 years ago filters-woocommerce.php 4 years ago filters-wp_rest_workarounds.php 5 years ago filters.php 4 years ago functions-admin.php 4 years ago functions.php 4 years ago handler.php 4 years ago inflect-cme.php 7 years ago manager.php 4 years ago network.php 4 years ago pp-handler.php 4 years ago pp-ui.php 4 years ago publishpress-roles.php 4 years ago settings-handler.php 4 years ago settings.php 4 years ago
manager.php
1009 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 $rcaps = $role->capabilities;
65
66 $core_caps = array_diff_key( _cme_core_caps(), array_fill_keys( array( 'unfiltered_html', 'unfiltered_upload', 'upload_files', 'edit_files', 'read' ), true ) );
67
68 if ( empty( $rcaps['dashboard_lockout_ok'] ) ) {
69 $edit_caps = array();
70 foreach ( get_post_types( array( 'public' => true ), 'object' ) as $type_obj ) {
71 $edit_caps = array_merge( $edit_caps, array_values( array_diff_key( (array) $type_obj->cap, array( 'read_private_posts' => true ) ) ) );
72 }
73
74 $edit_caps = array_fill_keys( $edit_caps, true );
75 unset( $edit_caps['read'] );
76 unset( $edit_caps['upload_files'] );
77 unset( $edit_caps['edit_files'] );
78
79 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 ) ) ) {
80 return true;
81 }
82 }
83
84 return false;
85 }
86
87 /**
88 * Class CapabilityManager.
89 * Sets the main environment for all Capability Manager components.
90 *
91 * @author Jordi Canals, Kevin Behrens
92 * @link https://publishpress.com/
93 */
94 class CapabilityManager
95 {
96 /**
97 * Array with all capabilities to be managed. (Depends on user caps).
98 * The array keys are the capability, the value is its screen name.
99 * @var array
100 */
101 var $capabilities = array();
102
103 /**
104 * Array with roles that can be managed. (Depends on user roles).
105 * The array keys are the role name, the value is its translated name.
106 * @var array
107 */
108 var $roles = array();
109
110 /**
111 * Current role we are managing
112 * @var string
113 */
114 var $current;
115
116 /**
117 * Maximum level current manager can assign to a user.
118 * @var int
119 */
120 private $max_level;
121
122 private $log_db_role_objects = array();
123
124 var $message;
125
126 /**
127 * Module ID. Is the module internal short name.
128 *
129 * @var string
130 */
131 public $ID;
132
133 public function __construct()
134 {
135 $this->ID = 'capsman';
136 $this->mod_url = plugins_url( '', CME_FILE );
137
138 if (is_admin() && !empty($_REQUEST['page']) && ('pp-capabilities-settings' == $_REQUEST['page']) && (!empty($_POST['all_options']) || !empty($_POST['all_options_pro']))) {
139 add_action('init', function() {
140 if (isset($_REQUEST['_wpnonce']) && wp_verify_nonce($_REQUEST['_wpnonce'], 'pp-capabilities-settings') && current_user_can('manage_capabilities')) {
141 require_once (dirname(CME_FILE) . '/includes/settings-handler.php');
142 }
143 }, 1);
144 }
145
146 $this->moduleLoad();
147
148 add_action('admin_menu', array($this, 'adminMenus'), 5); // execute prior to PP, to use menu hook
149
150 // Load styles
151 add_action('admin_print_styles', array($this, 'adminStyles'));
152
153 if ( isset($_REQUEST['page']) && ( 'pp-capabilities' == $_REQUEST['page'] ) ) {
154 add_action('admin_enqueue_scripts', array($this, 'adminScriptsPP'));
155 }
156
157 add_action('init', [$this, 'initRolesAdmin']);
158
159 add_action('wp_ajax_pp-roles-add-role', [$this, 'handleRolesAjax']);
160 add_action('wp_ajax_pp-roles-delete-role', [$this, 'handleRolesAjax']);
161
162 if (defined('PRESSPERMIT_VERSION')) {
163 add_action('wp_ajax_pp-roles-hide-role', [$this, 'handleRolesAjax']);
164 add_action('wp_ajax_pp-roles-unhide-role', [$this, 'handleRolesAjax']);
165 }
166
167 //process export
168 add_action( 'admin_init', [$this, 'processExport']);
169 }
170
171 /**
172 * Enqueues administration styles.
173 *
174 * @hook action 'admin_print_styles'
175 *
176 * @return void
177 */
178 function adminStyles()
179 {
180 if (empty($_REQUEST['page'])
181 || !in_array(
182 $_REQUEST['page'],
183 ['pp-capabilities', 'pp-capabilities-roles', 'pp-capabilities-admin-menus', 'pp-capabilities-nav-menus', 'pp-capabilities-editor-features', 'pp-capabilities-backup', 'pp-capabilities-settings', 'pp-capabilities-admin-features']
184 )
185 ) {
186 return;
187 }
188
189 wp_enqueue_style('cme-admin-common', $this->mod_url . '/common/css/pressshack-admin.css', [], PUBLISHPRESS_CAPS_VERSION);
190
191 wp_register_style( $this->ID . 'framework_admin', $this->mod_url . '/framework/styles/admin.css', false, PUBLISHPRESS_CAPS_VERSION);
192 wp_enqueue_style( $this->ID . 'framework_admin');
193
194 wp_register_style( $this->ID . '_admin', $this->mod_url . '/common/css/admin.css', false, PUBLISHPRESS_CAPS_VERSION);
195 wp_enqueue_style( $this->ID . '_admin');
196
197 $suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '.dev' : '';
198 $url = $this->mod_url . "/common/js/admin{$suffix}.js";
199 wp_enqueue_script( 'cme_admin', $url, array('jquery'), PUBLISHPRESS_CAPS_VERSION, true );
200 wp_localize_script( 'cme_admin', 'cmeAdmin', [
201 'negationCaption' => __( 'Explicity negate this capability by storing as disabled', 'capsman-enhanced' ),
202 'typeCapsNegationCaption' => __( 'Explicitly negate these capabilities by storing as disabled', 'capsman-enhanced' ),
203 'typeCapUnregistered' => __( 'Post type registration does not define this capability distinctly', 'capsman-enhanced' ),
204 'capNegated' => __( 'This capability is explicitly negated. Click to add/remove normally.', 'capsman-enhanced' ),
205 'chkCaption' => __( 'Add or remove this capability from the WordPress role', 'capsman-enhanced' ),
206 'switchableCaption' => __( 'Add or remove capability from the role normally', 'capsman-enhanced' ),
207 'deleteWarning' => __( 'Are you sure you want to delete this item ?', 'capsman-enhanced' ),
208 'saveWarning' => __( 'Add or clear custom item entry before saving changes.', 'capsman-enhanced' )
209 ]
210 );
211 }
212
213 function adminScriptsPP() {
214 wp_enqueue_style( 'plugin-install' );
215 wp_enqueue_script( 'plugin-install' );
216 add_thickbox();
217 }
218
219 /**
220 * Creates some filters at module load time.
221 *
222 * @return void
223 */
224 protected function moduleLoad ()
225 {
226 $old_version = get_option($this->ID . '_version');
227 if ( version_compare( $old_version, PUBLISHPRESS_CAPS_VERSION, 'ne') ) {
228 update_option($this->ID . '_version', PUBLISHPRESS_CAPS_VERSION);
229 $this->pluginUpdate();
230 }
231
232 // Only roles that a user can administer can be assigned to others.
233 add_filter('editable_roles', array($this, 'filterEditRoles'));
234
235 // Users with roles that cannot be managed, are not allowed to be edited.
236 add_filter('map_meta_cap', array(&$this, 'filterUserEdit'), 10, 4);
237
238 // ensure storage, retrieval of db-stored customizations to dynamic roles
239 if ( isset($_REQUEST['page']) && in_array( $_REQUEST['page'], array( 'pp-capabilities', 'pp-capabilities-backup' ) ) ) {
240 global $wpdb;
241 $role_key = $wpdb->prefix . 'user_roles';
242 $this->log_db_roles();
243 add_filter( 'option_' . $role_key, array( &$this, 'reinstate_db_roles' ), PHP_INT_MAX );
244 }
245
246 $action = (defined('PP_CAPABILITIES_COMPAT_MODE')) ? 'init' : 'plugins_loaded';
247 add_action( $action, array( &$this, 'processRoleUpdate' ) );
248 }
249
250 public function set_current_role($role_name) {
251 global $current_user;
252
253 if ($role_name && !empty($current_user) && !empty($current_user->ID)) {
254 update_option("capsman_last_role_{$current_user->ID}", $role_name);
255 }
256 }
257
258 public function get_last_role() {
259 global $current_user;
260
261 $role_name = get_option("capsman_last_role_{$current_user->ID}");
262
263 if (!$role_name || !get_role($role_name)) {
264 $role_name = get_option('default_role');
265 }
266
267 return $role_name;
268 }
269
270 // Direct query of stored role definitions
271 function log_db_roles( $legacy_arg = '' ) {
272 global $wpdb;
273
274 $results = (array) maybe_unserialize( $wpdb->get_var("SELECT option_value FROM $wpdb->options WHERE option_name = '{$wpdb->prefix}user_roles' LIMIT 1") );
275 foreach( $results as $_role_name => $_role ) {
276 $this->log_db_role_objects[$_role_name] = (object) $_role;
277 }
278
279 return $legacy_arg;
280 }
281
282 // note: this is only applied when accessing the cme role edit form
283 function reinstate_db_roles( $passthru_roles = array() ) {
284 global $wp_roles;
285
286 if ( isset($wp_roles) && $this->log_db_role_objects ) {
287 $intersect = array_intersect_key( $wp_roles->role_objects, $this->log_db_role_objects );
288 foreach( array_keys( $intersect ) as $key ) {
289 if ( ! empty( $this->log_db_role_objects[$key]->capabilities ) )
290 $wp_roles->role_objects[$key]->capabilities = $this->log_db_role_objects[$key]->capabilities;
291 }
292 }
293
294 return $passthru_roles;
295 }
296
297 /**
298 * Updates Capability Manager to a new version
299 *
300 * @return void
301 */
302 protected function pluginUpdate ()
303 {
304 global $wpdb;
305
306 $backup = get_option($this->ID . '_backup');
307 if ( false === $backup ) { // No previous backup found. Save it!
308 $roles = get_option($wpdb->prefix . 'user_roles');
309 update_option( $this->ID . '_backup', $roles, false );
310 update_option( $this->ID . '_backup_datestamp', current_time( 'timestamp' ), false );
311 }
312
313 if (!$wpdb->get_var("SELECT COUNT(option_id) FROM $wpdb->options WHERE option_name LIKE 'cme_backup_auto_%'")) {
314 pp_capabilities_autobackup();
315 }
316 }
317
318 /**
319 * Adds admin panel menus. (At plugins loading time. This is before plugins_loaded).
320 * User needs to have 'manage_capabilities' to access this menus.
321 * This is set as an action in the parent class constructor.
322 *
323 * @hook action admin_menu
324 * @return void
325 */
326 public function adminMenus ()
327 {
328 // First we check if user is administrator and can 'manage_capabilities'.
329 if ( current_user_can('administrator') && ! current_user_can('manage_capabilities') ) {
330 $this->setAdminCapability();
331 }
332
333 add_action( 'admin_menu', array( &$this, 'cme_menu' ), 18 );
334 }
335
336 public function cme_menu() {
337 $cap_name = (is_multisite() && is_super_admin()) ? 'read' : 'manage_capabilities';
338
339 $permissions_title = __('Capabilities', 'capsman-enhanced');
340
341 $menu_order = 72;
342
343 if (defined('PUBLISHPRESS_PERMISSIONS_MENU_GROUPING')) {
344 foreach ((array)get_option('active_plugins') as $plugin_file) {
345 if ( false !== strpos($plugin_file, 'publishpress.php') ) {
346 $menu_order = 27;
347 }
348 }
349 }
350
351 add_menu_page(
352 $permissions_title,
353 $permissions_title,
354 $cap_name,
355 'pp-capabilities',
356 array($this, 'generalManager'),
357 'dashicons-admin-network',
358 $menu_order
359 );
360
361 $hook = add_submenu_page('pp-capabilities', __('Roles', 'capsman-enhanced'), __('Roles', 'capsman-enhanced'), $cap_name, 'pp-capabilities-roles', [$this, 'ManageRoles']);
362
363 if (!empty($hook)) {
364 add_action(
365 "load-$hook",
366 function() {
367 require_once (dirname(CME_FILE) . '/includes/roles/roles-functions.php');
368 admin_roles_page_load();
369 }
370 );
371 }
372
373 add_submenu_page('pp-capabilities', __('Editor Features', 'capsman-enhanced'), __('Editor Features', 'capsman-enhanced'), $cap_name, 'pp-capabilities-editor-features', [$this, 'ManageEditorFeatures']);
374
375 add_submenu_page('pp-capabilities', __('Admin Features', 'capsman-enhanced'), __('Admin Features', 'capsman-enhanced'), $cap_name, 'pp-capabilities-admin-features', [$this, 'ManageAdminFeatures']);
376
377 do_action('pp-capabilities-admin-submenus');
378
379 add_submenu_page('pp-capabilities', __('Backup', 'capsman-enhanced'), __('Backup', 'capsman-enhanced'), $cap_name, 'pp-capabilities-backup', array($this, 'backupTool'));
380
381 if (defined('PUBLISHPRESS_CAPS_PRO_VERSION')) {
382 add_submenu_page('pp-capabilities', __('Settings', 'capsman-enhanced'), __('Settings', 'capsman-enhanced'), $cap_name, 'pp-capabilities-settings', array($this, 'settingsPage'));
383 }
384
385 if (!defined('PUBLISHPRESS_CAPS_PRO_VERSION')) {
386 add_submenu_page(
387 'pp-capabilities',
388 __('Upgrade to Pro', 'capsman-enhanced'),
389 __('Upgrade to Pro', 'capsman-enhanced'),
390 'manage_capabilities',
391 'capsman-enhanced',
392 array($this, 'generalManager')
393 );
394 }
395 }
396
397 function initRolesAdmin() {
398 // @todo: solve order of execution issue so this column headers definition is not duplicated
399 if (!empty($_REQUEST['page']) && ('pp-capabilities-roles' == $_REQUEST['page'])) {
400 add_filter(
401 "manage_capabilities_page_pp-capabilities-roles_columns",
402
403 function($arr) {
404 return [
405 'cb' => '<input type="checkbox"/>',
406 'name' => __('Name', 'capsman-enhanced'),
407 'role' => __('Role', 'capsman-enhanced'),
408 'count' => __('Users', 'capsman-enhanced'),
409 ];
410 }
411 );
412 }
413 }
414
415 function handleRolesAjax() {
416 require_once (dirname(CME_FILE) . '/includes/roles/roles-functions.php');
417
418 if (!class_exists('PP_Capabilities_Roles')) {
419 require_once (dirname(CME_FILE) . '/includes/roles/class/class-pp-roles.php');
420 }
421
422 $roles = pp_capabilities_roles()->run();
423 }
424
425 /**
426 * Manages roles
427 *
428 * @hook add_management_page
429 * @return void
430 */
431 public function ManageRoles ()
432 {
433 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
434 // TODO: Implement exceptions.
435 wp_die('<strong>' . esc_html__('You do not have permission to manage roles.', 'capsman-enhanced') . '</strong>');
436 }
437
438 require_once (dirname(CME_FILE) . '/includes/roles/roles-functions.php');
439
440 if (!class_exists('PP_Capabilities_Roles')) {
441 require_once (dirname(CME_FILE) . '/includes/roles/class/class-pp-roles.php');
442 }
443
444 $roles = pp_capabilities_roles()->run();
445
446 require_once ( dirname(CME_FILE) . '/includes/roles/roles.php' );
447 }
448
449
450 /**
451 * Manages Editor Features
452 *
453 * @return void
454 */
455 public function ManageEditorFeatures() {
456 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
457 // TODO: Implement exceptions.
458 wp_die('<strong>' . esc_html__('You do not have permission to manage editor features.', 'capabilities-pro') . '</strong>');
459 }
460
461 $this->generateNames();
462 $roles = array_keys($this->roles);
463
464 if (!isset($this->current)) {
465 if (empty($_POST) && !empty($_REQUEST['role'])) {
466 $this->set_current_role(sanitize_key($_REQUEST['role']));
467 }
468 }
469
470 if (!isset($this->current) || !get_role($this->current)) {
471 $this->current = get_option('default_role');
472 }
473
474 if (!in_array($this->current, $roles)) {
475 $this->current = array_shift($roles);
476 }
477
478 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && isset($_POST['ppc-editor-features-role']) && !empty($_REQUEST['_wpnonce'])) {
479 if (!wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'pp-capabilities-editor-features')) {
480 wp_die('<strong>' . esc_html__('You do not have permission to manage editor features.', 'capabilities-pro') . '</strong>');
481 } else {
482 $this->set_current_role(sanitize_key($_POST['ppc-editor-features-role']));
483
484 $classic_editor = pp_capabilities_is_classic_editor_available();
485
486 $def_post_types = array_unique(apply_filters('pp_capabilities_feature_post_types', ['post', 'page']));
487
488 foreach ($def_post_types as $post_type) {
489 if ($classic_editor) {
490 $posted_settings = (isset($_POST["capsman_feature_restrict_classic_{$post_type}"])) ? array_map('sanitize_text_field', $_POST["capsman_feature_restrict_classic_{$post_type}"]) : [];
491 $post_features_option = get_option("capsman_feature_restrict_classic_{$post_type}", []);
492 $post_features_option[sanitize_key($_POST['ppc-editor-features-role'])] = $posted_settings;
493 update_option("capsman_feature_restrict_classic_{$post_type}", $post_features_option, false);
494 }
495
496 $posted_settings = (isset($_POST["capsman_feature_restrict_{$post_type}"])) ? array_map('sanitize_text_field', $_POST["capsman_feature_restrict_{$post_type}"]) : [];
497 $post_features_option = get_option("capsman_feature_restrict_{$post_type}", []);
498 $post_features_option[sanitize_key($_POST['ppc-editor-features-role'])] = $posted_settings;
499 update_option("capsman_feature_restrict_{$post_type}", $post_features_option, false);
500 }
501
502 ak_admin_notify(__('Settings updated.', 'capabilities-pro'));
503 }
504 }
505
506 do_action('pp_capabilities_editor_features');
507 include(dirname(CME_FILE) . '/includes/features/editor-features.php');
508 }
509
510 /**
511 * Manages Admin Features
512 *
513 * @return void
514 */
515 public function ManageAdminFeatures() {
516 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
517 // TODO: Implement exceptions.
518 wp_die('<strong>' . esc_html__('You do not have permission to manage admin features.', 'capabilities-pro') . '</strong>');
519 }
520
521 $this->generateNames();
522 $roles = array_keys($this->roles);
523
524 if (!isset($this->current)) {
525 if (empty($_POST) && !empty($_REQUEST['role'])) {
526 $this->set_current_role(sanitize_key($_REQUEST['role']));
527 }
528 }
529
530 if (!isset($this->current) || !get_role($this->current)) {
531 $this->current = get_option('default_role');
532 }
533
534 if (!in_array($this->current, $roles)) {
535 $this->current = array_shift($roles);
536 }
537
538 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && isset($_POST['ppc-admin-features-role']) && !empty($_REQUEST['_wpnonce'])) {
539 if (!wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'pp-capabilities-admin-features')) {
540 wp_die('<strong>' . esc_html__('You do not have permission to manage admin features.', 'capabilities-pro') . '</strong>');
541 } else {
542 $features_role = sanitize_key($_POST['ppc-admin-features-role']);
543
544 $this->set_current_role($features_role);
545
546 $disabled_admin_items = !empty(get_option('capsman_disabled_admin_features')) ? (array)get_option('capsman_disabled_admin_features') : [];
547 $disabled_admin_items[$features_role] = isset($_POST['capsman_disabled_admin_features']) ? array_map('sanitize_text_field', $_POST['capsman_disabled_admin_features']) : '';
548
549 update_option('capsman_disabled_admin_features', $disabled_admin_items, false);
550
551 //set reload option for instant reflection if user is updating own role
552 if (in_array($features_role, wp_get_current_user()->roles)){
553 $ppc_page_reload = '1';
554 }
555
556 ak_admin_notify(__('Settings updated.', 'capabilities-pro'));
557 }
558 }
559
560 include(dirname(CME_FILE) . '/includes/features/admin-features.php');
561 }
562
563 /**
564 * Sets the 'manage_capabilities' cap to the administrator role.
565 *
566 * @return void
567 */
568 public function setAdminCapability ()
569 {
570 if ($admin = get_role('administrator')) {
571 $admin->add_cap('manage_capabilities');
572 }
573 }
574
575 /**
576 * Filters roles that can be shown in roles list.
577 * This is mainly used to prevent an user admin to create other users with
578 * higher capabilities.
579 *
580 * @hook 'editable_roles' filter.
581 *
582 * @param $roles List of roles to check.
583 * @return array Restircted roles list
584 */
585 function filterEditRoles ( $roles )
586 {
587 global $current_user;
588
589 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
590 $this->generateNames();
591 $valid = array_keys($this->roles);
592
593 foreach ( $roles as $role => $caps ) {
594 if ( ! in_array($role, $valid) ) {
595 unset($roles[$role]);
596 }
597 }
598 }
599
600 return $roles;
601 }
602
603 /**
604 * Checks if a user can be edited or not by current administrator.
605 * Returns array('do_not_allow') if user cannot be edited.
606 *
607 * @hook 'map_meta_cap' filter
608 *
609 * @param array $caps Current user capabilities
610 * @param string $cap Capability to check
611 * @param int $user_id Current user ID
612 * @param array $args For our purpose, we receive edited user id at $args[0]
613 * @return array Allowed capabilities.
614 */
615 function filterUserEdit ( $caps, $cap, $user_id, $args )
616 {
617 if ( ! in_array( $cap, array( 'edit_user', 'delete_user', 'promote_user', 'remove_user' ) ) || ( ! isset($args[0]) ) || $user_id == (int) $args[0] ) {
618 return $caps;
619 }
620
621 $user = new WP_User( (int) $args[0] );
622
623 $this->generateNames();
624
625 if ( defined( 'CME_LEGACY_USER_EDIT_FILTER' ) && CME_LEGACY_USER_EDIT_FILTER ) {
626 $valid = array_keys($this->roles);
627
628 foreach ( $user->roles as $role ) {
629 if ( ! in_array($role, $valid) ) {
630 $caps = array('do_not_allow');
631 break;
632 }
633 }
634 } else {
635 global $wp_roles;
636
637 foreach ( $user->roles as $role ) {
638 $r = get_role( $role );
639 $level = ak_caps2level($r->capabilities);
640
641 if ( ( ! $level ) && ( 'administrator' == $role ) )
642 $level = 10;
643
644 if ( $level > $this->max_level ) {
645 $caps = array('do_not_allow');
646 break;
647 }
648 }
649
650 }
651
652 return $caps;
653 }
654
655 function processRoleUpdate() {
656 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && ( ! empty($_REQUEST['SaveRole']) || ! empty($_REQUEST['AddCap']) ) ) {
657 check_admin_referer('capsman-general-manager');
658
659 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
660 // TODO: Implement exceptions.
661 wp_die('<strong>' . esc_html__('You do not have permission to manage capabilities.', 'capsman-enhanced') . '</strong>');
662 }
663
664 if ( ! empty($_REQUEST['current']) ) { // don't process role update unless form variable is received
665 $role = get_role(sanitize_key($_REQUEST['current']));
666 $current_level = ($role) ? ak_caps2level($role->capabilities) : 0;
667
668 $this->processAdminGeneral();
669
670 $set_level = (isset($_POST['level'])) ? (int) $_POST['level'] : 0;
671
672 if ($set_level != $current_level) {
673 global $wp_roles, $wp_version;
674
675 if ( version_compare($wp_version, '4.9', '>=') ) {
676 $wp_roles->for_site();
677 } else {
678 $wp_roles->reinit();
679 }
680
681 foreach( get_users(array('role' => sanitize_key($_REQUEST['current']), 'fields' => 'ID')) as $ID ) {
682 $user = new WP_User($ID);
683 $user->get_role_caps();
684 $user->update_user_level_from_caps();
685 }
686 }
687 }
688 }
689
690 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && ( ! empty($_REQUEST['RenameRole']) ) ) {
691 check_admin_referer('capsman-general-manager');
692
693 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
694 // TODO: Implement exceptions.
695 wp_die('<strong>' . esc_html__('You do not have permission to manage capabilities.', 'capsman-enhanced') . '</strong>');
696 }
697
698 if ( ! empty($_REQUEST['current']) ) { // don't process role update unless form variable is received
699 $this->processAdminGeneral();
700 }
701 }
702 }
703
704 /**
705 * Manages global settings admin.
706 *
707 * @hook add_submenu_page
708 * @return void
709 */
710 function generalManager () {
711 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
712 // TODO: Implement exceptions.
713 wp_die('<strong>' . esc_html__('You do not have permission to manage capabilities.', 'capsman-enhanced') . '</strong>');
714 }
715
716 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD'])) {
717 if ( empty($_REQUEST['SaveRole']) && empty($_REQUEST['AddCap']) && empty($_REQUEST['RenameRole']) ) {
718 check_admin_referer('capsman-general-manager');
719 $this->processAdminGeneral();
720 } elseif ( ! empty($_REQUEST['SaveRole']) ) {
721 ak_admin_notify( $this->message ); // moved update operation to earlier action to avoid UI refresh issues. But outputting notification there breaks styling.
722 } elseif ( ! empty($_REQUEST['AddCap']) ) {
723 ak_admin_notify( $this->message );
724 }
725 } else {
726 if (!empty($_REQUEST['added'])) {
727 ak_admin_notify(__('New capability added to role.', 'capsman-enhanced'));
728 }
729 }
730
731 $this->generateNames();
732 $roles = array_keys($this->roles);
733
734 if ( ! isset($this->current) ) { // By default, we manage the default role
735 if (empty($_POST) && !empty($_REQUEST['role'])) {
736 $role = sanitize_key($_REQUEST['role']);
737
738 if (!pp_capabilities_is_editable_role($role)) {
739 wp_die(esc_html__('The selected role is not editable.', 'capsman-enhanced'));
740 }
741
742 $this->set_current_role($role);
743 }
744 }
745
746 if (!isset($this->current) || !get_role($this->current)) {
747 $this->current = $this->get_last_role();
748 }
749
750 if ( ! in_array($this->current, $roles) ) { // Current role has been deleted.
751 $this->current = array_shift($roles);
752 }
753
754 include ( dirname(CME_FILE) . '/includes/admin.php' );
755 }
756
757 /**
758 * Processes and saves the changes in the general capabilities form.
759 *
760 * @return void
761 */
762 private function processAdminGeneral ()
763 {
764 check_admin_referer('capsman-general-manager');
765
766 if (! isset($_POST['action']) || 'update' != $_POST['action'] ) {
767 // TODO: Implement exceptions. This must be a fatal error.
768 ak_admin_error(__('Bad form Received', 'capsman-enhanced'));
769 return;
770 }
771
772 // Select a new role.
773 if ( ! empty($post['LoadRole']) && !empty($_POST['role']) ) {
774 $this->set_current_role(sanitize_key($_POST['role']));
775 } elseif (!empty($_POST['current'])) {
776 $this->set_current_role(sanitize_key($_POST['current']));
777
778 require_once( dirname(__FILE__).'/handler.php' );
779 $capsman_modify = new CapsmanHandler( $this );
780 $capsman_modify->processAdminGeneral();
781 }
782 }
783
784 /**
785 * Callback function to create names.
786 * Replaces underscores by spaces and uppercases the first letter.
787 *
788 * @access private
789 * @param string $cap Capability name.
790 * @return string The generated name.
791 */
792 function _capNamesCB ( $cap )
793 {
794 $cap = str_replace('_', ' ', $cap);
795
796 return $cap;
797 }
798
799 /**
800 * Generates an array with the system capability names.
801 * The key is the capability and the value the created screen name.
802 *
803 * @uses self::_capNamesCB()
804 * @return void
805 */
806 function generateSysNames ()
807 {
808 $this->max_level = 10;
809 $this->roles = ak_get_roles(true);
810 $caps = array();
811
812 foreach ( array_keys($this->roles) as $role ) {
813 $role_caps = get_role($role);
814 $caps = array_merge( $caps, (array) $role_caps->capabilities ); // user reported PHP 5.3.3 error without array cast
815 }
816
817 $keys = array_keys($caps);
818 $names = array_map(array($this, '_capNamesCB'), $keys);
819 $this->capabilities = array_combine($keys, $names);
820
821 asort($this->capabilities);
822 }
823
824 /**
825 * Generates an array with the user capability names.
826 * If user has 'administrator' role, system roles are generated.
827 * The key is the capability and the value the created screen name.
828 * A user cannot manage more capabilities that has himself (Except for administrators).
829 *
830 * @uses self::_capNamesCB()
831 * @return void
832 */
833 function generateNames ()
834 {
835 if ( current_user_can('administrator') || ( is_multisite() && is_super_admin() ) ) {
836 $this->generateSysNames();
837 } else {
838 global $user_ID;
839 $user = new WP_User($user_ID);
840 $this->max_level = ak_caps2level($user->allcaps);
841
842 $keys = array_keys($user->allcaps);
843 $names = array_map(array($this, '_capNamesCB'), $keys);
844
845 $this->capabilities = ( $keys ) ? array_combine($keys, $names) : array();
846
847 $roles = ak_get_roles(true);
848 unset($roles['administrator']);
849
850 if ( ( defined( 'CME_LEGACY_USER_EDIT_FILTER' ) && CME_LEGACY_USER_EDIT_FILTER ) || ( ! empty( $_REQUEST['page'] ) && 'pp-capabilities' == $_REQUEST['page'] ) ) {
851 foreach ( $user->roles as $role ) { // Unset the roles from capability list.
852 unset ( $this->capabilities[$role] );
853 unset ( $roles[$role]); // User cannot manage his roles.
854 }
855 }
856
857 asort($this->capabilities);
858
859 foreach ( array_keys($roles) as $role ) {
860 $r = get_role($role);
861 $level = ak_caps2level($r->capabilities);
862
863 if ( $level > $this->max_level ) {
864 unset($roles[$role]);
865 }
866 }
867
868 $this->roles = $roles;
869 }
870 }
871
872 /**
873 * Manages backup, restore and resset roles and capabilities
874 *
875 * @hook add_management_page
876 * @return void
877 */
878 function backupTool ()
879 {
880 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('restore_roles')) {
881 // TODO: Implement exceptions.
882 wp_die('<strong>' . esc_html__('You do not have permission to restore roles.', 'capsman-enhanced') . '</strong>');
883 }
884
885 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD'])) {
886 check_admin_referer('pp-capabilities-backup');
887 require_once( dirname(__FILE__).'/backup-handler.php' );
888 $cme_backup_handler = new Capsman_BackupHandler( $this );
889 $cme_backup_handler->processBackupTool();
890 }
891
892 if ( isset($_GET['action']) && 'reset-defaults' == $_GET['action']) {
893 check_admin_referer('capsman-reset-defaults');
894 require_once( dirname(__FILE__).'/backup-handler.php' );
895 $cme_backup_handler = new Capsman_BackupHandler( $this );
896 $cme_backup_handler->backupToolReset();
897 }
898
899 include ( dirname(CME_FILE) . '/includes/backup.php' );
900 }
901
902
903 /**
904 * Processes export.
905 *
906 * This function need to run in admin init
907 * to enable clean download.
908 *
909 * @return void
910 */
911 function processExport()
912 {
913 global $wpdb;
914
915 if ( isset($_POST['export_backup']) && isset($_POST['pp_capabilities_export_section']) && !empty($_POST['pp_capabilities_export_section'])) {
916 check_admin_referer('pp-capabilities-backup');
917
918 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('restore_roles')) {
919 // TODO: Implement exceptions.
920 wp_die('<strong>' . esc_html__('You do not have permission to perform this action.', 'capsman-enhanced') . '</strong>');
921 }
922
923 $export_option = array_map('sanitize_text_field', $_POST['pp_capabilities_export_section']);
924 $backup_sections = pp_capabilities_backup_sections();
925 $charset = get_option( 'blog_charset' );
926 $data = [];
927
928 //add role
929 if(in_array('user_roles', $export_option)){
930 $data['user_roles'] = get_option($wpdb->prefix . 'user_roles');
931 }
932
933 //other section
934 foreach($backup_sections as $backup_key => $backup_section){
935
936 if(!in_array($backup_key, $export_option)){
937 continue;
938 }
939 $section_options = $backup_section['options'];
940 if(is_array($section_options) && !empty($section_options)){
941 foreach($section_options as $section_option){
942 $active_backup[] = $backup_section['label'];
943 $data[$section_option] = get_option($section_option);
944 }
945 }
946 }
947
948 // Set the download headers.
949 nocache_headers();
950 header( 'Content-Type: application/json; charset=' . $charset );
951 header( 'Content-Disposition: attachment; filename=capabilities-export-' . current_time('Y-m-d_g-i-s_a') . '.json' );
952 header( "Expires: 0" );
953
954 // Serialize the export data.
955 echo serialize( $data );
956
957 // Start the download.
958 die();
959
960 }
961 }
962
963 function settingsPage() {
964 include ( dirname(CME_FILE) . '/includes/settings.php' );
965 }
966 }
967
968 function cme_publishpressFooter() {
969 ?>
970 <footer>
971
972 <div class="pp-rating">
973 <a href="https://wordpress.org/support/plugin/capability-manager-enhanced/reviews/#new-post" target="_blank" rel="noopener noreferrer">
974 <?php printf(
975 esc_html__('If you like %s, please leave us a %s rating. Thank you!', 'capsman-enhanced'),
976 '<strong>PublishPress Capabilities</strong>',
977 '<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>'
978 );
979 ?>
980 </a>
981 </div>
982
983 <hr>
984 <nav>
985 <ul>
986 <li><a href="https://publishpress.com/capability-manager/" target="_blank" rel="noopener noreferrer" title="<?php esc_attr_e('About PublishPress Capabilities', 'capsman-enhanced');?>"><?php esc_html_e('About', 'capsman-enhanced');?>
987 </a></li>
988 <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', 'capsman-enhanced');?>"><?php esc_html_e('Documentation', 'capsman-enhanced');?>
989 </a></li>
990 <li><a href="https://publishpress.com/contact" target="_blank" rel="noopener noreferrer" title="<?php esc_attr_e('Contact the PublishPress team', 'capsman-enhanced');?>"><?php esc_html_e('Contact', 'capsman-enhanced');?>
991 </a></li>
992 <li><a href="https://twitter.com/publishpresscom" target="_blank" rel="noopener noreferrer"><span class="dashicons dashicons-twitter"></span>
993 </a></li>
994 <li><a href="https://facebook.com/publishpress" target="_blank" rel="noopener noreferrer"><span class="dashicons dashicons-facebook"></span>
995 </a></li>
996 </ul>
997 </nav>
998
999 <div class="pp-pressshack-logo">
1000 <a href="https://publishpress.com" target="_blank" rel="noopener noreferrer">
1001
1002 <img src="<?php echo esc_url_raw(plugins_url('', CME_FILE) . '/common/img/publishpress-logo.png');?>" />
1003 </a>
1004 </div>
1005
1006 </footer>
1007 <?php
1008 }
1009