PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.4
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.4
4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 4.2.1 All 138 releases
learnpress / inc / custom-post-types / order.php

order.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.4.4, at inc/custom-post-types/order.php

889 lines 24.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @class LP_Order_Post_Type
4 *
5 * @author ThimPress
6 * @package LearnPress/Classes
7 * @version 1.0.2
8 */
9
10 use LearnPress\Ajax\Order\ExportOrderCSVAjax;
11 use LearnPress\Databases\DataBase;
12 use LearnPress\Databases\PostDB;
13 use LearnPress\Filters\OrderPostFilter;
14 use LearnPress\Helpers\LPDateTime;
15 use LearnPress\Models\OrderPostModel;
16 use LearnPress\Models\UserItems\UserCourseModel;
17 use LearnPress\Models\UserItems\UserItemModel;
18
19 if ( ! class_exists( 'LP_Order_Post_Type' ) ) {
20 final class LP_Order_Post_Type extends LP_Abstract_Post_Type {
21 /**
22 * Type of post
23 *
24 * @var string
25 */
26 protected $_post_type = LP_ORDER_CPT;
27 /**
28 * @var null
29 */
30 protected static $_instance = null;
31
32 /**
33 * LP_Order_Post_Type constructor.
34 */
35 public function __construct() {
36 add_action( 'admin_init', array( $this, 'register_post_statues' ) );
37 // add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ) );
38 add_action( 'posts_pre_query', array( $this, 'posts_pre_query' ), 999, 2 );
39 // add_action( 'admin_init', array( $this, 'remove_box' ) );
40 // add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
41 add_filter( 'wp_untrash_post_status', array( $this, 'restore_status_order' ), 11, 3 );
42 add_filter( 'admin_footer', array( $this, 'admin_footer' ) );
43 // add_filter( 'views_edit-lp_order', array( $this, 'filter_views' ) );
44 // Download order CSV file
45 $this->download_order_csv_file();
46
47 // Override title of LP Order on Admin
48 if ( is_admin() ) {
49 $can_override_title_order = false;
50 $current_url = LP_Helper::getUrlCurrent();
51 $post_id = LP_Helper::sanitize_params_submitted( $_GET['post'] ?? '' );
52 if ( ! empty( $post_id ) ) {
53 $post = get_post( $post_id );
54 if ( $post && $post->post_type == LP_ORDER_CPT ) {
55 $can_override_title_order = true;
56 }
57 } elseif ( strpos( $current_url, 'post_type=lp_order' ) !== false ) {
58 $can_override_title_order = true;
59 }
60
61 if ( $can_override_title_order ) {
62 add_filter( 'the_title', array( $this, 'order_title' ), 5, 2 );
63 }
64 }
65
66 parent::__construct();
67 }
68
69 /**
70 * Unset value in 'mine' key in views of LP Orders.
71 * The 'mine' is present in some case when 'user_posts_count'
72 * is not the same with total posts then wp add it to the views
73 * of WP Posts List table.
74 *
75 * @param array $views
76 *
77 * @return mixed
78 */
79 public function filter_views( $views ) {
80 if ( isset( $views['mine'] ) ) {
81 unset( $views['mine'] );
82 }
83
84 return $views;
85 }
86
87 /**
88 * Filter to hide orders are created by one order for multiple users.
89 *
90 * @param string $where
91 *
92 * @return string
93 */
94 public function filter_orders( string $where ): string {
95 if ( ! $this->is_page_list_posts_on_backend() ) {
96 return $where;
97 }
98
99 global $wpdb;
100
101 if ( isset( $_REQUEST['parent'] ) ) {
102 $where .= sprintf( ' AND post_parent = %d ', absint( $_REQUEST['parent'] ) );
103 } else {
104 // $where .= $wpdb->prepare( " AND (post_parent = 0 OR {$wpdb->posts}.ID IN( SELECT post_parent FROM {$wpdb->posts} X WHERE X.post_parent <> 0 AND X.post_type = %s) )", LP_ORDER_CPT );
105 $where .= ' AND post_parent = 0 ';
106 }
107
108 return $where;
109 }
110
111 public function enqueue_scripts() {
112 if ( get_post_type() != $this->_post_type ) {
113 return;
114 }
115 wp_enqueue_script( 'user-suggest' );
116 }
117
118 /**
119 * Restore user course item when the order is stored (usually from trash).
120 *
121 * @param string $new_status
122 * @param int $post_id
123 * @param string $previous_status
124 *
125 * @return string
126 */
127 public function restore_status_order( string $new_status, int $post_id, string $previous_status ): string {
128 if ( LP_ORDER_CPT != get_post_type( $post_id ) ) {
129 return $new_status;
130 }
131
132 return $previous_status;
133 }
134
135 /**
136 * Save order post.
137 *
138 * @param int $post_id
139 * @param WP_Post $post
140 * @param bool $is_update
141 *
142 * @editor tungnx
143 * @version 1.0.6
144 */
145 public function save_post( int $post_id, ?WP_Post $post = null, bool $is_update = false ) {
146 try {
147 $backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS );
148 if ( isset( $backtrace[6]['class'] ) && $backtrace[6]['class'] === LP_Order_CURD::class ) {
149 return;
150 }
151
152 if ( wp_is_post_revision( $post_id ) ) {
153 return;
154 }
155
156 // For create LP Order manual on Backend
157 $order = learn_press_get_order( $post_id );
158 if ( ! $order ) {
159 return;
160 }
161
162 $created_via = $order->get_created_via();
163 if ( empty( $created_via ) ) {
164 $created_via = LP_ORDER_CREATED_VIA_MANUAL;
165 $order->set_created_via( $created_via );
166 }
167
168 if ( isset( $_POST['order-customer'] ) && $order->is_manual() ) {
169 $user_id = LP_Request::get_param( 'order-customer' );
170 $order->set_user_id( $user_id );
171 }
172
173 $status = LP_Request::get_param( 'order-status' );
174 if ( ! empty( $status ) ) {
175 $order->update_status( $status );
176 } elseif ( $post->post_status === 'auto-draft' ) {
177 $order->update_status( 'pending' );
178 }
179
180 $order->save();
181 } catch ( Throwable $e ) {
182 error_log( __METHOD__ . ':' . $e->getMessage() );
183 }
184 }
185
186 /**
187 * Remove unused boxes
188 */
189 public function remove_box() {
190 remove_post_type_support( LP_ORDER_CPT, 'title' );
191 remove_post_type_support( LP_ORDER_CPT, 'editor' );
192 }
193
194 public function admin_footer() {
195 if ( ! $this->is_page_list_posts_on_backend() ) {
196 return;
197 }
198 ?>
199 <script type="text/javascript">
200 jQuery(function ($) {
201 $('#post-search-input').prop('placeholder',
202 '<?php esc_attr_e( 'Order number, course name, etc.', 'learnpress' ); ?>').css('width', 300)
203 })
204 </script>
205 <?php
206 }
207
208 /**
209 * Hook to filter LP orders by some conditions.
210 *
211 * @param string $where
212 *
213 * @return string
214 * @throws Exception
215 */
216 /*
217 public function posts_where_paged( $where ) {
218 // Code temporary, when release about 1 week, will remove it.
219 $lp_filter_post = new LP_Post_Type_Filter();
220 $lp_filter_post->post_type = LP_ORDER_CPT;
221 $lp_filter_post->post_status = [ 'lp-trash' ];
222 $orders_trash = LP_Post_DB::getInstance()->get_posts( $lp_filter_post );
223 if ( $orders_trash ) {
224 foreach ( $orders_trash as $order_trash ) {
225 $order = learn_press_get_order( $order_trash->ID );
226 if ( $order ) {
227 $order->update_status( 'trash' );
228 }
229 }
230 }
231 // Change status course from lp_trash to trash.
232
233 // End code temporary
234 global $wpdb, $wp_query;
235 $lp_db = LP_Database::getInstance();
236 if ( is_admin() && $this->is_page_list_posts_on_backend() ) {
237 $where = ' ';
238 $where .= $wpdb->prepare( " AND {$lp_db->tb_posts}.post_type = %s", LP_ORDER_CPT );
239 }
240
241 // Search by keyword
242 if ( ! empty( $wp_query->get( 's' ) ) ) {
243 $s = $wp_query->get( 's' );
244
245 // Check search LP Order ID with format #000[ID] or 000[ID]
246 $pattern = '/^#\d+$/';
247 if ( preg_match( $pattern, $s ) ) {
248 $s = str_replace( '#', '', $s );
249 }
250
251 $pattern2 = '#^0+.*\d+$#';
252 if ( preg_match( $pattern2, $s ) ) {
253 $s = (int) $s;
254 }
255
256 $s = trim( $s );
257
258 $where .= $wpdb->prepare( " AND {$lp_db->tb_posts}.ID = %d", $s );
259 $where .= $wpdb->prepare( ' OR lpori.order_item_name like %s', '%' . $wpdb->esc_like( $s ) . '%' );
260 }
261
262 // Search by author id
263 if ( ! empty( $wp_query->get( 'author' ) ) ) {
264 $user_id = absint( $wp_query->get( 'author' ) );
265 //$where .= $wpdb->prepare( ' AND uu.ID like %s ', $user_id );
266 $where .= " AND ( pm1.meta_value like '%\"$user_id\"%' OR pm1.meta_value = $user_id ) ";
267 }
268
269 if ( ! empty( $wp_query->get( 'm' ) ) ) {
270 $month = $wp_query->get( 'm' );
271 $where .= " AND YEAR({$lp_db->tb_posts}.post_date)=" . substr( $month, 0, 4 );
272 if ( strlen( $month ) > 5 ) {
273 $where .= " AND MONTH({$lp_db->tb_posts}.post_date)=" . substr( $month, 4, 2 );
274 }
275 }
276
277 // Filter by order status
278 if ( ! empty( $wp_query->get( 'post_status' ) ) ) {
279 $status = $wp_query->get( 'post_status' );
280 $where .= $wpdb->prepare( " AND {$lp_db->tb_posts}.post_status = %s", $status );
281 } else {
282 $where .= $wpdb->prepare( " AND {$lp_db->tb_posts}.post_status NOT IN (%s, %s, %s)", LP_ORDER_TRASH_DB, LP_ORDER_TRASH, 'auto-draft' );
283 }
284
285 return $where;
286 }*/
287
288 // public function posts_orderby( $orderby ) {
289 // global $wpdb;
290 //
291 // $order = $this->get_order_sort();
292 //
293 // switch ( $this->get_order_by() ) {
294 // case 'title':
295 // $orderby = "{$wpdb->posts}.ID {$order}";
296 // break;
297 // *case 'student':
298 // $orderby = "uu.user_login {$order}";
299 // break;*/
300 // case 'date':
301 // $orderby = "{$wpdb->posts}.post_date {$order}";
302 // break;
303 // case 'order_total':
304 // $orderby = "CAST(pm2.meta_value AS UNSIGNED) {$order}";
305 // break;
306 // }
307 //
308 // return $orderby;
309 // }
310
311 /*
312 public function posts_join_paged( $join ) {
313 global $wpdb, $wp_query;
314 $lp_db = LP_Database::getInstance();
315
316 // Search by keyword
317 if ( ! empty( $wp_query->get( 's' ) ) ) {
318 $join .= " INNER JOIN {$lp_db->tb_lp_order_items} lpori ON {$wpdb->posts}.ID = lpori.order_id";
319 }
320
321 if ( ! empty( $wp_query->get( 'author' ) ) ) {
322 $author_id = $wp_query->get( 'author' );
323 $join .= " INNER JOIN {$lp_db->tb_postmeta} pm1 ON {$wpdb->posts}.ID = pm1.post_id AND pm1.meta_key = '_user_id'";
324 $join .= " LEFT JOIN {$lp_db->tb_users} uu ON uu.ID = $author_id";
325 }
326
327 if ( $this->get_order_by() === 'order_total' ) {
328 $join .= " INNER JOIN {$lp_db->tb_postmeta} pm2 ON {$wpdb->posts}.ID = pm2.post_id AND pm2.meta_key = '_order_total'";
329 }
330
331 return $join;
332 }*/
333
334 /**
335 * Make our custom columns can be sortable
336 *
337 * @param $columns
338 *
339 * @return mixed
340 */
341 public function sortable_columns( $columns ) {
342 $columns['order_date'] = 'date';
343 $columns['order_total'] = 'order_total';
344
345 return $columns;
346 }
347
348 public function update_status() {
349 $order_id = ! empty( $_REQUEST['order_id'] ) ? absint( $_REQUEST['order_id'] ) : 0;
350 $status = ! empty( $_REQUEST['status'] ) ? LP_Helper::sanitize_params_submitted( $_REQUEST['status'] ) : 'Pending';
351
352 learn_press_update_order_status( $order_id, $status );
353
354 wp_send_json(
355 array(
356 'status' => $status,
357 'class' => sanitize_title( $status ),
358 )
359 );
360 }
361
362 /**
363 * Custom row's actions.
364 *
365 * @param array $actions
366 * @param WP_Post $post
367 *
368 * @return mixed
369 * @since 2.1.7
370 * @deprecated 4.2.6.4
371 */
372 /*
373 public function row_actions( $actions, $post ) {
374 if ( ! empty( $actions['inline hide-if-no-js'] ) ) {
375 unset( $actions['inline hide-if-no-js'] );
376 }
377 if ( ! empty( $actions['edit'] ) ) {
378 $actions['edit'] = preg_replace( '/>(.*?)<\/a>/', '>' . __( 'View Order', 'learnpress' ) . '</a>', $actions['edit'] );
379 }
380
381 return $actions;
382 }*/
383
384 /**
385 * re-order the orders by newest
386 *
387 * @param WP_Query $wp_query
388 *
389 * @editor tungnx
390 * @reason comment this function - because default sort by id
391 *
392 * @return mixed
393 */
394 public function pre_get_posts( $wp_query ) {
395 if ( ! is_admin() ) {
396 return $wp_query;
397 }
398
399 $post_type = $wp_query->get( 'post_type' );
400
401 if ( empty( $post_type ) || $post_type != LP_ORDER_CPT ) {
402 return $wp_query;
403 }
404
405 if ( is_admin() ) {
406 $wp_query->set( 'orderby', 'date' );
407 $wp_query->set( 'order', 'desc' );
408 }
409
410 $post_status = $wp_query->get( 'post_status' );
411 if ( empty( $post_status ) || $post_status == 'all' ) {
412 $wp_query->set(
413 'post_status',
414 array(
415 LP_ORDER_COMPLETED_DB,
416 LP_ORDER_PROCESSING_DB,
417 LP_ORDER_PENDING_DB,
418 LP_ORDER_FAILED_DB,
419 LP_ORDER_CANCELLED_DB,
420 LP_ORDER_REFUNDED_DB,
421 )
422 );
423 }
424
425 // Search by author id
426 /*
427 if ( ! empty( $wp_query->get( 'author' ) ) ) {
428 $user_id = absint( $wp_query->get( 'author' ) );
429 //$where .= $wpdb->prepare( ' AND uu.ID like %s ', $user_id );
430 $where .= " AND ( pm1.meta_value like '%\"$user_id\"%' OR pm1.meta_value = $user_id ) ";
431 }*/
432
433 $post_author = $wp_query->get( 'author' );
434 if ( ! empty( $post_author ) ) {
435 $user_id = absint( $post_author );
436 $meta_query = array(
437 // 'relation' => 'OR',
438 array(
439 'key' => '_user_id',
440 'value' => '%"' . $user_id . '"%',
441 'compare' => 'LIKE',
442 ),
443 // array(
444 // 'key' => '_user_id',
445 // 'value' => $user_id,
446 // 'compare' => '=',
447 // ),
448 );
449 $wp_query->set( 'meta_query', $meta_query );
450 }
451
452 return $wp_query;
453 }
454
455 /**
456 * Query lp orders in admin via Post DB
457 *
458 * @param array $posts
459 * @param WP_Query $wp_query
460 *
461 * @return array|WP_Query
462 */
463 public function posts_pre_query( $posts, $wp_query ) {
464 try {
465 if ( ! is_admin() ) {
466 return $posts;
467 }
468
469 $post_type = $wp_query->get( 'post_type' );
470
471 if ( empty( $post_type ) || $post_type != LP_ORDER_CPT ) {
472 return $posts;
473 }
474
475 // Convert params from WP_Query to PostFilter
476 $posts_per_page = get_user_option( "edit_{$post_type}_per_page", get_current_user_id() );
477 if ( empty( $posts_per_page ) ) {
478 $posts_per_page = 20;
479 }
480
481 $paged = max( 1, get_query_var( 'paged' ) );
482 $user_of_order = $wp_query->get( 'author' );
483 $status = $wp_query->get( 'post_status' );
484 $key = $wp_query->get( 's' );
485 $month = $wp_query->get( 'm' );
486 $refund_request_status = LP_Request::get_param( 'refund_request_status', '', 'key', 'get' );
487
488 $filter = new OrderPostFilter();
489 $param = array(
490 'paged' => $paged,
491 'posts_per_page' => $posts_per_page,
492 'author' => $user_of_order,
493 'post_status' => $status,
494 's' => $key,
495 'm' => $month,
496 'refund_request_status' => $refund_request_status,
497 );
498 LP_Order::handle_params_query_list_orders( $filter, $param );
499
500 // Get lp orders
501 $post_db = PostDB::getInstance();
502 $total_rows = 0;
503 $lp_orders = $post_db->get_posts( $filter, $total_rows );
504
505 $wp_query->post_count = $total_rows;
506 $wp_query->found_posts = $total_rows;
507 $posts = $lp_orders;
508 } catch ( Throwable $e ) {
509 LP_Debug::error_log( $e );
510 }
511
512 return $posts;
513 }
514
515 /**
516 *
517 */
518 public function columns_head( $existing ) {
519
520 // Remove Checkbox - adding it back below
521 if ( isset( $existing['cb'] ) ) {
522 $check = $existing['cb'];
523 unset( $existing['cb'] );
524 }
525
526 // Remove Title - adding it back below
527 if ( isset( $existing['title'] ) ) {
528 unset( $existing['title'] );
529 }
530
531 // Remove Format
532 if ( isset( $existing['format'] ) ) {
533 unset( $existing['format'] );
534 }
535
536 // Remove Author
537 if ( isset( $existing['author'] ) ) {
538 unset( $existing['author'] );
539 }
540
541 // Remove Comments
542 if ( isset( $existing['comments'] ) ) {
543 unset( $existing['comments'] );
544 }
545
546 // Remove Date
547 if ( isset( $existing['date'] ) ) {
548 unset( $existing['date'] );
549 }
550
551 // Remove Builder
552 if ( isset( $existing['builder_layout'] ) ) {
553 unset( $existing['builder_layout'] );
554 }
555
556 $columns['cb'] = '<input type="checkbox" />';
557 $columns['title'] = esc_html__( 'Order', 'learnpress' );
558 $columns['order_student'] = esc_html__( 'Student', 'learnpress' );
559 $columns['order_items'] = esc_html__( 'Purchased', 'learnpress' );
560 $columns['order_date'] = esc_html__( 'Date', 'learnpress' );
561 $columns['order_total'] = esc_html__( 'Total', 'learnpress' );
562 $columns['order_status'] = '<span class="status_head tips" data-tip="' . esc_attr__( 'Status', 'learnpress' ) . '">' . esc_attr__( 'Status', 'learnpress' ) . '</span>';
563
564 $columns = array_merge( $columns, $existing );
565
566 return $columns;
567 }
568
569 public function order_title( $title, $post_id ) {
570 if ( get_post_type( $post_id ) != LP_ORDER_CPT ) {
571 return $title;
572 }
573
574 return learn_press_transaction_order_number( $post_id );
575 }
576
577 /**
578 * Render column data
579 *
580 * @since 3.0.0
581 * @version 1.0.1
582 */
583 public function columns_content( $column, $post_id = 0 ) {
584 global $post;
585 $lp_order = learn_press_get_order( $post->ID );
586 $orderPostModel = OrderPostModel::find_by_id( $post->ID, true );
587
588 switch ( $column ) {
589 case 'order_student':
590 $user_ids = $lp_order->get_users();
591 if ( $user_ids ) {
592 $outputs = array();
593 foreach ( $user_ids as $user_id ) {
594 if ( get_user_by( 'id', $user_id ) ) {
595 $user = learn_press_get_user( $user_id );
596 $outputs[] = sprintf(
597 '<a href="user-edit.php?user_id=%d">%s (%s)</a><span>%s</span>',
598 $user_id,
599 $user->get_data( 'user_login' ),
600 $user->get_data( 'display_name' ),
601 $user->get_data( 'user_email' )
602 );
603 } elseif ( sizeof( $user_ids ) == 1 ) {
604 $outputs[] = $lp_order->get_customer_name();
605 }
606 }
607 echo join( ', ', $outputs );
608 } else {
609 echo esc_html__( '(Guest)', 'learnpress' );
610 }
611 break;
612 case 'order_status':
613 $lp_order_icons = LP_Order::get_icons_status();
614 $icon = $lp_order_icons[ $lp_order->get_status() ] ?? '';
615 $badge_html = '';
616
617 $refund_request_status = $lp_order->get_refund_request();
618 if ( 'pending' === $refund_request_status ) {
619 $badge_html = sprintf(
620 '<span class="lp-order-refund-request-badge">%s</span>',
621 esc_html__( 'Refund Requested', 'learnpress' )
622 );
623 }
624 printf(
625 '<span class="lp-order-status %1$s">%2$s%3$s</span>%4$s',
626 $lp_order->get_status(),
627 $icon,
628 LP_Order::get_status_label( $lp_order->get_status() ),
629 $badge_html
630 );
631 break;
632 case 'order_date':
633 // Check column post_date_gmt is default value
634 if ( $orderPostModel->post_date_gmt === '0000-00-00 00:00:00' ) {
635 $convert_post_date_gmt = get_gmt_from_date( $orderPostModel->post_date );
636 $orderPostModel->post_date_gmt = $convert_post_date_gmt;
637 }
638
639 $time = strtotime( $orderPostModel->post_date_gmt );
640 $time_diff = time() - $time;
641
642 $lpDateTimeGMT = new LPDateTime( $orderPostModel->post_date_gmt );
643 $time_local_format_mysql = $lpDateTimeGMT->format( LPDateTime::FORMAT_MYSQL, 'gmt_to_local' );
644
645 if ( $time_diff > 0 && $time_diff < DAY_IN_SECONDS ) {
646 $time_display = $lpDateTimeGMT->format(
647 LPDateTime::FORMAT_HUMAN,
648 'gmt_to_local',
649 true
650 );
651 } else {
652 $time_display = $lpDateTimeGMT->format(
653 LPDateTime::FORMAT_I18N_DATE_TIME,
654 'gmt_to_local',
655 true
656 );
657 }
658
659 echo sprintf(
660 '<abbr title="%s">%s</abbr>',
661 esc_attr( $time_local_format_mysql ),
662 esc_html( $time_display )
663 );
664 break;
665 case 'order_items':
666 do_action( 'learn-press/admin/order-items/layout', $lp_order );
667 break;
668 case 'order_total':
669 echo wp_kses_post( $lp_order->get_formatted_order_total() );
670 $method_title = $lp_order->get_payment_method_title();
671 $method_title = apply_filters( 'learn-press/order-payment-method-title', $method_title, $lp_order );
672
673 if ( ! empty( $method_title ) ) {
674 $method_title_html = sprintf(
675 __( 'Pay via <strong>%s</strong>', 'learnpress' ),
676 $method_title
677 );
678 ?>
679 <div class="payment-method-title">
680 <?php echo wp_kses_post( $method_title_html ); ?>
681 </div>
682 <?php
683 }
684 break;
685 }
686 }
687
688 /**
689 * Register order post type
690 */
691 public function args_register_post_type(): array {
692 return array(
693 'labels' => array(
694 'name' => __( 'Orders', 'learnpress' ),
695 'menu_name' => __( 'Orders', 'learnpress' ),
696 'singular_name' => __( 'Order', 'learnpress' ),
697 'add_new_item' => __( 'Add A New Order', 'learnpress' ),
698 'edit_item' => __( 'Order Details', 'learnpress' ),
699 'all_items' => __( 'Orders', 'learnpress' ),
700 'view_item' => __( 'View Order', 'learnpress' ),
701 'add_new' => __( 'Add New', 'learnpress' ),
702 'update_item' => __( 'Update Order', 'learnpress' ),
703 'search_items' => __( 'Search Orders', 'learnpress' ),
704 'not_found' => __( 'No order found', 'learnpress' ),
705 'not_found_in_trash' => __( 'There was no order found in the trash', 'learnpress' ),
706 ),
707 'public' => false,
708 'show_ui' => true,
709 'show_in_nav_menus' => false,
710 'show_in_admin_bar' => false,
711 'publicly_queryable' => false,
712 'show_in_menu' => 'learn_press',
713 'map_meta_cap' => true,
714 'capability_type' => LP_ORDER_CPT,
715 'hierarchical' => false,
716 'rewrite' => array(
717 'slug' => LP_ORDER_CPT,
718 'hierarchical' => true,
719 'with_front' => true,
720 ),
721 'supports' => array(
722 'title',
723 'custom-fields',
724 ),
725 'exclude_from_search' => true,
726 );
727 }
728
729 /**
730 * Register new post status for order
731 *
732 * @Todo when rewrite API, will remove this function
733 * will be not use learn_press_get_register_order_statuses
734 */
735 public function register_post_statues() {
736 $statuses = learn_press_get_register_order_statuses();
737 foreach ( $statuses as $status => $args ) {
738 register_post_status( $status, $args );
739 }
740 }
741
742 public static function instance() {
743 if ( ! self::$_instance ) {
744 self::$_instance = new self();
745 }
746
747 return self::$_instance;
748 }
749
750 /**
751 * Before post deleted
752 *
753 * @author tungnx
754 * @since 4.1.4
755 * @version 1.0.1
756 */
757 public function before_delete( int $order_id ) {
758 $lp_order_db = LP_Order_DB::getInstance();
759 $lp_user_items_db = LP_User_Items_DB::getInstance();
760
761 try {
762 ini_set( 'max_execution_time', 0 );
763 $order = learn_press_get_order( $order_id );
764 if ( ! $order ) {
765 return;
766 }
767
768 $items = $order->get_all_items();
769 if ( empty( $items ) ) {
770 return;
771 }
772
773 $order_item_ids = array();
774 $user_ids = $order->get_users();
775 foreach ( $user_ids as $user_id ) {
776 // delete_user_meta( $user_id, 'orders' );
777 foreach ( $items as $itemArr ) {
778 $order_item_ids[] = $itemArr['order_item_id'] ?? 0;
779 $item_type = $itemArr['item_type'] ?? '';
780 $userItemModel = UserItemModel::find_user_item(
781 $user_id,
782 $itemArr['item_id'] ?? 0,
783 $item_type ?? '',
784 $order_id,
785 LP_ORDER_CPT
786 );
787
788 if ( $userItemModel ) {
789 if ( $item_type === LP_COURSE_CPT ) {
790 $userCourseModel = new UserCourseModel( $userItemModel );
791 $userCourseModel->delete();
792 } else {
793 $userItemModel->delete();
794 }
795 }
796 }
797
798 do_action( 'learn-press/order/before-delete', $order, $user_id );
799 }
800
801 // Delete lp_order_item, lp_order_itemmeta
802 $filter_delete = new LP_Order_Filter();
803 $filter_delete->order_item_ids = $order_item_ids;
804 $lp_order_db->delete_order_item( $filter_delete );
805 $lp_order_db->delete_order_itemmeta( $filter_delete );
806 // End
807
808 ini_set( 'max_execution_time', LearnPress::$time_limit_default_of_sever );
809 } catch ( Throwable $e ) {
810 error_log( $e->getMessage() . '>' . __FILE__ );
811 }
812 }
813
814 /**
815 * Action delete Order
816 *
817 * @param int $order_id
818 *
819 * @author tungnx
820 * @since 4.1.4
821 * @version 1.0.0
822 */
823 public function deleted_post( int $order_id ) {
824 }
825
826 public function meta_boxes() {
827 return array(
828 'order_details' => array(
829 'title' => esc_html__( 'Order Details', 'learnpress' ),
830 'callback' => function ( $post ) {
831 learn_press_admin_view( 'meta-boxes/order/details.php', array( 'order' => new LP_Order( $post ) ) );
832 },
833 'context' => 'normal',
834 'priority' => 'high',
835 ),
836 'submitdiv' => array(
837 'title' => esc_html__( 'Order Actions', 'learnpress' ),
838 'callback' => function ( $post ) {
839 learn_press_admin_view( 'meta-boxes/order/actions.php', array( 'order' => new LP_Order( $post ) ) );
840 },
841 'context' => 'side',
842 'priority' => 'high',
843 ),
844 'order_exports' => array(
845 'title' => esc_html__( 'Order Exports', 'learnpress' ),
846 'callback' => function ( $post ) {
847 learn_press_admin_view( 'meta-boxes/order/exports-invoice.php', array( 'order' => new LP_Order( $post ) ) );
848 },
849 'context' => 'side',
850 'priority' => 'high',
851 ),
852 );
853 }
854
855 /**
856 * Download order CSV file and delete it after download
857 *
858 * @return void
859 */
860 public function download_order_csv_file() {
861 $export_id = LP_Request::get_param( 'export_id', '', 'key' );
862 if ( ! isset( $_GET['lp_download_order'] ) || empty( $export_id ) ) {
863 return;
864 }
865
866 $file = ExportOrderCSVAjax::get_export_csv_path( $export_id );
867 if ( ! file_exists( $file ) ) {
868 wp_die( __( 'File not found', 'learnpress' ) );
869 } elseif ( ! realpath( $file ) ) {
870 wp_die( __( 'Invalid file path', 'learnpress' ) );
871 }
872
873 $filename = basename( $file );
874
875 header( 'Content-Type: text/csv; charset=UTF-8' );
876 header( 'Content-Disposition: attachment; filename="' . $filename . '"' );
877 header( 'Content-Length: ' . filesize( $file ) );
878
879 readfile( $file );
880 unlink( $file );
881 exit;
882 }
883 }
884
885 // end LP_Order_Post_Type
886
887 $order_post_type = LP_Order_Post_Type::instance();
888 }
889