← All changes
|
includes/Services/Cloud_Print_Trigger_Service.php
+31
-3
1.10.0
→
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 | |