PluginProbe
Groups – Memberships and Access Control / 3.9.0
Groups – Memberships and Access Control v3.9.0
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 1.13.1 All 130 releases
groups / lib / admin / groups-admin-capabilities.php

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

517 lines 18.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * groups-admin-capabilities.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 // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
27
28 define( 'GROUPS_CAPABILITIES_PER_PAGE', 10 );
29 define( 'GROUPS_ADMIN_CAPABILITIES_NONCE_1', 'groups-cap-nonce-1');
30 define( 'GROUPS_ADMIN_CAPABILITIES_NONCE_2', 'groups-cap-nonce-2');
31 define( 'GROUPS_ADMIN_CAPABILITIES_ACTION_NONCE', 'groups-cap-action-nonce');
32 define( 'GROUPS_ADMIN_CAPABILITIES_FILTER_NONCE', 'groups-cap-filter-nonce' );
33
34 require_once GROUPS_CORE_LIB . '/class-groups-pagination.php';
35 require_once GROUPS_ADMIN_LIB . '/groups-admin-capabilities-add.php';
36 require_once GROUPS_ADMIN_LIB . '/groups-admin-capabilities-edit.php';
37 require_once GROUPS_ADMIN_LIB . '/groups-admin-capabilities-remove.php';
38
39 /**
40 * Manage capabilities: table of capabilities and add, edit, remove actions.
41 */
42 function groups_admin_capabilities() {
43
44 global $wpdb;
45
46 $output = '';
47 $today = date( 'Y-m-d', time() ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
48
49 if ( !Groups_User::current_user_can( GROUPS_ADMINISTER_GROUPS ) ) {
50 wp_die( esc_html__( 'Access denied.', 'groups' ) );
51 }
52
53 //
54 // handle actions
55 //
56 if ( isset( $_POST['action'] ) ) {
57 // handle action submit - do it
58 switch( $_POST['action'] ) {
59 case 'add' :
60 if ( !( $capability_id = groups_admin_capabilities_add_submit() ) ) {
61 return groups_admin_capabilities_add();
62 } else {
63 $capability = Groups_Capability::read( $capability_id );
64 Groups_Admin::add_message( sprintf(
65 /* translators: capability name */
66 __( 'The <em>%s</em> capability has been created.', 'groups' ),
67 $capability->capability ? stripslashes( wp_filter_nohtml_kses( $capability->capability ) ) : ''
68 ) );
69 }
70 break;
71 case 'edit' :
72 if ( !( $capability_id = groups_admin_capabilities_edit_submit() ) ) {
73 return groups_admin_capabilities_edit( $_POST['capability-id-field'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
74 } else {
75 $capability = Groups_Capability::read( $capability_id );
76 Groups_Admin::add_message( sprintf(
77 /* translators: capability name */
78 __( 'The <em>%s</em> capability has been updated.', 'groups' ),
79 $capability->capability ? stripslashes( wp_filter_nohtml_kses( $capability->capability ) ) : ''
80 ) );
81 }
82 break;
83 case 'remove' :
84 if ( $capability_id = groups_admin_capabilities_remove_submit() ) {
85 Groups_Admin::add_message( __( 'The capability has been deleted.', 'groups' ) );
86 }
87 break;
88 // bulk actions on groups: capabilities
89 case 'groups-action' :
90 if ( wp_verify_nonce( $_POST[GROUPS_ADMIN_GROUPS_ACTION_NONCE], 'admin' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
91 $capability_ids = isset( $_POST['capability_ids'] ) ? $_POST['capability_ids'] : null; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
92 $bulk = isset( $_POST['bulk'] ) ? $_POST['bulk'] : null; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
93 if ( is_array( $capability_ids ) && ( $bulk !== null ) ) {
94 foreach ( $capability_ids as $capability_id ) {
95 $bulk_action = isset( $_POST['bulk-action'] ) ? $_POST['bulk-action'] : null; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
96 switch( $bulk_action ) {
97 case 'remove' :
98 if ( isset( $_POST['confirm'] ) ) {
99 groups_admin_capabilities_bulk_remove_submit();
100 } else {
101 return groups_admin_capabilities_bulk_remove();
102 }
103 break;
104 }
105 break;
106 }
107 }
108 }
109 break;
110 }
111 } else if ( isset ( $_GET['action'] ) ) {
112 // handle action request - show form
113 switch( $_GET['action'] ) {
114 case 'add' :
115 return groups_admin_capabilities_add();
116 break;
117 case 'edit' :
118 if ( isset( $_GET['capability_id'] ) ) {
119 return groups_admin_capabilities_edit( $_GET['capability_id'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
120 }
121 break;
122 case 'remove' :
123 if ( isset( $_GET['capability_id'] ) ) {
124 return groups_admin_capabilities_remove( $_GET['capability_id'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
125 }
126 break;
127 case 'refresh' :
128 if ( check_admin_referer( 'refresh' ) ) {
129 $n = Groups_WordPress::refresh_capabilities();
130 if ( $n > 0 ) {
131 /* translators: count */
132 $output .= '<div class="updated fade"><p>' . sprintf( _n( 'One capability has been added.', '%d capabilities have been added.', $n, 'groups' ), $n ) . '</p></div>'; // phpcs:ignore WordPress.WP.I18n.MissingSingularPlaceholder
133 } else {
134 $output .= '<div class="updated fade"><p>' . esc_html__( 'No new capabilities have been found.', 'groups' ) . '</p></div>';
135 }
136 } else {
137 wp_die( esc_html__( 'A Duck!', 'groups' ) );
138 }
139 break;
140 }
141 }
142
143 //
144 // capabilities table
145 //
146 if (
147 isset( $_POST['clear_filters'] ) ||
148 isset( $_POST['capability_id'] ) ||
149 isset( $_POST['capability'] )
150 ) {
151 if ( !wp_verify_nonce( $_POST[GROUPS_ADMIN_CAPABILITIES_FILTER_NONCE], 'admin' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
152 wp_die( esc_html__( 'Access denied.', 'groups' ) );
153 }
154 }
155
156 // filters
157 $capability_id = Groups_Options::get_user_option( 'capabilities_capability_id', null );
158 $capability = Groups_Options::get_user_option( 'capabilities_capability', null );
159
160 if ( isset( $_POST['clear_filters'] ) ) {
161 Groups_Options::delete_user_option( 'capabilities_capability_id' );
162 Groups_Options::delete_user_option( 'capabilities_capability' );
163 $capability_id = null;
164 $capability = null;
165 } else if ( isset( $_POST['submitted'] ) ) {
166 // filter by name
167 if ( !empty( $_POST['capability'] ) ) {
168 $capability = sanitize_text_field( $_POST['capability'] );
169 Groups_Options::update_user_option( 'capabilities_capability', $capability );
170 }
171 // filter by capability id
172 if ( !empty( $_POST['capability_id'] ) ) {
173 $capability_id = intval( $_POST['capability_id'] );
174 Groups_Options::update_user_option( 'capabilities_capability_id', $capability_id );
175 } else if ( isset( $_POST['capability_id'] ) ) { // empty && isset => '' => all
176 $capability_id = null;
177 Groups_Options::delete_user_option( 'capabilities_capability_id' );
178 }
179 }
180
181 if ( isset( $_POST['row_count'] ) ) {
182 if ( !wp_verify_nonce( $_POST[GROUPS_ADMIN_CAPABILITIES_NONCE_1], 'admin' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
183 wp_die( esc_html__( 'Access denied.', 'groups' ) );
184 }
185 }
186
187 if ( isset( $_POST['paged'] ) ) {
188 if ( !wp_verify_nonce( $_POST[GROUPS_ADMIN_CAPABILITIES_NONCE_2], 'admin' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
189 wp_die( esc_html__( 'Access denied.', 'groups' ) );
190 }
191 }
192
193 $current_url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
194 $current_url = remove_query_arg( 'paged', $current_url );
195 $current_url = remove_query_arg( 'action', $current_url );
196 $current_url = remove_query_arg( 'capability_id', $current_url );
197
198 $capability_table = _groups_get_tablename( 'capability' );
199
200 $output .=
201 '<div class="manage-capabilities wrap">' .
202 '<h1>' .
203 esc_html__( 'Capabilities', 'groups' ) .
204 // add capability
205 sprintf(
206 '<a title="%s" class="add page-title-action" href="%s">',
207 esc_attr__( 'Click to add a new capability', 'groups' ),
208 esc_url( $current_url . '&action=add' )
209 ) .
210 sprintf(
211 '<img class="icon" alt="%s" src="%s" />',
212 esc_attr__( 'Add', 'groups' ),
213 esc_url( GROUPS_PLUGIN_URL . 'images/add.png' )
214 ) .
215 sprintf(
216 '<span class="label">%s</span>',
217 esc_html__( 'New Capability', 'groups' )
218 ) .
219 '</a>' .
220 // refresh capabilities
221 sprintf(
222 '<a title="%s" class="refresh page-title-action" href="%s">',
223 esc_attr__( 'Click to refresh capabilities', 'groups' ),
224 esc_url( wp_nonce_url( $current_url . '&action=refresh', 'refresh' ) )
225 ) .
226 sprintf(
227 '<img class="icon" alt="%s" src="%s" />',
228 esc_attr__( 'Refresh', 'groups' ),
229 esc_url( GROUPS_PLUGIN_URL . 'images/refresh.png' )
230 ) .
231 sprintf(
232 '<span class="label">%s</span>',
233 esc_html__( 'Refresh', 'groups' )
234 ) .
235 '</a>' .
236 '</h1>';
237
238 $output .= Groups_Admin::render_messages();
239
240 $row_count = isset( $_POST['row_count'] ) ? intval( $_POST['row_count'] ) : 0;
241
242 if ($row_count <= 0) {
243 $row_count = Groups_Options::get_user_option( 'capabilities_per_page', GROUPS_CAPABILITIES_PER_PAGE );
244 } else {
245 Groups_Options::update_user_option('capabilities_per_page', $row_count );
246 }
247 $offset = isset( $_GET['offset'] ) ? intval( $_GET['offset'] ) : 0;
248 if ( $offset < 0 ) {
249 $offset = 0;
250 }
251 $paged = isset( $_REQUEST['paged'] ) ? intval( $_REQUEST['paged'] ) : 0;
252 if ( $paged < 0 ) {
253 $paged = 0;
254 }
255
256 $orderby = isset( $_GET['orderby'] ) ? $_GET['orderby'] : null; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
257 switch ( $orderby ) {
258 case 'capability_id' :
259 case 'capability' :
260 case 'description' :
261 break;
262 default:
263 $orderby = 'name';
264 }
265
266 $order = isset( $_GET['order'] ) ? $_GET['order'] : null; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
267 switch ( $order ) {
268 case 'asc' :
269 case 'ASC' :
270 $switch_order = 'DESC';
271 break;
272 case 'desc' :
273 case 'DESC' :
274 $switch_order = 'ASC';
275 break;
276 default:
277 $order = 'ASC';
278 $switch_order = 'DESC';
279 }
280
281 $filters = array( " 1=%d " );
282 $filter_params = array( 1 );
283 if ( $capability_id ) {
284 $filters[] = " $capability_table.capability_id = %d ";
285 $filter_params[] = $capability_id;
286 }
287 if ( $capability ) {
288 $filters[] = " $capability_table.capability LIKE %s ";
289 $filter_params[] = '%' . $wpdb->esc_like( $capability ) . '%';
290 }
291
292 if ( !empty( $filters ) ) { // @phpstan-ignore empty.variable
293 $filters = " WHERE " . implode( " AND ", $filters );
294 } else {
295 $filters = '';
296 }
297
298 $count_query = $wpdb->prepare( "SELECT COUNT(*) FROM $capability_table $filters", $filter_params ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
299 $count = $wpdb->get_var( $count_query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
300 if ( $count > $row_count ) {
301 $paginate = true;
302 } else {
303 $paginate = false;
304 }
305 $pages = ceil ( $count / $row_count );
306 if ( $paged > $pages ) {
307 $paged = $pages;
308 }
309 if ( $paged != 0 ) {
310 $offset = ( $paged - 1 ) * $row_count;
311 }
312
313 $query = $wpdb->prepare(
314 // nosemgrep: audit.php.wp.security.sqli.input-in-sinks
315 "SELECT * FROM $capability_table $filters ORDER BY $orderby $order LIMIT $row_count OFFSET $offset", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
316 $filter_params
317 );
318
319 // nosemgrep: audit.php.wp.security.sqli.input-in-sinks
320 $results = $wpdb->get_results( $query, OBJECT ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
321
322 $column_display_names = array(
323 'capability_id' => __( 'ID', 'groups' ),
324 'capability' => __( 'Capability', 'groups' ),
325 'description' => __( 'Description', 'groups' )
326 );
327
328 $output .= '<div class="capabilities-overview">';
329
330 $output .=
331 '<div class="filters">' .
332 '<form id="setfilters" action="" method="post">' .
333 '<fieldset>' .
334 '<legend>' . esc_html__( 'Filters', 'groups' ) . '</legend>' .
335 '<label class="capability-id-filter">' .
336 esc_html__( 'Capability ID', 'groups' ) . ' ' .
337 '<input class="capability-id-filter" name="capability_id" type="text" value="' . esc_attr( $capability_id ) . '"/>' .
338 '</label>' . ' ' .
339 '<label class="capability-filter">' .
340 esc_html__( 'Capability', 'groups' ) . ' ' .
341 '<input class="capability-filter" name="capability" type="text" value="' . esc_attr( $capability ? stripslashes( $capability ) : '' ) . '"/>' .
342 '</label>' . ' ' .
343 wp_nonce_field( 'admin', GROUPS_ADMIN_CAPABILITIES_FILTER_NONCE, true, false ) .
344 '<input class="button" type="submit" value="' . esc_attr__( 'Apply', 'groups' ) . '"/>' . ' ' .
345 '<input class="button" type="submit" name="clear_filters" value="' . esc_attr__( 'Clear', 'groups' ) . '"/>' .
346 '<input type="hidden" value="submitted" name="submitted"/>' .
347 '</fieldset>' .
348 '</form>' .
349 '</div>';
350
351 if ( $paginate ) {
352 require_once GROUPS_CORE_LIB . '/class-groups-pagination.php';
353 $pagination = new Groups_Pagination( $count, null, $row_count );
354 $output .= '<form id="posts-filter" method="post" action="">';
355 $output .= '<div>';
356 $output .= wp_nonce_field( 'admin', GROUPS_ADMIN_CAPABILITIES_NONCE_2, true, false );
357 $output .= '</div>';
358 $output .= '<div class="tablenav top">';
359 $output .= $pagination->pagination( 'top' );
360 $output .= '</div>';
361 $output .= '</form>';
362 }
363
364 $output .= '<div class="page-options right">';
365 $output .= '<form id="setrowcount" action="" method="post">';
366 $output .= '<div>';
367 $output .= '<label for="row_count">' . esc_html__( 'Results per page', 'groups' ) . '</label>';
368 $output .= '<input name="row_count" type="text" size="2" value="' . esc_attr( $row_count ) .'" />';
369 $output .= wp_nonce_field( 'admin', GROUPS_ADMIN_CAPABILITIES_NONCE_1, true, false );
370 $output .= '<input class="button" type="submit" value="' . esc_attr__( 'Apply', 'groups' ) . '"/>';
371 $output .= '</div>';
372 $output .= '</form>';
373 $output .= '</div>';
374
375 $output .= '<form id="groups-action" method="post" action="">';
376
377 $output .= '<div class="tablenav top">';
378 $output .= '<div class="capabilities-bulk-container">';
379 $output .= '<div class="alignleft actions">';
380 $output .= '<select name="bulk-action">';
381 $output .= '<option selected="selected" value="-1">' . esc_html__( 'Bulk Actions', 'groups' ) . '</option>';
382 $output .= '<option value="remove">' . esc_html__( 'Remove', 'groups' ) . '</option>';
383 $output .= '</select>';
384 $output .= '<input class="button" type="submit" name="bulk" value="' . esc_attr__( 'Apply', 'groups' ) . '"/>';
385 $output .= '</div>';
386 $output .= '</div>';
387 $output .= '</div>';
388 $output .= wp_nonce_field( 'admin', GROUPS_ADMIN_GROUPS_ACTION_NONCE, true, false );
389 $output .= '<input type="hidden" name="action" value="groups-action"/>';
390
391 $output .= '<table id="" class="wp-list-table widefat fixed" cellspacing="0">';
392 $output .= '<thead>';
393 $output .= '<tr>';
394
395 $output .= '<th id="cb" class="manage-column column-cb check-column" scope="col"><input type="checkbox"></th>';
396
397 foreach ( $column_display_names as $key => $column_display_name ) {
398 $options = array(
399 'orderby' => $key,
400 'order' => $switch_order
401 );
402 $class = $key;
403 if ( !in_array($key, array( 'capabilities', 'edit', 'remove' ) ) ) {
404 if ( strcmp( $key, $orderby ) == 0 ) {
405 $lorder = strtolower( $order );
406 $class = "$key manage-column sorted $lorder";
407 } else {
408 $class = "$key manage-column sortable";
409 }
410 $column_display_name =
411 sprintf(
412 '<a href="%s"><span>%s</span><span class="sorting-indicator"></span></a>',
413 esc_url( add_query_arg( $options, $current_url ) ),
414 esc_html( $column_display_name )
415 );
416 } else {
417 $column_display_name = esc_html( $column_display_name );
418 }
419 $output .= sprintf(
420 '<th scope="col" class="%s">%s</th>',
421 esc_attr( $class ),
422 $column_display_name
423 );
424 }
425
426 $output .= '</tr>';
427 $output .= '</thead>';
428 $output .= '<tbody>';
429
430 if ( count( $results ) > 0 ) {
431 for ( $i = 0; $i < count( $results ); $i++ ) {
432 $result = $results[$i];
433
434 // Construct the "edit" URL.
435 $edit_url = add_query_arg(
436 array(
437 'capability_id' => intval( $result->capability_id ),
438 'action' => 'edit',
439 'paged' => $paged
440 ),
441 $current_url
442 );
443 // Construct the "delete" URL.
444 $delete_url = add_query_arg(
445 array(
446 'capability_id' => intval( $result->capability_id ),
447 'action' => 'remove',
448 'paged' => $paged
449 ),
450 $current_url
451 );
452
453 // Construct row actions for this group.
454 $row_actions =
455 '<div class="row-actions">' .
456 '<span class="edit">' .
457 '<a href="' . esc_url( $edit_url ) . '">' .
458 '<img src="' . GROUPS_PLUGIN_URL . 'images/edit.png"/>' .
459 __( 'Edit', 'groups' ) .
460 '</a>';
461 if ( $result->capability !== Groups_Post_Access::READ_POST_CAPABILITY ) {
462 $row_actions .=
463 ' | '.
464 '</span>' .
465 '<span class="remove trash">' .
466 '<a href="' . esc_url( $delete_url ) . '" class="submitdelete">' .
467 '<img src="' . GROUPS_PLUGIN_URL . 'images/remove.png"/>' .
468 __( 'Remove', 'groups' ) .
469 '</a>' .
470 '</span>';
471 }
472 $row_actions .= '</div>'; // .row-actions
473
474 $output .= '<tr class="' . ( $i % 2 == 0 ? 'even' : 'odd' ) . '">';
475
476 $output .= '<th class="check-column">';
477 $output .= '<input type="checkbox" value="' . esc_attr( $result->capability_id ) . '" name="capability_ids[]"/>';
478 $output .= '</th>';
479
480 $output .= '<td class="capability-id">';
481 $output .= $result->capability_id;
482 $output .= '</td>';
483 $output .= '<td class="capability">';
484 $output .= sprintf( '<a href="%s">%s</a>', esc_url( $edit_url ), $result->capability ? stripslashes( wp_filter_nohtml_kses( $result->capability ) ) : '' );
485 $output .= $row_actions;
486 $output .= '</td>';
487 $output .= '<td class="description">';
488 $output .= $result->description ? stripslashes( wp_filter_nohtml_kses( $result->description ) ) : '';
489 $output .= '</td>';
490
491 $output .= '</tr>';
492 }
493 } else {
494 $output .= '<tr><td colspan="3">' . esc_html__( 'There are no results.', 'groups' ) . '</td></tr>';
495 }
496
497 $output .= '</tbody>';
498 $output .= '</table>';
499
500 $output .= Groups_UIE::render_add_titles( '.capabilities-overview table td' );
501
502 $output .= '</form>'; // #groups-action
503
504 if ( $paginate ) {
505 require_once GROUPS_CORE_LIB . '/class-groups-pagination.php';
506 $pagination = new Groups_Pagination($count, null, $row_count);
507 $output .= '<div class="tablenav bottom">';
508 $output .= $pagination->pagination( 'bottom' );
509 $output .= '</div>';
510 }
511
512 $output .= '</div>'; // .capabilities-overview
513 $output .= '</div>'; // .manage-capabilities
514
515 echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
516 } // function groups_admin_capabilities()
517