PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.19
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.19
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 1.9.14 All 163 releases
← All changes | includes/API/V2/Write_Controller.php +15 -61 1.10.181.10.19 View file →
@@ -11,8 +11,9 @@
11 11 use WCPOS\WooCommercePOS\Services\Permission_Rules;
12 12 use WCPOS\WooCommercePOS\Services\Tax_Id_Types;
13 13 use WCPOS\WooCommercePOS\Sync\Api;
14 14 use WCPOS\WooCommercePOS\Sync\Collections;
15 +use WCPOS\WooCommercePOS\Sync\Create_Identity;
15 16 use WCPOS\WooCommercePOS\Sync\Endpoint_Permissions;
16 17 use WCPOS\WooCommercePOS\Sync\Header_Mirror;
17 18 use WCPOS\WooCommercePOS\Sync\Meta_Normalizer;
18 19 use WCPOS\WooCommercePOS\Sync\Mutation_Store;
@@ -52,9 +53,12 @@
52 53
53 54 /** @var mixed Duck-typed mutation store; tests inject an in-memory implementation. */
54 55 private $store;
55 56
57 + /** @var Create_Identity Shared proof for fresh and poisoned creates. */
58 + private Create_Identity $identity;
56 59
60 +
57 61 /**
58 62 * collection => wc/v3 route + how its uuid→id is resolved. ONE table, not
59 63 * per-collection controllers. Only collections whose resolver is correct AND
60 64 * exercised are exposed; the rest stay out until their phase:
@@ -99,8 +103,9 @@
99 103 }
100 104
101 105 public function __construct( $store = null ) {
102 106 $this->store = $store ? $store : new Mutation_Store();
107 + $this->identity = new Create_Identity( $this->store );
103 108 }
104 109
105 110 /** Resolve the collection-specific writer for registry metadata. */
106 111 private function writer( array $meta ) {
@@ -220,9 +225,14 @@
220 225 return $mismatch;
221 226 }
222 227 }
223 228 if ( is_array( $hit ) && 'poison' === ( $hit['status'] ?? '' ) ) {
224 - return $this->retry_identity_stamp( $meta, $m, $hit );
229 + $writer = $this->writer( $meta );
230 + $recovered = $this->identity->recover( $meta, $m, $hit, $writer );
231 + if ( is_wp_error( $recovered ) ) {
232 + return $recovered;
233 + }
234 + return $this->envelope_document( $this->document_for( $meta, $recovered['id'] ), $m['recordId'], $meta, $recovered['id'], $recovered['status'], $writer );
225 235 }
226 236 if ( is_array( $hit ) && in_array( ( $hit['status'] ?? '' ), array( 'done', 'applied' ), true ) ) {
227 237 if ( 'applied' === $hit['status'] && ! $this->store->finalize( $m['mutationId'], (int) $hit['remote_id'] ) ) {
228 238 return $this->finalize_error();
@@ -406,33 +416,12 @@
406 416 $this->store->mark_indeterminate( $m['mutationId'], 0, $response->get_status() );
407 417 return new WP_Error( 'woo_rxdb_sync_create_no_id', 'Create returned no server id.', array( 'status' => 502 ) );
408 418 }
409 419
410 - // Poison checkpoint, UUID persistence, and finalization remain shared here.
411 - $checkpointed = $this->store->mark_poison( $m['mutationId'], $new_id, $response->get_status() );
412 - $writer->persist( 'create_before_identity', $new_id, $m['payload'] );
413 - $identity_error = null;
414 - if ( ! $this->store->persist_uuid( $meta['id_type'], $new_id, $m['recordId'] ) ) {
415 - $identity_error = new WP_Error( 'woo_rxdb_sync_identity_persistence_failed', 'Unable to persist created record identity.', array( 'status' => 500 ) );
416 - } else {
417 - $resolved = $this->store->resolve_id_by_uuid( $meta['id_type'], $m['recordId'], $meta );
418 - if ( is_wp_error( $resolved ) ) {
419 - $identity_error = $resolved;
420 - } elseif ( $resolved !== $new_id ) {
421 - $identity_error = new WP_Error( 'woo_rxdb_sync_identity_persistence_failed', 'Unable to persist created record identity.', array( 'status' => 500 ) );
422 - }
420 + $stamped = $this->identity->stamp( $meta, $m, $new_id, $response->get_status(), $writer );
421 + if ( is_wp_error( $stamped ) ) {
422 + return $stamped;
423 423 }
424 - if ( ! $checkpointed ) {
425 - $this->store->mark_indeterminate( $m['mutationId'], $new_id, $response->get_status() );
426 - return $this->finalize_error();
427 - }
428 - if ( $identity_error ) {
429 - return $identity_error;
430 - }
431 - $writer->persist( 'create_after_identity', $new_id, $m['payload'] );
432 - if ( ! $this->store->finalize_poison( $m['mutationId'], $new_id ) ) {
433 - return $this->finalize_error();
434 - }
435 424 return $this->envelope_document( $this->document_for( $meta, $new_id ), $m['recordId'], $meta, $new_id, $response->get_status(), $writer );
436 425 }
437 426
438 427 /**
@@ -519,9 +508,9 @@
519 508 if ( $response->get_status() >= 400 ) {
520 509 return new WP_REST_Response( $response->get_data(), $response->get_status() );
521 510 }
522 511 $data = $response->get_data();
523 - $writer->persist( 'update', $id, $m['payload'], $current_bare, is_array( $data ) ? $data : array(), $prepared['context'] );
512 + $writer->after_update( $id, $m['payload'], $current_bare, is_array( $data ) ? $data : array(), $prepared['context'] );
524 513
525 514 $this->store->persist_uuid( $meta['id_type'], $id, $m['recordId'] );
526 515 $finalized = $this->checkpoint_and_finalize( $m['mutationId'], $id, $response->get_status() );
527 516 if ( is_wp_error( $finalized ) ) {
@@ -639,43 +628,8 @@
639 628 ? (int) $hit['response_status']
640 629 : ( 'create' === ( $hit['operation'] ?? '' ) ? 201 : null );
641 630 $writer = $this->writer( $meta );
642 631 return $this->envelope_document( $this->document_for( $meta, $remote_id ), $expected, $meta, $remote_id, $status, $writer );
643 - }
644 -
645 - private function retry_identity_stamp( array $meta, array $m, array $hit ) {
646 - $remote_id = (int) ( $hit['remote_id'] ?? 0 );
647 - $record_uuid = (string) ( $hit['record_uuid'] ?? '' );
648 - if ( $record_uuid !== $m['recordId'] ) {
649 - return new WP_Error( 'woo_rxdb_sync_identity_conflict', 'recordId disagrees with the stored mutation identity.', array( 'status' => 422 ) );
650 - }
651 - if ( 'create' !== ( $hit['operation'] ?? '' ) || $remote_id <= 0 ) {
652 - return new WP_Error( 'woo_rxdb_sync_identity_persistence_failed', 'Created record identity cannot be recovered safely.', array( 'status' => 500 ) );
653 - }
654 - $resolved = $this->store->resolve_id_by_uuid( $meta['id_type'], $record_uuid, $meta );
655 - if ( is_wp_error( $resolved ) ) {
656 - return $resolved;
657 - }
658 - if ( $resolved > 0 && $resolved !== $remote_id ) {
659 - return new WP_Error( 'woo_rxdb_sync_identity_persistence_failed', 'Stored create identity points at a different record.', array( 'status' => 500 ) );
660 - }
661 - if ( ! $this->store->persist_uuid( $meta['id_type'], $remote_id, $record_uuid ) ) {
662 - return new WP_Error( 'woo_rxdb_sync_identity_persistence_failed', 'Unable to persist created record identity.', array( 'status' => 500 ) );
663 - }
664 - $verified = $this->store->resolve_id_by_uuid( $meta['id_type'], $record_uuid, $meta );
665 - if ( is_wp_error( $verified ) ) {
666 - return $verified;
667 - }
668 - if ( $verified !== $remote_id ) {
669 - return new WP_Error( 'woo_rxdb_sync_identity_persistence_failed', 'Unable to persist created record identity.', array( 'status' => 500 ) );
670 - }
671 - $writer = $this->writer( $meta );
672 - $writer->persist( 'create_recovery', $remote_id, $m['payload'] );
673 - if ( ! $this->store->finalize_poison( $m['mutationId'], $remote_id ) ) {
674 - return $this->finalize_error();
675 - }
676 - $status = isset( $hit['response_status'] ) ? (int) $hit['response_status'] : 201;
677 - return $this->envelope_document( $this->document_for( $meta, $remote_id ), $record_uuid, $meta, $remote_id, $status, $writer );
678 632 }
679 633
680 634 /**
681 635 * Validate a client-submitted `tax_ids` payload against the v1 schema.