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
learnpress / inc / custom-post-types / quiz.php

quiz.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.4.9, at inc/custom-post-types/quiz.php

525 lines 14.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class LP_Quiz_Post_Type
4 *
5 * @author ThimPress
6 * @package LearnPress/Classes
7 * @version 4.0.0
8 */
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
16 defined( 'ABSPATH' ) || exit();
17
18 if ( ! class_exists( 'LP_Quiz_Post_Type' ) ) {
19
20 /**
21 * Class LP_Quiz_Post_Type
22 */
23 final class LP_Quiz_Post_Type extends LP_Abstract_Post_Type {
24
25 /**
26 * @var null
27 */
28 protected static $_instance = null;
29
30 /**
31 * @var array
32 */
33 public static $metaboxes = array();
34
35 /**
36 * @var string
37 */
38 protected $_post_type = LP_QUIZ_CPT;
39
40 /**
41 * @var string
42 */
43 protected $_screen_list = 'edit-' . LP_QUIZ_CPT;
44
45 /**
46 * LP_Quiz_Post_Type constructor.
47 *
48 * @param $post_type
49 * @param mixed
50 */
51 public function __construct() {
52
53 //$this->add_map_method( 'before_delete', 'before_delete_quiz' );
54
55 add_action( 'learn-press/admin/after-enqueue-scripts', array( $this, 'data_quiz_editor' ) );
56
57 add_filter( 'views_edit-' . LP_QUIZ_CPT, array( $this, 'views_pages' ), 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 );
60
61 parent::__construct();
62 }
63
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 /**
82 * Add filters to lesson view.
83 *
84 * @since 3.0.0
85 *
86 * @param array $views
87 *
88 * @return array
89 */
90 public function views_pages( array $views ): array {
91 $count_unassigned_quiz = LP_Course_DB::getInstance()->get_total_item_unassigned( LP_QUIZ_CPT );
92
93 if ( $count_unassigned_quiz > 0 ) {
94 $views['unassigned'] = sprintf(
95 '<a href="%s" class="%s">%s <span class="count">(%d)</span></a>',
96 admin_url( 'edit.php?post_type=' . LP_QUIZ_CPT . '&unassigned=yes' ),
97 isset( $_GET['unassigned'] ) ? 'current' : '',
98 __( 'Unassigned', 'learnpress' ),
99 $count_unassigned_quiz
100 );
101 }
102
103 return $views;
104 }
105
106 /**
107 * Register quiz post type.
108 */
109 public function args_register_post_type(): array {
110 $args = apply_filters(
111 'lp_quiz_post_type_args',
112 array(
113 'labels' => array(
114 'name' => esc_html__( 'Quizzes', 'learnpress' ),
115 'menu_name' => esc_html__( 'Quizzes', 'learnpress' ),
116 'singular_name' => esc_html__( 'Quiz', 'learnpress' ),
117 'add_new_item' => esc_html__( 'Add A New Quiz', 'learnpress' ),
118 'edit_item' => esc_html__( 'Edit Quiz', 'learnpress' ),
119 'all_items' => esc_html__( 'Quizzes', 'learnpress' ),
120 'view_item' => esc_html__( 'View Quiz', 'learnpress' ),
121 'add_new' => esc_html__( 'New Quiz', 'learnpress' ),
122 'update_item' => esc_html__( 'Update Quiz', 'learnpress' ),
123 'search_items' => esc_html__( 'Search Quizzes', 'learnpress' ),
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' ) ),
125 'not_found_in_trash' => esc_html__( 'There was no quiz found in the trash', 'learnpress' ),
126 ),
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(
138 'title',
139 'editor',
140 'revisions',
141 ),
142 'hierarchical' => false, // Quizzes have no parent-child hierarchy.
143 'rewrite' => array(
144 'slug' => 'quizzes',
145 'hierarchical' => true,
146 'with_front' => false,
147 ),
148 'exclude_from_search' => true,
149 )
150 );
151
152 return $args;
153 }
154
155 /**
156 * Load data for quiz editor.
157 *
158 * @since 3.0.0
159 */
160 public function data_quiz_editor() {
161 if ( LP_QUIZ_CPT !== get_post_type() ) {
162 return;
163 }
164
165 global $post;
166
167 $quiz = LP_Quiz::get_quiz( $post->ID );
168
169 $user_id = get_current_user_id();
170 $default_new_question_type = get_user_meta( $user_id, '_learn_press_memorize_question_types', true ) ? get_user_meta( $user_id, '_learn_press_memorize_question_types', true ) : 'true_or_false';
171
172 $hidden_questions = get_post_meta( $post->ID, '_lp_hidden_questions', true );
173 $hidden_questions_settings = get_post_meta( $post->ID, '_hidden_questions_settings', true );
174
175 wp_localize_script(
176 'learn-press-admin-quiz-editor',
177 'lp_quiz_editor',
178 apply_filters(
179 'learn-press/admin-localize-quiz-editor',
180 array(
181 'root' => array(
182 'quiz_id' => $post->ID,
183 'ajax' => admin_url( '' ),
184 'action' => 'admin_quiz_editor',
185 'nonce' => wp_create_nonce( 'learnpress_admin_quiz_editor' ),
186 'types' => LP_Question::get_types(),
187 'default_new' => $default_new_question_type,
188 ),
189 'chooseItems' => array(
190 'open' => false,
191 'addedItems' => array(),
192 'items' => array(),
193 ),
194 'i18n' => apply_filters(
195 'learn-press/quiz-editor/i18n',
196 array(
197 'option' => esc_html__( 'Option', 'learnpress' ),
198 'unique' => learn_press_uniqid(),
199 'back' => esc_html__( 'Back', 'learnpress' ),
200 'selected_items' => esc_html__( 'Selected items', 'learnpress' ),
201 'new_option' => esc_html__( 'New Option', 'learnpress' ),
202 'confirm_trash_question' => esc_html__( 'Do you want to move the "{{QUESTION_NAME}}" question to the trash?', 'learnpress' ),
203 'question_labels' => array(
204 'singular' => esc_html__( 'Question', 'learnpress' ),
205 'plural' => esc_html__( 'Questions', 'learnpress' ),
206 ),
207 'confirm_remove_blanks' => esc_html__( 'Are you sure to remove all the blanks?', 'learnpress' ),
208 )
209 ),
210 'listQuestions' => array(
211 'questions' => $quiz->quiz_editor_get_questions(),
212 'hidden_questions' => ! empty( $hidden_questions ) ? $hidden_questions : array(),
213 'hidden_questions_settings' => $hidden_questions_settings ? $hidden_questions_settings : array(),
214 'disableUpdateList' => false,
215 'supportAnswerOptions' => learn_press_get_question_support_answer_options(),
216 ),
217 )
218 )
219 );
220 }
221
222 /**
223 * Delete all questions assign to quiz.
224 *
225 * @since 3.0.0
226 *
227 * @param $post_id
228 */
229 public function before_delete_quiz( $post_id ) {
230 if ( get_post_type( $post_id ) !== LP_QUIZ_CPT ) {
231 return;
232 }
233
234 $curd = new LP_Quiz_CURD();
235 // remove question from course items
236 $curd->delete( $post_id );
237 }
238
239 /**
240 * Admin editor
241 *
242 * @since 3.3.0
243 * @version 1.0.1
244 * @return void
245 */
246 public function admin_editor() {
247 global $post;
248
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 );
256 }
257
258 /**
259 * Query lp quizzes in admin via Post DB
260 *
261 * @param array $posts
262 * @param WP_Query $wp_query
263 *
264 * @return array|WP_Query
265 * @since 4.4.8
266 * @version 1.0.0
267 */
268 public function posts_pre_query( $posts, $wp_query ) {
269 try {
270 if ( ! is_admin() ) {
271 return $posts;
272 }
273
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
309 );
310 $filter->field_count = 'p.ID';
311 $post_db = PostDB::getInstance();
312
313 if ( ! empty( $status ) ) {
314 $filter->post_status = array( $status );
315 }
316
317 if ( ! empty( $author ) ) {
318 $filter->post_author = absint( $author );
319 }
320
321 if ( ! empty( $search ) ) {
322 $filter->post_title = sanitize_text_field( wp_unslash( $search ) );
323 }
324
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 }
332
333 // Exclude status auto-draft
334 $filter->where[] = $post_db->wpdb->prepare( 'AND p.post_status != %s', PostModel::STATUS_AUTO_DRAFT );
335
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";
339
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 }
346
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 }
354
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 }
368
369 $filter->order = strtolower( $order ) === 'asc' ? 'ASC' : 'DESC';
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 );
381 }
382
383 return $posts;
384 }
385
386 /*public function posts_fields( $fields ): string {
387 global $wpdb;
388
389 if ( ! $this->is_page_list_posts_on_backend() ) {
390 return $fields;
391 }
392
393 $fields = ' DISTINCT ' . $fields;
394
395 if ( $this->get_order_by() == 'question-count' ) {
396 $fields .= ", (SELECT count(*) FROM {$wpdb->prefix}learnpress_quiz_questions qq WHERE {$wpdb->posts}.ID = qq.quiz_id ) as question_count";
397 }
398
399 return $fields;
400 }
401
402 public function posts_join_paged( $join ): string {
403 if ( ! $this->is_page_list_posts_on_backend() ) {
404 return $join;
405 }
406
407 return $join;
408 }
409
410 public function posts_where_paged( $where ) {
411 if ( ! $this->is_page_list_posts_on_backend() ) {
412 return $where;
413 }
414
415 global $wpdb;
416
417 if ( 'yes' === LP_Request::get( 'unassigned' ) ) {
418 $where .= $wpdb->prepare(
419 "
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 ",
427 LP_QUIZ_CPT
428 );
429 }
430
431 return $where;
432 }
433
434 public function posts_orderby( $order_by_statement ) {
435 global $wpdb;
436
437 if ( ! $this->is_page_list_posts_on_backend() ) {
438 return $order_by_statement;
439 }
440
441 $orderby = $this->get_order_by();
442 $order = $this->get_order_sort();
443
444 if ( $order && $orderby ) {
445 switch ( $orderby ) {
446 case 'course-name':
447 $order_by_statement = "post_title {$order}";
448 break;
449 case 'question-count':
450 $order_by_statement = "question_count {$order}";
451 break;
452 default:
453 $order_by_statement = "{$wpdb->posts}.post_title {$order}";
454 }
455 }
456
457 return $order_by_statement;
458 }*/
459
460 /**
461 * Quiz assigned view.
462 *
463 * @since 3.0.0
464 */
465 // public static function quiz_assigned() {
466 // learn_press_admin_view( 'meta-boxes/course/assigned.php' );
467 // }
468
469 public function meta_boxes() {
470 return array(
471 'quiz_assigned' => array(
472 'title' => esc_html__( 'Assigned', 'learnpress' ),
473 'callback' => function ( $post ) {
474 learn_press_admin_view( 'meta-boxes/course/assigned.php' );
475 },
476 'context' => 'side',
477 'priority' => 'high',
478 ),
479 'quiz-editor' => array(
480 'title' => esc_html__( 'Questions', 'learnpress' ),
481 'callback' => array( $this, 'admin_editor' ),
482 'context' => 'normal',
483 'priority' => 'high',
484 ),
485 );
486 }
487
488 /**
489 * @return LP_Quiz_Post_Type|null
490 */
491 public static function instance() {
492 if ( ! self::$_instance ) {
493 self::$_instance = new self();
494 }
495
496 return self::$_instance;
497 }
498
499 /**
500 * Handle when save post.
501 *
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
508 * @version 1.0.0
509 */
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}" );
515
516 // Clear cache get question_ids of quiz
517 $lp_quiz_cache = LP_Quiz_Cache::instance();
518 $lp_quiz_cache->clear( "$post_id/question_ids" );
519 }
520 }
521
522 // LP_Quiz_Post_Type
523 $quiz_post_type = LP_Quiz_Post_Type::instance();
524 }
525