PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.9
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.9
4.4.9 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 All 140 releases
learnpress / inc / TemplateHooks / Course / CourseMaterialTemplate.php

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

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