CoreAdmin.php
6 years ago
admin.php
5 years ago
backup-handler.php
5 years ago
backup.php
5 years ago
cap-helper.php
6 years ago
filters-admin.php
6 years ago
filters-woocommerce.php
7 years ago
filters-wp_rest_workarounds.php
6 years ago
filters.php
6 years ago
functions-admin.php
6 years ago
functions.php
5 years ago
handler.php
5 years ago
inflect-cme.php
7 years ago
manager.php
6 years ago
network.php
6 years ago
pp-handler.php
6 years ago
pp-ui.php
6 years ago
publishpress-roles.php
6 years ago
handler.php
407 lines
| 1 | <?php |
| 2 | class CapsmanHandler |
| 3 | { |
| 4 | var $cm; |
| 5 | |
| 6 | function __construct( $manager_obj ) { |
| 7 | $this->cm = $manager_obj; |
| 8 | } |
| 9 | |
| 10 | function processAdminGeneral( $post ) { |
| 11 | global $wp_roles; |
| 12 | |
| 13 | do_action('publishpress-caps_process_update'); |
| 14 | |
| 15 | // Create a new role. |
| 16 | if ( ! empty($post['CreateRole']) ) { |
| 17 | if ( $newrole = $this->createRole($post['create-name']) ) { |
| 18 | ak_admin_notify(__('New role created.', 'capsman-enhanced')); |
| 19 | $this->cm->current = $newrole; |
| 20 | } else { |
| 21 | if ( empty($post['create-name']) && ( ! defined('WPLANG') || ! WPLANG ) ) |
| 22 | ak_admin_error( 'Error: No role name specified.', 'capsman-enhanced' ); |
| 23 | else |
| 24 | ak_admin_error(__('Error: Failed creating the new role.', 'capsman-enhanced')); |
| 25 | } |
| 26 | |
| 27 | // rename role |
| 28 | } elseif (!empty($post['RenameRole']) && !empty($post['rename-name'])) { |
| 29 | $current = get_role($post['current']); |
| 30 | $new_title = sanitize_text_field($post['rename-name']); |
| 31 | |
| 32 | if ($current && isset($wp_roles->roles[$current->name]) && $new_title) { |
| 33 | $old_title = $wp_roles->roles[$current->name]['name']; |
| 34 | $wp_roles->roles[$current->name]['name'] = $new_title; |
| 35 | update_option($wp_roles->role_key, $wp_roles->roles); |
| 36 | |
| 37 | ak_admin_notify(sprintf(__('Role "%s" (id %s) renamed to "%s"', 'capsman-enhanced'), $old_title, strtolower($current->name), $new_title)); |
| 38 | $this->cm->current = $current->name; |
| 39 | } |
| 40 | // Copy current role to a new one. |
| 41 | } elseif ( ! empty($post['CopyRole']) ) { |
| 42 | $current = get_role($post['current']); |
| 43 | if ( $newrole = $this->createRole($post['copy-name'], $current->capabilities) ) { |
| 44 | ak_admin_notify(__('New role created.', 'capsman-enhanced')); |
| 45 | $this->cm->current = $newrole; |
| 46 | } else { |
| 47 | if ( empty($post['copy-name']) && ( ! defined('WPLANG') || ! WPLANG ) ) |
| 48 | ak_admin_error( 'Error: No role name specified.', 'capsman-enhanced' ); |
| 49 | else |
| 50 | ak_admin_error(__('Error: Failed creating the new role.', 'capsman-enhanced')); |
| 51 | } |
| 52 | |
| 53 | // Save role changes. Already saved at start with self::saveRoleCapabilities(). |
| 54 | } elseif ( ! empty($post['SaveRole']) ) { |
| 55 | if ( MULTISITE ) { |
| 56 | global $wp_roles; |
| 57 | ( method_exists( $wp_roles, 'for_site' ) ) ? $wp_roles->for_site() : $wp_roles->reinit(); |
| 58 | } |
| 59 | |
| 60 | $this->saveRoleCapabilities($post['current'], $post['caps'], $post['level']); |
| 61 | |
| 62 | if ( defined( 'PRESSPERMIT_ACTIVE' ) ) { // log customized role caps for subsequent restoration |
| 63 | // for bbPress < 2.2, need to log customization of roles following bbPress activation |
| 64 | $plugins = ( function_exists( 'bbp_get_version' ) && version_compare( bbp_get_version(), '2.2', '<' ) ) ? array( 'bbpress.php' ) : array(); // back compat |
| 65 | |
| 66 | if ( ! $customized_roles = get_option( 'pp_customized_roles' ) ) |
| 67 | $customized_roles = array(); |
| 68 | |
| 69 | $customized_roles[$post['role']] = (object) array( 'caps' => array_map( 'boolval', $post['caps'] ), 'plugins' => $plugins ); |
| 70 | update_option( 'pp_customized_roles', $customized_roles ); |
| 71 | |
| 72 | global $wpdb; |
| 73 | $wpdb->query( "UPDATE $wpdb->options SET autoload = 'no' WHERE option_name = 'pp_customized_roles'" ); |
| 74 | } |
| 75 | // Create New Capability and adds it to current role. |
| 76 | } elseif ( ! empty($post['AddCap']) ) { |
| 77 | if ( MULTISITE ) { |
| 78 | global $wp_roles; |
| 79 | ( method_exists( $wp_roles, 'for_site' ) ) ? $wp_roles->for_site() : $wp_roles->reinit(); |
| 80 | } |
| 81 | |
| 82 | $role = get_role($post['current']); |
| 83 | $role->name = $post['current']; // bbPress workaround |
| 84 | |
| 85 | if ( $newname = $this->createNewName($post['capability-name']) ) { |
| 86 | $role->add_cap($newname['name']); |
| 87 | |
| 88 | // for bbPress < 2.2, need to log customization of roles following bbPress activation |
| 89 | $plugins = ( function_exists( 'bbp_get_version' ) && version_compare( bbp_get_version(), '2.2', '<' ) ) ? array( 'bbpress.php' ) : array(); // back compat |
| 90 | |
| 91 | if ( ! $customized_roles = get_option( 'pp_customized_roles' ) ) |
| 92 | $customized_roles = array(); |
| 93 | |
| 94 | $customized_roles[$post['role']] = (object) array( 'caps' => array_merge( $role->capabilities, array( $newname['name'] => 1 ) ), 'plugins' => $plugins ); |
| 95 | update_option( 'pp_customized_roles', $customized_roles ); |
| 96 | |
| 97 | global $wpdb; |
| 98 | $wpdb->query( "UPDATE $wpdb->options SET autoload = 'no' WHERE option_name = 'pp_customized_roles'" ); |
| 99 | |
| 100 | $url = admin_url('admin.php?page=capsman&role=' . $post['role'] . '&added=1'); |
| 101 | wp_redirect($url); |
| 102 | exit; |
| 103 | } else { |
| 104 | ak_admin_notify(__('Incorrect capability name.')); |
| 105 | } |
| 106 | |
| 107 | } elseif ( ! empty($post['update_filtered_types']) || ! empty($post['update_filtered_taxonomies']) || ! empty($post['update_detailed_taxonomies']) ) { |
| 108 | //if ( /* settings saved successfully on plugins_loaded action */ ) { |
| 109 | ak_admin_notify(__('Type / Taxonomy settings saved.', 'capsman-enhanced')); |
| 110 | //} else { |
| 111 | // ak_admin_error(__('Error saving capability settings.', 'capsman-enhanced')); |
| 112 | //} |
| 113 | } else { |
| 114 | if (!apply_filters('publishpress-caps_submission_ok', false)) { |
| 115 | ak_admin_error(__('Bad form received.', 'capsman-enhanced')); |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | if ( ! empty($newrole) && defined('PRESSPERMIT_ACTIVE') ) { |
| 120 | if ( ( ! empty($post['CreateRole']) && ! empty( $_REQUEST['new_role_pp_only'] ) ) || ( ! empty($post['CopyRole']) && ! empty( $_REQUEST['copy_role_pp_only'] ) ) ) { |
| 121 | $pp_only = (array) pp_capabilities_get_permissions_option( 'supplemental_role_defs' ); |
| 122 | $pp_only[]= $newrole; |
| 123 | |
| 124 | pp_capabilities_update_permissions_option('supplemental_role_defs', $pp_only); |
| 125 | |
| 126 | _cme_pp_default_pattern_role( $newrole ); |
| 127 | pp_refresh_options(); |
| 128 | } |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | |
| 133 | /** |
| 134 | * Creates a new role/capability name from user input name. |
| 135 | * Name rules are: |
| 136 | * - 2-40 charachers lenght. |
| 137 | * - Only letters, digits, spaces and underscores. |
| 138 | * - Must to start with a letter. |
| 139 | * |
| 140 | * @param string $name Name from user input. |
| 141 | * @return array|false An array with the name and display_name, or false if not valid $name. |
| 142 | */ |
| 143 | private function createNewName( $name ) { |
| 144 | // Allow max 40 characters, letters, digits and spaces |
| 145 | $name = trim(substr($name, 0, 40)); |
| 146 | $pattern = '/^[a-zA-Z][a-zA-Z0-9 _]+$/'; |
| 147 | |
| 148 | if ( preg_match($pattern, $name) ) { |
| 149 | $roles = ak_get_roles(); |
| 150 | |
| 151 | $name = str_replace(' ', '_', $name); |
| 152 | if ( in_array($name, $roles) || array_key_exists($name, $this->cm->capabilities) ) { |
| 153 | return false; // Already a role or capability with this name. |
| 154 | } |
| 155 | |
| 156 | $display = explode('_', $name); |
| 157 | $name = strtolower($name); |
| 158 | |
| 159 | // Apply ucfirst proper caps unless capitalization already provided |
| 160 | foreach($display as $i => $word) { |
| 161 | if ($word === strtolower($word)) { |
| 162 | $display[$i] = ucfirst($word); |
| 163 | } |
| 164 | } |
| 165 | |
| 166 | $display = implode(' ', $display); |
| 167 | |
| 168 | return compact('name', 'display'); |
| 169 | } else { |
| 170 | return false; |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | /** |
| 175 | * Creates a new role. |
| 176 | * |
| 177 | * @param string $name Role name to create. |
| 178 | * @param array $caps Role capabilities. |
| 179 | * @return string|false Returns the name of the new role created or false if failed. |
| 180 | */ |
| 181 | private function createRole( $name, $caps = array() ) { |
| 182 | if ( ! is_array($caps) ) |
| 183 | $caps = array(); |
| 184 | |
| 185 | $role = $this->createNewName($name); |
| 186 | if ( ! is_array($role) ) { |
| 187 | return false; |
| 188 | } |
| 189 | |
| 190 | $new_role = add_role($role['name'], $role['display'], $caps); |
| 191 | if ( is_object($new_role) ) { |
| 192 | return $role['name']; |
| 193 | } else { |
| 194 | return false; |
| 195 | } |
| 196 | } |
| 197 | |
| 198 | /** |
| 199 | * Saves capability changes to roles. |
| 200 | * |
| 201 | * @param string $role_name Role name to change its capabilities |
| 202 | * @param array $caps New capabilities for the role. |
| 203 | * @return void |
| 204 | */ |
| 205 | private function saveRoleCapabilities( $role_name, $caps, $level ) { |
| 206 | $this->cm->generateNames(); |
| 207 | $role = get_role($role_name); |
| 208 | |
| 209 | // workaround to ensure db storage of customizations to bbp dynamic roles |
| 210 | $role->name = $role_name; |
| 211 | |
| 212 | $stored_role_caps = ( ! empty($role->capabilities) && is_array($role->capabilities) ) ? array_intersect( $role->capabilities, array(true, 1) ) : array(); |
| 213 | $stored_negative_role_caps = ( ! empty($role->capabilities) && is_array($role->capabilities) ) ? array_intersect( $role->capabilities, array(false) ) : array(); |
| 214 | |
| 215 | $old_caps = array_intersect_key( $stored_role_caps, $this->cm->capabilities); |
| 216 | $new_caps = ( is_array($caps) ) ? array_map('boolval', $caps) : array(); |
| 217 | $new_caps = array_merge($new_caps, ak_level2caps($level)); |
| 218 | |
| 219 | // Find caps to add and remove |
| 220 | $add_caps = array_diff_key($new_caps, $old_caps); |
| 221 | $del_caps = array_diff_key(array_merge($old_caps, $stored_negative_role_caps), $new_caps); |
| 222 | |
| 223 | $changed_caps = array(); |
| 224 | foreach( array_intersect_key( $new_caps, $old_caps ) as $cap_name => $cap_val ) { |
| 225 | if ( $new_caps[$cap_name] != $old_caps[$cap_name] ) |
| 226 | $changed_caps[$cap_name] = $cap_val; |
| 227 | } |
| 228 | |
| 229 | $add_caps = array_merge( $add_caps, $changed_caps ); |
| 230 | |
| 231 | if ( ! $is_administrator = current_user_can('administrator') ) { |
| 232 | unset($add_caps['manage_capabilities']); |
| 233 | unset($del_caps['manage_capabilities']); |
| 234 | } |
| 235 | |
| 236 | if ( 'administrator' == $role_name && isset($del_caps['manage_capabilities']) ) { |
| 237 | unset($del_caps['manage_capabilities']); |
| 238 | ak_admin_error(__('You cannot remove Manage Capabilities from Administrators', 'capsman-enhanced')); |
| 239 | } |
| 240 | |
| 241 | // additional safeguard against removal of read capability |
| 242 | if ( isset( $del_caps['read'] ) && _cme_is_read_removal_blocked( $role_name ) ) { |
| 243 | unset( $del_caps['read'] ); |
| 244 | } |
| 245 | |
| 246 | // Add new capabilities to role |
| 247 | foreach ( $add_caps as $cap => $grant ) { |
| 248 | if ( $is_administrator || current_user_can($cap) ) |
| 249 | $role->add_cap( $cap, $grant ); |
| 250 | } |
| 251 | |
| 252 | // Remove capabilities from role |
| 253 | foreach ( $del_caps as $cap => $grant) { |
| 254 | if ( $is_administrator || current_user_can($cap) ) |
| 255 | $role->remove_cap($cap); |
| 256 | } |
| 257 | |
| 258 | $this->cm->log_db_roles(); |
| 259 | |
| 260 | if (is_multisite() && is_super_admin() && is_main_site()) { |
| 261 | if ( ! $autocreate_roles = get_site_option( 'cme_autocreate_roles' ) ) |
| 262 | $autocreate_roles = array(); |
| 263 | |
| 264 | $this_role_autocreate = ! empty($_REQUEST['cme_autocreate_role']); |
| 265 | |
| 266 | if ( $this_role_autocreate && ! in_array( $role_name, $autocreate_roles ) ) { |
| 267 | $autocreate_roles []= $role_name; |
| 268 | update_site_option( 'cme_autocreate_roles', $autocreate_roles ); |
| 269 | } |
| 270 | |
| 271 | if ( ! $this_role_autocreate && in_array( $role_name, $autocreate_roles ) ) { |
| 272 | $autocreate_roles = array_diff( $autocreate_roles, array( $role_name ) ); |
| 273 | update_site_option( 'cme_autocreate_roles', $autocreate_roles ); |
| 274 | } |
| 275 | |
| 276 | if ( ! empty($_REQUEST['cme_net_sync_role']) ) { |
| 277 | // loop through all sites on network, creating or updating role def |
| 278 | |
| 279 | global $wpdb, $wp_roles, $blog_id; |
| 280 | $blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs ORDER BY blog_id" ); |
| 281 | $orig_blog_id = $blog_id; |
| 282 | |
| 283 | $role_caption = $wp_roles->role_names[$role_name]; |
| 284 | |
| 285 | $new_caps = ( is_array($caps) ) ? array_map('boolval', $caps) : array(); |
| 286 | $new_caps = array_merge($new_caps, ak_level2caps($level) ); |
| 287 | |
| 288 | $admin_role = $wp_roles->get_role('administrator'); |
| 289 | $main_admin_caps = array_merge( $admin_role->capabilities, ak_level2caps(10) ); |
| 290 | |
| 291 | foreach ( $blog_ids as $id ) { |
| 292 | if ( 1 == $id ) |
| 293 | continue; |
| 294 | |
| 295 | switch_to_blog( $id ); |
| 296 | ( method_exists( $wp_roles, 'for_site' ) ) ? $wp_roles->for_site() : $wp_roles->reinit(); |
| 297 | |
| 298 | if ( $blog_role = $wp_roles->get_role( $role_name ) ) { |
| 299 | $stored_role_caps = ( ! empty($blog_role->capabilities) && is_array($blog_role->capabilities) ) ? array_intersect( $blog_role->capabilities, array(true, 1) ) : array(); |
| 300 | |
| 301 | $old_caps = array_intersect_key( $stored_role_caps, $this->cm->capabilities); |
| 302 | |
| 303 | // Find caps to add and remove |
| 304 | $add_caps = array_diff_key($new_caps, $old_caps); |
| 305 | $del_caps = array_intersect_key( array_diff_key($old_caps, $new_caps), $main_admin_caps ); // don't mess with caps that are totally unused on main site |
| 306 | |
| 307 | // Add new capabilities to role |
| 308 | foreach ( $add_caps as $cap => $grant ) { |
| 309 | $blog_role->add_cap( $cap, $grant ); |
| 310 | } |
| 311 | |
| 312 | // Remove capabilities from role |
| 313 | foreach ( $del_caps as $cap => $grant) { |
| 314 | $blog_role->remove_cap($cap); |
| 315 | } |
| 316 | |
| 317 | } else { |
| 318 | $wp_roles->add_role( $role_name, $role_caption, $new_caps ); |
| 319 | } |
| 320 | |
| 321 | restore_current_blog(); |
| 322 | } |
| 323 | |
| 324 | ( method_exists( $wp_roles, 'for_site' ) ) ? $wp_roles->for_site() : $wp_roles->reinit(); |
| 325 | } |
| 326 | } // endif multisite installation with super admin editing a main site role |
| 327 | |
| 328 | pp_capabilities_autobackup(); |
| 329 | } |
| 330 | |
| 331 | |
| 332 | |
| 333 | /** |
| 334 | * Deletes a role. |
| 335 | * The role comes from the $_GET['role'] var and the nonce has already been checked. |
| 336 | * Default WordPress role cannot be deleted and if trying to do it, throws an error. |
| 337 | * Users with the deleted role, are moved to the WordPress default role. |
| 338 | * |
| 339 | * @return void |
| 340 | */ |
| 341 | function adminDeleteRole () |
| 342 | { |
| 343 | global $wpdb, $wp_roles; |
| 344 | |
| 345 | check_admin_referer('delete-role_' . $_GET['role']); |
| 346 | |
| 347 | $this->cm->current = $_GET['role']; |
| 348 | $default = get_option('default_role'); |
| 349 | if ( $default == $this->cm->current ) { |
| 350 | ak_admin_error(sprintf(__('Cannot delete default role. You <a href="%s">have to change it first</a>.', 'capsman-enhanced'), 'options-general.php')); |
| 351 | return; |
| 352 | } |
| 353 | |
| 354 | $like = $wpdb->esc_like( $this->cm->current ); |
| 355 | |
| 356 | $query = $wpdb->prepare( "SELECT ID FROM {$wpdb->usermeta} INNER JOIN {$wpdb->users} " |
| 357 | . "ON {$wpdb->usermeta}.user_id = {$wpdb->users}.ID " |
| 358 | . "WHERE meta_key='{$wpdb->prefix}capabilities' AND meta_value LIKE %s", $like ); |
| 359 | |
| 360 | $users = $wpdb->get_results($query); |
| 361 | |
| 362 | // Array of all roles except the one being deleted, for use below |
| 363 | $role_names = array_diff_key( array_keys( $wp_roles->role_names ), array( $this->cm->current => true ) ); |
| 364 | |
| 365 | $count = 0; |
| 366 | foreach ( $users as $u ) { |
| 367 | $skip_role_set = false; |
| 368 | |
| 369 | $user = new WP_User($u->ID); |
| 370 | if ( $user->has_cap($this->cm->current) ) { // Check again the user has the deleting role |
| 371 | |
| 372 | // Role may have been assigned supplementally. Don't move a user to default role if they still have one or more roles following the deletion. |
| 373 | foreach( $role_names as $_role_name ) { |
| 374 | if ( $user->has_cap($_role_name) ) { |
| 375 | $skip_role_set = true; |
| 376 | break; |
| 377 | } |
| 378 | } |
| 379 | |
| 380 | if ( ! $skip_role_set ) { |
| 381 | $user->set_role($default); |
| 382 | $count++; |
| 383 | } |
| 384 | } |
| 385 | } |
| 386 | |
| 387 | remove_role($this->cm->current); |
| 388 | unset($this->cm->roles[$this->cm->current]); |
| 389 | |
| 390 | if ( $customized_roles = get_option( 'pp_customized_roles' ) ) { |
| 391 | if ( isset( $customized_roles[$this->cm->current] ) ) { |
| 392 | unset( $customized_roles[$this->cm->current] ); |
| 393 | update_option( 'pp_customized_roles', $customized_roles ); |
| 394 | } |
| 395 | } |
| 396 | |
| 397 | ak_admin_notify(sprintf(__('Role has been deleted. %1$d users moved to default role %2$s.', 'capsman-enhanced'), $count, $this->cm->roles[$default])); |
| 398 | $this->cm->current = $default; |
| 399 | } |
| 400 | } |
| 401 | |
| 402 | if ( ! function_exists('boolval') ) { |
| 403 | function boolval( $val ) { |
| 404 | return (bool) $val; |
| 405 | } |
| 406 | } |
| 407 |