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

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

353 lines 10.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 }
353