PluginProbe ʕ •ᴥ•ʔ
WooCommerce Square / 5.4.2
WooCommerce Square v5.4.2
5.4.2 5.4.1 5.4.0 trunk 1.0.25 1.0.26 1.0.27 1.0.28 1.0.29 1.0.30 1.0.31 1.0.32 1.0.33 1.0.34 1.0.35 1.0.36 1.0.37 1.0.38 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.5.0 2.5.1 2.5.2 2.5.3 2.6.0 2.7.0 2.8.0 2.9.0 2.9.1 3.0.0 3.0.1 3.0.2 3.0.3 3.1.0 3.2.0 3.3.0 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.7.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 4.0.0 4.1.0 4.2.0 4.2.1 4.2.2 4.2.3 4.3.0 4.3.1 4.3.2 4.4.0 4.4.1 4.4.2 4.5.0 4.5.1 4.5.2 4.6.0 4.6.1 4.6.2 4.6.3 4.6.4 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.1 4.8.2 4.8.3 4.8.4 4.8.5 4.8.6 4.8.7 4.8.8 4.9.0 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 4.9.6 4.9.7 4.9.8 4.9.9 5.0.0 5.0.1 5.1.0 5.1.1 5.1.2 5.2.0 5.3.0 5.3.1 5.3.2 5.3.3
woocommerce-square / includes / Internal / Abilities / Domain / GetPendingJobs.php
woocommerce-square / includes / Internal / Abilities / Domain Last commit date
AbstractSquareAbility.php 1 month ago GetConnectionStatus.php 1 month ago GetLocations.php 1 month ago GetOrderPaymentStatus.php 1 month ago GetPendingJobs.php 1 month ago GetProductSyncState.php 1 month ago GetSyncRecords.php 1 month ago GetSyncStatus.php 1 month ago
GetPendingJobs.php
164 lines
1 <?php
2 /**
3 * Get pending background jobs ability definition.
4 *
5 * @package WooCommerce\Square
6 */
7
8 // @phan-file-suppress PhanUndeclaredClassMethod, PhanUndeclaredFunction @phan-suppress-current-line UnusedSuppression -- Abilities API + AbilityDefinition added in WC 10.9; suppression covers older-WC compat runs where this class never loads.
9
10 namespace WooCommerce\Square\Internal\Abilities\Domain;
11
12 defined( 'ABSPATH' ) || exit;
13
14 use Automattic\WooCommerce\Abilities\AbilityDefinition;
15 use WooCommerce\Square\Internal\Abilities\Abilities_Registrar;
16
17 /**
18 * Registers the woocommerce-square/get-pending-jobs ability.
19 *
20 * Returns active background sync jobs (queued + currently processing) so
21 * agents can answer "is sync stuck in a queue?" vs "still progressing?".
22 * Distinct from get-sync-status, which is a composite health snapshot —
23 * this ability surfaces the individual job records with per-job progress.
24 *
25 * Backing detail: Background_Job_Handler::get_jobs() reads job records
26 * from wp_options with a LIKE-on-JSON status filter. No transient writes,
27 * no API calls. Completed and failed jobs are excluded by default; pass
28 * `include_terminal: true` to include them (still capped at 20 entries
29 * total via the schema's `maximum` on `limit`).
30 *
31 * @internal Only loaded when WooCommerce 10.9+ is active.
32 */
33 class GetPendingJobs extends AbstractSquareAbility implements AbilityDefinition {
34
35 public static function get_name(): string {
36 return 'woocommerce-square/get-pending-jobs';
37 }
38
39 public static function get_registration_args(): array {
40 return array(
41 'label' => __( 'Get pending Square sync jobs', 'woocommerce-square' ),
42 'description' => __( 'Return active Square background sync jobs (queued + processing) with per-job progress (action, percentage, product counts, cursor). Use to diagnose whether a sync is stuck or still progressing.', 'woocommerce-square' ),
43 'category' => self::CATEGORY_SLUG,
44 'input_schema' => array(
45 'type' => 'object',
46 'default' => (object) array(),
47 'properties' => array(
48 'include_terminal' => array(
49 'type' => 'boolean',
50 'default' => false,
51 'description' => __( 'When true, also include completed and failed jobs. Defaults to false (active jobs only).', 'woocommerce-square' ),
52 ),
53 'limit' => array(
54 'type' => 'integer',
55 'minimum' => 1,
56 'maximum' => 20,
57 'default' => 20,
58 'description' => __( 'Maximum number of jobs to return, newest first. The schema enforces a hard upper bound of 20.', 'woocommerce-square' ),
59 ),
60 ),
61 'additionalProperties' => false,
62 ),
63 'output_schema' => array(
64 'type' => 'array',
65 'items' => array(
66 'type' => 'object',
67 'properties' => array(
68 'id' => array( 'type' => 'string' ),
69 'status' => array( 'type' => 'string' ),
70 'action' => array( 'type' => 'string' ),
71 'percentage' => array( 'type' => 'number' ),
72 'manual' => array( 'type' => 'boolean' ),
73 'system_of_record' => array( 'type' => 'string' ),
74 'product_count' => array( 'type' => 'integer' ),
75 'processed_count' => array( 'type' => 'integer' ),
76 'updated_count' => array( 'type' => 'integer' ),
77 'skipped_count' => array( 'type' => 'integer' ),
78 'catalog_processed' => array( 'type' => 'boolean' ),
79 'created_at' => array( 'type' => array( 'string', 'null' ) ),
80 'updated_at' => array( 'type' => array( 'string', 'null' ) ),
81 ),
82 ),
83 ),
84 'execute_callback' => array( self::class, 'execute' ),
85 'permission_callback' => array( Abilities_Registrar::class, 'can_manage_woocommerce_square' ),
86 'meta' => array(
87 'annotations' => array(
88 'readonly' => true,
89 'destructive' => false,
90 'idempotent' => true,
91 ),
92 'show_in_rest' => true,
93 'mcp' => array(
94 'public' => true,
95 ),
96 ),
97 );
98 }
99
100 /**
101 * Execute callback.
102 *
103 * @param mixed $input Optional input args (include_terminal, limit).
104 * @return array|\WP_Error
105 */
106 public static function execute( $input = null ) {
107 $handler = self::get_background_job_handler_or_error();
108 if ( is_wp_error( $handler ) ) {
109 return $handler;
110 }
111
112 $input = is_array( $input ) ? $input : array();
113 // Runtime clamp duplicates the schema's `minimum: 1` / `maximum: 20` bound on `limit`.
114 // The Abilities Loader applies the schema before execute() runs, so this branch only
115 // kicks in for direct callers that reach execute() outside the loader (tests, other
116 // PHP code). Keeping both copies guards against a future reader tightening one side
117 // of the contract and leaving the other stale.
118 $limit = isset( $input['limit'] ) ? max( 1, min( 20, (int) $input['limit'] ) ) : 20;
119 $statuses = ! empty( $input['include_terminal'] )
120 ? array( 'queued', 'processing', 'completed', 'failed' )
121 : array( 'queued', 'processing' );
122
123 $jobs = $handler->get_jobs( array( 'status' => $statuses ) );
124 if ( ! is_array( $jobs ) ) {
125 return array();
126 }
127
128 $jobs = array_slice( $jobs, 0, $limit );
129
130 $out = array();
131 foreach ( $jobs as $job ) {
132 if ( ! is_object( $job ) ) {
133 continue;
134 }
135 $out[] = self::normalize_job( $job );
136 }
137 return $out;
138 }
139
140 /**
141 * Coerce a Background_Job stdClass into a stable associative-array shape.
142 *
143 * @param object $job Job object returned by Background_Job_Handler::get_jobs().
144 * @return array
145 */
146 private static function normalize_job( $job ): array {
147 return array(
148 'id' => isset( $job->id ) ? (string) $job->id : '',
149 'status' => isset( $job->status ) ? (string) $job->status : '',
150 'action' => isset( $job->action ) ? (string) $job->action : '',
151 'percentage' => isset( $job->percentage ) ? (float) $job->percentage : 0.0,
152 'manual' => ! empty( $job->manual ),
153 'system_of_record' => isset( $job->system_of_record ) ? (string) $job->system_of_record : '',
154 'product_count' => isset( $job->product_ids ) && is_array( $job->product_ids ) ? count( $job->product_ids ) : 0,
155 'processed_count' => isset( $job->processed_product_ids ) && is_array( $job->processed_product_ids ) ? count( $job->processed_product_ids ) : 0,
156 'updated_count' => isset( $job->updated_product_ids ) && is_array( $job->updated_product_ids ) ? count( $job->updated_product_ids ) : 0,
157 'skipped_count' => isset( $job->skipped_products ) && is_array( $job->skipped_products ) ? count( $job->skipped_products ) : 0,
158 'catalog_processed' => ! empty( $job->catalog_processed ),
159 'created_at' => isset( $job->created_at ) ? (string) $job->created_at : null,
160 'updated_at' => isset( $job->updated_at ) ? (string) $job->updated_at : null,
161 );
162 }
163 }
164