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
← All changes | inc/TemplateHooks/Admin/AdminEditQizTemplate.php +164 -122 4.4.5 → 4.4.9 View file →
@@ -5,23 +5,28 @@
5 5 use Exception;
6 6 use LearnPress\Databases\DataBase;
7 7 use LearnPress\Filters\PostFilter;
8 8 use LearnPress\Helpers\Config;
9 +use LearnPress\Helpers\Response;
9 10 use LearnPress\Helpers\Singleton;
10 11 use LearnPress\Helpers\Template;
11 12 use LearnPress\Models\Question\QuestionPostModel;
12 13 use LearnPress\Models\QuizPostModel;
14 +use LearnPress\Models\UserModel;
13 15 use LearnPress\TemplateHooks\TemplateAJAX;
14 16 use LP_Database;
15 17 use LP_Post_DB;
16 18 use LP_Post_Type_Filter;
17 19 use stdClass;
20 +use Throwable;
18 21
22 +defined( 'ABSPATH' ) || exit;
23 +
19 24 /**
20 25 * Template Admin Edit Quiz.
21 26 *
22 27 * @since 4.2.9
23 - * @version 1.0.0
28 + * @version 1.0.3
24 29 */
25 30 class AdminEditQizTemplate {
26 31 use Singleton;
27 32
@@ -29,9 +34,9 @@
29 34 * @var QuizPostModel
30 35 */
31 36 public $quizPostModel;
32 37
33 - public function init() {
38 + public function init(): void {
34 39 add_action( 'learn-press/admin/edit-quiz/layout', [ $this, 'edit_quiz_layout' ] );
35 40 add_filter( 'lp/rest/ajax/allow_callback', [ $this, 'allow_callback' ] );
36 41 add_filter(
37 42 'wp_default_editor',
@@ -93,24 +98,35 @@
93 98 /**
94 99 * Render edit course curriculum html.
95 100 *
96 101 * @throws Exception
102 + * @since 4.2.9
103 + * @version 1.0.1
97 104 */
98 105 public static function render_edit_quiz( array $data ): stdClass {
99 - $quiz_id = $data['quiz_id'] ?? 0;
100 - $quizPostModel = QuizPostModel::find( $quiz_id, true );
101 - if ( ! $quizPostModel ) {
102 - throw new Exception( __( 'Quiz not found', 'learnpress' ) );
103 - }
106 + $content = new stdClass();
104 107
105 - // Check permission
106 - $quizPostModel->check_capabilities_create_item_course();
108 + try {
109 + $quiz_id = $data['quiz_id'] ?? 0;
110 + $quizPostModel = QuizPostModel::find( $quiz_id, true );
111 + if ( ! $quizPostModel ) {
112 + throw new Exception( __( 'Quiz not found', 'learnpress' ) );
113 + }
107 114
108 - self::instance()->quizPostModel = $quizPostModel;
115 + // Check permission
116 + $quizPostModel->check_capabilities_create_item_course();
109 117
110 - $content = new stdClass();
111 - $content->content = self::instance()->html_edit_quiz( $quizPostModel );
118 + self::instance()->quizPostModel = $quizPostModel;
112 119
120 + $content->content = self::instance()->html_edit_quiz( $quizPostModel );
121 + } catch ( Throwable $e ) {
122 + $content->content = Template::print_message(
123 + $e->getMessage(),
124 + Response::STATUS_ERROR,
125 + false
126 + );
127 + }
128 +
113 129 return $content;
114 130 }
115 131
116 132 /**
@@ -129,9 +145,9 @@
129 145 $count_questions = count( $question_ids );
130 146
131 147 foreach ( $question_ids as $question_id ) {
132 148 $questionPostModel = QuestionPostModel::find( $question_id, true );
133 - $html_questions .= $this->html_edit_question( $questionPostModel );
149 + $html_questions .= $this->html_edit_question( $questionPostModel );
134 150 }
135 151
136 152 $section_questions = [
137 153 'wrap' => '<div class="lp-edit-list-questions">',
@@ -147,12 +163,12 @@
147 163 '<h4>%s</h4>',
148 164 __( 'Details', 'learnpress' )
149 165 ),
150 166 'count-questions' => sprintf(
151 - '<div class="total-items" data-count="%s">%s</div>',
167 + '<div class="total-items" data-count="%d">%s</div>',
152 168 $count_questions,
153 169 sprintf(
154 - __( '<span class="count">%1$s</span> %2$s', 'learnpress' ),
170 + __( '<span class="count">%1$d</span> %2$s', 'learnpress' ),
155 171 $count_questions,
156 172 sprintf(
157 173 '<span class="one">%s</span><span class="plural">%s</span>',
158 174 __( 'Question', 'learnpress' ),
@@ -196,9 +212,12 @@
196 212 'wrap' => '<div class="question-edit-details lp-section-toggle">',
197 213 'header' => sprintf(
198 214 '<div class="lp-question-data-edit-header lp-trigger-toggle">
199 215 <label>%s</label>
200 - <div class="lp-tinymce-toggle"><span class="lp-icon-angle-down"></span><span class="lp-icon-angle-up"></span></div>
216 + <div class="lp-tinymce-toggle">
217 + <span class="lp-icon-angle-down"></span>
218 + <span class="lp-icon-angle-up"></span>
219 + </div>
201 220 </div>',
202 221 __( 'Option Details', 'learnpress' )
203 222 ),
204 223 'collapse' => '<div class="lp-section-collapse">',
@@ -231,16 +250,16 @@
231 250 'wrap' => sprintf(
232 251 '<div data-question-id="%s"
233 252 class="lp-question-item lp-section-toggle lp-collapse %s"
234 253 data-question-type="%s">',
235 - $question_id,
236 - $is_clone ? 'clone lp-hidden' : '',
237 - $is_clone ? '' : $questionPostModel->get_type()
254 + esc_attr( $question_id ),
255 + esc_attr( $is_clone ? 'clone lp-hidden' : '' ),
256 + esc_attr( $is_clone ? '' : $questionPostModel->get_type() )
238 257 ),
239 258 'head' => '<div class="lp-question-head">',
240 259 'drag' => sprintf(
241 260 '<span class="drag lp-icon-drag" title="%s"></span>',
242 - __( 'Drag to reorder section', 'learnpress' )
261 + esc_attr__( 'Drag to reorder section', 'learnpress' )
243 262 ),
244 263 'loading' => '<span class="lp-icon-spinner"></span>',
245 264 'title' => AdminEditQuestionTemplate::instance()->html_input_question_title( $question_title ),
246 265 'btn-update' => sprintf(
@@ -252,22 +271,32 @@
252 271 __( 'Cancel' )
253 272 ),
254 273 'type' => sprintf(
255 274 '<span class="lp-question-type-label">%s</span>',
256 - $questionPostModel instanceof QuestionPostModel ? $questionPostModel->get_type_label() : ''
275 + esc_html(
276 + $questionPostModel instanceof QuestionPostModel ? $questionPostModel->get_type_label() : ''
277 + )
257 278 ),
258 279 'btn-edit' => sprintf(
259 280 '<a class="lp-btn-edit-question-title lp-icon-edit-square" title="%s" href="%s" target="_blank"></a>',
260 - __( 'Edit question detail', 'learnpress' ),
261 - $questionPostModel instanceof QuestionPostModel ? $questionPostModel->get_edit_link() : '#'
281 + esc_attr__( 'Edit question detail', 'learnpress' ),
282 + esc_url(
283 + $questionPostModel instanceof QuestionPostModel ? $questionPostModel->get_edit_link() : '#'
284 + )
262 285 ),
263 286 'btn-delete' => sprintf(
264 287 '<span class="lp-btn-remove-question lp-icon-trash-o" title="%s" data-title="%s" data-content="%s"></span>',
265 - __( 'Remove question', 'learnpress' ),
266 - __( 'Are you sure?', 'learnpress' ),
267 - __( 'This question will be removed from this quiz. The question will no longer be assigned to this quiz, but will not be permanently deleted.', 'learnpress' )
288 + esc_attr__( 'Remove question', 'learnpress' ),
289 + esc_attr__( 'Are you sure?', 'learnpress' ),
290 + esc_attr__(
291 + 'This question will be removed from this quiz. The question will no longer be assigned to this quiz, but will not be permanently deleted.',
292 + 'learnpress'
293 + )
268 294 ),
269 - 'toggle' => '<div class="lp-question-toggle"><span class="lp-icon-angle-down"></span><span class="lp-icon-angle-up"></span></div>',
295 + 'toggle' => '<div class="lp-question-toggle">
296 + <span class="lp-icon-angle-down"></span>
297 + <span class="lp-icon-angle-up"></span>
298 + </div>',
270 299 'head_end' => '</div>',
271 300 'edit_main' => $html_edit_main,
272 301 'wrap_end' => '</div>',
273 302 ];
@@ -386,121 +415,134 @@
386 415 *
387 416 * @throws Exception
388 417 *
389 418 * @since 4.2.8.7
390 - * @version 1.0.1
419 + * @version 1.0.2
391 420 */
392 421 public static function render_list_items_not_assign( $data ): stdClass {
393 - $content = new stdClass();
394 - $quiz_id = $data['quiz_id'] ?? 0;
395 - $item_selecting = $data['item_selecting'] ?? [];
396 - $search_title = $data['search_title'] ?? '';
397 - $paged = intval( $data['paged'] ?? 1 );
398 - $item_selecting_compare = new stdClass();
422 + $content = new stdClass();
399 423
400 - $quizPostModel = QuizPostModel::find( $quiz_id, true );
401 - if ( ! $quizPostModel ) {
402 - throw new Exception( __( 'Quiz not found', 'learnpress' ) );
403 - }
424 + try {
425 + // Check permission
426 + if ( ! current_user_can( UserModel::ROLE_ADMINISTRATOR ) ) {
427 + throw new Exception( esc_html__( 'Access denied.', 'learnpress' ) );
428 + }
404 429
405 - $lp_posts_db = LP_Post_DB::getInstance();
406 - $filter = new PostFilter();
407 - $filter->only_fields = [
408 - 'DISTINCT(p.ID) AS ID',
409 - 'p.post_title',
410 - 'p.post_type',
411 - ];
412 - $filter->post_type = LP_QUESTION_CPT;
413 - $filter->post_status = [ 'publish' ];
414 - $filter->order_by = 'p.ID';
415 - $filter->page = $paged;
430 + $quiz_id = $data['quiz_id'] ?? 0;
431 + $item_selecting = $data['item_selecting'] ?? [];
432 + $search_title = $data['search_title'] ?? '';
433 + $paged = intval( $data['paged'] ?? 1 );
434 + $item_selecting_compare = new stdClass();
416 435
417 - if ( ! empty( $search_title ) ) {
418 - $filter->post_title = $search_title;
419 - }
436 + $quizPostModel = QuizPostModel::find( $quiz_id, true );
437 + if ( ! $quizPostModel ) {
438 + throw new Exception( __( 'Quiz not found', 'learnpress' ) );
439 + }
420 440
421 - // Old logic: Get all questions not assigned to any quiz.
422 - // New logic: Get all questions not assigned to the quiz.
423 - $filter->where[] = $lp_posts_db->wpdb->prepare(
424 - "AND p.ID NOT IN ( SELECT question_id FROM {$lp_posts_db->tb_lp_quiz_questions} WHERE quiz_id = %d )",
425 - $quizPostModel->ID
426 - );
441 + $lp_posts_db = LP_Post_DB::getInstance();
442 + $filter = new PostFilter();
443 + $filter->only_fields = [
444 + 'DISTINCT(p.ID) AS ID',
445 + 'p.post_title',
446 + 'p.post_type',
447 + ];
448 + $filter->post_type = LP_QUESTION_CPT;
449 + $filter->post_status = [ 'publish' ];
450 + $filter->order_by = 'p.ID';
451 + $filter->page = $paged;
427 452
453 + if ( ! empty( $search_title ) ) {
454 + $filter->post_title = $search_title;
455 + }
428 456
429 - $total_rows = 0;
430 - $posts = $lp_posts_db->get_posts( $filter, $total_rows );
431 - $total_pages = LP_Database::get_total_pages( $filter->limit, $total_rows );
457 + // Old logic: Get all questions not assigned to any quiz.
458 + // New logic: Get all questions not assigned to the quiz.
459 + $filter->where[] = $lp_posts_db->wpdb->prepare(
460 + "AND p.ID NOT IN ( SELECT question_id FROM {$lp_posts_db->tb_lp_quiz_questions} WHERE quiz_id = %d )",
461 + $quizPostModel->ID
462 + );
432 463
433 - $html_lis = '';
434 - if ( empty( $posts ) ) {
435 - $html_lis = sprintf( '<li>%s</li>', __( 'No items found', 'learnpress' ) );
436 - } else {
437 - if ( ! empty( $item_selecting ) ) {
438 - foreach ( $item_selecting as $item ) {
439 - if ( ! isset( $item['id'] ) || ! isset( $item['type'] ) ) {
464 + $total_rows = 0;
465 + $posts = $lp_posts_db->get_posts( $filter, $total_rows );
466 + $total_pages = LP_Database::get_total_pages( $filter->limit, $total_rows );
467 +
468 + $html_lis = '';
469 + if ( empty( $posts ) ) {
470 + $html_lis = sprintf( '<li>%s</li>', __( 'No items found', 'learnpress' ) );
471 + } else {
472 + if ( ! empty( $item_selecting ) ) {
473 + foreach ( $item_selecting as $item ) {
474 + if ( ! isset( $item['id'] ) || ! isset( $item['type'] ) ) {
475 + continue;
476 + }
477 +
478 + $item_selecting_compare->{$item['id']} = new stdClass();
479 + }
480 + }
481 +
482 + foreach ( $posts as $post ) {
483 + /**
484 + * @var $questionPostModel QuestionPostModel
485 + */
486 + $questionPostModel = QuestionPostModel::find( $post->ID, true );
487 + if ( ! $questionPostModel ) {
440 488 continue;
441 489 }
442 490
443 - $item_selecting_compare->{$item['id']} = new stdClass();
444 - }
445 - }
491 + $checked = '';
492 + if ( isset( $item_selecting_compare->{$post->ID} ) ) {
493 + $checked = ' checked="checked"';
494 + }
446 495
447 - foreach ( $posts as $post ) {
448 - /**
449 - * @var $questionPostModel QuestionPostModel
450 - */
451 - $questionPostModel = QuestionPostModel::find( $post->ID, true );
452 - if ( ! $questionPostModel ) {
453 - continue;
454 - }
496 + $title_display = sprintf(
497 + '<span class="title">%s<strong>(#%d - %s)</strong></span>',
498 + esc_html( $post->post_title ),
499 + $post->ID,
500 + esc_html( $questionPostModel->get_type_label() )
501 + );
455 502
456 - $checked = '';
457 - if ( isset( $item_selecting_compare->{$post->ID} ) ) {
458 - $checked = ' checked="checked"';
503 + $html_lis .= sprintf(
504 + '<li class="lp-select-item">%s%s</li>',
505 + sprintf(
506 + '<input name="lp-select-item"
507 + data-id="%d" data-type-label="%s"
508 + data-type="%s"
509 + data-title="%s" %s data-edit-link="%s"
510 + data-title-selected="%s"
511 + type="checkbox" />',
512 + esc_attr( $post->ID ?? 0 ),
513 + esc_attr( $questionPostModel->get_type_label() ?? '' ),
514 + esc_attr( $questionPostModel->get_type() ?? '' ),
515 + esc_attr( $title_display ), // For JS display on list selected.
516 + esc_attr( $checked ),
517 + esc_url( $questionPostModel->get_edit_link() ),
518 + esc_attr( $questionPostModel->get_the_title() ?? '' )
519 + ),
520 + $title_display
521 + );
459 522 }
523 + }
460 524
461 - $title_display = sprintf(
462 - '<span class="title">%s<strong>(#%d - %s)</strong></span>',
463 - $post->post_title,
464 - $post->ID,
465 - $questionPostModel->get_type_label()
466 - );
525 + $section = [
526 + 'ul' => '<ul class="list-items">',
527 + 'items' => $html_lis,
528 + 'ul_end' => '</ul>',
529 + 'pagination' => Template::instance()->html_pagination(
530 + [
531 + 'total_pages' => $total_pages,
532 + 'paged' => $paged,
533 + ]
534 + ),
535 + ];
467 536
468 - $html_lis .= sprintf(
469 - '<li class="lp-select-item">%s%s</li>',
470 - sprintf(
471 - '<input name="lp-select-item"
472 - data-id="%d" data-type-label="%s"
473 - data-type="%s"
474 - data-title="%s" %s data-edit-link="%s"
475 - data-title-selected="%s"
476 - type="checkbox" />',
477 - esc_attr( $post->ID ?? 0 ),
478 - esc_attr( $questionPostModel->get_type_label() ?? '' ),
479 - esc_attr( $questionPostModel->get_type() ?? '' ),
480 - esc_attr( $title_display ), // For JS display on list selected.
481 - esc_attr( $checked ),
482 - $questionPostModel->get_edit_link(),
483 - esc_attr( $questionPostModel->get_the_title() ?? '' )
484 - ),
485 - $title_display
486 - );
487 - }
537 + $content->content = Template::combine_components( $section );
538 + } catch ( Throwable $e ) {
539 + $content->content = Template::print_message(
540 + $e->getMessage(),
541 + Response::STATUS_ERROR,
542 + false
543 + );
488 544 }
489 -
490 - $section = [
491 - 'ul' => '<ul class="list-items">',
492 - 'items' => $html_lis,
493 - 'ul_end' => '</ul>',
494 - 'pagination' => Template::instance()->html_pagination(
495 - [
496 - 'total_pages' => $total_pages,
497 - 'paged' => $paged,
498 - ]
499 - ),
500 - ];
501 -
502 - $content->content = Template::combine_components( $section );
503 545
504 546 return $content;
505 547 }
506 548 }