| @@ -184,21 +184,25 @@ | ||
| 184 | 184 | |
| 185 | 185 | return $results ?: []; |
| 186 | 186 | } |
| 187 | 187 | |
| 188 | - public function existsForTripDateTime(int $tripId, string $departureDate, ?string $departureTime): bool | |
| 188 | + public function existsForTripDateTime(int $tripId, string $departureDate, ?string $departureTime, ?int $excludeId = null): bool | |
| 189 | 189 | { |
| 190 | 190 | $table = esc_sql($this->table); |
| 191 | 191 | |
| 192 | + // Optional so update() can ignore the row it is editing; omitted, behaviour | |
| 193 | + // is exactly as before for existing callers. | |
| 194 | + $exclude = $excludeId !== null ? $this->wpdb->prepare(' AND id <> %d', $excludeId) : ''; | |
| 195 | + | |
| 192 | 196 | if ($departureTime === null || $departureTime === '') { |
| 193 | 197 | $count = (int) $this->wpdb->get_var($this->wpdb->prepare( |
| 194 | - "SELECT COUNT(*) FROM `{$table}` WHERE trip_id = %d AND departure_date = %s AND departure_time IS NULL", | |
| 198 | + "SELECT COUNT(*) FROM `{$table}` WHERE trip_id = %d AND departure_date = %s AND departure_time IS NULL{$exclude}", | |
| 195 | 199 | $tripId, |
| 196 | 200 | $departureDate |
| 197 | 201 | )); |
| 198 | 202 | } else { |
| 199 | 203 | $count = (int) $this->wpdb->get_var($this->wpdb->prepare( |
| 200 | - "SELECT COUNT(*) FROM `{$table}` WHERE trip_id = %d AND departure_date = %s AND departure_time = %s", | |
| 204 | + "SELECT COUNT(*) FROM `{$table}` WHERE trip_id = %d AND departure_date = %s AND departure_time = %s{$exclude}", | |
| 201 | 205 | $tripId, |
| 202 | 206 | $departureDate, |
| 203 | 207 | $departureTime |
| 204 | 208 | )); |
| @@ -342,15 +346,26 @@ | ||
| 342 | 346 | if (!empty($insertData['original_price']) && !empty($insertData['discounted_price']) && empty($data['discount_percentage'])) { |
| 343 | 347 | $insertData['discount_percentage'] = round((($insertData['original_price'] - $insertData['discounted_price']) / $insertData['original_price']) * 100, 2); |
| 344 | 348 | } |
| 345 | 349 | |
| 346 | - $this->wpdb->insert($table, $insertData, [ | |
| 350 | + $inserted = $this->wpdb->insert($table, $insertData, [ | |
| 347 | 351 | '%d', '%s', '%s', '%s', '%s', '%s', '%d', '%d', '%d', '%d', |
| 348 | 352 | '%s', '%f', '%f', '%f', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%d', |
| 349 | 353 | '%d', '%s', '%d', |
| 350 | 354 | ]); |
| 351 | - | |
| 352 | - return $this->wpdb->insert_id; | |
| 355 | + | |
| 356 | + // A rejected insert used to be swallowed: insert_id stays 0, the caller | |
| 357 | + // looks up row 0, gets null, and trips its own return type with a fatal | |
| 358 | + // TypeError. Fail loudly instead so the caller can report something useful. | |
| 359 | + if ($inserted === false) { | |
| 360 | + throw new \RuntimeException( | |
| 361 | + $this->wpdb->last_error !== '' | |
| 362 | + ? $this->wpdb->last_error | |
| 363 | + : 'Could not save the availability date.' | |
| 364 | + ); | |
| 365 | + } | |
| 366 | + | |
| 367 | + return (int) $this->wpdb->insert_id; | |
| 353 | 368 | } |
| 354 | 369 | |
| 355 | 370 | /** |
| 356 | 371 | * Update availability date |