suppress_errors(true); try { foreach(Schema::cancellation($wpdb) as $table=>$sql){ if(in_array($table,[Tables::name($wpdb,'cancellation_policies'),Tables::name($wpdb,'cancellation_rules')],true)){ if(!$wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s',$wpdb->esc_like($table)))){dbDelta($sql);$this->check($wpdb);} }else{ $columns=$wpdb->get_col($wpdb->prepare('SHOW COLUMNS FROM %i',$table));$this->check($wpdb); $changes=[]; if($table===\ABeCe\Booking\Infrastructure\Database\Tables::name( $wpdb, 'bookings' )){ foreach(['cancellation_policy_snapshot'=>'longtext NULL AFTER pricing_snapshot','no_show_fee'=>"bigint NOT NULL DEFAULT '0' AFTER no_show_by_user_id",'no_show_snapshot'=>'longtext NULL AFTER no_show_fee'] as $name=>$definition)if(!in_array($name,$columns,true))$changes[]="ADD $name $definition"; }else{ $credit=$table===\ABeCe\Booking\Infrastructure\Database\Tables::name( $wpdb, 'credit_transactions' ); if($credit&&!in_array('business_reference',$columns,true))$changes[]='ADD business_reference varchar(190) DEFAULT NULL AFTER amount'; $indexes=$wpdb->get_col($wpdb->prepare('SHOW INDEX FROM %i',$table),2);$this->check($wpdb); $legacy=$credit?'uq_asb_credit_booking_type':'uq_asb_payment_booking_type';$unique=$credit?'uq_asb_credit_business_reference':'uq_asb_payment_business_reference'; // Add replacement uniqueness before dropping the old key, in the same atomic ALTER. if(!in_array($unique,$indexes,true))$changes[]='ADD UNIQUE KEY '.$unique.($credit?' (business_reference)':' (provider,provider_transaction_id)'); if(in_array($legacy,$indexes,true))$changes[]='DROP INDEX '.$legacy; } if($changes){$wpdb->query($wpdb->prepare('ALTER TABLE %i '.implode(', ',$changes),$table));$this->check($wpdb);} } Schema::verify( $wpdb, $table, Schema::adoptedPaymentShape($wpdb,$table) ?? ($table===\ABeCe\Booking\Infrastructure\Database\Tables::name( $wpdb, 'bookings' )&&in_array('external_contact_snapshot',$columns,true)?Schema::externalContacts($wpdb)[$table]:$sql) ); } }finally{$wpdb->suppress_errors($old);} } private function check(\wpdb $wpdb): void {if($wpdb->last_error)throw new RuntimeException(__('ABeCe Booking database migration failed. Existing data has been retained.','abece-booking'));} }