| @@ -23,21 +23,26 @@ | ||
| 23 | 23 | exit; |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | 26 | /** |
| 27 | - * @var string options form nonce name | |
| 27 | + * @var string GROUPS_ADMIN_OPTIONS_NONCE options form nonce name | |
| 28 | 28 | */ |
| 29 | 29 | define( 'GROUPS_ADMIN_OPTIONS_NONCE', 'groups-admin-nonce' ); |
| 30 | 30 | |
| 31 | 31 | /** |
| 32 | + * @var int GROUPS_SHOW_EXTENSIONS_BOX_INTERVAL 14 days in seconds | |
| 33 | + */ | |
| 34 | +define( 'GROUPS_SHOW_EXTENSIONS_BOX_INTERVAL', 1209600 ); | |
| 35 | + | |
| 36 | +/** | |
| 32 | 37 | * Options admin screen. |
| 33 | 38 | */ |
| 34 | 39 | function groups_admin_options() { |
| 35 | 40 | |
| 36 | - global $wpdb, $wp_roles; | |
| 41 | + global $wp_roles, $groups_version; | |
| 37 | 42 | |
| 38 | - if ( !current_user_can( GROUPS_ADMINISTER_OPTIONS ) ) { | |
| 39 | - wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) ); | |
| 43 | + if ( !Groups_User::current_user_can( GROUPS_ADMINISTER_OPTIONS ) ) { | |
| 44 | + wp_die( esc_html__( 'Access denied.', 'groups' ) ); | |
| 40 | 45 | } |
| 41 | 46 | |
| 42 | 47 | $is_sitewide_plugin = false; |
| 43 | 48 | if ( is_multisite() ) { |
| @@ -46,52 +51,32 @@ | ||
| 46 | 51 | $is_sitewide_plugin = in_array( 'groups/groups.php', $active_sitewide_plugins ); |
| 47 | 52 | } |
| 48 | 53 | |
| 49 | 54 | $caps = array( |
| 50 | - GROUPS_ACCESS_GROUPS => __( 'Access Groups', GROUPS_PLUGIN_DOMAIN ), | |
| 51 | - GROUPS_ADMINISTER_GROUPS => __( 'Administer Groups', GROUPS_PLUGIN_DOMAIN ), | |
| 52 | - GROUPS_ADMINISTER_OPTIONS => __( 'Administer Groups plugin options', GROUPS_PLUGIN_DOMAIN ), | |
| 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' ) | |
| 53 | 59 | ); |
| 54 | 60 | |
| 61 | + $previous_legacy_enable = Groups_Options::get_option( GROUPS_LEGACY_ENABLE, GROUPS_LEGACY_ENABLE_DEFAULT ); | |
| 62 | + | |
| 55 | 63 | // |
| 56 | 64 | // handle options form submission |
| 57 | 65 | // |
| 58 | - if ( isset( $_POST['submit'] ) ) { | |
| 59 | - if ( wp_verify_nonce( $_POST[GROUPS_ADMIN_OPTIONS_NONCE], 'admin' ) ) { | |
| 66 | + if ( isset( $_POST['submit'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing | |
| 67 | + if ( groups_verify_post_nonce( GROUPS_ADMIN_OPTIONS_NONCE, 'admin' ) ) { | |
| 60 | 68 | |
| 61 | - // admin override | |
| 62 | - if ( empty( $_POST[GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE] ) ) { | |
| 63 | - $admin_override = false; | |
| 64 | - } else { | |
| 65 | - $admin_override = true; | |
| 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 ); | |
| 66 | 74 | } |
| 67 | - // Don't move this to the plugin options, access will be faster | |
| 68 | - add_option( GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE, $admin_override ); // WP 3.3.1 : update alone wouldn't create the option when value is false | |
| 69 | - update_option( GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE, $admin_override ); | |
| 75 | + Groups_Post_Access::set_handles_post_types( $handle_post_types ); | |
| 70 | 76 | |
| 71 | - $post_types_option = Groups_Options::get_option( Groups_Post_Access::POST_TYPES, array() ); | |
| 72 | - $post_types = get_post_types( array( 'public' => true ) ); | |
| 73 | - $selected_post_types = is_array( $_POST['add_meta_boxes'] ) ? $_POST['add_meta_boxes'] : array(); | |
| 74 | - foreach( $post_types as $post_type ) { | |
| 75 | - $post_types_option[$post_type]['add_meta_box'] = in_array( $post_type, $selected_post_types ); | |
| 76 | - } | |
| 77 | - Groups_Options::update_option( Groups_Post_Access::POST_TYPES, $post_types_option ); | |
| 78 | - | |
| 79 | - $valid_read_caps = array( Groups_Post_Access::READ_POST_CAPABILITY ); | |
| 80 | - if ( !empty( $_POST[GROUPS_READ_POST_CAPABILITIES] ) ) { | |
| 81 | - $read_caps = $_POST[GROUPS_READ_POST_CAPABILITIES]; | |
| 82 | - foreach( $read_caps as $read_cap ) { | |
| 83 | - if ( $valid_cap = Groups_Capability::read( $read_cap ) ) { | |
| 84 | - if ( !in_array( $valid_cap->capability, $valid_read_caps ) ) { | |
| 85 | - $valid_read_caps[] = $valid_cap->capability; | |
| 86 | - } | |
| 87 | - } | |
| 88 | - } | |
| 89 | - } | |
| 90 | - Groups_Options::update_option( Groups_Post_Access::READ_POST_CAPABILITIES, $valid_read_caps ); | |
| 91 | - | |
| 92 | 77 | // tree view |
| 93 | - if ( !empty( $_POST[GROUPS_SHOW_TREE_VIEW] ) ) { | |
| 78 | + if ( !empty( $_POST[GROUPS_SHOW_TREE_VIEW] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing | |
| 94 | 79 | Groups_Options::update_option( GROUPS_SHOW_TREE_VIEW, true ); |
| 95 | 80 | } else { |
| 96 | 81 | Groups_Options::update_option( GROUPS_SHOW_TREE_VIEW, false ); |
| 97 | 82 | } |
| @@ -96,9 +81,9 @@ | ||
| 96 | 81 | Groups_Options::update_option( GROUPS_SHOW_TREE_VIEW, false ); |
| 97 | 82 | } |
| 98 | 83 | |
| 99 | 84 | // show in user profiles |
| 100 | - Groups_Options::update_option( GROUPS_SHOW_IN_USER_PROFILE, !empty( $_POST[GROUPS_SHOW_IN_USER_PROFILE] ) ); | |
| 85 | + Groups_Options::update_option( GROUPS_SHOW_IN_USER_PROFILE, !empty( $_POST[GROUPS_SHOW_IN_USER_PROFILE] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing | |
| 101 | 86 | |
| 102 | 87 | // roles & capabilities |
| 103 | 88 | $rolenames = $wp_roles->get_names(); |
| 104 | 89 | foreach ( $rolenames as $rolekey => $rolename ) { |
| @@ -103,10 +88,10 @@ | ||
| 103 | 88 | $rolenames = $wp_roles->get_names(); |
| 104 | 89 | foreach ( $rolenames as $rolekey => $rolename ) { |
| 105 | 90 | $role = $wp_roles->get_role( $rolekey ); |
| 106 | 91 | foreach ( $caps as $capkey => $capname ) { |
| 107 | - $role_cap_id = $rolekey.'-'.$capkey; | |
| 108 | - if ( !empty($_POST[$role_cap_id] ) ) { | |
| 92 | + $role_cap_id = $rolekey . '-' . $capkey; | |
| 93 | + if ( !empty( groups_sanitize_post( $role_cap_id ) ) ) { | |
| 109 | 94 | $role->add_cap( $capkey ); |
| 110 | 95 | } else { |
| 111 | 96 | $role->remove_cap( $capkey ); |
| 112 | 97 | } |
| @@ -115,29 +100,32 @@ | ||
| 115 | 100 | Groups_Controller::assure_capabilities(); |
| 116 | 101 | |
| 117 | 102 | if ( !$is_sitewide_plugin ) { |
| 118 | 103 | // delete data |
| 119 | - if ( !empty( $_POST['delete-data'] ) ) { | |
| 104 | + if ( !empty( $_POST['delete-data'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing | |
| 120 | 105 | Groups_Options::update_option( 'groups_delete_data', true ); |
| 121 | 106 | } else { |
| 122 | 107 | Groups_Options::update_option( 'groups_delete_data', false ); |
| 123 | 108 | } |
| 124 | 109 | } |
| 125 | - Groups_Admin::add_message( __( 'Options saved.', GROUPS_PLUGIN_DOMAIN ) ); | |
| 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' ) ); | |
| 126 | 119 | } |
| 127 | 120 | } |
| 128 | 121 | |
| 129 | 122 | echo '<div class="groups-options wrap">'; |
| 130 | 123 | |
| 131 | - echo | |
| 132 | - '<h1>' . | |
| 133 | - __( 'Groups Options', GROUPS_PLUGIN_DOMAIN ) . | |
| 134 | - '</h1>'; | |
| 124 | + echo '<h1>' . esc_html__( 'Groups Options', 'groups' ) . '</h1>'; | |
| 135 | 125 | |
| 136 | - echo Groups_Admin::render_messages(); | |
| 126 | + echo Groups_Admin::render_messages(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | |
| 137 | 127 | |
| 138 | - $admin_override = get_option( GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE, GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE_DEFAULT ); | |
| 139 | - | |
| 140 | 128 | $show_tree_view = Groups_Options::get_option( GROUPS_SHOW_TREE_VIEW, GROUPS_SHOW_TREE_VIEW_DEFAULT ); |
| 141 | 129 | $show_in_user_profile = Groups_Options::get_option( GROUPS_SHOW_IN_USER_PROFILE, GROUPS_SHOW_IN_USER_PROFILE_DEFAULT ); |
| 142 | 130 | |
| 143 | 131 | $rolenames = $wp_roles->get_names(); |
| @@ -144,13 +132,13 @@ | ||
| 144 | 132 | $caps_table = '<table class="groups-permissions">'; |
| 145 | 133 | $caps_table .= '<thead>'; |
| 146 | 134 | $caps_table .= '<tr>'; |
| 147 | 135 | $caps_table .= '<td class="role">'; |
| 148 | - $caps_table .= __( 'Role', GROUPS_PLUGIN_DOMAIN ); | |
| 136 | + $caps_table .= esc_html__( 'Role', 'groups' ); | |
| 149 | 137 | $caps_table .= '</td>'; |
| 150 | 138 | foreach ( $caps as $cap ) { |
| 151 | 139 | $caps_table .= '<td class="cap">'; |
| 152 | - $caps_table .= $cap; | |
| 140 | + $caps_table .= esc_html( $cap ); | |
| 153 | 141 | $caps_table .= '</td>'; |
| 154 | 142 | } |
| 155 | 143 | |
| 156 | 144 | $caps_table .= '</tr>'; |
| @@ -159,9 +147,9 @@ | ||
| 159 | 147 | foreach ( $rolenames as $rolekey => $rolename ) { |
| 160 | 148 | $role = $wp_roles->get_role( $rolekey ); |
| 161 | 149 | $caps_table .= '<tr>'; |
| 162 | 150 | $caps_table .= '<td>'; |
| 163 | - $caps_table .= translate_user_role( $rolename ); | |
| 151 | + $caps_table .= esc_html( translate_user_role( $rolename ) ); | |
| 164 | 152 | $caps_table .= '</td>'; |
| 165 | 153 | foreach ( $caps as $capkey => $capname ) { |
| 166 | 154 | |
| 167 | 155 | if ( $role->has_cap( $capkey ) ) { |
| @@ -171,9 +159,9 @@ | ||
| 171 | 159 | } |
| 172 | 160 | |
| 173 | 161 | $caps_table .= '<td class="checkbox">'; |
| 174 | 162 | $role_cap_id = $rolekey.'-'.$capkey; |
| 175 | - $caps_table .= '<input type="checkbox" name="' . $role_cap_id . '" id="' . $role_cap_id . '" ' . $checked . '/>'; | |
| 163 | + $caps_table .= '<input type="checkbox" name="' . esc_attr( $role_cap_id ) . '" id="' . esc_attr( $role_cap_id ) . '" ' . $checked . '/>'; | |
| 176 | 164 | $caps_table .= '</td>'; |
| 177 | 165 | } |
| 178 | 166 | $caps_table .= '</tr>'; |
| 179 | 167 | } |
| @@ -181,141 +169,218 @@ | ||
| 181 | 169 | $caps_table .= '</table>'; |
| 182 | 170 | |
| 183 | 171 | $delete_data = Groups_Options::get_option( 'groups_delete_data', false ); |
| 184 | 172 | |
| 185 | - if ( isset( $_GET['dismiss-groups-extensions-box'] ) && isset( $_GET['groups-extensions-box-nonce'] ) && wp_verify_nonce( $_GET['groups-extensions-box-nonce'], 'dismiss-box' ) ) { | |
| 186 | - Groups_Options::update_user_option( 'show-extensions-box', false ); | |
| 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() ); | |
| 187 | 175 | } |
| 188 | 176 | $extensions_box = ''; |
| 189 | - if ( Groups_Options::get_user_option( 'show-extensions-box', true ) ) { | |
| 190 | - $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' ); | |
| 191 | - $extensions_box = | |
| 192 | - '<div id="groups-extensions-box">' . | |
| 193 | - __( 'Enhanced functionality is available via official <a href="http://www.itthinx.com/shop/">Extensions</a> for Groups.', GROUPS_PLUGIN_DOMAIN ) . | |
| 194 | - sprintf( '<a class="close" href="%s">x</a>', esc_url( $dismiss_url ) ) . | |
| 195 | - '</div>'; | |
| 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>'; | |
| 196 | 197 | } |
| 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 | + | |
| 198 | 202 | // |
| 199 | 203 | // print the options form |
| 200 | 204 | // |
| 201 | 205 | echo |
| 202 | 206 | '<form action="" name="options" method="post">' . |
| 207 | + '<div>' . | |
| 203 | 208 | |
| 204 | 209 | '<p>' . |
| 205 | - '<input class="button button-primary" type="submit" name="submit" value="' . __( 'Save', GROUPS_PLUGIN_DOMAIN ) . '"/>' . | |
| 206 | - $extensions_box . | |
| 207 | - '</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>'; | |
| 208 | 214 | |
| 209 | - '<div>' . | |
| 210 | - '<h2>' . __( 'Administrator Access Override', GROUPS_PLUGIN_DOMAIN ) . '</h2>' . | |
| 211 | - '<p>' . | |
| 212 | - '<label>' . | |
| 213 | - '<input name="' . GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE . '" type="checkbox" ' . ( $admin_override ? 'checked="checked"' : '' ) . '/>' . | |
| 214 | - __( 'Administrators override all access permissions derived from Groups capabilities.', GROUPS_PLUGIN_DOMAIN ) . | |
| 215 | - '</label>' . | |
| 216 | - '</p>'; | |
| 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 | + } | |
| 217 | 230 | |
| 218 | - echo '<h2>' . __( 'Access restricions', GROUPS_PLUGIN_DOMAIN ) . '</h2>'; | |
| 231 | + echo '<h2>'; | |
| 232 | + echo esc_html__( 'Access restricions', 'groups' ); | |
| 233 | + echo '</h2>'; | |
| 219 | 234 | |
| 220 | - echo '<h3>' . __( 'Post types', GROUPS_PLUGIN_DOMAIN ) . '</h3>'; | |
| 235 | + echo '<h3>'; | |
| 236 | + echo esc_html__( 'Post types', 'groups' ); | |
| 237 | + echo '</h3>'; | |
| 221 | 238 | |
| 222 | - echo | |
| 223 | - '<p class="description">' . __( 'Show access restrictions for these post types.', GROUPS_PLUGIN_DOMAIN ) . '</p>'; | |
| 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>'; | |
| 224 | 242 | |
| 225 | - $post_types_option = Groups_Options::get_option( Groups_Post_Access::POST_TYPES, array() ); | |
| 226 | - $post_types = get_post_types( array( 'public' => true ) ); | |
| 243 | + $post_type_objects = get_post_types( array(), 'objects' ); | |
| 244 | + uasort( $post_type_objects, 'groups_admin_options_compare_post_types' ); | |
| 245 | + | |
| 227 | 246 | echo '<ul>'; |
| 228 | - foreach( $post_types as $post_type ) { | |
| 229 | - $post_type_object = get_post_type_object( $post_type ); | |
| 247 | + foreach ( $post_type_objects as $post_type => $post_type_object ) { | |
| 230 | 248 | echo '<li>'; |
| 231 | 249 | echo '<label>'; |
| 232 | 250 | $label = $post_type; |
| 233 | 251 | $labels = isset( $post_type_object->labels ) ? $post_type_object->labels : null; |
| 234 | 252 | if ( ( $labels !== null ) && isset( $labels->singular_name ) ) { |
| 235 | - $label = __( $labels->singular_name ); | |
| 253 | + $label = $labels->singular_name; // this is already translated | |
| 236 | 254 | } |
| 237 | - $checked = ( !isset( $post_types_option[$post_type]['add_meta_box'] ) || $post_types_option[$post_type]['add_meta_box'] ) ? ' checked="checked" ' : ''; | |
| 238 | - echo '<input name="add_meta_boxes[]" type="checkbox" value="' . esc_attr( $post_type ) . '" ' . $checked . '/>'; | |
| 239 | - echo $label; | |
| 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 | + } | |
| 240 | 267 | echo '</label>'; |
| 241 | 268 | echo '</li>'; |
| 242 | 269 | } |
| 243 | 270 | echo '<ul>'; |
| 244 | - echo | |
| 245 | - '<p class="description">' . | |
| 246 | - __( 'This determines for which post types access restriction settings are offered.', GROUPS_PLUGIN_DOMAIN ) . '<br/>' . | |
| 247 | - __( 'Disabling this setting for a post type does not remove existing access restrictions on individual posts of that type.', GROUPS_PLUGIN_DOMAIN ) . '<br/>' . | |
| 248 | - '</p>'; | |
| 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>'; | |
| 249 | 278 | |
| 250 | - | |
| 251 | - echo '<h3>' . __( 'Capabilities', GROUPS_PLUGIN_DOMAIN ) . '</h3>'; | |
| 252 | - | |
| 253 | - echo '<p class="description">' . | |
| 254 | - __( 'Include these capabilities to enforce read access on posts. The selected capabilities will be offered to restrict access to posts.', GROUPS_PLUGIN_DOMAIN ) . | |
| 255 | - '</p>'; | |
| 256 | - | |
| 257 | - $capability_table = _groups_get_tablename( "capability" ); | |
| 258 | - $capabilities = $wpdb->get_results( "SELECT * FROM $capability_table ORDER BY capability" ); | |
| 259 | - $applicable_read_caps = Groups_Options::get_option( Groups_Post_Access::READ_POST_CAPABILITIES, array( Groups_Post_Access::READ_POST_CAPABILITY ) ); | |
| 260 | - echo '<div class="select-capability-container" style="width:62%;">'; | |
| 261 | - printf( '<select class="select capability" name="%s" multiple="multiple">', GROUPS_READ_POST_CAPABILITIES . '[]' ); | |
| 262 | - foreach( $capabilities as $capability ) { | |
| 263 | - $selected = in_array( $capability->capability, $applicable_read_caps ) ? ' selected="selected" ' : ''; | |
| 264 | - if ( $capability->capability == Groups_Post_Access::READ_POST_CAPABILITY ) { | |
| 265 | - $selected .= ' disabled="disabled" '; | |
| 266 | - } | |
| 267 | - printf( '<option value="%s" %s>%s</option>', esc_attr( $capability->capability_id ), $selected, wp_filter_nohtml_kses( $capability->capability ) ); | |
| 268 | - } | |
| 269 | - echo '</select>'; | |
| 270 | - echo '</div>'; | |
| 271 | - | |
| 272 | - echo Groups_UIE::render_select( '.select.capability' ); | |
| 273 | - | |
| 274 | 279 | echo |
| 275 | - '<h2>' . __( 'User profiles', GROUPS_PLUGIN_DOMAIN ) . '</h2>' . | |
| 280 | + '<h2>' . esc_html__( 'User profiles', 'groups' ) . '</h2>' . | |
| 276 | 281 | '<p>' . |
| 277 | 282 | '<label>' . |
| 278 | - '<input name="' . GROUPS_SHOW_IN_USER_PROFILE . '" type="checkbox" ' . ( $show_in_user_profile ? 'checked="checked"' : '' ) . '/>' . | |
| 279 | - __( 'Show groups in user profiles.', GROUPS_PLUGIN_DOMAIN ) . | |
| 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' ) . | |
| 280 | 285 | '</label>' . |
| 281 | 286 | '</p>'; |
| 282 | 287 | |
| 283 | 288 | echo |
| 284 | - '<h2>' . __( 'Tree view', GROUPS_PLUGIN_DOMAIN ) . '</h2>' . | |
| 289 | + '<h2>' . esc_html__( 'Tree view', 'groups' ) . '</h2>' . | |
| 285 | 290 | '<p>' . |
| 286 | 291 | '<label>' . |
| 287 | - '<input name="' . GROUPS_SHOW_TREE_VIEW . '" type="checkbox" ' . ( $show_tree_view ? 'checked="checked"' : '' ) . '/>' . | |
| 288 | - __( 'Show the Groups tree view.', GROUPS_PLUGIN_DOMAIN ) . | |
| 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' ) . | |
| 289 | 294 | '</label>' . |
| 290 | 295 | '</p>'; |
| 291 | 296 | |
| 292 | 297 | echo |
| 293 | - '<h2>' . __( 'Permissions', GROUPS_PLUGIN_DOMAIN ) . '</h2>' . | |
| 294 | - '<p>' . __( 'These permissions apply to Groups management. They do not apply to access permissions derived from Groups capabilities.', GROUPS_PLUGIN_DOMAIN ) . '</p>' . | |
| 295 | - $caps_table . | |
| 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 | |
| 296 | 301 | '<p class="description">' . |
| 297 | - __( 'A minimum set of permissions will be preserved.', GROUPS_PLUGIN_DOMAIN ) . | |
| 302 | + esc_html__( 'A minimum set of permissions will be preserved.', 'groups' ) . | |
| 298 | 303 | '<br/>' . |
| 299 | - __( 'If you lock yourself out, please ask an administrator to help.', GROUPS_PLUGIN_DOMAIN ) . | |
| 304 | + esc_html__( 'If you lock yourself out, please ask an administrator to help.', 'groups' ) . | |
| 300 | 305 | '</p>'; |
| 301 | 306 | if ( !$is_sitewide_plugin ) { |
| 302 | 307 | echo |
| 303 | - '<h2>' . __( 'Deactivation and data persistence', GROUPS_PLUGIN_DOMAIN ) . '</h2>' . | |
| 308 | + '<h2>' . esc_html__( 'Deactivation and data persistence', 'groups' ) . '</h2>' . | |
| 304 | 309 | '<p>' . |
| 305 | 310 | '<label>' . |
| 306 | 311 | '<input name="delete-data" type="checkbox" ' . ( $delete_data ? 'checked="checked"' : '' ) . '/>' . |
| 307 | - __( 'Delete all Groups plugin data on deactivation', GROUPS_PLUGIN_DOMAIN ) . | |
| 312 | + esc_html__( 'Delete all Groups plugin data on deactivation', 'groups' ) . | |
| 308 | 313 | '</label>' . |
| 309 | 314 | '</p>' . |
| 310 | 315 | '<p class="description warning">' . |
| 311 | - __( '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_PLUGIN_DOMAIN ) . | |
| 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' ) . | |
| 312 | 317 | '</p>'; |
| 313 | 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 | + | |
| 314 | 379 | echo |
| 315 | 380 | '<p>' . |
| 316 | - wp_nonce_field( 'admin', GROUPS_ADMIN_OPTIONS_NONCE, true, false ) . | |
| 317 | - '<input class="button button-primary" type="submit" name="submit" value="' . __( 'Save', GROUPS_PLUGIN_DOMAIN ) . '"/>' . | |
| 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' ) . '"/>' . | |
| 318 | 383 | '</p>' . |
| 319 | 384 | '</div>' . |
| 320 | 385 | '</form>'; |
| 321 | 386 | |
| @@ -321,26 +386,24 @@ | ||
| 321 | 386 | |
| 322 | 387 | echo '</div>'; // .groups-options |
| 323 | 388 | } |
| 324 | 389 | |
| 390 | +/** | |
| 391 | + * Network administration options. | |
| 392 | + */ | |
| 325 | 393 | function groups_network_admin_options() { |
| 326 | 394 | |
| 327 | - if ( !current_user_can( GROUPS_ADMINISTER_OPTIONS ) ) { | |
| 328 | - wp_die( __( 'Access denied.', GROUPS_PLUGIN_DOMAIN ) ); | |
| 395 | + if ( !Groups_User::current_user_can( GROUPS_ADMINISTER_OPTIONS ) ) { | |
| 396 | + wp_die( esc_html__( 'Access denied.', 'groups' ) ); | |
| 329 | 397 | } |
| 330 | 398 | |
| 331 | - echo | |
| 332 | - '<div>' . | |
| 333 | - '<h1>' . | |
| 334 | - __( 'Groups network options', GROUPS_PLUGIN_DOMAIN ) . | |
| 335 | - '</h1>' . | |
| 336 | - '</div>'; | |
| 399 | + echo '<h1>' . esc_html__( 'Groups network options', 'groups' ) . '</h1>'; | |
| 337 | 400 | |
| 338 | 401 | // handle options form submission |
| 339 | - if ( isset( $_POST['submit'] ) ) { | |
| 340 | - if ( wp_verify_nonce( $_POST[GROUPS_ADMIN_OPTIONS_NONCE], 'admin' ) ) { | |
| 402 | + if ( isset( $_POST['submit'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing | |
| 403 | + if ( groups_verify_post_nonce( GROUPS_ADMIN_OPTIONS_NONCE, 'admin' ) ) { | |
| 341 | 404 | // delete data |
| 342 | - if ( !empty( $_POST['delete-data'] ) ) { | |
| 405 | + if ( !empty( $_POST['delete-data'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing | |
| 343 | 406 | Groups_Options::update_option( 'groups_network_delete_data', true ); |
| 344 | 407 | } else { |
| 345 | 408 | Groups_Options::update_option( 'groups_network_delete_data', false ); |
| 346 | 409 | } |
| @@ -352,19 +415,54 @@ | ||
| 352 | 415 | // options form |
| 353 | 416 | echo |
| 354 | 417 | '<form action="" name="options" method="post">' . |
| 355 | 418 | '<div>' . |
| 356 | - '<h2>' . __( 'Network deactivation and data persistence', GROUPS_PLUGIN_DOMAIN ) . '</h2>' . | |
| 419 | + '<h2>' . esc_html__( 'Network deactivation and data persistence', 'groups' ) . '</h2>' . | |
| 357 | 420 | '<p>' . |
| 421 | + '<label>' . | |
| 358 | 422 | '<input name="delete-data" type="checkbox" ' . ( $delete_data ? 'checked="checked"' : '' ) . '/>' . |
| 359 | - '<label for="delete-data">' . __( 'Delete all Groups plugin data for ALL sites on network deactivation', GROUPS_PLUGIN_DOMAIN ) . '</label>' . | |
| 423 | + ' ' . | |
| 424 | + esc_html__( 'Delete all Groups plugin data for ALL sites on network deactivation', 'groups' ) . | |
| 425 | + '</label>' . | |
| 360 | 426 | '</p>' . |
| 361 | 427 | '<p class="description warning">' . |
| 362 | - __( '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_PLUGIN_DOMAIN ) . | |
| 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' ) ) . | |
| 363 | 429 | '</p>' . |
| 364 | 430 | '<p>' . |
| 365 | - wp_nonce_field( 'admin', GROUPS_ADMIN_OPTIONS_NONCE, true, false ) . | |
| 366 | - '<input type="submit" name="submit" value="' . __( 'Save', GROUPS_PLUGIN_DOMAIN ) . '"/>' . | |
| 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' ) . '"/>' . | |
| 367 | 433 | '</p>' . |
| 368 | 434 | '</div>' . |
| 369 | 435 | '</form>'; |
| 370 | -} | |
| 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 | +} | |