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 +183 -171 4.1.74.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,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,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 - $questions = $quiz->get_questions();
281 - $count = sizeof( $questions );
282 - }
306 + if ( ! empty( $status ) ) {
307 + $filter->post_status = array( $status );
308 + }
283 309
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
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 )
288 323 );
289 - break;
290 - case 'duration':
291 - $duration_str = get_post_meta( $post_id, '_lp_duration', true );
292 - $duration = (int) $duration_str;
324 + }
293 325
294 - if ( $duration > 0 ) {
295 - $duration_str .= 's';
296 - $duration_str_arr = explode( ' ', $duration_str );
297 - $type_time = '';
326 + // Exclude status auto-draft
327 + $filter->where[] = $post_db->wpdb->prepare( 'AND p.post_status != %s', PostModel::STATUS_AUTO_DRAFT );
298 328
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 - }
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";
314 332
315 - $duration_str = sprintf( '%1$s %2$s', $duration_str_arr[0], $type_time );
316 - }
317 - } else {
318 - $duration_str = '--';
319 - }
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 + }
320 339
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;
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 + }
333 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 );
334 374 }
375 +
376 + return $posts;
335 377 }
336 378
337 - /**
338 - * @param $fields
339 - *
340 - * @return string
341 - */
342 - public function posts_fields( $fields ): string {
379 + /*public function posts_fields( $fields ): string {
343 380 global $wpdb;
344 381
345 382 if ( ! $this->is_page_list_posts_on_backend() ) {
346 383 return $fields;
@@ -354,13 +391,8 @@
354 391
355 392 return $fields;
356 393 }
357 394
358 - /**
359 - * @param $join
360 - *
361 - * @return string
362 - */
363 395 public function posts_join_paged( $join ): string {
364 396 if ( ! $this->is_page_list_posts_on_backend() ) {
365 397 return $join;
366 398 }
@@ -367,13 +399,8 @@
367 399
368 400 return $join;
369 401 }
370 402
371 - /**
372 - * @param $where
373 - *
374 - * @return mixed|string
375 - */
376 403 public function posts_where_paged( $where ) {
377 404 if ( ! $this->is_page_list_posts_on_backend() ) {
378 405 return $where;
379 406 }
@@ -382,15 +409,15 @@
382 409
383 410 if ( 'yes' === LP_Request::get( 'unassigned' ) ) {
384 411 $where .= $wpdb->prepare(
385 412 "
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 - ",
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 + ",
393 420 LP_QUIZ_CPT
394 421 );
395 422 }
396 423
@@ -396,13 +423,8 @@
396 423
397 424 return $where;
398 425 }
399 426
400 - /**
401 - * @param $order_by_statement
402 - *
403 - * @return string
404 - */
405 427 public function posts_orderby( $order_by_statement ) {
406 428 global $wpdb;
407 429
408 430 if ( ! $this->is_page_list_posts_on_backend() ) {
@@ -425,30 +447,17 @@
425 447 }
426 448 }
427 449
428 450 return $order_by_statement;
429 - }
451 + }*/
430 452
431 453 /**
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 454 * Quiz assigned view.
446 455 *
447 456 * @since 3.0.0
448 457 */
449 458 // public static function quiz_assigned() {
450 - // learn_press_admin_view( 'meta-boxes/course/assigned.php' );
459 + // learn_press_admin_view( 'meta-boxes/course/assigned.php' );
451 460 // }
452 461
453 462 public function meta_boxes() {
454 463 return array(
@@ -453,9 +462,9 @@
453 462 public function meta_boxes() {
454 463 return array(
455 464 'quiz_assigned' => array(
456 465 'title' => esc_html__( 'Assigned', 'learnpress' ),
457 - 'callback' => function( $post ) {
466 + 'callback' => function ( $post ) {
458 467 learn_press_admin_view( 'meta-boxes/course/assigned.php' );
459 468 },
460 469 'context' => 'side',
461 470 'priority' => 'high',
@@ -480,18 +489,26 @@
480 489 return self::$_instance;
481 490 }
482 491
483 492 /**
484 - * Save Post type Quiz
493 + * Handle when save post.
485 494 *
486 - * @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
487 501 * @version 1.0.0
488 - * @since 4.0.0
489 502 */
490 - public function save( int $post_id, WP_Post $post ) {
491 - $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}" );
492 508
493 509 // Clear cache get question_ids of quiz
510 + $lp_quiz_cache = LP_Quiz_Cache::instance();
494 511 $lp_quiz_cache->clear( "$post_id/question_ids" );
495 512 }
496 513 }
497 514
@@ -496,10 +513,5 @@
496 513 }
497 514
498 515 // LP_Quiz_Post_Type
499 516 $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 517 }