' => '',
];
$callback = [
'class' => get_class( $this ),
'method' => 'render_courses',
];
$args = lp_archive_skeleton_get_args();
$args['id_url'] = 'list-courses-default';
$args['courses_load_ajax'] = LP_Settings_Courses::is_ajax_load_courses() ? 1 : 0;
$args['courses_first_no_ajax'] = LP_Settings_Courses::is_no_load_ajax_first_courses() ? 1 : 0;
// Load list courses via AJAX.
if ( LP_Settings_Courses::is_ajax_load_courses() && ! LP_Settings_Courses::is_no_load_ajax_first_courses() ) {
$content = TemplateAJAX::load_content_via_ajax( $args, $callback );
} else { // Load courses first not AJAX, or for filter.
$content_obj = static::render_courses( $args );
$args['html_no_load_ajax_first'] = $content_obj->content;
$content = TemplateAJAX::load_content_via_ajax( $args, $callback );
}
echo Template::instance()->nest_elements( $html_wrapper, $content );
}
/**
* Render template list courses with settings param.
*
* @param array $settings
*
* @return stdClass { content: string_html }
* @since 4.2.5.7
* @version 1.0.5
*/
public static function render_courses( array $settings = [] ): stdClass {
$filter = new LP_Course_Filter();
Courses::handle_params_for_query_courses( $filter, $settings );
$total_rows = 0;
$courses = Courses::get_courses( $filter, $total_rows );
$total_pages = LP_Database::get_total_pages( $filter->limit, $total_rows );
$settings['total_pages'] = $total_pages;
$settings['total_rows'] = $total_rows;
$settings['courses_per_page'] = $filter->limit;
$skin = $settings['skin'] ?? ( wp_is_mobile() ? 'grid' : learn_press_get_courses_layout() );
$paged = $settings['paged'] ?? 1;
$settings['paged'] = $paged;
$listCoursesTemplate = self::instance();
// HTML section courses.
$html_courses = '';
if ( empty( $courses ) ) {
$html_courses = Template::print_message( __( 'No courses found', 'learnpress' ), 'info', false );
} else {
foreach ( $courses as $courseObj ) {
$course = CourseModel::find( $courseObj->ID, true );
$html_courses .= static::render_course( $course, $settings );
}
}
$section_courses = apply_filters(
'learn-press/layout/list-courses/section/courses',
[
'wrap' => sprintf(
'
',
esc_attr( $skin )
),
'courses' => $html_courses,
'wrap_end' => '
',
],
$courses,
$settings
);
$section_top = apply_filters(
'learn-press/layout/list-courses/section/top',
[
'wrapper' => '',
'search' => $listCoursesTemplate->html_search_form( $settings ),
'order_by' => $listCoursesTemplate->html_order_by( $settings['order_by'] ?? 'post_date' ),
'switch_layout' => $listCoursesTemplate->switch_layout(),
'btn_filter_courses_mobile' => FilterCourseTemplate::instance()->html_btn_filter_mobile( $settings ),
'wrapper_end' => '
',
],
$courses,
$settings
);
// For old themes use old hook.
$section_top = self::fix_theme_cb_hook_courses( $section_top, $courses, $settings );
//$section= self::fix_theme_el_hook_old_render_courses( $section, $courses, $settings );
// End.
// Pagination html
$data_pagination_type = LP_Settings::get_option( 'course_pagination_type', 'number' );
if ( empty( $settings['courses_load_ajax'] ) ) {
$data_pagination_type = 'number';
}
$data_pagination = [
'total_pages' => $total_pages,
'type' => $data_pagination_type,
'base' => add_query_arg( 'paged', '%#%', $settings['url_current'] ?? '' ),
'paged' => $settings['paged'] ?? 1,
];
$html_pagination = static::instance()->html_pagination( $data_pagination );
$section = apply_filters(
'learn-press/layout/list-courses/section',
[
'top' => Template::combine_components( $section_top ),
'courses' => Template::combine_components( $section_courses ),
'pagination' => $html_pagination,
],
$courses,
$settings
);
$content = new stdClass();
$content->content = Template::combine_components( $section );
$content->total_pages = $total_pages;
$content->paged = $paged;
return $content;
}
/**
* Render single item course
*
* @param CourseModel|LP_Course $course
* @param array $settings
*
* @return string
* @since 4.2.5.8
* @version 1.0.4
*/
public static function render_course( $course, array $settings = [] ): string {
if ( ! $course instanceof CourseModel ) {
$course = CourseModel::find( $course->get_id(), true );
}
$singleCourseTemplate = SingleCourseTemplate::instance();
$show_view_students = ! empty( $settings['show_view_students'] );
try {
// New layout course item.
// HTML top section, show image.
$section_top = apply_filters(
'learn-press/layout/list-courses/item/section-top',
[
'wrapper' => '',
'img' => sprintf(
'
%s',
esc_url( $course->get_permalink() ),
$singleCourseTemplate->html_image( $course )
),
'wrapper_end' => '
',
],
$course,
$settings
);
// HTML meta section.
$meta_data = apply_filters(
'learn-press/layout/list-courses/item/meta-data',
[
'duration' => $singleCourseTemplate->html_duration( $course ),
'level' => $singleCourseTemplate->html_level( $course ),
'lesson' => $singleCourseTemplate->html_count_item( $course, LP_LESSON_CPT ),
'quiz' => $singleCourseTemplate->html_count_item( $course, LP_QUIZ_CPT ),
'student' => $singleCourseTemplate->html_count_student( $course ),
],
$course,
$settings
);
if ( $course->is_offline() ) {
$singleCourseOfflineTemplate = SingleCourseOfflineTemplate::instance();
unset( $meta_data['quiz'] );
unset( $meta_data['student'] );
if ( ! empty( $meta_data['lesson'] ) ) {
$meta_data['lesson'] = $singleCourseOfflineTemplate->html_lesson_info( $course, true );
}
// Add address for offline course.
$html_address = $singleCourseOfflineTemplate->html_address( $course );
if ( ! empty( $html_address ) ) {
$meta_data['address'] = $singleCourseOfflineTemplate->html_address( $course );
}
}
$html_meta_data = '';
if ( ! empty( $meta_data ) ) {
foreach ( $meta_data as $k => $v ) {
$html_meta_data .= sprintf( '%s
', $k, $v );
}
$html_meta_data = sprintf( '%s
', $html_meta_data );
}
$btn_read_more_text = SingleCourseTemplate::text_button_course( $course );
// HTML bottom section end.
$section_bottom_end = apply_filters(
'learn-press/layout/list-courses/item/section/bottom/end',
[
'short_des' => $singleCourseTemplate->html_short_description( $course ),
'wrapper' => '',
//'clearfix' => '
',
//'course_footer' => '',
'wrapper_end' => '
',
],
$course,
$settings
);
// HTML bottom section.
$html_categories = $singleCourseTemplate->html_categories( $course );
if ( ! empty( $html_categories ) ) {
$html_categories = sprintf(
'%s %s
',
sprintf( '', __( 'in', 'learnpress' ) ),
$html_categories
);
}
$section_bottom = apply_filters(
'learn-press/layout/list-courses/item/section/bottom',
[
'wrapper' => '',
'title' => sprintf(
'
',
esc_url( $course->get_permalink() ),
$singleCourseTemplate->html_title( $course )
),
'featured' => $singleCourseTemplate->html_featured( $course ),
'wrapper_instructor_cate' => '
',
'instructor' => sprintf(
'
%s %s
',
sprintf( '
', __( 'by', 'learnpress' ) ),
$singleCourseTemplate->html_instructor( $course )
),
'category' => $html_categories,
'wrapper_instructor_cate_end' => '
',
'meta' => $html_meta_data,
'info' => Template::combine_components( $section_bottom_end ),
'wrapper_end' => '
',
],
$course,
$settings
);
$section = apply_filters(
'learn-press/layout/list-courses/item-li',
[
'wrapper_li' => '',
'wrapper_div' => sprintf( '', esc_attr( $course->get_id() ) ),
'top' => Template::combine_components( $section_top ),
'bottom' => Template::combine_components( $section_bottom ),
'wrapper_div_end' => '
',
'wrapper_li_end' => '',
],
$course,
$settings
);
// For old themes use old hook.
$section = self::fix_theme_course_old( $section, $course, $settings );
// End.
$html_item = Template::combine_components( $section );
// End new layout course item.
} catch ( Throwable $e ) {
$html_item = $e->getMessage();
}
return $html_item;
}
/**
* Button Load more
*
* @return string
* @since 4.2.3.3
* @version 1.0.0
*/
public function html_pagination_load_more(): string {
$html_wrapper = [
'',
];
$content = sprintf(
'%s',
__( 'Load more', 'learnpress' )
);
return Template::instance()->nest_elements( $html_wrapper, $content );
}
/**
* Button infinite
*
* @return string
* @since 4.2.3.3
* @version 1.0.0
*/
public function html_pagination_infinite(): string {
$html_wrapper = [
'',
];
$content = '';
return Template::instance()->nest_elements( $html_wrapper, $content );
}
/**
* Pagination number
*
* @param array $data
*
* @return string
* @since 4.2.3.3
* @version 1.0.0
*/
public function html_pagination_number( array $data = [] ): string {
if ( empty( $data['total_pages'] ) || $data['total_pages'] <= 1 ) {
return '';
}
$html_wrapper = $data['wrapper'] ?? [
'',
];
$pagination = paginate_links(
apply_filters(
'learn_press_pagination_args',
array(
'base' => $data['base'] ?? '',
'format' => '',
'add_args' => '',
'current' => max( 1, $data['paged'] ?? 1 ),
'total' => $data[ 'total_pages' ?? 1 ],
'prev_text' => '',
'next_text' => '',
'type' => 'list',
'end_size' => 3,
'mid_size' => 3,
)
)
);
return Template::instance()->nest_elements( $html_wrapper, $pagination );
}
/**
* Pagination
*
* @param array $data
*
* @return string
* @since 4.2.3.3
* @version 1.0.0
*/
public function html_pagination( array $data = [] ): string {
if ( empty( $data['total_pages'] ) || $data['total_pages'] <= 1 ) {
return '';
}
$pagination_type = $data['type'] ?? 'number';
switch ( $pagination_type ) {
case 'load-more':
if ( $data['paged'] >= $data['total_pages'] ) {
return '';
}
return $this->html_pagination_load_more();
case 'infinite':
if ( $data['paged'] >= $data['total_pages'] ) {
return '';
}
return $this->html_pagination_infinite();
default:
return $this->html_pagination_number( $data );
}
}
/**
* Pagination
*
* @param array $data
*
* @return string
* @since 4.2.3.3
* @version 1.0.1
*/
public function html_courses_page_result( array $data = [] ): string {
$html = '';
try {
$total_rows = $data['total_rows'] ?? 0;
$paged = $data['paged'] ?? 1;
$course_per_page = $data['courses_per_page'] ?? 8;
$pagination_type = $data['pagination_type'] ?? 'number';
$from = 1 + ( $paged - 1 ) * $course_per_page;
$to = ( $paged * $course_per_page > $total_rows ) ? $total_rows : $paged * $course_per_page;
$content = '';
if ( 0 === $total_rows ) {
} elseif ( 1 === $total_rows ) {
$content = esc_html__( 'Showing only one result', 'learnpress' );
} else {
$from_to = $from . '-' . $to;
// For pagination type is load-more or infinite.
if ( $pagination_type !== 'number' ) {
$from_to = '1 - ' . $to;
}
$content = sprintf( esc_html__( 'Showing %1$s of %2$s results', 'learnpress' ), $from_to, $total_rows );
}
if ( ! empty( $content ) ) {
$html = '' . $content . '';
}
} catch ( Throwable $e ) {
error_log( $e->getMessage() );
}
return $html;
}
/**
* Layouts type
*
* @param array $data
*
* @return string
* @since 4.2.3.3
* @version 1.0.0
*/
public function html_layout_type( array $data = [] ): string {
$html_wrapper = [
'' => '
',
];
$ico_grid_default = LP_WP_Filesystem::get_icon_svg( 'ico-grid.svg' );
$ico_list_default = LP_WP_Filesystem::get_icon_svg( 'ico-list.svg' );
$layouts = [
'list' => $data['courses_ico_list'] ?? $ico_list_default,
'grid' => $data['courses_ico_grid'] ?? $ico_grid_default,
];
$content = '';
foreach ( $layouts as $k => $v ) {
$active = ( $data['courses_layout_default'] ?? '' ) === $k ? 'active' : '';
$content .= sprintf(
'- %s
',
esc_attr( $active ),
esc_attr( $k ),
$v
);
}
$content .= '
';
return Template::instance()->nest_elements( $html_wrapper, $content );
}
/**
* Order by
*
* @param string $default_value
*
* @return string
* @since 4.2.3.2
* @version 1.0.1
*/
public function html_order_by( string $default_value = 'post_date' ): string {
$html_wrapper = [
'' => '
',
];
$values = apply_filters(
'learn-press/courses/order-by/values',
[
'post_date' => esc_html__( 'Newly published', 'learnpress' ),
'post_title' => esc_html__( 'Title a-z', 'learnpress' ),
'post_title_desc' => esc_html__( 'Title z-a', 'learnpress' ),
'price' => esc_html__( 'Price high to low', 'learnpress' ),
'price_low' => esc_html__( 'Price low to high', 'learnpress' ),
'popular' => esc_html__( 'Popular', 'learnpress' ),
]
);
$content = '';
return Template::instance()->nest_elements( $html_wrapper, $content );
}
public function html_search_form( array $data = [] ) {
$s = $data['c_search'] ?? '';
$class = $data['class'] ?? 'search-courses';
ob_start();
?>
$value ) {
$html_layouts .= sprintf(
'
',
esc_attr( $layout ),
esc_attr( $layout ),
checked( $layout, $active, false ),
esc_attr( $layout ),
sprintf( esc_attr__( 'Switch to %s', 'learnpress' ), $value ),
esc_attr( $layout )
);
}
$section = apply_filters(
'learn-press/layout/list-courses/section/switch-layout',
[
'wrapper' => '',
'layouts' => $html_layouts,
'wrapper_end' => '
',
]
);
return Template::combine_components( $section );
}
/**
* Layout course search suggest result.
*
* @param array $data
*
* @return void
* @since 4.2.3.2
* @version 1.0.1
*/
public function sections_course_suggest( array $data = [] ) {
$content = '';
$singleCourseTemplate = SingleCourseTemplate::instance();
ob_start();
try {
$courses = $data['courses'] ?? [];
$key_search = $data['keyword'] ?? '';
$total_courses = $data['total_course'] ?? 0;
// HTML section list courses.
$html_list_course = '';
foreach ( $courses as $courseObj ) {
if ( ! is_object( $courseObj ) ) {
continue;
}
$course_id = $courseObj->ID;
$courseModel = CourseModel::find( $course_id, true );
if ( ! $courseModel ) {
continue;
}
$section_item = apply_filters(
'learn-press/course-suggest/item/sections',
[
'wrapper' => '',
'course_image' => $singleCourseTemplate->html_image( $courseModel ),
'course_title' => sprintf(
'%s',
esc_url_raw( $courseModel->get_permalink() ),
$singleCourseTemplate->html_title( $courseModel )
),
'wrapper_end' => '',
],
$courseModel,
$key_search,
$data
);
$html_list_course .= Template::combine_components( $section_item );
}
$count_courses = sprintf(
'%s %s',
$total_courses,
_n( 'Course Found', 'Courses Found', $total_courses, 'learnpress' )
);
$view_all = sprintf(
'%s',
esc_url( add_query_arg(
'c_search',
$key_search,
learn_press_get_page_link( 'courses' ) ) ),
__( 'View All', 'learnpress' )
);
// Section.
$section = [
'wrapper' => '',
'courses' => $html_list_course,
'wrapper_end' => '
',
'wrapper_info' => '',
'count' => $count_courses,
'view_all' => $view_all,
'wrapper_info_end' => '
',
];
$content = Template::combine_components( $section );
echo $content;
} catch ( Throwable $e ) {
Template::print_message( $e->getMessage(), 'error' );
}
}
/**
* Sidebar
*
* @return void
* @version 1.0.0
* @since 4.2.3.2
*/
public function sidebar() {
try {
if ( is_active_sidebar( 'archive-courses-sidebar' ) ) {
$html_wrapper = [
'',
];
ob_start();
dynamic_sidebar( 'archive-courses-sidebar' );
echo Template::instance()->nest_elements( $html_wrapper, ob_get_clean() );
}
} catch ( Throwable $e ) {
error_log( $e->getMessage() );
}
}
/**
* Show total course free by Category.
* @return string
* @version 1.0.0
*
* @since 4.2.5.4
*/
public function html_count_course_free(): string {
$html_wrapper = [
'' => '
',
];
$category_current = 0;
$category_current_slug = get_query_var( 'term' );
if ( ! empty( $category_current_slug ) ) {
$category_current_obj = get_term_by( 'slug', $category_current_slug, LP_COURSE_CATEGORY_TAX );
if ( $category_current_obj instanceof WP_Term ) {
$category_current = $category_current_obj->term_id;
}
}
$filter = new LP_Course_Filter();
if ( ! empty( $category_current ) ) {
$filter->term_ids = [ $category_current ];
}
$count = Courses::count_course_free( $filter );
$content = sprintf(
'%1$s %2$s',
$count,
_n( 'Free Course', 'Free Courses', $count, 'learnpress' )
);
return Template::instance()->nest_elements( $html_wrapper, $content );
}
/**
* Show total students on Course Category.
*
* @return string
* @since 4.2.5.4
* @version 1.0.0
*/
public function html_count_students(): string {
$html_wrapper = [
'' => '
',
];
$category_current = 0;
$category_current_slug = get_query_var( 'term' );
if ( ! empty( $category_current_slug ) ) {
$category_current_obj = get_term_by( 'slug', $category_current_slug, LP_COURSE_CATEGORY_TAX );
if ( $category_current_obj instanceof WP_Term ) {
$category_current = $category_current_obj->term_id;
}
}
$lp_user_items_db = LP_User_Items_DB::getInstance();
$filter = new LP_User_Items_Filter();
// If page is course category, get total students of this category.
if ( ! empty( $category_current ) ) {
$filter->join[] = "INNER JOIN {$lp_user_items_db->tb_posts} AS p ON ui.item_id = p.ID";
$filter->join[] = "INNER JOIN {$lp_user_items_db->tb_term_relationships} AS r_term ON ui.item_id = r_term.object_id";
$filter->where[] = $lp_user_items_db->wpdb->prepare( 'AND r_term.term_taxonomy_id = %d', $category_current );
}
$count = UserCourseModel::count_students( $filter );
$content = sprintf(
'%1$s %2$s',
$count,
_n( 'Student', 'Students', $count, 'learnpress' )
);
return Template::instance()->nest_elements( $html_wrapper, $content );
}
/************************** Hook old *****************************/
/**
* Fix theme course-builder use old hook.
*
* @param array $section
*
* @return array
*/
public static function fix_theme_cb_hook_courses( $section, $courses, $settings ) {
/*$theme_name = wp_get_theme()->get( 'Name' );
if ( 'Course Builder' !== $theme_name ) {
return $section;
}*/
$section_top = apply_filters(
'learn-press/list-courses/layout/section/top',
[],
$courses,
$settings
);
$section_new = [];
if ( ! empty( $section_top ) ) {
foreach ( $section_top as $k => $v ) {
$section_new[ $k ] = $v['text_html'] ?? '';
}
return $section_new;
}
return $section;
}
/**
* Fix theme course-builder use old hook.
*
* @param array $section
*
* @return array
*/
public static function fix_theme_course_old( $section, $course, $settings ) {
/*$theme_name = wp_get_theme()->get( 'Name' );
if ( 'Course Builder' !== $theme_name ) {
return $section;
}*/
$course = learn_press_get_course( $course->get_id() );
$wrapper = apply_filters(
'learn-press/list-courses/layout/item/wrapper',
[],
$course,
$settings
);
if ( ! empty( $wrapper ) ) {
$i = 0;
foreach ( $wrapper as $k => $v ) {
if ( $i === 0 ) {
$section['wrapper_li'] = $k;
$section['wrapper_li_end'] = $v;
} elseif ( $i === 1 ) {
$section['wrapper_div'] = $k;
$section['wrapper_div_end'] = $v;
break;
}
++$i;
}
}
$section_item = apply_filters(
'learn-press/list-courses/layout/item/section',
[],
$course,
$settings
);
if ( ! empty( $section_item ) ) {
$section['top'] = $section_item['thim_top']['text_html'] ?? '';
}
$section_bottom = apply_filters(
'learn-press/list-courses/layout/item/section/bottom',
[],
$course,
$settings
);
$section_bottom_new = [];
if ( ! empty( $section_bottom ) ) {
foreach ( $section_bottom as $k => $v ) {
$section_bottom_new[ $k ] = $v['text_html'] ?? '';
}
$section['bottom'] = Template::combine_components( $section_bottom_new );
}
return $section;
}
/**
* Render string to data content
*
* @param array $data
* @param string $data_content
*
* @return string
*/
public function render_data( array $data, string $data_content ): string {
return str_replace(
[
'{{courses_order_by}}',
'{{courses_layout_type}}',
'{{courses_pagination}}',
'{{courses_page_result}}',
],
[
$this->html_order_by( $data['order_by'] ?? '' ),
$this->html_layout_type( $data ),
$this->html_pagination( $data['pagination'] ?? [] ),
$this->html_courses_page_result( $data ),
],
$data_content
);
}
}