PluginProbe
wpForo Forum / 2.3.5
wpForo Forum v2.3.5
3.1.5 3.1.4 3.1.2 3.1.1 3.1.0 3.0.9 3.0.8 3.0.7 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.10 1.4.11 1.4.12 1.4.13 1.4.2 All 137 releases
wpforo / admin / listtables / Moderations.php

Moderations.php in wpForo Forum 2.3.5, at admin/listtables/Moderations.php

369 lines 15.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace wpforo\admin\listtables;
4
5 use WP_List_Table;
6
7 require_once( ABSPATH . 'wp-admin/includes/template.php' );
8 require_once( ABSPATH . 'wp-admin/includes/screen.php' );
9 require_once( ABSPATH . 'wp-admin/includes/class-wp-screen.php' );
10 require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
11
12 class Moderations extends WP_List_Table {
13
14 public $wpfitems_count;
15
16 /** ************************************************************************
17 * REQUIRED. Set up a constructor that references the parent constructor. We
18 * use the parent reference to set some default configs.
19 ***************************************************************************/
20 function __construct() {
21 //Set parent defaults
22 parent::__construct(
23 [
24 'singular' => 'moderation', //singular name of the listed records
25 'plural' => 'moderations', //plural name of the listed records
26 'ajax' => false, //does this table support ajax?
27 'screen' => 'wpForoModerations',
28 ]
29 );
30
31 }
32
33
34 /** ************************************************************************
35 * Recommended. This method is called when the parent class can't find a method
36 * specifically build for a given column. Generally, it's recommended to include
37 * one method for each column you want to render, keeping your package class
38 * neat and organized. For example, if the class needs to process a column
39 * named 'title', it would first see if a method named $this->column_title()
40 * exists - if it does, that method will be used. If it doesn't, this one will
41 * be used. Generally, you should try to use custom column methods as much as
42 * possible.
43 *
44 * Since we have defined a column_title() method later on, this method doesn't
45 * need to concern itself with any column with a name of 'title'. Instead, it
46 * needs to handle everything else.
47 *
48 * For more detailed insight into how columns are handled, take a look at
49 * WP_List_Table::single_row_columns()
50 *
51 * @param array $item A singular item (one full row's worth of data)
52 * @param string $column_name The name/slug of the column to be processed
53 *
54 * @return string Text or HTML to be placed inside the column <td>
55 **************************************************************************/
56 function column_default( $item, $column_name ) {
57 switch( $column_name ) {
58 case 'title':
59 return apply_filters( 'wpforo_admin_listtables_moderations_column_title', $item[ $column_name ], $item );
60 case 'userid':
61 $userdata = get_userdata( $item[ $column_name ] );
62
63 return ( ! empty( $userdata->user_nicename ) ? urldecode( $userdata->user_nicename ) : $item[ $column_name ] );
64 case 'is_first_post':
65 return ( $item[ $column_name ] ) ? __( 'TOPIC', 'wpforo' ) : __( 'REPLY', 'wpforo' );
66 case 'private':
67 return ( $item[ $column_name ] ) ? __( 'YES', 'wpforo' ) : __( 'NO', 'wpforo' );
68 default:
69 return $item[ $column_name ];
70 }
71 }
72
73
74 /** ************************************************************************
75 * Recommended. This is a custom column method and is responsible for what
76 * is rendered in any column with a name/slug of 'title'. Every time the class
77 * needs to render a column, it first looks for a method named
78 * column_{$column_title} - if it exists, that method is run. If it doesn't
79 * exist, column_default() is called instead.
80 *
81 * This example also illustrates how to implement rollover actions. Actions
82 * should be an associative array formatted as 'slug'=>'link html' - and you
83 * will need to generate the URLs yourself. You could even ensure the links
84 *
85 *
86 * @param array $item A singular item (one full row's worth of data)
87 *
88 * @return string Text to be placed inside the column <td> (movie title only)
89 **************************************************************************@see WP_List_Table::::single_row_columns()
90 */
91 function column_postid( $item ) {
92 $vhref = WPF()->moderation->get_view_url( $item['postid'] );
93 //Build row actions
94 $actions = [ 'view' => '<a href="' . $vhref . '" target="_blank">' . __( 'View', 'wpforo' ) . '</a>' ];
95 if( $this->get_filter_by_status_var() ) {
96 $ahref = wp_nonce_url( admin_url( sprintf( 'admin.php?page=%1$s&wpfaction=%2$s&postid=%3$s', wpforo_prefix_slug( 'moderations' ), 'dashboard_post_approve', $item['postid'] ) ), 'wpforo-approve-post-' . $item['postid'] );
97 $actions['wpfapprove'] = '<a href="' . $ahref . '">' . __( 'Approve', 'wpforo' ) . '</a>';
98 } else {
99 $uhref = wp_nonce_url( admin_url( sprintf( 'admin.php?page=%1$s&wpfaction=%2$s&postid=%3$s', wpforo_prefix_slug( 'moderations' ), 'dashboard_post_unapprove', $item['postid'] ) ), 'wpforo-unapprove-post-' . $item['postid'] );
100 $actions['wpfunapprove'] = '<a href="' . $uhref . '">' . __( 'Unapprove', 'wpforo' ) . '</a>';
101 }
102 $dhref = wp_nonce_url( admin_url( sprintf( 'admin.php?page=%1$s&wpfaction=%2$s&postid=%3$s', wpforo_prefix_slug( 'moderations' ), 'dashboard_post_delete', $item['postid'] ) ), 'wpforo-delete-post-' . $item['postid'] );
103 $actions['delete'] = '<a onclick="return confirm(\'' . __( "Are you sure you want to DELETE this item?", 'wpforo' ) . '\');" href="' . $dhref . '">' . __( 'Delete', 'wpforo' ) . '</a>';
104
105 $actions = apply_filters( 'wpforo_admin_listtables_moderations_actions', $actions, $item );
106
107 //Return the title contents
108 return sprintf(
109 '%1$s %2$s',
110 /*$1%s*/ $item['postid'],
111 /*$2%s*/ $this->row_actions( $actions )
112 );
113 }
114
115
116 /** ************************************************************************
117 * REQUIRED if displaying checkboxes or using bulk actions! The 'cb' column
118 * is given special treatment when columns are processed. It ALWAYS needs to
119 * have its own method.
120 *
121 * @param array $item A singular item (one full row's worth of data)
122 *
123 * @return string Text to be placed inside the column <td> (movie title only)
124 **************************************************************************@see WP_List_Table::::single_row_columns()
125 */
126 function column_cb( $item ) {
127 return sprintf(
128 '<input type="checkbox" name="%1$s[]" value="%2$s" />',
129 /*$1%s*/ 'postids', //Let's simply repurpose the table's singular label ("movie")
130 /*$2%s*/ $item['postid'] //The value of the checkbox should be the record's id
131 );
132 }
133
134
135 /** ************************************************************************
136 * REQUIRED! This method dictates the table's columns and titles. This should
137 * return an array where the key is the column slug (and class) and the value
138 * is the column's title text. If you need a checkbox for bulk actions, refer
139 * to the $columns array below.
140 *
141 * The 'cb' column is treated differently than the rest. If including a checkbox
142 * column in your table you must create a column_cb() method. If you don't need
143 * to bulk actions or checkboxes, simply leave the 'cb' entry out of your array.
144 *
145 * @return array An associative array containing column information: 'slugs'=>'Visible Titles'
146 **************************************************************************@see WP_List_Table::::single_row_columns()
147 */
148 function get_columns() {
149 return [
150 'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
151 'postid' => __( 'ID', 'wpforo' ),
152 'title' => __( 'Title', 'wpforo' ),
153 'is_first_post' => __( 'Type', 'wpforo' ),
154 'userid' => __( 'Created By', 'wpforo' ),
155 'created' => __( 'Created', 'wpforo' ),
156 'private' => __( 'Private', 'wpforo' ),
157 ];
158 }
159
160
161 /** ************************************************************************
162 * Optional. If you want one or more columns to be sortable (ASC/DESC toggle),
163 * you will need to register it here. This should return an array where the
164 * key is the column that needs to be sortable, and the value is db column to
165 * sort by. Often, the key and value will be the same, but this is not always
166 * the case (as the value is a column name from the database, not the list table).
167 *
168 * This method merely defines which columns should be sortable and makes them
169 * clickable - it does not handle the actual sorting. You still need to detect
170 * the ORDERBY and ORDER querystring variables within prepare_items() and sort
171 * your data accordingly (usually by modifying your query).
172 *
173 * @return array An associative array containing all the columns that should be sortable: 'slugs'=>array('data_values',bool)
174 **************************************************************************/
175 function get_sortable_columns() {
176 return [
177 'postid' => [ 'postid', false ], //true means it's already sorted
178 'title' => [ 'title', false ],
179 'is_first_post' => [ 'is_first_post', false ],
180 'userid' => [ 'userid', false ],
181 'created' => [ 'created', false ],
182 'private' => [ 'private', false ],
183 ];
184 }
185
186
187 /** ************************************************************************
188 * Optional. If you need to include bulk actions in your list table, this is
189 * the place to define them. Bulk actions are an associative array in the format
190 * 'slug'=>'Visible Title'
191 *
192 * If this method returns an empty value, no bulk action will be rendered. If
193 * you specify any bulk actions, the bulk actions box will be rendered with
194 * the table automatically on display().
195 *
196 * Also note that list tables are not automatically wrapped in <form> elements,
197 * so you will need to create those manually in order for bulk actions to function.
198 *
199 * @return array An associative array containing all the bulk actions: 'slugs'=>'Visible Titles'
200 **************************************************************************/
201 function get_bulk_actions() {
202 $bulk_actions = [];
203 if( $this->get_filter_by_status_var() ) {
204 $bulk_actions['approve'] = __( 'Approve', 'wpforo' );
205 } else {
206 $bulk_actions['unapprove'] = __( 'Unapprove', 'wpforo' );
207 }
208 $bulk_actions['delete'] = __( 'Delete', 'wpforo' );
209
210 return $bulk_actions;
211 }
212
213
214 /** ************************************************************************
215 * REQUIRED! This is where you prepare your data for display. This method will
216 * usually be used to query the database, sort and filter the data, and generally
217 * get it ready to be displayed. At a minimum, we should set $this->items and
218 * $this->set_pagination_args(), although the following properties and methods
219 * are frequently interacted with here...
220 *
221 * @uses $this->_column_headers
222 * @uses $this->items
223 * @uses $this->get_columns()
224 * @uses $this->get_sortable_columns()
225 * @uses $this->get_pagenum()
226 * @uses $this->set_pagination_args()
227 **************************************************************************/
228 function prepare_items() {
229 /**
230 * First, lets decide how many records per page to show
231 */
232 $per_page = wpforo_get_option( 'count_per_page', 10 );
233
234
235 /**
236 * REQUIRED. Now we need to define our column headers. This includes a complete
237 * array of columns to be displayed (slugs & titles), a list of columns
238 * to keep hidden, and a list of columns that are sortable. Each of these
239 * can be defined in another method (as we've done here) before being
240 * used to build the value for our _column_headers property.
241 */
242 $columns = $this->get_columns();
243 $hidden = [];
244 $sortable = $this->get_sortable_columns();
245
246
247 /**
248 * REQUIRED. Finally, we build an array to be used by the class for column
249 * headers. The $this->_column_headers property takes an array which contains
250 * 3 other arrays. One for all columns, one for hidden columns, and one
251 * for sortable columns.
252 */
253 $this->_column_headers = [ $columns, $hidden, $sortable ];
254
255 /**
256 * REQUIRED. Now we can add our *sorted* data to the items' property, where
257 * it can be used by the rest of the class.
258 */
259 $args = [ 'check_private' => false, 'status' => $this->get_filter_by_status_var(), 'orderby' => '`created` DESC, `postid` DESC' ];
260 if( $s = wpfval( $_REQUEST, 's' ) ) {
261 $args['include'] = WPF()->moderation->search( $s );
262 }
263 $filter_by_userid = $this->get_filter_by_userid_var();
264 $orderby = wpfval( $_REQUEST, 'orderby' );
265 $order = strtoupper( (string) wpfval( $_REQUEST, 'order' ) );
266 if( $filter_by_userid !== - 1 ) $args['userid'] = $filter_by_userid;
267
268 if( $type = $this->get_filter_by_type_var() ){
269 $args['is_first_post'] = $type === 'topic';
270 }
271
272 if( array_key_exists( $orderby, $sortable ) ) $args['orderby'] = sanitize_text_field( $orderby );
273 if( in_array( $order, [ 'ASC', 'DESC' ] ) ) $args['order'] = sanitize_text_field( $order );
274
275 $paged = $this->get_pagenum();
276 $args['offset'] = ( $paged - 1 ) * $per_page;
277 $args['row_count'] = $per_page;
278
279 $items_count = 0;
280 $this->items = ( isset( $args['include'] ) && empty( $args['include'] ) ? [] : WPF()->post->get_posts( $args, $items_count ) );
281
282 $this->wpfitems_count = $items_count;
283
284 $this->set_pagination_args( [
285 'total_items' => $items_count, //WE have to calculate the total number of items
286 'per_page' => $per_page, //WE have to determine how many items to show on a page
287 'total_pages' => ceil( $items_count / $per_page ) //WE have to calculate the total number of pages
288 ] );
289 }
290
291 public function get_filter_by_status_var() {
292 $filter_by_status = wpfval( $_REQUEST, 'filter_by_status' );
293 if( ! is_null( $filter_by_status ) && $filter_by_status !== '-1' ) {
294 $status = intval( $filter_by_status );
295 } else {
296 $status = 1;
297 }
298
299 return $status;
300 }
301
302 public function get_filter_by_type_var() {
303 $filter_by_type = wpfval( $_REQUEST, 'filter_by_type' );
304
305 return in_array( $filter_by_type, [ 'topic', 'reply' ], true ) ? $filter_by_type : '';
306 }
307
308 public function get_filter_by_userid_var() {
309 $filter_by_userid = wpfval( $_REQUEST, 'filter_by_userid' );
310 if( ! is_null( $filter_by_userid ) && $filter_by_userid !== '-1' ) {
311 $userid = wpforo_bigintval( $filter_by_userid );
312 } else {
313 $userid = - 1;
314 }
315
316 return $userid;
317 }
318
319 public function users_dropdown() {
320 ?>
321 <label>
322 <select name="filter_by_userid">
323 <option value="-1">-- <?php _e( 'All Users', 'wpforo' ); ?> --</option>
324
325 <?php
326 if( $userids = WPF()->moderation->get_distinct_userids( $this->get_filter_by_status_var() ) ) {
327 $current_userid = $this->get_filter_by_userid_var();
328 foreach( $userids as $userid ) {
329 $userid = wpforo_bigintval( $userid );
330 $userdata = get_userdata( $userid );
331 ?>
332 <option value="<?php echo $userid ?>" <?php echo( $current_userid === $userid ? 'selected' : '' ) ?> > <?php echo( ! empty( $userdata->user_nicename ) ? urldecode( $userdata->user_nicename ) : $userid ) ?> </option>
333 <?php
334 }
335 }
336 ?>
337 </select>
338 </label>
339 <?php
340 }
341
342 public function status_dropdown() {
343 $filter_by_status = $this->get_filter_by_status_var();
344 if( $statuses = WPF()->moderation->post_statuses ) : ?>
345 <label>
346 <select name="filter_by_status">
347 <?php foreach( $statuses as $key => $status ) : ?>
348 <option value="<?php echo esc_attr( $key ) ?>" <?php echo( $filter_by_status === $key ? 'selected' : '' ) ?>><?php echo esc_html( $status ) ?></option>
349 <?php endforeach; ?>
350 </select>
351 </label>
352 <?php
353 endif;
354 }
355
356 public function type_dropdown() {
357 $filter_by_type = $this->get_filter_by_type_var();
358 ?>
359 <label>
360 <select name="filter_by_type">
361 <option value="">-- <?php _e('All', 'wpforo') ?> --</option>
362 <option value="topic" <?php echo( $filter_by_type === 'topic' ? 'selected' : '' ) ?>><?php _e('Topic', 'wpforo') ?></option>
363 <option value="reply" <?php echo( $filter_by_type === 'reply' ? 'selected' : '' ) ?>><?php _e('Reply', 'wpforo') ?></option>
364 </select>
365 </label>
366 <?php
367 }
368 }
369