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_Relay_Service.php +51 -5 1.9.15 → 1.10.20 View file →
@@ -136,8 +136,14 @@
136 136 'registered_at' => time(),
137 137 )
138 138 );
139 139 delete_transient( self::DOWN_TRANSIENT );
140 + // status() consults the per-printer negative cache before DOWN_TRANSIENT,
141 + // so clearing the site-wide marker alone is not enough: a printer that hit
142 + // an "unknown site" 404 backed off for REREGISTER_GUARD, and without this
143 + // it would keep returning null for the full hour even though the site_key
144 + // is valid again. Dropping those entries lets status resume on the next call.
145 + self::clear_status_cache();
140 146
141 147 // The printer URL is always rebuilt from the validated site_key —
142 148 // never from the relay response — so a compromised relay cannot
143 149 // point printers (and their tokens) at another host.
@@ -197,9 +203,12 @@
197 203 $state = array(
198 204 'enabled' => false,
199 205 'available' => true,
200 206 );
201 - if ( 1 === preg_match( '/^[a-f0-9]{32}$/', (string) ( $relay['site_key'] ?? '' ) ) ) {
207 + // Case-insensitive to match valid_credentials(): registration lowercases
208 + // on write, but a legacy uppercase key still signs hints and status
209 + // calls fine, so it must not report itself disabled to the settings app.
210 + if ( 1 === preg_match( '/^[a-f0-9]{32}$/i', (string) ( $relay['site_key'] ?? '' ) ) ) {
202 211 $state['enabled'] = true;
203 212 $state['printer_base_url'] = self::printer_base_url( (string) $relay['site_key'] );
204 213 }
205 214
@@ -286,8 +295,23 @@
286 295 // registry was rebuilt, so a guarded re-registration restores the
287 296 // same deterministic site key.
288 297 if ( 404 === $code && \is_array( $data ) && 'unknown site' === ( $data['error'] ?? '' ) ) {
289 298 self::schedule_reregistration();
299 +
300 + // Back off for the re-registration window, not the cache window.
301 + // This 404 is not a transient relay hiccup: the stored site_key is
302 + // not in the relay's registry, and nothing about that changes until
303 + // a re-registration succeeds — which is itself rate-limited to once
304 + // per REREGISTER_GUARD. Falling through to the 30s failure window
305 + // would replay the identical 404 twice a minute forever whenever a
306 + // site cannot re-register (the relay cannot reach its verification
307 + // endpoint, say), which is exactly what one site was doing: ~2,000
308 + // pointless requests a day. A successful registration deletes
309 + // DOWN_TRANSIENT, so this self-heals the moment re-registration
310 + // works rather than pinning the site down for the full hour.
311 + self::note_status_failure( $key, self::REREGISTER_GUARD );
312 +
313 + return null;
290 314 }
291 315 if ( 200 !== $code || ! \is_array( $data ) ) {
292 316 self::note_status_failure( $key );
293 317
@@ -405,13 +429,35 @@
405 429 /**
406 430 * Record a failed status call: per-printer negative cache plus the
407 431 * site-wide down marker so other printers skip their calls entirely.
408 432 *
409 - * @param string $transient_key Per-printer status transient key.
433 + * @param string $transient_key Per-printer status transient key.
434 + * @param int|null $ttl Backoff seconds; defaults to STATUS_CACHE_TTL.
435 + * Callers pass a longer window when the
436 + * failure cannot clear on its own within it.
410 437 */
411 - private static function note_status_failure( string $transient_key ): void {
412 - set_transient( $transient_key, array( 'failed' => true ), self::STATUS_CACHE_TTL );
413 - set_transient( self::DOWN_TRANSIENT, true, self::STATUS_CACHE_TTL );
438 + private static function note_status_failure( string $transient_key, ?int $ttl = null ): void {
439 + $ttl = null === $ttl ? self::STATUS_CACHE_TTL : max( 1, $ttl );
440 + set_transient( $transient_key, array( 'failed' => true ), $ttl );
441 + set_transient( self::DOWN_TRANSIENT, true, $ttl );
442 + }
443 +
444 + /**
445 + * Drop every per-printer status cache.
446 + *
447 + * Because status() checks the per-printer negative cache before DOWN_TRANSIENT,
448 + * a successful (re-)registration must clear these entries too — otherwise a
449 + * printer that backed off on an "unknown site" 404 keeps returning null for
450 + * the full REREGISTER_GUARD window despite the site_key being valid again.
451 + * Dropping any live positive caches is harmless: the next call re-polls.
452 + */
453 + private static function clear_status_cache(): void {
454 + foreach ( ( new Cloud_Print_Registry() )->get_printers() as $printer ) {
455 + $printer_id = (string) ( $printer['id'] ?? '' );
456 + if ( '' !== $printer_id ) {
457 + delete_transient( self::STATUS_TRANSIENT_PREFIX . $printer_id );
458 + }
459 + }
414 460 }
415 461
416 462 /**
417 463 * Schedule one guarded background re-registration.