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

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

571 lines 15.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_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 $curren_screen = get_current_screen();
349 if ( ! $curren_screen || $curren_screen->id !== 'edit-' . LP_QUESTION_CPT ) {
350 return $posts;
351 }
352
353 $post_type = $wp_query->get( 'post_type' );
354
355 if ( empty( $post_type ) || $post_type !== LP_QUESTION_CPT ) {
356 return $posts;
357 }
358
359 $posts_per_page = get_user_option( "edit_{$post_type}_per_page", get_current_user_id() );
360 if ( empty( $posts_per_page ) ) {
361 $posts_per_page = 20;
362 }
363
364 $paged = max( 1, get_query_var( 'paged' ) );
365 $author = $wp_query->get( 'author' );
366 $status = $wp_query->get( 'post_status' );
367 $search = $wp_query->get( 's' );
368 $month = $wp_query->get( 'm' );
369 $orderby = LP_Request::get_param( 'orderby', '', 'key' );
370 $order = LP_Request::get_param( 'order', '', 'key' );
371 $quiz_id = LP_Request::get_param( 'filter_quiz' );
372
373 $filter = new QuestionPostFilter();
374 $filter->page = $paged;
375 $filter->limit = $posts_per_page;
376 $filter->only_fields = [ 'p.ID', 'p.post_title', 'p.post_author', 'p.post_date', 'p.post_date_gmt' ];
377 $post_db = PostDB::getInstance();
378
379 if ( ! empty( $status ) ) {
380 $filter->post_status = array( $status );
381 }
382
383 if ( ! empty( $author ) ) {
384 $filter->post_author = absint( $author );
385 }
386
387 if ( ! empty( $search ) ) {
388 $filter->post_title = sanitize_text_field( wp_unslash( $search ) );
389 }
390
391 if ( ! empty( $month ) && is_numeric( $month ) && strlen( (string) $month ) === 6 ) {
392 $filter->where[] = $post_db->wpdb->prepare(
393 'AND YEAR(p.post_date) = %d AND MONTH(p.post_date) = %d',
394 substr( $month, 0, 4 ),
395 substr( $month, 4, 2 )
396 );
397 }
398
399 // Exclude status auto-draft
400 $filter->where[] = $post_db->wpdb->prepare( 'AND p.post_status != %s', PostModel::STATUS_AUTO_DRAFT );
401
402 // Join quiz questions when needed
403 if ( $quiz_id || $orderby === 'quiz-name' ) {
404 $filter->join[] = "LEFT JOIN {$post_db->wpdb->prefix}learnpress_quiz_questions qq ON p.ID = qq.question_id";
405 $filter->join[] = "LEFT JOIN {$post_db->wpdb->posts} qz ON qz.ID = qq.quiz_id";
406 }
407
408 // Filter by quiz
409 if ( $quiz_id ) {
410 $filter->where[] = $post_db->wpdb->prepare( 'AND qz.ID = %d', $quiz_id );
411 }
412
413 // Filter unassigned
414 if ( 'yes' === LP_Request::get_param( 'unassigned', '', 'key' ) ) {
415 $filter->where[] = "AND p.ID NOT IN(
416 SELECT qq_un.question_id
417 FROM {$post_db->wpdb->learnpress_quiz_questions} qq_un
418 )";
419 }
420
421 if ( $orderby === 'quiz-name' ) {
422 $filter->order_by = 'qz.post_title';
423 } elseif ( $orderby === 'title' ) {
424 $filter->order_by = 'p.post_title';
425 } elseif ( $orderby === 'author' ) {
426 $filter->order_by = 'p.post_author';
427 } elseif ( $orderby === 'date' ) {
428 $filter->order_by = 'p.post_date';
429 } else {
430 $filter->order_by = 'p.menu_order';
431 }
432
433 $filter->order = strtolower( $order ) === 'asc' ? 'ASC' : 'DESC';
434
435 // Get lp questions
436 $total_rows = 0;
437 $lp_questions = $post_db->get_posts( $filter, $total_rows );
438
439 $wp_query->post_count = count( $lp_questions );
440 $wp_query->found_posts = $total_rows;
441 $posts = $lp_questions;
442 } catch ( Throwable $e ) {
443 LP_Debug::error_log( $e );
444 }
445
446 return $posts;
447 }
448
449 /*public function posts_join_paged( $join ): string {
450 if ( ! $this->is_page_list_posts_on_backend() ) {
451 return $join;
452 }
453
454 global $wpdb;
455
456 $quiz_id = $this->_filter_quiz();
457 if ( $quiz_id || $this->get_order_by() == 'quiz-name' ) {
458 $join .= " LEFT JOIN {$wpdb->prefix}learnpress_quiz_questions qq ON {$wpdb->posts}.ID = qq.question_id";
459 $join .= " LEFT JOIN {$wpdb->posts} q ON q.ID = qq.quiz_id";
460 }
461
462 return $join;
463 }
464
465 public function posts_where_paged( $where ) {
466 static $posts_where_paged = false;
467
468 if ( $posts_where_paged || ! $this->is_page_list_posts_on_backend() ) {
469 return $where;
470 }
471
472 global $wpdb;
473 $quiz_id = $this->_filter_quiz();
474
475 if ( $quiz_id ) {
476 $where .= $wpdb->prepare( ' AND (q.ID = %d)', $quiz_id );
477 }
478
479 if ( 'yes' === LP_Request::get( 'unassigned' ) ) {
480 global $wpdb;
481 $where .= " AND {$wpdb->posts}.ID NOT IN(
482 SELECT qq.question_id
483 FROM {$wpdb->learnpress_quiz_questions} qq
484 )
485 ";
486 }
487
488 return $where;
489 }
490
491 public function posts_orderby( $order_by_statement ): string {
492 if ( ! $this->is_page_list_posts_on_backend() ) {
493 return $order_by_statement;
494 }
495
496 $orderby = $this->get_order_by();
497 $order = $this->get_order_sort();
498
499 if ( $orderby && $order ) {
500 switch ( $orderby ) {
501 case 'quiz-name':
502 $order_by_statement = "q.post_title {$order}";
503 break;
504 case 'date':
505 $order_by_statement = "post_date {$order}";
506 break;
507 }
508 }
509
510 return $order_by_statement;
511 }*/
512
513 /**
514 * @return bool|int
515 */
516 private function _filter_quiz() {
517 return LP_Request::get_int( 'filter_quiz' );
518 }
519
520 /**
521 * Quiz assigned view.
522 *
523 * @since 3.0.0
524 */
525 public static function question_assigned() {
526 learn_press_admin_view( 'meta-boxes/quiz/assigned.php' );
527 }
528
529 public function meta_boxes() {
530 return array(
531 'question_assigned' => array(
532 'title' => esc_html__( 'Assigned', 'learnpress' ),
533 'callback' => function ( $post ) {
534 learn_press_admin_view( 'meta-boxes/quiz/assigned.php' );
535 },
536 'context' => 'side',
537 'priority' => 'high',
538 ),
539 'question-editor' => array(
540 'title' => esc_html__( 'Questions Options', 'learnpress' ),
541 'callback' => array( $this, 'admin_editor' ),
542 'context' => 'normal',
543 'priority' => 'high',
544 ),
545 );
546 }
547
548 /**
549 * @return LP_Question_Post_Type|null
550 *
551 * @editor tungnx
552 */
553 public static function instance() {
554 if ( ! self::$_instance ) {
555 /*
556 $args = array(
557 'default_meta' => array(
558 '_lp_mark' => 1,
559 '_lp_type' => 'true_or_false',
560 ),
561 );*/
562 self::$_instance = new self();
563 }
564
565 return self::$_instance;
566 }
567 }
568
569 $question_post_type = LP_Question_Post_Type::instance();
570 }
571