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
learnpress / inc / rest-api / v1 / frontend / class-lp-rest-material-controller.php

class-lp-rest-material-controller.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.4.8, at inc/rest-api/v1/frontend/class-lp-rest-material-controller.php

567 lines 18.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use LearnPress\Helpers\Template;
4 use LearnPress\Models\UserItems\UserCourseModel;
5 use LearnPress\TemplateHooks\Course\CourseMaterialTemplate;
6 use LearnPress\Models\CourseModel;
7
8 /**
9 * Class LP_Rest_Material_Controller
10 * in LearnPres > Downloadable Materials
11 *
12 * @since 4.2.2
13 * @author khanhbd
14 * @version 1.0.2
15 */
16 class LP_Rest_Material_Controller extends LP_Abstract_REST_Controller {
17
18 public function __construct() {
19 $this->namespace = 'lp/v1/';
20 $this->rest_base = 'material';
21
22 parent::__construct();
23 }
24
25 public function register_routes() {
26 $this->routes = array(
27 'item-materials/(?P<item_id>[\d]+)' => array(
28 'args' => array(
29 'item_id' => array(
30 'description' => __( 'A unique identifier for the resource.', 'learnpress' ),
31 'type' => 'integer',
32 'sanitize_callback' => 'absint',
33 ),
34 ),
35 array(
36 'methods' => WP_REST_Server::CREATABLE,
37 'callback' => array( $this, 'save_post_materials' ),
38 'permission_callback' => array( $this, 'check_user_can_edit_material' ),
39 'args' => array(
40 'data' => array(
41 'description' => esc_html__( 'Data of material', 'learnpress' ),
42 'type' => 'string',
43 'required' => true,
44 'sanitize_callback' => 'sanitize_text_field',
45 ),
46 'file' => array(
47 'description' => esc_html__( 'File.', 'learnpress' ),
48 'type' => 'array',
49 ),
50 ),
51 ),
52 array(
53 'methods' => WP_REST_Server::READABLE,
54 'callback' => array( $this, 'backend_get_materials_by_item' ),
55 'permission_callback' => array( $this, 'check_user_can_edit_material' ),
56 ),
57 array(
58 'methods' => WP_REST_Server::EDITABLE,
59 'callback' => array( $this, 'update_material_orders' ),
60 'permission_callback' => array( $this, 'check_user_can_edit_material' ),
61 'args' => array(
62 'sort_arr' => array(
63 'description' => esc_html__( 'Material orders', 'learnpress' ),
64 'type' => 'string',
65 'required' => true,
66 'sanitize_callback' => 'sanitize_text_field',
67 ),
68 ),
69 ),
70 ),
71 '(?P<file_id>[\d]+)' => array(
72 'args' => array(
73 'file_id' => array(
74 'description' => __( 'A unique identifier for the resource.', 'learnpress' ),
75 'type' => 'integer',
76 ),
77 ),
78 array(
79 'methods' => WP_REST_Server::DELETABLE,
80 'callback' => array( $this, 'delete_material' ),
81 'permission_callback' => array( $this, 'check_user_can_edit_material' ),
82 ),
83 ),
84 /*'by-item' => array(
85 array(
86 'methods' => WP_REST_Server::CREATABLE,
87 'callback' => array( $this, 'get_materials_by_item' ),
88 'permission_callback' => '__return_true',
89 ),
90 ),*/
91 );
92
93 parent::register_routes();
94 }
95
96 /**
97 * Save files materials
98 *
99 * @param WP_REST_Request $request
100 *
101 * @return LP_REST_Response
102 * @version 1.0.1
103 * @since 4.2.2
104 */
105 public function save_post_materials( WP_REST_Request $request ) {
106 $response = new LP_REST_Response();
107 $response->data = [];
108
109 try {
110 $params = $request->get_params();
111 $item_id = $params['item_id'] ?? 0;
112 $material_data_string = $params['data'] ?? false;
113 $upload_file = $request->get_file_params();
114
115 if ( empty( $item_id ) ) {
116 throw new Exception( esc_html__( 'Invalid course or lesson', 'learnpress' ) );
117 }
118
119 if ( empty( $material_data_string ) ) {
120 throw new Exception( esc_html__( 'Invalid materials', 'learnpress' ) );
121 }
122
123 $material_data = LP_Helper::json_decode( wp_unslash( $material_data_string ), true );
124 $file = $upload_file['file'] ?? false;
125
126 // DB Init
127 $material_db = LP_Material_Files_DB::getInstance();
128 // LP Material Settings
129 $max_file_size = (int) LP_Settings::get_option( 'material_max_file_size', 2 );
130 $allow_upload_amount = (int) LP_Settings::get_option( 'material_upload_files', 2 );
131 // check file was uploaded
132 $count_uploaded_files = count( $material_db->get_material_by_item_id( $item_id, 0, 0, 1 ) );
133 // check file amount which can upload
134 $can_upload = $allow_upload_amount - $count_uploaded_files;
135
136 //Check file amount validation
137 if ( $can_upload <= 0 ) {
138 throw new Exception( esc_html__( 'Material feature is not allowed to upload', 'learnpress' ) );
139 } elseif ( $allow_upload_amount > 0 ) {
140 if ( count( $material_data ) > $can_upload ) {
141 throw new Exception( esc_html__( 'Your uploaded files reach the maximum amount!', 'learnpress' ) );
142 }
143 }
144
145 $file_methods = array( 'upload', 'external' );
146 $error_messages = '';
147 $success_messages = '';
148 foreach ( $material_data as $key => $material ) {
149 $label = LP_Helper::sanitize_params_submitted( $material['label'] ?? '' );
150 $method = $material['method'] ?? '';
151 $file_name = $file['name'][ $key ] ?? '';
152
153 // check file title
154 if ( empty( $label ) ) {
155 $error_messages .= sprintf( __( 'File "%s" title is not empty!', 'learnpress' ), $file_name );
156 continue;
157 }
158 // check file upload method
159 if ( ! in_array( $method, $file_methods ) ) {
160 $error_messages .= sprintf( __( 'File %s method is invalid!', 'learnpress' ), $label );
161 continue;
162 }
163
164 $file_path = '';
165 if ( $method == 'upload' ) {
166 if ( $file['size'][ $key ] > $max_file_size * 1024 * 1024 ) {
167 $error_messages .= sprintf( __( 'File %s size is too large!', 'learnpress' ), $label );
168 continue;
169 }
170
171 // Check type file
172 $file_info = wp_check_filetype( $file_name );
173 $file_type = $file_info['ext'] ?? '';
174 if ( empty( $file_info['ext'] )
175 || false === $this->material_check_file_extention( $file_info['ext'] )
176 || ! in_array( $file_info['type'], get_allowed_mime_types() ) ) {
177 $error_messages .= sprintf( esc_html__( 'File %s type is invalid!', 'learnpress' ), $label );
178 continue;
179 }
180
181 LP_WP_Filesystem::instance();
182 $file_uploading = [
183 'name' => $file_name,
184 'type' => $file_type,
185 'tmp_name' => $file['tmp_name'][ $key ],
186 'error' => $file['error'][ $key ],
187 'size' => $file['size'][ $key ],
188 ];
189 $file_handle_upload = wp_handle_upload( $file_uploading, [ 'test_form' => false ] );
190 if ( ! empty( $file_handle_upload['error'] ) ) {
191 $error_messages .= sprintf( esc_html__( 'File %s: ', 'learnpress' ), $label ) . $file_handle_upload['error'];
192 continue;
193 }
194
195 $file_path = str_replace( wp_upload_dir()['baseurl'], '', $file_handle_upload['url'] );
196 } elseif ( $method == 'external' ) {
197 $file_path = sanitize_url( $material['link'] );
198 $file_info = pathinfo( $file_path );
199 $file_extend = $file_info['extension'] ?? '';
200 if ( ! $file_extend ) {
201 $file_type = __( 'Unknown', 'learnpress' );
202 } else {
203 $file_type = $file_extend;
204 }
205 $check_allow_file = $this->check_wp_allowed_file_type( $file_extend );
206 if ( ! $check_allow_file ) {
207 $error_messages .= sprintf(
208 esc_html__( 'An error occurred while checking %1$s. %2$s', 'learnpress' ),
209 $label,
210 __( 'Oops! That file type isn’t allowed.', 'learnpress' )
211 );
212 continue;
213 }
214
215 // For a long time remove this code. @since 4.2.6.6
216 $material_db->wpdb->query(
217 "ALTER TABLE $material_db->tb_lp_files MODIFY file_type VARCHAR(100) NOT NULL DEFAULT '';"
218 );
219 }
220
221 $orders = $count_uploaded_files + $key + 1;
222 $insert_arr = [
223 'file_name' => sanitize_text_field( $label ),
224 'file_type' => $file_type ?? '',
225 'item_id' => (int) $item_id,
226 'item_type' => get_post_type( $item_id ),
227 'method' => $method,
228 'file_path' => $file_path,
229 'orders' => $orders,
230 'created_at' => current_time( 'Y-m-d H:i:s' ),
231 ];
232 $insert = $material_db->create_material( $insert_arr );
233 if ( ! $insert ) {
234 $error_messages .= sprintf( __( 'Cannot save file %s', 'learnpress' ), $label );
235 continue;
236 }
237
238 $success_messages .= __( 'Other files is upload successfully.', 'learnpress' );
239 $response->data[] = [
240 'file_name' => $label,
241 'method' => ucfirst( $method ),
242 'file_id' => $insert,
243 'orders' => $orders,
244 ];
245 }
246
247 if ( ! empty( $error_messages ) ) {
248 $response->message .= $error_messages;
249 }
250
251 if ( ! empty( $success_messages ) ) {
252 $response->status = 'success';
253 if ( empty( $error_messages ) ) {
254 $success_messages = __( 'Files upload successfully.', 'learnpress' );
255 }
256 $response->message .= $success_messages;
257 }
258 } catch ( Throwable $e ) {
259 $response->message = $e->getMessage();
260 }
261
262 return $response;
263 }
264
265 /**
266 * Get list files of a course or a lesson (use in wp-admin)
267 *
268 * @param WP_REST_Request $request
269 *
270 * @return LP_REST_Response
271 * @version 1.0.2
272 * @since 4.2.2
273 */
274 public function backend_get_materials_by_item( WP_REST_Request $request ): LP_REST_Response {
275 $response = new LP_REST_Response();
276
277 try {
278 $params = $request->get_params();
279 $item_id = $params['item_id'] ?? 0;
280 if ( ! $item_id ) {
281 throw new Exception( esc_html__( 'Invalid item id!', 'learnpress' ) );
282 }
283
284 $material_db = LP_Material_Files_DB::getInstance();
285 $page = absint( $params['page'] ?? 1 );
286 $per_page = $params['per_page'] ?? (int) LP_Settings::get_option( 'material_file_per_page', - 1 );
287 $offset = ( $per_page > 0 && $page > 1 ) ? $per_page * ( $page - 1 ) : 0;
288 $item_materials = $material_db->get_material_by_item_id( $item_id, $per_page, $offset, true );
289
290 if ( $item_materials ) {
291 $response->data->items = $item_materials;
292 $response->message = esc_html__( 'Successfully', 'learnpress' );
293 } else {
294 $response->message = esc_html__( 'Empty material!', 'learnpress' );
295 }
296
297 $response->status = 'success';
298 } catch ( Throwable $th ) {
299 $response->message = $th->getMessage();
300 }
301
302 return $response;
303 }
304
305 /**
306 * Get info file from external link
307 *
308 * @param $file_url
309 *
310 * @return array
311 * @version 1.0.1
312 * @since 4.2.2
313 * @depreacted 4.2.7.8.5
314 */
315 public function check_external_file( $file_url ): array {
316 $lp_file = LP_WP_Filesystem::instance();
317 $temp_file = $lp_file->download_url( $file_url );
318 $file = [];
319 if ( is_wp_error( $temp_file ) ) {
320 $file['error'] = true;
321 $file['error_message'] = $temp_file->get_error_message();
322 } else {
323 $file = array(
324 'name' => basename( $file_url ),
325 'type' => mime_content_type( $temp_file ),
326 'tmp_name' => $temp_file,
327 'size' => filesize( $temp_file ),
328 'error' => false,
329 'error_message' => '',
330 );
331 }
332
333 return $file;
334 }
335
336 /**
337 * @param [string] $file_name [upload file name]
338 * @param [] $file_tmp [file content]
339 *
340 * @return [array] [file infomations]
341 * @since 4.2.2
342 * [material_upload_file upload file when user choose upload method]
343 * @version 1.0.0
344 */
345 public function material_upload_file( $file_name, $file_tmp ) {
346 try {
347 $file = wp_upload_bits( $file_name, null, file_get_contents( $file_tmp ) );
348
349 return $file['error'] ? false : $file;
350 } catch ( Throwable $e ) {
351 error_log( $e->getMessage() );
352 }
353 }
354
355 /**
356 * @param [string] $ext [file extendsion]
357 *
358 * @return [string] [file extendsion]
359 * @version 1.0.0
360 * @since 4.2.2
361 * [material_check_file_extention return file type of file]
362 */
363 public function material_check_file_extention( $ext ) {
364 $allow_file_type = LP_Settings::get_option( 'material_allow_file_type', array( 'pdf', 'txt' ) );
365 $allow_file_type = implode( ',', $allow_file_type );
366 $allow_file_type = explode( ',', $allow_file_type );
367
368 return in_array( $ext, $allow_file_type ) ? $ext : false;
369 }
370
371
372 public function update_material_orders( WP_REST_Request $request ) {
373 $response = new LP_REST_Response();
374 try {
375 $item_id = $request['item_id'];
376 $sort_arr = $request->get_param( 'sort_arr' );
377 $sort_arr = json_decode( wp_unslash( $sort_arr ), true );
378 $material_db = LP_Material_Files_DB::getInstance();
379 $update_sort = $material_db->update_material_orders( $sort_arr, $item_id );
380 if ( $update_sort ) {
381 $response->status = 200;
382 $response->message = esc_html__( 'Updated.', 'learnpress' );
383 // $response->data = $sort_arr;
384 } else {
385 throw new Exception( esc_html__( 'Update failed!', 'learnpress' ) );
386 }
387 } catch ( Throwable $e ) {
388 $response->status = 400;
389 $response->message = $e->getMessage();
390 }
391
392 return rest_ensure_response( $response );
393 }
394
395 /**
396 * @param [type] $request [description]
397 *
398 * @return [json] [return message]
399 * @version 1.0.0
400 * @since 4.2.2
401 * [delete_material delete a material when a delete request is send]
402 */
403 public function delete_material( WP_REST_Request $request ) {
404 $response = new LP_REST_Response();
405 try {
406 $file_id = $request['file_id'];
407 if ( ! $file_id ) {
408 throw new Exception( esc_html__( 'Invalid file identifier', 'learnpress' ) );
409 }
410 // DB Init
411 $material_db = LP_Material_Files_DB::getInstance();
412 $file = $material_db->get_material( $file_id );
413 if ( ! $file ) {
414 throw new Exception( esc_html__( 'File not found', 'learnpress' ) );
415 }
416
417 // Get file author
418 $item_id = $file->item_id ?? 0;
419 $author = get_post_field( 'post_author', $item_id );
420 $current_user_id = get_current_user_id();
421 // check permission
422 if ( ! ( ( $author == $current_user_id && current_user_can( LP_TEACHER_ROLE ) ) || current_user_can( ADMIN_ROLE ) ) ) {
423 throw new Exception( esc_html__( 'You do not have permission to delete this file.', 'learnpress' ) );
424 }
425
426 // Delete record
427 $delete = $material_db->delete_material( $file_id );
428 if ( $delete ) {
429 $message = esc_html__( 'File is deleted.', 'learnpress' );
430 $deleted = true;
431 } else {
432 $message = esc_html__( 'There is an error when delete this file.', 'learnpress' );
433 $deleted = false;
434 }
435 $response->status = 200;
436 $response->delete = $deleted;
437 $response->message = $message;
438 } catch ( Throwable $th ) {
439 $response->status = 400;
440 $response->message = $th->getMessage();
441 }
442
443 return rest_ensure_response( $response );
444 }
445
446 /**
447 * Check user can view materials of item
448 *
449 * @param int $course_id course id
450 * @param int $lesson_id lesson id
451 *
452 * @throws Exception
453 * @since 4.2.7.4
454 * @version 1.0.0
455 */
456 public function check_user_can_get_materials( int $course_id, int $lesson_id ) {
457 $current_user = learn_press_get_current_user();
458 if ( $lesson_id && get_post_field( 'post_type', $lesson_id ) === LP_LESSON_CPT ) {
459 $can_view_content_course = $current_user->can_view_content_course( $course_id );
460 $can_view = $current_user->can_view_item( $lesson_id, $can_view_content_course );
461 } else {
462 $can_view = $current_user->can_view_content_course( $course_id );
463 }
464
465 if ( ! $can_view->flag ) {
466 $error_message = $can_view->message;
467 throw new Exception( $error_message );
468 }
469 }
470
471 /**
472 * Get material file of course or lesson
473 *
474 * @param WP_REST_Request $request
475 * @return WP_REST_Response $response
476 * @since 4.2.7.4
477 * @deprecated 4.2.8.7.5
478 * @version 1.0.0
479 */
480 /*
481 public function get_materials_by_item( WP_REST_Request $request ) {
482 $response = new LP_REST_Response();
483
484 try {
485 $params = $request->get_params();
486 $course_id = (int) $params['course_id'] ?? 0;
487 $item_id = (int) $params['item_id'] ?? 0;
488
489 $course = CourseModel::find( $course_id, true );
490 if ( ! $course ) {
491 throw new Exception( __( 'Course not found', 'learnpress' ) );
492 }
493
494 $this->check_user_can_get_materials( $course_id, $item_id );
495
496 if ( ! $item_id ) {
497 $get_materials_for_item_id = $course_id;
498 } else {
499 $get_materials_for_item_id = $item_id;
500 }
501
502 $material_db = LP_Material_Files_DB::getInstance();
503 $page = absint( $params['page'] ?? 1 );
504 $per_page = $params['per_page'] ?? (int) LP_Settings::get_option( 'material_file_per_page', - 1 );
505 $offset = ( $per_page > 0 && $page > 1 ) ? $per_page * ( $page - 1 ) : 0;
506 $total = $material_db->get_total( $get_materials_for_item_id );
507 $pages = $per_page > 0 ? ceil( $total / $per_page ) : 0;
508 $item_materials = $material_db->get_material_by_item_id( $get_materials_for_item_id, $per_page, $offset, false );
509 if ( $item_materials ) {
510 $response->data->load_more = $page < $pages && $per_page > 0;
511 ob_start();
512 $material_template = CourseMaterialTemplate::instance();
513 foreach ( $item_materials as $m ) {
514 $m->current_item_id = $get_materials_for_item_id;
515 echo $material_template->material_item( $m );
516 }
517 $response->data->items = ob_get_clean();
518 $response->message = esc_html__( 'Successfully', 'learnpress' );
519 } else {
520 $response->message = esc_html__( 'Empty material!', 'learnpress' );
521 }
522
523 $response->status = 'success';
524 } catch ( Throwable $e ) {
525 $response->message = Template::print_message( $e->getMessage(), 'warning', false );
526 }
527
528 return rest_ensure_response( $response );
529 }*/
530
531 /**
532 * Check user permission
533 *
534 * @param $request
535 *
536 * @return bool
537 * @version 1.0.1
538 * @since 4.2.2
539 */
540 public function check_user_can_edit_material( $request ): bool {
541 $permission = false;
542 $item_id = $request['item_id'] ?? $request->get_param( 'item_id' );
543 $author = get_post_field( 'post_author', $item_id );
544 $current_user_id = get_current_user_id();
545 if ( ( $author == $current_user_id && current_user_can( LP_TEACHER_ROLE ) ) || current_user_can( ADMIN_ROLE ) ) {
546 $permission = true;
547 }
548
549 return apply_filters( 'learnpress/rest-material/can-edit-material', $permission );
550 }
551
552 /**
553 * [check_wp_allowed_file_type description]
554 * @param string $file_ext file extend(png, jpg.....)
555 * @return boolean
556 */
557 public function check_wp_allowed_file_type( string $file_ext = '' ): bool {
558 $allowed = get_allowed_mime_types();
559 foreach ( $allowed as $ext => $mime ) {
560 if ( strpos( $ext, $file_ext ) !== false ) {
561 return true; // Found the string in a key
562 }
563 }
564 return false;
565 }
566 }
567