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