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 / question.php

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

581 lines 15.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class LP_Question_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\QuestionPostFilter;
12 use LearnPress\Models\PostModel;
13 use LearnPress\Models\Question\QuestionPostModel;
14 use LearnPress\Models\WPTables\QuestionsTable;
15
16 defined( 'ABSPATH' ) || exit();
17
18 if ( ! class_exists( 'LP_Question_Post_Type' ) ) {
19
20 /**
21 * Class LP_Question_Post_Type
22 */
23 class LP_Question_Post_Type extends LP_Abstract_Post_Type {
24 /**
25 * @var null
26 */
27 protected static $_instance = null;
28
29 /**
30 * @var string
31 */
32 protected $_post_type = LP_QUESTION_CPT;
33
34 /**
35 * @var string
36 */
37 protected $_screen_list = 'edit-' . LP_QUESTION_CPT;
38
39 /**
40 * LP_Question_Post_Type constructor.
41 *
42 * @param $post_type
43 * @param mixed
44 */
45 public function __construct() {
46 //add_action( 'wp_loaded', array( $this, 'wp_loaded' ) );
47 add_action( 'admin_head', array( $this, 'init' ) );
48 add_action( 'learn-press/admin/after-enqueue-scripts', array( $this, 'data_question_editor' ) );
49
50 add_filter( 'views_edit-' . LP_QUESTION_CPT, array( $this, 'views_pages' ), 11 );
51 add_action( 'posts_pre_query', array( $this, 'posts_pre_query' ), 999, 2 );
52 // add_filter( 'posts_where_paged', array( $this, 'posts_where_paged' ), 10 );
53
54 // $this->add_map_method( 'before_delete', 'before_delete_question' );
55
56 parent::__construct();
57 }
58
59 /**
60 * Declare class name of table list questions.
61 *
62 * @param string $class_name
63 * @param array $args
64 *
65 * @return string
66 * @since 4.2.9.5
67 */
68 public function wp_list_table_class_name( $class_name, $args ) {
69 if ( $this->check_class_name_handle_table( $args['screen'] ) ) {
70 $class_name = QuestionsTable::class;
71 }
72
73 return $class_name;
74 }
75
76 /**
77 * Add question types support answer options
78 *
79 * @since 3.3.0
80 */
81 public function wp_loaded() {
82 $default_support_options = apply_filters(
83 'learn-press/default-question-types-support-answer-options',
84 array(
85 'true_or_false',
86 'single_choice',
87 'multi_choice',
88 'fill_in_blanks',
89 )
90 );
91
92 foreach ( $default_support_options as $type ) {
93 LP_Global::add_object_feature( 'question.' . $type, 'answer-options', 'yes' );
94 }
95 }
96
97 /**
98 * Add filters to lesson view.
99 *
100 * @param array $views
101 *
102 * @return array
103 * @since 3.0.1
104 * @version 1.0.1
105 * @editor tungnx
106 */
107 public function views_pages( array $views ): array {
108 $lp_question_db = LP_Question_DB::getInstance();
109
110 try {
111 $filter = new LP_Question_Filter();
112 /*if ( ! current_user_can( 'administrator' ) ) {
113 $filter->where[] = $lp_question_db->wpdb->prepare( 'AND post_author = %d', get_current_user_id() );
114 }*/
115
116 $count_unassigned_questions = $lp_question_db->get_total_question_unassigned( $filter );
117
118 if ( $count_unassigned_questions > 0 ) {
119 $views['unassigned'] = sprintf(
120 '<a href="%s" class="%s">%s <span class="count">(%d)</span></a>',
121 admin_url( 'edit.php?post_type=' . LP_QUESTION_CPT . '&unassigned=yes' ),
122 isset( $_GET['unassigned'] ) ? 'current' : '',
123 __( 'Unassigned', 'learnpress' ),
124 $count_unassigned_questions
125 );
126 }
127 } catch ( Throwable $e ) {
128
129 }
130
131 return $views;
132 }
133
134 /**
135 * Load data for question editor.
136 *
137 * @since 3.0.0
138 */
139 public function data_question_editor() {
140 global $post;
141
142 if ( LP_QUESTION_CPT !== get_post_type() ) {
143 return;
144 }
145
146 $question = LP_Question::get_question( $post->ID );
147 $type = $question->get_type();
148 $answers = ( $question->get_data( 'answer_options' ) ? array_values( $question->get_data( 'answer_options' ) ) : array() );
149
150 if ( empty( $answers ) ) {
151 $answers = array(
152 array(
153 'order' => 1,
154 'question_answer_id' => 0,
155 'is_true' => 'yes',
156 'title' => esc_html__( 'Correct', 'learnpress' ),
157 ),
158 array(
159 'order' => 2,
160 'question_answer_id' => 0,
161 'is_true' => '',
162 'title' => esc_html__( 'Incorrect', 'learnpress' ),
163 ),
164 );
165
166 $type = 'true_or_false';
167 }
168
169 wp_localize_script(
170 'learn-press-admin-question-editor',
171 'lp_question_editor',
172 apply_filters(
173 'learn-press/question-editor/localize-script',
174 array(
175 'root' => array(
176 'id' => $post->ID,
177 'auto_draft' => get_post_status( $post->ID ) == 'auto-draft',
178 'open' => false,
179 'title' => get_the_title( $post->ID ),
180 'type' => array(
181 'key' => $type,
182 'label' => learn_press_question_types()[ $type ],
183 ),
184 'answers' => apply_filters( 'learn-press/question-editor/question-answers-data', $answers, $post->ID, 0 ),
185 'ajax' => admin_url( '' ),
186 'action' => 'admin_question_editor',
187 'nonce' => wp_create_nonce( 'learnpress_admin_question_editor' ),
188 'questionTypes' => LP_Question::get_types(),
189 'supportAnswerOptions' => learn_press_get_question_support_answer_options(),
190 ),
191 'i18n' => apply_filters(
192 'learn-press/question-editor/i18n',
193 array(
194 'new_option_label' => esc_html__( 'New Option', 'learnpress' ),
195 'confirm_remove_blanks' => esc_html__( 'Are you sure to remove all the blanks?', 'learnpress' ),
196 )
197 ),
198 )
199 )
200 );
201 }
202
203 /**
204 * Register question post type.
205 */
206 public function args_register_post_type(): array {
207 register_taxonomy(
208 'question_tag',
209 array( LP_QUESTION_CPT ),
210 array(
211 'labels' => array(
212 'name' => esc_html__( 'Question Tag', 'learnpress' ),
213 'menu_name' => esc_html__( 'Tag', 'learnpress' ),
214 'singular_name' => esc_html__( 'Tag', 'learnpress' ),
215 'add_new_item' => esc_html__( 'Add A New Tag', 'learnpress' ),
216 'all_items' => esc_html__( 'All Tags', 'learnpress' ),
217 ),
218 'public' => true,
219 'hierarchical' => false,
220 'show_ui' => true,
221 'show_admin_column' => false,
222 'show_in_nav_menus' => true,
223 'rewrite' => array(
224 'slug' => 'question-tag',
225 'hierarchical' => false,
226 'with_front' => false,
227 ),
228 )
229 );
230 add_post_type_support( 'question', 'comments' );
231
232 return array(
233 'labels' => array(
234 'name' => esc_html__( 'Question Bank', 'learnpress' ),
235 'menu_name' => esc_html__( 'Question Bank', 'learnpress' ),
236 'singular_name' => esc_html__( 'Question', 'learnpress' ),
237 'all_items' => esc_html__( 'Questions', 'learnpress' ),
238 'view_item' => esc_html__( 'View Question', 'learnpress' ),
239 'add_new_item' => esc_html__( 'Add A New Question', 'learnpress' ),
240 'add_new' => esc_html__( 'Add New', 'learnpress' ),
241 'edit_item' => esc_html__( 'Edit Question', 'learnpress' ),
242 'update_item' => esc_html__( 'Update Question', 'learnpress' ),
243 'search_items' => esc_html__( 'Search Questions', 'learnpress' ),
244 'not_found' => esc_html__( 'No questions found', 'learnpress' ),
245 'not_found_in_trash' => esc_html__( 'There was no questions found in the trash', 'learnpress' ),
246 ),
247 'public' => true,
248 'publicly_queryable' => true,
249 'show_ui' => true,
250 'has_archive' => false,
251 'capability_type' => LP_LESSON_CPT,
252 'map_meta_cap' => true,
253 'show_in_menu' => 'learn_press',
254 'show_in_admin_bar' => true,
255 'show_in_nav_menus' => true,
256 'show_in_rest' => learn_press_user_maybe_is_a_teacher(),
257 'supports' => array( 'title', 'editor', 'revisions' ),
258 'hierarchical' => false,
259 'rewrite' => array(
260 'slug' => 'questions',
261 'hierarchical' => true,
262 'with_front' => false,
263 ),
264 'exclude_from_search' => true,
265 );
266 }
267
268 /**
269 * Init question.
270 *
271 * @since 3.0.0
272 */
273 public function init() {
274 $hidden = get_user_meta( get_current_user_id(), 'manageedit-lp_questioncolumnshidden', true );
275
276 if ( ! is_array( $hidden ) && empty( $hidden ) ) {
277 update_user_meta( get_current_user_id(), 'manageedit-lp_questioncolumnshidden', array( 'taxonomy-question-tag' ) );
278 }
279 }
280
281 /**
282 * Remove question from quiz items.
283 *
284 * @param $question_id
285 *
286 * @since 3.0.0
287 */
288 public function before_delete_question( int $question_id = 0 ) {
289 $curd = new LP_Question_CURD();
290
291 $curd->delete( $question_id );
292 }
293
294 /**
295 * Handle when save post.
296 *
297 * @param int $post_id
298 * @param WP_Post|null $post
299 * @param bool $is_update
300 *
301 * @return void
302 * @since 4.2.7.6
303 * @version 1.0.0
304 */
305 public function save_post( int $post_id, ?WP_Post $post = null, bool $is_update = false ) {
306 // Clear cache get question by id
307 $lpCache = new LP_Cache();
308 $lpCache->clear( "questionPostModel/find/{$post_id}" );
309 $lpCache->clear( "questionModel/find/{$post_id}" );
310 }
311
312 /**
313 * Admin editor
314 *
315 * @since 3.3.0
316 *
317 * @return void
318 */
319 public function admin_editor() {
320 global $post;
321
322 $question_id = $post->ID;
323 $questionPostModel = QuestionPostModel::find( $question_id, true );
324 if ( ! $questionPostModel instanceof QuestionPostModel ) {
325 return;
326 }
327
328 do_action( 'learn-press/admin/edit-question/layout', $questionPostModel );
329 }
330
331 /**
332 * Query lp questions in admin via Post DB
333 *
334 * @param array $posts
335 * @param WP_Query $wp_query
336 *
337 * @return array|WP_Query
338 * @since 4.4.8
339 * @version 1.0.0
340 */
341 public function posts_pre_query( $posts, $wp_query ) {
342 try {
343 if ( ! is_admin() ) {
344 return $posts;
345 }
346
347 // Check screen
348 if ( ! function_exists( 'get_current_screen' ) ) {
349 return $posts;
350 }
351
352 $curren_screen = get_current_screen();
353 if ( ! $curren_screen || $curren_screen->id !== 'edit-' . LP_QUESTION_CPT ) {
354 return $posts;
355 }
356
357 $post_type = $wp_query->get( 'post_type' );
358
359 if ( empty( $post_type ) || $post_type !== LP_QUESTION_CPT ) {
360 return $posts;
361 }
362
363 $posts_per_page = get_user_option( "edit_{$post_type}_per_page", get_current_user_id() );
364 if ( empty( $posts_per_page ) ) {
365 $posts_per_page = 20;
366 }
367
368 $paged = max( 1, get_query_var( 'paged' ) );
369 $author = $wp_query->get( 'author' );
370 $status = $wp_query->get( 'post_status' );
371 $search = $wp_query->get( 's' );
372 $month = $wp_query->get( 'm' );
373 $orderby = LP_Request::get_param( 'orderby', '', 'key' );
374 $order = LP_Request::get_param( 'order', '', 'key' );
375 $quiz_id = LP_Request::get_param( 'filter_quiz' );
376
377 $filter = new QuestionPostFilter();
378 $filter->page = $paged;
379 $filter->limit = $posts_per_page;
380 $filter->only_fields = array_map(
381 function ( $field ) {
382 return "p.{$field}";
383 },
384 $filter->all_fields
385 );
386 $filter->field_count = 'p.ID';
387 $post_db = PostDB::getInstance();
388
389 if ( ! empty( $status ) ) {
390 $filter->post_status = array( $status );
391 }
392
393 if ( ! empty( $author ) ) {
394 $filter->post_author = absint( $author );
395 }
396
397 if ( ! empty( $search ) ) {
398 $filter->post_title = sanitize_text_field( wp_unslash( $search ) );
399 }
400
401 if ( ! empty( $month ) && is_numeric( $month ) && strlen( (string) $month ) === 6 ) {
402 $filter->where[] = $post_db->wpdb->prepare(
403 'AND YEAR(p.post_date) = %d AND MONTH(p.post_date) = %d',
404 substr( $month, 0, 4 ),
405 substr( $month, 4, 2 )
406 );
407 }
408
409 // Exclude status auto-draft
410 $filter->where[] = $post_db->wpdb->prepare( 'AND p.post_status != %s', PostModel::STATUS_AUTO_DRAFT );
411
412 // Join quiz questions when needed
413 if ( $quiz_id || $orderby === 'quiz-name' ) {
414 $filter->join[] = "LEFT JOIN {$post_db->wpdb->prefix}learnpress_quiz_questions qq ON p.ID = qq.question_id";
415 $filter->join[] = "LEFT JOIN {$post_db->wpdb->posts} qz ON qz.ID = qq.quiz_id";
416 }
417
418 // Filter by quiz
419 if ( $quiz_id ) {
420 $filter->where[] = $post_db->wpdb->prepare( 'AND qz.ID = %d', $quiz_id );
421 }
422
423 // Filter unassigned
424 if ( 'yes' === LP_Request::get_param( 'unassigned', '', 'key' ) ) {
425 $filter->where[] = "AND p.ID NOT IN(
426 SELECT qq_un.question_id
427 FROM {$post_db->wpdb->learnpress_quiz_questions} qq_un
428 )";
429 }
430
431 if ( $orderby === 'quiz-name' ) {
432 $filter->order_by = 'qz.post_title';
433 } elseif ( $orderby === 'title' ) {
434 $filter->order_by = 'p.post_title';
435 } elseif ( $orderby === 'author' ) {
436 $filter->order_by = 'p.post_author';
437 } elseif ( $orderby === 'date' ) {
438 $filter->order_by = 'p.post_date';
439 } else {
440 $filter->order_by = 'p.menu_order';
441 }
442
443 $filter->order = strtolower( $order ) === 'asc' ? 'ASC' : 'DESC';
444
445 // Get lp questions
446 $total_rows = 0;
447 $lp_questions = $post_db->get_posts( $filter, $total_rows );
448
449 $wp_query->post_count = count( $lp_questions );
450 $wp_query->found_posts = $total_rows;
451 $posts = $lp_questions;
452 } catch ( Throwable $e ) {
453 LP_Debug::error_log( $e );
454 }
455
456 return $posts;
457 }
458
459 /*public function posts_join_paged( $join ): string {
460 if ( ! $this->is_page_list_posts_on_backend() ) {
461 return $join;
462 }
463
464 global $wpdb;
465
466 $quiz_id = $this->_filter_quiz();
467 if ( $quiz_id || $this->get_order_by() == 'quiz-name' ) {
468 $join .= " LEFT JOIN {$wpdb->prefix}learnpress_quiz_questions qq ON {$wpdb->posts}.ID = qq.question_id";
469 $join .= " LEFT JOIN {$wpdb->posts} q ON q.ID = qq.quiz_id";
470 }
471
472 return $join;
473 }
474
475 public function posts_where_paged( $where ) {
476 static $posts_where_paged = false;
477
478 if ( $posts_where_paged || ! $this->is_page_list_posts_on_backend() ) {
479 return $where;
480 }
481
482 global $wpdb;
483 $quiz_id = $this->_filter_quiz();
484
485 if ( $quiz_id ) {
486 $where .= $wpdb->prepare( ' AND (q.ID = %d)', $quiz_id );
487 }
488
489 if ( 'yes' === LP_Request::get( 'unassigned' ) ) {
490 global $wpdb;
491 $where .= " AND {$wpdb->posts}.ID NOT IN(
492 SELECT qq.question_id
493 FROM {$wpdb->learnpress_quiz_questions} qq
494 )
495 ";
496 }
497
498 return $where;
499 }
500
501 public function posts_orderby( $order_by_statement ): string {
502 if ( ! $this->is_page_list_posts_on_backend() ) {
503 return $order_by_statement;
504 }
505
506 $orderby = $this->get_order_by();
507 $order = $this->get_order_sort();
508
509 if ( $orderby && $order ) {
510 switch ( $orderby ) {
511 case 'quiz-name':
512 $order_by_statement = "q.post_title {$order}";
513 break;
514 case 'date':
515 $order_by_statement = "post_date {$order}";
516 break;
517 }
518 }
519
520 return $order_by_statement;
521 }*/
522
523 /**
524 * @return bool|int
525 */
526 private function _filter_quiz() {
527 return LP_Request::get_int( 'filter_quiz' );
528 }
529
530 /**
531 * Quiz assigned view.
532 *
533 * @since 3.0.0
534 */
535 public static function question_assigned() {
536 learn_press_admin_view( 'meta-boxes/quiz/assigned.php' );
537 }
538
539 public function meta_boxes() {
540 return array(
541 'question_assigned' => array(
542 'title' => esc_html__( 'Assigned', 'learnpress' ),
543 'callback' => function ( $post ) {
544 learn_press_admin_view( 'meta-boxes/quiz/assigned.php' );
545 },
546 'context' => 'side',
547 'priority' => 'high',
548 ),
549 'question-editor' => array(
550 'title' => esc_html__( 'Questions Options', 'learnpress' ),
551 'callback' => array( $this, 'admin_editor' ),
552 'context' => 'normal',
553 'priority' => 'high',
554 ),
555 );
556 }
557
558 /**
559 * @return LP_Question_Post_Type|null
560 *
561 * @editor tungnx
562 */
563 public static function instance() {
564 if ( ! self::$_instance ) {
565 /*
566 $args = array(
567 'default_meta' => array(
568 '_lp_mark' => 1,
569 '_lp_type' => 'true_or_false',
570 ),
571 );*/
572 self::$_instance = new self();
573 }
574
575 return self::$_instance;
576 }
577 }
578
579 $question_post_type = LP_Question_Post_Type::instance();
580 }
581