Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
89.19% covered (warning)
89.19%
33 / 37
33.33% covered (danger)
33.33%
1 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
Order
89.19% covered (warning)
89.19%
33 / 37
33.33% covered (danger)
33.33%
1 / 3
10.13
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 schedule_check_for_transactions
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
4
 unschedule_check_for_transactions
91.67% covered (success)
91.67%
22 / 24
0.00% covered (danger)
0.00%
0 / 1
5.01
1<?php
2/**
3 * Constants for order meta keys.
4 *
5 * @package    brianhenryie/bh-wp-bitcoin-gateway
6 */
7
8namespace BrianHenryIE\WP_Bitcoin_Gateway\WooCommerce;
9
10use ActionScheduler;
11use BrianHenryIE\WP_Bitcoin_Gateway\Action_Scheduler\Background_Jobs;
12use BrianHenryIE\WP_Bitcoin_Gateway\API\Addresses\Bitcoin_Wallet;
13use BrianHenryIE\WP_Bitcoin_Gateway\API\Model\Bitcoin_Order;
14use BrianHenryIE\WP_Bitcoin_Gateway\API_Interface;
15use Psr\Log\LoggerAwareTrait;
16use Psr\Log\LoggerInterface;
17use WC_Order;
18
19/**
20 * Defines constants for metakeys.
21 * Handles order status change events, to schedule/unschedule background tasks.
22 */
23class Order {
24    use LoggerAwareTrait;
25
26    /**
27     * Used to check is the gateway a Bitcoin gateway.
28     */
29    protected API_Interface $api;
30
31    const BITCOIN_ADDRESS_META_KEY = 'bh_wp_bitcoin_gateway_address';
32
33    const EXCHANGE_RATE_AT_TIME_OF_PURCHASE_META_KEY = 'bh_wp_bitcoin_gateway_exchange_rate_at_time_of_purchase';
34
35    const ORDER_TOTAL_BITCOIN_AT_TIME_OF_PURCHASE_META_KEY = 'bh_wp_bitcoin_gateway_bitcoin_total_at_time_of_purchase';
36
37    const BITCOIN_AMOUNT_RECEIVED_META_KEY = 'bh_wp_bitcoin_gateway_bitcoin_amount_received';
38
39    const LAST_CHECKED_META_KEY = 'bh_wp_bitcoin_gateway_last_checked_time';
40
41    /**
42     * Constructor.
43     *
44     * @param API_Interface   $api The main plugin functions.
45     * @param LoggerInterface $logger A PSR logger.
46     */
47    public function __construct( API_Interface $api, LoggerInterface $logger ) {
48        $this->setLogger( $logger );
49        $this->api = $api;
50    }
51
52    /**
53     * When an order's status is set to "on-hold", schedule a background job to check for payments.
54     *
55     * @hooked woocommerce_order_status_changed
56     * @see WC_Order::status_transition()
57     *
58     * @param int    $order_id The id of the order whose status has changed.
59     * @param string $status_from The old status.
60     * @param string $status_to The new status.
61     */
62    public function schedule_check_for_transactions( int $order_id, string $status_from, string $status_to ): void {
63
64        if ( 'on-hold' !== $status_to ) {
65            return;
66        }
67
68        if ( ! $this->api->is_order_has_bitcoin_gateway( $order_id ) ) {
69            return;
70        }
71
72        // Schedule background check for payment.
73        $hook = Background_Jobs::CHECK_UNPAID_ORDER_HOOK;
74        $args = array( 'order_id' => $order_id );
75
76        if ( ! as_has_scheduled_action( $hook, $args ) ) {
77            $timestamp         = time() + ( 10 * MINUTE_IN_SECONDS );
78            $recurring_seconds = ( 10 * MINUTE_IN_SECONDS );
79            $this->logger->debug( "New order created, `shop_order:{$order_id}`, scheduling background job to check for payments" );
80            as_schedule_recurring_action( $timestamp, $recurring_seconds, $hook, $args );
81        }
82    }
83
84    /**
85     * When an order's status changes away from "pending" and "on-hold", cancel the scheduled background.
86     *
87     * E.g. when the order is paid or canceled.
88     *
89     * @hooked woocommerce_order_status_changed
90     * @see WC_Order::status_transition()
91     *
92     * @param int    $order_id The id of the order whose status has changed.
93     * @param string $status_from The old status.
94     * @param string $status_to The new status.
95     */
96    public function unschedule_check_for_transactions( int $order_id, string $status_from, string $status_to ): void {
97
98        if ( in_array( $status_to, array( 'pending', 'on-hold' ), true ) ) {
99            return;
100        }
101
102        if ( ! $this->api->is_order_has_bitcoin_gateway( $order_id ) ) {
103            return;
104        }
105
106        if ( empty( $status_to ) ) {
107            $status_to = 'trash?';
108        }
109
110        $context = array(
111            'order_id'    => $order_id,
112            'status_from' => $status_from,
113            'status_to'   => $status_to,
114        );
115
116        $hook  = Background_Jobs::CHECK_UNPAID_ORDER_HOOK;
117        $args  = array( 'order_id' => $order_id );
118        $query = array(
119            'hook' => $hook,
120            'args' => $args,
121        );
122
123        $context['action_scheduler_query'] = $query;
124
125        $actions = as_get_scheduled_actions( $query );
126        if ( ! empty( $actions ) ) {
127            $action_id = array_key_first( $actions );
128            $this->logger->debug( "`shop_order:{$order_id}` status changed from $status_from to $status_to, running `as_unschedule_all_actions` for check_unpaid_order job, action_id $action_id.", $context );
129            as_unschedule_all_actions( $hook, $args );
130        } else {
131            $this->logger->debug( "`shop_order:{$order_id}` status changed from $status_from to $status_to. No check_unpaid_order background job present to cancel.", $context );
132        }
133    }
134}