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