PluginProbe ʕ •ᴥ•ʔ
PublishPress Capabilities – User Role Editor, Access Permissions, User Capabilities, Admin Menus / 2.45.0
PublishPress Capabilities – User Role Editor, Access Permissions, User Capabilities, Admin Menus v2.45.0
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 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