| 1 |
<?php |
| 2 |
/** |
| 3 |
* Template hooks List Courses. |
| 4 |
* |
| 5 |
* @since 4.2.7 |
| 6 |
* @version 1.0.0 |
| 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\TemplateHooks\TemplateAJAX; |
| 16 |
use LP_Course_Filter; |
| 17 |
use LP_Database; |
| 18 |
use stdClass; |
| 19 |
use Throwable; |
| 20 |
|
| 21 |
class ListCoursesRelatedTemplate { |
| 22 |
use Singleton; |
| 23 |
|
| 24 |
public function init() { |
| 25 |
add_action( 'learn-press/single-course/courses-related/layout', [ $this, 'layout_courses' ], 10, 2 ); |
| 26 |
add_filter( 'lp/rest/ajax/allow_callback', [ $this, 'allow_callback' ] ); |
| 27 |
} |
| 28 |
|
| 29 |
/** |
| 30 |
* Allow callback for AJAX. |
| 31 |
* @use self::render_courses |
| 32 |
* @param array $callbacks |
| 33 |
* |
| 34 |
* @return array |
| 35 |
*/ |
| 36 |
public function allow_callback( array $callbacks ): array { |
| 37 |
$callbacks[] = get_class( $this ) . ':render_courses'; |
| 38 |
|
| 39 |
return $callbacks; |
| 40 |
} |
| 41 |
|
| 42 |
/** |
| 43 |
* Layout default list courses. |
| 44 |
* |
| 45 |
* @return void |
| 46 |
* @since 4.2.7 |
| 47 |
* @version 1.0.0 |
| 48 |
*/ |
| 49 |
public function layout_courses( CourseModel $course, $limit ) { |
| 50 |
$html_wrapper = [ |
| 51 |
'<div class="lp-list-courses-related">' => '</div>', |
| 52 |
]; |
| 53 |
|
| 54 |
$callback = [ |
| 55 |
'class' => get_class( $this ), |
| 56 |
'method' => 'render_courses', |
| 57 |
]; |
| 58 |
$args = [ |
| 59 |
'id_url' => 'course-related', |
| 60 |
'course_id' => $course->get_id(), |
| 61 |
'limit' => $limit, |
| 62 |
]; |
| 63 |
|
| 64 |
$content = TemplateAJAX::load_content_via_ajax( $args, $callback ); |
| 65 |
|
| 66 |
echo Template::instance()->nest_elements( $html_wrapper, $content ); |
| 67 |
} |
| 68 |
|
| 69 |
/** |
| 70 |
* Render template list courses with settings param. |
| 71 |
* |
| 72 |
* @param array $settings |
| 73 |
* |
| 74 |
* @return stdClass { content: string_html } |
| 75 |
* @since 4.2.7 |
| 76 |
* @version 1.0.3 |
| 77 |
*/ |
| 78 |
public static function render_courses( array $settings = [] ): stdClass { |
| 79 |
$content = new stdClass(); |
| 80 |
$content->content = ''; |
| 81 |
|
| 82 |
$filter = new LP_Course_Filter(); |
| 83 |
$course_id = $settings['course_id'] ?? 0; |
| 84 |
if ( empty( $course_id ) ) { |
| 85 |
return $content; |
| 86 |
} |
| 87 |
|
| 88 |
$courseModelCurrent = CourseModel::find( $course_id, true ); |
| 89 |
$terms = $courseModelCurrent->get_categories(); |
| 90 |
$term_ids = []; |
| 91 |
|
| 92 |
foreach ( $terms as $term ) { |
| 93 |
$term_ids[] = $term->term_id ?? 0; |
| 94 |
|
| 95 |
if ( $term->parent ) { |
| 96 |
$term_ids[] = $term->parent; |
| 97 |
} |
| 98 |
} |
| 99 |
|
| 100 |
$total_rows = 0; |
| 101 |
$filter->only_fields = [ 'DISTINCT(ID) AS ID' ]; |
| 102 |
$filter->post_status = [ 'publish' ]; |
| 103 |
$filter->limit = $settings['limit'] ?? 4; |
| 104 |
$filter->term_ids = $term_ids; |
| 105 |
$filter->query_count = false; |
| 106 |
$filter->order_by = 'rand()'; |
| 107 |
$filter->where[] = LP_Database::getInstance()->wpdb->prepare( 'AND p.ID != %d', $course_id ); |
| 108 |
|
| 109 |
$courses = Courses::get_courses( $filter, $total_rows ); |
| 110 |
if ( empty( $courses ) ) { |
| 111 |
return $content; |
| 112 |
} |
| 113 |
|
| 114 |
// Handle layout |
| 115 |
$html_ul_courses = [ |
| 116 |
'<ul class="lp-courses-related learn-press-courses">' => '</ul>', |
| 117 |
]; |
| 118 |
|
| 119 |
ob_start(); |
| 120 |
foreach ( $courses as $courseObj ) { |
| 121 |
$courseModel = CourseModel::find( $courseObj->ID, true ); |
| 122 |
if ( ! $courseModel instanceof CourseModel ) { |
| 123 |
continue; |
| 124 |
} |
| 125 |
echo ListCoursesTemplate::render_course( $courseModel, $settings ); |
| 126 |
} |
| 127 |
$html_courses = Template::instance()->nest_elements( $html_ul_courses, ob_get_clean() ); |
| 128 |
|
| 129 |
$sections = apply_filters( |
| 130 |
'learn-press/list-courses/related/sections', |
| 131 |
[ |
| 132 |
'header' => sprintf( '<h3 class="section-title">%s</h3>', __( 'You might be interested in', 'learnpress' ) ), |
| 133 |
'courses' => $html_courses, |
| 134 |
], |
| 135 |
$courseModelCurrent, |
| 136 |
$courses, |
| 137 |
$settings |
| 138 |
); |
| 139 |
$content->content = Template::combine_components( $sections ); |
| 140 |
|
| 141 |
return $content; |
| 142 |
} |
| 143 |
|
| 144 |
/** |
| 145 |
* Render single item course |
| 146 |
* |
| 147 |
* @param CourseModel $course |
| 148 |
* @param array $settings |
| 149 |
* |
| 150 |
* @return string |
| 151 |
* @since 4.2.5.8 |
| 152 |
* @version 1.0.1 |
| 153 |
*/ |
| 154 |
public static function render_course( CourseModel $course, array $settings = [] ): string { |
| 155 |
$singleCourseTemplate = SingleCourseTemplate::instance(); |
| 156 |
|
| 157 |
try { |
| 158 |
$top_wrapper = [ |
| 159 |
'<div class="course-wrap-thumbnail">' => '</div>', |
| 160 |
'<div class="course-thumbnail">' => '</div>', |
| 161 |
]; |
| 162 |
$img = sprintf( '<a href="%s">%s</a>', $course->get_permalink(), $singleCourseTemplate->html_image( $course ) ); |
| 163 |
$html_top = Template::instance()->nest_elements( $top_wrapper, $img ); |
| 164 |
|
| 165 |
// Section main top |
| 166 |
$section_main_top = [ |
| 167 |
'wrapper_start' => '<div class="course-content-top">', |
| 168 |
'level' => $singleCourseTemplate->html_level( $course ), |
| 169 |
'price' => $singleCourseTemplate->html_price( $course ), |
| 170 |
'wrapper_end' => '</div>', |
| 171 |
]; |
| 172 |
$html_main_top = Template::combine_components( $section_main_top ); |
| 173 |
// End section main top |
| 174 |
|
| 175 |
// Section main bottom |
| 176 |
$html_count_student = $singleCourseTemplate->html_count_student( $course ); |
| 177 |
$section_main_bottom = [ |
| 178 |
'wrapper_start' => '<div class="course-content-bottom">', |
| 179 |
'students' => $html_count_student, |
| 180 |
'lessons' => $singleCourseTemplate->html_count_item( $course, LP_LESSON_CPT ), |
| 181 |
'wrapper_end' => '</div>', |
| 182 |
]; |
| 183 |
$html_main_bottom = Template::combine_components( $section_main_bottom ); |
| 184 |
// End section main bottom |
| 185 |
|
| 186 |
$section_main = apply_filters( |
| 187 |
'learn-press/list-courses/related/layout/item/section/bottom', |
| 188 |
[ |
| 189 |
'wrapper_start' => '<div class="course-content">', |
| 190 |
'top' => $html_main_top, |
| 191 |
'category' => $singleCourseTemplate->html_categories( $course ), |
| 192 |
'title' => sprintf( '<a href="%s">%s</a>', $course->get_permalink(), $singleCourseTemplate->html_title( $course, 'h4' ) ), |
| 193 |
'bottom' => $html_main_bottom, |
| 194 |
'wrapper_end' => '</div>', |
| 195 |
], |
| 196 |
$course, |
| 197 |
$settings |
| 198 |
); |
| 199 |
$html_section_main = Template::combine_components( $section_main ); |
| 200 |
|
| 201 |
$section = apply_filters( |
| 202 |
'learn-press/list-courses/related/layout/item/section', |
| 203 |
[ |
| 204 |
'wrapper_start' => sprintf( '<li class="course-item" data-id="%s">', esc_attr( $course->get_id() ) ), |
| 205 |
'top' => $html_top, |
| 206 |
'bottom' => $html_section_main, |
| 207 |
'wrapper_end' => '</li>', |
| 208 |
], |
| 209 |
$course, |
| 210 |
$settings |
| 211 |
); |
| 212 |
$html_item = Template::combine_components( $section ); |
| 213 |
} catch ( Throwable $e ) { |
| 214 |
$html_item = $e->getMessage(); |
| 215 |
} |
| 216 |
|
| 217 |
return $html_item; |
| 218 |
} |
| 219 |
} |
| 220 |
|