PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.20
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.20
1.10.20 1.10.19 1.10.18 1.10.17 1.10.16 1.10.15 1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 1.10.1 1.10.0 1.9.17 1.9.15 1.9.16 All 164 releases
← All changes | includes/Services/Cloud_Print_Trigger_Service.php +31 -3 1.10.1 → 1.10.20 View file →
@@ -108,8 +108,23 @@
108 108 return \in_array( $trigger, array( 'created', 'paid' ), true ) ? $trigger : self::DEFAULT_TRIGGER;
109 109 }
110 110
111 111 /**
112 + * Order-meta key holding how many jobs an assignment has already fired.
113 + *
114 + * Keyed by the same triple the job count filters on, so two rules that
115 + * differ only by trigger keep separate marks. Hashed because a template id
116 + * can be an arbitrary virtual slug and meta keys have a length limit.
117 + *
118 + * @param string $printer_id Printer id.
119 + * @param string $template_id Template id.
120 + * @param string $trigger Normalized trigger.
121 + */
122 + private static function fired_meta_key( string $printer_id, string $template_id, string $trigger ): string {
123 + return '_wcpos_cp_fired_' . md5( $printer_id . "\0" . $template_id . "\0" . $trigger );
124 + }
125 +
126 + /**
112 127 * Create jobs for an order according to the configured assignments.
113 128 *
114 129 * @param int $order_id Order ID.
115 130 */
@@ -177,9 +192,17 @@
177 192 'template_id' => $template_id,
178 193 'trigger' => $trigger,
179 194 )
180 195 );
181 - $shortfall = max( 0, $copies - $existing );
196 + // Counting rows alone cannot dedupe: the rows are deletable (by
197 + // the admin, and by the retention purge), and handle_order()
198 + // runs again on every later status change. A deleted receipt
199 + // would then read as never printed and be queued a second time
200 + // — including one the admin had deliberately cancelled. The
201 + // high-water mark survives the rows it counts.
202 + $fired_key = self::fired_meta_key( $printer_id, $template_id, $trigger );
203 + $fired = (int) $order->get_meta( $fired_key );
204 + $shortfall = max( 0, $copies - max( $existing, $fired ) );
182 205 if ( 0 === $shortfall ) {
183 206 continue;
184 207 }
185 208
@@ -206,8 +229,13 @@
206 229 $template,
207 230 array(),
208 231 $trigger
209 232 );
233 + if ( $job_id > 0 ) {
234 + ++$fired;
235 + $order->update_meta_data( $fired_key, (string) $fired );
236 + $order->save_meta_data();
237 + }
210 238 if ( 0 === $job_id ) {
211 239 Logger::log(
212 240 sprintf(
213 241 'Cloud print: skipping assignment for printer "%s" — template "%s" is not printable on provider "%s".',
@@ -285,11 +313,11 @@
285 313 // requires_submit) — a legacy row without a provider is star-cloudprnt.
286 314 $provider = Provider::normalize( (string) ( $printer['provider'] ?? '' ) );
287 315 $drawer_options = self::drawer_options_for_provider( $provider, $drawer_options );
288 316
289 - // The resolver owns both halves of the answer for every provider: an
317 + // Provider::format() owns both halves of the answer for every provider: an
290 318 // empty kind means the template cannot be rendered on this printer.
291 - $fmt = ( new Print_Format_Resolver() )->resolve( $printer, $template );
319 + $fmt = Provider::format( $printer, $template );
292 320 if ( '' === $fmt['kind'] ) {
293 321 return 0;
294 322 }
295 323