1 | <?php |
||
2 | /** |
||
3 | * CLI |
||
4 | * |
||
5 | * @author Pronamic <[email protected]> |
||
6 | * @copyright 2005-2022 Pronamic |
||
7 | * @license GPL-3.0-or-later |
||
8 | * @package Pronamic\WordPress\Pay\Mollie |
||
9 | */ |
||
10 | |||
11 | namespace Pronamic\WordPress\Pay\Gateways\Mollie; |
||
12 | |||
13 | /** |
||
14 | * Title: CLI |
||
15 | * Description: |
||
16 | * Copyright: 2005-2022 Pronamic |
||
17 | * Company: Pronamic |
||
18 | * |
||
19 | * @author Remco Tolsma |
||
20 | * @version 2.1.0 |
||
21 | * @since 2.1.0 |
||
22 | * @link https://github.com/woocommerce/woocommerce/blob/3.9.0/includes/class-wc-cli.php |
||
23 | */ |
||
24 | class CLI { |
||
25 | /** |
||
26 | * Customer data store. |
||
27 | * |
||
28 | * @var CustomerDataStore |
||
29 | */ |
||
30 | protected $customer_data_store; |
||
31 | |||
32 | /** |
||
33 | * Profile data store. |
||
34 | * |
||
35 | * @var ProfileDataStore |
||
36 | */ |
||
37 | protected $profile_data_store; |
||
38 | |||
39 | /** |
||
40 | * Construct CLI. |
||
41 | */ |
||
42 | public function __construct() { |
||
43 | \WP_CLI::add_command( |
||
44 | 'pronamic-pay mollie organizations synchronize', |
||
45 | function( $args, $assoc_args ) { |
||
46 | $this->wp_cli_organizations_synchronize( $args, $assoc_args ); |
||
47 | }, |
||
48 | array( |
||
49 | 'shortdesc' => 'Synchronize Mollie organizations to WordPress (not implemented yet).', |
||
50 | ) |
||
51 | ); |
||
52 | |||
53 | \WP_CLI::add_command( |
||
54 | 'pronamic-pay mollie customers synchronize', |
||
55 | function( $args, $assoc_args ) { |
||
56 | $this->wp_cli_customers_synchronize( $args, $assoc_args ); |
||
57 | }, |
||
58 | array( |
||
59 | 'shortdesc' => 'Synchronize Mollie customers to WordPress.', |
||
60 | ) |
||
61 | ); |
||
62 | |||
63 | \WP_CLI::add_command( |
||
64 | 'pronamic-pay mollie customers connect-wp-users', |
||
65 | function( $args, $assoc_args ) { |
||
66 | $this->wp_cli_customers_connect_wp_users( $args, $assoc_args ); |
||
67 | }, |
||
68 | array( |
||
69 | 'shortdesc' => 'Connect Mollie customers to WordPress users by email.', |
||
70 | ) |
||
71 | ); |
||
72 | |||
73 | \WP_CLI::add_command( |
||
74 | 'pronamic-pay mollie payments list', |
||
75 | function( $args, $assoc_args ) { |
||
76 | $this->wp_cli_payments( $args, $assoc_args ); |
||
77 | }, |
||
78 | array( |
||
79 | 'shortdesc' => 'Mollie payments.', |
||
80 | ) |
||
81 | ); |
||
82 | |||
83 | \WP_CLI::add_command( |
||
84 | 'pronamic-pay mollie payments cancel', |
||
85 | function( $args, $assoc_args ) { |
||
86 | $this->wp_cli_payments_cancel( $args, $assoc_args ); |
||
87 | }, |
||
88 | array( |
||
89 | 'shortdesc' => 'Cancel Mollie payments.', |
||
90 | ) |
||
91 | ); |
||
92 | |||
93 | // Data Stores. |
||
94 | $this->profile_data_store = new ProfileDataStore(); |
||
95 | $this->customer_data_store = new CustomerDataStore(); |
||
96 | } |
||
97 | |||
98 | /** |
||
99 | * CLI organizations synchronize. |
||
100 | * |
||
101 | * @link https://docs.mollie.com/reference/v2/organizations-api/current-organization |
||
102 | * @param array<string> $args Arguments. |
||
103 | * @param array<string> $assoc_args Associative arguments. |
||
104 | * @return void |
||
105 | */ |
||
106 | public function wp_cli_organizations_synchronize( $args, $assoc_args ) { |
||
107 | \WP_CLI::error( 'Command not implemented yet.' ); |
||
108 | } |
||
109 | |||
110 | /** |
||
111 | * CLI customers synchronize. |
||
112 | * |
||
113 | * @link https://docs.mollie.com/reference/v2/customers-api/list-customers |
||
114 | * @param array<string> $args Arguments. |
||
115 | * @param array<string> $assoc_args Associative arguments. |
||
116 | * @return void |
||
117 | */ |
||
118 | public function wp_cli_customers_synchronize( $args, $assoc_args ) { |
||
119 | global $post; |
||
120 | global $wpdb; |
||
121 | |||
122 | $query = new \WP_Query( |
||
123 | array( |
||
124 | 'post_type' => 'pronamic_gateway', |
||
125 | 'post_status' => 'publish', |
||
126 | 'nopaging' => true, |
||
127 | // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Slow query allowed on CLI. |
||
128 | 'meta_query' => array( |
||
129 | array( |
||
130 | 'key' => '_pronamic_gateway_id', |
||
131 | 'value' => 'mollie', |
||
132 | ), |
||
133 | array( |
||
134 | 'key' => '_pronamic_gateway_mollie_api_key', |
||
135 | 'compare' => 'EXISTS', |
||
136 | ), |
||
137 | ), |
||
138 | ) |
||
139 | ); |
||
140 | |||
141 | if ( $query->have_posts() ) { |
||
142 | while ( $query->have_posts() ) { |
||
143 | $query->the_post(); |
||
144 | |||
145 | $api_key = get_post_meta( $post->ID, '_pronamic_gateway_mollie_api_key', true ); |
||
146 | |||
147 | \WP_CLI::log( $post->post_title ); |
||
148 | \WP_CLI::log( $api_key ); |
||
149 | \WP_CLI::log( '' ); |
||
150 | |||
151 | $client = new Client( $api_key ); |
||
152 | |||
153 | $urls = array( |
||
154 | 'https://api.mollie.com/v2/customers?limit=250', |
||
155 | ); |
||
156 | |||
157 | $profile = Profile::from_object( $client->get_current_profile() ); |
||
158 | |||
159 | $profile_id = $this->profile_data_store->save_profile( |
||
160 | $profile, |
||
161 | array( |
||
162 | 'api_key_live' => ( 'live_' === substr( $api_key, 0, 5 ) ) ? $api_key : null, |
||
163 | 'api_key_test' => ( 'test_' === substr( $api_key, 0, 5 ) ) ? $api_key : null, |
||
164 | ), |
||
165 | array( |
||
166 | 'api_key_live' => '%s', |
||
167 | 'api_key_test' => '%s', |
||
168 | ) |
||
169 | ); |
||
170 | |||
171 | while ( ! empty( $urls ) ) { |
||
172 | $url = (string) array_shift( $urls ); |
||
173 | |||
174 | \WP_CLI::log( $url ); |
||
175 | |||
176 | $response = $client->send_request( $url ); |
||
177 | |||
178 | if ( isset( $response->count ) ) { |
||
179 | \WP_CLI::log( |
||
180 | \sprintf( |
||
181 | 'Found %d customer(s).', |
||
182 | $response->count |
||
183 | ) |
||
184 | ); |
||
185 | } |
||
186 | |||
187 | if ( \property_exists( $response, '_embedded' ) && isset( $response->_embedded->customers ) ) { |
||
188 | \WP_CLI\Utils\format_items( |
||
189 | 'table', |
||
190 | $response->_embedded->customers, |
||
191 | array( |
||
192 | 'id', |
||
193 | 'mode', |
||
194 | 'name', |
||
195 | 'email', |
||
196 | 'locale', |
||
197 | ) |
||
198 | ); |
||
199 | |||
200 | foreach ( $response->_embedded->customers as $object ) { |
||
201 | $customer = Customer::from_object( $object ); |
||
202 | |||
203 | $customer_id = $this->customer_data_store->save_customer( |
||
204 | $customer, |
||
205 | array( |
||
206 | 'profile_id' => $profile_id, |
||
207 | ), |
||
208 | array( |
||
209 | 'profile_id' => '%d', |
||
210 | ) |
||
211 | ); |
||
212 | } |
||
213 | } |
||
214 | |||
215 | if ( \property_exists( $response, '_links' ) && isset( $response->_links->next->href ) ) { |
||
216 | $urls[] = $response->_links->next->href; |
||
217 | } |
||
218 | } |
||
219 | } |
||
220 | |||
221 | \wp_reset_postdata(); |
||
222 | } |
||
223 | } |
||
224 | |||
225 | /** |
||
226 | * CLI connect Mollie customers to WordPress users. |
||
227 | * |
||
228 | * @link https://docs.mollie.com/reference/v2/customers-api/list-customers |
||
229 | * @link https://make.wordpress.org/cli/handbook/internal-api/wp-cli-add-command/ |
||
230 | * @link https://developer.wordpress.org/reference/classes/wpdb/query/ |
||
231 | * @param array<string> $args Arguments. |
||
232 | * @param array<string> $assoc_args Associative arguments. |
||
233 | * @return void |
||
234 | */ |
||
235 | public function wp_cli_customers_connect_wp_users( $args, $assoc_args ) { |
||
236 | global $wpdb; |
||
237 | |||
238 | $query = " |
||
239 | INSERT IGNORE INTO $wpdb->pronamic_pay_mollie_customer_users ( |
||
240 | customer_id, |
||
241 | user_id |
||
242 | ) |
||
243 | SELECT |
||
244 | mollie_customer.id AS mollie_customer_id, |
||
245 | wp_user.ID AS wp_user_id |
||
246 | FROM |
||
247 | $wpdb->pronamic_pay_mollie_customers AS mollie_customer |
||
248 | INNER JOIN |
||
249 | $wpdb->users AS wp_user |
||
250 | ON mollie_customer.email = wp_user.user_email |
||
251 | ; |
||
252 | "; |
||
253 | |||
254 | // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Prepare is OK. |
||
255 | $result = $wpdb->query( $query ); |
||
256 | |||
257 | if ( false === $result ) { |
||
258 | \WP_CLI::error( |
||
259 | sprintf( |
||
260 | 'Database error: %s.', |
||
261 | $wpdb->last_error |
||
262 | ) |
||
263 | ); |
||
264 | } |
||
265 | |||
266 | \WP_CLI::log( |
||
267 | sprintf( |
||
268 | 'Connected %d users and Mollie customers.', |
||
269 | $result |
||
270 | ) |
||
271 | ); |
||
272 | } |
||
273 | |||
274 | /** |
||
275 | * CLI Mollie payments. |
||
276 | * |
||
277 | * @param array<string> $args Arguments. |
||
278 | * @param array<string> $assoc_args Associative arguments. |
||
279 | * @return void |
||
280 | */ |
||
281 | public function wp_cli_payments( $args, $assoc_args ) { |
||
282 | $assoc_args = \wp_parse_args( |
||
283 | $assoc_args, |
||
284 | array( |
||
285 | 'api_key' => null, |
||
286 | 'api_url' => 'https://api.mollie.com/v2/payments', |
||
287 | 'from' => null, |
||
288 | 'limit' => 250, |
||
289 | 'format' => 'table', |
||
290 | ) |
||
291 | ); |
||
292 | |||
293 | $api_key = $assoc_args['api_key']; |
||
294 | $api_url = $assoc_args['api_url']; |
||
295 | $from = $assoc_args['from']; |
||
296 | $limit = $assoc_args['limit']; |
||
297 | $format = $assoc_args['format']; |
||
298 | |||
299 | if ( empty( $api_key ) ) { |
||
300 | \WP_CLI::error( 'This command requires an API key for authentication' ); |
||
301 | |||
302 | return; |
||
303 | } |
||
304 | |||
305 | $client = new Client( $api_key ); |
||
306 | |||
307 | $payments = array(); |
||
308 | |||
309 | $api_url = $assoc_args['api_url']; |
||
310 | |||
311 | if ( null !== $limit ) { |
||
312 | $api_url = \add_query_arg( 'limit', $limit, $api_url ); |
||
313 | } |
||
314 | |||
315 | if ( null !== $from ) { |
||
316 | $api_url = \add_query_arg( 'from', $from, $api_url ); |
||
317 | } |
||
318 | |||
319 | $response = $client->send_request( $api_url ); |
||
320 | |||
321 | if ( \property_exists( $response, '_embedded' ) && isset( $response->_embedded->payments ) ) { |
||
322 | foreach ( $response->_embedded->payments as $object ) { |
||
323 | $payments[] = $object; |
||
324 | } |
||
325 | } |
||
326 | |||
327 | $is_cancelable = \WP_CLI\Utils\get_flag_value( $assoc_args, 'is_cancelable' ); |
||
328 | |||
329 | if ( null !== $is_cancelable ) { |
||
330 | $payments = \array_filter( |
||
331 | $payments, |
||
332 | function( $payment ) { |
||
333 | if ( ! \property_exists( $payment, 'isCancelable' ) ) { |
||
334 | return false; |
||
335 | } |
||
336 | |||
337 | // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase -- Mollie name. |
||
338 | return $payment->isCancelable; |
||
339 | } |
||
340 | ); |
||
341 | } |
||
342 | |||
343 | $data = $payments; |
||
344 | |||
345 | if ( 'ids' === $format ) { |
||
346 | $data = \wp_list_pluck( $payments, 'id' ); |
||
347 | } |
||
348 | |||
349 | if ( empty( $data ) ) { |
||
350 | if ( \property_exists( $response, '_links' ) && isset( $response->_links->next->href ) ) { |
||
351 | \WP_CLI::log( |
||
352 | \sprintf( |
||
353 | 'Number Payments: %s, Number Filtered Payments: %s, API URL: %s.', |
||
354 | \count( $response->_embedded->payments ), |
||
355 | \count( $payments ), |
||
356 | $api_url |
||
357 | ) |
||
358 | ); |
||
359 | |||
360 | $automatic = \WP_CLI\Utils\get_flag_value( $assoc_args, 'automatic' ); |
||
361 | |||
362 | if ( true == $automatic ) { |
||
363 | $new_assoc_args = $assoc_args; |
||
364 | |||
365 | $new_assoc_args['api_url'] = $response->_links->next->href; |
||
366 | |||
367 | $this->wp_cli_payments( $args, $new_assoc_args ); |
||
368 | } |
||
369 | |||
370 | return; |
||
371 | } |
||
372 | } |
||
373 | |||
374 | \WP_CLI\Utils\format_items( |
||
375 | $format, |
||
376 | $data, |
||
377 | array( |
||
378 | 'id', |
||
379 | 'createdAt', |
||
380 | 'mode', |
||
381 | 'description', |
||
382 | 'method', |
||
383 | ) |
||
384 | ); |
||
385 | } |
||
386 | |||
387 | /** |
||
388 | * CLI cancel Mollie payments. |
||
389 | * |
||
390 | * @link https://docs.mollie.com/reference/v2/payments-api/list-payments |
||
391 | * @link https://make.wordpress.org/cli/handbook/internal-api/wp-cli-add-command/ |
||
392 | * @link https://developer.wordpress.org/reference/classes/wpdb/query/ |
||
393 | * @param array<string> $args Arguments. |
||
394 | * @param array<string> $assoc_args Associative arguments. |
||
395 | * @return void |
||
396 | */ |
||
397 | public function wp_cli_payments_cancel( $args, $assoc_args ) { |
||
398 | $assoc_args = \wp_parse_args( |
||
399 | $assoc_args, |
||
400 | array( |
||
401 | 'api_key' => null, |
||
402 | ) |
||
403 | ); |
||
404 | |||
405 | $api_key = $assoc_args['api_key']; |
||
406 | |||
407 | if ( empty( $api_key ) ) { |
||
408 | \WP_CLI::error( 'This command requires an API key for authentication' ); |
||
409 | |||
410 | return; |
||
411 | } |
||
412 | |||
413 | $client = new Client( $api_key ); |
||
414 | |||
415 | foreach ( $args as $id ) { |
||
416 | \WP_CLI::log( |
||
417 | \sprintf( |
||
418 | 'Try to cancel payment `%s`…', |
||
419 | $id |
||
420 | ) |
||
421 | ); |
||
422 | |||
423 | $url = 'https://api.mollie.com/v2/payments/' . $id; |
||
424 | |||
425 | \WP_CLI::log( |
||
426 | \sprintf( |
||
427 | 'DELETE %s', |
||
428 | $url |
||
429 | ) |
||
430 | ); |
||
431 | |||
432 | $response = $client->send_request( $url, 'DELETE' ); |
||
433 | |||
434 | \WP_CLI::log( |
||
435 | \sprintf( |
||
436 | '- status = %s, createdAt = %s, canceledAt = %s', |
||
437 | $response->status, |
||
438 | // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase -- Mollie name. |
||
439 | $response->createdAt, |
||
440 | // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase -- Mollie name. |
||
441 | $response->canceledAt |
||
442 | ) |
||
443 | ); |
||
444 | |||
445 | \WP_CLI::log( '' ); |
||
446 | } |
||
447 | |||
448 | \WP_CLI::log( '' ); |
||
449 | |||
450 | \WP_CLI::log( 'If you want to cancel the next batch of payments you can run the following command:' ); |
||
451 | |||
452 | \WP_CLI::log( '' ); |
||
453 | |||
454 | \WP_CLI::log( |
||
455 | \sprintf( |
||
456 | 'wp pronamic-pay mollie payments cancel $( wp pronamic-pay mollie payments list --api_key=%s --from=%s --is_cancelable --format=%s ) --api_key=%s', |
||
457 | \escapeshellarg( $api_key ), |
||
458 | \escapeshellarg( $id ), |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
![]() |
|||
459 | \escapeshellarg( 'ids' ), |
||
460 | \escapeshellarg( $api_key ) |
||
461 | ) |
||
462 | ); |
||
463 | } |
||
464 | } |
||
465 |