PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.18
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.18
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/Sync/Digest_Index.php +50 -35 1.10.131.10.18 View file →
@@ -418,15 +418,15 @@
418 418 $live_rows = isset( $row['digest']['live_rows'] ) ? (string) $row['digest']['live_rows'] : '';
419 419 // Products are the one collection whose servability is NARROWER than a live
420 420 // row: POS visibility and the readable-catalog scope both apply, so the
421 421 // richer reader owns them. Every other id-space is exactly its live row.
422 - $products = 'products' === $collection;
423 - if ( ! $products && ( '' === $live_rows || ! method_exists( $this, $live_rows ) ) ) {
422 + $servable = $row['digest']['servable'] ?? null;
423 + if ( null === $servable && ( '' === $live_rows || ! method_exists( $this, $live_rows ) ) ) {
424 424 return $ids;
425 425 }
426 426 $wpdb->last_error = '';
427 - if ( $products ) {
428 - $servable_ids = $this->servable_product_ids( $ids, true );
427 + if ( null !== $servable ) {
428 + $servable_ids = $this->$servable( $ids, true );
429 429 } else {
430 430 $predicate = (string) \call_user_func( array( $this, $live_rows ), 'requested.id' );
431 431 $requested = implode( ' UNION ALL ', array_fill( 0, \count( $ids ), 'SELECT %d AS id' ) );
432 432 $servable_ids = $wpdb->get_col(
@@ -536,18 +536,18 @@
536 536 global $wpdb;
537 537 $bucket_size = max( 1, (int) ( $range['bucket_size'] ?? 1 ) );
538 538 $window_start = max( 0, (int) ( $range['start'] ?? 0 ) );
539 539 $window_end = max( 0, (int) ( $range['end'] ?? 0 ) );
540 - $publish = 'products' === $collection && 'publish' === ( $filters['status'] ?? '' );
541 - $object_types = self::OBJECT_TYPES_SQL;
542 - $current_sql = $this->row_digest_select_sql( 'p.ID >= %d AND p.ID < %d' );
543 - if ( 'customers' === $collection ) {
544 - $object_types = "('customer')";
545 - $current_sql = $this->customer_digest_select_sql( 'u.ID >= %d AND u.ID < %d' );
546 - } elseif ( 'orders' === $collection ) {
547 - $object_types = "('order')";
548 - $current_sql = $this->order_digest_select_sql( '{id} >= %d AND {id} < %d' );
540 + $digest = Collections::row( $collection )['digest'] ?? null;
541 + if ( null === $digest ) {
542 + return array(
543 + 'buckets' => array(),
544 + 'max_id' => 0,
545 + );
549 546 }
547 + $publish = isset( Collections::row( $collection )['digest']['published_ids'] ) && 'publish' === ( $filters['status'] ?? '' );
548 + $object_types = "('" . implode( "','", $digest['object_types'] ) . "')";
549 + $current_sql = $this->{$digest['select']}( $digest['id_column'] . ' >= %d AND ' . $digest['id_column'] . ' < %d' );
550 550 $current_scope = $publish ? $this->product_servable_predicate_sql( 't.id', true ) : array(
551 551 'sql' => '',
552 552 'args' => array(),
553 553 );
@@ -655,8 +655,9 @@
655 655 public function bucket_drift( array $range ): array {
656 656 global $wpdb;
657 657 $range_start = max( 0, (int) ( $range['start'] ?? 0 ) );
658 658 $range_end = max( 0, (int) ( $range['end'] ?? 0 ) );
659 + $digest = Collections::row( 'products' )['digest'];
659 660 $table = $this->table_name();
660 661
661 662 // Same-formula invariant: the current side must digest identically to the stored side.
662 663 $this->raise_group_concat_max_len();
@@ -664,17 +665,17 @@
664 665 $wpdb->prepare(
665 666 'SELECT cur.id AS id,'
666 667 . " CASE WHEN d.digest IS NULL THEN 'missing_stored' ELSE 'changed' END AS status,"
667 668 . ' d.digest AS stored_digest, cur.crc AS current_digest, cur.object_type AS object_type'
668 - . ' FROM (' . $this->row_digest_select_sql( 'p.ID >= %d AND p.ID < %d' ) . ') cur'
669 + . ' FROM (' . $this->{$digest['select']}( $digest['id_column'] . ' >= %d AND ' . $digest['id_column'] . ' < %d' ) . ') cur'
669 670 . " LEFT JOIN {$table} d ON d.object_id = cur.id AND d.object_type = cur.object_type"
670 671 . ' WHERE d.digest IS NULL OR d.digest <> cur.crc'
671 672 . ' UNION ALL'
672 673 . " SELECT d.object_id AS id, 'deleted' AS status, d.digest AS stored_digest, NULL AS current_digest, d.object_type AS object_type"
673 674 . " FROM {$table} d"
674 - . ' WHERE d.object_type IN ' . self::OBJECT_TYPES_SQL
675 + . ' WHERE d.object_type IN ' . "('" . implode( "','", $digest['object_types'] ) . "')"
675 676 . ' AND d.object_id >= %d AND d.object_id < %d'
676 - . ' AND NOT ' . $this->live_row_exists_sql( 'd.object_id' )
677 + . ' AND NOT ' . $this->{$digest['live_rows']}( 'd.object_id' )
677 678 . ' ORDER BY id ASC',
678 679 $range_start,
679 680 $range_end,
680 681 $range_start,
@@ -725,15 +726,14 @@
725 726
726 727 $servable_join = '';
727 728 $servable_filter = '';
728 729 $servable_args = array();
729 - if ( 'customers' === $collection ) {
730 - $inner_sql = $this->customer_digest_select_sql( 'u.ID >= %d AND u.ID < %d' );
731 - } elseif ( 'orders' === $collection ) {
732 - // Orders bucket over their own id-space (HPOS o.id / CPT p.ID) via the {id} placeholder.
733 - $inner_sql = $this->order_digest_select_sql( '{id} >= %d AND {id} < %d' );
734 - } else {
735 - $inner_sql = $this->row_digest_select_sql( 'p.ID >= %d AND p.ID < %d' );
730 + $digest = Collections::row( $collection )['digest'] ?? null;
731 + if ( null === $digest ) {
732 + return array();
733 + }
734 + $inner_sql = $this->{$digest['select']}( $digest['id_column'] . ' >= %d AND ' . $digest['id_column'] . ' < %d' );
735 + if ( isset( $digest['servable'] ) ) {
736 736 $servable_join = " INNER JOIN {$wpdb->posts} catalog_post ON catalog_post.ID = cur.id";
737 737 if ( 'publish' === ( $filters['status'] ?? '' ) ) {
738 738 $servable_join .= " LEFT JOIN {$wpdb->posts} parent_product ON parent_product.ID = catalog_post.post_parent"
739 739 . " AND catalog_post.post_type = 'product_variation'";
@@ -904,28 +904,43 @@
904 904 *
905 905 * @return array{sql: string, args: array<int, int>}
906 906 */
907 907 private function live_max_id_sql( string $collection, bool $publish ): array {
908 - global $wpdb;
909 - if ( 'customers' === $collection ) {
908 + $digest = Collections::row( $collection )['digest'] ?? null;
909 + if ( null === $digest ) {
910 910 return array(
911 - 'sql' => "SELECT MAX(u.ID) FROM {$wpdb->users} u",
911 + 'sql' => 'SELECT NULL WHERE 1 = 0',
912 912 'args' => array(),
913 913 );
914 914 }
915 - if ( 'orders' === $collection ) {
916 - if ( $this->orders_are_hpos() ) {
917 - $orders_table = $wpdb->prefix . 'wc_orders';
918 - return array(
919 - 'sql' => "SELECT MAX(o.id) FROM {$orders_table} o WHERE " . $this->live_order_predicate_sql( 'o' ),
920 - 'args' => array(),
921 - );
922 - }
915 + return $this->{$digest['live_max']}( $publish );
916 + }
917 +
918 + private function customer_live_max_id_sql(): array {
919 + global $wpdb;
920 + return array(
921 + 'sql' => "SELECT MAX(u.ID) FROM {$wpdb->users} u",
922 + 'args' => array(),
923 + );
924 + }
925 +
926 + private function order_live_max_id_sql(): array {
927 + global $wpdb;
928 + if ( $this->orders_are_hpos() ) {
929 + $orders_table = $wpdb->prefix . 'wc_orders';
923 930 return array(
924 - 'sql' => "SELECT MAX(p.ID) FROM {$wpdb->posts} p WHERE " . $this->live_order_predicate_sql( 'p' ),
931 + 'sql' => "SELECT MAX(o.id) FROM {$orders_table} o WHERE " . $this->live_order_predicate_sql( 'o' ),
925 932 'args' => array(),
926 933 );
927 934 }
935 + return array(
936 + 'sql' => "SELECT MAX(p.ID) FROM {$wpdb->posts} p WHERE " . $this->live_order_predicate_sql( 'p' ),
937 + 'args' => array(),
938 + );
939 + }
940 +
941 + private function product_live_max_id_sql( bool $publish ): array {
942 + global $wpdb;
928 943 if ( ! $publish ) {
929 944 return array(
930 945 'sql' => "SELECT MAX(p.ID) FROM {$wpdb->posts} p WHERE " . $this->live_product_predicate_sql( 'p' ),
931 946 'args' => array(),