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.1 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 All 141 releases
← All changes | inc/curds/class-lp-order-curd.php +634 -618 4.3.9 → 4.4.9 View file →
@@ -1,618 +1,634 @@
1 -<?php
2 -/**
3 - * Class LP_Order_CURD
4 - *
5 - * @since 3.0.0
6 - */
7 -
8 -use LearnPress\Models\UserItems\UserCourseModel;
9 -
10 -defined( 'ABSPATH' ) || exit();
11 -
12 -class LP_Order_CURD extends LP_Object_Data_CURD implements LP_Interface_CURD {
13 -
14 - /**
15 - * @var string
16 - */
17 - protected $_meta_type = 'post';
18 -
19 - /**
20 - * @var array
21 - */
22 - protected $_meta_keys = array();
23 -
24 - /**
25 - * @param LP_Order $order
26 - *
27 - * @return mixed
28 - */
29 - public function create( &$order ) {
30 - if ( ! $order instanceof LP_Order ) {
31 - return false;
32 - }
33 -
34 - $order->set_order_date( time() );
35 - $order->set_order_key( learn_press_generate_order_key() );
36 - $status = $this->format_status_save_db( $order );
37 - $lp_time = new LP_Datetime( time() );
38 -
39 - $order_data = array(
40 - 'post_author' => get_current_user_id(),
41 - 'post_parent' => $order->get_parent_id(),
42 - 'post_type' => LP_ORDER_CPT,
43 - 'post_status' => $status,
44 - 'ping_status' => 'closed',
45 - 'post_title' => $order->get_title(),
46 - 'post_date' => $lp_time->toSql( true ),
47 - 'post_date_gmt' => $lp_time->toSql(),
48 - 'post_excerpt' => $order->get_customer_note(),
49 - );
50 -
51 - $order_data = apply_filters( 'learn-press/order/new-data', $order_data );
52 -
53 - $id = wp_insert_post( $order_data, true );
54 - if ( $id && ! is_wp_error( $id ) ) {
55 - $order->set_id( $id );
56 - // Update title oder when order is have just create.
57 - wp_update_post(
58 - array(
59 - 'ID' => $id,
60 - 'post_title' => learn_press_transaction_order_number( $id ),
61 - )
62 - );
63 - $this->_updates( $order );
64 - }
65 -
66 - return $id;
67 - }
68 -
69 - /**
70 - * Update order.
71 - *
72 - * @param LP_Order $order
73 - *
74 - * @return int
75 - * @Todo tungnx - check method
76 - */
77 - public function update( &$order ) {
78 - if ( ! $order instanceof LP_Order ) {
79 - return false;
80 - }
81 -
82 - $status = $this->format_status_save_db( $order );
83 - $post_data = array(
84 - //'post_title' => $order->get_order_number(),
85 - 'post_date' => $order->get_order_date( 'edit' )->toSql(),
86 - 'post_date_gmt' => $order->get_order_date( 'edit' )->toSql( false ),
87 - 'post_status' => $status,
88 - //'post_parent' => $order->get_parent_id(),
89 - );
90 - $post_data = apply_filters( 'learn-press/order/update-data', $post_data, $order->get_id() );
91 -
92 - /**
93 - * When updating this object, to prevent infinite loops, use $wpdb
94 - * to update data, since wp_update_post spawns more calls to the
95 - * save_post action.
96 - *
97 - * This ensures hooks are fired by either WP itself (admin screen save),
98 - * or an update purely from CRUD.
99 - */
100 - if ( doing_action( 'save_post' ) ) {
101 - $GLOBALS['wpdb']->update( $GLOBALS['wpdb']->posts, $post_data, array( 'ID' => $order->get_id() ) );
102 - clean_post_cache( $order->get_id() );
103 - } else {
104 - wp_update_post( array_merge( array( 'ID' => $order->get_id() ), $post_data ) );
105 - }
106 - $this->_updates( $order );
107 -
108 - return $order->get_id();
109 - }
110 -
111 - /**
112 - * Format status of LP Order before save DB.
113 - *
114 - * @param LP_Order $lp_order
115 - *
116 - * @return string
117 - */
118 - private function format_status_save_db( LP_Order $lp_order ): string {
119 - $status = ! empty( $lp_order->get_status() ) ? $lp_order->get_status() : LP_ORDER_PENDING;
120 - if ( $status === LP_ORDER_TRASH || $status === 'auto-draft' ) {
121 - return $status;
122 - }
123 -
124 - if ( ! preg_match( '/^lp-/', $status ) ) {
125 - $status = 'lp-' . $status;
126 - }
127 -
128 - return $status;
129 - }
130 -
131 - /**
132 - * @param LP_Order $order
133 - */
134 - public function _updates( &$order ) {
135 - $this->update_post_meta( $order );
136 - $order->update_meta();
137 - }
138 -
139 - /**
140 - * @param LP_Order $order
141 - */
142 - public function update_post_meta( $order ) {
143 - $meta_data = array(
144 - '_order_currency' => $order->get_currency(),
145 - '_prices_include_tax' => 'no',
146 - '_user_id' => $order->get_user_id(),
147 - '_order_subtotal' => $order->get_subtotal(),
148 - '_order_total' => $order->get_total(),
149 - '_order_key' => $order->get_order_key(),
150 - '_payment_method' => $order->get_data( 'payment_method', '' ),
151 - '_payment_method_title' => $order->get_payment_method_title(),
152 - '_user_ip_address' => $order->get_user_ip_address(),
153 - '_user_agent' => $order->get_user_agent(),
154 - '_order_version' => '3.0.0',
155 - '_created_via' => $order->get_created_via(),
156 - );
157 -
158 - $checkout_email = $order->get_checkout_email();
159 - if ( $checkout_email ) {
160 - $meta_data['_checkout_email'] = $checkout_email;
161 - }
162 -
163 - foreach ( $meta_data as $key => $value ) {
164 - update_post_meta( $order->get_id(), $key, $value );
165 - }
166 - }
167 -
168 - /**
169 - * Read order's items
170 - *
171 - * @param LP_Order $order
172 - *
173 - * @return mixed
174 - */
175 - /*
176 - old function - comment by tungnx
177 - public function read_items( $order ) {
178 - global $wpdb;
179 - $screen = function_exists('get_current_screen')? get_current_screen():null;
180 - $query = $wpdb->prepare( "
181 - SELECT order_item_id as id, order_item_name as name
182 - , oim.meta_value as `course_id`
183 - # , oim2.meta_value as `quantity`
184 - # , oim3.meta_value as `total`
185 - FROM {$wpdb->learnpress_order_items} oi
186 - INNER JOIN {$wpdb->learnpress_order_itemmeta} oim ON oi.order_item_id = oim.learnpress_order_item_id AND oim.meta_key='_course_id'
187 - # INNER JOIN {$wpdb->learnpress_order_itemmeta} oim2 ON oi.order_item_id = oim2.learnpress_order_item_id AND oim2.meta_key='_quantity'
188 - # INNER JOIN {$wpdb->learnpress_order_itemmeta} oim3 ON oi.order_item_id = oim3.learnpress_order_item_id AND oim3.meta_key='_total'
189 - WHERE order_id = %d
190 - ", $order->get_id() );
191 -
192 - $_items = $wpdb->get_results( $query );
193 - $items = array();
194 - // Loop items
195 - if ( $_items ) {
196 - foreach ( $_items as $item ) {
197 - $item = (array) $item;
198 - $items[$item['id']] = $item;
199 - if(!$screen || $screen->id !== 'edit-lp_order'){
200 - $this->get_item_meta( $item );
201 - }
202 - if ( ! empty( $item['course_id'] ) ) {
203 - $items[ $item['id'] ] = $item;
204 - }
205 - }
206 - }
207 -
208 - return $items;// apply_filters( 'learn_press_order_get_items', $items, $this );
209 - } */
210 -
211 - /**
212 - * Get order's items
213 - *
214 - * @param LP_Order $order
215 - *
216 - * @return mixed
217 - * @author tungnx
218 - * Todo: review to rewrite.
219 - */
220 - public function read_items( $order ) {
221 - $key = "order/{$order->get_id()}/{$order->get_status()}/items";
222 - $items = LP_Cache::cache_load_first( 'get', $key );
223 - if ( false !== $items ) {
224 - return $items;
225 - }
226 -
227 - global $wpdb;
228 -
229 - $table_order_items = $wpdb->learnpress_order_items;
230 - $table_order_item_meta = $wpdb->learnpress_order_itemmeta;
231 -
232 - $query = $wpdb->prepare(
233 - "SELECT o_item.order_item_id, o_item.order_item_name, o_itemmeta.meta_value, o_itemmeta.meta_key
234 - From $table_order_items as o_item
235 - INNER JOIN $table_order_item_meta as o_itemmeta
236 - ON o_item.order_item_id = o_itemmeta.learnpress_order_item_id
237 - WHERE o_item.order_id = %d
238 - LIMIT %d",
239 - $order->get_id(),
240 - 4 * 50
241 - );
242 -
243 - // Todo: write query to function and call ajax load more
244 - $order_item_metas = $wpdb->get_results( $query, OBJECT );
245 -
246 - $items = array();
247 -
248 - foreach ( $order_item_metas as $order_item_meta ) {
249 - if ( ! array_key_exists( $order_item_meta->order_item_id, $items ) ) {
250 - $items[ $order_item_meta->order_item_id ] = array();
251 - $items[ $order_item_meta->order_item_id ]['id'] = $order_item_meta->order_item_id;
252 - $items[ $order_item_meta->order_item_id ]['name'] = isset( $order_item_meta->order_item_name ) ? $order_item_meta->order_item_name : '';
253 - }
254 -
255 - switch ( $order_item_meta->meta_key ) {
256 - case '_course_id':
257 - $items[ $order_item_meta->order_item_id ]['course_id'] = $order_item_meta->meta_value;
258 - break;
259 - case '_quantity':
260 - $items[ $order_item_meta->order_item_id ]['quantity'] = $order_item_meta->meta_value;
261 - break;
262 - case '_subtotal':
263 - $items[ $order_item_meta->order_item_id ]['subtotal'] = $order_item_meta->meta_value;
264 - break;
265 - case '_total':
266 - $items[ $order_item_meta->order_item_id ]['total'] = $order_item_meta->meta_value;
267 - break;
268 - default:
269 - $items[ $order_item_meta->order_item_id ][ $order_item_meta->meta_key ] = $order_item_meta->meta_value;
270 - }
271 - }
272 -
273 - LP_Cache::cache_load_first( 'set', $key, $items );
274 -
275 - return $items; // apply_filters( 'learn_press_order_get_items', $items, $this );
276 - }
277 -
278 - /**
279 - * Get order's items
280 - *
281 - * @param LP_Order $order
282 - * @param array $filter
283 - *
284 - * @return mixed
285 - * @author tungnx
286 - */
287 - public function read_items_filter( $order, $filter = array() ) {
288 - global $wpdb;
289 -
290 - $p = $filter['p'];
291 - $limit = $filter['limit'] * 4; // 4 fields on 1 item
292 - $offset = $p * $limit;
293 -
294 - $table_order_items = $wpdb->learnpress_order_items;
295 - $table_order_item_meta = $wpdb->learnpress_order_itemmeta;
296 -
297 - $query = $wpdb->prepare(
298 - "SELECT o_item.order_item_id, o_item.order_item_name, o_itemmeta.meta_value, o_itemmeta.meta_key
299 - From $table_order_items as o_item
300 - INNER JOIN $table_order_item_meta as o_itemmeta
301 - ON o_item.order_item_id = o_itemmeta.learnpress_order_item_id
302 - WHERE o_item.order_id = %d
303 - LIMIT %d, %d",
304 - $order->get_id(),
305 - $offset,
306 - $limit
307 - );
308 -
309 - // Todo: write query to function and call ajax load more
310 - $order_item_metas = $wpdb->get_results( $query, OBJECT );
311 -
312 - $items = array();
313 -
314 - foreach ( $order_item_metas as $order_item_meta ) {
315 - if ( ! array_key_exists( $order_item_meta->order_item_id, $items ) ) {
316 - $items[ $order_item_meta->order_item_id ] = array();
317 - $items[ $order_item_meta->order_item_id ]['id'] = $order_item_meta->order_item_id;
318 - $items[ $order_item_meta->order_item_id ]['name'] = isset( $order_item_meta->order_item_name ) ? $order_item_meta->order_item_name : '';
319 - }
320 -
321 - switch ( $order_item_meta->meta_key ) {
322 - case '_course_id':
323 - $items[ $order_item_meta->order_item_id ]['course_id'] = $order_item_meta->meta_value;
324 - break;
325 - case '_quantity':
326 - $items[ $order_item_meta->order_item_id ]['quantity'] = $order_item_meta->meta_value;
327 - break;
328 - case '_subtotal':
329 - $items[ $order_item_meta->order_item_id ]['subtotal'] = $order_item_meta->meta_value;
330 - break;
331 - case '_total':
332 - $items[ $order_item_meta->order_item_id ]['total'] = $order_item_meta->meta_value;
333 - break;
334 - default:
335 - $items[ $order_item_meta->order_item_id ][ $order_item_meta->meta_key ] = $order_item_meta->meta_value;
336 - }
337 - }
338 -
339 - return $items; // apply_filters( 'learn_press_order_get_items', $items, $this );
340 - }
341 -
342 - /*public function getTotalItem() {
343 - }*/
344 -
345 - /*public function get_item_meta( &$item ) {
346 - $metas = get_metadata( 'learnpress_order_item', $item['id'] );
347 - if ( $metas ) {
348 - foreach ( $metas as $k => $v ) {
349 - $item[ preg_replace( '!^_!', '', $k ) ] = LP_Helper::maybe_unserialize( $v[0] );
350 - }
351 - }
352 - }*/
353 -
354 - public function delete( &$object ) {
355 - // TODO: Implement delete() method.
356 - }
357 -
358 - /**
359 - * @param LP_Order $order
360 - *
361 - * @return LP_Order
362 - * @deprecated 4.2.3.5
363 - */
364 - /*public function cln( $order ) {
365 - _deprecated_function( __METHOD__, '4.2.3.5' );
366 -
367 - $cloned = clone $order;
368 -
369 - $cloned->set_id( 0 );
370 - $cloned->save();
371 -
372 - $meta_keys = array(
373 - '_order_currency',
374 - '_prices_include_tax',
375 - '_user_ip_address',
376 - '_user_agent',
377 - '_order_subtotal',
378 - '_order_total',
379 - '_order_key',
380 - '_payment_method',
381 - '_payment_method_title',
382 - '_order_version',
383 - '_created_via',
384 - );
385 -
386 - foreach ( $meta_keys as $key ) {
387 - update_post_meta( $cloned->get_id(), $key, get_post_meta( $order->get_id(), $key, true ) );
388 - }
389 -
390 - $this->cln_items( $order->get_id(), $cloned->get_id() );
391 -
392 - return $cloned;
393 - }*/
394 -
395 - /**
396 - * Clone items from an order to another
397 - *
398 - * @param int $from
399 - * @param int $to
400 - *
401 - * @return mixed
402 - * @deprecated 4.2.3.5
403 - */
404 - /*public function cln_items( $from, $to ) {
405 - _deprecated_function( __METHOD__, '4.2.3.5' );
406 - $order = learn_press_get_order( $from );
407 - global $wpdb;
408 -
409 - $query = $wpdb->prepare(
410 - "
411 - SELECT *
412 - FROM {$wpdb->learnpress_order_items} oi
413 - INNER JOIN {$wpdb->learnpress_order_itemmeta} oim ON oi.order_item_id = oim.learnpress_order_item_id
414 - WHERE order_id = %d
415 - ",
416 - $from
417 - );
418 -
419 - $items = $order->get_items();
420 - if ( $items ) {
421 - $to_order = learn_press_get_order( $to );
422 - if ( ! $to_order ) {
423 - return false;
424 - }
425 -
426 - $to_order->remove_order_items();
427 -
428 - foreach ( $items as $item ) {
429 - $wpdb->insert(
430 - $wpdb->learnpress_order_items,
431 - array(
432 - 'order_item_name' => $item['name'],
433 - 'order_id' => $to,
434 - )
435 - );
436 - $learnpress_order_item_id = $wpdb->insert_id;
437 -
438 - $query = $wpdb->prepare(
439 - "
440 - SELECT *
441 - FROM {$wpdb->learnpress_order_itemmeta}
442 - WHERE learnpress_order_item_id = %d
443 - ",
444 - $item['id']
445 - );
446 -
447 - if ( $metas = $wpdb->get_results( $query ) ) {
448 - foreach ( $metas as $meta ) {
449 - $wpdb->insert(
450 - $wpdb->learnpress_order_itemmeta,
451 - array(
452 - 'learnpress_order_item_id' => $learnpress_order_item_id,
453 - 'meta_key' => $meta->meta_key,
454 - 'meta_value' => $meta->meta_value,
455 - )
456 - );
457 - }
458 - }
459 - }
460 - }
461 - $this->read_items( $order );
462 -
463 - return true;
464 - }*/
465 -
466 - /**
467 - * Load order data
468 - *
469 - * @param LP_Order $order
470 - *
471 - * @return mixed
472 - * @throws Exception
473 - */
474 - public function load( &$order ) {
475 - $the_id = $order->get_id();
476 - if ( ! $the_id || LP_ORDER_CPT !== learn_press_get_post_type( $the_id ) ) {
477 - if ( LP_Debug::is_debug() ) {
478 - throw new Exception( sprintf( __( 'Invalid order with ID "%d".', 'learnpress' ), $the_id ) );
479 - }
480 - }
481 -
482 - $post = get_post( $the_id );
483 - if ( $post ) {
484 - $_users = get_post_meta( $order->get_id(), '_user_id' );
485 - if ( $_users ) {
486 - settype( $_users, 'array' );
487 - } else {
488 - $_users = array();
489 - }
490 - if ( sizeof( $_users ) > 1 ) {
491 - $users = $_users;
492 - } elseif ( sizeof( $_users ) == 1 ) {
493 - $users = $_users[0];
494 - } else {
495 - $users = 0;
496 - }
497 -
498 - $order->set_data_via_methods(
499 - array(
500 - 'user_id' => $users,
501 - 'order_date' => new LP_Datetime( $post->post_date ),
502 - 'date_modified' => new LP_Datetime( $post->post_modified ),
503 - 'status' => str_replace( 'lp-', '', $post->post_status ),
504 - 'parent_id' => $post->post_parent,
505 - 'created_via' => get_post_meta( $post->ID, '_created_via', true ),
506 - 'total' => get_post_meta( $post->ID, '_order_total', true ),
507 - 'subtotal' => get_post_meta( $post->ID, '_order_subtotal', true ),
508 - 'order_key' => get_post_meta( $post->ID, '_order_key', true ),
509 - 'user_ip_address' => get_post_meta( $post->ID, '_user_ip_address', true ),
510 - 'user_agent' => get_post_meta( $post->ID, '_user_agent', true ),
511 - 'checkout_email' => get_post_meta( $post->ID, '_checkout_email', true ),
512 - 'currency' => get_post_meta( $post->ID, '_order_currency', true ),
513 - )
514 - );
515 - $order->set_data( 'order_subtotal', get_post_meta( $post->ID, '_order_subtotal', true ) );
516 - $order->set_data( 'order_total', get_post_meta( $post->ID, '_order_total', true ) );
517 - $order->set_data( 'payment_method', get_post_meta( $post->ID, '_payment_method', true ) );
518 - $order->set_data( 'payment_method_title', get_post_meta( $post->ID, '_payment_method_title', true ) );
519 - //$order->get_items();
520 - $order->read_meta();
521 - }
522 -
523 - return true;
524 - }
525 -
526 - /**
527 - * Recover an order checked out by Guest for an user.
528 - *
529 - * @param string $order_key
530 - * @param int $user_id
531 - *
532 - * @return bool|LP_Order|WP_Error
533 - */
534 - public function recover( $order_key, $user_id ) {
535 - try {
536 - $order = $this->get_order_by_key( $order_key );
537 -
538 - // Validations
539 - if ( ! $order ) {
540 - throw new Exception( esc_html__( 'Invalid Order key.', 'learnpress' ) );
541 - }
542 -
543 - if ( ! $order->is_guest() ) {
544 - throw new Exception( esc_html__( 'Order key is already assigned.', 'learnpress' ) );
545 - }
546 -
547 - $user = learn_press_get_user( $user_id );
548 -
549 - if ( ! $user || $user instanceof LP_User_Guest ) {
550 - throw new Exception( esc_html__( 'Invalid User!', 'learnpress' ) );
551 - }
552 -
553 - if ( $order->get_checkout_email() !== $user->get_email() ) {
554 - throw new Exception( esc_html__( 'Invalid order key with Email!', 'learnpress' ) );
555 - }
556 -
557 - // Set user to order and update
558 - $order->set_user_id( $user_id );
559 - $order->save();
560 -
561 - // Update user_id of lp_user_item
562 - if ( $order->is_completed() ) {
563 - $user_item_db = LP_User_Items_DB::getInstance();
564 - $filter = new LP_User_Items_Filter();
565 - $filter->ref_id = $order->get_id();
566 - $filter->limit = -1;
567 - $userItemModels = $user_item_db->get_user_items( $filter );
568 - if ( ! empty( $userItemModels ) ) {
569 - foreach ( $userItemModels as $userItemModelObj ) {
570 - $userItemModel = new UserCourseModel( $userItemModelObj );
571 - $userItemModel->user_id = $user_id;
572 - $userItemModel->save();
573 - }
574 - }
575 - }
576 -
577 - // Trigger action
578 - do_action( 'learn-press/order/recovered-successful', $order->get_id(), $user_id );
579 - } catch ( Exception $ex ) {
580 - return new WP_Error( 'lp_order_recover_error', $ex->getMessage() );
581 - }
582 -
583 - return $order;
584 - }
585 -
586 - /**
587 - * Retrieve an order by order key.
588 - *
589 - * @param string $order_key
590 - *
591 - * @return bool|LP_Order
592 - */
593 - public function get_order_by_key( $order_key ) {
594 - global $wpdb;
595 - $query = $wpdb->prepare(
596 - "
597 - SELECT ID
598 - FROM {$wpdb->posts} p
599 - INNER JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID AND pm.meta_key = %s AND pm.meta_value = %s
600 - ",
601 - '_order_key',
602 - $order_key
603 - );
604 -
605 - $order = false;
606 - $order_id = $wpdb->get_var( $query );
607 -
608 - if ( $order_id ) {
609 - $order = learn_press_get_order( $order_id );
610 - }
611 -
612 - return $order;
613 - }
614 -
615 - public function duplicate( &$order, $args = array() ) {
616 - // TODO: Implement duplicate() method.
617 - }
618 -}
1 +<?php
2 +/**
3 + * Class LP_Order_CURD
4 + *
5 + * @since 3.0.0
6 + */
7 +
8 +use LearnPress\Models\UserItems\UserCourseModel;
9 +
10 +defined( 'ABSPATH' ) || exit();
11 +
12 +class LP_Order_CURD extends LP_Object_Data_CURD implements LP_Interface_CURD {
13 +
14 + /**
15 + * @var string
16 + */
17 + protected $_meta_type = 'post';
18 +
19 + /**
20 + * @var array
21 + */
22 + protected $_meta_keys = array();
23 +
24 + /**
25 + * @param LP_Order $order
26 + *
27 + * @return mixed
28 + */
29 + public function create( &$order ) {
30 + if ( ! $order instanceof LP_Order ) {
31 + return false;
32 + }
33 +
34 + //$order->set_order_date( time() );
35 + $order->set_order_key( learn_press_generate_order_key() );
36 + $status = $this->format_status_save_db( $order );
37 + $lp_time = new LP_Datetime( time() );
38 +
39 + $order_data = array(
40 + 'post_author' => get_current_user_id(),
41 + 'post_parent' => $order->get_parent_id(),
42 + 'post_type' => LP_ORDER_CPT,
43 + 'post_status' => $status,
44 + 'ping_status' => 'closed',
45 + 'post_title' => $order->get_title(),
46 + 'post_date' => $lp_time->toSql( true ),
47 + 'post_date_gmt' => $lp_time->toSql(),
48 + 'post_excerpt' => $order->get_customer_note(),
49 + );
50 +
51 + $order_data = apply_filters( 'learn-press/order/new-data', $order_data );
52 +
53 + $id = wp_insert_post( $order_data, true );
54 + if ( $id && ! is_wp_error( $id ) ) {
55 + $order->set_id( $id );
56 + // Update title oder when order is have just create.
57 + wp_update_post(
58 + array(
59 + 'ID' => $id,
60 + 'post_title' => learn_press_transaction_order_number( $id ),
61 + )
62 + );
63 + $this->_updates( $order );
64 + }
65 +
66 + return $id;
67 + }
68 +
69 + /**
70 + * Update order.
71 + *
72 + * @param LP_Order $order
73 + *
74 + * @return int
75 + * @Todo tungnx - check method
76 + */
77 + public function update( &$order ) {
78 + if ( ! $order instanceof LP_Order ) {
79 + return false;
80 + }
81 +
82 + $post = get_post( $order->get_id() );
83 + $status = $this->format_status_save_db( $order );
84 + $post_data = array(
85 + 'post_status' => $status,
86 + );
87 +
88 + // For case edit Order on Backend.
89 + if ( isset( $_POST['order-date'] ) ) {
90 + // Data time submit edit order will is local time
91 + $order_date = LP_Request::get_param( 'order-date' );
92 + $order_hour = LP_Request::get_param( 'order-hour', '00' );
93 + $order_min = LP_Request::get_param( 'order-minute', '00' );
94 + $date_time_local = $order_date . ' ' . $order_hour . ':' . $order_min . ':00';
95 +
96 + // Date GMT
97 + $lpDateTimeLocal = new LP_Datetime( $date_time_local );
98 + $date_time_gmt = $lpDateTimeLocal->to_gmt_string( $lpDateTimeLocal );
99 + $post_data['post_date'] = $date_time_local;
100 + $post_data['post_date_gmt'] = $date_time_gmt;
101 + } elseif ( $post->post_status === 'auto-draft'
102 + && $post->post_date_gmt === '0000-00-00 00:00:00' ) {
103 + $date_time_gmt = get_gmt_from_date( $post->post_date );
104 + $post_data['post_date_gmt'] = $date_time_gmt;
105 + }
106 +
107 + $post_data = apply_filters( 'learn-press/order/update-data', $post_data, $order->get_id() );
108 +
109 + /**
110 + * When updating this object, to prevent infinite loops, use $wpdb
111 + * to update data, since wp_update_post spawns more calls to the
112 + * save_post action.
113 + *
114 + * This ensures hooks are fired by either WP itself (admin screen save),
115 + * or an update purely from CRUD.
116 + */
117 + if ( doing_action( 'save_post' ) ) {
118 + $GLOBALS['wpdb']->update( $GLOBALS['wpdb']->posts, $post_data, array( 'ID' => $order->get_id() ) );
119 + clean_post_cache( $order->get_id() );
120 + } else {
121 + wp_update_post( array_merge( array( 'ID' => $order->get_id() ), $post_data ) );
122 + }
123 + $this->_updates( $order );
124 +
125 + return $order->get_id();
126 + }
127 +
128 + /**
129 + * Format status of LP Order before save DB.
130 + *
131 + * @param LP_Order $lp_order
132 + *
133 + * @return string
134 + */
135 + private function format_status_save_db( LP_Order $lp_order ): string {
136 + $status = ! empty( $lp_order->get_status() ) ? $lp_order->get_status() : LP_ORDER_PENDING;
137 + if ( $status === LP_ORDER_TRASH || $status === 'auto-draft' ) {
138 + return $status;
139 + }
140 +
141 + if ( ! preg_match( '/^lp-/', $status ) ) {
142 + $status = 'lp-' . $status;
143 + }
144 +
145 + return $status;
146 + }
147 +
148 + /**
149 + * @param LP_Order $order
150 + */
151 + public function _updates( &$order ) {
152 + $this->update_post_meta( $order );
153 + $order->update_meta();
154 + }
155 +
156 + /**
157 + * @param LP_Order $order
158 + */
159 + public function update_post_meta( $order ) {
160 + $meta_data = array(
161 + '_order_currency' => $order->get_currency(),
162 + '_prices_include_tax' => 'no',
163 + '_user_id' => $order->get_user_id(),
164 + '_order_subtotal' => $order->get_subtotal(),
165 + '_order_total' => $order->get_total(),
166 + '_order_key' => $order->get_order_key(),
167 + '_payment_method' => $order->get_data( 'payment_method', '' ),
168 + '_payment_method_title' => $order->get_payment_method_title(),
169 + '_user_ip_address' => $order->get_user_ip_address(),
170 + '_user_agent' => $order->get_user_agent(),
171 + '_order_version' => '3.0.0',
172 + '_created_via' => $order->get_created_via(),
173 + );
174 +
175 + $checkout_email = $order->get_checkout_email();
176 + if ( $checkout_email ) {
177 + $meta_data['_checkout_email'] = $checkout_email;
178 + }
179 +
180 + foreach ( $meta_data as $key => $value ) {
181 + update_post_meta( $order->get_id(), $key, $value );
182 + }
183 + }
184 +
185 + /**
186 + * Read order's items
187 + *
188 + * @param LP_Order $order
189 + *
190 + * @return mixed
191 + */
192 + /*
193 + old function - comment by tungnx
194 + public function read_items( $order ) {
195 + global $wpdb;
196 + $screen = function_exists('get_current_screen')? get_current_screen():null;
197 + $query = $wpdb->prepare( "
198 + SELECT order_item_id as id, order_item_name as name
199 + , oim.meta_value as `course_id`
200 + # , oim2.meta_value as `quantity`
201 + # , oim3.meta_value as `total`
202 + FROM {$wpdb->learnpress_order_items} oi
203 + INNER JOIN {$wpdb->learnpress_order_itemmeta} oim ON oi.order_item_id = oim.learnpress_order_item_id AND oim.meta_key='_course_id'
204 + # INNER JOIN {$wpdb->learnpress_order_itemmeta} oim2 ON oi.order_item_id = oim2.learnpress_order_item_id AND oim2.meta_key='_quantity'
205 + # INNER JOIN {$wpdb->learnpress_order_itemmeta} oim3 ON oi.order_item_id = oim3.learnpress_order_item_id AND oim3.meta_key='_total'
206 + WHERE order_id = %d
207 + ", $order->get_id() );
208 +
209 + $_items = $wpdb->get_results( $query );
210 + $items = array();
211 + // Loop items
212 + if ( $_items ) {
213 + foreach ( $_items as $item ) {
214 + $item = (array) $item;
215 + $items[$item['id']] = $item;
216 + if(!$screen || $screen->id !== 'edit-lp_order'){
217 + $this->get_item_meta( $item );
218 + }
219 + if ( ! empty( $item['course_id'] ) ) {
220 + $items[ $item['id'] ] = $item;
221 + }
222 + }
223 + }
224 +
225 + return $items;// apply_filters( 'learn_press_order_get_items', $items, $this );
226 + } */
227 +
228 + /**
229 + * Get order's items
230 + *
231 + * @param LP_Order $order
232 + *
233 + * @return mixed
234 + * @author tungnx
235 + * Todo: review to rewrite.
236 + */
237 + public function read_items( $order ) {
238 + $key = "order/{$order->get_id()}/{$order->get_status()}/items";
239 + $items = LP_Cache::cache_load_first( 'get', $key );
240 + if ( false !== $items ) {
241 + return $items;
242 + }
243 +
244 + global $wpdb;
245 +
246 + $table_order_items = $wpdb->learnpress_order_items;
247 + $table_order_item_meta = $wpdb->learnpress_order_itemmeta;
248 +
249 + $query = $wpdb->prepare(
250 + "SELECT o_item.order_item_id, o_item.order_item_name, o_itemmeta.meta_value, o_itemmeta.meta_key
251 + From $table_order_items as o_item
252 + INNER JOIN $table_order_item_meta as o_itemmeta
253 + ON o_item.order_item_id = o_itemmeta.learnpress_order_item_id
254 + WHERE o_item.order_id = %d
255 + LIMIT %d",
256 + $order->get_id(),
257 + 4 * 50
258 + );
259 +
260 + // Todo: write query to function and call ajax load more
261 + $order_item_metas = $wpdb->get_results( $query, OBJECT );
262 +
263 + $items = array();
264 +
265 + foreach ( $order_item_metas as $order_item_meta ) {
266 + if ( ! array_key_exists( $order_item_meta->order_item_id, $items ) ) {
267 + $items[ $order_item_meta->order_item_id ] = array();
268 + $items[ $order_item_meta->order_item_id ]['id'] = $order_item_meta->order_item_id;
269 + $items[ $order_item_meta->order_item_id ]['name'] = isset( $order_item_meta->order_item_name ) ? $order_item_meta->order_item_name : '';
270 + }
271 +
272 + switch ( $order_item_meta->meta_key ) {
273 + case '_course_id':
274 + $items[ $order_item_meta->order_item_id ]['course_id'] = $order_item_meta->meta_value;
275 + break;
276 + case '_quantity':
277 + $items[ $order_item_meta->order_item_id ]['quantity'] = $order_item_meta->meta_value;
278 + break;
279 + case '_subtotal':
280 + $items[ $order_item_meta->order_item_id ]['subtotal'] = $order_item_meta->meta_value;
281 + break;
282 + case '_total':
283 + $items[ $order_item_meta->order_item_id ]['total'] = $order_item_meta->meta_value;
284 + break;
285 + default:
286 + $items[ $order_item_meta->order_item_id ][ $order_item_meta->meta_key ] = $order_item_meta->meta_value;
287 + }
288 + }
289 +
290 + LP_Cache::cache_load_first( 'set', $key, $items );
291 +
292 + return $items; // apply_filters( 'learn_press_order_get_items', $items, $this );
293 + }
294 +
295 + /**
296 + * Get order's items
297 + *
298 + * @param LP_Order $order
299 + * @param array $filter
300 + *
301 + * @return mixed
302 + * @author tungnx
303 + */
304 + public function read_items_filter( $order, $filter = array() ) {
305 + global $wpdb;
306 +
307 + $p = $filter['p'];
308 + $limit = $filter['limit'] * 4; // 4 fields on 1 item
309 + $offset = $p * $limit;
310 +
311 + $table_order_items = $wpdb->learnpress_order_items;
312 + $table_order_item_meta = $wpdb->learnpress_order_itemmeta;
313 +
314 + $query = $wpdb->prepare(
315 + "SELECT o_item.order_item_id, o_item.order_item_name, o_itemmeta.meta_value, o_itemmeta.meta_key
316 + From $table_order_items as o_item
317 + INNER JOIN $table_order_item_meta as o_itemmeta
318 + ON o_item.order_item_id = o_itemmeta.learnpress_order_item_id
319 + WHERE o_item.order_id = %d
320 + LIMIT %d, %d",
321 + $order->get_id(),
322 + $offset,
323 + $limit
324 + );
325 +
326 + // Todo: write query to function and call ajax load more
327 + $order_item_metas = $wpdb->get_results( $query, OBJECT );
328 +
329 + $items = array();
330 +
331 + foreach ( $order_item_metas as $order_item_meta ) {
332 + if ( ! array_key_exists( $order_item_meta->order_item_id, $items ) ) {
333 + $items[ $order_item_meta->order_item_id ] = array();
334 + $items[ $order_item_meta->order_item_id ]['id'] = $order_item_meta->order_item_id;
335 + $items[ $order_item_meta->order_item_id ]['name'] = isset( $order_item_meta->order_item_name ) ? $order_item_meta->order_item_name : '';
336 + }
337 +
338 + switch ( $order_item_meta->meta_key ) {
339 + case '_course_id':
340 + $items[ $order_item_meta->order_item_id ]['course_id'] = $order_item_meta->meta_value;
341 + break;
342 + case '_quantity':
343 + $items[ $order_item_meta->order_item_id ]['quantity'] = $order_item_meta->meta_value;
344 + break;
345 + case '_subtotal':
346 + $items[ $order_item_meta->order_item_id ]['subtotal'] = $order_item_meta->meta_value;
347 + break;
348 + case '_total':
349 + $items[ $order_item_meta->order_item_id ]['total'] = $order_item_meta->meta_value;
350 + break;
351 + default:
352 + $items[ $order_item_meta->order_item_id ][ $order_item_meta->meta_key ] = $order_item_meta->meta_value;
353 + }
354 + }
355 +
356 + return $items; // apply_filters( 'learn_press_order_get_items', $items, $this );
357 + }
358 +
359 + /*public function getTotalItem() {
360 + }*/
361 +
362 + /*public function get_item_meta( &$item ) {
363 + $metas = get_metadata( 'learnpress_order_item', $item['id'] );
364 + if ( $metas ) {
365 + foreach ( $metas as $k => $v ) {
366 + $item[ preg_replace( '!^_!', '', $k ) ] = LP_Helper::maybe_unserialize( $v[0] );
367 + }
368 + }
369 + }*/
370 +
371 + public function delete( &$object ) {
372 + // TODO: Implement delete() method.
373 + }
374 +
375 + /**
376 + * @param LP_Order $order
377 + *
378 + * @return LP_Order
379 + * @deprecated 4.2.3.5
380 + */
381 + /*public function cln( $order ) {
382 + _deprecated_function( __METHOD__, '4.2.3.5' );
383 +
384 + $cloned = clone $order;
385 +
386 + $cloned->set_id( 0 );
387 + $cloned->save();
388 +
389 + $meta_keys = array(
390 + '_order_currency',
391 + '_prices_include_tax',
392 + '_user_ip_address',
393 + '_user_agent',
394 + '_order_subtotal',
395 + '_order_total',
396 + '_order_key',
397 + '_payment_method',
398 + '_payment_method_title',
399 + '_order_version',
400 + '_created_via',
401 + );
402 +
403 + foreach ( $meta_keys as $key ) {
404 + update_post_meta( $cloned->get_id(), $key, get_post_meta( $order->get_id(), $key, true ) );
405 + }
406 +
407 + $this->cln_items( $order->get_id(), $cloned->get_id() );
408 +
409 + return $cloned;
410 + }*/
411 +
412 + /**
413 + * Clone items from an order to another
414 + *
415 + * @param int $from
416 + * @param int $to
417 + *
418 + * @return mixed
419 + * @deprecated 4.2.3.5
420 + */
421 + /*public function cln_items( $from, $to ) {
422 + _deprecated_function( __METHOD__, '4.2.3.5' );
423 + $order = learn_press_get_order( $from );
424 + global $wpdb;
425 +
426 + $query = $wpdb->prepare(
427 + "
428 + SELECT *
429 + FROM {$wpdb->learnpress_order_items} oi
430 + INNER JOIN {$wpdb->learnpress_order_itemmeta} oim ON oi.order_item_id = oim.learnpress_order_item_id
431 + WHERE order_id = %d
432 + ",
433 + $from
434 + );
435 +
436 + $items = $order->get_items();
437 + if ( $items ) {
438 + $to_order = learn_press_get_order( $to );
439 + if ( ! $to_order ) {
440 + return false;
441 + }
442 +
443 + $to_order->remove_order_items();
444 +
445 + foreach ( $items as $item ) {
446 + $wpdb->insert(
447 + $wpdb->learnpress_order_items,
448 + array(
449 + 'order_item_name' => $item['name'],
450 + 'order_id' => $to,
451 + )
452 + );
453 + $learnpress_order_item_id = $wpdb->insert_id;
454 +
455 + $query = $wpdb->prepare(
456 + "
457 + SELECT *
458 + FROM {$wpdb->learnpress_order_itemmeta}
459 + WHERE learnpress_order_item_id = %d
460 + ",
461 + $item['id']
462 + );
463 +
464 + if ( $metas = $wpdb->get_results( $query ) ) {
465 + foreach ( $metas as $meta ) {
466 + $wpdb->insert(
467 + $wpdb->learnpress_order_itemmeta,
468 + array(
469 + 'learnpress_order_item_id' => $learnpress_order_item_id,
470 + 'meta_key' => $meta->meta_key,
471 + 'meta_value' => $meta->meta_value,
472 + )
473 + );
474 + }
475 + }
476 + }
477 + }
478 + $this->read_items( $order );
479 +
480 + return true;
481 + }*/
482 +
483 + /**
484 + * Load order data
485 + *
486 + * @param LP_Order $order
487 + *
488 + * @return mixed
489 + * @throws Exception
490 + */
491 + public function load( &$order ) {
492 + $the_id = $order->get_id();
493 + if ( ! $the_id || LP_ORDER_CPT !== learn_press_get_post_type( $the_id ) ) {
494 + if ( LP_Debug::is_debug() ) {
495 + throw new Exception( sprintf( __( 'Invalid order with ID "%d".', 'learnpress' ), $the_id ) );
496 + }
497 + }
498 +
499 + $post = get_post( $the_id );
500 + if ( $post ) {
501 + $_users = get_post_meta( $order->get_id(), '_user_id' );
502 + if ( $_users ) {
503 + settype( $_users, 'array' );
504 + } else {
505 + $_users = array();
506 + }
507 + if ( sizeof( $_users ) > 1 ) {
508 + $users = $_users;
509 + } elseif ( sizeof( $_users ) == 1 ) {
510 + $users = $_users[0];
511 + } else {
512 + $users = 0;
513 + }
514 +
515 + $lpDateTimeGmt = new LP_Datetime( $post->post_date_gmt );
516 + $date_local = $lpDateTimeGmt->toSql( true );
517 + $order->set_order_date( new LP_Datetime( $date_local ) );
518 +
519 + $order->set_user_id( $users );
520 + $order->set_date_modified( new LP_Datetime( $post->post_modified ) );
521 + $order->set_status( str_replace( 'lp-', '', $post->post_status ) );
522 + $order->set_parent_id( $post->post_parent );
523 + $order->set_created_via( get_post_meta( $post->ID, '_created_via', true ) );
524 + $order->set_total( get_post_meta( $post->ID, '_order_total', true ) );
525 + $order->set_subtotal( get_post_meta( $post->ID, '_order_subtotal', true ) );
526 + $order->set_order_key( get_post_meta( $post->ID, '_order_key', true ) );
527 + $order->set_user_ip_address( get_post_meta( $post->ID, '_user_ip_address', true ) );
528 + $order->set_user_agent( get_post_meta( $post->ID, '_user_agent', true ) );
529 + $order->set_checkout_email( get_post_meta( $post->ID, '_checkout_email', true ) );
530 + $order->set_currency( get_post_meta( $post->ID, '_order_currency', true ) );
531 + $order->set_data( 'order_subtotal', get_post_meta( $post->ID, '_order_subtotal', true ) );
532 + $order->set_data( 'order_total', get_post_meta( $post->ID, '_order_total', true ) );
533 + $order->set_data( 'payment_method', get_post_meta( $post->ID, '_payment_method', true ) );
534 + $order->set_data( 'payment_method_title', get_post_meta( $post->ID, '_payment_method_title', true ) );
535 + //$order->get_items();
536 + $order->read_meta();
537 + }
538 +
539 + return true;
540 + }
541 +
542 + /**
543 + * Recover an order checked out by Guest for an user.
544 + *
545 + * @param string $order_key
546 + * @param int $user_id
547 + *
548 + * @return bool|LP_Order|WP_Error
549 + */
550 + public function recover( $order_key, $user_id ) {
551 + try {
552 + $order = $this->get_order_by_key( $order_key );
553 +
554 + // Validations
555 + if ( ! $order ) {
556 + throw new Exception( esc_html__( 'Invalid Order key.', 'learnpress' ) );
557 + }
558 +
559 + if ( ! $order->is_guest() ) {
560 + throw new Exception( esc_html__( 'Order key is already assigned.', 'learnpress' ) );
561 + }
562 +
563 + $user = learn_press_get_user( $user_id );
564 +
565 + if ( ! $user || $user instanceof LP_User_Guest ) {
566 + throw new Exception( esc_html__( 'Invalid User!', 'learnpress' ) );
567 + }
568 +
569 + if ( $order->get_checkout_email() !== $user->get_email() ) {
570 + throw new Exception( esc_html__( 'Invalid order key with Email!', 'learnpress' ) );
571 + }
572 +
573 + // Set user to order and update
574 + $order->set_user_id( $user_id );
575 + $order->save();
576 +
577 + // Update user_id of lp_user_item
578 + if ( $order->is_completed() ) {
579 + $user_item_db = LP_User_Items_DB::getInstance();
580 + $filter = new LP_User_Items_Filter();
581 + $filter->ref_id = $order->get_id();
582 + $filter->limit = -1;
583 + $userItemModels = $user_item_db->get_user_items( $filter );
584 + if ( ! empty( $userItemModels ) ) {
585 + foreach ( $userItemModels as $userItemModelObj ) {
586 + $userItemModel = new UserCourseModel( $userItemModelObj );
587 + $userItemModel->user_id = $user_id;
588 + $userItemModel->save();
589 + }
590 + }
591 + }
592 +
593 + // Trigger action
594 + do_action( 'learn-press/order/recovered-successful', $order->get_id(), $user_id );
595 + } catch ( Exception $ex ) {
596 + return new WP_Error( 'lp_order_recover_error', $ex->getMessage() );
597 + }
598 +
599 + return $order;
600 + }
601 +
602 + /**
603 + * Retrieve an order by order key.
604 + *
605 + * @param string $order_key
606 + *
607 + * @return bool|LP_Order
608 + */
609 + public function get_order_by_key( $order_key ) {
610 + global $wpdb;
611 + $query = $wpdb->prepare(
612 + "
613 + SELECT ID
614 + FROM {$wpdb->posts} p
615 + INNER JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID AND pm.meta_key = %s AND pm.meta_value = %s
616 + ",
617 + '_order_key',
618 + $order_key
619 + );
620 +
621 + $order = false;
622 + $order_id = $wpdb->get_var( $query );
623 +
624 + if ( $order_id ) {
625 + $order = learn_press_get_order( $order_id );
626 + }
627 +
628 + return $order;
629 + }
630 +
631 + public function duplicate( &$order, $args = array() ) {
632 + // TODO: Implement duplicate() method.
633 + }
634 +}