PluginProbe ʕ •ᴥ•ʔ
PublishPress Capabilities – User Role Editor, Access Permissions, User Capabilities, Admin Menus / 2.4.1
PublishPress Capabilities – User Role Editor, Access Permissions, User Capabilities, Admin Menus v2.4.1
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 4 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 4 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
1028 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-roles',
356 array($this, 'ManageRoles'),
357 'dashicons-admin-network',
358 $menu_order
359 );
360
361 $hook = add_submenu_page('pp-capabilities-roles', __('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-roles', $permissions_title, $permissions_title, $cap_name, 'pp-capabilities', [$this, 'generalManager']);
374
375 add_submenu_page('pp-capabilities-roles', __('Editor Features', 'capsman-enhanced'), __('Editor Features', 'capsman-enhanced'), $cap_name, 'pp-capabilities-editor-features', [$this, 'ManageEditorFeatures']);
376
377 add_submenu_page('pp-capabilities-roles', __('Admin Features', 'capsman-enhanced'), __('Admin Features', 'capsman-enhanced'), $cap_name, 'pp-capabilities-admin-features', [$this, 'ManageAdminFeatures']);
378
379 do_action('pp-capabilities-admin-submenus');
380
381 add_submenu_page('pp-capabilities-roles', __('Backup', 'capsman-enhanced'), __('Backup', 'capsman-enhanced'), $cap_name, 'pp-capabilities-backup', array($this, 'backupTool'));
382
383 if (defined('PUBLISHPRESS_CAPS_PRO_VERSION')) {
384 add_submenu_page('pp-capabilities-roles', __('Settings', 'capsman-enhanced'), __('Settings', 'capsman-enhanced'), $cap_name, 'pp-capabilities-settings', array($this, 'settingsPage'));
385 }
386
387 if (!defined('PUBLISHPRESS_CAPS_PRO_VERSION')) {
388 add_submenu_page(
389 'pp-capabilities-roles',
390 __('Upgrade to Pro', 'capsman-enhanced'),
391 __('Upgrade to Pro', 'capsman-enhanced'),
392 'manage_capabilities',
393 'capsman-enhanced',
394 array($this, 'generalManager')
395 );
396 }
397 }
398
399 function initRolesAdmin() {
400 // @todo: solve order of execution issue so this column headers definition is not duplicated
401 if (!empty($_REQUEST['page']) && ('pp-capabilities-roles' == $_REQUEST['page'])) {
402 add_filter(
403 "manage_capabilities_page_pp-capabilities-roles_columns",
404
405 function($arr) {
406 return [
407 'cb' => '<input type="checkbox"/>',
408 'name' => esc_html__('Role Name', 'capsman-enhanced'),
409 'count' => esc_html__('Users', 'capsman-enhanced'),
410 'capabilities' => esc_html__('Capabilities', 'capsman-enhanced'),
411 'editor_features' => esc_html__('Editor Features', 'capsman-enhanced'),
412 'admin_features' => esc_html__('Admin Features', 'capsman-enhanced'),
413 'admin_menus' => esc_html__('Admin Menus', 'capsman-enhanced'),
414 'nav_menus' => esc_html__('Nav Menus', 'capsman-enhanced'),
415 ];
416 }
417 );
418 }
419 }
420
421 function handleRolesAjax() {
422 require_once (dirname(CME_FILE) . '/includes/roles/roles-functions.php');
423
424 if (!class_exists('PP_Capabilities_Roles')) {
425 require_once (dirname(CME_FILE) . '/includes/roles/class/class-pp-roles.php');
426 }
427
428 $roles = pp_capabilities_roles()->run();
429 }
430
431 /**
432 * Manages roles
433 *
434 * @hook add_management_page
435 * @return void
436 */
437 public function ManageRoles ()
438 {
439 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
440 // TODO: Implement exceptions.
441 wp_die('<strong>' . esc_html__('You do not have permission to manage roles.', 'capsman-enhanced') . '</strong>');
442 }
443
444 require_once (dirname(CME_FILE) . '/includes/roles/roles-functions.php');
445
446 if (!class_exists('PP_Capabilities_Roles')) {
447 require_once (dirname(CME_FILE) . '/includes/roles/class/class-pp-roles.php');
448 }
449
450 $roles = pp_capabilities_roles()->run();
451
452 require_once ( dirname(CME_FILE) . '/includes/roles/roles.php' );
453 }
454
455
456 /**
457 * Manages Editor Features
458 *
459 * @return void
460 */
461 public function ManageEditorFeatures() {
462 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
463 // TODO: Implement exceptions.
464 wp_die('<strong>' . esc_html__('You do not have permission to manage editor features.', 'capabilities-pro') . '</strong>');
465 }
466
467 $this->generateNames();
468 $roles = array_keys($this->roles);
469
470 if (!isset($this->current)) {
471 if (empty($_POST) && !empty($_REQUEST['role'])) {
472 $this->set_current_role(sanitize_key($_REQUEST['role']));
473 }
474 }
475
476 if (!isset($this->current) || !get_role($this->current)) {
477 $this->current = get_option('default_role');
478 }
479
480 if (!in_array($this->current, $roles)) {
481 $this->current = array_shift($roles);
482 }
483
484 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && isset($_POST['ppc-editor-features-role']) && !empty($_REQUEST['_wpnonce'])) {
485 if (!wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'pp-capabilities-editor-features')) {
486 wp_die('<strong>' . esc_html__('You do not have permission to manage editor features.', 'capabilities-pro') . '</strong>');
487 } else {
488 $this->set_current_role(sanitize_key($_POST['ppc-editor-features-role']));
489
490 $classic_editor = pp_capabilities_is_classic_editor_available();
491
492 $def_post_types = array_unique(apply_filters('pp_capabilities_feature_post_types', ['post', 'page']));
493
494 $active_tab = isset($_POST['pp_caps_tab']) ? sanitize_key($_POST['pp_caps_tab']) : 'post';
495
496 foreach ($def_post_types as $post_type) {
497 if ($classic_editor) {
498
499 if (isset($_POST['editor-features-all-submit'])){
500 $posted_settings = (isset($_POST["capsman_feature_restrict_classic_{$active_tab}"])) ? array_map('sanitize_text_field', $_POST["capsman_feature_restrict_classic_{$active_tab}"]) : [];
501 } else {
502 $posted_settings = (isset($_POST["capsman_feature_restrict_classic_{$post_type}"])) ? array_map('sanitize_text_field', $_POST["capsman_feature_restrict_classic_{$post_type}"]) : [];
503 }
504
505 $post_features_option = get_option("capsman_feature_restrict_classic_{$post_type}", []);
506 $post_features_option[sanitize_key($_POST['ppc-editor-features-role'])] = $posted_settings;
507 update_option("capsman_feature_restrict_classic_{$post_type}", $post_features_option, false);
508 }
509
510 if (isset($_POST['editor-features-all-submit'])){
511 $posted_settings = (isset($_POST["capsman_feature_restrict_{$active_tab}"])) ? array_map('sanitize_text_field', $_POST["capsman_feature_restrict_{$active_tab}"]) : [];
512 }else {
513 $posted_settings = (isset($_POST["capsman_feature_restrict_{$post_type}"])) ? array_map('sanitize_text_field', $_POST["capsman_feature_restrict_{$post_type}"]) : [];
514 }
515
516 $post_features_option = get_option("capsman_feature_restrict_{$post_type}", []);
517 $post_features_option[sanitize_key($_POST['ppc-editor-features-role'])] = $posted_settings;
518 update_option("capsman_feature_restrict_{$post_type}", $post_features_option, false);
519 }
520
521 ak_admin_notify(__('Settings updated.', 'capabilities-pro'));
522 }
523 }
524
525 do_action('pp_capabilities_editor_features');
526 include(dirname(CME_FILE) . '/includes/features/editor-features.php');
527 }
528
529 /**
530 * Manages Admin Features
531 *
532 * @return void
533 */
534 public function ManageAdminFeatures() {
535 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
536 // TODO: Implement exceptions.
537 wp_die('<strong>' . esc_html__('You do not have permission to manage admin features.', 'capabilities-pro') . '</strong>');
538 }
539
540 $this->generateNames();
541 $roles = array_keys($this->roles);
542
543 if (!isset($this->current)) {
544 if (empty($_POST) && !empty($_REQUEST['role'])) {
545 $this->set_current_role(sanitize_key($_REQUEST['role']));
546 }
547 }
548
549 if (!isset($this->current) || !get_role($this->current)) {
550 $this->current = get_option('default_role');
551 }
552
553 if (!in_array($this->current, $roles)) {
554 $this->current = array_shift($roles);
555 }
556
557 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && isset($_POST['ppc-admin-features-role']) && !empty($_REQUEST['_wpnonce'])) {
558 if (!wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'pp-capabilities-admin-features')) {
559 wp_die('<strong>' . esc_html__('You do not have permission to manage admin features.', 'capabilities-pro') . '</strong>');
560 } else {
561 $features_role = sanitize_key($_POST['ppc-admin-features-role']);
562
563 $this->set_current_role($features_role);
564
565 $disabled_admin_items = !empty(get_option('capsman_disabled_admin_features')) ? (array)get_option('capsman_disabled_admin_features') : [];
566 $disabled_admin_items[$features_role] = isset($_POST['capsman_disabled_admin_features']) ? array_map('sanitize_text_field', $_POST['capsman_disabled_admin_features']) : '';
567
568 update_option('capsman_disabled_admin_features', $disabled_admin_items, false);
569
570 //set reload option for instant reflection if user is updating own role
571 if (in_array($features_role, wp_get_current_user()->roles)){
572 $ppc_page_reload = '1';
573 }
574
575 ak_admin_notify(__('Settings updated.', 'capabilities-pro'));
576 }
577 }
578
579 include(dirname(CME_FILE) . '/includes/features/admin-features.php');
580 }
581
582 /**
583 * Sets the 'manage_capabilities' cap to the administrator role.
584 *
585 * @return void
586 */
587 public function setAdminCapability ()
588 {
589 if ($admin = get_role('administrator')) {
590 $admin->add_cap('manage_capabilities');
591 }
592 }
593
594 /**
595 * Filters roles that can be shown in roles list.
596 * This is mainly used to prevent an user admin to create other users with
597 * higher capabilities.
598 *
599 * @hook 'editable_roles' filter.
600 *
601 * @param $roles List of roles to check.
602 * @return array Restircted roles list
603 */
604 function filterEditRoles ( $roles )
605 {
606 global $current_user;
607
608 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
609 $this->generateNames();
610 $valid = array_keys($this->roles);
611
612 foreach ( $roles as $role => $caps ) {
613 if ( ! in_array($role, $valid) ) {
614 unset($roles[$role]);
615 }
616 }
617 }
618
619 return $roles;
620 }
621
622 /**
623 * Checks if a user can be edited or not by current administrator.
624 * Returns array('do_not_allow') if user cannot be edited.
625 *
626 * @hook 'map_meta_cap' filter
627 *
628 * @param array $caps Current user capabilities
629 * @param string $cap Capability to check
630 * @param int $user_id Current user ID
631 * @param array $args For our purpose, we receive edited user id at $args[0]
632 * @return array Allowed capabilities.
633 */
634 function filterUserEdit ( $caps, $cap, $user_id, $args )
635 {
636 if ( ! in_array( $cap, array( 'edit_user', 'delete_user', 'promote_user', 'remove_user' ) ) || ( ! isset($args[0]) ) || $user_id == (int) $args[0] ) {
637 return $caps;
638 }
639
640 $user = new WP_User( (int) $args[0] );
641
642 $this->generateNames();
643
644 if ( defined( 'CME_LEGACY_USER_EDIT_FILTER' ) && CME_LEGACY_USER_EDIT_FILTER ) {
645 $valid = array_keys($this->roles);
646
647 foreach ( $user->roles as $role ) {
648 if ( ! in_array($role, $valid) ) {
649 $caps = array('do_not_allow');
650 break;
651 }
652 }
653 } else {
654 global $wp_roles;
655
656 foreach ( $user->roles as $role ) {
657 $r = get_role( $role );
658 $level = ak_caps2level($r->capabilities);
659
660 if ( ( ! $level ) && ( 'administrator' == $role ) )
661 $level = 10;
662
663 if ( $level > $this->max_level ) {
664 $caps = array('do_not_allow');
665 break;
666 }
667 }
668
669 }
670
671 return $caps;
672 }
673
674 function processRoleUpdate() {
675 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && ( ! empty($_REQUEST['SaveRole']) || ! empty($_REQUEST['AddCap']) ) ) {
676 check_admin_referer('capsman-general-manager');
677
678 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
679 // TODO: Implement exceptions.
680 wp_die('<strong>' . esc_html__('You do not have permission to manage capabilities.', 'capsman-enhanced') . '</strong>');
681 }
682
683 if ( ! empty($_REQUEST['current']) ) { // don't process role update unless form variable is received
684 $role = get_role(sanitize_key($_REQUEST['current']));
685 $current_level = ($role) ? ak_caps2level($role->capabilities) : 0;
686
687 $this->processAdminGeneral();
688
689 $set_level = (isset($_POST['level'])) ? (int) $_POST['level'] : 0;
690
691 if ($set_level != $current_level) {
692 global $wp_roles, $wp_version;
693
694 if ( version_compare($wp_version, '4.9', '>=') ) {
695 $wp_roles->for_site();
696 } else {
697 $wp_roles->reinit();
698 }
699
700 foreach( get_users(array('role' => sanitize_key($_REQUEST['current']), 'fields' => 'ID')) as $ID ) {
701 $user = new WP_User($ID);
702 $user->get_role_caps();
703 $user->update_user_level_from_caps();
704 }
705 }
706 }
707 }
708
709 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD']) && ( ! empty($_REQUEST['RenameRole']) ) ) {
710 check_admin_referer('capsman-general-manager');
711
712 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
713 // TODO: Implement exceptions.
714 wp_die('<strong>' . esc_html__('You do not have permission to manage capabilities.', 'capsman-enhanced') . '</strong>');
715 }
716
717 if ( ! empty($_REQUEST['current']) ) { // don't process role update unless form variable is received
718 $this->processAdminGeneral();
719 }
720 }
721 }
722
723 /**
724 * Manages global settings admin.
725 *
726 * @hook add_submenu_page
727 * @return void
728 */
729 function generalManager () {
730 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities')) {
731 // TODO: Implement exceptions.
732 wp_die('<strong>' . esc_html__('You do not have permission to manage capabilities.', 'capsman-enhanced') . '</strong>');
733 }
734
735 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD'])) {
736 if ( empty($_REQUEST['SaveRole']) && empty($_REQUEST['AddCap']) && empty($_REQUEST['RenameRole']) ) {
737 check_admin_referer('capsman-general-manager');
738 $this->processAdminGeneral();
739 } elseif ( ! empty($_REQUEST['SaveRole']) ) {
740 ak_admin_notify( $this->message ); // moved update operation to earlier action to avoid UI refresh issues. But outputting notification there breaks styling.
741 } elseif ( ! empty($_REQUEST['AddCap']) ) {
742 ak_admin_notify( $this->message );
743 }
744 } else {
745 if (!empty($_REQUEST['added'])) {
746 ak_admin_notify(__('New capability added to role.', 'capsman-enhanced'));
747 }
748 }
749
750 $this->generateNames();
751 $roles = array_keys($this->roles);
752
753 if ( ! isset($this->current) ) { // By default, we manage the default role
754 if (empty($_POST) && !empty($_REQUEST['role'])) {
755 $role = sanitize_key($_REQUEST['role']);
756
757 if (!pp_capabilities_is_editable_role($role)) {
758 wp_die(esc_html__('The selected role is not editable.', 'capsman-enhanced'));
759 }
760
761 $this->set_current_role($role);
762 }
763 }
764
765 if (!isset($this->current) || !get_role($this->current)) {
766 $this->current = $this->get_last_role();
767 }
768
769 if ( ! in_array($this->current, $roles) ) { // Current role has been deleted.
770 $this->current = array_shift($roles);
771 }
772
773 include ( dirname(CME_FILE) . '/includes/admin.php' );
774 }
775
776 /**
777 * Processes and saves the changes in the general capabilities form.
778 *
779 * @return void
780 */
781 private function processAdminGeneral ()
782 {
783 check_admin_referer('capsman-general-manager');
784
785 if (! isset($_POST['action']) || 'update' != $_POST['action'] ) {
786 // TODO: Implement exceptions. This must be a fatal error.
787 ak_admin_error(__('Bad form Received', 'capsman-enhanced'));
788 return;
789 }
790
791 // Select a new role.
792 if ( ! empty($post['LoadRole']) && !empty($_POST['role']) ) {
793 $this->set_current_role(sanitize_key($_POST['role']));
794 } elseif (!empty($_POST['current'])) {
795 $this->set_current_role(sanitize_key($_POST['current']));
796
797 require_once( dirname(__FILE__).'/handler.php' );
798 $capsman_modify = new CapsmanHandler( $this );
799 $capsman_modify->processAdminGeneral();
800 }
801 }
802
803 /**
804 * Callback function to create names.
805 * Replaces underscores by spaces and uppercases the first letter.
806 *
807 * @access private
808 * @param string $cap Capability name.
809 * @return string The generated name.
810 */
811 function _capNamesCB ( $cap )
812 {
813 $cap = str_replace('_', ' ', $cap);
814
815 return $cap;
816 }
817
818 /**
819 * Generates an array with the system capability names.
820 * The key is the capability and the value the created screen name.
821 *
822 * @uses self::_capNamesCB()
823 * @return void
824 */
825 function generateSysNames ()
826 {
827 $this->max_level = 10;
828 $this->roles = ak_get_roles(true);
829 $caps = array();
830
831 foreach ( array_keys($this->roles) as $role ) {
832 $role_caps = get_role($role);
833 $caps = array_merge( $caps, (array) $role_caps->capabilities ); // user reported PHP 5.3.3 error without array cast
834 }
835
836 $keys = array_keys($caps);
837 $names = array_map(array($this, '_capNamesCB'), $keys);
838 $this->capabilities = array_combine($keys, $names);
839
840 asort($this->capabilities);
841 }
842
843 /**
844 * Generates an array with the user capability names.
845 * If user has 'administrator' role, system roles are generated.
846 * The key is the capability and the value the created screen name.
847 * A user cannot manage more capabilities that has himself (Except for administrators).
848 *
849 * @uses self::_capNamesCB()
850 * @return void
851 */
852 function generateNames ()
853 {
854 if ( current_user_can('administrator') || ( is_multisite() && is_super_admin() ) ) {
855 $this->generateSysNames();
856 } else {
857 global $user_ID;
858 $user = new WP_User($user_ID);
859 $this->max_level = ak_caps2level($user->allcaps);
860
861 $keys = array_keys($user->allcaps);
862 $names = array_map(array($this, '_capNamesCB'), $keys);
863
864 $this->capabilities = ( $keys ) ? array_combine($keys, $names) : array();
865
866 $roles = ak_get_roles(true);
867 unset($roles['administrator']);
868
869 if ( ( defined( 'CME_LEGACY_USER_EDIT_FILTER' ) && CME_LEGACY_USER_EDIT_FILTER ) || ( ! empty( $_REQUEST['page'] ) && 'pp-capabilities' == $_REQUEST['page'] ) ) {
870 foreach ( $user->roles as $role ) { // Unset the roles from capability list.
871 unset ( $this->capabilities[$role] );
872 unset ( $roles[$role]); // User cannot manage his roles.
873 }
874 }
875
876 asort($this->capabilities);
877
878 foreach ( array_keys($roles) as $role ) {
879 $r = get_role($role);
880 $level = ak_caps2level($r->capabilities);
881
882 if ( $level > $this->max_level ) {
883 unset($roles[$role]);
884 }
885 }
886
887 $this->roles = $roles;
888 }
889 }
890
891 /**
892 * Manages backup, restore and resset roles and capabilities
893 *
894 * @hook add_management_page
895 * @return void
896 */
897 function backupTool ()
898 {
899 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('restore_roles')) {
900 // TODO: Implement exceptions.
901 wp_die('<strong>' . esc_html__('You do not have permission to restore roles.', 'capsman-enhanced') . '</strong>');
902 }
903
904 if (!empty($_SERVER['REQUEST_METHOD']) && ('POST' == $_SERVER['REQUEST_METHOD'])) {
905 check_admin_referer('pp-capabilities-backup');
906 require_once( dirname(__FILE__).'/backup-handler.php' );
907 $cme_backup_handler = new Capsman_BackupHandler( $this );
908 $cme_backup_handler->processBackupTool();
909 }
910
911 if ( isset($_GET['action']) && 'reset-defaults' == $_GET['action']) {
912 check_admin_referer('capsman-reset-defaults');
913 require_once( dirname(__FILE__).'/backup-handler.php' );
914 $cme_backup_handler = new Capsman_BackupHandler( $this );
915 $cme_backup_handler->backupToolReset();
916 }
917
918 include ( dirname(CME_FILE) . '/includes/backup.php' );
919 }
920
921
922 /**
923 * Processes export.
924 *
925 * This function need to run in admin init
926 * to enable clean download.
927 *
928 * @return void
929 */
930 function processExport()
931 {
932 global $wpdb;
933
934 if ( isset($_POST['export_backup']) && isset($_POST['pp_capabilities_export_section']) && !empty($_POST['pp_capabilities_export_section'])) {
935 check_admin_referer('pp-capabilities-backup');
936
937 if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('restore_roles')) {
938 // TODO: Implement exceptions.
939 wp_die('<strong>' . esc_html__('You do not have permission to perform this action.', 'capsman-enhanced') . '</strong>');
940 }
941
942 $export_option = array_map('sanitize_text_field', $_POST['pp_capabilities_export_section']);
943 $backup_sections = pp_capabilities_backup_sections();
944 $charset = get_option( 'blog_charset' );
945 $data = [];
946
947 //add role
948 if(in_array('user_roles', $export_option)){
949 $data['user_roles'] = get_option($wpdb->prefix . 'user_roles');
950 }
951
952 //other section
953 foreach($backup_sections as $backup_key => $backup_section){
954
955 if(!in_array($backup_key, $export_option)){
956 continue;
957 }
958 $section_options = $backup_section['options'];
959 if(is_array($section_options) && !empty($section_options)){
960 foreach($section_options as $section_option){
961 $active_backup[] = $backup_section['label'];
962 $data[$section_option] = get_option($section_option);
963 }
964 }
965 }
966
967 // Set the download headers.
968 nocache_headers();
969 header( 'Content-Type: application/json; charset=' . $charset );
970 header( 'Content-Disposition: attachment; filename=capabilities-export-' . current_time('Y-m-d_g-i-s_a') . '.json' );
971 header( "Expires: 0" );
972
973 // Serialize the export data.
974 echo serialize( $data );
975
976 // Start the download.
977 die();
978
979 }
980 }
981
982 function settingsPage() {
983 include ( dirname(CME_FILE) . '/includes/settings.php' );
984 }
985 }
986
987 function cme_publishpressFooter() {
988 ?>
989 <footer>
990
991 <div class="pp-rating">
992 <a href="https://wordpress.org/support/plugin/capability-manager-enhanced/reviews/#new-post" target="_blank" rel="noopener noreferrer">
993 <?php printf(
994 esc_html__('If you like %s, please leave us a %s rating. Thank you!', 'capsman-enhanced'),
995 '<strong>PublishPress Capabilities</strong>',
996 '<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>'
997 );
998 ?>
999 </a>
1000 </div>
1001
1002 <hr>
1003 <nav>
1004 <ul>
1005 <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');?>
1006 </a></li>
1007 <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');?>
1008 </a></li>
1009 <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');?>
1010 </a></li>
1011 <li><a href="https://twitter.com/publishpresscom" target="_blank" rel="noopener noreferrer"><span class="dashicons dashicons-twitter"></span>
1012 </a></li>
1013 <li><a href="https://facebook.com/publishpress" target="_blank" rel="noopener noreferrer"><span class="dashicons dashicons-facebook"></span>
1014 </a></li>
1015 </ul>
1016 </nav>
1017
1018 <div class="pp-pressshack-logo">
1019 <a href="https://publishpress.com" target="_blank" rel="noopener noreferrer">
1020
1021 <img src="<?php echo esc_url_raw(plugins_url('', CME_FILE) . '/common/img/publishpress-logo.png');?>" />
1022 </a>
1023 </div>
1024
1025 </footer>
1026 <?php
1027 }
1028