PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
← All changes | inc/custom-post-types/quiz.php +179 -161 4.2.04.4.8 View file →
@@ -6,8 +6,14 @@
6 6 * @package LearnPress/Classes
7 7 * @version 4.0.0
8 8 */
9 9
10 +use LearnPress\Databases\PostDB;
11 +use LearnPress\Filters\QuizPostFilter;
12 +use LearnPress\Models\PostModel;
13 +use LearnPress\Models\QuizPostModel;
14 +use LearnPress\Models\WPTables\QuizzesTable;
15 +
10 16 defined( 'ABSPATH' ) || exit();
11 17
12 18 if ( ! class_exists( 'LP_Quiz_Post_Type' ) ) {
13 19
@@ -31,8 +37,13 @@
31 37 */
32 38 protected $_post_type = LP_QUIZ_CPT;
33 39
34 40 /**
41 + * @var string
42 + */
43 + protected $_screen_list = 'edit-' . LP_QUIZ_CPT;
44 +
45 + /**
35 46 * LP_Quiz_Post_Type constructor.
36 47 *
37 48 * @param $post_type
38 49 * @param mixed
@@ -43,14 +54,32 @@
43 54
44 55 add_action( 'learn-press/admin/after-enqueue-scripts', array( $this, 'data_quiz_editor' ) );
45 56
46 57 add_filter( 'views_edit-' . LP_QUIZ_CPT, array( $this, 'views_pages' ), 10 );
47 - add_filter( 'posts_where_paged', array( $this, 'posts_where_paged' ), 10 );
58 + add_action( 'posts_pre_query', array( $this, 'posts_pre_query' ), 999, 2 );
59 + // add_filter( 'posts_where_paged', array( $this, 'posts_where_paged' ), 10 );
48 60
49 61 parent::__construct();
50 62 }
51 63
52 64 /**
65 + * Declare class name of table list quizzes.
66 + *
67 + * @param string $class_name
68 + * @param array $args
69 + *
70 + * @return string
71 + * @since 4.2.9.5
72 + */
73 + public function wp_list_table_class_name( $class_name, $args ) {
74 + if ( $this->check_class_name_handle_table( $args['screen'] ) ) {
75 + $class_name = QuizzesTable::class;
76 + }
77 +
78 + return $class_name;
79 + }
80 +
81 + /**
53 82 * Add filters to lesson view.
54 83 *
55 84 * @since 3.0.0
56 85 *
@@ -80,9 +109,9 @@
80 109 public function args_register_post_type(): array {
81 110 $args = apply_filters(
82 111 'lp_quiz_post_type_args',
83 112 array(
84 - 'labels' => array(
113 + 'labels' => array(
85 114 'name' => esc_html__( 'Quizzes', 'learnpress' ),
86 115 'menu_name' => esc_html__( 'Quizzes', 'learnpress' ),
87 116 'singular_name' => esc_html__( 'Quiz', 'learnpress' ),
88 117 'add_new_item' => esc_html__( 'Add A New Quiz', 'learnpress' ),
@@ -94,29 +123,30 @@
94 123 'search_items' => esc_html__( 'Search Quizzes', 'learnpress' ),
95 124 'not_found' => sprintf( __( 'You haven\'t had any quizzes yet. Click <a href="%s">Add new</a> to start', 'learnpress' ), admin_url( 'post-new.php?post_type=lp_quiz' ) ),
96 125 'not_found_in_trash' => esc_html__( 'There was no quiz found in the trash', 'learnpress' ),
97 126 ),
98 - 'public' => true,
99 - 'publicly_queryable' => true,
100 - 'show_ui' => true,
101 - 'has_archive' => false,
102 - 'capability_type' => LP_LESSON_CPT,
103 - 'map_meta_cap' => true,
104 - 'show_in_menu' => 'learn_press',
105 - 'show_in_rest' => true,
106 - 'show_in_admin_bar' => true,
107 - 'show_in_nav_menus' => true,
108 - 'supports' => array(
127 + 'public' => true,
128 + 'publicly_queryable' => true,
129 + 'show_ui' => true,
130 + 'has_archive' => false,
131 + 'capability_type' => LP_LESSON_CPT,
132 + 'map_meta_cap' => true,
133 + 'show_in_menu' => 'learn_press',
134 + 'show_in_rest' => true,
135 + 'show_in_admin_bar' => true,
136 + 'show_in_nav_menus' => true,
137 + 'supports' => array(
109 138 'title',
110 139 'editor',
111 140 'revisions',
112 141 ),
113 - 'hierarchical' => true,
114 - 'rewrite' => array(
142 + 'hierarchical' => false, // Quizzes have no parent-child hierarchy.
143 + 'rewrite' => array(
115 144 'slug' => 'quizzes',
116 145 'hierarchical' => true,
117 146 'with_front' => false,
118 147 ),
148 + 'exclude_from_search' => true,
119 149 )
120 150 );
121 151
122 152 return $args;
@@ -209,137 +239,145 @@
209 239 /**
210 240 * Admin editor
211 241 *
212 242 * @since 3.3.0
213 - *
214 - * @return bool|string
243 + * @version 1.0.1
244 + * @return void
215 245 */
216 246 public function admin_editor() {
217 - $quiz = LP_Quiz::get_quiz();
247 + global $post;
218 248
219 - echo learn_press_admin_view_content( 'quiz/editor' );
249 + $quiz_id = $post->ID;
250 + $quizPostModel = QuizPostModel::find( $quiz_id, true );
251 + if ( ! $quizPostModel instanceof QuizPostModel ) {
252 + return;
253 + }
254 +
255 + do_action( 'learn-press/admin/edit-quiz/layout', $quizPostModel );
220 256 }
221 257
222 258 /**
223 - * Add columns to admin manage quiz page
259 + * Query lp quizzes in admin via Post DB
224 260 *
225 - * @param array $columns
261 + * @param array $posts
262 + * @param WP_Query $wp_query
226 263 *
227 - * @return array
264 + * @return array|WP_Query
265 + * @since 4.4.8
266 + * @version 1.0.0
228 267 */
229 - public function columns_head( $columns ) {
230 - $pos = array_search( 'title', array_keys( $columns ) );
268 + public function posts_pre_query( $posts, $wp_query ) {
269 + try {
270 + if ( ! is_admin() ) {
271 + return $posts;
272 + }
231 273
232 - if ( false !== $pos && ! array_key_exists( LP_COURSE_CPT, $columns ) ) {
233 - $columns = array_merge(
234 - array_slice( $columns, 0, $pos + 1 ),
235 - array(
236 - 'instructor' => esc_html__( 'Author', 'learnpress' ),
237 - LP_COURSE_CPT => esc_html__( 'Course', 'learnpress' ),
238 - 'num_of_question' => esc_html__( 'Questions', 'learnpress' ),
239 - 'duration' => esc_html__( 'Duration', 'learnpress' ),
240 - ),
241 - array_slice( $columns, $pos + 1 )
242 - );
243 - }
274 + // Check screen
275 + $curren_screen = get_current_screen();
276 + if ( ! $curren_screen || $curren_screen->id !== 'edit-' . LP_QUIZ_CPT ) {
277 + return $posts;
278 + }
244 279
245 - unset( $columns['taxonomy-lesson-tag'] );
246 - $user = wp_get_current_user();
280 + $post_type = $wp_query->get( 'post_type' );
247 281
248 - if ( in_array( 'lp_teacher', $user->roles ) ) {
249 - unset( $columns['instructor'] );
250 - }
282 + if ( empty( $post_type ) || $post_type !== LP_QUIZ_CPT ) {
283 + return $posts;
284 + }
251 285
252 - if ( ! empty( $columns['author'] ) ) {
253 - unset( $columns['author'] );
254 - }
286 + $posts_per_page = get_user_option( "edit_{$post_type}_per_page", get_current_user_id() );
287 + if ( empty( $posts_per_page ) ) {
288 + $posts_per_page = 20;
289 + }
255 290
256 - return $columns;
257 - }
291 + $paged = max( 1, get_query_var( 'paged' ) );
292 + $author = $wp_query->get( 'author' );
293 + $status = $wp_query->get( 'post_status' );
294 + $search = $wp_query->get( 's' );
295 + $month = $wp_query->get( 'm' );
296 + $orderby = LP_Request::get_param( 'orderby', '', 'key' );
297 + $order = LP_Request::get_param( 'order', '', 'key' );
258 298
259 - /**
260 - * Display content for custom column
261 - *
262 - * @param string $name
263 - * @param int $post_id
264 - */
265 - public function columns_content( $name, $post_id = 0 ) {
266 - global $post;
299 + $filter = new QuizPostFilter();
300 + $filter->only_fields = [ 'p.ID', 'p.post_title', 'p.post_author', 'p.post_date', 'p.post_date_gmt' ];
301 + $filter->field_count = 'p.ID';
302 + $filter->page = $paged;
303 + $filter->limit = $posts_per_page;
304 + $post_db = PostDB::getInstance();
267 305
268 - switch ( $name ) {
269 - case 'instructor':
270 - $this->column_instructor( $post_id );
271 - break;
272 - case 'lp_course':
273 - $this->_get_item_course( $post_id );
274 - break;
275 - case 'num_of_question':
276 - if ( property_exists( $post, 'question_count' ) ) {
277 - $count = $post->question_count;
278 - } else {
279 - $quiz = LP_Quiz::get_quiz( $post_id );
280 - $count = $quiz->count_questions();
281 - }
306 + if ( ! empty( $status ) ) {
307 + $filter->post_status = array( $status );
308 + }
282 309
283 - printf(
284 - '<span class="lp-label-counter' . ( ! $count ? ' disabled' : '' ) . '" title="%s">%s</span>',
285 - ( $count ) ? sprintf( _n( '%d question', '%d questions', $count, 'learnpress' ), $count ) : __( 'This quiz has no questions', 'learnpress' ),
286 - $count
310 + if ( ! empty( $author ) ) {
311 + $filter->post_author = absint( $author );
312 + }
313 +
314 + if ( ! empty( $search ) ) {
315 + $filter->post_title = sanitize_text_field( wp_unslash( $search ) );
316 + }
317 +
318 + if ( ! empty( $month ) && is_numeric( $month ) && strlen( (string) $month ) === 6 ) {
319 + $filter->where[] = $post_db->wpdb->prepare(
320 + 'AND YEAR(p.post_date) = %d AND MONTH(p.post_date) = %d',
321 + substr( $month, 0, 4 ),
322 + substr( $month, 4, 2 )
287 323 );
288 - break;
289 - case 'duration':
290 - $duration_str = get_post_meta( $post_id, '_lp_duration', true );
291 - $duration = (int) $duration_str;
324 + }
292 325
293 - if ( $duration > 0 ) {
294 - $duration_str .= 's';
295 - $duration_str_arr = explode( ' ', $duration_str );
296 - $type_time = '';
326 + // Exclude status auto-draft
327 + $filter->where[] = $post_db->wpdb->prepare( 'AND p.post_status != %s', PostModel::STATUS_AUTO_DRAFT );
297 328
298 - if ( is_array( $duration_str_arr ) && ! empty( $duration_str_arr ) && count( $duration_str_arr ) >= 2 ) {
299 - switch ( $duration_str_arr[1] ) {
300 - case 'hours':
301 - $type_time = __( 'hours', 'learnpress' );
302 - break;
303 - case 'minutes':
304 - $type_time = __( 'minutes', 'learnpress' );
305 - break;
306 - case 'days':
307 - $type_time = __( 'days', 'learnpress' );
308 - break;
309 - case 'weeks':
310 - $type_time = __( 'weeks', 'learnpress' );
311 - break;
312 - }
329 + // Add question count field
330 + $filter->only_fields[] = "(SELECT COUNT(*) FROM {$post_db->tb_lp_quiz_questions} qq_count
331 + WHERE qq_count.quiz_id = p.ID) AS question_count";
313 332
314 - $duration_str = sprintf( '%1$s %2$s', $duration_str_arr[0], $type_time );
315 - }
316 - } else {
317 - $duration_str = '--';
318 - }
333 + // Join sections/courses when sorting by course-name
334 + if ( $orderby === 'course-name' ) {
335 + $filter->join[] = "LEFT JOIN {$post_db->wpdb->prefix}learnpress_section_items si ON p.ID = si.item_id";
336 + $filter->join[] = "LEFT JOIN {$post_db->wpdb->prefix}learnpress_sections s ON s.section_id = si.section_id";
337 + $filter->join[] = "LEFT JOIN {$post_db->wpdb->posts} c ON c.ID = s.section_course_id";
338 + }
319 339
320 - echo esc_html( $duration_str );
321 - break;
322 - case 'preview':
323 - printf(
324 - '<input type="checkbox" class="learn-press-checkbox learn-press-toggle-item-preview" %s value="%s" data-nonce="%s" />',
325 - get_post_meta( $post_id, '_lp_preview', true ) == 'yes' ? ' checked="checked"' : '',
326 - $post_id,
327 - wp_create_nonce( 'learn-press-toggle-item-preview' )
328 - );
329 - break;
330 - default:
331 - break;
340 + // Filter unassigned
341 + if ( 'yes' === LP_Request::get_param( 'unassigned', '', 'key' ) ) {
342 + $filter->where[] = "AND p.ID NOT IN(
343 + SELECT si.item_id
344 + FROM {$post_db->wpdb->learnpress_section_items} si
345 + )";
346 + }
332 347
348 + if ( $orderby === 'course-name' ) {
349 + $filter->order_by = 'c.post_title';
350 + } elseif ( $orderby === 'question-count' ) {
351 + $filter->order_by = 'question_count';
352 + } elseif ( $orderby === 'title' ) {
353 + $filter->order_by = 'p.post_title';
354 + } elseif ( $orderby === 'author' ) {
355 + $filter->order_by = 'p.post_author';
356 + } elseif ( $orderby === 'date' ) {
357 + $filter->order_by = 'p.post_date';
358 + } else {
359 + $filter->order_by = 'p.menu_order';
360 + }
361 +
362 + $filter->order = strtolower( $order ) === 'asc' ? 'ASC' : 'DESC';
363 +
364 + // Get lp quizzes
365 + $total_rows = 0;
366 + $lp_quizzes = $post_db->get_posts( $filter, $total_rows );
367 +
368 + $wp_query->post_count = count( $lp_quizzes );
369 + $wp_query->found_posts = $total_rows;
370 + $wp_query->max_num_pages = (int) ceil( $total_rows / $posts_per_page );
371 + $posts = $lp_quizzes;
372 + } catch ( Throwable $e ) {
373 + LP_Debug::error_log( $e );
333 374 }
375 +
376 + return $posts;
334 377 }
335 378
336 - /**
337 - * @param $fields
338 - *
339 - * @return string
340 - */
341 - public function posts_fields( $fields ): string {
379 + /*public function posts_fields( $fields ): string {
342 380 global $wpdb;
343 381
344 382 if ( ! $this->is_page_list_posts_on_backend() ) {
345 383 return $fields;
@@ -353,13 +391,8 @@
353 391
354 392 return $fields;
355 393 }
356 394
357 - /**
358 - * @param $join
359 - *
360 - * @return string
361 - */
362 395 public function posts_join_paged( $join ): string {
363 396 if ( ! $this->is_page_list_posts_on_backend() ) {
364 397 return $join;
365 398 }
@@ -366,13 +399,8 @@
366 399
367 400 return $join;
368 401 }
369 402
370 - /**
371 - * @param $where
372 - *
373 - * @return mixed|string
374 - */
375 403 public function posts_where_paged( $where ) {
376 404 if ( ! $this->is_page_list_posts_on_backend() ) {
377 405 return $where;
378 406 }
@@ -381,15 +409,15 @@
381 409
382 410 if ( 'yes' === LP_Request::get( 'unassigned' ) ) {
383 411 $where .= $wpdb->prepare(
384 412 "
385 - AND {$wpdb->posts}.ID NOT IN(
386 - SELECT si.item_id
387 - FROM {$wpdb->learnpress_section_items} si
388 - INNER JOIN {$wpdb->posts} p ON p.ID = si.item_id
389 - WHERE p.post_type = %s
390 - )
391 - ",
413 + AND {$wpdb->posts}.ID NOT IN(
414 + SELECT si.item_id
415 + FROM {$wpdb->learnpress_section_items} si
416 + INNER JOIN {$wpdb->posts} p ON p.ID = si.item_id
417 + WHERE p.post_type = %s
418 + )
419 + ",
392 420 LP_QUIZ_CPT
393 421 );
394 422 }
395 423
@@ -395,13 +423,8 @@
395 423
396 424 return $where;
397 425 }
398 426
399 - /**
400 - * @param $order_by_statement
401 - *
402 - * @return string
403 - */
404 427 public function posts_orderby( $order_by_statement ) {
405 428 global $wpdb;
406 429
407 430 if ( ! $this->is_page_list_posts_on_backend() ) {
@@ -424,30 +447,17 @@
424 447 }
425 448 }
426 449
427 450 return $order_by_statement;
428 - }
451 + }*/
429 452
430 453 /**
431 - * @param $columns
432 - *
433 - * @return mixed
434 - */
435 - public function sortable_columns( $columns ) {
436 - $columns['instructor'] = 'author';
437 - $columns[ LP_COURSE_CPT ] = 'course-name';
438 - $columns['num_of_question'] = 'question-count';
439 -
440 - return $columns;
441 - }
442 -
443 - /**
444 454 * Quiz assigned view.
445 455 *
446 456 * @since 3.0.0
447 457 */
448 458 // public static function quiz_assigned() {
449 - // learn_press_admin_view( 'meta-boxes/course/assigned.php' );
459 + // learn_press_admin_view( 'meta-boxes/course/assigned.php' );
450 460 // }
451 461
452 462 public function meta_boxes() {
453 463 return array(
@@ -452,9 +462,9 @@
452 462 public function meta_boxes() {
453 463 return array(
454 464 'quiz_assigned' => array(
455 465 'title' => esc_html__( 'Assigned', 'learnpress' ),
456 - 'callback' => function( $post ) {
466 + 'callback' => function ( $post ) {
457 467 learn_press_admin_view( 'meta-boxes/course/assigned.php' );
458 468 },
459 469 'context' => 'side',
460 470 'priority' => 'high',
@@ -479,18 +489,26 @@
479 489 return self::$_instance;
480 490 }
481 491
482 492 /**
483 - * Save Post type Quiz
493 + * Handle when save post.
484 494 *
485 - * @author tungnx
495 + * @param int $post_id
496 + * @param WP_Post|null $post
497 + * @param bool $is_update
498 + *
499 + * @return void
500 + * @since 4.2.7.6
486 501 * @version 1.0.0
487 - * @since 4.0.0
488 502 */
489 - public function save( int $post_id, WP_Post $post ) {
490 - $lp_quiz_cache = LP_Quiz_Cache::instance();
503 + public function save_post( int $post_id = 0, ?WP_Post $post = null, bool $is_update = false ) {
504 + // Clear cache get quiz by id
505 + $lpCache = new LP_Cache();
506 + $lpCache->clear( "quizPostModel/find/{$post_id}" );
507 + $lpCache->clear( "quizModel/find/{$post_id}" );
491 508
492 509 // Clear cache get question_ids of quiz
510 + $lp_quiz_cache = LP_Quiz_Cache::instance();
493 511 $lp_quiz_cache->clear( "$post_id/question_ids" );
494 512 }
495 513 }
496 514