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-profile-controller.php

class-lp-rest-profile-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-profile-controller.php

660 lines 19.9 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\Response;
4 use LearnPress\Helpers\Template;
5 use LearnPress\Models\UserModel;
6
7 class LP_REST_Profile_Controller extends LP_Abstract_REST_Controller {
8 public function __construct() {
9 $this->namespace = 'lp/v1';
10 $this->rest_base = 'profile';
11
12 parent::__construct();
13 }
14
15 public function register_routes() {
16 $this->routes = array(
17 'student/statistic' => array(
18 array(
19 'methods' => WP_REST_Server::READABLE,
20 'callback' => array( $this, 'student_statistics' ),
21 'permission_callback' => array( $this, 'check_permission' ),
22 ),
23 ),
24 'instructor/statistic' => array(
25 array(
26 'methods' => WP_REST_Server::READABLE,
27 'callback' => array( $this, 'instructor_statistics' ),
28 'permission_callback' => '__return_true',
29 ),
30 ),
31 'course-tab' => array(
32 array(
33 'methods' => WP_REST_Server::READABLE,
34 'callback' => array( $this, 'course_tab' ),
35 'permission_callback' => array( $this, 'check_permission' ),
36 ),
37 ),
38 /*'course-attend' => array(
39 array(
40 'methods' => WP_REST_Server::CREATABLE,
41 'callback' => array( $this, 'course_attend' ),
42 'permission_callback' => array( $this, 'check_permission' ),
43 ),
44 ),*/
45 'get-avatar' => array(
46 array(
47 'methods' => WP_REST_Server::READABLE,
48 'callback' => array( $this, 'get_avatar' ),
49 'permission_callback' => function () {
50 return (bool) get_current_user_id();
51 },
52 ),
53 ),
54 'upload-avatar' => array(
55 array(
56 'methods' => WP_REST_Server::CREATABLE,
57 'callback' => array( $this, 'upload_avatar' ),
58 'permission_callback' => function () {
59 return (bool) get_current_user_id();
60 },
61 ),
62 ),
63 'remove-avatar' => array(
64 array(
65 'methods' => WP_REST_Server::CREATABLE,
66 'callback' => array( $this, 'remove_avatar' ),
67 'permission_callback' => function () {
68 return (bool) get_current_user_id();
69 },
70 ),
71 ),
72 'cover-image' => array(
73 array(
74 'methods' => WP_REST_Server::CREATABLE,
75 'callback' => array( $this, 'handle_cover_image' ),
76 'permission_callback' => function () {
77 return get_current_user_id();
78 },
79 ),
80 ),
81 );
82
83 parent::register_routes();
84 }
85
86 /**
87 * Check permission
88 *
89 * @param $request
90 *
91 * @return bool
92 */
93 public function check_permission( $request ): bool {
94 $user_id = $request->get_param( 'userID' );
95
96 if ( empty( $user_id ) ) {
97 return false;
98 }
99
100 /*$profile = learn_press_get_profile( $user_id );
101
102 if ( ! $profile->current_user_can( 'view-tab-my-courses' ) ) {
103 return false;
104 }*/
105
106 return true;
107 }
108
109 public function get_avatar( WP_REST_Request $request ) {
110 $response = new LP_REST_Response();
111
112 $thumb_size = learn_press_get_avatar_thumb_size();
113
114 $profile = LP_Profile::instance( get_current_user_id() );
115 $avatar_url = $profile->get_upload_profile_src();
116
117 $response->data->width = $thumb_size['width'];
118 $response->data->height = $thumb_size['height'];
119 $response->data->url = $avatar_url ? $avatar_url : '';
120
121 return rest_ensure_response( $response );
122 }
123
124 /**
125 * Upload avatar
126 *
127 * @param WP_REST_Request $request
128 * @return WP_Error|WP_HTTP_Response|WP_REST_Response
129 */
130 public function upload_avatar( WP_REST_Request $request ) {
131 $file_base64 = $request->get_param( 'file' );
132 $response = new LP_REST_Response();
133
134 try {
135 $user_id = get_current_user_id();
136 if ( ! $user_id ) {
137 throw new Exception( __( 'User not found', 'learnpress' ) );
138 }
139
140 $userModel = UserModel::find( $user_id, true );
141 if ( ! $userModel ) {
142 throw new Exception( __( 'User not found', 'learnpress' ) );
143 }
144
145 if ( empty( $file_base64 ) ) {
146 throw new Exception( __( 'File not found', 'learnpress' ) );
147 }
148
149 $upload_dir = learn_press_user_profile_picture_upload_dir();
150
151 $target_dir = LP_WP_Filesystem::instance()->is_dir( $upload_dir['path'] );
152
153 if ( ! $target_dir ) {
154 wp_mkdir_p( $upload_dir['path'] );
155 }
156
157 if ( ! LP_WP_Filesystem::instance()->is_writable( $upload_dir['path'] ) ) {
158 throw new Exception( __( 'The upload directory is not writable', 'learnpress' ) );
159 }
160
161 // Delete old image if exists
162 $path_img = $userModel->get_meta_value_by_key( UserModel::META_KEY_IMAGE );
163 if ( $path_img ) {
164 if ( 0 === strpos( $path_img, '/' ) ) {
165 $path = $upload_dir['basedir'] . $path_img;
166 } else {
167 $path = trailingslashit( $upload_dir['path'] ) . basename( $path_img );
168 }
169
170 if ( file_exists( $path ) ) {
171 LP_WP_Filesystem::instance()->unlink( $path );
172 }
173 }
174
175 $file_name = md5( $user_id . microtime( true ) ) . '.png';
176
177 $file_base64 = str_replace( 'data:image/png;base64,', '', $file_base64 );
178 $file_base64 = base64_decode( $file_base64 );
179 if ( false === $file_base64 ) {
180 throw new Exception( __( 'Invalid avatar image data', 'learnpress' ) );
181 }
182
183 // Check file size
184 $max_size = wp_max_upload_size();
185 if ( $max_size > 0 && strlen( $file_base64 ) > $max_size ) {
186 throw new Exception( __( 'Avatar image is too large', 'learnpress' ) );
187 }
188
189 // Create file temp to check MIME
190 $tmp_file = wp_tempnam();
191 if ( ! $tmp_file ) {
192 throw new Exception( __( 'Cannot create temporary file', 'learnpress' ) );
193 }
194
195 $write_tmp = LP_WP_Filesystem::instance()->put_contents( $tmp_file, $file_base64 );
196 if ( false === $write_tmp ) {
197 LP_WP_Filesystem::instance()->unlink( $tmp_file );
198 throw new Exception( __( 'Cannot write temporary file', 'learnpress' ) );
199 }
200
201 $allowed_mimes = array(
202 'png' => 'image/png',
203 );
204 $check = wp_check_filetype_and_ext( $write_tmp, $file_name, $allowed_mimes );
205
206 if ( empty( $check['type'] ) ) {
207 throw new Exception( __( 'Invalid avatar image type', 'learnpress' ) );
208 }
209
210 if ( ! empty( $check['proper_filename'] ) ) {
211 $file_name = $check['proper_filename'];
212 }
213
214 // Re-encode the image to strip embedded scripts or malicious metadata.
215 $editor = wp_get_image_editor( $tmp_file );
216 if ( is_wp_error( $editor ) ) {
217 LP_WP_Filesystem::instance()->unlink( $write_tmp );
218 throw new Exception( __( 'Cannot create image editor', 'learnpress' ) );
219 }
220
221 $editor->set_quality( 100 );
222 $editor->save( $upload_dir['path'] . '/' . $file_name );
223
224 $path_save = trailingslashit( $upload_dir['subdir'] ) . $file_name;
225 $userModel->set_meta_value_by_key( UserModel::META_KEY_IMAGE, $path_save );
226 do_action( 'learnpress/rest/frontend/profile/upload_avatar', $user_id );
227
228 $response->status = 'success';
229 $response->message = __( 'Avatar updated', 'learnpress' );
230 } catch ( Throwable $th ) {
231 $response->message = $th->getMessage();
232 }
233
234 return rest_ensure_response( $response );
235 }
236
237 public function remove_avatar( WP_REST_Request $request ) {
238 $response = new Response();
239
240 try {
241 $user_id = get_current_user_id();
242
243 if ( ! $user_id ) {
244 throw new Exception( esc_html__( 'The user is invalid', 'learnpress' ) );
245 }
246
247 $upload_dir = learn_press_user_profile_picture_upload_dir( true );
248
249 $target_dir = LP_WP_Filesystem::instance()->is_dir( $upload_dir['path'] );
250
251 if ( ! $target_dir ) {
252 wp_mkdir_p( $upload_dir['path'] );
253 }
254
255 if ( ! LP_WP_Filesystem::instance()->is_writable( $upload_dir['path'] ) ) {
256 throw new Exception( __( 'The upload directory is not writable', 'learnpress' ) );
257 }
258
259 $path_img = get_user_meta( $user_id, UserModel::META_KEY_IMAGE, true );
260
261 if ( $path_img ) {
262 if ( 0 === strpos( $path_img, '/' ) ) {
263 $path = $upload_dir['basedir'] . $path_img;
264 } else {
265 $path = trailingslashit( $upload_dir['path'] ) . basename( $path_img );
266 }
267
268 if ( file_exists( $path ) ) {
269 LP_WP_Filesystem::instance()->unlink( $path );
270 }
271
272 delete_user_meta( $user_id, UserModel::META_KEY_IMAGE );
273
274 $response->status = Response::STATUS_SUCCESS;
275 $response->message = esc_html__( 'The profile picture has been removed successfully', 'learnpress' );
276 }
277 } catch ( Throwable $th ) {
278 $response->message = $th->getMessage();
279 }
280
281 return rest_ensure_response( $response );
282 }
283
284 /**
285 * Statistics of a student.
286 *
287 * @param WP_REST_Request $request
288 *
289 * @return WP_Error|WP_HTTP_Response|WP_REST_Response
290 */
291 public function student_statistics( WP_REST_Request $request ) {
292 $user_id = (int) $request->get_param( 'userID' );
293 $response = new LP_REST_Response();
294 $response->data = '';
295
296 try {
297 if ( empty( $user_id ) ) {
298 throw new Exception( esc_html__( 'No user ID found!', 'learnpress' ) );
299 }
300
301 $userModel = UserModel::find( $user_id, true );
302 if ( ! $userModel ) {
303 throw new Exception( esc_html__( 'The user does not exist!', 'learnpress' ) );
304 }
305
306 // Check permission
307 $profile = LP_Profile::instance( $user_id );
308 if ( ! $profile->current_user_can( 'view-tab-my-courses' ) ) {
309 throw new Exception( esc_html__( 'You do not have permission to view this statistic!', 'learnpress' ) );
310 }
311
312 $statistic = $userModel->get_student_statistic();
313 $data = apply_filters(
314 'learn-press/profile/student-statistics/info',
315 [
316 'enrolled_courses' => [
317 'title' => __( 'Total enrolled courses', 'learnpress' ),
318 'label' => __( 'Enrolled Course', 'learnpress' ),
319 'count' => $statistic['enrolled_courses'] ?? 0,
320 ],
321 'in_progress_course' => [
322 'title' => __( 'Total course is in progress', 'learnpress' ),
323 'label' => __( 'Inprogress Course', 'learnpress' ),
324 'count' => $statistic['in_progress_course'] ?? 0,
325 ],
326 'finished_courses' => [
327 'title' => __( 'Total courses finished', 'learnpress' ),
328 'label' => __( 'Finished Course', 'learnpress' ),
329 'count' => $statistic['finished_courses'] ?? 0,
330 ],
331 'passed_courses' => [
332 'title' => __( 'Total courses passed', 'learnpress' ),
333 'label' => __( 'Passed Course', 'learnpress' ),
334 'count' => $statistic['passed_courses'] ?? 0,
335 ],
336 'failed_courses' => [
337 'title' => __( 'Total courses failed', 'learnpress' ),
338 'label' => __( 'Failed Course', 'learnpress' ),
339 'count' => $statistic['failed_courses'] ?? 0,
340 ],
341 ]
342 );
343
344 ob_start();
345 Template::instance()->get_frontend_template(
346 'profile/tabs/statistics/student-statistics.php',
347 compact( 'data' )
348 );
349 $response->data = ob_get_clean();
350 $response->status = 'success';
351 } catch ( Exception $e ) {
352 ob_end_clean();
353 $response->message = $e->getMessage();
354 }
355
356 return rest_ensure_response( $response );
357 }
358
359 /**
360 * Statistics of an instructor.
361 *
362 * @param WP_REST_Request $request
363 *
364 * @return WP_Error|WP_HTTP_Response|WP_REST_Response
365 */
366 public function instructor_statistics( WP_REST_Request $request ) {
367 $user_id = $request->get_param( 'userID' );
368 $response = new LP_REST_Response();
369 $response->data = '';
370
371 try {
372 if ( empty( $user_id ) ) {
373 throw new Exception( esc_html__( 'No user ID found!', 'learnpress' ) );
374 }
375
376 $userModel = UserModel::find( $user_id, true );
377 if ( ! $userModel ) {
378 throw new Exception( esc_html__( 'The user does not exist!', 'learnpress' ) );
379 }
380
381 $profile = LP_Profile::instance( $user_id );
382 if ( $profile instanceof WP_Error ) {
383 throw new Exception( $profile->get_error_message() );
384 }
385
386 // Check permission
387 if ( ! $profile->current_user_can( 'view-tab-courses' ) ) {
388 throw new Exception( esc_html__( 'You do not have permission to view this statistic!', 'learnpress' ) );
389 }
390
391 $statistic = $userModel->get_instructor_statistic();
392
393 $data = apply_filters(
394 'learn-press/profile/instructor-statistics/info',
395 [
396 'total_course' => [
397 'title' => __( 'Total Course', 'learnpress' ),
398 'label' => __( 'Total Course', 'learnpress' ),
399 'count' => $statistic['total_course'] ?? 0,
400 ],
401 'published_course' => [
402 'title' => __( 'Published Course', 'learnpress' ),
403 'label' => __( 'Published Course', 'learnpress' ),
404 'count' => $statistic['published_course'] ?? 0,
405 ],
406 'pending_course' => [
407 'title' => __( 'Pending Course', 'learnpress' ),
408 'label' => __( 'Pending Course', 'learnpress' ),
409 'count' => $statistic['pending_course'] ?? 0,
410 ],
411 'total_student' => [
412 'title' => __( 'Total Student', 'learnpress' ),
413 'label' => __( 'Total Student', 'learnpress' ),
414 'count' => $statistic['total_student'] ?? 0,
415 ],
416 'student_completed' => [
417 'title' => __( 'Student Completed', 'learnpress' ),
418 'label' => __( 'Student Completed', 'learnpress' ),
419 'count' => $statistic['student_completed'] ?? 0,
420 ],
421 'student_in_progress' => [
422 'title' => __( 'Student In-progress', 'learnpress' ),
423 'label' => __( 'Student In-progress', 'learnpress' ),
424 'count' => $statistic['student_in_progress'] ?? 0,
425 ],
426 ]
427 );
428
429 ob_start();
430 Template::instance()->get_frontend_template(
431 'profile/tabs/statistics/instructor-statistics.php',
432 compact( 'data' )
433 );
434 $response->data = ob_get_clean();
435 $response->status = 'success';
436 } catch ( Exception $e ) {
437 ob_end_clean();
438 $response->message = $e->getMessage();
439 }
440
441 return rest_ensure_response( $response );
442 }
443
444 public function course_tab( $request ) {
445 $params = $request->get_params();
446 $user_id = $params['userID'] ?? get_current_user_id();
447 $status = $params['status'] ?? '';
448 $paged = $params['paged'] ?? 1;
449 $query_type = $params['query'] ?? '';
450 $layout = $params['layout'] ?? 'grid';
451 $response = new LP_REST_Response();
452
453 try {
454 if ( empty( $user_id ) ) {
455 throw new Exception( esc_html__( 'No user ID found!', 'learnpress' ) );
456 }
457
458 $profile = LP_Profile::instance( $user_id );
459 if ( 'purchased' === $query_type ) {
460 if ( ! $profile->current_user_can( 'view-tab-my-courses' ) ) {
461 throw new Exception( esc_html__( 'You do not have permission to view this tab!', 'learnpress' ) );
462 }
463 } elseif ( 'own' === $query_type ) {
464 if ( ! $profile->current_user_can( 'view-tab-courses' ) ) {
465 throw new Exception( esc_html__( 'You do not have permission to view this tab!', 'learnpress' ) );
466 }
467 } else {
468 throw new Exception( esc_html__( 'Request invalid!', 'learnpress' ) );
469 }
470
471 $query = $profile->query_courses(
472 $query_type,
473 apply_filters(
474 'learnpress/rest/frontend/profile/course_tab/query',
475 array(
476 'status' => $status,
477 'limit' => LP_Settings::get_option( 'archive_course_limit', 6 ),
478 'paged' => $paged,
479 ),
480 $request
481 )
482 );
483
484 // LP_User_Item_Course.
485 $course_item_objects = ! empty( $query->get_items() ) ? $query->get_items() : false;
486
487 if ( empty( $course_item_objects ) ) {
488 throw new Exception( esc_html__( 'No Course available!', 'learnpress' ) );
489 }
490
491 $course_ids = array_map(
492 function ( $course_object ) {
493 return ! is_object( $course_object ) ? absint( $course_object ) : $course_object->get_id();
494 },
495 $course_item_objects
496 );
497
498 if ( empty( $course_ids ) ) {
499 throw new Exception( esc_html__( 'No Course IDs available!', 'learnpress' ) );
500 }
501
502 $user = learn_press_get_user( $user_id );
503
504 if ( empty( $user ) ) {
505 throw new Exception( esc_html__( 'No User available!', 'learnpress' ) );
506 }
507
508 do_action( 'learnpress/rest/frontend/profile/course_tab', $params );
509
510 $num_pages = $query->get_pages();
511 $current_page = $query->get_paged();
512
513 $template = $layout === 'grid' ? 'profile/tabs/courses/course-grid' : 'profile/tabs/courses/course-list';
514
515 $response->data = learn_press_get_template_content(
516 $template,
517 array(
518 'user' => $user,
519 'course_ids' => $course_ids,
520 'num_pages' => max( absint( $num_pages ), 1 ),
521 'current_page' => absint( $current_page ),
522 )
523 );
524 $response->status = 'success';
525
526 } catch ( Exception $e ) {
527 $response->message = $e->getMessage();
528 }
529
530 return $response;
531 }
532
533 /**
534 * Get course's user attend
535 *
536 * @param WP_REST_Request $request
537 *
538 * @return LP_REST_Response
539 * @since 4.1.5
540 * @version 1.0.0
541 * @author tungnx
542 */
543 /*public function course_attend( WP_REST_Request $request ): LP_REST_Response {
544 $params = $request->get_params();
545 $user_id = get_current_user_id();
546 $status = $params['status'] ?? '';
547 $paged = $params['paged'] ?? 1;
548 $layout = $params['layout'] ?? 'grid';
549 $response = new LP_REST_Response();
550
551 try {
552 if ( ! $user_id ) {
553 throw new Exception( __( 'The user is invalid', 'learnpress' ) );
554 }
555
556 $filter = new LP_User_Items_Filter();
557 $filter->limit = LP_Settings::get_option( 'archive_course_limit', 6 );
558 $filter->user_id = $user_id;
559 $total_rows = 0;
560 $courses = LP_User_Item_Course::get_user_courses( $filter, $total_rows );
561 $response->data->courses = $courses;
562 $response->data->total_pages = LP_Database::get_total_pages( $filter->limit, $total_rows );
563 } catch ( Throwable $e ) {
564 $response->message = $e->getMessage();
565 }
566
567 return $response;
568 }*/
569
570 /**
571 * API upload cover image profile.
572 *
573 * @param WP_REST_Request $request
574 *
575 * @return LP_REST_Response
576 * @since 4.2.7.2
577 * @version 1.0.0
578 */
579 public function handle_cover_image( WP_REST_Request $request ): LP_REST_Response {
580 $files = $request->get_file_params();
581 $action = $request->get_param( 'action' );
582 $response = new LP_REST_Response();
583 $upload_dir = learn_press_user_profile_picture_upload_dir();
584
585 try {
586 $user_id = get_current_user_id();
587 if ( ! $user_id ) {
588 throw new Exception( __( 'User is invalid!', 'learnpress' ) );
589 }
590
591 $user = UserModel::find( $user_id, true );
592 if ( ! $user ) {
593 throw new Exception( __( 'User is invalid!', 'learnpress' ) );
594 }
595
596 if ( $action === 'remove' ) {
597 $user->delete_cover_image();
598
599 $response->status = 'success';
600 $response->message = __( 'Cover image has been removed successfully', 'learnpress' );
601 $response->data->action = $action;
602
603 return $response;
604 }
605
606 if ( empty( $files ) || empty( $files['image'] ) ) {
607 throw new Exception( __( 'File is invalid!', 'learnpress' ) );
608 }
609
610 $cover_image_file = $files['image'];
611 $cover_image_name = $cover_image_file['name'];
612 $check_type = wp_check_filetype( $cover_image_name );
613
614 // Only allow image type
615 $image_types_allow = [ 'image/jpeg', 'image/png', 'image/webp' ];
616 if ( ! $check_type['type'] || ! in_array( $check_type['type'], $image_types_allow ) ) {
617 throw new Exception( __( 'File type is not allowed', 'learnpress' ) );
618 }
619
620 $cover_dir_path = $upload_dir['path'] . '/' . 'cover-image/';
621 $target_dir = LP_WP_Filesystem::instance()->is_dir( $cover_dir_path );
622 if ( ! $target_dir ) {
623 wp_mkdir_p( $cover_dir_path );
624 }
625
626 if ( ! LP_WP_Filesystem::instance()->is_writable( $cover_dir_path ) ) {
627 throw new Exception( __( 'The upload directory is not writable', 'learnpress' ) );
628 }
629
630 // Delete old image if exists
631 $user->delete_cover_image();
632
633 $file_name = md5( $user_id . microtime( true ) ) . '.' . $check_type['ext'];
634 $file_img_cer_blob = LP_WP_Filesystem::instance()->file_get_contents( $cover_image_file['tmp_name'] );
635 $put_content = LP_WP_Filesystem::instance()->put_contents(
636 $cover_dir_path . '/' . $file_name,
637 $file_img_cer_blob
638 );
639 if ( ! $put_content ) {
640 throw new Exception( __( 'Cannot write the file', 'learnpress' ) );
641 }
642
643 $upload_subdir = $upload_dir['subdir'] . '/' . 'cover-image/';
644 $path_save = $upload_subdir . $file_name;
645 $user->set_cover_image_url( $path_save );
646
647 do_action( 'learnpress/rest/frontend/profile/upload_cover_image', $user_id );
648
649 $response->status = 'success';
650 $response->message = __( 'Cover image is updated', 'learnpress' );
651 $response->data->url = $user->get_cover_image_url();
652 $response->data->action = $action;
653 } catch ( Throwable $th ) {
654 $response->message = $th->getMessage();
655 }
656
657 return $response;
658 }
659 }
660