PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.3.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.3.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 4.2.1 All 138 releases
learnpress / inc / custom-post-types / quiz.php

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

499 lines 13.7 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\Models\QuizPostModel;
11
12 defined( 'ABSPATH' ) || exit();
13
14 if ( ! class_exists( 'LP_Quiz_Post_Type' ) ) {
15
16 /**
17 * Class LP_Quiz_Post_Type
18 */
19 final class LP_Quiz_Post_Type extends LP_Abstract_Post_Type {
20
21 /**
22 * @var null
23 */
24 protected static $_instance = null;
25
26 /**
27 * @var array
28 */
29 public static $metaboxes = array();
30
31 /**
32 * @var string
33 */
34 protected $_post_type = LP_QUIZ_CPT;
35
36 /**
37 * LP_Quiz_Post_Type constructor.
38 *
39 * @param $post_type
40 * @param mixed
41 */
42 public function __construct() {
43
44 //$this->add_map_method( 'before_delete', 'before_delete_quiz' );
45
46 add_action( 'learn-press/admin/after-enqueue-scripts', array( $this, 'data_quiz_editor' ) );
47
48 add_filter( 'views_edit-' . LP_QUIZ_CPT, array( $this, 'views_pages' ), 10 );
49 add_filter( 'posts_where_paged', array( $this, 'posts_where_paged' ), 10 );
50
51 parent::__construct();
52 }
53
54 /**
55 * Add filters to lesson view.
56 *
57 * @since 3.0.0
58 *
59 * @param array $views
60 *
61 * @return array
62 */
63 public function views_pages( array $views ): array {
64 $count_unassigned_quiz = LP_Course_DB::getInstance()->get_total_item_unassigned( LP_QUIZ_CPT );
65
66 if ( $count_unassigned_quiz > 0 ) {
67 $views['unassigned'] = sprintf(
68 '<a href="%s" class="%s">%s <span class="count">(%d)</span></a>',
69 admin_url( 'edit.php?post_type=' . LP_QUIZ_CPT . '&unassigned=yes' ),
70 isset( $_GET['unassigned'] ) ? 'current' : '',
71 __( 'Unassigned', 'learnpress' ),
72 $count_unassigned_quiz
73 );
74 }
75
76 return $views;
77 }
78
79 /**
80 * Register quiz post type.
81 */
82 public function args_register_post_type(): array {
83 $args = apply_filters(
84 'lp_quiz_post_type_args',
85 array(
86 'labels' => array(
87 'name' => esc_html__( 'Quizzes', 'learnpress' ),
88 'menu_name' => esc_html__( 'Quizzes', 'learnpress' ),
89 'singular_name' => esc_html__( 'Quiz', 'learnpress' ),
90 'add_new_item' => esc_html__( 'Add A New Quiz', 'learnpress' ),
91 'edit_item' => esc_html__( 'Edit Quiz', 'learnpress' ),
92 'all_items' => esc_html__( 'Quizzes', 'learnpress' ),
93 'view_item' => esc_html__( 'View Quiz', 'learnpress' ),
94 'add_new' => esc_html__( 'New Quiz', 'learnpress' ),
95 'update_item' => esc_html__( 'Update Quiz', 'learnpress' ),
96 'search_items' => esc_html__( 'Search Quizzes', 'learnpress' ),
97 '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' ) ),
98 'not_found_in_trash' => esc_html__( 'There was no quiz found in the trash', 'learnpress' ),
99 ),
100 'public' => true,
101 'publicly_queryable' => true,
102 'show_ui' => true,
103 'has_archive' => false,
104 'capability_type' => LP_LESSON_CPT,
105 'map_meta_cap' => true,
106 'show_in_menu' => 'learn_press',
107 'show_in_rest' => true,
108 'show_in_admin_bar' => true,
109 'show_in_nav_menus' => true,
110 'supports' => array(
111 'title',
112 'editor',
113 'revisions',
114 ),
115 'hierarchical' => true,
116 'rewrite' => array(
117 'slug' => 'quizzes',
118 'hierarchical' => true,
119 'with_front' => false,
120 ),
121 'exclude_from_search' => true,
122 )
123 );
124
125 return $args;
126 }
127
128 /**
129 * Load data for quiz editor.
130 *
131 * @since 3.0.0
132 */
133 public function data_quiz_editor() {
134 if ( LP_QUIZ_CPT !== get_post_type() ) {
135 return;
136 }
137
138 global $post;
139
140 $quiz = LP_Quiz::get_quiz( $post->ID );
141
142 $user_id = get_current_user_id();
143 $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';
144
145 $hidden_questions = get_post_meta( $post->ID, '_lp_hidden_questions', true );
146 $hidden_questions_settings = get_post_meta( $post->ID, '_hidden_questions_settings', true );
147
148 wp_localize_script(
149 'learn-press-admin-quiz-editor',
150 'lp_quiz_editor',
151 apply_filters(
152 'learn-press/admin-localize-quiz-editor',
153 array(
154 'root' => array(
155 'quiz_id' => $post->ID,
156 'ajax' => admin_url( '' ),
157 'action' => 'admin_quiz_editor',
158 'nonce' => wp_create_nonce( 'learnpress_admin_quiz_editor' ),
159 'types' => LP_Question::get_types(),
160 'default_new' => $default_new_question_type,
161 ),
162 'chooseItems' => array(
163 'open' => false,
164 'addedItems' => array(),
165 'items' => array(),
166 ),
167 'i18n' => apply_filters(
168 'learn-press/quiz-editor/i18n',
169 array(
170 'option' => esc_html__( 'Option', 'learnpress' ),
171 'unique' => learn_press_uniqid(),
172 'back' => esc_html__( 'Back', 'learnpress' ),
173 'selected_items' => esc_html__( 'Selected items', 'learnpress' ),
174 'new_option' => esc_html__( 'New Option', 'learnpress' ),
175 'confirm_trash_question' => esc_html__( 'Do you want to move the "{{QUESTION_NAME}}" question to the trash?', 'learnpress' ),
176 'question_labels' => array(
177 'singular' => esc_html__( 'Question', 'learnpress' ),
178 'plural' => esc_html__( 'Questions', 'learnpress' ),
179 ),
180 'confirm_remove_blanks' => esc_html__( 'Are you sure to remove all the blanks?', 'learnpress' ),
181 )
182 ),
183 'listQuestions' => array(
184 'questions' => $quiz->quiz_editor_get_questions(),
185 'hidden_questions' => ! empty( $hidden_questions ) ? $hidden_questions : array(),
186 'hidden_questions_settings' => $hidden_questions_settings ? $hidden_questions_settings : array(),
187 'disableUpdateList' => false,
188 'supportAnswerOptions' => learn_press_get_question_support_answer_options(),
189 ),
190 )
191 )
192 );
193 }
194
195 /**
196 * Delete all questions assign to quiz.
197 *
198 * @since 3.0.0
199 *
200 * @param $post_id
201 */
202 public function before_delete_quiz( $post_id ) {
203 if ( get_post_type( $post_id ) !== LP_QUIZ_CPT ) {
204 return;
205 }
206
207 $curd = new LP_Quiz_CURD();
208 // remove question from course items
209 $curd->delete( $post_id );
210 }
211
212 /**
213 * Admin editor
214 *
215 * @since 3.3.0
216 * @version 1.0.1
217 * @return void
218 */
219 public function admin_editor() {
220 global $post;
221
222 $quiz_id = $post->ID;
223 $quizPostModel = QuizPostModel::find( $quiz_id, true );
224 if ( ! $quizPostModel instanceof QuizPostModel ) {
225 return;
226 }
227
228 do_action( 'learn-press/admin/edit-quiz/layout', $quizPostModel );
229 }
230
231 /**
232 * Add columns to admin manage quiz page
233 *
234 * @param array $columns
235 *
236 * @return array
237 */
238 public function columns_head( $columns ) {
239 $pos = array_search( 'title', array_keys( $columns ) );
240
241 if ( false !== $pos && ! array_key_exists( LP_COURSE_CPT, $columns ) ) {
242 $columns = array_merge(
243 array_slice( $columns, 0, $pos + 1 ),
244 array(
245 'instructor' => esc_html__( 'Author', 'learnpress' ),
246 LP_COURSE_CPT => esc_html__( 'Course', 'learnpress' ),
247 'num_of_question' => esc_html__( 'Questions', 'learnpress' ),
248 'duration' => esc_html__( 'Duration', 'learnpress' ),
249 ),
250 array_slice( $columns, $pos + 1 )
251 );
252 }
253
254 unset( $columns['taxonomy-lesson-tag'] );
255 $user = wp_get_current_user();
256
257 if ( in_array( 'lp_teacher', $user->roles ) ) {
258 unset( $columns['instructor'] );
259 }
260
261 if ( ! empty( $columns['author'] ) ) {
262 unset( $columns['author'] );
263 }
264
265 return $columns;
266 }
267
268 /**
269 * Display content for custom column
270 *
271 * @param string $name
272 * @param int $post_id
273 */
274 public function columns_content( $name, $post_id = 0 ) {
275 $quizPostModel = QuizPostModel::find( $post_id, true );
276 if ( ! $quizPostModel ) {
277 return;
278 }
279
280 switch ( $name ) {
281 case 'instructor':
282 $this->column_instructor( $post_id );
283 break;
284 case 'lp_course':
285 $this->_get_item_course( $post_id );
286 break;
287 case 'num_of_question':
288 $count = $quizPostModel->count_questions();
289
290 printf(
291 '<span class="lp-label-counter %s" title="%s">%s</span>',
292 ! $count ? 'disabled' : '',
293 $count ?
294 sprintf( _n( '%d question', '%d questions', $count, 'learnpress' ), $count ) :
295 __( 'This quiz has no questions', 'learnpress' ),
296 $count
297 );
298 break;
299 case 'duration':
300 $duration_str = $quizPostModel->get_duration();
301 $duration_arr = explode( ' ', $duration_str );
302 $duration = $duration_arr[0];
303 $duration_type = $duration_arr[1];
304
305 if ( $duration > 0 ) {
306 $duration_str = LP_Datetime::get_string_plural_duration( $duration, $duration_type );
307 } else {
308 $duration_str = __( 'Unlimited', 'learnpress' );
309 }
310
311 echo esc_html( $duration_str );
312 break;
313 case 'preview':
314 printf(
315 '<input type="checkbox" class="learn-press-checkbox learn-press-toggle-item-preview" %s value="%s" data-nonce="%s" />',
316 get_post_meta( $post_id, '_lp_preview', true ) == 'yes' ? ' checked="checked"' : '',
317 $post_id,
318 wp_create_nonce( 'learn-press-toggle-item-preview' )
319 );
320 break;
321 default:
322 break;
323
324 }
325 }
326
327 /**
328 * @param $fields
329 *
330 * @return string
331 */
332 public function posts_fields( $fields ): string {
333 global $wpdb;
334
335 if ( ! $this->is_page_list_posts_on_backend() ) {
336 return $fields;
337 }
338
339 $fields = ' DISTINCT ' . $fields;
340
341 if ( $this->get_order_by() == 'question-count' ) {
342 $fields .= ", (SELECT count(*) FROM {$wpdb->prefix}learnpress_quiz_questions qq WHERE {$wpdb->posts}.ID = qq.quiz_id ) as question_count";
343 }
344
345 return $fields;
346 }
347
348 /**
349 * @param $join
350 *
351 * @return string
352 */
353 public function posts_join_paged( $join ): string {
354 if ( ! $this->is_page_list_posts_on_backend() ) {
355 return $join;
356 }
357
358 return $join;
359 }
360
361 /**
362 * @param $where
363 *
364 * @return mixed|string
365 */
366 public function posts_where_paged( $where ) {
367 if ( ! $this->is_page_list_posts_on_backend() ) {
368 return $where;
369 }
370
371 global $wpdb;
372
373 if ( 'yes' === LP_Request::get( 'unassigned' ) ) {
374 $where .= $wpdb->prepare(
375 "
376 AND {$wpdb->posts}.ID NOT IN(
377 SELECT si.item_id
378 FROM {$wpdb->learnpress_section_items} si
379 INNER JOIN {$wpdb->posts} p ON p.ID = si.item_id
380 WHERE p.post_type = %s
381 )
382 ",
383 LP_QUIZ_CPT
384 );
385 }
386
387 return $where;
388 }
389
390 /**
391 * @param $order_by_statement
392 *
393 * @return string
394 */
395 public function posts_orderby( $order_by_statement ) {
396 global $wpdb;
397
398 if ( ! $this->is_page_list_posts_on_backend() ) {
399 return $order_by_statement;
400 }
401
402 $orderby = $this->get_order_by();
403 $order = $this->get_order_sort();
404
405 if ( $order && $orderby ) {
406 switch ( $orderby ) {
407 case 'course-name':
408 $order_by_statement = "post_title {$order}";
409 break;
410 case 'question-count':
411 $order_by_statement = "question_count {$order}";
412 break;
413 default:
414 $order_by_statement = "{$wpdb->posts}.post_title {$order}";
415 }
416 }
417
418 return $order_by_statement;
419 }
420
421 /**
422 * @param $columns
423 *
424 * @return mixed
425 */
426 public function sortable_columns( $columns ) {
427 $columns['instructor'] = 'author';
428 $columns[ LP_COURSE_CPT ] = 'course-name';
429 $columns['num_of_question'] = 'question-count';
430
431 return $columns;
432 }
433
434 /**
435 * Quiz assigned view.
436 *
437 * @since 3.0.0
438 */
439 // public static function quiz_assigned() {
440 // learn_press_admin_view( 'meta-boxes/course/assigned.php' );
441 // }
442
443 public function meta_boxes() {
444 return array(
445 'quiz_assigned' => array(
446 'title' => esc_html__( 'Assigned', 'learnpress' ),
447 'callback' => function ( $post ) {
448 learn_press_admin_view( 'meta-boxes/course/assigned.php' );
449 },
450 'context' => 'side',
451 'priority' => 'high',
452 ),
453 'quiz-editor' => array(
454 'title' => esc_html__( 'Questions', 'learnpress' ),
455 'callback' => array( $this, 'admin_editor' ),
456 'context' => 'normal',
457 'priority' => 'high',
458 ),
459 );
460 }
461
462 /**
463 * @return LP_Quiz_Post_Type|null
464 */
465 public static function instance() {
466 if ( ! self::$_instance ) {
467 self::$_instance = new self();
468 }
469
470 return self::$_instance;
471 }
472
473 /**
474 * Handle when save post.
475 *
476 * @param int $post_id
477 * @param WP_Post|null $post
478 * @param bool $is_update
479 *
480 * @return void
481 * @since 4.2.7.6
482 * @version 1.0.0
483 */
484 public function save_post( int $post_id = 0, ?WP_Post $post = null, bool $is_update = false ) {
485 // Clear cache get quiz by id
486 $lpCache = new LP_Cache();
487 $lpCache->clear( "quizPostModel/find/{$post_id}" );
488 $lpCache->clear( "quizModel/find/{$post_id}" );
489
490 // Clear cache get question_ids of quiz
491 $lp_quiz_cache = LP_Quiz_Cache::instance();
492 $lp_quiz_cache->clear( "$post_id/question_ids" );
493 }
494 }
495
496 // LP_Quiz_Post_Type
497 $quiz_post_type = LP_Quiz_Post_Type::instance();
498 }
499