features
3 years ago
roles
3 years ago
admin-load.php
3 years ago
admin.php
3 years ago
backup-handler.php
3 years ago
backup.php
3 years ago
cap-helper.php
4 years ago
dashboard.php
3 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
3 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
3 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
test-user-ui.php
3 years ago
test-user.php
3 years ago
admin-load.php
635 lines
| 1 | <?php |
| 2 | |
| 3 | /* |
| 4 | * PublishPress Capabilities [Free] |
| 5 | * |
| 6 | * Admin execution controller: menu registration and other filters and actions that need to be loaded for every wp-admin URL |
| 7 | * |
| 8 | * This module should not include full functions related to our own plugin screens. |
| 9 | * Instead, use these filter and action handlers to load other classes when needed. |
| 10 | * |
| 11 | */ |
| 12 | class PP_Capabilities_Admin_UI { |
| 13 | function __construct() { |
| 14 | global $pagenow; |
| 15 | |
| 16 | /** |
| 17 | * The class responsible for handling notifications |
| 18 | */ |
| 19 | require_once (dirname(CME_FILE) . '/classes/pp-capabilities-notices.php'); |
| 20 | |
| 21 | /** |
| 22 | * Installer class |
| 23 | */ |
| 24 | require_once (dirname(CME_FILE) . '/classes/pp-capabilities-installer.php'); |
| 25 | |
| 26 | add_action('init', [$this, 'featureRestrictionsGutenberg'], PHP_INT_MAX - 1); |
| 27 | |
| 28 | if (is_admin()) { |
| 29 | add_action('admin_init', [$this, 'featureRestrictionsClassic'], PHP_INT_MAX - 1); |
| 30 | add_action('wp_ajax_save_dashboard_feature_by_ajax', [$this, 'saveDashboardFeature']); |
| 31 | |
| 32 | // Installation hooks |
| 33 | add_action( |
| 34 | 'pp_capabilities_install', |
| 35 | ['PublishPress\\Capabilities\\Classes\\PP_Capabilities_Installer', 'runInstallTasks'] |
| 36 | ); |
| 37 | add_action( |
| 38 | 'pp_capabilities_upgrade', |
| 39 | ['PublishPress\\Capabilities\\Classes\\PP_Capabilities_Installer', 'runUpgradeTasks'] |
| 40 | ); |
| 41 | add_action('admin_init', [$this, 'manage_installation'], 2000); |
| 42 | } |
| 43 | |
| 44 | add_filter('cme_publishpress_capabilities_capabilities', 'cme_publishpress_capabilities_capabilities'); |
| 45 | |
| 46 | add_action('admin_enqueue_scripts', [$this, 'adminScripts'], 100); |
| 47 | add_action('admin_print_scripts', [$this, 'adminPrintScripts']); |
| 48 | |
| 49 | add_action('profile_update', [$this, 'action_profile_update'], 10, 2); |
| 50 | |
| 51 | if (is_multisite()) { |
| 52 | add_action('add_user_to_blog', [$this, 'action_profile_update'], 9); |
| 53 | } else { |
| 54 | add_action('user_register', [$this, 'action_profile_update'], 9); |
| 55 | } |
| 56 | add_action('init', [$this, 'register_textdomain']); |
| 57 | |
| 58 | if (is_admin() && (isset($_REQUEST['page']) && (in_array($_REQUEST['page'], ['pp-capabilities', 'pp-capabilities-backup', 'pp-capabilities-roles', 'pp-capabilities-admin-menus', 'pp-capabilities-editor-features', 'pp-capabilities-nav-menus', 'pp-capabilities-settings', 'pp-capabilities-admin-features', 'pp-capabilities-profile-features', 'pp-capabilities-dashboard'])) |
| 59 | |
| 60 | || (!empty($_REQUEST['action']) && in_array($_REQUEST['action'], ['pp-roles-add-role', 'pp-roles-delete-role', 'pp-roles-hide-role', 'pp-roles-unhide-role'])) |
| 61 | || ( ! empty($_SERVER['SCRIPT_NAME']) && strpos(sanitize_text_field($_SERVER['SCRIPT_NAME']), 'p-admin/plugins.php' ) && ! empty($_REQUEST['action'] ) ) |
| 62 | || ( isset($_GET['action']) && ('reset-defaults' == $_GET['action']) && isset($_REQUEST['_wpnonce']) && wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'capsman-reset-defaults') ) |
| 63 | || in_array( $pagenow, array( 'users.php', 'user-edit.php', 'profile.php', 'user-new.php' ) ) |
| 64 | ) ) { |
| 65 | global $capsman; |
| 66 | |
| 67 | // Run the plugin |
| 68 | require_once ( dirname(CME_FILE) . '/framework/lib/formating.php' ); |
| 69 | require_once ( dirname(CME_FILE) . '/framework/lib/users.php' ); |
| 70 | |
| 71 | require_once ( dirname(CME_FILE) . '/includes/manager.php' ); |
| 72 | $capsman = new CapabilityManager(); |
| 73 | } else { |
| 74 | add_action( 'admin_menu', [$this, 'cmeSubmenus'], 18 ); |
| 75 | } |
| 76 | |
| 77 | add_action('init', function() { // late execution avoids clash with autoloaders in other plugins |
| 78 | global $pagenow; |
| 79 | |
| 80 | if ((($pagenow == 'admin.php') && isset($_GET['page']) && in_array($_GET['page'], ['pp-capabilities', 'pp-capabilities-backup', 'pp-capabilities-roles', 'pp-capabilities-admin-menus', 'pp-capabilities-editor-features', 'pp-capabilities-nav-menus', 'pp-capabilities-settings', 'pp-capabilities-admin-features', 'pp-capabilities-profile-features', 'pp-capabilities-dashboard'])) // @todo: CSS for button alignment in Editor Features, Admin Features |
| 81 | || (defined('DOING_AJAX') && DOING_AJAX && !empty($_REQUEST['action']) && (false !== strpos(sanitize_key($_REQUEST['action']), 'capability-manager-enhanced'))) |
| 82 | ) { |
| 83 | if (!class_exists('\PublishPress\WordPressReviews\ReviewsController')) { |
| 84 | include_once PUBLISHPRESS_CAPS_ABSPATH . '/vendor/publishpress/wordpress-reviews/ReviewsController.php'; |
| 85 | } |
| 86 | |
| 87 | if (class_exists('\PublishPress\WordPressReviews\ReviewsController')) { |
| 88 | $reviews = new \PublishPress\WordPressReviews\ReviewsController( |
| 89 | 'capability-manager-enhanced', |
| 90 | 'PublishPress Capabilities', |
| 91 | plugin_dir_url(CME_FILE) . 'common/img/capabilities-wp-logo.png' |
| 92 | ); |
| 93 | |
| 94 | add_filter('publishpress_wp_reviews_display_banner_capability-manager-enhanced', [$this, 'shouldDisplayBanner']); |
| 95 | |
| 96 | $reviews->init(); |
| 97 | } |
| 98 | } |
| 99 | }); |
| 100 | |
| 101 | |
| 102 | add_filter('pp_capabilities_feature_post_types', [$this, 'fltEditorFeaturesPostTypes'], 5); |
| 103 | add_filter('block_editor_settings_all', [$this, 'filterCodeEditingStatus'], 999); |
| 104 | add_filter('classic_editor_enabled_editors_for_post_type', [$this, 'filterRolePostTypeEditor'], 10, 2); |
| 105 | add_filter('classic_editor_plugin_settings', [$this, 'filterRoleEditorSettings']); |
| 106 | |
| 107 | //profile features integration |
| 108 | require_once (dirname(CME_FILE) . '/includes/features/restrict-profile-features.php'); |
| 109 | \PublishPress\Capabilities\PP_Capabilities_Profile_Features::instance(); |
| 110 | |
| 111 | //capabilities settings |
| 112 | add_action('pp-capabilities-settings-ui', [$this, 'settingsUI']); |
| 113 | |
| 114 | //clear the "done" flag on new plugin install |
| 115 | add_action('activated_plugin', [$this, 'clearProfileFeaturesDoneFlag'], 10, 2); |
| 116 | //prevent access to admin dashboard |
| 117 | add_action('admin_init', [$this, 'blockDashboardAccess']); |
| 118 | } |
| 119 | |
| 120 | function register_textdomain() { |
| 121 | |
| 122 | $domain = 'capsman-enhanced'; |
| 123 | $mofile_custom = sprintf('%s-%s.mo', $domain, get_user_locale()); |
| 124 | $locations = [ |
| 125 | trailingslashit( WP_LANG_DIR . '/' . $domain ), |
| 126 | trailingslashit( WP_LANG_DIR . '/loco/plugins/'), |
| 127 | trailingslashit( WP_LANG_DIR ), |
| 128 | trailingslashit( plugin_dir_path(CME_FILE) . 'languages' ), |
| 129 | ]; |
| 130 | // Try custom locations in WP_LANG_DIR. |
| 131 | foreach ($locations as $location) { |
| 132 | if (load_textdomain($domain, $location . $mofile_custom)) { |
| 133 | return true; |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | } |
| 138 | |
| 139 | /** |
| 140 | * Filters the editors that are enabled for the post type. |
| 141 | * |
| 142 | * @param array $editors Associative array of the editors and whether they are enabled for the post type. |
| 143 | * @param string $post_type The post type. |
| 144 | */ |
| 145 | public function filterRolePostTypeEditor($editors, $post_type) { |
| 146 | $user = wp_get_current_user(); |
| 147 | |
| 148 | if (is_object($user) && isset($user->roles)) { |
| 149 | $current_user_editors = []; |
| 150 | foreach ($user->roles as $user_role) { |
| 151 | //get role option |
| 152 | $role_option = get_option("pp_capabilities_{$user_role}_role_option", []); |
| 153 | if (is_array($role_option) && !empty($role_option) && !empty($role_option['role_editor'])) { |
| 154 | $current_user_editors = array_merge($current_user_editors, $role_option['role_editor']); |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | if (!empty($current_user_editors)) { |
| 159 | $current_user_editors = array_unique($current_user_editors); |
| 160 | $editors = array( |
| 161 | 'classic_editor' => in_array('classic_editor', $current_user_editors) ? true : false, |
| 162 | 'block_editor' => in_array('block_editor', $current_user_editors) ? true : false, |
| 163 | ); |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | return $editors; |
| 168 | } |
| 169 | |
| 170 | /** |
| 171 | * Override the classic editor plugin's settings. |
| 172 | * |
| 173 | * @param bool $settings |
| 174 | * @return mixed |
| 175 | */ |
| 176 | public function filterRoleEditorSettings($settings) { |
| 177 | $user = wp_get_current_user(); |
| 178 | |
| 179 | if (is_object($user) && isset($user->roles)) { |
| 180 | $current_user_editors = []; |
| 181 | foreach ($user->roles as $user_role) { |
| 182 | //get role option |
| 183 | $role_option = get_option("pp_capabilities_{$user_role}_role_option", []); |
| 184 | if (is_array($role_option) && !empty($role_option) && !empty($role_option['role_editor'])) { |
| 185 | $current_user_editors = array_merge($current_user_editors, $role_option['role_editor']); |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | if (!empty($current_user_editors)) { |
| 190 | $current_user_editors = array_unique($current_user_editors); |
| 191 | $settings = []; |
| 192 | $settings['editor'] = ($current_user_editors[0] === 'classic_editor') ? 'classic' : 'block'; |
| 193 | $settings['allow-users'] = count($current_user_editors) > 1 ? true : false; |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | return $settings; |
| 198 | } |
| 199 | |
| 200 | public function filterCodeEditingStatus($settings) { |
| 201 | $user = wp_get_current_user(); |
| 202 | |
| 203 | if (is_object($user) && isset($user->roles)) { |
| 204 | foreach ($user->roles as $user_role) { |
| 205 | //get role option |
| 206 | $role_option = get_option("pp_capabilities_{$user_role}_role_option", []); |
| 207 | if (is_array($role_option) && !empty($role_option) && !empty($role_option['disable_code_editor']) && (int)$role_option['disable_code_editor'] > 0) { |
| 208 | $settings['codeEditingEnabled'] = false; |
| 209 | break; |
| 210 | } |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | return $settings; |
| 215 | } |
| 216 | |
| 217 | public function fltEditorFeaturesPostTypes($def_post_types) { |
| 218 | if((int)get_option('cme_editor_features_private_post_type') > 0 || defined('PP_CAPABILITIES_PRIVATE_TYPES')){ |
| 219 | $private_cpt = get_post_types(['public' => true, 'show_ui' => true], 'names', 'or'); |
| 220 | $public_cpt = get_post_types(['public' => true, 'show_ui' => true], 'names', 'or'); |
| 221 | $def_post_types = array_unique(array_merge($def_post_types, $private_cpt, $public_cpt)); |
| 222 | }else{ |
| 223 | $def_post_types = array_merge($def_post_types, get_post_types(['public' => true], 'names')); |
| 224 | } |
| 225 | |
| 226 | unset($def_post_types['attachment']); |
| 227 | |
| 228 | return $def_post_types; |
| 229 | } |
| 230 | |
| 231 | public function shouldDisplayBanner() { |
| 232 | global $pagenow; |
| 233 | |
| 234 | return ($pagenow == 'admin.php') && isset($_GET['page']) && in_array($_GET['page'], ['pp-capabilities', 'pp-capabilities-backup', 'pp-capabilities-roles', 'pp-capabilities-admin-menus', 'pp-capabilities-editor-features', 'pp-capabilities-nav-menus', 'pp-capabilities-settings', 'pp-capabilities-admin-features', 'pp-capabilities-profile-features', 'pp-capabilities-dashboard']); |
| 235 | } |
| 236 | |
| 237 | private function applyFeatureRestrictions($editor = 'gutenberg') { |
| 238 | global $pagenow; |
| 239 | |
| 240 | if (is_multisite() && is_super_admin() && !defined('PP_CAPABILITIES_RESTRICT_SUPER_ADMIN')) { |
| 241 | return; |
| 242 | } |
| 243 | |
| 244 | if (!pp_capabilities_feature_enabled('editor-features')) { |
| 245 | return; |
| 246 | } |
| 247 | |
| 248 | // Return if not a post editor request |
| 249 | if (!in_array($pagenow, ['post.php', 'post-new.php'])) { |
| 250 | return; |
| 251 | } |
| 252 | |
| 253 | static $def_post_types; // avoid redundant filter application |
| 254 | |
| 255 | if (!isset($def_post_types)) { |
| 256 | $def_post_types = array_unique(apply_filters('pp_capabilities_feature_post_types', ['post', 'page'])); |
| 257 | } |
| 258 | |
| 259 | $post_type = pp_capabilities_get_post_type(); |
| 260 | |
| 261 | // Return if not a supported post type |
| 262 | if (in_array($post_type, apply_filters('pp_capabilities_unsupported_post_types', ['attachment']))) { |
| 263 | return; |
| 264 | } |
| 265 | |
| 266 | switch ($editor) { |
| 267 | case 'gutenberg': |
| 268 | if (_pp_capabilities_is_block_editor_active()) { |
| 269 | require_once ( dirname(CME_FILE) . '/includes/features/restrict-editor-features.php' ); |
| 270 | PP_Capabilities_Post_Features::applyRestrictions($post_type); |
| 271 | } |
| 272 | |
| 273 | break; |
| 274 | |
| 275 | case 'classic': |
| 276 | if (!_pp_capabilities_is_block_editor_active()) { |
| 277 | require_once ( dirname(CME_FILE) . '/includes/features/restrict-editor-features.php' ); |
| 278 | PP_Capabilities_Post_Features::adminInitClassic($post_type); |
| 279 | } |
| 280 | } |
| 281 | } |
| 282 | |
| 283 | function featureRestrictionsGutenberg() { |
| 284 | $this->applyFeatureRestrictions(); |
| 285 | } |
| 286 | |
| 287 | function featureRestrictionsClassic() { |
| 288 | $this->applyFeatureRestrictions('classic'); |
| 289 | } |
| 290 | |
| 291 | function adminScripts() { |
| 292 | global $publishpress; |
| 293 | |
| 294 | if (function_exists('get_current_screen') && (!defined('PUBLISHPRESS_VERSION') || empty($publishpress) || empty($publishpress->modules) || empty($publishpress->modules->roles))) { |
| 295 | $screen = get_current_screen(); |
| 296 | |
| 297 | if ('user-edit' === $screen->base || 'profile' === $screen->base || ('user' === $screen->base && 'add' === $screen->action)) { |
| 298 | |
| 299 | $multi_role = ('user-edit' === $screen->base && get_option('cme_capabilities_edit_user_multi_roles')) || ('user' === $screen->base && 'add' === $screen->action && (defined('PP_CAPABILITIES_ADD_USER_MULTI_ROLES') || get_option('cme_capabilities_add_user_multi_roles'))) ? true : false; |
| 300 | |
| 301 | // Check if we are on the user's profile page |
| 302 | wp_enqueue_script( |
| 303 | 'pp-capabilities-chosen-js', |
| 304 | plugin_dir_url(CME_FILE) . 'common/libs/chosen-v1.8.7/chosen.jquery.js', |
| 305 | ['jquery'], |
| 306 | PUBLISHPRESS_CAPS_VERSION |
| 307 | ); |
| 308 | |
| 309 | wp_enqueue_script( |
| 310 | 'pp-capabilities-jquery-ui', |
| 311 | plugin_dir_url(CME_FILE) . 'common/libs/jquery/jquery-ui.js', |
| 312 | ['jquery'], |
| 313 | PUBLISHPRESS_CAPS_VERSION |
| 314 | ); |
| 315 | |
| 316 | wp_enqueue_script( |
| 317 | 'pp-capabilities-roles-profile-js', |
| 318 | plugin_dir_url(CME_FILE) . 'common/js/profile.js', |
| 319 | ['jquery', 'pp-capabilities-chosen-js'], |
| 320 | PUBLISHPRESS_CAPS_VERSION |
| 321 | ); |
| 322 | |
| 323 | wp_enqueue_style( |
| 324 | 'pp-capabilities-chosen-css', |
| 325 | plugin_dir_url(CME_FILE) . 'common/libs/chosen-v1.8.7/chosen.css', |
| 326 | false, |
| 327 | PUBLISHPRESS_CAPS_VERSION |
| 328 | ); |
| 329 | wp_enqueue_style( |
| 330 | 'pp-capabilities-roles-profile-css', |
| 331 | plugin_dir_url(CME_FILE) . 'common/css/profile.css', |
| 332 | ['pp-capabilities-chosen-css'], |
| 333 | PUBLISHPRESS_CAPS_VERSION |
| 334 | ); |
| 335 | |
| 336 | $roles = !empty($_GET['user_id']) ? $this->getUsersRoles((int) $_GET['user_id']) : []; |
| 337 | |
| 338 | if (empty($roles)) { |
| 339 | $roles = (array) get_option('default_role'); |
| 340 | } |
| 341 | |
| 342 | wp_localize_script( |
| 343 | 'pp-capabilities-roles-profile-js', |
| 344 | 'ppCapabilitiesProfileData', |
| 345 | [ |
| 346 | 'role_description' => esc_html__('Drag multiple roles selection to change order.', 'capsman-enhanced'), |
| 347 | 'selected_roles' => $roles, |
| 348 | 'multi_roles' => $multi_role ? 1 : 0, |
| 349 | 'profile_page_title' => esc_html__('Page title', 'capsman-enhanced'), |
| 350 | 'rankmath_title' => esc_html__('Rank Math SEO', 'capsman-enhanced'), |
| 351 | 'nonce' => wp_create_nonce('ppc-profile-edit-action') |
| 352 | ] |
| 353 | ); |
| 354 | } |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | function adminPrintScripts() { |
| 359 | |
| 360 | global $capabilities_toplevel_page; |
| 361 | |
| 362 | if (!empty($capabilities_toplevel_page) && pp_capabilities_feature_enabled('capabilities') && current_user_can('manage_capabilities')) { |
| 363 | /** |
| 364 | * Update capabilities top level slug from dashboard/toplevel page to capabilities |
| 365 | */ |
| 366 | $menu_inline_script = " |
| 367 | jQuery(document).ready( function($) { |
| 368 | if (jQuery('li#toplevel_page_{$capabilities_toplevel_page} a.toplevel_page_{$capabilities_toplevel_page}').length > 0) { |
| 369 | var toplevel_page = jQuery('li#toplevel_page_{$capabilities_toplevel_page} a.toplevel_page_{$capabilities_toplevel_page}'); |
| 370 | var toplevel_page_link = toplevel_page.attr('href'); |
| 371 | if (toplevel_page_link) { |
| 372 | toplevel_page.attr('href', toplevel_page_link.replace('{$capabilities_toplevel_page}', 'pp-capabilities')); |
| 373 | } |
| 374 | } |
| 375 | });"; |
| 376 | ppc_add_inline_script($menu_inline_script); |
| 377 | } |
| 378 | |
| 379 | // Counteract overzealous menu icon styling in PublishPress <= 3.2.0 :) |
| 380 | if (defined('PUBLISHPRESS_VERSION') && version_compare(constant('PUBLISHPRESS_VERSION'), '3.2.0', '<=') && defined('PP_CAPABILITIES_FIX_ADMIN_ICON')):?> |
| 381 | <style type="text/css"> |
| 382 | #toplevel_page_pp-capabilities-dashboard .dashicons-before::before, #toplevel_page_pp-capabilities-dashboard .wp-has-current-submenu .dashicons-before::before { |
| 383 | background-image: inherit !important; |
| 384 | content: "\f112" !important; |
| 385 | } |
| 386 | </style> |
| 387 | <?php endif; |
| 388 | } |
| 389 | |
| 390 | /** |
| 391 | * Returns a list of roles with name and display name to populate a select field. |
| 392 | * |
| 393 | * @param int $userId |
| 394 | * |
| 395 | * @return array |
| 396 | */ |
| 397 | protected function getUsersRoles($userId) |
| 398 | { |
| 399 | if (empty($userId)) { |
| 400 | return []; |
| 401 | } |
| 402 | |
| 403 | $user = get_user_by('id', $userId); |
| 404 | |
| 405 | if (empty($user)) { |
| 406 | return []; |
| 407 | } |
| 408 | |
| 409 | return array_values($user->roles); |
| 410 | } |
| 411 | |
| 412 | public function action_profile_update($userId, $oldUserData = []) |
| 413 | { |
| 414 | // Check if we need to update the user's roles, allowing to set multiple roles. |
| 415 | if ((!empty($_REQUEST['_wpnonce']) && wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'update-user_' . $userId) |
| 416 | || !empty($_REQUEST['_wpnonce_create-user']) && wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce_create-user']), 'create-user')) |
| 417 | && isset($_POST['pp_roles']) && current_user_can('promote_users')) { |
| 418 | // Remove the user's roles |
| 419 | $user = get_user_by('ID', $userId); |
| 420 | |
| 421 | $newRoles = array_map('sanitize_key', $_POST['pp_roles']); |
| 422 | $currentRoles = $user->roles; |
| 423 | |
| 424 | if (empty($newRoles) || !is_array($newRoles)) { |
| 425 | return; |
| 426 | } |
| 427 | |
| 428 | // Remove all roles |
| 429 | foreach ($currentRoles as $role) { |
| 430 | // Check if it is a bbPress rule. If so, don't remove it. |
| 431 | $isBBPressRole = preg_match('/^bbp_/', $role); |
| 432 | |
| 433 | if (!$isBBPressRole) { |
| 434 | $user->remove_role($role); |
| 435 | } |
| 436 | } |
| 437 | |
| 438 | // Add new roles in order |
| 439 | foreach ($newRoles as $role) { |
| 440 | $user->add_role($role); |
| 441 | } |
| 442 | } |
| 443 | } |
| 444 | |
| 445 | |
| 446 | // perf enhancement: display submenu links without loading framework and plugin code |
| 447 | function cmeSubmenus() { |
| 448 | global $capabilities_toplevel_page; |
| 449 | //we need to set primary menu capability to the first menu user has access to |
| 450 | $sub_menu_pages = pp_capabilities_sub_menu_lists(true); |
| 451 | $user_menu_caps = pp_capabilities_user_can_caps(); |
| 452 | $menu_cap = false; |
| 453 | $cap_callback = false; |
| 454 | $cap_page_slug = false; |
| 455 | $cap_title = __('Capabilities', 'capsman-enhanced'); |
| 456 | $cap_name = false; |
| 457 | if (is_multisite() && is_super_admin()) { |
| 458 | $cap_name = 'read'; |
| 459 | $cap_callback = [$this, 'dashboardPage']; |
| 460 | $cap_page_slug = 'pp-capabilities-dashboard'; |
| 461 | } elseif (count($user_menu_caps) > 0) { |
| 462 | $cap_name = $user_menu_caps[0]; |
| 463 | $cap_index = str_replace(['manage_capabilities_', 'manage_', '_'], ['', '', '-'], $cap_name); |
| 464 | if ($cap_index !== 'capabilities') { |
| 465 | $cap_title .= count($user_menu_caps) === 1 ? ' '. $sub_menu_pages[$cap_index]['title'] : ''; |
| 466 | } |
| 467 | $cap_page_slug = $sub_menu_pages[$cap_index]['page']; |
| 468 | $cap_callback = $sub_menu_pages[$cap_index]['callback']; |
| 469 | } |
| 470 | |
| 471 | $capabilities_toplevel_page = $cap_page_slug; |
| 472 | |
| 473 | if (!$cap_name) { |
| 474 | return; |
| 475 | } |
| 476 | |
| 477 | $menu_order = 72; |
| 478 | |
| 479 | if (defined('PUBLISHPRESS_PERMISSIONS_MENU_GROUPING')) { |
| 480 | foreach ((array)get_option('active_plugins') as $plugin_file) { |
| 481 | if ( false !== strpos($plugin_file, 'publishpress.php') ) { |
| 482 | $menu_order = 27; |
| 483 | } |
| 484 | } |
| 485 | } |
| 486 | |
| 487 | add_menu_page( |
| 488 | $cap_title, |
| 489 | $cap_title, |
| 490 | $cap_name, |
| 491 | $cap_page_slug, |
| 492 | $cap_callback, |
| 493 | 'dashicons-admin-network', |
| 494 | $menu_order |
| 495 | ); |
| 496 | |
| 497 | foreach ($sub_menu_pages as $feature => $subpage_option) { |
| 498 | if ($subpage_option['dashboard_control'] === false || pp_capabilities_feature_enabled($feature)) { |
| 499 | add_submenu_page($cap_page_slug, $subpage_option['title'], $subpage_option['title'], $subpage_option['capabilities'], $subpage_option['page'], $subpage_option['callback']); |
| 500 | } |
| 501 | } |
| 502 | |
| 503 | } |
| 504 | |
| 505 | |
| 506 | public function settingsUI() { |
| 507 | wp_enqueue_script('pp-capabilities-chosen-js', plugin_dir_url(CME_FILE) . 'common/libs/chosen-v1.8.7/chosen.jquery.js', ['jquery'], PUBLISHPRESS_CAPS_VERSION); |
| 508 | wp_enqueue_style('pp-capabilities-chosen-css', plugin_dir_url(CME_FILE) . 'common/libs/chosen-v1.8.7/chosen.css', false, PUBLISHPRESS_CAPS_VERSION); |
| 509 | require_once(dirname(__FILE__).'/settings-ui.php'); |
| 510 | new Capabilities_Settings_UI(); |
| 511 | } |
| 512 | |
| 513 | /** |
| 514 | * Clear the "done" flag on new plugin install |
| 515 | * (forcing another auto-refresh on next Profile Restrictions visit) |
| 516 | * |
| 517 | * @param string $plugin Path to the plugin file relative to the plugins directory. |
| 518 | * @param bool $network_wide Whether to enable the plugin for all sites in the network |
| 519 | * or just the current site. Multisite only. Default false. |
| 520 | * |
| 521 | * @return void |
| 522 | */ |
| 523 | public function clearProfileFeaturesDoneFlag($plugin, $network_wide) { |
| 524 | delete_option('capsman_profile_features_updated'); |
| 525 | } |
| 526 | |
| 527 | /** |
| 528 | * Block dasbboard access |
| 529 | * |
| 530 | * @return void |
| 531 | */ |
| 532 | public function blockDashboardAccess() { |
| 533 | |
| 534 | if (current_user_can('manage_options') || wp_doing_ajax()) { |
| 535 | return; |
| 536 | } |
| 537 | |
| 538 | $user = wp_get_current_user(); |
| 539 | if (isset($user->roles) && is_array($user->roles)) { |
| 540 | foreach ($user->roles as $user_role) { |
| 541 | //get role option |
| 542 | $role_option = get_option("pp_capabilities_{$user_role}_role_option", []); |
| 543 | if (is_array($role_option) && !empty($role_option) |
| 544 | && !empty($role_option['block_dashboard_access']) |
| 545 | && (int)$role_option['block_dashboard_access'] > 0 |
| 546 | ) { |
| 547 | wp_safe_redirect(home_url()); |
| 548 | die(); |
| 549 | } |
| 550 | } |
| 551 | } |
| 552 | } |
| 553 | |
| 554 | /** |
| 555 | * Ajax for saving a feature from dashboard page |
| 556 | * |
| 557 | * Copied from PublishPress Blocks |
| 558 | * |
| 559 | * @return boolean,void Return false if failure, echo json on success |
| 560 | */ |
| 561 | public function saveDashboardFeature() |
| 562 | { |
| 563 | if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities_dashboard')) { |
| 564 | wp_send_json( __('No permission!', 'capsman-enhanced'), 403 ); |
| 565 | return false; |
| 566 | } |
| 567 | |
| 568 | if ( |
| 569 | ! wp_verify_nonce( |
| 570 | sanitize_key( $_POST['nonce'] ), |
| 571 | 'pp-capabilities-dashboard-nonce' |
| 572 | ) |
| 573 | ) { |
| 574 | wp_send_json( __('Invalid nonce token!', 'capsman-enhanced'), 400 ); |
| 575 | } |
| 576 | |
| 577 | if( empty( $_POST['feature'] ) || ! $_POST['feature'] ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 578 | wp_send_json( __('Error: wrong data', 'capsman-enhanced'), 400 ); |
| 579 | return false; |
| 580 | } |
| 581 | |
| 582 | $capsman_dashboard_features_status = !empty(get_option('capsman_dashboard_features_status')) ? (array)get_option('capsman_dashboard_features_status') : []; |
| 583 | |
| 584 | |
| 585 | $feature = sanitize_text_field( $_POST['feature'] ); |
| 586 | |
| 587 | $capsman_dashboard_features_status[$feature]['status'] = (bool) $_POST['new_state'] ? 'on' : 'off'; |
| 588 | update_option('capsman_dashboard_features_status', $capsman_dashboard_features_status, false); |
| 589 | |
| 590 | wp_send_json( true, 200 ); |
| 591 | } |
| 592 | |
| 593 | /** |
| 594 | * Manages the installation detecting if this is the first time this plugin runs or is an upgrade. |
| 595 | * If no version is stored in the options, we treat as a new installation. Otherwise, we check the |
| 596 | * last version. If different, it is an upgrade or downgrade. |
| 597 | */ |
| 598 | public function manage_installation() |
| 599 | { |
| 600 | $option_name = 'PUBLISHPRESS_CAPS_VERSION'; |
| 601 | |
| 602 | $previous_version = get_option($option_name); |
| 603 | $current_version = PUBLISHPRESS_CAPS_VERSION; |
| 604 | |
| 605 | if (!apply_filters('pp_capabilities_skip_installation', false, $previous_version, $current_version)) { |
| 606 | if (empty($previous_version)) { |
| 607 | /** |
| 608 | * Action called when the plugin is installed. |
| 609 | * |
| 610 | * @param string $current_version |
| 611 | */ |
| 612 | do_action('pp_capabilities_install', $current_version); |
| 613 | } elseif (version_compare($previous_version, $current_version, '>')) { |
| 614 | /** |
| 615 | * Action called when the plugin is downgraded. |
| 616 | * |
| 617 | * @param string $previous_version |
| 618 | */ |
| 619 | do_action('pp_capabilities_downgrade', $previous_version); |
| 620 | } elseif (version_compare($previous_version, $current_version, '<')) { |
| 621 | /** |
| 622 | * Action called when the plugin is upgraded. |
| 623 | * |
| 624 | * @param string $previous_version |
| 625 | */ |
| 626 | do_action('pp_capabilities_upgrade', $previous_version); |
| 627 | } |
| 628 | } |
| 629 | |
| 630 | if ($current_version !== $previous_version) { |
| 631 | update_option($option_name, $current_version, true); |
| 632 | } |
| 633 | } |
| 634 | } |
| 635 |