This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
0 ignored issues
–
show
|
|||
2 | if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly |
||
3 | |||
4 | /** |
||
5 | * Admin Grading Overview Data Table in Sensei. |
||
6 | * |
||
7 | * @package Assessment |
||
8 | * @author Automattic |
||
9 | * @since 1.3.0 |
||
10 | */ |
||
11 | class Sensei_Grading_Main extends WooThemes_Sensei_List_Table { |
||
12 | |||
13 | public $user_id; |
||
14 | public $course_id; |
||
15 | public $lesson_id; |
||
16 | public $view; |
||
17 | public $user_ids = false; |
||
18 | public $page_slug = 'sensei_grading'; |
||
19 | |||
20 | /** |
||
21 | * Constructor |
||
22 | * @since 1.3.0 |
||
23 | */ |
||
24 | public function __construct ( $args = null ) { |
||
25 | |||
26 | $defaults = array( |
||
27 | 'course_id' => 0, |
||
28 | 'lesson_id' => 0, |
||
29 | 'user_id' => false, |
||
30 | 'view' => 'ungraded', |
||
31 | ); |
||
32 | $args = wp_parse_args( $args, $defaults ); |
||
33 | |||
34 | $this->course_id = intval( $args['course_id'] ); |
||
35 | $this->lesson_id = intval( $args['lesson_id'] ); |
||
36 | if ( !empty($args['user_id']) ) { |
||
37 | $this->user_id = intval( $args['user_id'] ); |
||
38 | } |
||
39 | |||
40 | if( !empty( $args['view'] ) && in_array( $args['view'], array( 'in-progress', 'graded', 'ungraded', 'all' ) ) ) { |
||
41 | $this->view = $args['view']; |
||
42 | } |
||
43 | |||
44 | // Load Parent token into constructor |
||
45 | parent::__construct( 'grading_main' ); |
||
46 | |||
47 | // Actions |
||
48 | add_action( 'sensei_before_list_table', array( $this, 'data_table_header' ) ); |
||
49 | add_action( 'sensei_after_list_table', array( $this, 'data_table_footer' ) ); |
||
50 | } // End __construct() |
||
51 | |||
52 | /** |
||
53 | * Define the columns that are going to be used in the table |
||
54 | * @since 1.7.0 |
||
55 | * @return array $columns, the array of columns to use with the table |
||
56 | */ |
||
57 | function get_columns() { |
||
58 | $columns = array( |
||
59 | 'title' => __( 'Learner', 'woothemes-sensei' ), |
||
60 | 'course' => __( 'Course', 'woothemes-sensei' ), |
||
61 | 'lesson' => __( 'Lesson', 'woothemes-sensei' ), |
||
62 | 'updated' => __( 'Updated', 'woothemes-sensei' ), |
||
63 | 'user_status' => __( 'Status', 'woothemes-sensei' ), |
||
64 | 'user_grade' => __( 'Grade', 'woothemes-sensei' ), |
||
65 | 'action' => '', |
||
66 | ); |
||
67 | |||
68 | $columns = apply_filters( 'sensei_grading_default_columns', $columns, $this ); |
||
69 | return $columns; |
||
70 | } |
||
71 | |||
72 | /** |
||
73 | * Define the columns that are going to be used in the table |
||
74 | * @since 1.7.0 |
||
75 | * @return array $columns, the array of columns to use with the table |
||
76 | */ |
||
77 | function get_sortable_columns() { |
||
78 | $columns = array( |
||
79 | 'title' => array( 'title', false ), |
||
80 | 'course' => array( 'course', false ), |
||
81 | 'lesson' => array( 'lesson', false ), |
||
82 | 'updated' => array( 'updated', false ), |
||
83 | 'user_status' => array( 'user_status', false ), |
||
84 | 'user_grade' => array( 'user_grade', false ), |
||
85 | ); |
||
86 | $columns = apply_filters( 'sensei_grading_default_columns_sortable', $columns, $this ); |
||
87 | return $columns; |
||
88 | } |
||
89 | |||
90 | /** |
||
91 | * Prepare the table with different parameters, pagination, columns and table elements |
||
92 | * @since 1.7.0 |
||
93 | * @return void |
||
94 | */ |
||
95 | public function prepare_items() { |
||
96 | global $per_page, $wp_version; |
||
97 | |||
98 | // Handle orderby |
||
99 | $orderby = ''; |
||
100 | if ( !empty( $_GET['orderby'] ) ) { |
||
101 | if ( array_key_exists( esc_html( $_GET['orderby'] ), $this->get_sortable_columns() ) ) { |
||
102 | $orderby = esc_html( $_GET['orderby'] ); |
||
103 | } // End If Statement |
||
104 | } |
||
105 | |||
106 | // Handle order |
||
107 | $order = 'DESC'; |
||
108 | if ( !empty( $_GET['order'] ) ) { |
||
109 | $order = ( 'ASC' == strtoupper($_GET['order']) ) ? 'ASC' : 'DESC'; |
||
110 | } |
||
111 | |||
112 | // Handle search |
||
113 | $search = false; |
||
114 | if ( !empty( $_GET['s'] ) ) { |
||
115 | $search = esc_html( $_GET['s'] ); |
||
116 | } // End If Statement |
||
117 | $this->search = $search; |
||
118 | |||
119 | // Searching users on statuses requires sub-selecting the statuses by user_ids |
||
120 | if ( $this->search ) { |
||
121 | $user_args = array( |
||
122 | 'search' => '*' . $this->search . '*', |
||
123 | 'fields' => 'ID', |
||
124 | ); |
||
125 | // Filter for extending |
||
126 | $user_args = apply_filters( 'sensei_grading_search_users', $user_args ); |
||
127 | if ( !empty( $user_args ) ) { |
||
128 | $learners_search = new WP_User_Query( $user_args ); |
||
129 | // Store for reuse on counts |
||
130 | $this->user_ids = $learners_search->get_results(); |
||
131 | } |
||
132 | } // End If Statement |
||
133 | |||
134 | $per_page = $this->get_items_per_page( 'sensei_comments_per_page' ); |
||
135 | $per_page = apply_filters( 'sensei_comments_per_page', $per_page, 'sensei_comments' ); |
||
136 | |||
137 | $paged = $this->get_pagenum(); |
||
138 | $offset = 0; |
||
139 | if ( !empty($paged) ) { |
||
140 | $offset = $per_page * ( $paged - 1 ); |
||
141 | } // End If Statement |
||
142 | |||
143 | $activity_args = array( |
||
144 | 'type' => 'sensei_lesson_status', |
||
145 | 'number' => $per_page, |
||
146 | 'offset' => $offset, |
||
147 | 'orderby' => $orderby, |
||
148 | 'order' => $order, |
||
149 | 'status' => 'any', |
||
150 | ); |
||
151 | |||
152 | View Code Duplication | if( $this->lesson_id ) { |
|
153 | $activity_args['post_id'] = $this->lesson_id; |
||
154 | } |
||
155 | elseif( $this->course_id ) { |
||
156 | // Currently not possible to restrict to a single Course, as that requires WP_Comment to support multiple |
||
157 | // post_ids (i.e. every lesson within the Course), WP 4.1 ( https://core.trac.wordpress.org/changeset/29808 ) |
||
158 | if ( version_compare($wp_version, '4.1', '>=') ) { |
||
159 | $activity_args['post__in'] = Sensei()->course->course_lessons( $this->course_id, 'any', 'ids' ); |
||
160 | } |
||
161 | } |
||
162 | // Sub select to group of learners |
||
163 | if ( $this->user_ids ) { |
||
164 | $activity_args['user_id'] = (array) $this->user_ids; |
||
165 | } |
||
166 | // Restrict to a single Learner |
||
167 | if( $this->user_id ) { |
||
168 | $activity_args['user_id'] = $this->user_id; |
||
169 | } |
||
170 | |||
171 | |||
172 | switch( $this->view ) { |
||
173 | case 'in-progress' : |
||
174 | $activity_args['status'] = 'in-progress'; |
||
175 | break; |
||
176 | |||
177 | case 'ungraded' : |
||
178 | $activity_args['status'] = 'ungraded'; |
||
179 | break; |
||
180 | |||
181 | case 'graded' : |
||
182 | $activity_args['status'] = array( 'graded', 'passed', 'failed' ); |
||
183 | break; |
||
184 | |||
185 | case 'all' : |
||
186 | default: |
||
187 | $activity_args['status'] = 'any'; |
||
188 | break; |
||
189 | } // End switch |
||
190 | |||
191 | $activity_args = apply_filters( 'sensei_grading_filter_statuses', $activity_args ); |
||
192 | |||
193 | // WP_Comment_Query doesn't support SQL_CALC_FOUND_ROWS, so instead do this twice |
||
194 | $total_statuses = Sensei_Utils::sensei_check_for_activity( array_merge( $activity_args, array('count' => true, 'offset' => 0, 'number' => 0) ) ); |
||
195 | |||
196 | // Ensure we change our range to fit (in case a search threw off the pagination) - Should this be added to all views? |
||
197 | if ( $total_statuses < $activity_args['offset'] ) { |
||
198 | $new_paged = floor( $total_statuses / $activity_args['number'] ); |
||
199 | $activity_args['offset'] = $new_paged * $activity_args['number']; |
||
200 | } |
||
201 | $statuses = Sensei_Utils::sensei_check_for_activity( $activity_args, true ); |
||
202 | // Need to always return an array, even with only 1 item |
||
203 | if ( !is_array($statuses) ) { |
||
204 | $statuses = array( $statuses ); |
||
205 | } |
||
206 | $this->total_items = $total_statuses; |
||
207 | $this->items = $statuses; |
||
208 | |||
209 | $total_items = $this->total_items; |
||
210 | $total_pages = ceil( $total_items / $per_page ); |
||
211 | $this->set_pagination_args( array( |
||
212 | 'total_items' => $total_items, |
||
213 | 'total_pages' => $total_pages, |
||
214 | 'per_page' => $per_page |
||
215 | ) ); |
||
216 | } |
||
217 | |||
218 | /** |
||
219 | * Generates content for a single row of the table, overriding parent |
||
220 | * @since 1.7.0 |
||
221 | * @param object $item The current item |
||
222 | */ |
||
223 | protected function get_row_data( $item ) { |
||
224 | global $wp_version; |
||
225 | |||
226 | $grade = ''; |
||
227 | if( 'complete' == $item->comment_approved ) { |
||
228 | $status_html = '<span class="graded">' . __( 'Completed', 'woothemes-sensei' ) . '</span>'; |
||
229 | $grade = __( 'No Grade', 'woothemes-sensei' ); |
||
230 | } |
||
231 | elseif( 'graded' == $item->comment_approved ) { |
||
232 | $status_html = '<span class="graded">' . __( 'Graded', 'woothemes-sensei' ) . '</span>'; |
||
233 | $grade = get_comment_meta( $item->comment_ID, 'grade', true) . '%'; |
||
234 | } |
||
235 | elseif( 'passed' == $item->comment_approved ) { |
||
236 | $status_html = '<span class="passed">' . __( 'Passed', 'woothemes-sensei' ) . '</span>'; |
||
237 | $grade = get_comment_meta( $item->comment_ID, 'grade', true) . '%'; |
||
238 | } |
||
239 | elseif( 'failed' == $item->comment_approved ) { |
||
240 | $status_html = '<span class="failed">' . __( 'Failed', 'woothemes-sensei' ) . '</span>'; |
||
241 | $grade = get_comment_meta( $item->comment_ID, 'grade', true) . '%'; |
||
242 | } |
||
243 | View Code Duplication | elseif( 'ungraded' == $item->comment_approved ) { |
|
244 | $status_html = '<span class="ungraded">' . __( 'Ungraded', 'woothemes-sensei' ) . '</span>'; |
||
245 | $grade = __( 'N/A', 'woothemes-sensei' ); |
||
246 | } |
||
247 | View Code Duplication | else { |
|
248 | $status_html = '<span class="in-progress">' . __( 'In Progress', 'woothemes-sensei' ) . '</span>'; |
||
249 | $grade = __( 'N/A', 'woothemes-sensei' ); |
||
250 | } |
||
251 | |||
252 | $title = Sensei_Learner::get_full_name( $item->user_id ); |
||
253 | |||
254 | // QuizID to be deprecated |
||
255 | $quiz_id = get_post_meta( $item->comment_post_ID, '_lesson_quiz', true ); |
||
256 | $quiz_link = esc_url( add_query_arg( array( 'page' => $this->page_slug, 'user' => $item->user_id, 'quiz_id' => $quiz_id ), admin_url( 'admin.php' ) ) ); |
||
257 | |||
258 | $grade_link = ''; |
||
259 | switch( $item->comment_approved ) { |
||
260 | View Code Duplication | case 'ungraded': |
|
261 | $grade_link = '<a class="button-primary button" href="' . $quiz_link . '">' . __('Grade quiz', 'woothemes-sensei' ) . '</a>'; |
||
262 | break; |
||
263 | |||
264 | case 'graded': |
||
265 | case 'passed': |
||
266 | View Code Duplication | case 'failed': |
|
267 | $grade_link = '<a class="button-secondary button" href="' . $quiz_link . '">' . __('Review grade', 'woothemes-sensei' ) . '</a>'; |
||
268 | break; |
||
269 | } |
||
270 | |||
271 | $course_id = get_post_meta( $item->comment_post_ID, '_lesson_course', true ); |
||
272 | $course_title = ''; |
||
273 | if ( !empty($course_id) && version_compare($wp_version, '4.1', '>=') ) { |
||
274 | $course_title = '<a href="' . esc_url( add_query_arg( array( 'page' => $this->page_slug, 'course_id' => $course_id ), admin_url( 'admin.php' ) ) ) . '">' . get_the_title( $course_id ) . '</a>'; |
||
275 | } |
||
276 | else if ( !empty($course_id) ) { |
||
277 | $course_title = get_the_title( $course_id ); |
||
278 | } |
||
279 | $lesson_title = '<a href="' . add_query_arg( array( 'page' => $this->page_slug, 'lesson_id' => $item->comment_post_ID ), admin_url( 'admin.php' ) ) . '">' . get_the_title( $item->comment_post_ID ) . '</a>'; |
||
280 | |||
281 | $column_data = apply_filters( 'sensei_grading_main_column_data', array( |
||
282 | 'title' => '<strong><a class="row-title" href="' . esc_url( add_query_arg( array( 'page' => $this->page_slug, 'user_id' => $item->user_id ), admin_url( 'admin.php' ) ) ) . '"">' . $title . '</a></strong>', |
||
283 | 'course' => $course_title, |
||
284 | 'lesson' => $lesson_title, |
||
285 | 'updated' => $item->comment_date, |
||
286 | 'user_status' => $status_html, |
||
287 | 'user_grade' => $grade, |
||
288 | 'action' => $grade_link, |
||
289 | ), $item, $course_id ); |
||
290 | |||
291 | return $column_data; |
||
292 | } |
||
293 | |||
294 | /** |
||
295 | * Sets output when no items are found |
||
296 | * Overloads the parent method |
||
297 | * @since 1.3.0 |
||
298 | * @return void |
||
299 | */ |
||
300 | public function no_items() { |
||
301 | |||
302 | _e( 'No submissions found.', 'woothemes-sensei' ); |
||
303 | |||
304 | } // End no_items() |
||
305 | |||
306 | /** |
||
307 | * Output for table heading |
||
308 | * @since 1.3.0 |
||
309 | * @return void |
||
310 | */ |
||
311 | public function data_table_header() { |
||
312 | global $wp_version; |
||
313 | |||
314 | echo '<div class="grading-selects">'; |
||
315 | do_action( 'sensei_grading_before_dropdown_filters' ); |
||
316 | |||
317 | echo '<div class="select-box">' . "\n"; |
||
318 | |||
319 | echo '<select id="grading-course-options" name="grading_course" class="chosen_select widefat">' . "\n"; |
||
320 | |||
321 | echo Sensei()->grading->courses_drop_down_html( $this->course_id ); |
||
322 | |||
323 | echo '</select>' . "\n"; |
||
324 | |||
325 | echo '</div>' . "\n"; |
||
326 | |||
327 | echo '<div class="select-box">' . "\n"; |
||
328 | |||
329 | echo '<select id="grading-lesson-options" data-placeholder="← ' . __( 'Select a course', 'woothemes-sensei' ) . '" name="grading_lesson" class="chosen_select widefat">' . "\n"; |
||
330 | |||
331 | echo Sensei()->grading->lessons_drop_down_html( $this->course_id, $this->lesson_id ); |
||
332 | |||
333 | echo '</select>' . "\n"; |
||
334 | |||
335 | echo '</div>' . "\n"; |
||
336 | |||
337 | if( $this->course_id && $this->lesson_id ) { |
||
338 | |||
339 | echo '<div class="select-box reset-filter">' . "\n"; |
||
340 | |||
341 | echo '<a class="button-secondary" href="' . esc_url( remove_query_arg( array( 'lesson_id', 'course_id' ) ) ) . '">' . __( 'Reset filter', 'woothemes-sensei' ) . '</a>' . "\n"; |
||
342 | |||
343 | echo '</div>' . "\n"; |
||
344 | |||
345 | } |
||
346 | |||
347 | echo '</div><!-- /.grading-selects -->'; |
||
348 | |||
349 | $menu = array(); |
||
350 | |||
351 | // Setup counters |
||
352 | $count_args = array( |
||
353 | 'type' => 'lesson', |
||
354 | ); |
||
355 | $query_args = array( |
||
356 | 'page' => $this->page_slug, |
||
357 | ); |
||
358 | View Code Duplication | if( $this->course_id ) { |
|
359 | // Currently not possible to restrict to a single Course, as that requires WP_Comment to support multiple |
||
360 | // post_ids (i.e. every lesson within the Course), WP 4.1 ( https://core.trac.wordpress.org/changeset/29808 ) |
||
361 | $query_args['course_id'] = $this->course_id; |
||
362 | if ( version_compare($wp_version, '4.1', '>=') ) { |
||
363 | $count_args['post__in'] = Sensei()->course->course_lessons( $this->course_id, 'any', 'ids' ); |
||
364 | } |
||
365 | } |
||
366 | if( $this->lesson_id ) { |
||
367 | $query_args['lesson_id'] = $this->lesson_id; |
||
368 | // Restrict to a single lesson |
||
369 | $count_args['post_id'] = $this->lesson_id; |
||
370 | } |
||
371 | if( $this->search ) { |
||
372 | $query_args['s'] = $this->search; |
||
373 | } |
||
374 | if ( !empty($this->user_ids) ) { |
||
375 | $count_args['user_id'] = $this->user_ids; |
||
376 | } |
||
377 | if( !empty($this->user_id) ) { |
||
378 | $query_args['user_id'] = $this->user_id; |
||
379 | $count_args['user_id'] = $this->user_id; |
||
380 | } |
||
381 | |||
382 | $all_lessons_count = $ungraded_lessons_count = $graded_lessons_count = $inprogress_lessons_count = 0; |
||
383 | $all_class = $ungraded_class = $graded_class = $inprogress_class = ''; |
||
384 | |||
385 | switch( $this->view ) : |
||
386 | case 'all': |
||
387 | $all_class = 'current'; |
||
388 | break; |
||
389 | case 'ungraded' : |
||
390 | default: |
||
391 | $ungraded_class = 'current'; |
||
392 | break; |
||
393 | case 'graded' : |
||
394 | $graded_class = 'current'; |
||
395 | break; |
||
396 | case 'in-progress' : |
||
397 | $inprogress_class = 'current'; |
||
398 | break; |
||
399 | endswitch; |
||
400 | |||
401 | $counts = Sensei()->grading->count_statuses( apply_filters( 'sensei_grading_count_statues', $count_args ) ); |
||
402 | |||
403 | $inprogress_lessons_count = $counts['in-progress']; |
||
404 | $ungraded_lessons_count = $counts['ungraded']; |
||
405 | $graded_lessons_count = $counts['graded'] + $counts['passed'] + $counts['failed']; |
||
406 | $all_lessons_count = $counts['complete'] + $ungraded_lessons_count + $graded_lessons_count + $inprogress_lessons_count; |
||
407 | |||
408 | // Display counters and status links |
||
409 | $all_args = $ungraded_args = $graded_args = $inprogress_args = $query_args; |
||
410 | |||
411 | $all_args['view'] = 'all'; |
||
412 | $ungraded_args['view'] = 'ungraded'; |
||
413 | $graded_args['view'] = 'graded'; |
||
414 | $inprogress_args['view'] = 'in-progress'; |
||
415 | |||
416 | $format = '<a class="%s" href="%s">%s <span class="count">(%s)</span></a>'; |
||
417 | $menu['all'] = sprintf( $format, $all_class, esc_url( add_query_arg( $all_args, admin_url( 'admin.php' ) ) ), __( 'All', 'woothemes-sensei' ), number_format( (int) $all_lessons_count ) ); |
||
418 | $menu['ungraded'] = sprintf( $format, $ungraded_class, esc_url( add_query_arg( $ungraded_args, admin_url( 'admin.php' ) ) ), __( 'Ungraded', 'woothemes-sensei' ), number_format( (int) $ungraded_lessons_count ) ); |
||
419 | $menu['graded'] = sprintf( $format, $graded_class, esc_url( add_query_arg( $graded_args, admin_url( 'admin.php' ) ) ), __( 'Graded', 'woothemes-sensei' ), number_format( (int) $graded_lessons_count ) ); |
||
420 | $menu['in-progress'] = sprintf( $format, $inprogress_class, esc_url( add_query_arg( $inprogress_args, admin_url( 'admin.php' ) ) ), __( 'In Progress', 'woothemes-sensei' ), number_format( (int) $inprogress_lessons_count ) ); |
||
421 | |||
422 | $menu = apply_filters( 'sensei_grading_sub_menu', $menu ); |
||
423 | View Code Duplication | if ( !empty($menu) ) { |
|
424 | echo '<ul class="subsubsub">' . "\n"; |
||
425 | foreach ( $menu as $class => $item ) { |
||
426 | $menu[ $class ] = "\t<li class='$class'>$item"; |
||
427 | } |
||
428 | echo implode( " |</li>\n", $menu ) . "</li>\n"; |
||
429 | echo '</ul>' . "\n"; |
||
430 | } |
||
431 | |||
432 | } // End data_table_header() |
||
433 | |||
434 | /** |
||
435 | * Output for table footer |
||
436 | * @since 1.3.0 |
||
437 | * @return void |
||
438 | */ |
||
439 | public function data_table_footer() { |
||
440 | // Nothing right now |
||
441 | } // End data_table_footer() |
||
442 | |||
443 | } // End Class |
||
444 | |||
445 | /** |
||
446 | * Class WooThems_Sensei_Grading_Main |
||
447 | * @ignore only for backward compatibility |
||
448 | * @since 1.9.0 |
||
449 | */ |
||
450 | class WooThemes_Sensei_Grading_Main extends Sensei_Grading_Main{} |
||
451 |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.