LLMS_Controller_Orders
LLMS_Controller_Orders class.
Contents
Source Source
File: includes/controllers/class.llms.controller.orders.php
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 | class LLMS_Controller_Orders { /** * Constructor. * * @since 3.0.0 * @since 3.19.0 Updated. * @since 3.33.0 Added `before_delete_post` action to handle order deletion. * @since 4.2.0 Added `llms_user_enrollment_deleted` action to handle order status change on enrollment deletion. * @since 5.4.0 Perform `error_order()` when Detect a product deletion while processing a recurring charge. * @since 7.0.0 Added callback for `wp_untrash_post_status` filter. * Remove action callbacks for order confirm, create, and payment source switch in favor of hooks in `LLMS_Controller_Checkout`. * * @return void */ public function __construct() { add_filter( 'wp_untrash_post_status' , array ( $this , 'set_untrash_status' ), 10, 3 ); // This action adds our lifterlms specific actions when order & transaction statuses change. add_action( 'transition_post_status' , array ( $this , 'transition_status' ), 10, 3 ); // This action adds lifterlms specific action when an order is deleted, just before the WP post postmetas are removed. add_action( 'before_delete_post' , array ( $this , 'on_delete_order' ) ); // This action is meant to do specific actions on orders when an enrollment, with an order as trigger, is deleted. add_action( 'llms_user_enrollment_deleted' , array ( $this , 'on_user_enrollment_deleted' ), 10, 3 ); // Transaction status changes cascade up to the order to change the order status. add_action( 'lifterlms_transaction_status_failed' , array ( $this , 'transaction_failed' ), 10, 1 ); add_action( 'lifterlms_transaction_status_refunded' , array ( $this , 'transaction_refunded' ), 10, 1 ); add_action( 'lifterlms_transaction_status_succeeded' , array ( $this , 'transaction_succeeded' ), 10, 1 ); // Status changes for orders to enroll students and trigger completion actions. add_action( 'lifterlms_order_status_completed' , array ( $this , 'complete_order' ), 10, 2 ); add_action( 'lifterlms_order_status_active' , array ( $this , 'complete_order' ), 10, 2 ); // Status changes to pending cancel. add_action( 'lifterlms_order_status_pending-cancel' , array ( $this , 'pending_cancel_order' ), 10, 1 ); // Status changes for orders to unenroll students upon purchase. add_action( 'lifterlms_order_status_refunded' , array ( $this , 'error_order' ), 10, 1 ); add_action( 'lifterlms_order_status_cancelled' , array ( $this , 'error_order' ), 10, 1 ); add_action( 'lifterlms_order_status_expired' , array ( $this , 'error_order' ), 10, 1 ); add_action( 'lifterlms_order_status_failed' , array ( $this , 'error_order' ), 10, 1 ); add_action( 'lifterlms_order_status_on-hold' , array ( $this , 'error_order' ), 10, 1 ); add_action( 'lifterlms_order_status_trash' , array ( $this , 'error_order' ), 10, 1 ); // Detect a product deletion while processing a recurring charge. add_action( 'llms_order_recurring_charge_aborted_product_deleted' , array ( $this , 'error_order' ), 10, 1 ); /** * Scheduler Actions */ // Charge recurring payments. add_action( 'llms_charge_recurring_payment' , array ( $this , 'recurring_charge' ), 10, 1 ); // Expire access plans. add_action( 'llms_access_plan_expiration' , array ( $this , 'expire_access' ), 10, 1 ); } /** * Perform actions on a successful order completion. * * @since 1.0.0 * @since 3.19.0 Unknown. * * @param LLMS_Order $order Instance of an LLMS_Order. * @param string $old_status Previous order status (eg: 'pending'). * @return void */ public function complete_order( $order , $old_status ) { // Clear expiration date when moving from a pending-cancel order. if ( 'pending-cancel' === $old_status ) { $order ->set( 'date_access_expires' , '' ); } // Record access start time & maybe schedule expiration. $order ->start_access(); $order_id = $order ->get( 'id' ); $product_id = $order ->get( 'product_id' ); $user_id = $order ->get( 'user_id' ); unset( llms()->session->llms_coupon ); /** * Action fired on order complete. * * Prior to the students being enrolled. * * @since 1.0.0 * * @param integer $order_id The WP_Post ID of the order. */ do_action( 'lifterlms_order_complete' , $order_id ); // @todo used by AffiliateWP only, can remove after updating AffiliateWP. // Enroll student. llms_enroll_student( $user_id , $product_id , 'order_' . $order_id ); // Trigger purchase action, used by engagements. /** * Action fired on product purchased. * * After the student has been enrolled. * * @since Unknown * * @param integer $user_id The WP_User ID of the buyer. * @param integer $product_id The WP_Post ID of the purchased product (course/membership). */ do_action( 'lifterlms_product_purchased' , $user_id , $product_id ); /** * Action fired on access plan purchased. * * After the student has been enrolled. * * @since Unknown * * @param integer $user_id The WP_User ID of the buyer. * @param integer $product_id The WP_Post ID of the purchased access plan. */ do_action( 'lifterlms_access_plan_purchased' , $user_id , $order ->get( 'plan_id' ) ); // Maybe schedule a payment. $order ->maybe_schedule_payment(); } /** * Called when an order's status changes to refunded, cancelled, expired, or failed. * * Also called on product deletion detected while processing a recurring charge. * @since 3.0.0 * @since 3.10.0 Unknown. * @since 4.2.0 Added `llms_unenroll_on_error_order` filter hook. * @since 5.4.0 Unenroll with 'cancelled' status on 'llms_order_recurring_charge_aborted_product_deleted'. * The `$order` param can be also a WP_Post or its `ID`. * * @param int|WP_Post|LLMS_Order $order Instance of an LLMS_Order, WP_Post or WP_Post ID of the order. * @return void */ public function error_order( $order ) { $order = is_a ( $order , 'LLMS_Order' ) ? $order : llms_get_post( $order ); if ( ! ( $order && is_a ( $order , 'LLMS_Order' ) ) ) { return ; } $order ->unschedule_recurring_payment(); /** * Determine if student should be unenrolled on order error. * * @since 4.2.0 * * @param bool $unenroll_on_error_order True if the student should be unenrolled, false otherwise. Default true. * @param LLMS_Order $order Order object. */ if ( ! apply_filters( 'llms_unenroll_on_error_order' , true, $order ) ) { return ; } switch ( current_filter() ) { case 'lifterlms_order_status_trash' : case 'lifterlms_order_status_cancelled' : case 'lifterlms_order_status_on-hold' : case 'lifterlms_order_status_refunded' : case 'llms_order_recurring_charge_aborted_product_deleted' : $status = 'cancelled' ; break ; case 'lifterlms_order_status_expired' : case 'lifterlms_order_status_failed' : default : $status = 'expired' ; break ; } llms_unenroll_student( $order ->get( 'user_id' ), $order ->get( 'product_id' ), $status , 'order_' . $order ->get( 'id' ) ); } /** * Called when a post is permanently deleted. * * Will delete any enrollment records linked to the LLMS_Order with the ID of the deleted post. * * @since 3.33.0 * * @param int $post_id WP_Post ID. * @return void */ public function on_delete_order( $post_id ) { $order = llms_get_post( $post_id ); if ( $order && is_a ( $order , 'LLMS_Order' ) ) { llms_delete_student_enrollment( $order ->get( 'user_id' ), $order ->get( 'product_id' ), 'order_' . $order ->get( 'id' ) ); } } /** * Called when an user enrollment is deleted. * * Will set the related order status to 'cancelled'. * * @since 4.2.0 * * @param int $user_id WP User ID. * @param int $product_id WP Post ID of the course or membership. * @param string $trigger The deleted enrollment trigger, or 'any' if no specific trigger. * @return void */ public function on_user_enrollment_deleted( $user_id , $product_id , $trigger ) { $order_id = 'order_' === substr ( $trigger , 0, 6 ) ? absint( substr ( $trigger , 6 ) ) : false; $order = $order_id ? llms_get_post( $order_id ) : false; if ( $order && is_a ( $order , 'LLMS_Order' ) ) { // No need to run an unenrollment as we're reacting to an enrollment deletion, user enrollments data already removed. add_filter( 'llms_unenroll_on_error_order' , '__return_false' , 100 ); $order ->set_status( 'cancelled' ); // Reset unenrollment's suspension.. remove_filter( 'llms_unenroll_on_error_order' , '__return_false' , 100 ); } } /** * Handle expiration & cancellation from a course / membership. * * Called via scheduled action set during order completion for plans with a limited access plan. * Additionally called when an order is marked as "pending-cancel" to revoke access at the end of a pre-paid period. * * @since 3.0.0 * @since 3.19.0 Unknown. * @since 7.5.0 Potentially allow recurring payment to go ahead even if access plans expired. * * @param int $order_id WP_Post ID of the LLMS Order. * @return void */ public function expire_access( $order_id ) { $order = new LLMS_Order( $order_id ); $new_order_status = false; // Pending cancel order moves to cancelled. if ( 'llms-pending-cancel' === $order ->get( 'status' ) ) { $status = 'cancelled' ; // Enrollment status. $note = __( 'Student unenrolled at the end of access period due to subscription cancellation.' , 'lifterlms' ); $new_order_status = 'cancelled' ; // All others move to expired. } else { $status = 'expired' ; // Enrollment status. $note = __( 'Student unenrolled due to automatic access plan expiration' , 'lifterlms' ); } /** * Filters whether or not recurring payments should be stopped on access plan expiration. * * By default when an access plan expires, recurring payments are stopped. * * @since 7.5.0 * * @param bool * @param LLMS_Order $order Instance of the order. * @param mixed $new_order_status New order status. If `false` it means that the new order status is not * going to change. At this stage the orders status is not changed yet. * @param string $enrollment_status The new enrollment status. At this stage the enrollment status is not changed yet. */ $unschedule_recurring_payment = apply_filters( 'llms_unschedule_recurring_payment_on_access_plan_expiration' , true, $order , $new_order_status , $status ); llms_unenroll_student( $order ->get( 'user_id' ), $order ->get( 'product_id' ), $status , 'order_' . $order ->get( 'id' ) ); $order ->add_note( $note ); if ( $unschedule_recurring_payment ) { $order ->unschedule_recurring_payment(); } if ( $new_order_status ) { $order ->set_status( $new_order_status ); } } /** * Unschedule recurring payments and schedule access expiration. * * @since 3.19.0 * * @param LLMS_Order $order LLMS_Order object. * @return void */ public function pending_cancel_order( $order ) { $date = $order ->get_next_payment_due_date( 'Y-m-d H:i:s' ); $order ->set( 'date_access_expires' , $date ); $order ->unschedule_recurring_payment(); $order ->maybe_schedule_expiration(); } /** * Trigger a recurring payment. * * Called by action scheduler. * * @since 3.0.0 * @since 3.32.0 Record order notes and trigger actions during errors. * @since 3.36.1 Made sure to process only proper LLMS_Orders of existing users. * @since 5.2.0 Fixed buggy logging on gateway error because it doesn't support recurring payments. * @since 5.4.0 Handle case when the order's related product has been removed. * * @param int $order_id WP Post ID of the order. * @return bool `false` if the recurring charge cannot be processed, `true` when the charge is successfully handed off to the gateway. */ public function recurring_charge( $order_id ) { // Make sure the order still exists. $order = llms_get_post( $order_id ); if ( ! $order || ! is_a ( $order , 'LLMS_Order' ) ) { /** * Fired when a LifterLMS order's recurring charge errors because the order doesn't exist anymore * * @since Unknown * * @param int $order_id WP Post ID of the order. * @param LLMS_Controller_Orders $controller This controller's instance. */ do_action( 'llms_order_recurring_charge_order_error' , $order_id , $this ); llms_log( sprintf( 'Recurring charge for Order #%d could not be processed because the order no longer exists.' , $order_id ), 'recurring-payments' ); return false; } // Check the user still exists. $user_id = $order ->get( 'user_id' ); if ( ! get_user_by( 'id' , $user_id ) ) { /** * Fired when a LifterLMS order's recurring charge errors because the user who placed the order doesn't exist anymore * * @since Unknown * * @param int $order_id WP Post ID of the order. * @param int $user_id WP User ID of the user who placed the order. * @param LLMS_Controller_Orders $controller This controller's instance. */ do_action( 'llms_order_recurring_charge_user_error' , $order_id , $user_id , $this ); llms_log( sprintf( 'Recurring charge for Order #%1$d could not be processed because the user (#%2$d) no longer exists.' , $order_id , $user_id ), 'recurring-payments' ); // Translators: %d = The deleted user's ID. $order ->add_note( sprintf( __( 'Recurring charge skipped. The user (#%d) no longer exists.' , 'lifterlms' ), $user_id ) ); return false; } // Ensure Gateway is still available. $gateway = $order ->get_gateway(); if ( is_wp_error( $gateway ) ) { /** * Fired when a LifterLMS order's recurring charge errors because of a gateway error. E.g. it's not available anymore. * * @since Unknown * * @param int $order_id WP Post ID of the order. * @param WP_Error $error WP_Error instance. * @param LLMS_Controller_Orders $controller This controller's instance. */ do_action( 'llms_order_recurring_charge_gateway_error' , $order_id , $gateway , $this ); llms_log( sprintf( 'Recurring charge for Order #%1$d could not be processed because the "%2$s" gateway is no longer available. Gateway Error: %3$s' , $order_id , $order ->get( 'payment_gateway' ), $gateway ->get_error_message() ), 'recurring-payments' ); $order ->add_note( sprintf( // Translators: %s = error message encountered while loading the gateway. __( 'Recurring charge was not processed due to an error encountered while loading the payment gateway: %s.' , 'lifterlms' ), $gateway ->get_error_message() ) ); return false; } // Gateway doesn't support recurring payments. if ( ! $gateway ->supports( 'recurring_payments' ) ) { /** * Fired when a LifterLMS order's recurring charge errors because the selected gateway doesn't support recurring payments. * * @since Unknown * * @param int $order_id WP Post ID of the order. * @param LLMS_Payment_Gateway $gateway LLMS_Payment_Gateway extending class instance. * @param LLMS_Controller_Orders $controller This controller's instance. */ do_action( 'llms_order_recurring_charge_gateway_payments_disabled' , $order_id , $gateway , $this ); llms_log( sprintf( 'Recurring charge for order #%d could not be processed because the gateway no longer supports recurring payments.' , $order_id ), 'recurring-payments' ); $order ->add_note( __( 'Recurring charge skipped because recurring payments are disabled for the payment gateway.' , 'lifterlms' ) ); return false; } // Recurring payments disabled as a site feature when in staging mode. if ( ! LLMS_Site::get_feature( 'recurring_payments' ) ) { /** * Fired when a LifterLMS order's recurring charge errors because the recurring payments site feature is disabled. * * @since Unknown * * @param int $order_id WP Post ID of the order. * @param LLMS_Payment_Gateway $gateway LLMS_Payment_Gateway extending class instance. * @param LLMS_Controller_Orders $controller This controller's instance. */ do_action( 'llms_order_recurring_charge_skipped' , $order_id , $gateway , $this ); $order ->add_note( __( 'Recurring charge skipped because recurring payments are disabled in staging mode.' , 'lifterlms' ) ); return false; } // Related product removed. if ( empty ( $order ->get_product() ) ) { /** * Fired when a LifterLMS order's recurring charge errors because the purchased product (Course/Membership) doesn't exist anymore. * * @since Unknown * * @param int $order_id WP Post ID of the order. * @param LLMS_Controller_Orders $controller This controller's instance. */ do_action( 'llms_order_recurring_charge_aborted_product_deleted' , $order_id , $this ); llms_log( sprintf( 'Recurring charge for order #%d could not be processed because the product #%d does not exist anymore.' , $order_id , $order ->get( 'product_id' ) ), 'recurring-payments' ); $order ->add_note( __( 'Recurring charge aborted because the purchased product does not exist anymore.' , 'lifterlms' ) ); return false; } // Passed validation, hand off to the gateway. $gateway ->handle_recurring_transaction( $order ); return true; } /** * Sets an order's post status to `llms-pending` when untrashing an order. * * This is a filter hook callback for the WP core filter `wp_untrash_post_status`. * * @since 7.0.0 * * @param string $new_status The new status of the post after untrashing. * @param int $post_id The WP_Post ID of the order. * @param string $previous_status The status of the post at the point where it was trashed. * @return string */ public function set_untrash_status( $new_status , $post_id , $previous_status ) { if ( 'llms_order' === get_post_type( $post_id ) ) { /** * Filters the status that an order post gets assigned when it is restored from the trash. * * This is a filter nearly identical to `wp_untrash_post_status` applied specifically to `llms_order` posts. * * @since 7.0.0 * * * @param string $new_status The new status of the post being restored. * @param int $post_id The ID of the post being restored. * @param string $previous_status The status of the post at the point where it was trashed. */ $new_status = apply_filters( 'llms_untrash_order_status' , 'llms-pending' , $post_id , $previous_status ); } return $new_status ; } /** * When a transaction fails, update the parent order's status. * * @since 3.0.0 * @since 3.10.0 Unknown. * * @param LLMS_Transaction $txn Instance of the LLMS_Transaction. * @return void */ public function transaction_failed( $txn ) { $order = $txn ->get_order(); // Halt if legacy. if ( $order ->is_legacy() ) { return ; } if ( $order ->can_be_retried() ) { $order ->maybe_schedule_retry(); } else { $order ->set( 'status' , 'llms-failed' ); } } /** * When a transaction is refunded, update the parent order's status. * * @since 3.0.0 * * @param LLMS_Transaction $txn Instance of the LLMS_Transaction. * @return void */ public function transaction_refunded( $txn ) { $order = $txn ->get_order(); // Halt if legacy. if ( $order ->is_legacy() ) { return ; } $order ->set( 'status' , 'llms-refunded' ); } /** * When a transaction succeeds, update the parent order's status. * * @since 3.0.0 * @since 3.10.0 Unknown. * * @param LLMS_Transaction $txn Instance of the LLMS_Transaction. * @return void */ public function transaction_succeeded( $txn ) { // Get the order. $order = $txn ->get_order(); // Halt if legacy. if ( $order ->is_legacy() ) { return ; } // Update the status based on the order type. $status = $order ->is_recurring() ? 'llms-active' : 'llms-completed' ; $order ->set( 'status' , $status ); $order ->set( 'last_retry_rule' , '' ); // Retries should always start with tne first rule for new transactions. // Maybe schedule a payment. $order ->maybe_schedule_payment(); } /** * Trigger actions when the status of LifterLMS Orders and LifterLMS Transactions change status. * * @since 3.0.0 * @since 3.19.0 Unknown. * * @param string $new_status New status. * @param string $old_status Old status. * @param WP_Post $post WP_Post instance of the transaction. * @return void */ public function transition_status( $new_status , $old_status , $post ) { // Don't do anything if the status hasn't changed. if ( $new_status === $old_status ) { return ; } // We're only concerned with order post statuses here. if ( 'llms_order' !== $post ->post_type && 'llms_transaction' !== $post ->post_type ) { return ; } $post_type = str_replace ( 'llms_' , '' , $post ->post_type ); $obj = 'order' === $post_type ? new LLMS_Order( $post ) : new LLMS_Transaction( $post ); // Record order status changes as notes. if ( 'order' === $post_type ) { $obj ->add_note( sprintf( __( 'Order status changed from %1$s to %2$s' , 'lifterlms' ), llms_get_order_status_name( $old_status ), llms_get_order_status_name( $new_status ) ) ); } // Remove prefixes from all the things. $new_status = str_replace ( array ( 'llms-' , 'txn-' ), '' , $new_status ); $old_status = str_replace ( array ( 'llms-' , 'txn-' ), '' , $old_status ); /** * Fired when a LifterLMS order or transaction changes status. * * The first dynamic portion of this hook, `$post_type`, refers to the unprefixed object post type ('order|transaction'). * The second dynamic portion of this hook, `$old_status`, refers to the previous object status. * The third dynamic portion of this hook, `$new_status`, refers to the new object status. * * @since Unknown * * @param LLMS_Order|LLMS_Transaction $object The LifterLMS order or transaction instance. * @param string $old_status The previous order or transaction status. * @param string $new_status The new order or transaction status. */ do_action( "lifterlms_{$post_type}_status_{$old_status}_to_{$new_status}" , $obj , $old_status , $new_status ); /** * Fired when a LifterLMS order or transaction changes status. * * The first dynamic portion of this hook, `$post_type`, refers to the unprefixed object post type ('order|transaction'). * The second dynamic portion of this hook, `$new_status`, refers to the new object status. * * @since Unknown * * @param LLMS_Order|LLMS_Transaction $object The LifterLMS order or transaction instance. * @param string $old_status The previous order or transaction status. * @param string $new_status The new order or transaction status. */ do_action( "lifterlms_{$post_type}_status_{$new_status}" , $obj , $old_status , $new_status ); } /** * Validate a gateway can be used to process the current action / transaction. * * @since 3.10.0 * * @param string $gateway_id Gateway's id. * @param LLMS_Access_Plan $plan Instance of the LLMS_Access_Plan related to the action/transaction. * @return WP_Error|LLMS_Payment_Gateway WP_Error or LLMS_Payment_Gateway subclass. */ private function validate_selected_gateway( $gateway_id , $plan ) { $gateway = llms()->payment_gateways()->get_gateway_by_id( $gateway_id ); $err = new WP_Error(); // Valid gateway. if ( is_subclass_of ( $gateway , 'LLMS_Payment_Gateway' ) ) { // Gateway not enabled. if ( 'manual' !== $gateway ->get_id() && ! $gateway ->is_enabled() ) { return $err ->add( 'gateway-error' , __( 'The selected payment gateway is not currently enabled.' , 'lifterlms' ) ); // It's a recurring plan and the gateway doesn't support recurring. } elseif ( $plan ->is_recurring() && ! $gateway ->supports( 'recurring_payments' ) ) { // Translators: %s = The gateway display name. return $err ->add( 'gateway-error' , sprintf( __( '%s does not support recurring payments and cannot process this transaction.' , 'lifterlms' ), $gateway ->get_title() ) ); // Not recurring and the gateway doesn't support single payments. } elseif ( ! $plan ->is_recurring() && ! $gateway ->supports( 'single_payments' ) ) { // Translators: %s = The gateway display name. return $err ->add( 'gateway-error' , sprintf( __( '%s does not support single payments and cannot process this transaction.' , 'lifterlms' ), $gateway ->get_title() ) ); } } else { return $err ->add( 'invalid-gateway' , __( 'An invalid payment method was selected.' , 'lifterlms' ) ); } return $gateway ; } /** * Confirm order form post. * * User clicks confirm order or gateway determines the order is confirmed. * * Executes payment gateway confirm order method and completes order. * Redirects user to appropriate page / post * * @since 3.0.0 * @since 3.4.0 Unknown. * @since 3.34.4 Added filter `llms_order_can_be_confirmed`. * @since 3.34.5 Fixed logic error in `llms_order_can_be_confirmed` conditional. * @since 3.35.0 Return early if nonce doesn't pass verification and sanitize `$_POST` data. * @since 5.9.0 Stop using deprecated `FILTER_SANITIZE_STRING`. * @deprecated 7.0.0 Deprecated in favor of {@see LLMS_Controller_Checkout::confirm_pending_order()}. * * @return void */ public function confirm_pending_order() { _deprecated_function( __METHOD__ , '7.0.0' , 'LLMS_Controller_Checkout::confirm_pending_order' ); LLMS_Controller_Checkout::instance()->confirm_pending_order(); } /** * Handle form submission of the checkout / payment form. * * 1. Logs in or Registers a user * 2. Validates all fields * 3. Handles coupon pricing adjustments * 4. Creates a PENDING llms_order * * If errors, returns error on screen to user * If success, passes to the selected gateways "process_payment" method * the process_payment method should complete by returning an error or * triggering the "lifterlms_process_payment_redirect" // Todo check this last statement. * * @since 3.0.0 * @since 3.27.0 Unknown. * @since 3.35.0 Sanitize ` $_POST ` data. * @since 5.0.0 Build customer data using LLMS_Forms fields information. * @since 5.0.1 Delegate sanitization of user information fields of the ` $_POST ` to LLMS_Form_Handler::submit(). * @since 5.9.0 Stop using deprecated `FILTER_SANITIZE_STRING`. * @deprecated 7.0.0 Deprecated in favor of {@see LLMS_Controller_Checkout::create_pending_order()}. * |
Expand full source code Collapse full source code View on GitHub
Methods Methods
- __construct — Constructor.
- complete_order — Perform actions on a successful order completion.
- confirm_pending_order — Confirm order form post. — deprecated
- create_pending_order — Handle form submission of the checkout / payment form. — deprecated
- error_order — Called when an order's status changes to refunded, cancelled, expired, or failed.
- expire_access — Handle expiration & cancellation from a course / membership.
- on_delete_order — Called when a post is permanently deleted.
- on_user_enrollment_deleted — Called when an user enrollment is deleted.
- pending_cancel_order — Unschedule recurring payments and schedule access expiration.
- recurring_charge — Trigger a recurring payment.
- set_untrash_status — Sets an order's post status to `llms-pending` when untrashing an order.
- switch_payment_source — Handle form submission of the "Update Payment Method" form on the student dashboard when viewing a single order. — deprecated
- transaction_failed — When a transaction fails, update the parent order's status.
- transaction_refunded — When a transaction is refunded, update the parent order's status.
- transaction_succeeded — When a transaction succeeds, update the parent order's status.
- transition_status — Trigger actions when the status of LifterLMS Orders and LifterLMS Transactions change status.
- validate_selected_gateway — Validate a gateway can be used to process the current action / transaction.
Changelog Changelog
Version | Description |
---|---|
5.0.0 | Build customer data using LLMS_Forms fields information. |
4.2.0 | Added logic to set the order status to 'cancelled' when an enrollment linked to an order is deleted. Also llms_unenroll_on_error_order fiter hook added. |
3.36.1 | In recurring_charge() , made sure to process only proper LLMS_Orders of existing users. |
3.34.5 | Fixed logic error in llms_order_can_be_confirmed conditional. |
3.34.4 | Added filter llms_order_can_be_confirmed . |
3.33.0 | Added logic to delete any enrollment records linked to an LLMS_Order on its permanent deletion. |
3.0.0 | Introduced. |