PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.9
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.9
4.4.9 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 All 140 releases
← All changes | inc/custom-post-types/quiz.php +191 -169 4.1.6.9 → 4.4.9 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,13 +109,13 @@
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 - 'add_new_item' => esc_html__( 'Add New Quiz', 'learnpress' ),
117 + 'add_new_item' => esc_html__( 'Add A New Quiz', 'learnpress' ),
89 118 'edit_item' => esc_html__( 'Edit Quiz', 'learnpress' ),
90 119 'all_items' => esc_html__( 'Quizzes', 'learnpress' ),
91 120 'view_item' => esc_html__( 'View Quiz', 'learnpress' ),
92 121 'add_new' => esc_html__( 'New Quiz', 'learnpress' ),
@@ -92,31 +121,32 @@
92 121 'add_new' => esc_html__( 'New Quiz', 'learnpress' ),
93 122 'update_item' => esc_html__( 'Update Quiz', 'learnpress' ),
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 - 'not_found_in_trash' => esc_html__( 'No quiz found in Trash', 'learnpress' ),
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;
@@ -168,14 +198,14 @@
168 198 'unique' => learn_press_uniqid(),
169 199 'back' => esc_html__( 'Back', 'learnpress' ),
170 200 'selected_items' => esc_html__( 'Selected items', 'learnpress' ),
171 201 'new_option' => esc_html__( 'New Option', 'learnpress' ),
172 - 'confirm_trash_question' => esc_html__( 'Do you want to move question "{{QUESTION_NAME}}" to trash?', 'learnpress' ),
202 + 'confirm_trash_question' => esc_html__( 'Do you want to move the "{{QUESTION_NAME}}" question to the trash?', 'learnpress' ),
173 203 'question_labels' => array(
174 204 'singular' => esc_html__( 'Question', 'learnpress' ),
175 205 'plural' => esc_html__( 'Questions', 'learnpress' ),
176 206 ),
177 - 'confirm_remove_blanks' => esc_html__( 'Are you sure to remove all blanks?', 'learnpress' ),
207 + 'confirm_remove_blanks' => esc_html__( 'Are you sure to remove all the blanks?', 'learnpress' ),
178 208 )
179 209 ),
180 210 'listQuestions' => array(
181 211 'questions' => $quiz->quiz_editor_get_questions(),
@@ -209,135 +239,152 @@
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 )
274 + // Check screen
275 + if ( ! function_exists( 'get_current_screen' ) ) {
276 + return $posts;
277 + }
278 +
279 + $curren_screen = get_current_screen();
280 + if ( ! $curren_screen || $curren_screen->id !== 'edit-' . LP_QUIZ_CPT ) {
281 + return $posts;
282 + }
283 +
284 + $post_type = $wp_query->get( 'post_type' );
285 +
286 + if ( empty( $post_type ) || $post_type !== LP_QUIZ_CPT ) {
287 + return $posts;
288 + }
289 +
290 + $posts_per_page = get_user_option( "edit_{$post_type}_per_page", get_current_user_id() );
291 + if ( empty( $posts_per_page ) ) {
292 + $posts_per_page = 20;
293 + }
294 +
295 + $paged = max( 1, get_query_var( 'paged' ) );
296 + $author = $wp_query->get( 'author' );
297 + $status = $wp_query->get( 'post_status' );
298 + $search = $wp_query->get( 's' );
299 + $month = $wp_query->get( 'm' );
300 + $orderby = LP_Request::get_param( 'orderby', '', 'key' );
301 + $order = LP_Request::get_param( 'order', '', 'key' );
302 +
303 + $filter = new QuizPostFilter();
304 + $filter->only_fields = array_map(
305 + function ( $field ) {
306 + return "p.{$field}";
307 + },
308 + $filter->all_fields
242 309 );
243 - }
310 + $filter->field_count = 'p.ID';
311 + $post_db = PostDB::getInstance();
244 312
245 - unset( $columns['taxonomy-lesson-tag'] );
246 - $user = wp_get_current_user();
313 + if ( ! empty( $status ) ) {
314 + $filter->post_status = array( $status );
315 + }
247 316
248 - if ( in_array( 'lp_teacher', $user->roles ) ) {
249 - unset( $columns['instructor'] );
250 - }
317 + if ( ! empty( $author ) ) {
318 + $filter->post_author = absint( $author );
319 + }
251 320
252 - if ( ! empty( $columns['author'] ) ) {
253 - unset( $columns['author'] );
254 - }
321 + if ( ! empty( $search ) ) {
322 + $filter->post_title = sanitize_text_field( wp_unslash( $search ) );
323 + }
255 324
256 - return $columns;
257 - }
325 + if ( ! empty( $month ) && is_numeric( $month ) && strlen( (string) $month ) === 6 ) {
326 + $filter->where[] = $post_db->wpdb->prepare(
327 + 'AND YEAR(p.post_date) = %d AND MONTH(p.post_date) = %d',
328 + substr( $month, 0, 4 ),
329 + substr( $month, 4, 2 )
330 + );
331 + }
258 332
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;
333 + // Exclude status auto-draft
334 + $filter->where[] = $post_db->wpdb->prepare( 'AND p.post_status != %s', PostModel::STATUS_AUTO_DRAFT );
267 335
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 - $questions = $quiz->get_questions();
281 - $count = sizeof( $questions );
282 - }
336 + // Add question count field
337 + $filter->only_fields[] = "(SELECT COUNT(*) FROM {$post_db->tb_lp_quiz_questions} qq_count
338 + WHERE qq_count.quiz_id = p.ID) AS question_count";
283 339
284 - printf(
285 - '<span class="lp-label-counter' . ( ! $count ? ' disabled' : '' ) . '" title="%s">%s</span>',
286 - ( $count ) ? sprintf( _n( '%d question', '%d questions', $count, 'learnpress' ), $count ) : __( 'This quiz has no questions', 'learnpress' ),
287 - $count
288 - );
289 - break;
290 - case 'duration':
291 - $duration_str = get_post_meta( $post_id, '_lp_duration', true );
292 - $duration = (int) $duration_str;
340 + // Join sections/courses when sorting by course-name
341 + if ( $orderby === 'course-name' ) {
342 + $filter->join[] = "LEFT JOIN {$post_db->wpdb->prefix}learnpress_section_items si ON p.ID = si.item_id";
343 + $filter->join[] = "LEFT JOIN {$post_db->wpdb->prefix}learnpress_sections s ON s.section_id = si.section_id";
344 + $filter->join[] = "LEFT JOIN {$post_db->wpdb->posts} c ON c.ID = s.section_course_id";
345 + }
293 346
294 - if ( $duration > 0 ) {
295 - $duration_str .= 's';
296 - $duration_str_arr = explode( ' ', $duration_str );
297 - $type_time = '';
298 - switch ( $duration_str_arr[1] ) {
299 - case 'hours':
300 - $type_time = __( 'hours', 'learnpress' );
301 - break;
302 - case 'minutes':
303 - $type_time = __( 'minutes', 'learnpress' );
304 - break;
305 - case 'days':
306 - $type_time = __( 'days', 'learnpress' );
307 - break;
308 - case 'weeks':
309 - $type_time = __( 'weeks', 'learnpress' );
310 - break;
311 - }
347 + // Filter unassigned
348 + if ( 'yes' === LP_Request::get_param( 'unassigned', '', 'key' ) ) {
349 + $filter->where[] = "AND p.ID NOT IN(
350 + SELECT si.item_id
351 + FROM {$post_db->wpdb->learnpress_section_items} si
352 + )";
353 + }
312 354
313 - $duration_str = sprintf( '%1$s %2$s', $duration_str_arr[0], $type_time );
314 - } else {
315 - $duration_str = '--';
316 - }
355 + if ( $orderby === 'course-name' ) {
356 + $filter->order_by = 'c.post_title';
357 + } elseif ( $orderby === 'question-count' ) {
358 + $filter->order_by = 'question_count';
359 + } elseif ( $orderby === 'title' ) {
360 + $filter->order_by = 'p.post_title';
361 + } elseif ( $orderby === 'author' ) {
362 + $filter->order_by = 'p.post_author';
363 + } elseif ( $orderby === 'date' ) {
364 + $filter->order_by = 'p.post_date';
365 + } else {
366 + $filter->order_by = 'p.menu_order';
367 + }
317 368
318 - echo esc_html( $duration_str );
319 - break;
320 - case 'preview':
321 - printf(
322 - '<input type="checkbox" class="learn-press-checkbox learn-press-toggle-item-preview" %s value="%s" data-nonce="%s" />',
323 - get_post_meta( $post_id, '_lp_preview', true ) == 'yes' ? ' checked="checked"' : '',
324 - $post_id,
325 - wp_create_nonce( 'learn-press-toggle-item-preview' )
326 - );
327 - break;
328 - default:
329 - break;
369 + $filter->order = strtolower( $order ) === 'asc' ? 'ASC' : 'DESC';
330 370
371 + // Get lp quizzes
372 + $total_rows = 0;
373 + $lp_quizzes = $post_db->get_posts( $filter, $total_rows );
374 +
375 + $wp_query->post_count = count( $lp_quizzes );
376 + $wp_query->found_posts = $total_rows;
377 + $wp_query->max_num_pages = (int) ceil( $total_rows / $posts_per_page );
378 + $posts = $lp_quizzes;
379 + } catch ( Throwable $e ) {
380 + LP_Debug::error_log( $e );
331 381 }
382 +
383 + return $posts;
332 384 }
333 385
334 - /**
335 - * @param $fields
336 - *
337 - * @return string
338 - */
339 - public function posts_fields( $fields ): string {
386 + /*public function posts_fields( $fields ): string {
340 387 global $wpdb;
341 388
342 389 if ( ! $this->is_page_list_posts_on_backend() ) {
343 390 return $fields;
@@ -351,13 +398,8 @@
351 398
352 399 return $fields;
353 400 }
354 401
355 - /**
356 - * @param $join
357 - *
358 - * @return string
359 - */
360 402 public function posts_join_paged( $join ): string {
361 403 if ( ! $this->is_page_list_posts_on_backend() ) {
362 404 return $join;
363 405 }
@@ -364,13 +406,8 @@
364 406
365 407 return $join;
366 408 }
367 409
368 - /**
369 - * @param $where
370 - *
371 - * @return mixed|string
372 - */
373 410 public function posts_where_paged( $where ) {
374 411 if ( ! $this->is_page_list_posts_on_backend() ) {
375 412 return $where;
376 413 }
@@ -379,15 +416,15 @@
379 416
380 417 if ( 'yes' === LP_Request::get( 'unassigned' ) ) {
381 418 $where .= $wpdb->prepare(
382 419 "
383 - AND {$wpdb->posts}.ID NOT IN(
384 - SELECT si.item_id
385 - FROM {$wpdb->learnpress_section_items} si
386 - INNER JOIN {$wpdb->posts} p ON p.ID = si.item_id
387 - WHERE p.post_type = %s
388 - )
389 - ",
420 + AND {$wpdb->posts}.ID NOT IN(
421 + SELECT si.item_id
422 + FROM {$wpdb->learnpress_section_items} si
423 + INNER JOIN {$wpdb->posts} p ON p.ID = si.item_id
424 + WHERE p.post_type = %s
425 + )
426 + ",
390 427 LP_QUIZ_CPT
391 428 );
392 429 }
393 430
@@ -393,13 +430,8 @@
393 430
394 431 return $where;
395 432 }
396 433
397 - /**
398 - * @param $order_by_statement
399 - *
400 - * @return string
401 - */
402 434 public function posts_orderby( $order_by_statement ) {
403 435 global $wpdb;
404 436
405 437 if ( ! $this->is_page_list_posts_on_backend() ) {
@@ -422,30 +454,17 @@
422 454 }
423 455 }
424 456
425 457 return $order_by_statement;
426 - }
458 + }*/
427 459
428 460 /**
429 - * @param $columns
430 - *
431 - * @return mixed
432 - */
433 - public function sortable_columns( $columns ) {
434 - $columns['instructor'] = 'author';
435 - $columns[ LP_COURSE_CPT ] = 'course-name';
436 - $columns['num_of_question'] = 'question-count';
437 -
438 - return $columns;
439 - }
440 -
441 - /**
442 461 * Quiz assigned view.
443 462 *
444 463 * @since 3.0.0
445 464 */
446 465 // public static function quiz_assigned() {
447 - // learn_press_admin_view( 'meta-boxes/course/assigned.php' );
466 + // learn_press_admin_view( 'meta-boxes/course/assigned.php' );
448 467 // }
449 468
450 469 public function meta_boxes() {
451 470 return array(
@@ -450,9 +469,9 @@
450 469 public function meta_boxes() {
451 470 return array(
452 471 'quiz_assigned' => array(
453 472 'title' => esc_html__( 'Assigned', 'learnpress' ),
454 - 'callback' => function( $post ) {
473 + 'callback' => function ( $post ) {
455 474 learn_press_admin_view( 'meta-boxes/course/assigned.php' );
456 475 },
457 476 'context' => 'side',
458 477 'priority' => 'high',
@@ -477,18 +496,26 @@
477 496 return self::$_instance;
478 497 }
479 498
480 499 /**
481 - * Save Post type Quiz
500 + * Handle when save post.
482 501 *
483 - * @author tungnx
502 + * @param int $post_id
503 + * @param WP_Post|null $post
504 + * @param bool $is_update
505 + *
506 + * @return void
507 + * @since 4.2.7.6
484 508 * @version 1.0.0
485 - * @since 4.0.0
486 509 */
487 - public function save( int $post_id, WP_Post $post ) {
488 - $lp_quiz_cache = LP_Quiz_Cache::instance();
510 + public function save_post( int $post_id = 0, ?WP_Post $post = null, bool $is_update = false ) {
511 + // Clear cache get quiz by id
512 + $lpCache = new LP_Cache();
513 + $lpCache->clear( "quizPostModel/find/{$post_id}" );
514 + $lpCache->clear( "quizModel/find/{$post_id}" );
489 515
490 516 // Clear cache get question_ids of quiz
517 + $lp_quiz_cache = LP_Quiz_Cache::instance();
491 518 $lp_quiz_cache->clear( "$post_id/question_ids" );
492 519 }
493 520 }
494 521
@@ -493,10 +520,5 @@
493 520 }
494 521
495 522 // LP_Quiz_Post_Type
496 523 $quiz_post_type = LP_Quiz_Post_Type::instance();
497 -
498 - //Todo: Nhamdv see to rewrite
499 - // $quiz_post_type
500 - // ->add_meta_box( 'lesson_assigned', esc_html__( 'Assigned', 'learnpress' ), 'quiz_assigned', 'side', 'high' )
501 - // ->add_meta_box( 'quiz-editor', esc_html__( 'Questions', 'learnpress' ), 'admin_editor', 'normal', 'high' );
502 524 }