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

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

518 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 $curren_screen = get_current_screen();
276 if ( ! $curren_screen || $curren_screen->id !== 'edit-' . LP_QUIZ_CPT ) {
277 return $posts;
278 }
279
280 $post_type = $wp_query->get( 'post_type' );
281
282 if ( empty( $post_type ) || $post_type !== LP_QUIZ_CPT ) {
283 return $posts;
284 }
285
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 }
290
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' );
298
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();
305
306 if ( ! empty( $status ) ) {
307 $filter->post_status = array( $status );
308 }
309
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 )
323 );
324 }
325
326 // Exclude status auto-draft
327 $filter->where[] = $post_db->wpdb->prepare( 'AND p.post_status != %s', PostModel::STATUS_AUTO_DRAFT );
328
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";
332
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 }
339
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 }
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 );
374 }
375
376 return $posts;
377 }
378
379 /*public function posts_fields( $fields ): string {
380 global $wpdb;
381
382 if ( ! $this->is_page_list_posts_on_backend() ) {
383 return $fields;
384 }
385
386 $fields = ' DISTINCT ' . $fields;
387
388 if ( $this->get_order_by() == 'question-count' ) {
389 $fields .= ", (SELECT count(*) FROM {$wpdb->prefix}learnpress_quiz_questions qq WHERE {$wpdb->posts}.ID = qq.quiz_id ) as question_count";
390 }
391
392 return $fields;
393 }
394
395 public function posts_join_paged( $join ): string {
396 if ( ! $this->is_page_list_posts_on_backend() ) {
397 return $join;
398 }
399
400 return $join;
401 }
402
403 public function posts_where_paged( $where ) {
404 if ( ! $this->is_page_list_posts_on_backend() ) {
405 return $where;
406 }
407
408 global $wpdb;
409
410 if ( 'yes' === LP_Request::get( 'unassigned' ) ) {
411 $where .= $wpdb->prepare(
412 "
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 ",
420 LP_QUIZ_CPT
421 );
422 }
423
424 return $where;
425 }
426
427 public function posts_orderby( $order_by_statement ) {
428 global $wpdb;
429
430 if ( ! $this->is_page_list_posts_on_backend() ) {
431 return $order_by_statement;
432 }
433
434 $orderby = $this->get_order_by();
435 $order = $this->get_order_sort();
436
437 if ( $order && $orderby ) {
438 switch ( $orderby ) {
439 case 'course-name':
440 $order_by_statement = "post_title {$order}";
441 break;
442 case 'question-count':
443 $order_by_statement = "question_count {$order}";
444 break;
445 default:
446 $order_by_statement = "{$wpdb->posts}.post_title {$order}";
447 }
448 }
449
450 return $order_by_statement;
451 }*/
452
453 /**
454 * Quiz assigned view.
455 *
456 * @since 3.0.0
457 */
458 // public static function quiz_assigned() {
459 // learn_press_admin_view( 'meta-boxes/course/assigned.php' );
460 // }
461
462 public function meta_boxes() {
463 return array(
464 'quiz_assigned' => array(
465 'title' => esc_html__( 'Assigned', 'learnpress' ),
466 'callback' => function ( $post ) {
467 learn_press_admin_view( 'meta-boxes/course/assigned.php' );
468 },
469 'context' => 'side',
470 'priority' => 'high',
471 ),
472 'quiz-editor' => array(
473 'title' => esc_html__( 'Questions', 'learnpress' ),
474 'callback' => array( $this, 'admin_editor' ),
475 'context' => 'normal',
476 'priority' => 'high',
477 ),
478 );
479 }
480
481 /**
482 * @return LP_Quiz_Post_Type|null
483 */
484 public static function instance() {
485 if ( ! self::$_instance ) {
486 self::$_instance = new self();
487 }
488
489 return self::$_instance;
490 }
491
492 /**
493 * Handle when save post.
494 *
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
501 * @version 1.0.0
502 */
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}" );
508
509 // Clear cache get question_ids of quiz
510 $lp_quiz_cache = LP_Quiz_Cache::instance();
511 $lp_quiz_cache->clear( "$post_id/question_ids" );
512 }
513 }
514
515 // LP_Quiz_Post_Type
516 $quiz_post_type = LP_Quiz_Post_Type::instance();
517 }
518