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
← All changes | inc/TemplateHooks/Course/CourseMaterialTemplate.php +352 -352 4.3.9.14.4.8 View file →
@@ -1,352 +1,352 @@
1 -<?php
2 -/**
3 - * Template hooks Archive Package.
4 - *
5 - * @since 1.0.0
6 - * @version 1.0.0
7 - */
8 -namespace LearnPress\TemplateHooks\Course;
9 -
10 -use LearnPress\Helpers\Template;
11 -use LearnPress\Models\CourseModel;
12 -use LearnPress\Models\UserItems\UserCourseModel;
13 -use LearnPress\Models\UserModel;
14 -use LearnPress\TemplateHooks\TemplateAJAX;
15 -use LP_Material_Files_DB;
16 -use stdClass;
17 -use LP_Global;
18 -use LP_WP_Filesystem;
19 -use LP_Settings;
20 -use Throwable;
21 -use Exception;
22 -class CourseMaterialTemplate {
23 - public static function instance() {
24 - static $instance = null;
25 -
26 - if ( is_null( $instance ) ) {
27 - $instance = new self();
28 - }
29 -
30 - return $instance;
31 - }
32 -
33 - protected function __construct() {
34 - add_action( 'learn-press/course-material/layout', array( $this, 'sections' ) );
35 - add_filter( 'lp/rest/ajax/allow_callback', array( $this, 'allow_callback' ) );
36 - }
37 - /**
38 - * Allow callback for AJAX.
39 - *
40 - * @param array $callbacks
41 - *
42 - * @return array
43 - */
44 - public function allow_callback( array $callbacks ): array {
45 - $callbacks[] = get_class( $this ) . ':render_material_items';
46 -
47 - return $callbacks;
48 - }
49 -
50 - /**
51 - * Layout for course material.
52 - *
53 - * @throws Exception
54 - */
55 - public function sections( array $data = array() ) {
56 - $item = LP_Global::course_item();
57 - $item_id = 0;
58 - if ( ! $item && get_post_type( get_the_ID() ) === LP_COURSE_CPT ) {
59 - $item_id = get_the_ID();
60 - } elseif ( $item ) {
61 - $item_id = $item->get_id();
62 - } else {
63 - throw new Exception( __( 'Item not found', 'learnpress' ) );
64 - }
65 - // $item_id = $item->get_id();
66 - $material_db = LP_Material_Files_DB::getInstance();
67 - $per_page = (int) LP_Settings::get_option( 'material_file_per_page', - 1 );
68 - $total_rows = $material_db->get_total( $item_id );
69 - $total_pages = $per_page > 0 ? ceil( $total_rows / $per_page ) : 0;
70 -
71 - $args = array_merge(
72 - [
73 - 'id_url' => 'course-material',
74 - 'item_id' => $item_id,
75 - 'paged' => 1,
76 - 'per_page' => $per_page,
77 - 'total_pages' => $total_pages,
78 - ],
79 - $data
80 - );
81 - if ( get_post_type( $item_id ) !== LP_COURSE_CPT ) {
82 - $args['course_id'] = $item->get_course_id();
83 - }
84 -
85 - $callback = array(
86 - 'class' => self::class,
87 - 'method' => 'render_material_items',
88 - );
89 - $content = TemplateAJAX::load_content_via_ajax( $args, $callback );
90 - $section = array(
91 - 'wrap' => '<div class="lp-material-skeleton">',
92 - 'content' => $content,
93 - 'wrap_end' => '</div>',
94 - );
95 - echo Template::combine_components( $section );
96 - }
97 -
98 - public static function render_material_items( $args ): stdClass {
99 - $content = new stdClass();
100 -
101 - try {
102 - $userModel = UserModel::find( get_current_user_id(), true );
103 - $course_id = $args['course_id'] ?? 0;
104 - $item_id = $args['item_id'] ?? 0;
105 - if ( get_post_type( $item_id ) === LP_COURSE_CPT ) {
106 - $courseModel = CourseModel::find( $item_id, true );
107 - } elseif ( $course_id ) {
108 - $courseModel = CourseModel::find( $course_id, true );
109 - } else {
110 - throw new Exception( esc_html__( 'Course not found!', 'learnpress' ) );
111 - }
112 -
113 - $can_show = false;
114 - if ( $userModel instanceof UserModel ) {
115 - if ( $courseModel->check_user_is_author( $userModel )
116 - || user_can( $userModel->get_id(), ADMIN_ROLE ) ) {
117 - $can_show = true;
118 - } else {
119 - $userCourseModel = UserCourseModel::find( $userModel->get_id(), $courseModel->get_id(), true );
120 - if ( $userCourseModel &&
121 - ( $userCourseModel->has_enrolled_or_finished()
122 - || $userCourseModel->has_purchased() ) ) {
123 - $can_show = true;
124 - }
125 - }
126 - } elseif ( $courseModel->has_no_enroll_requirement() ) {
127 - $can_show = true;
128 - }
129 -
130 - $can_show = apply_filters( 'learn-press/course-material/can-show', $can_show, $courseModel, $userModel );
131 -
132 - $file_per_page = LP_Settings::get_option( 'material_file_per_page', - 1 );
133 - $count_files = LP_Material_Files_DB::getInstance()->get_total( $courseModel->get_id() );
134 - if ( ! $can_show || $file_per_page == 0 || $count_files <= 0 ) {
135 - throw new Exception( '' );
136 - }
137 -
138 - $material_db = LP_Material_Files_DB::getInstance();
139 - $paged = absint( $args['paged'] ?? 1 );
140 - $per_page = intval( $args['per_page'] ?? 1 );
141 - $offset = ( $per_page > 0 && $paged > 1 ) ? $per_page * ( $paged - 1 ) : 0;
142 - // $total_pages = $per_page > 0 ? ceil( $total_rows / $per_page ) : 0;
143 - $material_files = $material_db->get_material_by_item_id( $args['item_id'], $per_page, $offset, false );
144 - if ( empty( $material_files ) ) {
145 - $content->content = '';
146 - } else {
147 - $material_html = '';
148 - foreach ( $material_files as $m ) {
149 - $material_html .= self::material_item( $m, $args['item_id'] );
150 - }
151 - if ( $args['paged'] === 1 ) {
152 - $sections = array(
153 - 'wrap' => '<div class="lp-list-material">',
154 - 'table_wrap' => '<table class="course-material-table" >',
155 - 'table_header' => self::table_header(),
156 - 'table_body' => '<tbody>',
157 - 'material_html' => $material_html,
158 - 'table_body_end' => '</tbody>',
159 - 'table_wrap_end' => '</table>',
160 - 'loadmore_btn' => self::html_load_more_btn( $args ),
161 - 'wrap_end' => '</div>',
162 - );
163 - $content->content = Template::combine_components( $sections );
164 - } else {
165 - $content->content = $material_html;
166 - }
167 - $content->total_pages = $args['total_pages'];
168 - $content->paged = $args['paged'];
169 - }
170 - } catch ( Throwable $e ) {
171 - if ( $e->getMessage() === '' ) {
172 - $content->content = '';
173 - } else {
174 - $content->content = Template::print_message( $e->getMessage(), 'error', false );
175 - }
176 - }
177 - return $content;
178 - }
179 -
180 - public static function table_header() {
181 - $sections = array(
182 - 'wrap' => '<thead>',
183 - 'file-name' => sprintf( '<th class="lp-material-th-file-name">%s</th>', esc_html__( 'Name', 'learnpress' ) ),
184 - 'file-type' => sprintf( '<th class="lp-material-th-file-type">%s</th>', esc_html__( 'Type', 'learnpress' ) ),
185 - 'file-size' => sprintf( '<th class="lp-material-th-file-size">%s</th>', esc_html__( 'Size', 'learnpress' ) ),
186 - 'file-link' => sprintf( '<th class="lp-material-th-file-link">%s</th>', esc_html__( 'Download', 'learnpress' ) ),
187 - 'wrap_end' => '</thead>',
188 - );
189 - return Template::combine_components( $sections );
190 - }
191 -
192 - public static function material_item( $material, $current_item_id ) {
193 - $sections = array(
194 - 'wrap' => '<tr class="lp-material-item">',
195 - 'file-name' => self::html_file_name( $material, $current_item_id ),
196 - 'file-type' => self::html_file_type( $material ),
197 - 'file-size' => self::html_file_size( $material ),
198 - 'file-link' => self::html_file_link( $material ),
199 - 'wrap_end' => '</tr>',
200 - );
201 - return Template::combine_components( $sections );
202 - }
203 -
204 - /**
205 - * Generate HTML for file name.
206 - *
207 - * @param object $material Material object.
208 - * @param int $current_item_id Current item ID.
209 - *
210 - * @return string
211 - */
212 - public static function html_file_name( $material, $current_item_id ): string {
213 - if ( get_post_type( $current_item_id ) == LP_COURSE_CPT && $material->item_type == LP_LESSON_CPT ) {
214 - $html_file_name = sprintf( esc_html( '%1$s ( %2$s )' ), $material->file_name, get_the_title( $material->item_id ) );
215 - } else {
216 - $html_file_name = sprintf( esc_html( '%s' ), $material->file_name );
217 - }
218 -
219 - return sprintf( '<td class="lp-material-file-name">%s</td>', $html_file_name );
220 - }
221 -
222 - /**
223 - * Generate HTML for file type.
224 - *
225 - * @param object $material Material object.
226 - *
227 - * @return string
228 - */
229 - public static function html_file_type( $material ): string {
230 - return sprintf( '<td class="lp-material-file-type">%s</td>', $material->file_type );
231 - }
232 -
233 - /**
234 - * Get file size in human-readable format.
235 - *
236 - * @param object $material Material object.
237 - *
238 - * @return string
239 - */
240 - public static function html_file_size( $material ): string {
241 - if ( $material->method == 'upload' ) {
242 - $file_size = filesize( wp_upload_dir()['basedir'] . $material->file_path );
243 - $file_size = ( $file_size / 1024 < 1024 ) ? round( $file_size / 1024, 2 ) . 'KB' : round( $file_size / 1024 / 1024, 2 ) . 'MB';
244 - } else {
245 - $args = array(
246 - 'timeout' => 0.1,
247 - );
248 - $file_head = wp_remote_head( $material->file_path, $args );
249 -
250 - if ( is_wp_error( $file_head )
251 - || ! isset( $file_head['headers']['content-length'] )
252 - || ! $file_head['headers']['content-length'] ) {
253 - $file_size = '';
254 - } else {
255 - $file_size = $file_head['headers']['content-length'];
256 - $file_size = self::convert_kb( intval( $file_size ) );
257 - }
258 - }
259 -
260 - return apply_filters(
261 - 'learn-press/course-material/file-size',
262 - sprintf( '<td class="lp-material-file-size">%s</td>', $file_size ),
263 - $material
264 - );
265 - }
266 -
267 - /**
268 - * Convert file size to human-readable format.
269 - *
270 - * @param int $file_size File size in bytes.
271 - *
272 - * @return string
273 - */
274 - public static function convert_kb( int $file_size ): string {
275 - // Convert bytes to kilobytes
276 - $file_size = $file_size / 1024;
277 -
278 - if ( $file_size < 1024 ) {
279 - return round( $file_size, 2 ) . 'KB';
280 - } elseif ( $file_size < 1048576 ) {
281 - return round( $file_size / 1024, 2 ) . 'MB';
282 - } else {
283 - return round( $file_size / 1048576, 2 ) . 'GB';
284 - }
285 - }
286 -
287 - /**
288 - * Generate HTML for file link.
289 - *
290 - * @param object $material Material object.
291 - *
292 - * @return string
293 - */
294 - public static function html_file_link( $material ): string {
295 - $file_path = $material->file_path ?? '';
296 - if ( empty( $file_path ) ) {
297 - return '';
298 - }
299 -
300 - $file_url = $file_path;
301 - if ( $material->method === 'upload' ) {
302 - $file_url = wp_upload_dir()['baseurl'] . $file_path;
303 - }
304 -
305 - $enable_nofollow = LP_Settings::instance()->get_option( 'material_url_nofollow', 'yes' );
306 - $rel = '';
307 - if ( $enable_nofollow == 'yes' && $material->method == 'external' ) {
308 - $rel = 'nofollow';
309 - }
310 -
311 - return apply_filters(
312 - 'learn-press/course-material/file-link',
313 - sprintf(
314 - '<td class="lp-material-file-link">
315 - <a href="%s" target="_blank" rel="%s">
316 - <i class="lp-icon-file-download btn-download-material"></i>
317 - </a>
318 - </td>',
319 - esc_url_raw( $file_url ),
320 - $rel
321 - )
322 - );
323 - }
324 -
325 - /**
326 - * Generate HTML for load more button.
327 - *
328 - * @param array $args Arguments containing pagination info.
329 - *
330 - * @return string
331 - */
332 - public static function html_load_more_btn( array $args = [] ): string {
333 - $paged = $args['paged'] ?? 1;
334 - $total_pages = $args['total_pages'] ?? 1;
335 -
336 - if ( $paged >= $total_pages ) {
337 - return '';
338 - }
339 -
340 - return apply_filters(
341 - 'learn-press/course-material/btn-load-more',
342 - sprintf(
343 - '<div class="lp-loadmore-material">
344 - <button class="lp-btn lp-loadmore-material">
345 - %s
346 - </button>
347 - </div>',
348 - esc_html__( 'Load More', 'learnpress' )
349 - )
350 - );
351 - }
352 -}
1 +<?php
2 +/**
3 + * Template hooks Archive Package.
4 + *
5 + * @since 1.0.0
6 + * @version 1.0.0
7 + */
8 +namespace LearnPress\TemplateHooks\Course;
9 +
10 +use LearnPress\Helpers\Template;
11 +use LearnPress\Models\CourseModel;
12 +use LearnPress\Models\UserItems\UserCourseModel;
13 +use LearnPress\Models\UserModel;
14 +use LearnPress\TemplateHooks\TemplateAJAX;
15 +use LP_Material_Files_DB;
16 +use stdClass;
17 +use LP_Global;
18 +use LP_WP_Filesystem;
19 +use LP_Settings;
20 +use Throwable;
21 +use Exception;
22 +class CourseMaterialTemplate {
23 + public static function instance() {
24 + static $instance = null;
25 +
26 + if ( is_null( $instance ) ) {
27 + $instance = new self();
28 + }
29 +
30 + return $instance;
31 + }
32 +
33 + protected function __construct() {
34 + add_action( 'learn-press/course-material/layout', array( $this, 'sections' ) );
35 + add_filter( 'lp/rest/ajax/allow_callback', array( $this, 'allow_callback' ) );
36 + }
37 + /**
38 + * Allow callback for AJAX.
39 + *
40 + * @param array $callbacks
41 + *
42 + * @return array
43 + */
44 + public function allow_callback( array $callbacks ): array {
45 + $callbacks[] = get_class( $this ) . ':render_material_items';
46 +
47 + return $callbacks;
48 + }
49 +
50 + /**
51 + * Layout for course material.
52 + *
53 + * @throws Exception
54 + */
55 + public function sections( array $data = array() ) {
56 + $item = LP_Global::course_item();
57 + $item_id = 0;
58 + if ( ! $item && get_post_type( get_the_ID() ) === LP_COURSE_CPT ) {
59 + $item_id = get_the_ID();
60 + } elseif ( $item ) {
61 + $item_id = $item->get_id();
62 + } else {
63 + throw new Exception( __( 'Item not found', 'learnpress' ) );
64 + }
65 + // $item_id = $item->get_id();
66 + $material_db = LP_Material_Files_DB::getInstance();
67 + $per_page = (int) LP_Settings::get_option( 'material_file_per_page', - 1 );
68 + $total_rows = $material_db->get_total( $item_id );
69 + $total_pages = $per_page > 0 ? ceil( $total_rows / $per_page ) : 0;
70 +
71 + $args = array_merge(
72 + [
73 + 'id_url' => 'course-material',
74 + 'item_id' => $item_id,
75 + 'paged' => 1,
76 + 'per_page' => $per_page,
77 + 'total_pages' => $total_pages,
78 + ],
79 + $data
80 + );
81 + if ( get_post_type( $item_id ) !== LP_COURSE_CPT ) {
82 + $args['course_id'] = $item->get_course_id();
83 + }
84 +
85 + $callback = array(
86 + 'class' => self::class,
87 + 'method' => 'render_material_items',
88 + );
89 + $content = TemplateAJAX::load_content_via_ajax( $args, $callback );
90 + $section = array(
91 + 'wrap' => '<div class="lp-material-skeleton">',
92 + 'content' => $content,
93 + 'wrap_end' => '</div>',
94 + );
95 + echo Template::combine_components( $section );
96 + }
97 +
98 + public static function render_material_items( $args ): stdClass {
99 + $content = new stdClass();
100 +
101 + try {
102 + $userModel = UserModel::find( get_current_user_id(), true );
103 + $course_id = $args['course_id'] ?? 0;
104 + $item_id = $args['item_id'] ?? 0;
105 + if ( get_post_type( $item_id ) === LP_COURSE_CPT ) {
106 + $courseModel = CourseModel::find( $item_id, true );
107 + } elseif ( $course_id ) {
108 + $courseModel = CourseModel::find( $course_id, true );
109 + } else {
110 + throw new Exception( esc_html__( 'Course not found!', 'learnpress' ) );
111 + }
112 +
113 + $can_show = false;
114 + if ( $userModel instanceof UserModel ) {
115 + if ( $courseModel->check_user_is_author( $userModel )
116 + || user_can( $userModel->get_id(), ADMIN_ROLE ) ) {
117 + $can_show = true;
118 + } else {
119 + $userCourseModel = UserCourseModel::find( $userModel->get_id(), $courseModel->get_id(), true );
120 + if ( $userCourseModel &&
121 + ( $userCourseModel->has_enrolled_or_finished()
122 + || $userCourseModel->has_purchased() ) ) {
123 + $can_show = true;
124 + }
125 + }
126 + } elseif ( $courseModel->has_no_enroll_requirement() ) {
127 + $can_show = true;
128 + }
129 +
130 + $can_show = apply_filters( 'learn-press/course-material/can-show', $can_show, $courseModel, $userModel );
131 +
132 + $file_per_page = LP_Settings::get_option( 'material_file_per_page', - 1 );
133 + $count_files = LP_Material_Files_DB::getInstance()->get_total( $courseModel->get_id() );
134 + if ( ! $can_show || $file_per_page == 0 || $count_files <= 0 ) {
135 + throw new Exception( '' );
136 + }
137 +
138 + $material_db = LP_Material_Files_DB::getInstance();
139 + $paged = absint( $args['paged'] ?? 1 );
140 + $per_page = intval( $args['per_page'] ?? 1 );
141 + $offset = ( $per_page > 0 && $paged > 1 ) ? $per_page * ( $paged - 1 ) : 0;
142 + // $total_pages = $per_page > 0 ? ceil( $total_rows / $per_page ) : 0;
143 + $material_files = $material_db->get_material_by_item_id( $args['item_id'], $per_page, $offset, false );
144 + if ( empty( $material_files ) ) {
145 + $content->content = '';
146 + } else {
147 + $material_html = '';
148 + foreach ( $material_files as $m ) {
149 + $material_html .= self::material_item( $m, $args['item_id'] );
150 + }
151 + if ( $args['paged'] === 1 ) {
152 + $sections = array(
153 + 'wrap' => '<div class="lp-list-material">',
154 + 'table_wrap' => '<table class="course-material-table" >',
155 + 'table_header' => self::table_header(),
156 + 'table_body' => '<tbody>',
157 + 'material_html' => $material_html,
158 + 'table_body_end' => '</tbody>',
159 + 'table_wrap_end' => '</table>',
160 + 'loadmore_btn' => self::html_load_more_btn( $args ),
161 + 'wrap_end' => '</div>',
162 + );
163 + $content->content = Template::combine_components( $sections );
164 + } else {
165 + $content->content = $material_html;
166 + }
167 + $content->total_pages = $args['total_pages'];
168 + $content->paged = $args['paged'];
169 + }
170 + } catch ( Throwable $e ) {
171 + if ( $e->getMessage() === '' ) {
172 + $content->content = '';
173 + } else {
174 + $content->content = Template::print_message( $e->getMessage(), 'error', false );
175 + }
176 + }
177 + return $content;
178 + }
179 +
180 + public static function table_header() {
181 + $sections = array(
182 + 'wrap' => '<thead>',
183 + 'file-name' => sprintf( '<th class="lp-material-th-file-name">%s</th>', esc_html__( 'Name', 'learnpress' ) ),
184 + 'file-type' => sprintf( '<th class="lp-material-th-file-type">%s</th>', esc_html__( 'Type', 'learnpress' ) ),
185 + 'file-size' => sprintf( '<th class="lp-material-th-file-size">%s</th>', esc_html__( 'Size', 'learnpress' ) ),
186 + 'file-link' => sprintf( '<th class="lp-material-th-file-link">%s</th>', esc_html__( 'Download', 'learnpress' ) ),
187 + 'wrap_end' => '</thead>',
188 + );
189 + return Template::combine_components( $sections );
190 + }
191 +
192 + public static function material_item( $material, $current_item_id ) {
193 + $sections = array(
194 + 'wrap' => '<tr class="lp-material-item">',
195 + 'file-name' => self::html_file_name( $material, $current_item_id ),
196 + 'file-type' => self::html_file_type( $material ),
197 + 'file-size' => self::html_file_size( $material ),
198 + 'file-link' => self::html_file_link( $material ),
199 + 'wrap_end' => '</tr>',
200 + );
201 + return Template::combine_components( $sections );
202 + }
203 +
204 + /**
205 + * Generate HTML for file name.
206 + *
207 + * @param object $material Material object.
208 + * @param int $current_item_id Current item ID.
209 + *
210 + * @return string
211 + */
212 + public static function html_file_name( $material, $current_item_id ): string {
213 + if ( get_post_type( $current_item_id ) == LP_COURSE_CPT && $material->item_type == LP_LESSON_CPT ) {
214 + $html_file_name = sprintf( esc_html( '%1$s ( %2$s )' ), $material->file_name, get_the_title( $material->item_id ) );
215 + } else {
216 + $html_file_name = sprintf( esc_html( '%s' ), $material->file_name );
217 + }
218 +
219 + return sprintf( '<td class="lp-material-file-name">%s</td>', $html_file_name );
220 + }
221 +
222 + /**
223 + * Generate HTML for file type.
224 + *
225 + * @param object $material Material object.
226 + *
227 + * @return string
228 + */
229 + public static function html_file_type( $material ): string {
230 + return sprintf( '<td class="lp-material-file-type">%s</td>', $material->file_type );
231 + }
232 +
233 + /**
234 + * Get file size in human-readable format.
235 + *
236 + * @param object $material Material object.
237 + *
238 + * @return string
239 + */
240 + public static function html_file_size( $material ): string {
241 + if ( $material->method == 'upload' ) {
242 + $file_size = filesize( wp_upload_dir()['basedir'] . $material->file_path );
243 + $file_size = ( $file_size / 1024 < 1024 ) ? round( $file_size / 1024, 2 ) . 'KB' : round( $file_size / 1024 / 1024, 2 ) . 'MB';
244 + } else {
245 + $args = array(
246 + 'timeout' => 0.1,
247 + );
248 + $file_head = wp_remote_head( $material->file_path, $args );
249 +
250 + if ( is_wp_error( $file_head )
251 + || ! isset( $file_head['headers']['content-length'] )
252 + || ! $file_head['headers']['content-length'] ) {
253 + $file_size = '';
254 + } else {
255 + $file_size = $file_head['headers']['content-length'];
256 + $file_size = self::convert_kb( intval( $file_size ) );
257 + }
258 + }
259 +
260 + return apply_filters(
261 + 'learn-press/course-material/file-size',
262 + sprintf( '<td class="lp-material-file-size">%s</td>', $file_size ),
263 + $material
264 + );
265 + }
266 +
267 + /**
268 + * Convert file size to human-readable format.
269 + *
270 + * @param int $file_size File size in bytes.
271 + *
272 + * @return string
273 + */
274 + public static function convert_kb( int $file_size ): string {
275 + // Convert bytes to kilobytes
276 + $file_size = $file_size / 1024;
277 +
278 + if ( $file_size < 1024 ) {
279 + return round( $file_size, 2 ) . 'KB';
280 + } elseif ( $file_size < 1048576 ) {
281 + return round( $file_size / 1024, 2 ) . 'MB';
282 + } else {
283 + return round( $file_size / 1048576, 2 ) . 'GB';
284 + }
285 + }
286 +
287 + /**
288 + * Generate HTML for file link.
289 + *
290 + * @param object $material Material object.
291 + *
292 + * @return string
293 + */
294 + public static function html_file_link( $material ): string {
295 + $file_path = $material->file_path ?? '';
296 + if ( empty( $file_path ) ) {
297 + return '';
298 + }
299 +
300 + $file_url = $file_path;
301 + if ( $material->method === 'upload' ) {
302 + $file_url = wp_upload_dir()['baseurl'] . $file_path;
303 + }
304 +
305 + $enable_nofollow = LP_Settings::instance()->get_option( 'material_url_nofollow', 'yes' );
306 + $rel = '';
307 + if ( $enable_nofollow == 'yes' && $material->method == 'external' ) {
308 + $rel = 'nofollow';
309 + }
310 +
311 + return apply_filters(
312 + 'learn-press/course-material/file-link',
313 + sprintf(
314 + '<td class="lp-material-file-link">
315 + <a href="%s" target="_blank" rel="%s">
316 + <i class="lp-icon-file-download btn-download-material"></i>
317 + </a>
318 + </td>',
319 + esc_url_raw( $file_url ),
320 + $rel
321 + )
322 + );
323 + }
324 +
325 + /**
326 + * Generate HTML for load more button.
327 + *
328 + * @param array $args Arguments containing pagination info.
329 + *
330 + * @return string
331 + */
332 + public static function html_load_more_btn( array $args = [] ): string {
333 + $paged = $args['paged'] ?? 1;
334 + $total_pages = $args['total_pages'] ?? 1;
335 +
336 + if ( $paged >= $total_pages ) {
337 + return '';
338 + }
339 +
340 + return apply_filters(
341 + 'learn-press/course-material/btn-load-more',
342 + sprintf(
343 + '<div class="lp-loadmore-material">
344 + <button class="lp-btn lp-loadmore-material">
345 + %s
346 + </button>
347 + </div>',
348 + esc_html__( 'Load More', 'learnpress' )
349 + )
350 + );
351 + }
352 +}