PluginProbe
Groups – Memberships and Access Control / 4.7.0
Groups – Memberships and Access Control v4.7.0
4.7.1 4.7.0 4.6.0 4.5.0 4.4.0 4.3.0 trunk 1.0.0-beta-1 1.0.0-beta-2 1.0.0-beta-3 1.0.0-beta-3b 1.0.0-beta-3c 1.0.0-beta-3d 1.1.4 1.1.5 1.10.0 1.10.1 1.10.2 1.10.3 1.11.0 1.11.1 1.11.2 1.11.3 1.12.0 1.13.0 All 131 releases
groups / lib / admin / groups-admin-options.php

groups-admin-options.php in Groups – Memberships and Access Control 4.7.0, at lib/admin/groups-admin-options.php

469 lines 18.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * groups-admin-options.php
4 *
5 * Copyright (c) "kento" Karim Rahimpur www.itthinx.com
6 *
7 * This code is released under the GNU General Public License.
8 * See COPYRIGHT.txt and LICENSE.txt.
9 *
10 * This code is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * This header and all notices must be kept intact.
16 *
17 * @author Karim Rahimpur
18 * @package groups
19 * @since groups 1.0.0
20 */
21
22 if ( !defined( 'ABSPATH' ) ) {
23 exit;
24 }
25
26 /**
27 * @var string GROUPS_ADMIN_OPTIONS_NONCE options form nonce name
28 */
29 define( 'GROUPS_ADMIN_OPTIONS_NONCE', 'groups-admin-nonce' );
30
31 /**
32 * @var int GROUPS_SHOW_EXTENSIONS_BOX_INTERVAL 14 days in seconds
33 */
34 define( 'GROUPS_SHOW_EXTENSIONS_BOX_INTERVAL', 1209600 );
35
36 /**
37 * Options admin screen.
38 */
39 function groups_admin_options() {
40
41 global $wp_roles, $groups_version;
42
43 if ( !Groups_User::current_user_can( GROUPS_ADMINISTER_OPTIONS ) ) {
44 wp_die( esc_html__( 'Access denied.', 'groups' ) );
45 }
46
47 $is_sitewide_plugin = false;
48 if ( is_multisite() ) {
49 $active_sitewide_plugins = get_site_option( 'active_sitewide_plugins', array() );
50 $active_sitewide_plugins = array_keys( $active_sitewide_plugins );
51 $is_sitewide_plugin = in_array( 'groups/groups.php', $active_sitewide_plugins );
52 }
53
54 $caps = array(
55 GROUPS_ACCESS_GROUPS => __( 'Access Groups', 'groups' ),
56 GROUPS_ADMINISTER_GROUPS => __( 'Administer Groups', 'groups' ),
57 GROUPS_ADMINISTER_OPTIONS => __( 'Administer Groups plugin options', 'groups' ),
58 GROUPS_RESTRICT_ACCESS => __( 'Restrict Access', 'groups' )
59 );
60
61 $previous_legacy_enable = Groups_Options::get_option( GROUPS_LEGACY_ENABLE, GROUPS_LEGACY_ENABLE_DEFAULT );
62
63 //
64 // handle options form submission
65 //
66 if ( isset( $_POST['submit'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
67 if ( groups_verify_post_nonce( GROUPS_ADMIN_OPTIONS_NONCE, 'admin' ) ) {
68
69 $post_types = get_post_types();
70 $selected_post_types = groups_sanitize_post( 'add_meta_boxes' ) ?? array();
71 $handle_post_types = array();
72 foreach ( $post_types as $post_type ) {
73 $handle_post_types[$post_type] = in_array( $post_type, $selected_post_types );
74 }
75 Groups_Post_Access::set_handles_post_types( $handle_post_types );
76
77 // tree view
78 if ( !empty( $_POST[GROUPS_SHOW_TREE_VIEW] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
79 Groups_Options::update_option( GROUPS_SHOW_TREE_VIEW, true );
80 } else {
81 Groups_Options::update_option( GROUPS_SHOW_TREE_VIEW, false );
82 }
83
84 // show in user profiles
85 Groups_Options::update_option( GROUPS_SHOW_IN_USER_PROFILE, !empty( $_POST[GROUPS_SHOW_IN_USER_PROFILE] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
86
87 // roles & capabilities
88 $rolenames = $wp_roles->get_names();
89 foreach ( $rolenames as $rolekey => $rolename ) {
90 $role = $wp_roles->get_role( $rolekey );
91 foreach ( $caps as $capkey => $capname ) {
92 $role_cap_id = $rolekey . '-' . $capkey;
93 if ( !empty( groups_sanitize_post( $role_cap_id ) ) ) {
94 $role->add_cap( $capkey );
95 } else {
96 $role->remove_cap( $capkey );
97 }
98 }
99 }
100 Groups_Controller::assure_capabilities();
101
102 if ( !$is_sitewide_plugin ) {
103 // delete data
104 if ( !empty( $_POST['delete-data'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
105 Groups_Options::update_option( 'groups_delete_data', true );
106 } else {
107 Groups_Options::update_option( 'groups_delete_data', false );
108 }
109 }
110
111 // legacy enable ?
112 if ( !empty( $_POST[GROUPS_LEGACY_ENABLE] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
113 Groups_Options::update_option( GROUPS_LEGACY_ENABLE, true );
114 } else {
115 Groups_Options::update_option( GROUPS_LEGACY_ENABLE, false );
116 }
117
118 Groups_Admin::add_message( __( 'Options saved.', 'groups' ) );
119 }
120 }
121
122 echo '<div class="groups-options wrap">';
123
124 echo '<h1>' . esc_html__( 'Groups Options', 'groups' ) . '</h1>';
125
126 echo Groups_Admin::render_messages(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
127
128 $show_tree_view = Groups_Options::get_option( GROUPS_SHOW_TREE_VIEW, GROUPS_SHOW_TREE_VIEW_DEFAULT );
129 $show_in_user_profile = Groups_Options::get_option( GROUPS_SHOW_IN_USER_PROFILE, GROUPS_SHOW_IN_USER_PROFILE_DEFAULT );
130
131 $rolenames = $wp_roles->get_names();
132 $caps_table = '<table class="groups-permissions">';
133 $caps_table .= '<thead>';
134 $caps_table .= '<tr>';
135 $caps_table .= '<td class="role">';
136 $caps_table .= esc_html__( 'Role', 'groups' );
137 $caps_table .= '</td>';
138 foreach ( $caps as $cap ) {
139 $caps_table .= '<td class="cap">';
140 $caps_table .= esc_html( $cap );
141 $caps_table .= '</td>';
142 }
143
144 $caps_table .= '</tr>';
145 $caps_table .= '</thead>';
146 $caps_table .= '<tbody>';
147 foreach ( $rolenames as $rolekey => $rolename ) {
148 $role = $wp_roles->get_role( $rolekey );
149 $caps_table .= '<tr>';
150 $caps_table .= '<td>';
151 $caps_table .= esc_html( translate_user_role( $rolename ) );
152 $caps_table .= '</td>';
153 foreach ( $caps as $capkey => $capname ) {
154
155 if ( $role->has_cap( $capkey ) ) {
156 $checked = ' checked="checked" ';
157 } else {
158 $checked = '';
159 }
160
161 $caps_table .= '<td class="checkbox">';
162 $role_cap_id = $rolekey.'-'.$capkey;
163 $caps_table .= '<input type="checkbox" name="' . esc_attr( $role_cap_id ) . '" id="' . esc_attr( $role_cap_id ) . '" ' . $checked . '/>';
164 $caps_table .= '</td>';
165 }
166 $caps_table .= '</tr>';
167 }
168 $caps_table .= '</tbody>';
169 $caps_table .= '</table>';
170
171 $delete_data = Groups_Options::get_option( 'groups_delete_data', false );
172
173 if ( groups_sanitize_get( 'dismiss-groups-extensions-box' ) && groups_verify_get_nonce( 'groups-extensions-box-nonce', 'dismiss-box' ) ) {
174 Groups_Options::update_user_option( 'show-extensions-box', time() );
175 }
176 $extensions_box = '';
177 $show_extensions_box = Groups_Options::get_user_option( 'show-extensions-box', 0 );
178 if ( ( time() - $show_extensions_box ) > GROUPS_SHOW_EXTENSIONS_BOX_INTERVAL ) {
179 // $dismiss_url = wp_nonce_url( add_query_arg( 'dismiss-groups-extensions-box', '1', admin_url( 'admin.php?page=groups-admin-options' ) ), 'dismiss-box', 'groups-extensions-box-nonce' );
180 $extensions_box = '<div id="groups-extensions-box">';
181 // $extensions_box .= sprintf( '<a title="%s" class="close" href="%s"></a>', esc_attr_x( 'Dismiss', 'title of dismiss notice link', 'groups' ), esc_url( $dismiss_url ) );
182 $extensions_box .= '<h3>';
183 $extensions_box .= esc_html__( 'Your support matters!', 'groups' );
184 $extensions_box .= '</h3>';
185 $extensions_box .= '<p>';
186 $extensions_box .= sprintf(
187 /* translators: 1: opening tag 2: closing tag */
188 esc_html__( 'Enhanced functionality is available via official %1$sExtensions%2$s for Groups.', 'groups' ),
189 '<a href="https://www.itthinx.com/shop/">',
190 '</a>'
191 );
192 $extensions_box .= '</p>';
193 $extensions_box .= '<p>';
194 $extensions_box .= esc_html__( 'By getting an official extension, you fund the work that is necessary to maintain and improve Groups.', 'groups' );
195 $extensions_box .= '</p>';
196 $extensions_box .= '</div>';
197 }
198
199 require_once GROUPS_ADMIN_LIB . '/class-groups-admin-bitcoin.php';
200 $bitcoin_box = Groups_Admin_Bitcoin::get_groups_bitcoin_box( array( 'where' => 'options' ) );
201
202 //
203 // print the options form
204 //
205 echo
206 '<form action="" name="options" method="post">' .
207 '<div>' .
208
209 '<p>' .
210 '<input class="button button-primary" type="submit" name="submit" value="' . esc_attr__( 'Save', 'groups' ) . '"/>' .
211 $bitcoin_box . // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
212 $extensions_box . // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
213 '</p>';
214
215 if ( _groups_admin_override() ) {
216 echo
217 '<h2 style="color:red">' .
218 esc_html__( 'Administrator Access Override', 'groups' ) .
219 '</h2>' .
220 '<p>' .
221 esc_html__( 'Administrators override all access permissions derived from Groups capabilities.', 'groups' ) .
222 '</p>' .
223 '<p>' .
224 wp_kses_post( __( 'To disable, do not define the constant <code>GROUPS_ADMINISTRATOR_OVERRIDE</code> or set it to <code>false</code>.', 'groups' ) ) .
225 '</p>' .
226 '<p>' .
227 wp_kses_post( __( 'Enabling this on production sites is <strong>not</strong> recommended.', 'groups' ) ) .
228 '</p>';
229 }
230
231 echo '<h2>';
232 echo esc_html__( 'Access restricions', 'groups' );
233 echo '</h2>';
234
235 echo '<h3>';
236 echo esc_html__( 'Post types', 'groups' );
237 echo '</h3>';
238
239 echo '<p class="description">';
240 echo esc_html__( 'Show access restrictions for these post types.', 'groups' ); // @todo change wording to '...handles access...' ?
241 echo '</p>';
242
243 $post_type_objects = get_post_types( array(), 'objects' );
244 uasort( $post_type_objects, 'groups_admin_options_compare_post_types' );
245
246 echo '<ul>';
247 foreach ( $post_type_objects as $post_type => $post_type_object ) {
248 echo '<li>';
249 echo '<label>';
250 $label = $post_type;
251 $labels = isset( $post_type_object->labels ) ? $post_type_object->labels : null;
252 if ( ( $labels !== null ) && isset( $labels->singular_name ) ) {
253 $label = $labels->singular_name; // this is already translated
254 }
255 $checked = Groups_Post_Access::handles_post_type( $post_type ) ? ' checked="checked" ' : '';
256 echo '<input name="add_meta_boxes[]" type="checkbox" value="' . esc_attr( $post_type ) . '" ' . $checked . '/>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
257 $is_public = isset( $post_type_object->public ) && $post_type_object->public;
258 echo $is_public ? '<strong>' : '';
259 echo esc_html( $label );
260 echo $is_public ? '</strong>' : '';
261 if ( $post_type != $label ) {
262 echo ' ';
263 echo '<code><small>';
264 echo esc_html( $post_type );
265 echo '</small></code>';
266 }
267 echo '</label>';
268 echo '</li>';
269 }
270 echo '<ul>';
271 echo '<p class="description">';
272 esc_html_e( 'This determines for which post types access restriction settings are offered.', 'groups' );
273 echo ' ';
274 esc_html_e( 'Disabling this setting for a post type also disables existing access restrictions on individual posts of that type.', 'groups' );
275 echo ' ';
276 esc_html_e( 'Some post types shown may not offer access restrictions even though they appear enabled here.', 'groups' );
277 echo '</p>';
278
279 echo
280 '<h2>' . esc_html__( 'User profiles', 'groups' ) . '</h2>' .
281 '<p>' .
282 '<label>' .
283 '<input name="' . GROUPS_SHOW_IN_USER_PROFILE . '" type="checkbox" ' . ( $show_in_user_profile ? 'checked="checked"' : '' ) . '/>' . // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
284 esc_html__( 'Show groups in user profiles.', 'groups' ) .
285 '</label>' .
286 '</p>';
287
288 echo
289 '<h2>' . esc_html__( 'Tree view', 'groups' ) . '</h2>' .
290 '<p>' .
291 '<label>' .
292 '<input name="' . GROUPS_SHOW_TREE_VIEW . '" type="checkbox" ' . ( $show_tree_view ? 'checked="checked"' : '' ) . '/>' . // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
293 esc_html__( 'Show the Groups tree view.', 'groups' ) .
294 '</label>' .
295 '</p>';
296
297 echo
298 '<h2>' . esc_html__( 'Permissions', 'groups' ) . '</h2>' .
299 '<p>' . esc_html__( 'These permissions apply to Groups management. They do not apply to access permissions derived from Groups capabilities.', 'groups' ) . '</p>' .
300 $caps_table . // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
301 '<p class="description">' .
302 esc_html__( 'A minimum set of permissions will be preserved.', 'groups' ) .
303 '<br/>' .
304 esc_html__( 'If you lock yourself out, please ask an administrator to help.', 'groups' ) .
305 '</p>';
306 if ( !$is_sitewide_plugin ) {
307 echo
308 '<h2>' . esc_html__( 'Deactivation and data persistence', 'groups' ) . '</h2>' .
309 '<p>' .
310 '<label>' .
311 '<input name="delete-data" type="checkbox" ' . ( $delete_data ? 'checked="checked"' : '' ) . '/>' .
312 esc_html__( 'Delete all Groups plugin data on deactivation', 'groups' ) .
313 '</label>' .
314 '</p>' .
315 '<p class="description warning">' .
316 esc_html__( 'CAUTION: If this option is active while the plugin is deactivated, ALL plugin settings and data will be DELETED. If you are going to use this option, now would be a good time to make a backup. By enabling this option you agree to be solely responsible for any loss of data or any other consequences thereof.', 'groups' ) .
317 '</p>';
318 }
319
320 $groups_legacy_enable = Groups_Options::get_option( GROUPS_LEGACY_ENABLE, GROUPS_LEGACY_ENABLE_DEFAULT );
321 if (
322 defined( 'GROUPS_SHOW_LEGACY_SETTINGS' ) && GROUPS_SHOW_LEGACY_SETTINGS === true || $groups_legacy_enable
323 ) {
324 echo '<h2>' . esc_html__( 'Legacy Settings', 'groups' ) . '</h2>';
325 echo '<p>' .
326 '<label>' .
327 '<input name="' . esc_attr( GROUPS_LEGACY_ENABLE ) . '" type="checkbox" ' . ( $groups_legacy_enable ? 'checked="checked"' : '' ) . '/>' . // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
328 esc_html__( 'Enable legacy access control based on capabilities.', 'groups' ) .
329 '</label>' .
330 '</p>';
331 if ( $groups_legacy_enable ) {
332 require_once GROUPS_LEGACY_LIB . '/admin/groups-admin-options-legacy.php';
333 do_action( 'groups_admin_options_legacy', $groups_legacy_enable !== $previous_legacy_enable );
334 }
335
336 $legacy_enabled = Groups_Options::get_option( GROUPS_LEGACY_ENABLE );
337 echo '<h3>';
338 /* translators: version number */
339 printf( esc_html__( 'Switching to Groups %s', 'groups' ), esc_html( $groups_version ) );
340 echo '</h3>';
341 echo '<p>';
342 /* translators: version number */
343 printf( esc_html__( 'Groups %s features a simpler model for access restrictions based on groups instead of capabilities used in Groups 1.x.', 'groups' ), esc_html( $groups_version ) );
344 echo ' ';
345 esc_html_e( 'To put it simple, previously you would have used capabilities to restrict access to posts and now you simply use groups.', 'groups' );
346 echo ' ';
347 esc_html_e( 'To make it easier to transition to the new model for those who migrate from a previous version, we have included legacy access control based on capabilities.', 'groups' );
348 echo '</p>';
349 echo '<div class="indent">';
350 echo '<p>';
351 esc_html_e( 'The following is only of interest if you have upgraded from Groups 1.x:', 'groups' );
352 echo '<br/>';
353 if ( $legacy_enabled ) {
354 esc_html_e( 'You are running the system with legacy access control based on capabilities enabled.', 'groups' );
355 echo ' ';
356 esc_html_e( 'This means that if you had access restrictions in place that were based on capabilities, your entries will still be protected.', 'groups' );
357 } else {
358 esc_html_e( 'You are running the system with legacy access control based on capabilities disabled.', 'groups' );
359 echo ' ';
360 esc_html_e( 'This could be important!', 'groups' );
361 echo ' ';
362 esc_html_e( 'If you had any access restrictions in place based on capabilities, the entries will now be unprotected, unless you enable legacy access restrictions or place appropriate access restrictions based on groups on the desired entries.', 'groups' );
363 }
364 echo '</p>';
365 echo '<p>';
366 esc_html_e( 'If you would like to switch to access restrictions based on groups (recommended) instead of capabilities, you can easily do so by setting the appropriate groups on your protected posts, pages and other entries to restrict access.', 'groups' );
367 echo ' ';
368 esc_html_e( 'Once you have adjusted your access restrictions based on groups, you can disable legacy access control.', 'groups' );
369 echo ' ';
370 echo sprintf(
371 /* translators: documentation pages link */
372 esc_html__( 'Please refer to the %s for details on how to switch to and use the new access restrictions.', 'groups' ),
373 sprintf( '<a target="_blank" href="https://docs.itthinx.com/document/groups/">%s</a>', esc_html__( 'Documentation', 'groups' ) )
374 );
375 echo '</p>';
376 echo '</div>'; // .indent
377 }
378
379 echo
380 '<p>' .
381 wp_nonce_field( 'admin', GROUPS_ADMIN_OPTIONS_NONCE, true, false ) . // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
382 '<input class="button button-primary" type="submit" name="submit" value="' . esc_attr__( 'Save', 'groups' ) . '"/>' .
383 '</p>' .
384 '</div>' .
385 '</form>';
386
387 echo '</div>'; // .groups-options
388 }
389
390 /**
391 * Network administration options.
392 */
393 function groups_network_admin_options() {
394
395 if ( !Groups_User::current_user_can( GROUPS_ADMINISTER_OPTIONS ) ) {
396 wp_die( esc_html__( 'Access denied.', 'groups' ) );
397 }
398
399 echo '<h1>' . esc_html__( 'Groups network options', 'groups' ) . '</h1>';
400
401 // handle options form submission
402 if ( isset( $_POST['submit'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
403 if ( groups_verify_post_nonce( GROUPS_ADMIN_OPTIONS_NONCE, 'admin' ) ) {
404 // delete data
405 if ( !empty( $_POST['delete-data'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
406 Groups_Options::update_option( 'groups_network_delete_data', true );
407 } else {
408 Groups_Options::update_option( 'groups_network_delete_data', false );
409 }
410 }
411 }
412
413 $delete_data = Groups_Options::get_option( 'groups_network_delete_data', false );
414
415 // options form
416 echo
417 '<form action="" name="options" method="post">' .
418 '<div>' .
419 '<h2>' . esc_html__( 'Network deactivation and data persistence', 'groups' ) . '</h2>' .
420 '<p>' .
421 '<label>' .
422 '<input name="delete-data" type="checkbox" ' . ( $delete_data ? 'checked="checked"' : '' ) . '/>' .
423 ' ' .
424 esc_html__( 'Delete all Groups plugin data for ALL sites on network deactivation', 'groups' ) .
425 '</label>' .
426 '</p>' .
427 '<p class="description warning">' .
428 wp_kses_post( __( 'CAUTION: If this option is active while the plugin is deactivated, ALL plugin settings and data will be DELETED for <strong>all sites</strong>. If you are going to use this option, now would be a good time to make a backup. By enabling this option you agree to be solely responsible for any loss of data or any other consequences thereof.', 'groups' ) ) .
429 '</p>' .
430 '<p>' .
431 wp_nonce_field( 'admin', GROUPS_ADMIN_OPTIONS_NONCE, true, false ) . // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
432 '<input class="button button-primary" type="submit" name="submit" value="' . esc_attr__( 'Save', 'groups' ) . '"/>' .
433 '</p>' .
434 '</div>' .
435 '</form>';
436 }
437
438 /**
439 * Compare two post types, considering those that have $public and/or $show_ui true as coming first.
440 *
441 * @param object $o1
442 * @param object $o2
443 *
444 * @return int
445 */
446 function groups_admin_options_compare_post_types( $o1, $o2 ) {
447 $name_1 = isset( $o1->name ) ? $o1->name : '';
448 $name_2 = isset( $o2->name ) ? $o2->name : '';
449 $public_1 = isset( $o1->public ) && $o1->public;
450 $public_2 = isset( $o2->public ) && $o2->public;
451 $show_ui_1 = isset( $o1->show_ui ) && $o1->show_ui;
452 $show_ui_2 = isset( $o2->show_ui ) && $o2->show_ui;
453 $n1 = 0;
454 $n2 = 0;
455 if ( $public_1 ) {
456 $n1--;
457 }
458 if ( $show_ui_1 ) {
459 $n1--;
460 }
461 if ( $public_2 ) {
462 $n2--;
463 }
464 if ( $show_ui_2 ) {
465 $n2--;
466 }
467 return ( $n1 - $n2 ) * 10 + strcmp( $name_1, $name_2 );
468 }
469