class.llms.gateway.manual.php 6.91 KB
Newer Older
cyrille's avatar
cyrille committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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
<?php
/**
 * Manual Payment Gateway Class
 *
 * @package LifterLMS/Classes
 *
 * @since 3.0.0
 * @version 3.30.3
 */

defined( 'ABSPATH' ) || exit;

/**
 * Manual Payment Gateway Class
 *
 * @since 3.0.0
 * @since 3.30.3 Explicitly define class properties.
 */
class LLMS_Payment_Gateway_Manual extends LLMS_Payment_Gateway {

	/**
	 * @var string
	 * @since 3.0.0
	 */
	public $payment_instructions;

	/**
	 * Constructor
	 *
	 * @return  void
	 * @since   3.0.0
	 * @version 3.10.0
	 */
	public function __construct() {

		$this->id                   = 'manual';
		$this->admin_description    = __( 'Collect manual or offline payments. Also handles any free orders during checkout.', 'lifterlms' );
		$this->admin_title          = __( 'Manual', 'lifterlms' );
		$this->title                = __( 'Manual', 'lifterlms' );
		$this->description          = __( 'Pay manually via check', 'lifterlms' );
		$this->payment_instructions = ''; // Fields.

		$this->supports = array(
			'checkout_fields'    => false,
			'refunds'            => false, // Manual refunds are available always for all gateways and are not handled by this class.
			'single_payments'    => true,
			'recurring_payments' => true,
			'test_mode'          => false,
		);

		add_filter( 'llms_get_gateway_settings_fields', array( $this, 'get_settings_fields' ), 10, 2 );
		add_action( 'lifterlms_before_view_order_table', array( $this, 'before_view_order_table' ) );

	}

	/**
	 * Output payment instructions if the order is pending
	 *
	 * @return   void
	 * @since    3.0.0
	 * @version  3.10.0
	 */
	public function before_view_order_table() {

		global $wp;

		if ( ! empty( $wp->query_vars['orders'] ) ) {

			$order = new LLMS_Order( intval( $wp->query_vars['orders'] ) );

			if ( 'manual' === $order->get( 'payment_gateway' ) && in_array( $order->get( 'status' ), array( 'llms-pending', 'llms-on-hold' ) ) ) {

				echo $this->get_payment_instructions();

			}
		}

	}

	/**
	 * Get fields displayed on the checkout form
	 *
	 * @return   string
	 * @since    3.0.0
	 * @version  3.7.5
	 */
	public function get_payment_instructions() {
		$opt = $this->get_option( 'payment_instructions' );
		if ( $opt ) {
			$fields = '<div class="llms-notice llms-info"><h3>' . esc_html__( 'Payment Instructions', 'lifterlms' ) . '</h3>' . wpautop( wptexturize( wp_kses_post( $opt ) ) ) . '</div>';
		} else {
			$fields = '';
		}
		return apply_filters( 'llms_get_payment_instructions', $fields, $this->id );
	}

	/**
	 * Get admin setting fields
	 *
	 * @param    array  $fields      default fields
	 * @param    string $gateway_id  gateway ID
	 * @return   array
	 * @since    3.0.0
	 * @version  3.0.0
	 */
	public function get_settings_fields( $fields, $gateway_id ) {

		if ( $this->id !== $gateway_id ) {
			return $fields;
		}

		$fields[] = array(
			'id'    => $this->get_option_name( 'payment_instructions' ),
			'desc'  => '<br>' . __( 'Displayed to the user when this gateway is selected during checkout. Add information here instructing the student on how to send payment.', 'lifterlms' ),
			'title' => __( 'Payment Instructions', 'lifterlms' ),
			'type'  => 'textarea',
		);

		return $fields;

	}

	/**
	 * Called when the Update Payment Method form is submitted from a single order view on the student dashboard
	 *
	 * Gateways should do whatever the gateway needs to do to validate the new payment method and save it to the order
	 * so that future payments on the order will use this new source
	 *
	 * @param    obj   $order      Instance of the LLMS_Order
	 * @param    array $form_data  Additional data passed from the submitted form (EG $_POST)
	 * @return   void
	 * @since    3.10.0
	 * @version  3.10.0
	 */
	public function handle_payment_source_switch( $order, $form_data = array() ) {

		$previous_gateway = $order->get( 'payment_gateway' );

		if ( $this->get_id() === $previous_gateway ) {
			return;
		}

		$order->set( 'payment_gateway', $this->get_id() );
		$order->set( 'gateway_customer_id', '' );
		$order->set( 'gateway_source_id', '' );
		$order->set( 'gateway_subscription_id', '' );

		$order->add_note( sprintf( __( 'Payment method switched from "%1$s" to "%2$s"', 'lifterlms' ), $previous_gateway, $this->get_admin_title() ) );

	}

	/**
	 * Handle a Pending Order
	 * Called by LLMS_Controller_Orders->create_pending_order() on checkout form submission
	 * All data will be validated before it's passed to this function
	 *
	 * @param   obj       $order   Instance LLMS_Order for the order being processed
	 * @param   obj       $plan    Instance LLMS_Access_Plan for the order being processed
	 * @param   obj       $person  Instance of LLMS_Student for the purchasing customer
	 * @param   obj|false $coupon  Instance of LLMS_Coupon applied to the order being processed, or false when none is being used
	 * @return  void
	 * @since   3.0.0
	 * @version 3.10.0
	 */
	public function handle_pending_order( $order, $plan, $person, $coupon = false ) {

		// No payment (free orders).
		if ( floatval( 0 ) === $order->get_initial_price( array(), 'float' ) ) {

			// Free access plans do not generate receipts.
			if ( $plan->is_free() ) {

				$order->set( 'status', 'llms-completed' );

				// Free trial, reduced to free via coupon, etc....
				// We do want to record a transaction and then generate a receipt.
			} else {

				// Record a $0.00 transaction to ensure a receipt is sent.
				$order->record_transaction(
					array(
						'amount'             => floatval( 0 ),
						'source_description' => __( 'Free', 'lifterlms' ),
						'transaction_id'     => uniqid(),
						'status'             => 'llms-txn-succeeded',
						'payment_gateway'    => 'manual',
						'payment_type'       => 'single',
					)
				);

			}

			$this->complete_transaction( $order );

			// Payment due.
		} else {

			/**
			 * @hooked LLMS_Notification: manual_payment_due - 10
			 */
			do_action( 'llms_manual_payment_due', $order, $this );

			// Show the user payment instructions for the order.
			do_action( 'lifterlms_handle_pending_order_complete', $order );
			wp_redirect( $order->get_view_link() );
			exit;

		}

	}

	/**
	 * Called by scheduled actions to charge an order for a scheduled recurring transaction
	 * This function must be defined by gateways which support recurring transactions
	 *
	 * @param    obj $order   Instance LLMS_Order for the order being processed
	 * @return   mixed
	 * @since    3.10.0
	 * @version  3.10.0
	 */
	public function handle_recurring_transaction( $order ) {

		// Switch to order on hold if it's a paid order.
		if ( $order->get_price( 'total', array(), 'float' ) > 0 ) {

			// Update status.
			$order->set_status( 'on-hold' );

			/**
			 * @hooked LLMS_Notification: manual_payment_due - 10
			 */
			do_action( 'llms_manual_payment_due', $order, $this );

		}

	}

	/**
	 * Determine if the gateway is enabled according to admin settings checkbox
	 *
	 * @return   boolean
	 * @since    3.0.0
	 * @version  3.0.0
	 */
	public function is_enabled() {
		return ( 'yes' === $this->get_enabled() ) ? true : false;
	}


}