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.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 / TemplateHooks / Course / AdminEditCurriculumTemplate.php

AdminEditCurriculumTemplate.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.3.8, at inc/TemplateHooks/Course/AdminEditCurriculumTemplate.php

744 lines 22.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace LearnPress\TemplateHooks\Course;
4
5 use Exception;
6 use LearnPress\Databases\DataBase;
7 use LearnPress\Databases\PostDB;
8 use LearnPress\Filters\PostFilter;
9 use LearnPress\Helpers\Singleton;
10 use LearnPress\Helpers\Template;
11 use LearnPress\Models\CourseModel;
12 use LearnPress\Models\CoursePostModel;
13 use LearnPress\Models\PostModel;
14 use LearnPress\Models\UserModel;
15 use LearnPress\TemplateHooks\Admin\AdminTemplate;
16 use LearnPress\TemplateHooks\TemplateAJAX;
17 use LP_Database;
18 use LP_Post_DB;
19 use LP_Post_Type_Filter;
20 use stdClass;
21
22 /**
23 * Template hooks Admin Edit Course Curriculum.
24 *
25 * @since 4.2.8.6
26 * @version 1.0.1
27 */
28 class AdminEditCurriculumTemplate {
29 use Singleton;
30
31 /**
32 * Course model.
33 *
34 * @var CourseModel
35 */
36 public $courseModel;
37
38 /**
39 * Context data from AJAX request.
40 * Contains flags like is_course_builder.
41 *
42 * @var array
43 */
44 public $context_data = [];
45
46 public function init() {
47 add_action( 'learn-press/admin/edit-curriculum/layout', [ $this, 'edit_course_curriculum_layout' ] );
48 add_filter( 'lp/rest/ajax/allow_callback', [ $this, 'allow_callback' ] );
49 }
50
51 /**
52 * Layout for edit course curriculum.
53 *
54 * @since 4.2.8.6
55 * @version 1.0.1
56 *
57 * @param CourseModel $courseModel
58 * @param array $context Additional context merged into AJAX args (e.g. ['is_course_builder' => true]).
59 */
60 public function edit_course_curriculum_layout( CourseModel $courseModel, array $context = [] ) {
61 wp_enqueue_style( 'lp-edit-curriculum' );
62 wp_enqueue_script( 'lp-edit-course' );
63
64 $args = array_merge(
65 [
66 'id_url' => 'edit-course-curriculum',
67 'course_id' => $courseModel->ID,
68 ],
69 $context
70 );
71
72 $call_back = [
73 'class' => self::class,
74 'method' => 'render_edit_course_curriculum',
75 ];
76
77 echo TemplateAJAX::load_content_via_ajax( $args, $call_back );
78 }
79
80 /**
81 * Allow callback for AJAX.
82 * @use self::render_edit_course_curriculum
83 * @use self::render_html
84 *
85 * @param array $callbacks
86 *
87 * @return array
88 */
89 public function allow_callback( array $callbacks ): array {
90 $callbacks[] = get_class( $this ) . ':render_edit_course_curriculum';
91 $callbacks[] = get_class( $this ) . ':render_list_items_not_assign';
92
93 return $callbacks;
94 }
95
96 /**
97 * Render edit course curriculum html.
98 *
99 * @throws Exception
100 */
101 public static function render_edit_course_curriculum( array $data ): stdClass {
102 $course_id = $data['course_id'] ?? 0;
103 $courseModel = CourseModel::find( $course_id, true );
104 if ( ! $courseModel ) {
105 throw new Exception( __( 'Course not found', 'learnpress' ) );
106 }
107
108 self::instance()->courseModel = $courseModel;
109 self::instance()->context_data = $data; // Store context data for filters
110
111 $coursePostModel = new CoursePostModel( $courseModel );
112 if ( ! $coursePostModel->check_capabilities_create() ) {
113 throw new Exception( __( 'You do not have permission to edit this course', 'learnpress' ) );
114 }
115
116 $content = new stdClass();
117 $content->content = self::instance()->html_edit_curriculum( $courseModel );
118
119 return $content;
120 }
121
122 /**
123 * HTML for edit curriculum.
124 *
125 * @param CourseModel $courseModel
126 *
127 * @return string
128 */
129 public function html_edit_curriculum( CourseModel $courseModel ): string {
130 $html_sections = '';
131
132 // Get sections items
133 $sections_items = $courseModel->get_section_items();
134 $count_sections = count( $sections_items );
135
136 foreach ( $sections_items as $section_items ) {
137 $html_sections .= $this->html_edit_section( $courseModel, $section_items );
138 }
139
140 $sections = [
141 'wrap' => '<div class="curriculum-sections">',
142 'list-sections' => $html_sections,
143 'section-clone' => $this->html_edit_section( $courseModel ),
144 'wrap_end' => '</div>',
145 ];
146
147 $section = [
148 'wrap' => '<div id="lp-course-edit-curriculum">',
149 'heading' => '<div class="heading">',
150 'h4' => sprintf(
151 '<h4>%s</h4>',
152 __( 'Details', 'learnpress' )
153 ),
154 'count-sections' => sprintf(
155 '<div class="count-sections" data-count="%s">%s</div>',
156 $count_sections,
157 sprintf(
158 __( '<span class="count">%1$s</span> %2$s', 'learnpress' ),
159 $count_sections,
160 sprintf(
161 '<span class="one">%s</span><span class="plural">%s</span>',
162 __( 'Section', 'learnpress' ),
163 __( 'Sections', 'learnpress' )
164 )
165 )
166 ),
167 'count-items' => sprintf(
168 '<div class="total-items" data-count="%s">%s</div>',
169 $courseModel->count_items(),
170 sprintf(
171 __( '<span class="count">%1$s</span> %2$s', 'learnpress' ),
172 $courseModel->count_items(),
173 sprintf(
174 '<span class="one">%s</span><span class="plural">%s</span>',
175 __( 'Item', 'learnpress' ),
176 __( 'Items', 'learnpress' )
177 )
178 )
179 ),
180 'section-toggle' =>
181 '<div class="course-toggle-all-sections lp-collapse">
182 <span class="lp-icon-angle-down"></span>
183 <span class="lp-icon-angle-up"></span>
184 </div>',
185 'heading_end' => '</div>',
186 'sections' => Template::combine_components( $sections ),
187 'add_new_section' => $this->html_add_new_section(),
188 'select_items' => $this->html_popup_items_to_select_clone( $courseModel ),
189 'wrap_end' => '</div>',
190 ];
191
192 return Template::combine_components( $section );
193 }
194
195 /**
196 * HTML for edit section.
197 *
198 * @param CourseModel $courseModel
199 * @param null|object $section_items
200 *
201 * @return string
202 */
203 public function html_edit_section( CourseModel $courseModel, $section_items = null ): string {
204 $is_clone = is_null( $section_items );
205 $total_items = 0;
206 $items = [];
207 $html_items = '';
208 $section_id = $section_items->section_id ?? 0;
209 $section_name = $section_items->section_name ?? '';
210
211 if ( ! $is_clone ) {
212 $total_items = count( $section_items->items ?? [] );
213 $items = $section_items->items ?? [];
214
215 foreach ( $items as $item ) {
216 $html_items .= $this->html_section_item( $courseModel, $item );
217 }
218 }
219
220 $section_list_items = [
221 'wrap' => '<ul class="section-list-items">',
222 'items' => $html_items,
223 'item_clone' => $this->html_section_item( $courseModel ),
224 'wrap_end' => '</ul>',
225 ];
226
227 $section = [
228 'wrap' => sprintf(
229 '<div data-section-id="%s" class="section lp-collapse %s">',
230 $section_id,
231 $is_clone ? 'clone lp-hidden' : ''
232 ),
233 'head' => '<div class="section-head">',
234 'drag' => sprintf(
235 '<span class="drag lp-icon-drag" title="%s"></span>',
236 __( 'Drag to reorder section', 'learnpress' )
237 ),
238 'loading' => '<span class="lp-icon-spinner"></span>',
239 'title' => $this->html_input_section_title( $section_name ),
240 'btn-edit' => sprintf(
241 '<span class="lp-btn-edit-section-title lp-icon-edit" title="%s"></span>',
242 __( 'Edit section title', 'learnpress' )
243 ),
244 'btn-delete' => sprintf(
245 '<button type="button" class="lp-btn-delete-section button"
246 data-send="%s"
247 data-title="%s" data-content="%s">%s
248 </button>',
249 Template::convert_data_to_json(
250 [
251 'action' => 'course_delete_section',
252 'course_id' => $courseModel->get_id(),
253 'id_url' => 'course-delete-section',
254 ]
255 ),
256 __( 'Are you sure?', 'learnpress' ),
257 __( 'This section will be deleted. The items in this section will no longer be assigned to this course, but will not be permanently deleted.', 'learnpress' ),
258 __( 'Delete Section', 'learnpress' )
259 ),
260 'btn-update' => sprintf(
261 '<button type="button" class="lp-btn-update-section-title button">%s</button>',
262 __( 'Update' )
263 ),
264 'btn-cancel' => sprintf(
265 '<button type="button" class="lp-btn-cancel-update-section-title button">%s</button>',
266 __( 'Cancel' )
267 ),
268 'count-items' => sprintf(
269 '<div class="section-items-counts" data-count="%s">%s</div>',
270 $total_items,
271 sprintf(
272 __( '<span class="count">%1$s</span> %2$s', 'learnpress' ),
273 $total_items,
274 sprintf(
275 '<span class="one">%s</span><span class="plural">%s</span>',
276 __( 'Item', 'learnpress' ),
277 __( 'Items', 'learnpress' )
278 )
279 )
280 ),
281 'toggle' => '<div class="section-toggle"><span class="lp-icon-angle-down"></span><span class="lp-icon-angle-up"></span></div>',
282 'head_end' => '</div>',
283 'wrap_content' => '<div class="section-collapse">',
284 'section-content' => '<div class="section-content">',
285 'section-description' => sprintf(
286 '<div class="section-description">%s%s%s</div>',
287 $this->html_edit_section_description( $section_items->section_description ?? '' ),
288 sprintf(
289 '<button type="button" class="lp-btn-update-section-description button">%s</button>',
290 __( 'Update' )
291 ),
292 sprintf(
293 '<button type="button" class="lp-btn-cancel-update-section-description button">%s</button>',
294 __( 'Cancel' )
295 )
296 ),
297 'section-list-items' => Template::combine_components( $section_list_items ),
298 'section-content-end' => '</div>',
299 'section-item-actions' => $this->html_section_item_actions(),
300 'wrap_content_end' => '</div>',
301 'wrap_end' => '</div>',
302 ];
303
304 return Template::combine_components( $section );
305 }
306
307 /**
308 * HTML input section title.
309 *
310 * @param string $section_name
311 *
312 * @return string
313 */
314 public function html_input_section_title( string $section_name = '' ): string {
315 return sprintf(
316 '<input class="lp-section-title-input"
317 name="lp-section-title-input"
318 type="text"
319 value="%1$s"
320 data-old="%1$s"
321 placeholder="%2$s"
322 data-mess-empty-title="%3$s"
323 data-send="%4$s">',
324 esc_attr( $section_name ),
325 esc_attr__( 'Update section title', 'learnpress' ),
326 esc_attr__( 'Section title is required', 'learnpress' ),
327 Template::convert_data_to_json(
328 [
329 'action' => 'course_update_section',
330 'course_id' => $this->courseModel->get_id(),
331 'id_url' => 'course-update-section-title',
332 ]
333 )
334 );
335 }
336
337 /**
338 * HTML for section description input.
339 *
340 * @param string|null $section_description
341 *
342 * @return string
343 */
344 public function html_edit_section_description( string $section_description = '' ): string {
345 return sprintf(
346 '<textarea class="lp-section-description-input"
347 name="lp-section-description-input"
348 type="text"
349 data-old="%1$s"
350 placeholder="%2$s"
351 data-send="%3$s">%1$s</textarea>',
352 esc_attr( $section_description ),
353 esc_attr__( '+ Add Description', 'learnpress' ),
354 Template::convert_data_to_json(
355 [
356 'action' => 'course_update_section',
357 'course_id' => $this->courseModel->get_id(),
358 'id_url' => 'course-update-section-description',
359 ]
360 )
361 );
362 }
363
364 /**
365 * HTML add new section.
366 *
367 * @return string
368 */
369 public function html_add_new_section(): string {
370 $section = [
371 'wrap' => '<div class="add-new-section">',
372 'icon' => '<span class="lp-icon-plus"></span>',
373 'input' => sprintf(
374 '<input class="lp-section-title-new-input"
375 name="lp-section-title-new-input"
376 type="text"
377 title="%1$s"
378 placeholder="%1$s"
379 data-mess-empty-title="%2$s"
380 data-send="%3$s">',
381 esc_attr__( 'Create a new section', 'learnpress' ),
382 esc_attr__( 'Section title is required', 'learnpress' ),
383 Template::convert_data_to_json(
384 [
385 'action' => 'course_add_section',
386 'course_id' => $this->courseModel->get_id(),
387 'id_url' => 'course-add-section',
388 ]
389 ),
390 ),
391 'button' => sprintf(
392 '<button type="button"
393 class="lp-btn-add-section button lp-btn-edit-primary">%s
394 </button>',
395 __( 'Add Section', 'learnpress' )
396 ),
397 'wrap_end' => '</div>',
398 ];
399
400 return Template::combine_components( $section );
401 }
402
403 /**
404 * HTML for section item.
405 * $item is null when clone item new
406 *
407 * @param CourseModel $courseModel
408 * @param null|object $item
409 *
410 * @return string
411 */
412 public function html_section_item( CourseModel $courseModel, $item = null ): string {
413 $is_clone = is_null( $item );
414 $item_id = $item->item_id ?? 0;
415 $item_title = $item->title ?? '';
416 $item_type = $item->item_type ?? '';
417
418 /**
419 * @var $itemModel PostModel
420 */
421 $itemModel = $courseModel->get_item_model( $item_id, $item_type );
422
423 $edit_button = apply_filters(
424 'learn-press/admin/curriculum/section-item/edit-button',
425 sprintf(
426 '<li title="%s"><a href="%s" target="_blank" class="lp-icon-edit-square edit-link"></a></li>',
427 __( 'Edit item detail', 'learnpress' ),
428 $itemModel ? $itemModel->get_edit_link() : ''
429 ),
430 $item,
431 $itemModel,
432 $courseModel
433 );
434
435 $section_action = [
436 'wrap' => '<ul class="item-actions">',
437 'preview' => sprintf(
438 '<li title="%s" class="lp-btn-set-preview-item"><a class="%s"></a></li>',
439 __( 'Enable/Disable Preview', 'learnpress' ),
440 $itemModel && $itemModel->post_type === LP_LESSON_CPT
441 && $itemModel->has_preview() ? 'lp-icon-eye' : 'lp-icon-eye-slash'
442 ),
443 'edit' => $edit_button,
444 'delete' => sprintf(
445 '<li class="action lp-btn-delete-item"
446 data-title="%s" data-content="%s">%s</li>',
447 __( 'Are you sure?', 'learnpress' ),
448 __( 'This item will be removed from this section. This item will no longer be assigned to this course. It will not be permanently deleted from the system.', 'learnpress' ),
449 sprintf( '<a class="lp-icon-trash-o" title="%s"></a>', __( 'Remove item', 'learnpress' ) )
450 ),
451 'wrap_end' => '</ul>',
452 ];
453
454 $section_action = apply_filters(
455 'learn-press/admin/curriculum/section-item/actions',
456 $section_action,
457 $item,
458 $itemModel,
459 $courseModel,
460 $this->context_data
461 );
462
463 $section = [
464 'li' => sprintf(
465 '<li data-item-id="%s" data-item-type="%s" class="section-item %s %s">',
466 $item_id,
467 $item_type,
468 $item_type,
469 $is_clone ? 'clone lp-hidden' : ''
470 ),
471 'drag' => sprintf(
472 '<span class="drag lp-icon-drag" title="%s"></span>',
473 __( 'Drag to reorder item', 'learnpress' )
474 ),
475 'icon' => '<div class="item-ico-type"></div>',
476 'loading' => '<span class="lp-icon-spinner"></span>',
477 'input-title' => sprintf(
478 '<input name="%1$s" class="%1$s" type="text" value="%2$s" data-old="%2$s" data-mess-empty-title="%3$s">',
479 'lp-item-title-input',
480 wp_kses_post( $item_title ),
481 esc_attr__( 'Item title is required', 'learnpress' )
482 ),
483 'btn-update' => sprintf(
484 '<button type="button" class="lp-btn-update-item-title button button-primary">%s</button>',
485 __( 'Update' )
486 ),
487 'btn-cancel' => sprintf(
488 '<button type="button" class="lp-btn-cancel-update-item-title button">%s</button>',
489 __( 'Cancel' )
490 ),
491 'item_actions' => Template::combine_components( $section_action ),
492 'li_end' => '</li>',
493 ];
494
495 return Template::combine_components( $section );
496 }
497
498 public function html_section_item_actions(): string {
499 $course_item_types = CourseModel::item_types_support();
500
501 $html_buttons = '';
502 foreach ( $course_item_types as $type ) {
503 $item_label = CourseModel::item_types_label( $type );
504
505 $html_buttons .= sprintf(
506 '<button class="lp-btn-select-item-type button"
507 data-item-type="%s"
508 data-placeholder="%s"
509 data-button-add-text="%s"
510 type="button">%s</button>',
511 $type,
512 sprintf( __( 'Create a new %s', 'learnpress' ), $item_label ),
513 sprintf( __( 'Add %s', 'learnpress' ), $item_label ),
514 sprintf( __( 'New %s', 'learnpress' ), $item_label )
515 );
516 }
517
518 $section = [
519 'wrap' => '<div class="section-actions">',
520 'buttons' => $html_buttons,
521 'btn-select-items' => sprintf(
522 '<button type="button"
523 data-template="#lp-tmpl-select-course-items-bank"
524 class="button lp-btn-show-popup-items-to-select">
525 %s</button>',
526 __( 'Content Bank', 'learnpress' )
527 ),
528 'add-item-type' => $this->html_add_item_type(),
529 'wrap_end' => '</div>',
530 ];
531
532 return Template::combine_components( $section );
533 }
534
535 /**
536 * HTML for section item new.
537 *
538 * @return string
539 */
540 public function html_add_item_type(): string {
541 $section = [
542 'wrap' => '<div class="lp-add-item-type clone lp-hidden">',
543 'icon-plus' => '<div class="lp-icon-plus"></div>',
544 'item-ico-type' => '<div class="item-ico-type"></div>',
545 'actions' => '<div class="new-item-actions">',
546 'input' => sprintf(
547 '<input class="%1$s" name="%1$s" data-mess-empty-title="%2$s" type="text"/>',
548 'lp-add-item-type-title-input',
549 esc_attr__( 'Item title is required', 'learnpress' )
550 ),
551 'button_add' => '<button class="lp-btn-add-item button button-primary" type="button"></button>',
552 'button_cancel' => sprintf(
553 '<button class="lp-btn-add-item-cancel button" type="button">%s</button>',
554 __( 'Cancel' )
555 ),
556 'actions_end' => '</div>',
557 'wrap_end' => '</div>',
558 ];
559
560 return Template::combine_components( $section );
561 }
562
563 /**
564 * HTML for popup items to select.
565 *
566 * @param CourseModel $course_model
567 *
568 * @return string
569 */
570 public function html_popup_items_to_select_clone( CourseModel $course_model ): string {
571 /**
572 * @uses self::render_list_items_not_assign
573 */
574 $html_items = TemplateAJAX::load_content_via_ajax(
575 [
576 'id_url' => 'list-items-not-assign',
577 'enableScrollToView' => false,
578 'course_id' => $course_model->ID,
579 'item_type' => LP_LESSON_CPT,
580 'paged' => 1,
581 ],
582 [
583 'class' => self::class,
584 'method' => 'render_list_items_not_assign',
585 ]
586 );
587
588 $tabs = [];
589 $course_item_types = CourseModel::item_types_support();
590 foreach ( $course_item_types as $type ) {
591 $item_label = CourseModel::item_types_label( $type );
592 $tabs[ $type ] = $item_label;
593 }
594
595 $section = [
596 'wrap-script-template' => '<script type="text/template" id="lp-tmpl-select-course-items-bank">',
597 'popup' => AdminTemplate::html_popup_items_to_select_clone( $tabs, $html_items ),
598 'wrap-script-template-end' => '</div>',
599 ];
600
601 return Template::combine_components( $section );
602 }
603
604 /**
605 * Render list items not assign to course.
606 * Get all items not assigned to any course, use old logic.
607 * If user current is Admin, get all items.
608 * Else get all items created by user current.
609 *
610 * @throws Exception
611 * @since 4.2.8.6
612 * @version 1.0.4
613 */
614 public static function render_list_items_not_assign( $data ): stdClass {
615 $user = wp_get_current_user();
616 $content = new stdClass();
617 $course_id = $data['course_id'] ?? 0;
618 $item_type = $data['item_type'] ?? LP_LESSON_CPT;
619 $item_selecting = $data['item_selecting'] ?? [];
620 $search_title = $data['search_title'] ?? '';
621 $paged = intval( $data['paged'] ?? 1 );
622 $item_selecting_compare = new stdClass();
623
624 $courseModel = CourseModel::find( $course_id, true );
625 if ( ! $courseModel ) {
626 throw new Exception( __( 'Course not found', 'learnpress' ) );
627 }
628
629 // Check permission
630 $coursePostModel = new CoursePostModel( $courseModel );
631 if ( ! $coursePostModel->check_capabilities_create() ) {
632 throw new Exception( __( 'You do not have permission view list', 'learnpress' ) );
633 }
634
635 $lp_posts_db = PostDB::getInstance();
636 $filter = new PostFilter();
637 $filter->only_fields = [
638 'DISTINCT(p.ID) AS ID',
639 'p.post_title',
640 'p.post_type',
641 ];
642 $filter->post_type = $item_type;
643 $filter->post_status = [ 'publish' ];
644 $filter->order_by = 'p.ID';
645 $filter->page = $paged;
646 if ( ! user_can( $user, UserModel::ROLE_ADMINISTRATOR ) ) {
647 $filter->post_author = $user->ID;
648 }
649
650 if ( ! empty( $search_title ) ) {
651 $filter->post_title = $search_title;
652 }
653
654 // Old logic: Get all items not assigned to any course.
655 $filter->where[] = "AND p.ID NOT IN ( SELECT item_id FROM {$lp_posts_db->tb_lp_section_items} )";
656
657 // New logic: Get all items not assigned to the course.
658 // Code here
659
660 $total_rows = 0;
661 $filter = apply_filters(
662 'learn-press/filter-list-items-not-assign-course',
663 $filter,
664 $data,
665 $courseModel
666 );
667 $posts = $lp_posts_db->get_posts( $filter, $total_rows );
668 $total_pages = LP_Database::get_total_pages( $filter->limit, $total_rows );
669
670 $html_lis = '';
671 if ( empty( $posts ) ) {
672 $html_lis = sprintf( '<li>%s</li>', __( 'No items found', 'learnpress' ) );
673 } else {
674 if ( ! empty( $item_selecting ) ) {
675 foreach ( $item_selecting as $item ) {
676 if ( ! isset( $item['item_id'] ) || ! isset( $item['item_type'] ) ) {
677 continue;
678 }
679
680 $item_selecting_compare->{$item['item_id']} = new stdClass();
681 $item_selecting_compare->{$item['item_id']}->item_type = $item['item_type'];
682 }
683 }
684
685 foreach ( $posts as $post ) {
686 /**
687 * @var $itemModel PostModel
688 */
689 $itemModel = $courseModel->get_item_model( $post->ID, $post->post_type );
690 if ( ! $itemModel ) {
691 continue;
692 }
693
694 $checked = '';
695
696 if ( isset( $item_selecting_compare->{$post->ID} ) ) {
697 $checked = ' checked="checked"';
698 }
699
700 $title_display = sprintf(
701 '<span class="title">%s<strong>(#%d)</strong></span>',
702 $post->post_title,
703 $post->ID,
704 );
705
706 $html_lis .= sprintf(
707 '<li class="lp-select-item">%s%s</li>',
708 sprintf(
709 '<input name="lp-select-item"
710 data-id="%d"
711 data-type="%s"
712 data-title="%s" %s data-edit-link="%s"
713 data-title-selected="%s"
714 type="checkbox" />',
715 esc_attr( $post->ID ?? 0 ),
716 esc_attr( $post->post_type ?? '' ),
717 esc_attr( $title_display ), // For JS display on list selected.
718 esc_attr( $checked ),
719 get_edit_post_link( $post->ID ),
720 esc_attr( get_the_title( $post->ID ) )
721 ),
722 $title_display
723 );
724 }
725 }
726
727 $section = [
728 'ul' => '<ul class="list-items">',
729 'items' => $html_lis,
730 'ul_end' => '</ul>',
731 'pagination' => Template::instance()->html_pagination(
732 [
733 'total_pages' => $total_pages,
734 'paged' => $paged,
735 ]
736 ),
737 ];
738
739 $content->content = Template::combine_components( $section );
740
741 return $content;
742 }
743 }
744