PluginProbe
WooCommerce / 11.1.0-beta.2
WooCommerce v11.1.0-beta.2
11.1.0 11.1.0-rc.2 11.1.0-rc.1 11.1.0-beta.2 11.1.0-beta.1 11.0.1 11.0.0 11.0.0-rc.3 11.0.0-rc.2 11.0.0-rc.1 11.0.0-beta.2 11.0.0-beta.1 10.9.4 10.9.3 10.9.2 10.9.1 10.9.0 10.9.0-rc.1 10.9.0-beta.2 10.9.0-beta.1 10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 All 648 releases
woocommerce / src / Internal / Admin / Settings / PaymentsRestController.php
PaymentsRestController.php
1,403 lines 51.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 declare( strict_types=1 );
3
4 namespace Automattic\WooCommerce\Internal\Admin\Settings;
5
6 use Automattic\WooCommerce\Internal\RestApiControllerBase;
7 use Automattic\WooCommerce\Internal\Utilities\ArrayUtil;
8 use Exception;
9 use WP_Error;
10 use WP_REST_Request;
11 use WP_REST_Response;
12
13 /**
14 * Controller for the REST endpoints to service the Payments settings page.
15 *
16 * @internal
17 */
18 class PaymentsRestController extends RestApiControllerBase {
19
20 /**
21 * The root namespace for the JSON REST API endpoints.
22 *
23 * @var string
24 */
25 protected string $route_namespace = 'wc-admin';
26
27 /**
28 * Route base.
29 *
30 * @var string
31 */
32 protected string $rest_base = 'settings/payments';
33
34 /**
35 * The payments settings page service.
36 *
37 * @var Payments
38 */
39 private Payments $payments;
40
41 /**
42 * Get the WooCommerce REST API namespace for the class.
43 *
44 * @return string
45 */
46 protected function get_rest_api_namespace(): string {
47 return 'wc-admin-settings-payments';
48 }
49
50 /**
51 * Register the REST API endpoints handled by this controller.
52 *
53 * @param bool $override Whether to override the existing routes. Useful for testing.
54 */
55 public function register_routes( bool $override = false ) {
56 register_rest_route(
57 $this->route_namespace,
58 '/' . $this->rest_base . '/country',
59 array(
60 array(
61 'methods' => \WP_REST_Server::EDITABLE,
62 'callback' => fn( $request ) => $this->run( $request, 'set_country' ),
63 'validation_callback' => 'rest_validate_request_arg',
64 'permission_callback' => fn( $request ) => $this->check_permissions( $request ),
65 'args' => array(
66 'location' => array(
67 'description' => esc_html__( 'The ISO3166 alpha-2 country code to save for the current user.', 'woocommerce' ),
68 'type' => 'string',
69 'pattern' => '[a-zA-Z]{2}', // Two alpha characters.
70 'required' => true,
71 'validate_callback' => fn( $value, $request ) => $this->check_location_arg( $value, $request ),
72 ),
73 ),
74 ),
75 ),
76 $override
77 );
78 register_rest_route(
79 $this->route_namespace,
80 '/' . $this->rest_base . '/providers',
81 array(
82 array(
83 'methods' => \WP_REST_Server::CREATABLE,
84 'callback' => fn( $request ) => $this->run( $request, 'get_providers' ),
85 'validation_callback' => 'rest_validate_request_arg',
86 'permission_callback' => fn( $request ) => $this->check_permissions( $request ),
87 'args' => array(
88 'location' => array(
89 'description' => esc_html__( 'ISO3166 alpha-2 country code. Defaults to WooCommerce\'s base location country.', 'woocommerce' ),
90 'type' => 'string',
91 'pattern' => '[a-zA-Z]{2}', // Two alpha characters.
92 'required' => false,
93 'validate_callback' => fn( $value, $request ) => $this->check_location_arg( $value, $request ),
94 ),
95 ),
96 ),
97 'schema' => fn() => $this->get_schema_for_get_payment_providers(),
98 ),
99 $override
100 );
101 register_rest_route(
102 $this->route_namespace,
103 '/' . $this->rest_base . '/providers/order',
104 array(
105 array(
106 'methods' => \WP_REST_Server::EDITABLE,
107 'callback' => fn( $request ) => $this->run( $request, 'update_providers_order' ),
108 'permission_callback' => fn( $request ) => $this->check_permissions( $request ),
109 'args' => array(
110 'order_map' => array(
111 'description' => esc_html__( 'A map of provider ID to integer values representing the sort order.', 'woocommerce' ),
112 'type' => 'object',
113 'required' => true,
114 'validate_callback' => fn( $value ) => $this->check_providers_order_map_arg( $value ),
115 'sanitize_callback' => fn( $value ) => $this->sanitize_providers_order_arg( $value ),
116 ),
117 ),
118 ),
119 ),
120 $override
121 );
122 register_rest_route(
123 $this->route_namespace,
124 '/' . $this->rest_base . '/suggestion/(?P<id>[\w\d\-]+)/attach',
125 array(
126 array(
127 'methods' => \WP_REST_Server::EDITABLE,
128 'callback' => fn( $request ) => $this->run( $request, 'attach_payment_extension_suggestion' ),
129 'permission_callback' => fn( $request ) => $this->check_permissions( $request ),
130 ),
131 ),
132 $override
133 );
134 register_rest_route(
135 $this->route_namespace,
136 '/' . $this->rest_base . '/suggestion/(?P<id>[\w\d\-]+)/hide',
137 array(
138 array(
139 'methods' => \WP_REST_Server::EDITABLE,
140 'callback' => fn( $request ) => $this->run( $request, 'hide_payment_extension_suggestion' ),
141 'permission_callback' => fn( $request ) => $this->check_permissions( $request ),
142 ),
143 ),
144 $override
145 );
146 register_rest_route(
147 $this->route_namespace,
148 '/' . $this->rest_base . '/suggestion/(?P<suggestion_id>[\w\d\-]+)/incentive/(?P<incentive_id>[\w\d\-]+)/dismiss',
149 array(
150 array(
151 'methods' => \WP_REST_Server::EDITABLE,
152 'callback' => fn( $request ) => $this->run( $request, 'dismiss_payment_extension_suggestion_incentive' ),
153 'permission_callback' => fn( $request ) => $this->check_permissions( $request ),
154 'args' => array(
155 'context' => array(
156 'description' => esc_html__( 'The context ID for which to dismiss the incentive. If not provided, will dismiss the incentive for all contexts.', 'woocommerce' ),
157 'type' => 'string',
158 'required' => false,
159 'sanitize_callback' => 'sanitize_key',
160 ),
161 'do_not_track' => array(
162 'description' => esc_html__( 'If true, the incentive dismissal will be ignored by tracking.', 'woocommerce' ),
163 'type' => 'boolean',
164 'required' => false,
165 'default' => false,
166 'sanitize_callback' => 'rest_sanitize_boolean',
167 ),
168 ),
169 ),
170 ),
171 $override
172 );
173 }
174
175 /**
176 * Initialize the class instance.
177 *
178 * @param Payments $payments The payments settings page service.
179 *
180 * @internal
181 */
182 final public function init( Payments $payments ): void {
183 $this->payments = $payments;
184 }
185
186 /**
187 * Get the payment providers for the given location.
188 *
189 * @param WP_REST_Request $request The request object.
190 * @return WP_Error|WP_REST_Response
191 */
192 protected function get_providers( WP_REST_Request $request ) {
193 $location = $request->get_param( 'location' );
194 if ( empty( $location ) ) {
195 // Fall back to the providers country if no location is provided.
196 $location = $this->payments->get_country();
197 }
198
199 try {
200 $providers = $this->payments->get_payment_providers( $location );
201 } catch ( Exception $e ) {
202 return new WP_Error( 'woocommerce_rest_payment_providers_error', $e->getMessage(), array( 'status' => 500 ) );
203 }
204
205 try {
206 $suggestions = $this->get_extension_suggestions( $location );
207 } catch ( Exception $e ) {
208 return new WP_Error( 'woocommerce_rest_payment_providers_error', $e->getMessage(), array( 'status' => 500 ) );
209 }
210
211 // Separate the offline PMs from the main providers list.
212 $offline_payment_providers = array_values(
213 array_filter(
214 $providers,
215 fn( $provider ) => PaymentsProviders::TYPE_OFFLINE_PM === $provider['_type']
216 )
217 );
218 $providers = array_values(
219 array_filter(
220 $providers,
221 fn( $provider ) => PaymentsProviders::TYPE_OFFLINE_PM !== $provider['_type']
222 )
223 );
224
225 $response = array(
226 'providers' => $providers,
227 'offline_payment_methods' => $offline_payment_providers,
228 'suggestions' => $suggestions,
229 'suggestion_categories' => $this->payments->get_payment_extension_suggestion_categories(),
230 );
231
232 return rest_ensure_response( $this->prepare_payment_providers_response( $response ) );
233 }
234
235 /**
236 * Set the country for the payment providers.
237 *
238 * @param WP_REST_Request $request The request object.
239 *
240 * @return WP_Error|WP_REST_Response
241 */
242 protected function set_country( WP_REST_Request $request ) {
243 $location = $request->get_param( 'location' );
244
245 $result = $this->payments->set_country( $location );
246
247 return rest_ensure_response( array( 'success' => $result ) );
248 }
249
250 /**
251 * Update the payment providers order.
252 *
253 * @param WP_REST_Request $request The request object.
254 *
255 * @return WP_Error|WP_REST_Response
256 */
257 protected function update_providers_order( WP_REST_Request $request ) {
258 $order_map = $request->get_param( 'order_map' );
259
260 $result = $this->payments->update_payment_providers_order_map( $order_map );
261
262 return rest_ensure_response( array( 'success' => $result ) );
263 }
264
265 /**
266 * Attach a payment extension suggestion.
267 *
268 * @param WP_REST_Request $request The request object.
269 *
270 * @return WP_Error|WP_REST_Response
271 */
272 protected function attach_payment_extension_suggestion( WP_REST_Request $request ) {
273 $suggestion_id = $request->get_param( 'id' );
274
275 try {
276 $result = $this->payments->attach_payment_extension_suggestion( $suggestion_id );
277 } catch ( Exception $e ) {
278 return new WP_Error( 'woocommerce_rest_payment_extension_suggestion_error', $e->getMessage(), array( 'status' => 400 ) );
279 }
280
281 return rest_ensure_response( array( 'success' => $result ) );
282 }
283
284 /**
285 * Hide a payment extension suggestion.
286 *
287 * @param WP_REST_Request $request The request object.
288 *
289 * @return WP_Error|WP_REST_Response
290 */
291 protected function hide_payment_extension_suggestion( WP_REST_Request $request ) {
292 $suggestion_id = $request->get_param( 'id' );
293
294 try {
295 $result = $this->payments->hide_payment_extension_suggestion( $suggestion_id );
296 } catch ( Exception $e ) {
297 return new WP_Error( 'woocommerce_rest_payment_extension_suggestion_error', $e->getMessage(), array( 'status' => 400 ) );
298 }
299
300 return rest_ensure_response( array( 'success' => $result ) );
301 }
302
303 /**
304 * Dismiss a payment extension suggestion incentive.
305 *
306 * @param WP_REST_Request $request The request object.
307 *
308 * @return WP_Error|WP_REST_Response
309 */
310 protected function dismiss_payment_extension_suggestion_incentive( WP_REST_Request $request ) {
311 $suggestion_id = $request->get_param( 'suggestion_id' );
312 $incentive_id = $request->get_param( 'incentive_id' );
313 $context = $request->get_param( 'context' ) ?? 'all';
314 $do_not_track = $request->get_param( 'do_not_track' ) ?? false;
315
316 try {
317 $result = $this->payments->dismiss_extension_suggestion_incentive( $suggestion_id, $incentive_id, $context, $do_not_track );
318 } catch ( Exception $e ) {
319 return new WP_Error( 'woocommerce_rest_payment_extension_suggestion_incentive_error', $e->getMessage(), array( 'status' => 400 ) );
320 }
321
322 return rest_ensure_response( array( 'success' => $result ) );
323 }
324
325 /**
326 * Get the payment extension suggestions (other) for the given location.
327 *
328 * @param string $location The location for which the suggestions are being fetched.
329 *
330 * @return array[] The payment extension suggestions for the given location,
331 * excluding the ones part of the main providers list.
332 * @throws Exception If there are malformed or invalid suggestions.
333 */
334 private function get_extension_suggestions( string $location ): array {
335 // If the requesting user can't install plugins, we don't suggest any extensions.
336 if ( ! current_user_can( 'install_plugins' ) ) {
337 return array();
338 }
339
340 $suggestions = $this->payments->get_payment_extension_suggestions( $location );
341
342 return $suggestions['other'] ?? array();
343 }
344
345 /**
346 * General permissions check for payments settings REST API endpoint.
347 *
348 * @param WP_REST_Request $request The request for which the permission is checked.
349 * @return bool|WP_Error True if the current user has the capability, otherwise an "Unauthorized" error or False if no error is available for the request method.
350 */
351 private function check_permissions( WP_REST_Request $request ) {
352 $context = 'read';
353 if ( 'POST' === $request->get_method() ) {
354 $context = 'edit';
355 } elseif ( 'DELETE' === $request->get_method() ) {
356 $context = 'delete';
357 }
358
359 if ( wc_rest_check_manager_permissions( 'payment_gateways', $context ) ) {
360 return true;
361 }
362
363 $error_information = $this->get_authentication_error_by_method( $request->get_method() );
364 if ( is_null( $error_information ) ) {
365 return false;
366 }
367
368 return new WP_Error(
369 $error_information['code'],
370 $error_information['message'],
371 array( 'status' => rest_authorization_required_code() )
372 );
373 }
374
375 /**
376 * Validate the location argument.
377 *
378 * @param mixed $value Value of the argument.
379 * @param WP_REST_Request $request The current request object.
380 *
381 * @return WP_Error|true True if the location argument is valid, otherwise a WP_Error object.
382 */
383 private function check_location_arg( $value, WP_REST_Request $request ) {
384 // If the 'location' argument is not a string return an error.
385 if ( ! is_string( $value ) ) {
386 return new WP_Error( 'rest_invalid_param', esc_html__( 'The location argument must be a string.', 'woocommerce' ), array( 'status' => 400 ) );
387 }
388
389 // Get the registered attributes for this endpoint request.
390 $attributes = $request->get_attributes();
391
392 // Grab the location param schema.
393 $args = $attributes['args']['location'];
394
395 // If the location param doesn't match the regex pattern then we should return an error as well.
396 if ( ! preg_match( '/^' . $args['pattern'] . '$/', $value ) ) {
397 return new WP_Error( 'rest_invalid_param', esc_html__( 'The location argument must be a valid ISO3166 alpha-2 country code.', 'woocommerce' ), array( 'status' => 400 ) );
398 }
399
400 return true;
401 }
402
403 /**
404 * Validate the providers order map argument.
405 *
406 * @param mixed $value Value of the argument.
407 *
408 * @return WP_Error|true True if the providers order map argument is valid, otherwise a WP_Error object.
409 */
410 private function check_providers_order_map_arg( $value ) {
411 if ( ! is_array( $value ) ) {
412 return new WP_Error( 'rest_invalid_param', esc_html__( 'The ordering argument must be an object.', 'woocommerce' ), array( 'status' => 400 ) );
413 }
414
415 foreach ( $value as $provider_id => $order ) {
416 if ( ! is_string( $provider_id ) || ! is_numeric( $order ) ) {
417 return new WP_Error( 'rest_invalid_param', esc_html__( 'The ordering argument must be an object with provider IDs as keys and numeric values as values.', 'woocommerce' ), array( 'status' => 400 ) );
418 }
419
420 if ( $this->sanitize_provider_id( $provider_id ) !== $provider_id ) {
421 return new WP_Error( 'rest_invalid_param', esc_html__( 'The provider ID must be a string with only ASCII letters, digits, underscores, and dashes.', 'woocommerce' ), array( 'status' => 400 ) );
422 }
423
424 if ( false === filter_var( $order, FILTER_VALIDATE_INT ) ) {
425 return new WP_Error( 'rest_invalid_param', esc_html__( 'The order value must be an integer.', 'woocommerce' ), array( 'status' => 400 ) );
426 }
427 }
428
429 return true;
430 }
431
432 /**
433 * Sanitize the providers ordering argument.
434 *
435 * @param array $value Value of the argument.
436 *
437 * @return array
438 */
439 private function sanitize_providers_order_arg( array $value ): array {
440 // Sanitize the ordering object to ensure that the order values are integers and the provider IDs are safe strings.
441 foreach ( $value as $provider_id => $order ) {
442 $id = $this->sanitize_provider_id( $provider_id );
443 $value[ $id ] = intval( $order );
444 }
445
446 return $value;
447 }
448
449 /**
450 * Sanitize a provider ID.
451 *
452 * This method ensures that the provider ID is a safe string by removing any unwanted characters.
453 * It strips all HTML tags, removes accents, percent-encoded characters, and HTML entities,
454 * and allows only lowercase and uppercase letters, digits, underscores, and dashes.
455 *
456 * @param string $provider_id The provider ID to sanitize.
457 *
458 * @return string The sanitized provider ID.
459 */
460 private function sanitize_provider_id( string $provider_id ): string {
461 $provider_id = wp_strip_all_tags( $provider_id );
462 $provider_id = remove_accents( $provider_id );
463 // Remove percent-encoded characters.
464 $provider_id = preg_replace( '|%([a-fA-F0-9][a-fA-F0-9])|', '', $provider_id );
465 // Remove HTML entities.
466 $provider_id = preg_replace( '/&.+?;/', '', $provider_id );
467
468 // Only lowercase and uppercase ASCII letters, digits, underscores, and dashes are allowed.
469 $provider_id = preg_replace( '|[^a-z0-9_\-]|i', '', $provider_id );
470
471 return $provider_id;
472 }
473
474 /**
475 * Prepare the response for the GET payment providers request.
476 *
477 * @param array $response The response to prepare.
478 *
479 * @return array The prepared response.
480 */
481 private function prepare_payment_providers_response( array $response ): array {
482 $response = $this->prepare_payment_providers_response_recursive( $response, $this->get_schema_for_get_payment_providers() );
483
484 $response['providers'] = $this->add_provider_links( $response['providers'] );
485 $response['suggestions'] = $this->add_suggestion_links( $response['suggestions'] );
486
487 return $response;
488 }
489
490 /**
491 * Recursively prepare the response items for the GET payment providers request.
492 *
493 * @param mixed $response_item The response item to prepare.
494 * @param array $schema The schema to use for preparing the response.
495 *
496 * @return mixed The prepared response item.
497 */
498 private function prepare_payment_providers_response_recursive( $response_item, array $schema ) {
499 if ( is_null( $response_item ) ) {
500 return null;
501 }
502
503 if ( ! array_key_exists( 'properties', $schema ) ||
504 ! is_array( $schema['properties'] ) ) {
505
506 // Filter out null values for loosely defined schema types.
507 if ( is_array( $response_item ) ) {
508 return ArrayUtil::filter_null_values_recursive( $response_item );
509 }
510 return $response_item;
511 }
512
513 $prepared_response = array();
514 foreach ( $schema['properties'] as $key => $property_schema ) {
515 if ( is_array( $response_item ) && array_key_exists( $key, $response_item ) ) {
516 if ( is_array( $property_schema ) && array_key_exists( 'properties', $property_schema ) ) {
517 $prepared_response[ $key ] = $this->prepare_payment_providers_response_recursive( $response_item[ $key ], $property_schema );
518 } elseif ( is_array( $property_schema ) && array_key_exists( 'items', $property_schema ) ) {
519 $prepared_response[ $key ] = array_map(
520 fn( $item ) => $this->prepare_payment_providers_response_recursive( $item, $property_schema['items'] ),
521 $response_item[ $key ]
522 );
523 } else {
524 $prepared_response[ $key ] = $response_item[ $key ];
525 }
526 }
527 }
528
529 // Ensure the order is the same as in the schema.
530 $prepared_response = array_merge( array_fill_keys( array_keys( $schema['properties'] ), null ), $prepared_response );
531
532 // Remove any null values from the response.
533 return ArrayUtil::filter_null_values_recursive( $prepared_response );
534 }
535
536 /**
537 * Add links to providers list items.
538 *
539 * @param array $providers The providers list.
540 *
541 * @return array The providers list with added links.
542 */
543 private function add_provider_links( array $providers ): array {
544 foreach ( $providers as $key => $provider ) {
545 if ( empty( $provider['_links'] ) ) {
546 $providers[ $key ]['_links'] = array();
547 }
548
549 // If this is a suggestion, add dedicated links.
550 if ( ! empty( $provider['_type'] ) &&
551 PaymentsProviders::TYPE_SUGGESTION === $provider['_type'] &&
552 ! empty( $provider['_suggestion_id'] )
553 ) {
554 $providers[ $key ]['_links']['attach'] = array(
555 'href' => rest_url( sprintf( '/%s/%s/suggestion/%s/attach', $this->route_namespace, $this->rest_base, $provider['_suggestion_id'] ) ),
556 );
557 $providers[ $key ]['_links']['hide'] = array(
558 'href' => rest_url( sprintf( '/%s/%s/suggestion/%s/hide', $this->route_namespace, $this->rest_base, $provider['_suggestion_id'] ) ),
559 );
560 }
561
562 // If we have an incentive, add a link to dismiss it.
563 if ( ! empty( $provider['_incentive'] ) && ! empty( $provider['_suggestion_id'] ) ) {
564 if ( empty( $provider['_incentive']['_links'] ) ) {
565 $providers[ $key ]['_incentive']['_links'] = array();
566 }
567
568 $providers[ $key ]['_incentive']['_links']['dismiss'] = array(
569 'href' => rest_url( sprintf( '/%s/%s/suggestion/%s/incentive/%s/dismiss', $this->route_namespace, $this->rest_base, $provider['_suggestion_id'], $provider['_incentive']['id'] ) ),
570 );
571 }
572 }
573
574 return $providers;
575 }
576
577 /**
578 * Add links to suggestions list items.
579 *
580 * @param array $suggestions The suggestions list.
581 *
582 * @return array The suggestions list with added links.
583 */
584 private function add_suggestion_links( array $suggestions ): array {
585 foreach ( $suggestions as $key => $suggestion ) {
586 if ( empty( $suggestion['id'] ) ) {
587 continue;
588 }
589
590 if ( empty( $suggestion['_links'] ) ) {
591 $suggestions[ $key ]['_links'] = array();
592 }
593
594 $suggestions[ $key ]['_links']['attach'] = array(
595 'href' => rest_url( sprintf( '/%s/%s/suggestion/%s/attach', $this->route_namespace, $this->rest_base, $suggestion['id'] ) ),
596 );
597 $suggestions[ $key ]['_links']['hide'] = array(
598 'href' => rest_url( sprintf( '/%s/%s/suggestion/%s/hide', $this->route_namespace, $this->rest_base, $suggestion['id'] ) ),
599 );
600 }
601
602 return $suggestions;
603 }
604
605 /**
606 * Get the schema for the GET payment providers request.
607 *
608 * @return array[]
609 */
610 private function get_schema_for_get_payment_providers(): array {
611 $schema = array(
612 '$schema' => 'http://json-schema.org/draft-04/schema#',
613 'title' => 'WooCommerce Settings Payments providers for the given location.',
614 'type' => 'object',
615 );
616 $schema['properties'] = array(
617 'providers' => array(
618 'type' => 'array',
619 'description' => esc_html__( 'The ordered providers list. This includes registered payment gateways, suggestions, and offline payment methods group entry. The individual offline payment methods are separate.', 'woocommerce' ),
620 'context' => array( 'view', 'edit' ),
621 'readonly' => true,
622 'items' => $this->get_schema_for_payment_provider(),
623 ),
624 'offline_payment_methods' => array(
625 'type' => 'array',
626 'description' => esc_html__( 'The ordered offline payment methods providers list.', 'woocommerce' ),
627 'context' => array( 'view', 'edit' ),
628 'readonly' => true,
629 'items' => $this->get_schema_for_payment_provider(),
630 ),
631 'suggestions' => array(
632 'type' => 'array',
633 'description' => esc_html__( 'The list of suggestions, excluding the ones part of the providers list.', 'woocommerce' ),
634 'context' => array( 'view', 'edit' ),
635 'readonly' => true,
636 'items' => $this->get_schema_for_suggestion(),
637 ),
638 'suggestion_categories' => array(
639 'type' => 'array',
640 'description' => esc_html__( 'The suggestion categories.', 'woocommerce' ),
641 'context' => array( 'view', 'edit' ),
642 'readonly' => true,
643 'items' => array(
644 'type' => 'object',
645 'description' => esc_html__( 'A suggestion category.', 'woocommerce' ),
646 'context' => array( 'view', 'edit' ),
647 'readonly' => true,
648 'properties' => array(
649 'id' => array(
650 'type' => 'string',
651 'description' => esc_html__( 'The unique identifier for the category.', 'woocommerce' ),
652 'context' => array( 'view', 'edit' ),
653 'readonly' => true,
654 ),
655 '_priority' => array(
656 'type' => 'integer',
657 'description' => esc_html__( 'The priority of the category.', 'woocommerce' ),
658 'context' => array( 'view', 'edit' ),
659 'readonly' => true,
660 ),
661 'title' => array(
662 'type' => 'string',
663 'description' => esc_html__( 'The title of the category.', 'woocommerce' ),
664 'context' => array( 'view', 'edit' ),
665 'readonly' => true,
666 ),
667 'description' => array(
668 'type' => 'string',
669 'description' => esc_html__( 'The description of the category.', 'woocommerce' ),
670 'context' => array( 'view', 'edit' ),
671 'readonly' => true,
672 ),
673
674 ),
675 ),
676 ),
677 );
678
679 return $schema;
680 }
681
682 /**
683 * Get the schema for a payment provider.
684 *
685 * @return array The schema for a payment provider.
686 */
687 private function get_schema_for_payment_provider(): array {
688 return array(
689 'type' => 'object',
690 'description' => esc_html__( 'A payment provider in the context of the main Payments Settings page list.', 'woocommerce' ),
691 'properties' => array(
692 'id' => array(
693 'type' => 'string',
694 'description' => esc_html__( 'The unique identifier for the provider.', 'woocommerce' ),
695 'context' => array( 'view', 'edit' ),
696 'readonly' => true,
697 ),
698 '_order' => array(
699 'type' => 'integer',
700 'description' => esc_html__( 'The sort order of the provider.', 'woocommerce' ),
701 'context' => array( 'view', 'edit' ),
702 'readonly' => true,
703 ),
704 '_type' => array(
705 'type' => 'string',
706 'description' => esc_html__( 'The type of payment provider. Use this to differentiate between the various items in the list and determine their intended use.', 'woocommerce' ),
707 'context' => array( 'view', 'edit' ),
708 'readonly' => true,
709 ),
710 'title' => array(
711 'type' => 'string',
712 'description' => esc_html__( 'The title of the provider.', 'woocommerce' ),
713 'context' => array( 'view', 'edit' ),
714 'readonly' => true,
715 ),
716 'description' => array(
717 'type' => 'string',
718 'description' => esc_html__( 'The description of the provider.', 'woocommerce' ),
719 'context' => array( 'view', 'edit' ),
720 'readonly' => true,
721 ),
722 'supports' => array(
723 'description' => esc_html__( 'Supported features for this provider.', 'woocommerce' ),
724 'type' => 'array',
725 'context' => array( 'view', 'edit' ),
726 'readonly' => true,
727 'items' => array(
728 'type' => 'string',
729 ),
730 ),
731 'plugin' => array(
732 'type' => 'object',
733 'description' => esc_html__( 'The corresponding plugin details of the provider.', 'woocommerce' ),
734 'context' => array( 'view', 'edit' ),
735 'readonly' => true,
736 'properties' => array(
737 '_type' => array(
738 'type' => 'string',
739 'enum' => array(
740 PaymentsProviders::EXTENSION_TYPE_WPORG,
741 PaymentsProviders::EXTENSION_TYPE_MU_PLUGIN,
742 PaymentsProviders::EXTENSION_TYPE_THEME,
743 PaymentsProviders::EXTENSION_TYPE_UNKNOWN,
744 ),
745 'description' => esc_html__( 'The type of the containing entity. Generally this is a regular plugin but it can also be a non-standard entity like a theme or a must-user plugin.', 'woocommerce' ),
746 'context' => array( 'view', 'edit' ),
747 'readonly' => true,
748 ),
749 'slug' => array(
750 'type' => 'string',
751 'description' => esc_html__( 'The slug of the containing entity.', 'woocommerce' ),
752 'context' => array( 'view', 'edit' ),
753 'readonly' => true,
754 ),
755 'file' => array(
756 'type' => 'string',
757 'description' => esc_html__( 'The plugin main file. This is a relative path to the plugins directory.', 'woocommerce' ),
758 'context' => array( 'view', 'edit' ),
759 'readonly' => true,
760 ),
761 'status' => array(
762 'type' => 'string',
763 'enum' => array(
764 PaymentsProviders::EXTENSION_NOT_INSTALLED,
765 PaymentsProviders::EXTENSION_INSTALLED,
766 PaymentsProviders::EXTENSION_ACTIVE,
767 ),
768 'description' => esc_html__( 'The status of the containing entity.', 'woocommerce' ),
769 'context' => array( 'view', 'edit' ),
770 'readonly' => true,
771 ),
772 ),
773 ),
774 'image' => array(
775 'type' => 'string',
776 'description' => esc_html__( 'The URL of the provider image.', 'woocommerce' ),
777 'readonly' => true,
778 ),
779 'icon' => array(
780 'type' => 'string',
781 'description' => esc_html__( 'The URL of the provider icon (square aspect ratio - 72px by 72px).', 'woocommerce' ),
782 'readonly' => true,
783 ),
784 'links' => array(
785 'type' => 'array',
786 'description' => esc_html__( 'Links for the provider.', 'woocommerce' ),
787 'context' => array( 'view', 'edit' ),
788 'readonly' => true,
789 'items' => array(
790 'type' => 'object',
791 'properties' => array(
792 '_type' => array(
793 'type' => 'string',
794 'description' => esc_html__( 'The type of the link.', 'woocommerce' ),
795 'context' => array( 'view', 'edit' ),
796 'readonly' => true,
797 ),
798 'url' => array(
799 'type' => 'string',
800 'description' => esc_html__( 'The URL of the link.', 'woocommerce' ),
801 'context' => array( 'view', 'edit' ),
802 'readonly' => true,
803 ),
804 ),
805 ),
806 ),
807 'state' => array(
808 'type' => 'object',
809 'description' => esc_html__( 'The general state of the provider with regards to it\'s payments processing.', 'woocommerce' ),
810 'properties' => array(
811 'enabled' => array(
812 'type' => 'boolean',
813 'description' => esc_html__( 'Whether the provider is enabled for use on checkout.', 'woocommerce' ),
814 'context' => array( 'view', 'edit' ),
815 'readonly' => true,
816 ),
817 'account_connected' => array(
818 'type' => 'boolean',
819 'description' => esc_html__( 'Whether the provider has a payments processing account connected.', 'woocommerce' ),
820 'context' => array( 'view', 'edit' ),
821 'readonly' => true,
822 ),
823 'needs_setup' => array(
824 'type' => 'boolean',
825 'description' => esc_html__( 'Whether the provider needs setup.', 'woocommerce' ),
826 'context' => array( 'view', 'edit' ),
827 'readonly' => true,
828 ),
829 'test_mode' => array(
830 'type' => 'boolean',
831 'description' => esc_html__( 'Whether the provider is in test mode for payments processing.', 'woocommerce' ),
832 'context' => array( 'view', 'edit' ),
833 'readonly' => true,
834 ),
835 'dev_mode' => array(
836 'type' => 'boolean',
837 'description' => esc_html__( 'Whether the provider is in dev mode. Having this true usually leads to forcing test payments. ', 'woocommerce' ),
838 'context' => array( 'view', 'edit' ),
839 'readonly' => true,
840 ),
841 ),
842 ),
843 'management' => array(
844 'type' => 'object',
845 'description' => esc_html__( 'The management details of the provider.', 'woocommerce' ),
846 'properties' => array(
847 '_links' => array(
848 'type' => 'object',
849 'context' => array( 'view', 'edit' ),
850 'readonly' => true,
851 'properties' => array(
852 'settings' => array(
853 'type' => 'object',
854 'description' => esc_html__( 'The link to the settings page for the payment gateway.', 'woocommerce' ),
855 'context' => array( 'view', 'edit' ),
856 'readonly' => true,
857 'properties' => array(
858 'href' => array(
859 'type' => 'string',
860 'description' => esc_html__( 'The URL to the settings page for the payment gateway.', 'woocommerce' ),
861 'context' => array( 'view', 'edit' ),
862 'readonly' => true,
863 ),
864 ),
865 ),
866 ),
867 ),
868 ),
869 ),
870 'onboarding' => array(
871 'type' => 'object',
872 'description' => esc_html__( 'Onboarding-related details for the provider.', 'woocommerce' ),
873 'properties' => array(
874 'type' => array(
875 'type' => 'string',
876 'description' => esc_html__( 'The type of onboarding process the provider supports.', 'woocommerce' ),
877 'context' => array( 'view', 'edit' ),
878 'readonly' => true,
879 ),
880 'state' => array(
881 'type' => 'object',
882 'description' => esc_html__( 'The state of the onboarding process.', 'woocommerce' ),
883 'context' => array( 'view', 'edit' ),
884 ),
885 'messages' => array(
886 'type' => 'object',
887 'description' => esc_html__( 'Various messages to possibly show the user.', 'woocommerce' ),
888 'context' => array( 'view', 'edit' ),
889 'readonly' => true,
890 'additionalProperties' => array(
891 'type' => 'string',
892 'description' => esc_html__( 'Message to show the user.', 'woocommerce' ),
893 'readonly' => true,
894 ),
895 ),
896 'steps' => array(
897 'type' => 'array',
898 'description' => esc_html__( 'The onboarding steps in case this provider supports native in-context onboarding.', 'woocommerce' ),
899 'context' => array( 'view', 'edit' ),
900 'readonly' => true,
901 ),
902 '_links' => array(
903 'type' => 'object',
904 'context' => array( 'view', 'edit' ),
905 'readonly' => true,
906 'properties' => array(
907 'preload' => array(
908 'type' => 'object',
909 'description' => esc_html__( 'The onboarding preload link for the payment gateway.', 'woocommerce' ),
910 'context' => array( 'view', 'edit' ),
911 'readonly' => true,
912 'properties' => array(
913 'href' => array(
914 'type' => 'string',
915 'description' => esc_html__( 'The URL to do onboarding preload for the payment gateway.', 'woocommerce' ),
916 'context' => array( 'view', 'edit' ),
917 'readonly' => true,
918 ),
919 ),
920 ),
921 'onboard' => array(
922 'type' => 'object',
923 'description' => esc_html__( 'The start/continue onboarding link for the payment gateway.', 'woocommerce' ),
924 'context' => array( 'view', 'edit' ),
925 'readonly' => true,
926 'properties' => array(
927 'href' => array(
928 'type' => 'string',
929 'description' => esc_html__( 'The URL to start/continue onboarding for the payment gateway.', 'woocommerce' ),
930 'context' => array( 'view', 'edit' ),
931 'readonly' => true,
932 ),
933 ),
934 ),
935 'disable_test_account' => array(
936 'type' => 'object',
937 'description' => esc_html__( 'The link to disable the test account for the payment gateway.', 'woocommerce' ),
938 'context' => array( 'view', 'edit' ),
939 'readonly' => true,
940 'properties' => array(
941 'href' => array(
942 'type' => 'string',
943 'description' => esc_html__( 'The URL to POST to disable the test account for the payment gateway.', 'woocommerce' ),
944 'context' => array( 'view', 'edit' ),
945 'readonly' => true,
946 ),
947 ),
948 ),
949 'reset' => array(
950 'type' => 'object',
951 'description' => esc_html__( 'The link to reset the provider state/account and restart the onboarding.', 'woocommerce' ),
952 'context' => array( 'view', 'edit' ),
953 'readonly' => true,
954 'properties' => array(
955 'href' => array(
956 'type' => 'string',
957 'description' => esc_html__( 'The URL to POST to for resetting the provider onboarding.', 'woocommerce' ),
958 'context' => array( 'view', 'edit' ),
959 'readonly' => true,
960 ),
961 ),
962 ),
963 ),
964 ),
965 'recommended_payment_methods' => array(
966 'type' => 'array',
967 'description' => esc_html__( 'The list of recommended payment methods details for the payment gateway.', 'woocommerce' ),
968 'context' => array( 'view', 'edit' ),
969 'readonly' => true,
970 'items' => array(
971 'type' => 'object',
972 'description' => esc_html__( 'The details for a recommended payment method.', 'woocommerce' ),
973 'context' => array( 'view', 'edit' ),
974 'readonly' => true,
975 'properties' => array(
976 'id' => array(
977 'type' => 'string',
978 'description' => esc_html__( 'The unique identifier for the payment method.', 'woocommerce' ),
979 'context' => array( 'view', 'edit' ),
980 'readonly' => true,
981 ),
982 '_order' => array(
983 'type' => 'integer',
984 'description' => esc_html__( 'The sort order of the payment method.', 'woocommerce' ),
985 'context' => array( 'view', 'edit' ),
986 'readonly' => true,
987 ),
988 'enabled' => array(
989 'type' => 'boolean',
990 'description' => esc_html__( 'Whether the payment method should be recommended as enabled or not.', 'woocommerce' ),
991 'context' => array( 'view', 'edit' ),
992 'readonly' => true,
993 ),
994 'required' => array(
995 'type' => 'boolean',
996 'description' => esc_html__( 'Whether the payment method should be required (and force-enabled) or not.', 'woocommerce' ),
997 'context' => array( 'view', 'edit' ),
998 'readonly' => true,
999 ),
1000 'title' => array(
1001 'type' => 'string',
1002 'description' => esc_html__( 'The title of the payment method. Does not include HTML tags.', 'woocommerce' ),
1003 'context' => array( 'view', 'edit' ),
1004 'readonly' => true,
1005 ),
1006 'description' => array(
1007 'type' => 'string',
1008 'description' => esc_html__( 'The description of the payment method. It can contain basic HTML.', 'woocommerce' ),
1009 'context' => array( 'view', 'edit' ),
1010 'readonly' => true,
1011 ),
1012 'icon' => array(
1013 'type' => 'string',
1014 'description' => esc_html__( 'The URL of the payment method icon or a base64-encoded SVG image.', 'woocommerce' ),
1015 'context' => array( 'view', 'edit' ),
1016 'readonly' => true,
1017 ),
1018 'notice' => array(
1019 'type' => 'object',
1020 'description' => esc_html__( 'An optional notice to display for this payment method (e.g., verification requirements).', 'woocommerce' ),
1021 'context' => array( 'view', 'edit' ),
1022 'readonly' => true,
1023 'properties' => array(
1024 'badge' => array(
1025 'type' => 'string',
1026 'description' => esc_html__( 'Short text for a badge/chip displayed next to the payment method title.', 'woocommerce' ),
1027 'context' => array( 'view', 'edit' ),
1028 'readonly' => true,
1029 ),
1030 'message' => array(
1031 'type' => 'string',
1032 'description' => esc_html__( 'Warning message displayed when the payment method is enabled. Plain text only.', 'woocommerce' ),
1033 'context' => array( 'view', 'edit' ),
1034 'readonly' => true,
1035 ),
1036 'link_text' => array(
1037 'type' => 'string',
1038 'description' => esc_html__( 'Text for the call-to-action link in the notice.', 'woocommerce' ),
1039 'context' => array( 'view', 'edit' ),
1040 'readonly' => true,
1041 ),
1042 'link_url' => array(
1043 'type' => 'string',
1044 'description' => esc_html__( 'URL for the call-to-action link in the notice.', 'woocommerce' ),
1045 'context' => array( 'view', 'edit' ),
1046 'readonly' => true,
1047 ),
1048 ),
1049 ),
1050 ),
1051 ),
1052 ),
1053 'context' => array(
1054 'type' => 'object',
1055 'description' => esc_html__( 'Various contextual data for the onboarding process to use.', 'woocommerce' ),
1056 'context' => array( 'view', 'edit' ),
1057 'readonly' => true,
1058 ),
1059 ),
1060 ),
1061 'tags' => array(
1062 'type' => 'array',
1063 'description' => esc_html__( 'The tags associated with the provider.', 'woocommerce' ),
1064 'uniqueItems' => true,
1065 'context' => array( 'view', 'edit' ),
1066 'readonly' => true,
1067 'items' => array(
1068 'type' => 'string',
1069 'description' => esc_html__( 'Tag associated with the provider.', 'woocommerce' ),
1070 'readonly' => true,
1071 ),
1072 ),
1073 '_suggestion_id' => array(
1074 'type' => 'string',
1075 'description' => esc_html__( 'The suggestion ID matching this provider.', 'woocommerce' ),
1076 'context' => array( 'view', 'edit' ),
1077 'readonly' => true,
1078 ),
1079 '_incentive' => $this->get_schema_for_incentive(),
1080 '_links' => array(
1081 'type' => 'object',
1082 'context' => array( 'view', 'edit' ),
1083 'readonly' => true,
1084 'properties' => array(
1085 'attach' => array(
1086 'type' => 'object',
1087 'description' => esc_html__( 'The link to mark the suggestion as attached. This should be called when an extension is installed.', 'woocommerce' ),
1088 'context' => array( 'view', 'edit' ),
1089 'readonly' => true,
1090 'properties' => array(
1091 'href' => array(
1092 'type' => 'string',
1093 'description' => esc_html__( 'The URL to attach the suggestion.', 'woocommerce' ),
1094 'context' => array( 'view', 'edit' ),
1095 'readonly' => true,
1096 ),
1097 ),
1098 ),
1099 'hide' => array(
1100 'type' => 'object',
1101 'description' => esc_html__( 'The link to hide the suggestion.', 'woocommerce' ),
1102 'context' => array( 'view', 'edit' ),
1103 'readonly' => true,
1104 'properties' => array(
1105 'href' => array(
1106 'type' => 'string',
1107 'description' => esc_html__( 'The URL to hide the suggestion.', 'woocommerce' ),
1108 'context' => array( 'view', 'edit' ),
1109 'readonly' => true,
1110 ),
1111 ),
1112 ),
1113 ),
1114 ),
1115 ),
1116 );
1117 }
1118
1119 /**
1120 * Get the schema for a suggestion.
1121 *
1122 * @return array The schema for a suggestion.
1123 */
1124 private function get_schema_for_suggestion(): array {
1125 return array(
1126 'type' => 'object',
1127 'description' => esc_html__( 'A suggestion with full details.', 'woocommerce' ),
1128 'context' => array( 'view', 'edit' ),
1129 'readonly' => true,
1130 'properties' => array(
1131 'id' => array(
1132 'type' => 'string',
1133 'description' => esc_html__( 'The unique identifier for the suggestion.', 'woocommerce' ),
1134 'context' => array( 'view', 'edit' ),
1135 'readonly' => true,
1136 ),
1137 '_priority' => array(
1138 'type' => 'integer',
1139 'description' => esc_html__( 'The priority of the suggestion.', 'woocommerce' ),
1140 'context' => array( 'view', 'edit' ),
1141 'readonly' => true,
1142 ),
1143 '_type' => array(
1144 'type' => 'string',
1145 'description' => esc_html__( 'The type of the suggestion.', 'woocommerce' ),
1146 'context' => array( 'view', 'edit' ),
1147 'readonly' => true,
1148 ),
1149 'title' => array(
1150 'type' => 'string',
1151 'description' => esc_html__( 'The title of the suggestion.', 'woocommerce' ),
1152 'context' => array( 'view', 'edit' ),
1153 'readonly' => true,
1154 ),
1155 'description' => array(
1156 'type' => 'string',
1157 'description' => esc_html__( 'The description of the suggestion.', 'woocommerce' ),
1158 'context' => array( 'view', 'edit' ),
1159 'readonly' => true,
1160 ),
1161 'plugin' => array(
1162 'type' => 'object',
1163 'context' => array( 'view', 'edit' ),
1164 'readonly' => true,
1165 'properties' => array(
1166 '_type' => array(
1167 'type' => 'string',
1168 'enum' => array( PaymentsProviders::EXTENSION_TYPE_WPORG ),
1169 'description' => esc_html__( 'The type of the plugin.', 'woocommerce' ),
1170 'context' => array( 'view', 'edit' ),
1171 'readonly' => true,
1172 ),
1173 'slug' => array(
1174 'type' => 'string',
1175 'description' => esc_html__( 'The slug of the plugin.', 'woocommerce' ),
1176 'context' => array( 'view', 'edit' ),
1177 'readonly' => true,
1178 ),
1179 'status' => array(
1180 'type' => 'string',
1181 'enum' => array(
1182 PaymentsProviders::EXTENSION_NOT_INSTALLED,
1183 PaymentsProviders::EXTENSION_INSTALLED,
1184 PaymentsProviders::EXTENSION_ACTIVE,
1185 ),
1186 'description' => esc_html__( 'The status of the plugin.', 'woocommerce' ),
1187 'context' => array( 'view', 'edit' ),
1188 'readonly' => true,
1189 ),
1190 ),
1191 ),
1192 'image' => array(
1193 'type' => 'string',
1194 'description' => esc_html__( 'The URL of the image.', 'woocommerce' ),
1195 'readonly' => true,
1196 ),
1197 'icon' => array(
1198 'type' => 'string',
1199 'description' => esc_html__( 'The URL of the icon (square aspect ratio).', 'woocommerce' ),
1200 'readonly' => true,
1201 ),
1202 'links' => array(
1203 'type' => 'array',
1204 'context' => array( 'view', 'edit' ),
1205 'readonly' => true,
1206 'items' => array(
1207 'type' => 'object',
1208 'properties' => array(
1209 '_type' => array(
1210 'type' => 'string',
1211 'description' => esc_html__( 'The type of the link.', 'woocommerce' ),
1212 'context' => array( 'view', 'edit' ),
1213 'readonly' => true,
1214 ),
1215 'url' => array(
1216 'type' => 'string',
1217 'description' => esc_html__( 'The URL of the link.', 'woocommerce' ),
1218 'context' => array( 'view', 'edit' ),
1219 'readonly' => true,
1220 ),
1221 ),
1222 ),
1223 ),
1224 '_incentive' => $this->get_schema_for_incentive(),
1225 'tags' => array(
1226 'description' => esc_html__( 'The tags associated with the suggestion.', 'woocommerce' ),
1227 'type' => 'array',
1228 'uniqueItems' => true,
1229 'context' => array( 'view', 'edit' ),
1230 'readonly' => true,
1231 'items' => array(
1232 'type' => 'string',
1233 'description' => esc_html__( 'The tags associated with the suggestion.', 'woocommerce' ),
1234 'readonly' => true,
1235 ),
1236 ),
1237 'category' => array(
1238 'type' => 'string',
1239 'description' => esc_html__( 'The category of the suggestion.', 'woocommerce' ),
1240 'context' => array( 'view', 'edit' ),
1241 'readonly' => true,
1242 ),
1243 '_links' => array(
1244 'type' => 'object',
1245 'context' => array( 'view', 'edit' ),
1246 'readonly' => true,
1247 'properties' => array(
1248 'attach' => array(
1249 'type' => 'object',
1250 'description' => esc_html__( 'The link to mark the suggestion as attached. This should be called when an extension is installed.', 'woocommerce' ),
1251 'context' => array( 'view', 'edit' ),
1252 'readonly' => true,
1253 'properties' => array(
1254 'href' => array(
1255 'type' => 'string',
1256 'description' => esc_html__( 'The URL to attach the suggestion.', 'woocommerce' ),
1257 'context' => array( 'view', 'edit' ),
1258 'readonly' => true,
1259 ),
1260 ),
1261 ),
1262 'hide' => array(
1263 'type' => 'object',
1264 'description' => esc_html__( 'The link to hide the suggestion.', 'woocommerce' ),
1265 'context' => array( 'view', 'edit' ),
1266 'readonly' => true,
1267 'properties' => array(
1268 'href' => array(
1269 'type' => 'string',
1270 'description' => esc_html__( 'The URL to hide the suggestion.', 'woocommerce' ),
1271 'context' => array( 'view', 'edit' ),
1272 'readonly' => true,
1273 ),
1274 ),
1275 ),
1276 ),
1277 ),
1278 ),
1279 );
1280 }
1281
1282 /**
1283 * Get the schema for an incentive.
1284 *
1285 * @return array The incentive schema.
1286 */
1287 private function get_schema_for_incentive(): array {
1288 return array(
1289 'type' => 'object',
1290 'description' => esc_html__( 'The active incentive for the provider.', 'woocommerce' ),
1291 'context' => array( 'view', 'edit' ),
1292 'readonly' => true,
1293 'properties' => array(
1294 'id' => array(
1295 'type' => 'string',
1296 'description' => esc_html__( 'The incentive unique ID. This ID needs to be used for incentive dismissals.', 'woocommerce' ),
1297 'context' => array( 'view', 'edit' ),
1298 'readonly' => true,
1299 ),
1300 'promo_id' => array(
1301 'type' => 'string',
1302 'description' => esc_html__( 'The incentive promo ID. This ID need to be fed into the onboarding flow.', 'woocommerce' ),
1303 'context' => array( 'view', 'edit' ),
1304 'readonly' => true,
1305 ),
1306 'title' => array(
1307 'type' => 'string',
1308 'description' => esc_html__( 'The incentive title. It can contain stylistic HTML.', 'woocommerce' ),
1309 'context' => array( 'view', 'edit' ),
1310 'readonly' => true,
1311 ),
1312 'description' => array(
1313 'type' => 'string',
1314 'description' => esc_html__( 'The incentive description. It can contain stylistic HTML.', 'woocommerce' ),
1315 'context' => array( 'view', 'edit' ),
1316 'readonly' => true,
1317 ),
1318 'short_description' => array(
1319 'type' => 'string',
1320 'description' => esc_html__( 'The short description of the incentive. It can contain stylistic HTML.', 'woocommerce' ),
1321 'context' => array( 'view', 'edit' ),
1322 'readonly' => true,
1323 ),
1324 'cta_label' => array(
1325 'type' => 'string',
1326 'description' => esc_html__( 'The call to action label for the incentive.', 'woocommerce' ),
1327 'context' => array( 'view', 'edit' ),
1328 'readonly' => true,
1329 ),
1330 'tc_url' => array(
1331 'type' => 'string',
1332 'description' => esc_html__( 'The URL to the terms and conditions for the incentive.', 'woocommerce' ),
1333 'context' => array( 'view', 'edit' ),
1334 'readonly' => true,
1335 ),
1336 'badge' => array(
1337 'type' => 'string',
1338 'description' => esc_html__( 'The badge label for the incentive.', 'woocommerce' ),
1339 'context' => array( 'view', 'edit' ),
1340 'readonly' => true,
1341 ),
1342 '_dismissals' => array(
1343 'type' => 'array',
1344 'description' => esc_html__( 'The dismissals list for the incentive. Each dismissal entry includes a context and a timestamp. The `all` entry means the incentive was dismissed for all contexts.', 'woocommerce' ),
1345 'uniqueItems' => true,
1346 'context' => array( 'view', 'edit' ),
1347 'readonly' => true,
1348 'items' => array(
1349 'type' => 'object',
1350 'properties' => array(
1351 'context' => array(
1352 'type' => 'string',
1353 'description' => esc_html__( 'Context ID in which the incentive was dismissed.', 'woocommerce' ),
1354 'readonly' => true,
1355 ),
1356 'timestamp' => array(
1357 'type' => 'integer',
1358 'description' => esc_html__( 'Unix timestamp representing when the incentive was dismissed.', 'woocommerce' ),
1359 'readonly' => true,
1360 ),
1361 ),
1362 ),
1363 ),
1364 '_links' => array(
1365 'type' => 'object',
1366 'context' => array( 'view', 'edit' ),
1367 'readonly' => true,
1368 'properties' => array(
1369 'dismiss' => array(
1370 'type' => 'object',
1371 'description' => esc_html__( 'The link to dismiss the incentive.', 'woocommerce' ),
1372 'context' => array( 'view', 'edit' ),
1373 'readonly' => true,
1374 'properties' => array(
1375 'href' => array(
1376 'type' => 'string',
1377 'description' => esc_html__( 'The URL to dismiss the incentive.', 'woocommerce' ),
1378 'context' => array( 'view', 'edit' ),
1379 'readonly' => true,
1380 ),
1381 ),
1382 ),
1383 'onboard' => array(
1384 'type' => 'object',
1385 'description' => esc_html__( 'The start/continue onboarding link for the payment gateway.', 'woocommerce' ),
1386 'context' => array( 'view', 'edit' ),
1387 'readonly' => true,
1388 'properties' => array(
1389 'href' => array(
1390 'type' => 'string',
1391 'description' => esc_html__( 'The URL to start/continue onboarding for the payment gateway.', 'woocommerce' ),
1392 'context' => array( 'view', 'edit' ),
1393 'readonly' => true,
1394 ),
1395 ),
1396 ),
1397 ),
1398 ),
1399 ),
1400 );
1401 }
1402 }
1403