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