key => value, applied (replace-or-add) on save */ private array $pending = array(); /** * @var int */ private $term_id; public function __construct( int $term_id ) { $this->term_id = $term_id; } public function get_id(): int { return $this->term_id; } /** The term's _woocommerce_pos_uuid metas as objects carrying ->id (meta_id), * ->key, ->value — meta_id ASC so first-valid-wins matches the bulk read. */ public function get_meta_data(): array { global $wpdb; if ( ! isset( $wpdb ) ) { return array(); } $rows = $wpdb->get_results( $wpdb->prepare( "SELECT meta_id, meta_value FROM {$wpdb->termmeta} WHERE term_id = %d AND meta_key = %s ORDER BY meta_id ASC", $this->term_id, Pos_Uuid::META_KEY ), ARRAY_A ); $out = array(); foreach ( (array) $rows as $row ) { if ( ! \is_array( $row ) ) { continue; } $out[] = (object) array( 'id' => (int) ( $row['meta_id'] ?? 0 ), 'key' => Pos_Uuid::META_KEY, 'value' => $row['meta_value'] ?? '', ); } return $out; } public function update_meta_data( string $key, $value ): void { $this->pending[ $key ] = $value; // replace-or-add (matches WC_Data) } public function save_meta_data(): void { if ( \function_exists( 'update_term_meta' ) ) { foreach ( $this->pending as $key => $value ) { // update_term_meta() rewrites EVERY matching row to the new value // without collapsing extras — a collision re-key on a term with // duplicate uuid rows would keep the duplicates. Enforce the // one-row contract: delete all rows for the key, then add one. if ( \function_exists( 'get_term_meta' ) && \function_exists( 'delete_term_meta' ) && \count( (array) get_term_meta( $this->term_id, $key, false ) ) > 1 ) { delete_term_meta( $this->term_id, $key ); add_term_meta( $this->term_id, $key, $value, true ); continue; } update_term_meta( $this->term_id, $key, $value ); } } $this->pending = array(); } public function delete_meta_data_by_mid( $mid ): void { if ( $mid && \function_exists( 'delete_metadata_by_mid' ) ) { delete_metadata_by_mid( 'term', $mid ); } } }