admin-notices
2 months ago
features
2 weeks ago
plugin-capabilities
2 months ago
redirects
2 months ago
roles
1 month ago
admin-load.php
1 month ago
admin.php
2 weeks ago
application-passwords.php
2 weeks ago
backup-handler.php
2 weeks ago
backup.php
1 month ago
cap-helper.php
6 months ago
dashboard.php
2 months ago
extractor-capabilities.php
6 months ago
filters-admin.php
6 months ago
filters-woocommerce.php
6 months ago
filters-wp_rest_workarounds.php
6 months ago
filters.php
5 months ago
functions-admin.php
2 weeks ago
functions.php
2 weeks ago
handler.php
2 weeks ago
inflect-cme.php
6 months ago
manager.php
2 weeks ago
network.php
6 months ago
plugin-capabilities.php
2 months ago
pp-handler.php
6 months ago
pp-ui.php
3 months ago
publishpress-roles.php
6 months ago
settings-handler.php
6 months ago
settings-ui.php
2 weeks ago
settings.php
6 months ago
test-user-ui.php
1 month ago
test-user.php
5 months ago
admin-load.php
878 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 | // Redirect on plugin activation |
| 30 | add_action('admin_init', [$this, 'redirect_on_activate'], 2000); |
| 31 | |
| 32 | add_action('admin_init', [$this, 'featureRestrictionsClassic'], PHP_INT_MAX - 1); |
| 33 | add_action('wp_ajax_save_dashboard_feature_by_ajax', [$this, 'saveDashboardFeature']); |
| 34 | |
| 35 | // Admin feature settings update ajax callback |
| 36 | add_action('wp_ajax_ppc_update_admin_feature_settings', [$this, 'ajaxUpdateAdminFeatureSettings']); |
| 37 | |
| 38 | // Installation hooks |
| 39 | add_action( |
| 40 | 'pp_capabilities_install', |
| 41 | ['PublishPress\\Capabilities\\Classes\\PP_Capabilities_Installer', 'runInstallTasks'] |
| 42 | ); |
| 43 | add_action( |
| 44 | 'pp_capabilities_upgrade', |
| 45 | ['PublishPress\\Capabilities\\Classes\\PP_Capabilities_Installer', 'runUpgradeTasks'] |
| 46 | ); |
| 47 | add_action('admin_init', [$this, 'manage_installation'], 2000); |
| 48 | |
| 49 | //Add role blocked nav menu indication |
| 50 | add_action('wp_nav_menu_item_custom_fields', [$this, 'add_nav_menu_indicator'], 20, 5); |
| 51 | } |
| 52 | |
| 53 | add_filter('cme_publishpress_capabilities_capabilities', 'cme_publishpress_capabilities_capabilities'); |
| 54 | |
| 55 | add_action('admin_enqueue_scripts', [$this, 'adminScripts'], 100); |
| 56 | add_action('admin_print_scripts', [$this, 'adminPrintScripts']); |
| 57 | |
| 58 | add_action('profile_update', [$this, 'action_profile_update'], 10, 2); |
| 59 | |
| 60 | if (is_multisite()) { |
| 61 | add_action('add_user_to_blog', [$this, 'action_profile_update'], 9); |
| 62 | } else { |
| 63 | add_action('user_register', [$this, 'action_profile_update'], 9); |
| 64 | } |
| 65 | add_action('init', [$this, 'register_textdomain']); |
| 66 | |
| 67 | 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', 'pp-capabilities-frontend-features', 'pp-capabilities-redirects', 'pp-capabilities-admin-styles', 'pp-capabilities-admin-notices'])) |
| 68 | |
| 69 | || (!empty($_REQUEST['action']) && in_array($_REQUEST['action'], ['pp-roles-add-role', 'pp-roles-delete-role', 'pp-roles-hide-role', 'pp-roles-unhide-role'])) |
| 70 | || ( ! empty($_SERVER['SCRIPT_NAME']) && strpos(sanitize_text_field($_SERVER['SCRIPT_NAME']), 'p-admin/plugins.php' ) && ! empty($_REQUEST['action'] ) ) |
| 71 | || ( isset($_GET['action']) && ('reset-defaults' == $_GET['action']) && isset($_REQUEST['_wpnonce']) && wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'capsman-reset-defaults') ) |
| 72 | || in_array( $pagenow, array( 'users.php', 'user-edit.php', 'profile.php', 'user-new.php' ) ) |
| 73 | ) ) { |
| 74 | global $capsman; |
| 75 | |
| 76 | // Run the plugin |
| 77 | require_once ( dirname(CME_FILE) . '/framework/lib/formating.php' ); |
| 78 | require_once ( dirname(CME_FILE) . '/framework/lib/users.php' ); |
| 79 | |
| 80 | require_once ( dirname(CME_FILE) . '/includes/manager.php' ); |
| 81 | $capsman = new CapabilityManager(); |
| 82 | } else { |
| 83 | add_action( 'admin_menu', [$this, 'cmeSubmenus'], 18 ); |
| 84 | } |
| 85 | |
| 86 | add_action('init', function() { // late execution avoids clash with autoloaders in other plugins |
| 87 | global $pagenow; |
| 88 | |
| 89 | 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', 'pp-capabilities-redirects', 'pp-capabilities-admin-styles', 'pp-capabilities-admin-notices'])) // @todo: CSS for button alignment in Editor Features, Admin Features |
| 90 | || (defined('DOING_AJAX') && DOING_AJAX && !empty($_REQUEST['action']) && (false !== strpos(sanitize_key($_REQUEST['action']), 'capability-manager-enhanced'))) |
| 91 | ) { |
| 92 | if (!class_exists('\PublishPress\WordPressReviews\ReviewsController')) { |
| 93 | include_once PUBLISHPRESS_CAPS_ABSPATH . '/lib/vendor/publishpress/wordpress-reviews/ReviewsController.php'; |
| 94 | } |
| 95 | |
| 96 | if (class_exists('\PublishPress\WordPressReviews\ReviewsController')) { |
| 97 | $reviews = new \PublishPress\WordPressReviews\ReviewsController( |
| 98 | 'capability-manager-enhanced', |
| 99 | 'PublishPress Capabilities', |
| 100 | plugin_dir_url(CME_FILE) . 'common/img/capabilities-wp-logo.png' |
| 101 | ); |
| 102 | |
| 103 | add_filter('publishpress_wp_reviews_display_banner_capability-manager-enhanced', [$this, 'shouldDisplayBanner']); |
| 104 | |
| 105 | $reviews->init(); |
| 106 | } |
| 107 | } |
| 108 | }); |
| 109 | |
| 110 | |
| 111 | add_filter('pp_capabilities_feature_post_types', [$this, 'fltEditorFeaturesPostTypes'], 5); |
| 112 | add_filter('block_editor_settings_all', [$this, 'filterCodeEditingStatus'], 999); |
| 113 | add_filter('classic_editor_enabled_editors_for_post_type', [$this, 'filterRolePostTypeEditor'], 10, 2); |
| 114 | add_filter('classic_editor_plugin_settings', [$this, 'filterRoleEditorSettings']); |
| 115 | |
| 116 | //profile features integration |
| 117 | require_once (dirname(CME_FILE) . '/includes/features/restrict-profile-features.php'); |
| 118 | \PublishPress\Capabilities\PP_Capabilities_Profile_Features::instance(); |
| 119 | |
| 120 | //frontend features post metabox |
| 121 | require_once (dirname(__FILE__) . '/features/frontend-features/frontend-features-metaboxes.php'); |
| 122 | \PublishPress\Capabilities\PP_Capabilities_Frontend_Features_Metaboxes::instance(); |
| 123 | |
| 124 | //capabilities settings |
| 125 | add_action('pp-capabilities-settings-ui', [$this, 'settingsUI']); |
| 126 | |
| 127 | //clear the "done" flag on new plugin install |
| 128 | add_action('activated_plugin', [$this, 'clearProfileFeaturesDoneFlag'], 10, 2); |
| 129 | //prevent access to admin dashboard |
| 130 | add_action('admin_init', [$this, 'blockDashboardAccess']); |
| 131 | // Add plugin list action links |
| 132 | add_filter('plugin_action_links', [$this, 'addPluginActionLinks'], 10, 2); |
| 133 | add_filter('plugin_row_meta', [$this, 'addPluginRowMetaLinks'], 10, 2); |
| 134 | add_filter('all_plugins', [$this, 'filterPluginsListName']); |
| 135 | } |
| 136 | |
| 137 | function register_textdomain() { |
| 138 | |
| 139 | $domain = 'capability-manager-enhanced'; |
| 140 | $mofile_custom = sprintf('%s-%s.mo', $domain, get_user_locale()); |
| 141 | $locations = [ |
| 142 | trailingslashit( WP_LANG_DIR . '/plugins/'), |
| 143 | trailingslashit( WP_LANG_DIR . '/' . $domain ), |
| 144 | trailingslashit( WP_LANG_DIR . '/loco/plugins/'), |
| 145 | trailingslashit( WP_LANG_DIR ), |
| 146 | trailingslashit( plugin_dir_path(CME_FILE) . 'languages' ), |
| 147 | ]; |
| 148 | // Try custom locations in WP_LANG_DIR. |
| 149 | foreach ($locations as $location) { |
| 150 | if (load_textdomain($domain, $location . $mofile_custom)) { |
| 151 | return true; |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | } |
| 156 | |
| 157 | /** |
| 158 | * Filters the editors that are enabled for the post type. |
| 159 | * |
| 160 | * @param array $editors Associative array of the editors and whether they are enabled for the post type. |
| 161 | * @param string $post_type The post type. |
| 162 | */ |
| 163 | public function filterRolePostTypeEditor($editors, $post_type) { |
| 164 | $user = wp_get_current_user(); |
| 165 | |
| 166 | if (is_object($user) && isset($user->roles)) { |
| 167 | $current_user_editors = []; |
| 168 | foreach ($user->roles as $user_role) { |
| 169 | //get role option |
| 170 | $role_option = get_option("pp_capabilities_{$user_role}_role_option", []); |
| 171 | if (is_array($role_option) && !empty($role_option) && !empty($role_option['role_editor'])) { |
| 172 | $current_user_editors = array_merge($current_user_editors, $role_option['role_editor']); |
| 173 | } |
| 174 | } |
| 175 | |
| 176 | if (!empty($current_user_editors)) { |
| 177 | $current_user_editors = array_unique($current_user_editors); |
| 178 | $editors = array( |
| 179 | 'classic_editor' => in_array('classic_editor', $current_user_editors) ? true : false, |
| 180 | 'block_editor' => in_array('block_editor', $current_user_editors) ? true : false, |
| 181 | ); |
| 182 | } |
| 183 | } |
| 184 | |
| 185 | return $editors; |
| 186 | } |
| 187 | |
| 188 | /** |
| 189 | * Override the classic editor plugin's settings. |
| 190 | * |
| 191 | * @param bool $settings |
| 192 | * @return mixed |
| 193 | */ |
| 194 | public function filterRoleEditorSettings($settings) { |
| 195 | $user = wp_get_current_user(); |
| 196 | |
| 197 | if (is_object($user) && isset($user->roles)) { |
| 198 | $current_user_editors = []; |
| 199 | foreach ($user->roles as $user_role) { |
| 200 | //get role option |
| 201 | $role_option = get_option("pp_capabilities_{$user_role}_role_option", []); |
| 202 | if (is_array($role_option) && !empty($role_option) && !empty($role_option['role_editor'])) { |
| 203 | $current_user_editors = array_merge($current_user_editors, $role_option['role_editor']); |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | if (!empty($current_user_editors)) { |
| 208 | $current_user_editors = array_unique($current_user_editors); |
| 209 | $settings = []; |
| 210 | $settings['editor'] = ($current_user_editors[0] === 'classic_editor') ? 'classic' : 'block'; |
| 211 | $settings['allow-users'] = count($current_user_editors) > 1 ? true : false; |
| 212 | } |
| 213 | } |
| 214 | |
| 215 | return $settings; |
| 216 | } |
| 217 | |
| 218 | public function filterCodeEditingStatus($settings) { |
| 219 | $user = wp_get_current_user(); |
| 220 | |
| 221 | if (is_object($user) && isset($user->roles)) { |
| 222 | foreach ($user->roles as $user_role) { |
| 223 | //get role option |
| 224 | $role_option = get_option("pp_capabilities_{$user_role}_role_option", []); |
| 225 | if (is_array($role_option) && !empty($role_option) && !empty($role_option['disable_code_editor']) && (int)$role_option['disable_code_editor'] > 0) { |
| 226 | $settings['codeEditingEnabled'] = false; |
| 227 | break; |
| 228 | } |
| 229 | } |
| 230 | } |
| 231 | |
| 232 | return $settings; |
| 233 | } |
| 234 | |
| 235 | public function fltEditorFeaturesPostTypes($def_post_types) { |
| 236 | if((int)get_option('cme_editor_features_private_post_type') > 0 || defined('PP_CAPABILITIES_PRIVATE_TYPES')){ |
| 237 | $private_cpt = get_post_types(['public' => true, 'show_ui' => true], 'names', 'or'); |
| 238 | $public_cpt = get_post_types(['public' => true, 'show_ui' => true], 'names', 'or'); |
| 239 | $def_post_types = array_unique(array_merge($def_post_types, $private_cpt, $public_cpt)); |
| 240 | }else{ |
| 241 | $def_post_types = array_merge($def_post_types, get_post_types(['public' => true], 'names')); |
| 242 | } |
| 243 | |
| 244 | unset($def_post_types['attachment']); |
| 245 | |
| 246 | return $def_post_types; |
| 247 | } |
| 248 | |
| 249 | public function shouldDisplayBanner() { |
| 250 | global $pagenow; |
| 251 | |
| 252 | 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', 'pp-capabilities-redirects', 'pp-capabilities-admin-styles', 'pp-capabilities-admin-notices']); |
| 253 | } |
| 254 | |
| 255 | private function applyFeatureRestrictions($editor = 'gutenberg') { |
| 256 | global $pagenow; |
| 257 | |
| 258 | if (is_multisite() && is_super_admin() && !defined('PP_CAPABILITIES_RESTRICT_SUPER_ADMIN')) { |
| 259 | return; |
| 260 | } |
| 261 | |
| 262 | if (!pp_capabilities_feature_enabled('editor-features')) { |
| 263 | return; |
| 264 | } |
| 265 | |
| 266 | // Return if not a post editor request |
| 267 | if (!in_array($pagenow, ['post.php', 'post-new.php'])) { |
| 268 | return; |
| 269 | } |
| 270 | |
| 271 | static $def_post_types; // avoid redundant filter application |
| 272 | |
| 273 | if (!isset($def_post_types)) { |
| 274 | $def_post_types = array_unique(apply_filters('pp_capabilities_feature_post_types', ['post', 'page'])); |
| 275 | } |
| 276 | |
| 277 | $post_type = pp_capabilities_get_post_type(); |
| 278 | |
| 279 | // Return if not a supported post type |
| 280 | if (in_array($post_type, apply_filters('pp_capabilities_unsupported_post_types', ['attachment']))) { |
| 281 | return; |
| 282 | } |
| 283 | |
| 284 | switch ($editor) { |
| 285 | case 'gutenberg': |
| 286 | if (_pp_capabilities_is_block_editor_active()) { |
| 287 | require_once ( dirname(CME_FILE) . '/includes/features/restrict-editor-features.php' ); |
| 288 | PP_Capabilities_Post_Features::applyRestrictions($post_type); |
| 289 | } |
| 290 | |
| 291 | break; |
| 292 | |
| 293 | case 'classic': |
| 294 | if (!_pp_capabilities_is_block_editor_active()) { |
| 295 | require_once ( dirname(CME_FILE) . '/includes/features/restrict-editor-features.php' ); |
| 296 | PP_Capabilities_Post_Features::adminInitClassic($post_type); |
| 297 | } |
| 298 | } |
| 299 | } |
| 300 | |
| 301 | function featureRestrictionsGutenberg() { |
| 302 | $this->applyFeatureRestrictions(); |
| 303 | } |
| 304 | |
| 305 | function featureRestrictionsClassic() { |
| 306 | $this->applyFeatureRestrictions('classic'); |
| 307 | } |
| 308 | |
| 309 | function adminScripts() { |
| 310 | global $publishpress; |
| 311 | |
| 312 | // Include global style and script |
| 313 | wp_enqueue_style('cme-admin-global-css', plugin_dir_url(CME_FILE) . 'common/css/global.css', [], PUBLISHPRESS_CAPS_VERSION); |
| 314 | wp_enqueue_script('cme-admin-global-js', plugin_dir_url(CME_FILE) . 'common/js/global.js', ['jquery'], PUBLISHPRESS_CAPS_VERSION); |
| 315 | wp_localize_script( |
| 316 | 'cme-admin-global-js', |
| 317 | 'ppCapabilitiesGlobalData', |
| 318 | [ |
| 319 | 'nonce' => wp_create_nonce('ppc-test-user-admin-bar-action') |
| 320 | ] |
| 321 | ); |
| 322 | |
| 323 | if (function_exists('get_current_screen') && (!defined('PUBLISHPRESS_VERSION') || empty($publishpress) || empty($publishpress->modules) || empty($publishpress->modules->roles))) { |
| 324 | $screen = get_current_screen(); |
| 325 | |
| 326 | if ('user-edit' === $screen->base || 'profile' === $screen->base || ('user' === $screen->base && 'add' === $screen->action)) { |
| 327 | |
| 328 | $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; |
| 329 | |
| 330 | // Check if we are on the user's profile page |
| 331 | wp_enqueue_script( |
| 332 | 'pp-capabilities-chosen-js', |
| 333 | plugin_dir_url(CME_FILE) . 'common/libs/chosen-v1.8.7/chosen.jquery.js', |
| 334 | ['jquery'], |
| 335 | PUBLISHPRESS_CAPS_VERSION |
| 336 | ); |
| 337 | |
| 338 | // Enqueue jQuery UI script from WordPress core |
| 339 | wp_enqueue_script('jquery-ui-core'); |
| 340 | |
| 341 | wp_enqueue_script( |
| 342 | 'pp-capabilities-roles-profile-js', |
| 343 | plugin_dir_url(CME_FILE) . 'common/js/profile.js', |
| 344 | ['jquery', 'pp-capabilities-chosen-js'], |
| 345 | PUBLISHPRESS_CAPS_VERSION |
| 346 | ); |
| 347 | |
| 348 | wp_enqueue_style( |
| 349 | 'pp-capabilities-chosen-css', |
| 350 | plugin_dir_url(CME_FILE) . 'common/libs/chosen-v1.8.7/chosen.css', |
| 351 | false, |
| 352 | PUBLISHPRESS_CAPS_VERSION |
| 353 | ); |
| 354 | wp_enqueue_style( |
| 355 | 'pp-capabilities-roles-profile-css', |
| 356 | plugin_dir_url(CME_FILE) . 'common/css/profile.css', |
| 357 | ['pp-capabilities-chosen-css'], |
| 358 | PUBLISHPRESS_CAPS_VERSION |
| 359 | ); |
| 360 | |
| 361 | $roles = !empty($_GET['user_id']) ? $this->getUsersRoles((int) $_GET['user_id']) : []; |
| 362 | |
| 363 | if (empty($roles)) { |
| 364 | $roles = (array) get_option('default_role'); |
| 365 | } |
| 366 | |
| 367 | wp_localize_script( |
| 368 | 'pp-capabilities-roles-profile-js', |
| 369 | 'ppCapabilitiesProfileData', |
| 370 | [ |
| 371 | 'role_description' => esc_html__('Drag multiple roles selection to change roles order.', 'capability-manager-enhanced'), |
| 372 | 'selected_roles' => $roles, |
| 373 | 'multi_roles' => $multi_role ? 1 : 0, |
| 374 | 'profile_page_title' => esc_html__('Page title', 'capability-manager-enhanced'), |
| 375 | 'rankmath_title' => esc_html__('Rank Math SEO', 'capability-manager-enhanced'), |
| 376 | 'nonce' => wp_create_nonce('ppc-profile-edit-action') |
| 377 | ] |
| 378 | ); |
| 379 | } |
| 380 | |
| 381 | } |
| 382 | } |
| 383 | |
| 384 | function adminPrintScripts() { |
| 385 | |
| 386 | global $capabilities_toplevel_page; |
| 387 | |
| 388 | if (!empty($capabilities_toplevel_page) && pp_capabilities_feature_enabled('capabilities') && current_user_can('manage_capabilities')) { |
| 389 | /** |
| 390 | * Update capabilities top level slug from dashboard/toplevel page to capabilities |
| 391 | */ |
| 392 | $menu_inline_script = " |
| 393 | jQuery(document).ready( function($) { |
| 394 | if (jQuery('li#toplevel_page_{$capabilities_toplevel_page} a.toplevel_page_{$capabilities_toplevel_page}').length > 0) { |
| 395 | var toplevel_page = jQuery('li#toplevel_page_{$capabilities_toplevel_page} a.toplevel_page_{$capabilities_toplevel_page}'); |
| 396 | var toplevel_page_link = toplevel_page.attr('href'); |
| 397 | if (toplevel_page_link) { |
| 398 | toplevel_page.attr('href', toplevel_page_link.replace('{$capabilities_toplevel_page}', 'pp-capabilities')); |
| 399 | } |
| 400 | } |
| 401 | });"; |
| 402 | ppc_add_inline_script($menu_inline_script); |
| 403 | } |
| 404 | |
| 405 | // Counteract overzealous menu icon styling in PublishPress <= 3.2.0 :) |
| 406 | if (defined('PUBLISHPRESS_VERSION') && version_compare(constant('PUBLISHPRESS_VERSION'), '3.2.0', '<=') && defined('PP_CAPABILITIES_FIX_ADMIN_ICON')):?> |
| 407 | <style type="text/css"> |
| 408 | #toplevel_page_pp-capabilities-dashboard .dashicons-before::before, #toplevel_page_pp-capabilities-dashboard .wp-has-current-submenu .dashicons-before::before { |
| 409 | background-image: inherit !important; |
| 410 | content: "\f112" !important; |
| 411 | } |
| 412 | </style> |
| 413 | <?php endif; |
| 414 | } |
| 415 | |
| 416 | /** |
| 417 | * Returns a list of roles with name and display name to populate a select field. |
| 418 | * |
| 419 | * @param int $userId |
| 420 | * |
| 421 | * @return array |
| 422 | */ |
| 423 | protected function getUsersRoles($userId) |
| 424 | { |
| 425 | if (empty($userId)) { |
| 426 | return []; |
| 427 | } |
| 428 | |
| 429 | $user = get_user_by('id', $userId); |
| 430 | |
| 431 | if (empty($user)) { |
| 432 | return []; |
| 433 | } |
| 434 | |
| 435 | return array_values($user->roles); |
| 436 | } |
| 437 | |
| 438 | public function action_profile_update($userId, $oldUserData = []) |
| 439 | { |
| 440 | // Check if we need to update the user's roles, allowing to set multiple roles. |
| 441 | if ((!empty($_REQUEST['_wpnonce']) && wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce']), 'update-user_' . $userId) |
| 442 | || !empty($_REQUEST['_wpnonce_create-user']) && wp_verify_nonce(sanitize_key($_REQUEST['_wpnonce_create-user']), 'create-user')) |
| 443 | && isset($_POST['pp_roles']) && current_user_can('promote_users')) { |
| 444 | if (!current_user_can('edit_user', $userId) || !current_user_can('promote_user', $userId)) { |
| 445 | return; |
| 446 | } |
| 447 | |
| 448 | $user = get_user_by('ID', $userId); |
| 449 | if (empty($user)) { |
| 450 | return; |
| 451 | } |
| 452 | |
| 453 | $newRoles = array_unique( |
| 454 | array_filter( |
| 455 | array_map('sanitize_key', (array) $_POST['pp_roles']) |
| 456 | ) |
| 457 | ); |
| 458 | $currentRoles = $user->roles; |
| 459 | |
| 460 | if (empty($newRoles) || !is_array($newRoles)) { |
| 461 | return; |
| 462 | } |
| 463 | |
| 464 | $editableRoles = function_exists('get_editable_roles') |
| 465 | ? array_keys(get_editable_roles()) |
| 466 | : array_keys(apply_filters('editable_roles', wp_roles()->roles)); |
| 467 | |
| 468 | // Reject the request if any submitted role is not editable by current user. |
| 469 | if (array_diff($newRoles, $editableRoles)) { |
| 470 | return; |
| 471 | } |
| 472 | |
| 473 | // Remove all roles |
| 474 | foreach ($currentRoles as $role) { |
| 475 | // Check if it is a bbPress rule. If so, don't remove it. |
| 476 | $isBBPressRole = preg_match('/^bbp_/', $role); |
| 477 | |
| 478 | if (!$isBBPressRole) { |
| 479 | $user->remove_role($role); |
| 480 | } |
| 481 | } |
| 482 | |
| 483 | // Add new roles in order |
| 484 | foreach ($newRoles as $role) { |
| 485 | $user->add_role($role); |
| 486 | } |
| 487 | } |
| 488 | } |
| 489 | |
| 490 | |
| 491 | // perf enhancement: display submenu links without loading framework and plugin code |
| 492 | function cmeSubmenus() { |
| 493 | global $capabilities_toplevel_page, $current_user; |
| 494 | |
| 495 | //make sure admin doesn't lose access to capabilities screen |
| 496 | if (!current_user_can('manage_capabilities') && current_user_can('administrator')) { |
| 497 | $pp_capabilities = apply_filters('cme_publishpress_capabilities_capabilities', []); |
| 498 | $role = get_role('administrator'); |
| 499 | foreach ($pp_capabilities as $cap) { |
| 500 | if (!$role->has_cap($cap)) { |
| 501 | $role->add_cap($cap); |
| 502 | $current_user->allcaps[$cap] = true; |
| 503 | } |
| 504 | } |
| 505 | } |
| 506 | |
| 507 | //we need to set primary menu capability to the first menu user has access to |
| 508 | $sub_menu_pages = pp_capabilities_sub_menu_lists(true); |
| 509 | $user_menu_caps = pp_capabilities_user_can_caps(); |
| 510 | $menu_cap = false; |
| 511 | $cap_callback = false; |
| 512 | $cap_page_slug = false; |
| 513 | $cap_title = __('Capabilities', 'capability-manager-enhanced'); |
| 514 | $cap_name = false; |
| 515 | |
| 516 | //remove caps that doesn't have menu |
| 517 | if (in_array('manage_capabilities_user_testing', $user_menu_caps)) { |
| 518 | $cap_key = array_search('manage_capabilities_user_testing', $user_menu_caps); |
| 519 | if ($cap_key !== false) { |
| 520 | unset($user_menu_caps[$cap_key]); |
| 521 | $user_menu_caps = array_filter($user_menu_caps); |
| 522 | } |
| 523 | } |
| 524 | |
| 525 | if (is_multisite() && is_super_admin()) { |
| 526 | $cap_name = 'read'; |
| 527 | $cap_callback = [$this, 'dashboardPage']; |
| 528 | $cap_page_slug = 'pp-capabilities-dashboard'; |
| 529 | } elseif (count($user_menu_caps) > 0) { |
| 530 | $cap_name = $user_menu_caps[0]; |
| 531 | $cap_index = str_replace(['manage_capabilities_', 'manage_', '_'], ['', '', '-'], $cap_name); |
| 532 | if (($cap_index !== 'capabilities') && (count($user_menu_caps) === 1)) { |
| 533 | $cap_title = $sub_menu_pages[$cap_index]['title']; |
| 534 | } |
| 535 | $cap_page_slug = $sub_menu_pages[$cap_index]['page']; |
| 536 | $cap_callback = $sub_menu_pages[$cap_index]['callback']; |
| 537 | } |
| 538 | |
| 539 | $capabilities_toplevel_page = $cap_page_slug; |
| 540 | |
| 541 | if (!$cap_name) { |
| 542 | return; |
| 543 | } |
| 544 | |
| 545 | $menu_order = 72; |
| 546 | |
| 547 | if (defined('PUBLISHPRESS_PERMISSIONS_MENU_GROUPING')) { |
| 548 | foreach ((array)get_option('active_plugins') as $plugin_file) { |
| 549 | if ( false !== strpos($plugin_file, 'publishpress.php') ) { |
| 550 | $menu_order = 27; |
| 551 | } |
| 552 | } |
| 553 | } |
| 554 | |
| 555 | add_menu_page( |
| 556 | $cap_title, |
| 557 | $cap_title, |
| 558 | $cap_name, |
| 559 | $cap_page_slug, |
| 560 | $cap_callback, |
| 561 | 'dashicons-admin-network', |
| 562 | $menu_order |
| 563 | ); |
| 564 | |
| 565 | foreach ($sub_menu_pages as $feature => $subpage_option) { |
| 566 | if ($subpage_option['dashboard_control'] === false || pp_capabilities_feature_enabled($feature)) { |
| 567 | add_submenu_page($cap_page_slug, $subpage_option['title'], $subpage_option['title'], $subpage_option['capabilities'], $subpage_option['page'], $subpage_option['callback']); |
| 568 | } |
| 569 | } |
| 570 | |
| 571 | } |
| 572 | |
| 573 | |
| 574 | public function settingsUI() { |
| 575 | 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); |
| 576 | wp_enqueue_style('pp-capabilities-chosen-css', plugin_dir_url(CME_FILE) . 'common/libs/chosen-v1.8.7/chosen.css', false, PUBLISHPRESS_CAPS_VERSION); |
| 577 | require_once(dirname(__FILE__).'/settings-ui.php'); |
| 578 | new Capabilities_Settings_UI(); |
| 579 | } |
| 580 | |
| 581 | /** |
| 582 | * Clear the "done" flag on new plugin install |
| 583 | * (forcing another auto-refresh on next Profile Restrictions visit) |
| 584 | * |
| 585 | * @param string $plugin Path to the plugin file relative to the plugins directory. |
| 586 | * @param bool $network_wide Whether to enable the plugin for all sites in the network |
| 587 | * or just the current site. Multisite only. Default false. |
| 588 | * |
| 589 | * @return void |
| 590 | */ |
| 591 | public function clearProfileFeaturesDoneFlag($plugin, $network_wide) { |
| 592 | delete_option('capsman_profile_features_updated'); |
| 593 | } |
| 594 | |
| 595 | /** |
| 596 | * Block dasbboard access |
| 597 | * |
| 598 | * @return void |
| 599 | */ |
| 600 | public function blockDashboardAccess() { |
| 601 | |
| 602 | if (current_user_can('manage_options') || wp_doing_ajax()) { |
| 603 | return; |
| 604 | } |
| 605 | |
| 606 | $user = wp_get_current_user(); |
| 607 | if (isset($user->roles) && is_array($user->roles)) { |
| 608 | foreach ($user->roles as $user_role) { |
| 609 | //get role option |
| 610 | $role_option = get_option("pp_capabilities_{$user_role}_role_option", []); |
| 611 | if (is_array($role_option) && !empty($role_option) |
| 612 | && !empty($role_option['block_dashboard_access']) |
| 613 | && (int)$role_option['block_dashboard_access'] > 0 |
| 614 | ) { |
| 615 | wp_safe_redirect(home_url()); |
| 616 | die(); |
| 617 | } |
| 618 | } |
| 619 | } |
| 620 | } |
| 621 | |
| 622 | /** |
| 623 | * Ajax for saving a feature from dashboard page |
| 624 | * |
| 625 | * Copied from PublishPress Blocks |
| 626 | * |
| 627 | * @return boolean,void Return false if failure, echo json on success |
| 628 | */ |
| 629 | public function saveDashboardFeature() |
| 630 | { |
| 631 | if ((!is_multisite() || !is_super_admin()) && !current_user_can('administrator') && !current_user_can('manage_capabilities_dashboard')) { |
| 632 | wp_send_json( __('No permission!', 'capability-manager-enhanced'), 403 ); |
| 633 | return false; |
| 634 | } |
| 635 | |
| 636 | if ( |
| 637 | ! wp_verify_nonce( |
| 638 | sanitize_key( $_POST['nonce'] ), |
| 639 | 'pp-capabilities-dashboard-nonce' |
| 640 | ) |
| 641 | ) { |
| 642 | wp_send_json( __('Invalid nonce token!', 'capability-manager-enhanced'), 400 ); |
| 643 | } |
| 644 | |
| 645 | if( empty( $_POST['feature'] ) || ! $_POST['feature'] ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized |
| 646 | wp_send_json( __('Error: wrong data', 'capability-manager-enhanced'), 400 ); |
| 647 | return false; |
| 648 | } |
| 649 | |
| 650 | $capsman_dashboard_features_status = !empty(get_option('capsman_dashboard_features_status')) ? (array)get_option('capsman_dashboard_features_status') : []; |
| 651 | |
| 652 | |
| 653 | $feature = sanitize_text_field( $_POST['feature'] ); |
| 654 | |
| 655 | $capsman_dashboard_features_status[$feature]['status'] = (bool) $_POST['new_state'] ? 'on' : 'off'; |
| 656 | update_option('capsman_dashboard_features_status', $capsman_dashboard_features_status, false); |
| 657 | do_action('pp_capabilities_dashboard_feature_updated', $feature, $capsman_dashboard_features_status[$feature]['status']); |
| 658 | |
| 659 | wp_send_json( true, 200 ); |
| 660 | } |
| 661 | |
| 662 | /** |
| 663 | * Ajax handler for updating admin feature settings |
| 664 | */ |
| 665 | public function ajaxUpdateAdminFeatureSettings() { |
| 666 | |
| 667 | $response['status'] = 'error'; |
| 668 | $response['message'] = __('An error occured!', 'capability-manager-enhanced'); |
| 669 | $response['content'] = ''; |
| 670 | |
| 671 | // Verify nonce and capabilities |
| 672 | if (empty($_POST['nonce']) || !wp_verify_nonce(sanitize_key($_POST['nonce']), 'pp-capabilities-admin-features')) { |
| 673 | $response['message'] = __('Security check failed', 'capability-manager-enhanced'); |
| 674 | } elseif (!current_user_can('manage_capabilities_admin_features')) { |
| 675 | $response['message'] = __('Permission denied', 'capability-manager-enhanced'); |
| 676 | } else { |
| 677 | $hide_submenu = !empty($_POST['hide_submenu']) ? (int)($_POST['hide_submenu']) : 0; |
| 678 | |
| 679 | $admin_feature_settings = (array) get_option('ppc_admin_features_settings', []); |
| 680 | $admin_feature_settings['hide_submenu'] = $hide_submenu; |
| 681 | |
| 682 | update_option('ppc_admin_features_settings', $admin_feature_settings); |
| 683 | |
| 684 | $response['status'] = 'success'; |
| 685 | $response['message'] = __('Settings updated successfully.', 'capability-manager-enhanced'); |
| 686 | } |
| 687 | |
| 688 | wp_send_json($response); |
| 689 | } |
| 690 | |
| 691 | /** |
| 692 | * Manages the installation detecting if this is the first time this plugin runs or is an upgrade. |
| 693 | * If no version is stored in the options, we treat as a new installation. Otherwise, we check the |
| 694 | * last version. If different, it is an upgrade or downgrade. |
| 695 | */ |
| 696 | public function manage_installation() |
| 697 | { |
| 698 | $option_name = 'PUBLISHPRESS_CAPS_VERSION'; |
| 699 | |
| 700 | $previous_version = get_option($option_name); |
| 701 | $current_version = PUBLISHPRESS_CAPS_VERSION; |
| 702 | |
| 703 | if (!apply_filters('pp_capabilities_skip_installation', false, $previous_version, $current_version)) { |
| 704 | if (empty($previous_version)) { |
| 705 | /** |
| 706 | * Action called when the plugin is installed. |
| 707 | * |
| 708 | * @param string $current_version |
| 709 | */ |
| 710 | do_action('pp_capabilities_install', $current_version); |
| 711 | } elseif (version_compare($previous_version, $current_version, '>')) { |
| 712 | /** |
| 713 | * Action called when the plugin is downgraded. |
| 714 | * |
| 715 | * @param string $previous_version |
| 716 | */ |
| 717 | do_action('pp_capabilities_downgrade', $previous_version); |
| 718 | } elseif (version_compare($previous_version, $current_version, '<')) { |
| 719 | /** |
| 720 | * Action called when the plugin is upgraded. |
| 721 | * |
| 722 | * @param string $previous_version |
| 723 | */ |
| 724 | do_action('pp_capabilities_upgrade', $previous_version); |
| 725 | } |
| 726 | } |
| 727 | |
| 728 | if ($current_version !== $previous_version) { |
| 729 | update_option($option_name, $current_version, true); |
| 730 | } |
| 731 | } |
| 732 | |
| 733 | |
| 734 | /** |
| 735 | * Fires just before the move buttons of a nav menu item in the menu editor. |
| 736 | * Add role blocked nav menu indication |
| 737 | * |
| 738 | * @param int $item_id Menu item ID. |
| 739 | * @param \WP_Post $item Menu item data object. |
| 740 | * @param int $depth Depth of menu item. Used for padding. |
| 741 | * @param \stdClass $args An object of menu item arguments. |
| 742 | * @param int $id Nav menu ID. |
| 743 | */ |
| 744 | public function add_nav_menu_indicator( $item_id, $item, $depth, $args, $id = null ) { |
| 745 | global $capsman; |
| 746 | |
| 747 | if (!is_admin() || !pp_capabilities_feature_enabled('nav-menus')) { |
| 748 | return; |
| 749 | } |
| 750 | |
| 751 | $nav_menu_item_option = !empty(get_option('capsman_nav_item_menus')) ? (array)get_option('capsman_nav_item_menus') : []; |
| 752 | if (!is_array($nav_menu_item_option)) { |
| 753 | return; |
| 754 | } |
| 755 | $nav_menu_item_option = array_filter($nav_menu_item_option); |
| 756 | |
| 757 | if (empty($nav_menu_item_option)) { |
| 758 | return; |
| 759 | } |
| 760 | |
| 761 | $searchPrefix = $item_id . '_'; |
| 762 | |
| 763 | $restricted_roles = array_filter( |
| 764 | array_map( |
| 765 | function ($subArray) use ($searchPrefix) { |
| 766 | return array_filter( |
| 767 | $subArray, |
| 768 | function ($value) use ($searchPrefix) { |
| 769 | return strpos($value, $searchPrefix) === 0; |
| 770 | } |
| 771 | ); |
| 772 | }, |
| 773 | $nav_menu_item_option |
| 774 | ) |
| 775 | ); |
| 776 | |
| 777 | if (empty($restricted_roles)) { |
| 778 | return; |
| 779 | } |
| 780 | $ppc_other_permissions = [ |
| 781 | "ppc_users" => esc_html__('Logged In Users', 'capability-manager-enhanced'), |
| 782 | "ppc_guest" => esc_html__('Logged Out Users', 'capability-manager-enhanced') |
| 783 | ]; |
| 784 | $wp_roles_obj = wp_roles(); |
| 785 | $roles = $wp_roles_obj->get_names(); |
| 786 | ?> |
| 787 | <div class="ppc-nav-edit"> |
| 788 | <div class="clear"></div> |
| 789 | <h4 style="margin-bottom: 0.6em;"><?php esc_html_e( 'PublishPress Capabilities Menu Restriction', 'capability-manager-enhanced' ) ?></h4> |
| 790 | <p class="description description-wide ppc-nav-mode"><?php esc_html_e( 'This menu is restricted for the following roles', 'capability-manager-enhanced' ) ?></p> |
| 791 | <ul> |
| 792 | <?php foreach (array_keys($restricted_roles) as $role) : |
| 793 | $role_url = admin_url('admin.php?page=pp-capabilities-nav-menus&role=' . $role . ''); |
| 794 | if (array_key_exists($role, $ppc_other_permissions)) { |
| 795 | $role_caption = $ppc_other_permissions[$role]; |
| 796 | } else { |
| 797 | if (is_array($roles) && !empty($roles[$role])) { |
| 798 | $role_caption = $roles[$role]; |
| 799 | } else { |
| 800 | $role_caption = translate_user_role($role); |
| 801 | } |
| 802 | } |
| 803 | ?> |
| 804 | <li style="margin-bottom: 5px;"> |
| 805 | <a target="blank" href="<?php echo esc_url($role_url); ?>"><?php echo esc_html($role_caption); ?></a> |
| 806 | </li> |
| 807 | <?php endforeach; ?> |
| 808 | </ul> |
| 809 | </div> |
| 810 | |
| 811 | <?php |
| 812 | } |
| 813 | |
| 814 | /** |
| 815 | * Redirect user on plugin activation |
| 816 | * |
| 817 | * @return void |
| 818 | */ |
| 819 | public function redirect_on_activate() |
| 820 | { |
| 821 | if (get_option('pp_capabilities_activated')) { |
| 822 | delete_option('pp_capabilities_activated'); |
| 823 | wp_safe_redirect(admin_url("admin.php?page=pp-capabilities-dashboard")); |
| 824 | exit; |
| 825 | } |
| 826 | } |
| 827 | |
| 828 | public function addPluginActionLinks($links, $file) |
| 829 | { |
| 830 | if ($file == plugin_basename(CME_FILE) && ! defined('PUBLISHPRESS_CAPS_PRO_VERSION')) { |
| 831 | $upgrade_link = ['<a href="https://publishpress.com/links/capabilities-menu" |
| 832 | target="_blank" style="font-weight: bold;"> |
| 833 | ' . __('Upgrade to Pro', 'capability-manager-enhanced') . ' |
| 834 | </a>']; |
| 835 | |
| 836 | $links = array_merge($upgrade_link, $links); |
| 837 | } |
| 838 | |
| 839 | return $links; |
| 840 | } |
| 841 | |
| 842 | public function addPluginRowMetaLinks($links, $file) |
| 843 | { |
| 844 | if ($file == plugin_basename(CME_FILE)) { |
| 845 | $links[] = '<a href="' . admin_url('admin.php?page=pp-capabilities-dashboard') . '">' . __('Dashboard', 'capability-manager-enhanced') . '</a>'; |
| 846 | $links[] = "<a href='" . admin_url("admin.php?page=pp-capabilities") . "'>" . esc_html__('Capabilities', 'capability-manager-enhanced') . "</a>"; |
| 847 | $links[] = '<a href="' . admin_url('admin.php?page=pp-capabilities-roles') . '">' . __('Roles', 'capability-manager-enhanced') . '</a>'; |
| 848 | $links[] = "<a href='" . admin_url("admin.php?page=pp-capabilities-settings") . "'>" . esc_html__('Settings', 'capability-manager-enhanced') . "</a>"; |
| 849 | } |
| 850 | |
| 851 | return $links; |
| 852 | } |
| 853 | |
| 854 | /** |
| 855 | * Show "Free" suffix for this plugin only on WordPress plugin list screens. |
| 856 | * |
| 857 | * @param array $all_plugins |
| 858 | * |
| 859 | * @return array |
| 860 | */ |
| 861 | public function filterPluginsListName($all_plugins) |
| 862 | { |
| 863 | global $pagenow; |
| 864 | |
| 865 | if (!is_admin() || 'plugins.php' !== $pagenow) { |
| 866 | return $all_plugins; |
| 867 | } |
| 868 | |
| 869 | $plugin_file = plugin_basename(CME_FILE); |
| 870 | |
| 871 | if (isset($all_plugins[$plugin_file]['Name'])) { |
| 872 | $all_plugins[$plugin_file]['Name'] = 'PublishPress Capabilities Free'; |
| 873 | } |
| 874 | |
| 875 | return $all_plugins; |
| 876 | } |
| 877 | } |
| 878 |