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 +190 -171 4.1.7.1 → 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,138 +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 = '';
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 + }
298 354
299 - if ( is_array( $duration_str_arr ) && ! empty( $duration_str_arr ) && count( $duration_str_arr ) >= 2 ) {
300 - switch ( $duration_str_arr[1] ) {
301 - case 'hours':
302 - $type_time = __( 'hours', 'learnpress' );
303 - break;
304 - case 'minutes':
305 - $type_time = __( 'minutes', 'learnpress' );
306 - break;
307 - case 'days':
308 - $type_time = __( 'days', 'learnpress' );
309 - break;
310 - case 'weeks':
311 - $type_time = __( 'weeks', 'learnpress' );
312 - break;
313 - }
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 + }
314 368
315 - $duration_str = sprintf( '%1$s %2$s', $duration_str_arr[0], $type_time );
316 - }
317 - } else {
318 - $duration_str = '--';
319 - }
369 + $filter->order = strtolower( $order ) === 'asc' ? 'ASC' : 'DESC';
320 370
321 - echo esc_html( $duration_str );
322 - break;
323 - case 'preview':
324 - printf(
325 - '<input type="checkbox" class="learn-press-checkbox learn-press-toggle-item-preview" %s value="%s" data-nonce="%s" />',
326 - get_post_meta( $post_id, '_lp_preview', true ) == 'yes' ? ' checked="checked"' : '',
327 - $post_id,
328 - wp_create_nonce( 'learn-press-toggle-item-preview' )
329 - );
330 - break;
331 - default:
332 - break;
371 + // Get lp quizzes
372 + $total_rows = 0;
373 + $lp_quizzes = $post_db->get_posts( $filter, $total_rows );
333 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 );
334 381 }
382 +
383 + return $posts;
335 384 }
336 385
337 - /**
338 - * @param $fields
339 - *
340 - * @return string
341 - */
342 - public function posts_fields( $fields ): string {
386 + /*public function posts_fields( $fields ): string {
343 387 global $wpdb;
344 388
345 389 if ( ! $this->is_page_list_posts_on_backend() ) {
346 390 return $fields;
@@ -354,13 +398,8 @@
354 398
355 399 return $fields;
356 400 }
357 401
358 - /**
359 - * @param $join
360 - *
361 - * @return string
362 - */
363 402 public function posts_join_paged( $join ): string {
364 403 if ( ! $this->is_page_list_posts_on_backend() ) {
365 404 return $join;
366 405 }
@@ -367,13 +406,8 @@
367 406
368 407 return $join;
369 408 }
370 409
371 - /**
372 - * @param $where
373 - *
374 - * @return mixed|string
375 - */
376 410 public function posts_where_paged( $where ) {
377 411 if ( ! $this->is_page_list_posts_on_backend() ) {
378 412 return $where;
379 413 }
@@ -382,15 +416,15 @@
382 416
383 417 if ( 'yes' === LP_Request::get( 'unassigned' ) ) {
384 418 $where .= $wpdb->prepare(
385 419 "
386 - AND {$wpdb->posts}.ID NOT IN(
387 - SELECT si.item_id
388 - FROM {$wpdb->learnpress_section_items} si
389 - INNER JOIN {$wpdb->posts} p ON p.ID = si.item_id
390 - WHERE p.post_type = %s
391 - )
392 - ",
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 + ",
393 427 LP_QUIZ_CPT
394 428 );
395 429 }
396 430
@@ -396,13 +430,8 @@
396 430
397 431 return $where;
398 432 }
399 433
400 - /**
401 - * @param $order_by_statement
402 - *
403 - * @return string
404 - */
405 434 public function posts_orderby( $order_by_statement ) {
406 435 global $wpdb;
407 436
408 437 if ( ! $this->is_page_list_posts_on_backend() ) {
@@ -425,30 +454,17 @@
425 454 }
426 455 }
427 456
428 457 return $order_by_statement;
429 - }
458 + }*/
430 459
431 460 /**
432 - * @param $columns
433 - *
434 - * @return mixed
435 - */
436 - public function sortable_columns( $columns ) {
437 - $columns['instructor'] = 'author';
438 - $columns[ LP_COURSE_CPT ] = 'course-name';
439 - $columns['num_of_question'] = 'question-count';
440 -
441 - return $columns;
442 - }
443 -
444 - /**
445 461 * Quiz assigned view.
446 462 *
447 463 * @since 3.0.0
448 464 */
449 465 // public static function quiz_assigned() {
450 - // learn_press_admin_view( 'meta-boxes/course/assigned.php' );
466 + // learn_press_admin_view( 'meta-boxes/course/assigned.php' );
451 467 // }
452 468
453 469 public function meta_boxes() {
454 470 return array(
@@ -453,9 +469,9 @@
453 469 public function meta_boxes() {
454 470 return array(
455 471 'quiz_assigned' => array(
456 472 'title' => esc_html__( 'Assigned', 'learnpress' ),
457 - 'callback' => function( $post ) {
473 + 'callback' => function ( $post ) {
458 474 learn_press_admin_view( 'meta-boxes/course/assigned.php' );
459 475 },
460 476 'context' => 'side',
461 477 'priority' => 'high',
@@ -480,18 +496,26 @@
480 496 return self::$_instance;
481 497 }
482 498
483 499 /**
484 - * Save Post type Quiz
500 + * Handle when save post.
485 501 *
486 - * @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
487 508 * @version 1.0.0
488 - * @since 4.0.0
489 509 */
490 - public function save( int $post_id, WP_Post $post ) {
491 - $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}" );
492 515
493 516 // Clear cache get question_ids of quiz
517 + $lp_quiz_cache = LP_Quiz_Cache::instance();
494 518 $lp_quiz_cache->clear( "$post_id/question_ids" );
495 519 }
496 520 }
497 521
@@ -496,10 +520,5 @@
496 520 }
497 521
498 522 // LP_Quiz_Post_Type
499 523 $quiz_post_type = LP_Quiz_Post_Type::instance();
500 -
501 - //Todo: Nhamdv see to rewrite
502 - // $quiz_post_type
503 - // ->add_meta_box( 'lesson_assigned', esc_html__( 'Assigned', 'learnpress' ), 'quiz_assigned', 'side', 'high' )
504 - // ->add_meta_box( 'quiz-editor', esc_html__( 'Questions', 'learnpress' ), 'admin_editor', 'normal', 'high' );
505 524 }