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

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

935 lines 26.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Template hooks List Courses.
4 *
5 * @since 4.2.3.2
6 * @version 1.0.3
7 */
8
9 namespace LearnPress\TemplateHooks\Course;
10
11 use LearnPress\Helpers\Singleton;
12 use LearnPress\Helpers\Template;
13 use LearnPress\Models\CourseModel;
14 use LearnPress\Models\Courses;
15 use LearnPress\Models\UserItems\UserCourseModel;
16 use LearnPress\TemplateHooks\TemplateAJAX;
17 use LP_Course;
18 use LP_Course_Filter;
19 use LP_Database;
20 use LP_Settings;
21 use LP_Settings_Courses;
22 use LP_User_Items_DB;
23 use LP_User_Items_Filter;
24 use LP_WP_Filesystem;
25 use stdClass;
26 use Throwable;
27 use WP_Term;
28
29 class ListCoursesTemplate {
30 use Singleton;
31
32 public function init() {
33 add_action( 'learn-press/list-courses/layout', [ $this, 'layout_courses' ] );
34 add_action( 'learn-press/rest-api/courses/suggest/layout', [ $this, 'sections_course_suggest' ] );
35 add_action( 'learn-press/archive-course/sidebar', [ $this, 'sidebar' ] );
36 add_filter( 'lp/rest/ajax/allow_callback', [ $this, 'allow_callback' ] );
37 }
38
39 public function allow_callback( $callbacks ) {
40 /**
41 * @uses self::render_courses()
42 */
43 $callbacks[] = get_class( $this ) . ':render_courses';
44
45 return $callbacks;
46 }
47
48 /**
49 * Layout default list courses.
50 *
51 * @return void
52 * @since 4.2.5.8
53 * @version 1.0.1
54 */
55 public function layout_courses() {
56 $html_wrapper = [
57 '<div class="lp-list-courses-default">' => '</div>',
58 ];
59
60 $callback = [
61 'class' => get_class( $this ),
62 'method' => 'render_courses',
63 ];
64
65 $args = lp_archive_skeleton_get_args();
66 $args['id_url'] = 'list-courses-default';
67 $args['courses_load_ajax'] = LP_Settings_Courses::is_ajax_load_courses() ? 1 : 0;
68 $args['courses_first_no_ajax'] = LP_Settings_Courses::is_no_load_ajax_first_courses() ? 1 : 0;
69
70 // Load list courses via AJAX.
71 if ( LP_Settings_Courses::is_ajax_load_courses() && ! LP_Settings_Courses::is_no_load_ajax_first_courses() ) {
72 $content = TemplateAJAX::load_content_via_ajax( $args, $callback );
73 } else { // Load courses first not AJAX, or for filter.
74 $content_obj = static::render_courses( $args );
75 $args['html_no_load_ajax_first'] = $content_obj->content;
76 $content = TemplateAJAX::load_content_via_ajax( $args, $callback );
77 }
78
79 echo Template::instance()->nest_elements( $html_wrapper, $content );
80 }
81
82 /**
83 * Render template list courses with settings param.
84 *
85 * @param array $settings
86 *
87 * @return stdClass { content: string_html }
88 * @since 4.2.5.7
89 * @version 1.0.5
90 */
91 public static function render_courses( array $settings = [] ): stdClass {
92 $filter = new LP_Course_Filter();
93 Courses::handle_params_for_query_courses( $filter, $settings );
94
95 $total_rows = 0;
96 $courses = Courses::get_courses( $filter, $total_rows );
97 $total_pages = LP_Database::get_total_pages( $filter->limit, $total_rows );
98 $settings['total_pages'] = $total_pages;
99 $settings['total_rows'] = $total_rows;
100 $settings['courses_per_page'] = $filter->limit;
101 $skin = $settings['skin'] ?? ( wp_is_mobile() ? 'grid' : learn_press_get_courses_layout() );
102 $paged = $settings['paged'] ?? 1;
103 $settings['paged'] = $paged;
104 $listCoursesTemplate = self::instance();
105
106 // HTML section courses.
107 $html_courses = '';
108 if ( empty( $courses ) ) {
109 $html_courses = Template::print_message( __( 'No courses found', 'learnpress' ), 'info', false );
110 } else {
111 foreach ( $courses as $courseObj ) {
112 $course = CourseModel::find( $courseObj->ID, true );
113 $html_courses .= static::render_course( $course, $settings );
114 }
115 }
116
117 $section_courses = apply_filters(
118 'learn-press/layout/list-courses/section/courses',
119 [
120 'wrap' => sprintf(
121 '<ul class="learn-press-courses lp-list-courses-no-css %1$s" data-layout="%1$s">',
122 esc_attr( $skin )
123 ),
124 'courses' => $html_courses,
125 'wrap_end' => '</ul>',
126 ],
127 $courses,
128 $settings
129 );
130
131 $section_top = apply_filters(
132 'learn-press/layout/list-courses/section/top',
133 [
134 'wrapper' => '<div class="lp-courses-bar">',
135 'search' => $listCoursesTemplate->html_search_form( $settings ),
136 'order_by' => $listCoursesTemplate->html_order_by( $settings['order_by'] ?? 'post_date' ),
137 'switch_layout' => $listCoursesTemplate->switch_layout(),
138 'btn_filter_courses_mobile' => FilterCourseTemplate::instance()->html_btn_filter_mobile( $settings ),
139 'wrapper_end' => '</div>',
140 ],
141 $courses,
142 $settings
143 );
144
145 // For old themes use old hook.
146 $section_top = self::fix_theme_cb_hook_courses( $section_top, $courses, $settings );
147 //$section= self::fix_theme_el_hook_old_render_courses( $section, $courses, $settings );
148 // End.
149
150 // Pagination html
151 $data_pagination_type = LP_Settings::get_option( 'course_pagination_type', 'number' );
152 if ( empty( $settings['courses_load_ajax'] ) ) {
153 $data_pagination_type = 'number';
154 }
155 $data_pagination = [
156 'total_pages' => $total_pages,
157 'type' => $data_pagination_type,
158 'base' => add_query_arg( 'paged', '%#%', $settings['url_current'] ?? '' ),
159 'paged' => $settings['paged'] ?? 1,
160 ];
161 $html_pagination = static::instance()->html_pagination( $data_pagination );
162
163 $section = apply_filters(
164 'learn-press/layout/list-courses/section',
165 [
166 'top' => Template::combine_components( $section_top ),
167 'courses' => Template::combine_components( $section_courses ),
168 'pagination' => $html_pagination,
169 ],
170 $courses,
171 $settings
172 );
173
174 $content = new stdClass();
175 $content->content = Template::combine_components( $section );
176 $content->total_pages = $total_pages;
177 $content->paged = $paged;
178
179 return $content;
180 }
181
182 /**
183 * Render single item course
184 *
185 * @param CourseModel|LP_Course $course
186 * @param array $settings
187 *
188 * @return string
189 * @since 4.2.5.8
190 * @version 1.0.4
191 */
192 public static function render_course( $course, array $settings = [] ): string {
193 if ( ! $course instanceof CourseModel ) {
194 $course = CourseModel::find( $course->get_id(), true );
195 }
196 $singleCourseTemplate = SingleCourseTemplate::instance();
197 $show_view_students = ! empty( $settings['show_view_students'] );
198
199 try {
200 // New layout course item.
201
202 // HTML top section, show image.
203 $section_top = apply_filters(
204 'learn-press/layout/list-courses/item/section-top',
205 [
206 'wrapper' => '<div class="course-thumbnail">',
207 'img' => sprintf(
208 '<a href="%s">%s</a>',
209 esc_url( $course->get_permalink() ),
210 $singleCourseTemplate->html_image( $course )
211 ),
212 'wrapper_end' => '</div>',
213 ],
214 $course,
215 $settings
216 );
217
218 // HTML meta section.
219 $meta_data = apply_filters(
220 'learn-press/layout/list-courses/item/meta-data',
221 [
222 'duration' => $singleCourseTemplate->html_duration( $course ),
223 'level' => $singleCourseTemplate->html_level( $course ),
224 'lesson' => $singleCourseTemplate->html_count_item( $course, LP_LESSON_CPT ),
225 'quiz' => $singleCourseTemplate->html_count_item( $course, LP_QUIZ_CPT ),
226 'student' => $singleCourseTemplate->html_count_student( $course ),
227 ],
228 $course,
229 $settings
230 );
231
232 if ( $course->is_offline() ) {
233 $singleCourseOfflineTemplate = SingleCourseOfflineTemplate::instance();
234 unset( $meta_data['quiz'] );
235 unset( $meta_data['student'] );
236 if ( ! empty( $meta_data['lesson'] ) ) {
237 $meta_data['lesson'] = $singleCourseOfflineTemplate->html_lesson_info( $course, true );
238 }
239
240 // Add address for offline course.
241 $html_address = $singleCourseOfflineTemplate->html_address( $course );
242 if ( ! empty( $html_address ) ) {
243 $meta_data['address'] = $singleCourseOfflineTemplate->html_address( $course );
244 }
245 }
246
247 $html_meta_data = '';
248 if ( ! empty( $meta_data ) ) {
249 foreach ( $meta_data as $k => $v ) {
250 $html_meta_data .= sprintf( '<div class="meta-item meta-item-%s">%s</div>', $k, $v );
251 }
252
253 $html_meta_data = sprintf( '<div class="course-wrap-meta">%s</div>', $html_meta_data );
254 }
255
256 $btn_read_more_text = SingleCourseTemplate::text_button_course( $course );
257
258 // HTML bottom section end.
259 $section_bottom_end = apply_filters(
260 'learn-press/layout/list-courses/item/section/bottom/end',
261 [
262 'short_des' => $singleCourseTemplate->html_short_description( $course ),
263 'wrapper' => '<div class="course-info">',
264 //'clearfix' => '<div class="clearfix"></div>',
265 //'course_footer' => '<div class="course-footer">',
266 'price' => $singleCourseTemplate->html_price( $course ),
267 'btn_read_more' => sprintf(
268 '<div class="course-readmore"><a href="%s">%s</a></div>',
269 esc_url( $course->get_permalink() ),
270 $btn_read_more_text
271 ),
272 'btn_view_list' => $show_view_students ? sprintf(
273 '<div class="lp-wrap-btn-view-course-students">
274 <button type="button" class="lp-button lp-btn-view-students" data-course-id="%s" data-course-title="%s">%s</button>
275 </div>',
276 esc_attr( $course->get_id() ),
277 esc_attr( $course->get_title() ),
278 esc_html__( 'View List Students', 'learnpress' )
279 ) : '',
280 //'course_footer_end' => '</div>',
281 'wrapper_end' => '</div>',
282 ],
283 $course,
284 $settings
285 );
286
287 // HTML bottom section.
288 $html_categories = $singleCourseTemplate->html_categories( $course );
289 if ( ! empty( $html_categories ) ) {
290 $html_categories = sprintf(
291 '<div>%s %s</div>',
292 sprintf( '<label>%s</label>', __( 'in', 'learnpress' ) ),
293 $html_categories
294 );
295 }
296 $section_bottom = apply_filters(
297 'learn-press/layout/list-courses/item/section/bottom',
298 [
299 'wrapper' => '<div class="course-content">',
300 'title' => sprintf(
301 '<h3 class="wap-course-title"><a class="course-permalink" href="%s">%s</a></h3>',
302 esc_url( $course->get_permalink() ),
303 $singleCourseTemplate->html_title( $course )
304 ),
305 'featured' => $singleCourseTemplate->html_featured( $course ),
306 'wrapper_instructor_cate' => '<div class="course-instructor-category">',
307 'instructor' => sprintf(
308 '<div>%s %s</div>',
309 sprintf( '<label>%s</label>', __( 'by', 'learnpress' ) ),
310 $singleCourseTemplate->html_instructor( $course )
311 ),
312 'category' => $html_categories,
313 'wrapper_instructor_cate_end' => '</div>',
314 'meta' => $html_meta_data,
315 'info' => Template::combine_components( $section_bottom_end ),
316 'wrapper_end' => '</div>',
317 ],
318 $course,
319 $settings
320 );
321
322 $section = apply_filters(
323 'learn-press/layout/list-courses/item-li',
324 [
325 'wrapper_li' => '<li class="course">',
326 'wrapper_div' => sprintf( '<div class="course-item" data-id="%s">', esc_attr( $course->get_id() ) ),
327 'top' => Template::combine_components( $section_top ),
328 'bottom' => Template::combine_components( $section_bottom ),
329 'wrapper_div_end' => '</div>',
330 'wrapper_li_end' => '</li>',
331 ],
332 $course,
333 $settings
334 );
335
336 // For old themes use old hook.
337 $section = self::fix_theme_course_old( $section, $course, $settings );
338 // End.
339
340 $html_item = Template::combine_components( $section );
341 // End new layout course item.
342 } catch ( Throwable $e ) {
343 $html_item = $e->getMessage();
344 }
345
346 return $html_item;
347 }
348
349 /**
350 * Button Load more
351 *
352 * @return string
353 * @since 4.2.3.3
354 * @version 1.0.0
355 */
356 public function html_pagination_load_more(): string {
357 $html_wrapper = [
358 '<button class="courses-btn-load-more learn-press-pagination lp-button courses-btn-load-more-no-css">' => '</button>',
359 ];
360 $content = sprintf(
361 '%s<span class="lp-loading-circle lp-loading-no-css hide"></span>',
362 __( 'Load more', 'learnpress' )
363 );
364
365 return Template::instance()->nest_elements( $html_wrapper, $content );
366 }
367
368 /**
369 * Button infinite
370 *
371 * @return string
372 * @since 4.2.3.3
373 * @version 1.0.0
374 */
375 public function html_pagination_infinite(): string {
376 $html_wrapper = [
377 '<div class="courses-load-infinite-no-css courses-load-infinite learn-press-pagination">' => '</div>',
378 ];
379 $content = '<span class="lp-loading-circle lp-loading-no-css hide"></span>';
380
381 return Template::instance()->nest_elements( $html_wrapper, $content );
382 }
383
384 /**
385 * Pagination number
386 *
387 * @param array $data
388 *
389 * @return string
390 * @since 4.2.3.3
391 * @version 1.0.0
392 */
393 public function html_pagination_number( array $data = [] ): string {
394 if ( empty( $data['total_pages'] ) || $data['total_pages'] <= 1 ) {
395 return '';
396 }
397
398 $html_wrapper = $data['wrapper'] ?? [
399 '<nav class="learn-press-pagination navigation pagination">' => '</nav>',
400 ];
401
402 $pagination = paginate_links(
403 apply_filters(
404 'learn_press_pagination_args',
405 array(
406 'base' => $data['base'] ?? '',
407 'format' => '',
408 'add_args' => '',
409 'current' => max( 1, $data['paged'] ?? 1 ),
410 'total' => $data[ 'total_pages' ?? 1 ],
411 'prev_text' => '<i class="lp-icon-arrow-left"></i>',
412 'next_text' => '<i class="lp-icon-arrow-right"></i>',
413 'type' => 'list',
414 'end_size' => 3,
415 'mid_size' => 3,
416 )
417 )
418 );
419
420 return Template::instance()->nest_elements( $html_wrapper, $pagination );
421 }
422
423 /**
424 * Pagination
425 *
426 * @param array $data
427 *
428 * @return string
429 * @since 4.2.3.3
430 * @version 1.0.0
431 */
432 public function html_pagination( array $data = [] ): string {
433 if ( empty( $data['total_pages'] ) || $data['total_pages'] <= 1 ) {
434 return '';
435 }
436
437 $pagination_type = $data['type'] ?? 'number';
438 switch ( $pagination_type ) {
439 case 'load-more':
440 if ( $data['paged'] >= $data['total_pages'] ) {
441 return '';
442 }
443
444 return $this->html_pagination_load_more();
445 case 'infinite':
446 if ( $data['paged'] >= $data['total_pages'] ) {
447 return '';
448 }
449
450 return $this->html_pagination_infinite();
451 default:
452 return $this->html_pagination_number( $data );
453 }
454 }
455
456 /**
457 * Pagination
458 *
459 * @param array $data
460 *
461 * @return string
462 * @since 4.2.3.3
463 * @version 1.0.1
464 */
465 public function html_courses_page_result( array $data = [] ): string {
466 $html = '';
467
468 try {
469 $total_rows = $data['total_rows'] ?? 0;
470 $paged = $data['paged'] ?? 1;
471 $course_per_page = $data['courses_per_page'] ?? 8;
472 $pagination_type = $data['pagination_type'] ?? 'number';
473
474 $from = 1 + ( $paged - 1 ) * $course_per_page;
475 $to = ( $paged * $course_per_page > $total_rows ) ? $total_rows : $paged * $course_per_page;
476
477 $content = '';
478 if ( 0 === $total_rows ) {
479
480 } elseif ( 1 === $total_rows ) {
481 $content = esc_html__( 'Showing only one result', 'learnpress' );
482 } else {
483 $from_to = $from . '-' . $to;
484 // For pagination type is load-more or infinite.
485 if ( $pagination_type !== 'number' ) {
486 $from_to = '1 - ' . $to;
487 }
488 $content = sprintf( esc_html__( 'Showing %1$s of %2$s results', 'learnpress' ), $from_to, $total_rows );
489 }
490
491 if ( ! empty( $content ) ) {
492 $html = '<span class="courses-page-result">' . $content . '</span>';
493 }
494 } catch ( Throwable $e ) {
495 error_log( $e->getMessage() );
496 }
497
498 return $html;
499 }
500
501 /**
502 * Layouts type
503 *
504 * @param array $data
505 *
506 * @return string
507 * @since 4.2.3.3
508 * @version 1.0.0
509 */
510 public function html_layout_type( array $data = [] ): string {
511 $html_wrapper = [
512 '<div class="courses-layouts-display">' => '</div>',
513 ];
514
515 $ico_grid_default = LP_WP_Filesystem::get_icon_svg( 'ico-grid.svg' );
516 $ico_list_default = LP_WP_Filesystem::get_icon_svg( 'ico-list.svg' );
517
518 $layouts = [
519 'list' => $data['courses_ico_list'] ?? $ico_list_default,
520 'grid' => $data['courses_ico_grid'] ?? $ico_grid_default,
521 ];
522
523 $content = '<ul class="courses-layouts-display-list">';
524 foreach ( $layouts as $k => $v ) {
525 $active = ( $data['courses_layout_default'] ?? '' ) === $k ? 'active' : '';
526 $content .= sprintf(
527 '<li class="courses-layout %s" data-layout="%s">%s</li>',
528 esc_attr( $active ),
529 esc_attr( $k ),
530 $v
531 );
532 }
533 $content .= '</ul>';
534
535 return Template::instance()->nest_elements( $html_wrapper, $content );
536 }
537
538 /**
539 * Order by
540 *
541 * @param string $default_value
542 *
543 * @return string
544 * @since 4.2.3.2
545 * @version 1.0.1
546 */
547 public function html_order_by( string $default_value = 'post_date' ): string {
548 $html_wrapper = [
549 '<div class="courses-order-by-wrapper">' => '</div>',
550 ];
551
552 $values = apply_filters(
553 'learn-press/courses/order-by/values',
554 [
555 'post_date' => esc_html__( 'Newly published', 'learnpress' ),
556 'post_title' => esc_html__( 'Title a-z', 'learnpress' ),
557 'post_title_desc' => esc_html__( 'Title z-a', 'learnpress' ),
558 'price' => esc_html__( 'Price high to low', 'learnpress' ),
559 'price_low' => esc_html__( 'Price low to high', 'learnpress' ),
560 'popular' => esc_html__( 'Popular', 'learnpress' ),
561 ]
562 );
563
564 $content = '<select name="order_by" class="courses-order-by">';
565 foreach ( $values as $k => $v ) {
566 $content .= sprintf(
567 '<option value="%s" %s>%s</option>',
568 esc_attr( $k ),
569 selected( $default_value, $k, false ),
570 $v
571 );
572 }
573 $content .= '</select>';
574
575 return Template::instance()->nest_elements( $html_wrapper, $content );
576 }
577
578 public function html_search_form( array $data = [] ) {
579 $s = $data['c_search'] ?? '';
580 $class = $data['class'] ?? 'search-courses';
581 ob_start();
582 ?>
583 <form class="<?php echo esc_attr( $class ); ?>" method="get"
584 action="<?php echo esc_url_raw( learn_press_get_page_link( 'courses' ) ); ?>">
585 <input type="search" placeholder="<?php esc_attr_e( 'Search courses...', 'learnpress' ); ?>"
586 name="c_search"
587 value="<?php echo esc_attr( $s ); ?>">
588 <button type="submit" name="lp-btn-search-courses"><i class="lp-icon-search"></i></button>
589 </form>
590 <?php
591 return ob_get_clean();
592 }
593
594 /**
595 * Html switch layout.
596 *
597 * @return string
598 */
599 public function switch_layout(): string {
600 $layouts = learn_press_courses_layouts();
601 $active = learn_press_get_courses_layout();
602
603 $html_layouts = '';
604 foreach ( $layouts as $layout => $value ) {
605 $html_layouts .= sprintf(
606 '<input type="radio" name="lp-switch-layout-btn" value="%s" id="lp-switch-layout-btn-%s" %s>
607 <label class="switch-btn %s" title="%s" for="lp-switch-layout-btn-%s"></label>',
608 esc_attr( $layout ),
609 esc_attr( $layout ),
610 checked( $layout, $active, false ),
611 esc_attr( $layout ),
612 sprintf( esc_attr__( 'Switch to %s', 'learnpress' ), $value ),
613 esc_attr( $layout )
614 );
615 }
616
617 $section = apply_filters(
618 'learn-press/layout/list-courses/section/switch-layout',
619 [
620 'wrapper' => '<div class="switch-layout">',
621 'layouts' => $html_layouts,
622 'wrapper_end' => '</div>',
623 ]
624 );
625
626 return Template::combine_components( $section );
627 }
628
629 /**
630 * Layout course search suggest result.
631 *
632 * @param array $data
633 *
634 * @return void
635 * @since 4.2.3.2
636 * @version 1.0.1
637 */
638 public function sections_course_suggest( array $data = [] ) {
639 $content = '';
640 $singleCourseTemplate = SingleCourseTemplate::instance();
641
642 ob_start();
643 try {
644 $courses = $data['courses'] ?? [];
645 $key_search = $data['keyword'] ?? '';
646 $total_courses = $data['total_course'] ?? 0;
647
648 // HTML section list courses.
649 $html_list_course = '';
650 foreach ( $courses as $courseObj ) {
651 if ( ! is_object( $courseObj ) ) {
652 continue;
653 }
654 $course_id = $courseObj->ID;
655 $courseModel = CourseModel::find( $course_id, true );
656 if ( ! $courseModel ) {
657 continue;
658 }
659
660 $section_item = apply_filters(
661 'learn-press/course-suggest/item/sections',
662 [
663 'wrapper' => '<li class="item-course-suggest">',
664 'course_image' => $singleCourseTemplate->html_image( $courseModel ),
665 'course_title' => sprintf(
666 '<a href="%s">%s</a>',
667 esc_url_raw( $courseModel->get_permalink() ),
668 $singleCourseTemplate->html_title( $courseModel )
669 ),
670 'wrapper_end' => '</li>',
671 ],
672 $courseModel,
673 $key_search,
674 $data
675 );
676 $html_list_course .= Template::combine_components( $section_item );
677 }
678
679 $count_courses = sprintf(
680 '%s %s',
681 $total_courses,
682 _n( 'Course Found', 'Courses Found', $total_courses, 'learnpress' )
683 );
684 $view_all = sprintf(
685 '<a href="%s">%s</a>',
686 esc_url( add_query_arg(
687 'c_search',
688 $key_search,
689 learn_press_get_page_link( 'courses' ) ) ),
690 __( 'View All', 'learnpress' )
691 );
692
693 // Section.
694 $section = [
695 'wrapper' => '<ul class="lp-courses-suggest-list">',
696 'courses' => $html_list_course,
697 'wrapper_end' => '</ul>',
698 'wrapper_info' => '<div class="lp-courses-suggest-info">',
699 'count' => $count_courses,
700 'view_all' => $view_all,
701 'wrapper_info_end' => '</div>',
702 ];
703 $content = Template::combine_components( $section );
704 echo $content;
705 } catch ( Throwable $e ) {
706 Template::print_message( $e->getMessage(), 'error' );
707 }
708 }
709
710 /**
711 * Sidebar
712 *
713 * @return void
714 * @version 1.0.0
715 * @since 4.2.3.2
716 */
717 public function sidebar() {
718 try {
719 if ( is_active_sidebar( 'archive-courses-sidebar' ) ) {
720 $html_wrapper = [
721 '<div class="lp-archive-courses-sidebar">' => '</div>',
722 ];
723
724 ob_start();
725 dynamic_sidebar( 'archive-courses-sidebar' );
726 echo Template::instance()->nest_elements( $html_wrapper, ob_get_clean() );
727 }
728 } catch ( Throwable $e ) {
729 error_log( $e->getMessage() );
730 }
731 }
732
733 /**
734 * Show total course free by Category.
735 * @return string
736 * @version 1.0.0
737 *
738 * @since 4.2.5.4
739 */
740 public function html_count_course_free(): string {
741 $html_wrapper = [
742 '<div class="courses-count-free">' => '</div>',
743 ];
744
745 $category_current = 0;
746 $category_current_slug = get_query_var( 'term' );
747 if ( ! empty( $category_current_slug ) ) {
748 $category_current_obj = get_term_by( 'slug', $category_current_slug, LP_COURSE_CATEGORY_TAX );
749 if ( $category_current_obj instanceof WP_Term ) {
750 $category_current = $category_current_obj->term_id;
751 }
752 }
753
754 $filter = new LP_Course_Filter();
755 if ( ! empty( $category_current ) ) {
756 $filter->term_ids = [ $category_current ];
757 }
758
759 $count = Courses::count_course_free( $filter );
760 $content = sprintf(
761 '<span class="courses-count-free-number">%1$s</span> %2$s',
762 $count,
763 _n( 'Free Course', 'Free Courses', $count, 'learnpress' )
764 );
765
766 return Template::instance()->nest_elements( $html_wrapper, $content );
767 }
768
769 /**
770 * Show total students on Course Category.
771 *
772 * @return string
773 * @since 4.2.5.4
774 * @version 1.0.0
775 */
776 public function html_count_students(): string {
777 $html_wrapper = [
778 '<div class="courses-count-students">' => '</div>',
779 ];
780
781 $category_current = 0;
782 $category_current_slug = get_query_var( 'term' );
783 if ( ! empty( $category_current_slug ) ) {
784 $category_current_obj = get_term_by( 'slug', $category_current_slug, LP_COURSE_CATEGORY_TAX );
785 if ( $category_current_obj instanceof WP_Term ) {
786 $category_current = $category_current_obj->term_id;
787 }
788 }
789
790 $lp_user_items_db = LP_User_Items_DB::getInstance();
791 $filter = new LP_User_Items_Filter();
792
793 // If page is course category, get total students of this category.
794 if ( ! empty( $category_current ) ) {
795 $filter->join[] = "INNER JOIN {$lp_user_items_db->tb_posts} AS p ON ui.item_id = p.ID";
796 $filter->join[] = "INNER JOIN {$lp_user_items_db->tb_term_relationships} AS r_term ON ui.item_id = r_term.object_id";
797 $filter->where[] = $lp_user_items_db->wpdb->prepare( 'AND r_term.term_taxonomy_id = %d', $category_current );
798 }
799
800 $count = UserCourseModel::count_students( $filter );
801 $content = sprintf(
802 '<span class="courses-count-students-number">%1$s</span> %2$s',
803 $count,
804 _n( 'Student', 'Students', $count, 'learnpress' )
805 );
806
807 return Template::instance()->nest_elements( $html_wrapper, $content );
808 }
809
810 /************************** Hook old *****************************/
811
812 /**
813 * Fix theme course-builder use old hook.
814 *
815 * @param array $section
816 *
817 * @return array
818 */
819 public static function fix_theme_cb_hook_courses( $section, $courses, $settings ) {
820 /*$theme_name = wp_get_theme()->get( 'Name' );
821 if ( 'Course Builder' !== $theme_name ) {
822 return $section;
823 }*/
824
825 $section_top = apply_filters(
826 'learn-press/list-courses/layout/section/top',
827 [],
828 $courses,
829 $settings
830 );
831
832 $section_new = [];
833 if ( ! empty( $section_top ) ) {
834 foreach ( $section_top as $k => $v ) {
835 $section_new[ $k ] = $v['text_html'] ?? '';
836 }
837
838 return $section_new;
839 }
840
841 return $section;
842 }
843
844 /**
845 * Fix theme course-builder use old hook.
846 *
847 * @param array $section
848 *
849 * @return array
850 */
851 public static function fix_theme_course_old( $section, $course, $settings ) {
852 /*$theme_name = wp_get_theme()->get( 'Name' );
853 if ( 'Course Builder' !== $theme_name ) {
854 return $section;
855 }*/
856
857 $course = learn_press_get_course( $course->get_id() );
858
859 $wrapper = apply_filters(
860 'learn-press/list-courses/layout/item/wrapper',
861 [],
862 $course,
863 $settings
864 );
865 if ( ! empty( $wrapper ) ) {
866 $i = 0;
867 foreach ( $wrapper as $k => $v ) {
868 if ( $i === 0 ) {
869 $section['wrapper_li'] = $k;
870 $section['wrapper_li_end'] = $v;
871 } elseif ( $i === 1 ) {
872 $section['wrapper_div'] = $k;
873 $section['wrapper_div_end'] = $v;
874 break;
875 }
876
877 ++$i;
878 }
879 }
880
881 $section_item = apply_filters(
882 'learn-press/list-courses/layout/item/section',
883 [],
884 $course,
885 $settings
886 );
887 if ( ! empty( $section_item ) ) {
888 $section['top'] = $section_item['thim_top']['text_html'] ?? '';
889 }
890
891 $section_bottom = apply_filters(
892 'learn-press/list-courses/layout/item/section/bottom',
893 [],
894 $course,
895 $settings
896 );
897 $section_bottom_new = [];
898 if ( ! empty( $section_bottom ) ) {
899 foreach ( $section_bottom as $k => $v ) {
900 $section_bottom_new[ $k ] = $v['text_html'] ?? '';
901 }
902
903 $section['bottom'] = Template::combine_components( $section_bottom_new );
904 }
905
906 return $section;
907 }
908
909 /**
910 * Render string to data content
911 *
912 * @param array $data
913 * @param string $data_content
914 *
915 * @return string
916 */
917 public function render_data( array $data, string $data_content ): string {
918 return str_replace(
919 [
920 '{{courses_order_by}}',
921 '{{courses_layout_type}}',
922 '{{courses_pagination}}',
923 '{{courses_page_result}}',
924 ],
925 [
926 $this->html_order_by( $data['order_by'] ?? '' ),
927 $this->html_layout_type( $data ),
928 $this->html_pagination( $data['pagination'] ?? [] ),
929 $this->html_courses_page_result( $data ),
930 ],
931 $data_content
932 );
933 }
934 }
935