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