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
← All changes | inc/rest-api/v1/frontend/class-lp-rest-material-controller.php +566 -566 4.3.8 → 4.4.9 View file →
@@ -1,566 +1,566 @@
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 -}
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 +}