Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
68.29% |
28 / 41 |
|
50.00% |
2 / 4 |
CRAP | |
0.00% |
0 / 1 |
Background_Jobs | |
68.29% |
28 / 41 |
|
50.00% |
2 / 4 |
10.04 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
check_unpaid_order | |
68.57% |
24 / 35 |
|
0.00% |
0 / 1 |
5.78 | |||
generate_new_addresses | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
check_new_addresses_for_transactions | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * After five minutes check the unpaid order for payments. |
4 | * - TODO After x unpaid time, mark unpaid orders as failed/cancelled. |
5 | * When the fresh address list falls below the cache threshold, generate new addresses. |
6 | * |
7 | * @package brianhenryie/bh-wp-bitcoin-gateway |
8 | */ |
9 | |
10 | namespace BrianHenryIE\WP_Bitcoin_Gateway\Action_Scheduler; |
11 | |
12 | use ActionScheduler; |
13 | use Exception; |
14 | use BrianHenryIE\WP_Bitcoin_Gateway\API_Interface; |
15 | use Psr\Log\LoggerAwareTrait; |
16 | use Psr\Log\LoggerInterface; |
17 | use WC_Order; |
18 | |
19 | /** |
20 | * Handles do_action initiated from Action Scheduler. |
21 | */ |
22 | class Background_Jobs { |
23 | use LoggerAwareTrait; |
24 | |
25 | const CHECK_UNPAID_ORDER_HOOK = 'bh_wp_bitcoin_gateway_check_unpaid_order'; |
26 | const GENERATE_NEW_ADDRESSES_HOOK = 'bh_wp_bitcoin_gateway_generate_new_addresses'; |
27 | const CHECK_NEW_ADDRESSES_TRANSACTIONS_HOOK = 'bh_wp_bitcoin_gateway_check_new_addresses_transactions'; |
28 | |
29 | /** |
30 | * Main class for carrying out the jobs. |
31 | * |
32 | * @var API_Interface |
33 | */ |
34 | protected API_Interface $api; |
35 | |
36 | /** |
37 | * Constructor |
38 | * |
39 | * @param API_Interface $api Main plugin class. |
40 | * @param LoggerInterface $logger PSR logger. |
41 | */ |
42 | public function __construct( API_Interface $api, LoggerInterface $logger ) { |
43 | $this->setLogger( $logger ); |
44 | $this->api = $api; |
45 | } |
46 | |
47 | /** |
48 | * Query a Blockchain API for updates to the order. If the order is still awaiting payment, schedule another job |
49 | * to check again soon. |
50 | * |
51 | * @hooked bh_wp_bitcoin_gateway_check_unpaid_order |
52 | * @see self::CHECK_UNPAID_ORDER_HOOK |
53 | * |
54 | * @param int $order_id WooCommerce order id to check. |
55 | */ |
56 | public function check_unpaid_order( int $order_id ): void { |
57 | |
58 | $context = array(); |
59 | |
60 | // How to find the action_id of the action currently being run? |
61 | $query = array( |
62 | 'hook' => self::CHECK_UNPAID_ORDER_HOOK, |
63 | 'args' => array( 'order_id' => $order_id ), |
64 | ); |
65 | |
66 | $context['query'] = $query; |
67 | |
68 | $action_id = ActionScheduler::store()->query_action( $query ); |
69 | $claim_id = ActionScheduler::store()->get_claim_id( $action_id ); |
70 | |
71 | $context['order_id'] = $order_id; |
72 | $context['task'] = $query; |
73 | $context['action_id'] = $action_id; |
74 | $context['claim_id'] = $claim_id; |
75 | |
76 | $this->logger->debug( |
77 | "Running check_unpaid_order background task for `shop_order:{$order_id}` action id: {$action_id}, claim id: {$claim_id}", |
78 | $context |
79 | ); |
80 | |
81 | $order = wc_get_order( $order_id ); |
82 | |
83 | if ( ! ( $order instanceof WC_Order ) ) { |
84 | $this->logger->error( 'Invalid order id ' . $order_id . ' passed to check_unpaid_order() background job', array( 'order_id' => $order_id ) ); |
85 | return; |
86 | } |
87 | |
88 | if ( in_array( $order->get_status(), wc_get_is_paid_statuses(), true ) ) { |
89 | $this->logger->info( "`shop_order:{$order_id}` already paid, status: {$order->get_status()}.", array( 'order_id' => $order_id ) ); |
90 | |
91 | add_action( |
92 | 'action_scheduler_after_process_queue', |
93 | function () use ( $query, $action_id, $order ) { |
94 | $this->logger->info( "Cancellilng future update checks for `shop_order:{$order->get_id()}`, status: {$order->get_status()}." ); |
95 | try { |
96 | as_unschedule_all_actions( $query['hook'], $query['args'] ); |
97 | } catch ( \InvalidArgumentException $exception ) { |
98 | $this->logger->error( "Failed to as_unschedule_all_actions for action {$action_id}", array( 'exception' => $exception ) ); |
99 | } |
100 | } |
101 | ); |
102 | return; |
103 | } |
104 | |
105 | try { |
106 | $result = $this->api->get_order_details( $order ); |
107 | } catch ( Exception $exception ) { |
108 | |
109 | // 403. |
110 | // TODO: Log better. |
111 | $this->logger->error( 'Error getting details for `shop_order:' . $order_id . '`', array( 'order_id' => $order_id ) ); |
112 | } |
113 | } |
114 | |
115 | |
116 | /** |
117 | * When available addresses fall below a threshold, more are generated on a background job. |
118 | * |
119 | * @hooked bh_wp_bitcoin_gateway_generate_new_addresses |
120 | * @see self::GENERATE_NEW_ADDRESSES_HOOK |
121 | */ |
122 | public function generate_new_addresses(): void { |
123 | |
124 | $this->logger->debug( 'Starting generate_new_addresses() background job.' ); |
125 | |
126 | $result = $this->api->generate_new_addresses(); |
127 | } |
128 | |
129 | |
130 | /** |
131 | * After new addresses have been created, we check to see are they fresh/available to use. |
132 | * TODO It's not unlikely we'll hit 429 rate limits during this, so we'll loop through as many as we can, |
133 | * then schedule a new job when we're told to stop. |
134 | * |
135 | * @hooked bh_wp_bitcoin_gateway_check_new_addresses_transactions |
136 | * @see self::CHECK_NEW_ADDRESSES_TRANSACTIONS_HOOK |
137 | */ |
138 | public function check_new_addresses_for_transactions(): void { |
139 | |
140 | $this->logger->debug( 'Starting check_new_addresses_for_transactions() background job.' ); |
141 | |
142 | $result = $this->api->check_new_addresses_for_transactions(); |
143 | } |
144 | } |