table = Db::prefix() . 'rsv_timetable_capacity'; } public function get_all($timetable_id, ?int $limit = null, int $skip = 0): array { if ($limit === null) { return Db::get_results( "SELECT * FROM {$this->table} WHERE timetable_id = %d ORDER BY id", [$timetable_id] ); } return Db::get_results( "SELECT * FROM {$this->table} WHERE timetable_id = %d ORDER BY id LIMIT %d OFFSET %d", [$timetable_id, $limit, $skip] ); } public function count_all($timetable_id): int { return (int) Db::get_var( "SELECT COUNT(*) FROM {$this->table} WHERE timetable_id = %d", [$timetable_id] ); } public function get(int $id): ?RsvTimetableCapacity { $row = Db::get_row( "SELECT * FROM {$this->table} WHERE id = %d", [$id], ARRAY_A ); return $row === null ? null : RsvTimetableCapacity::from_array($row); } public function create(RsvTimetableCapacity $capacity): int { return Db::insert($this->table, $capacity->to_array()); } public function delete(int $id): void { Db::delete($this->table, ['id' => $id]); } public function update(int $id, RsvTimetableCapacity $capacity): int { $capacity->id = $id; return Db::update($this->table, $capacity->to_array(), ['id' => $id]); } public function get_overlapping_capacity(int $timetable_id, DateTime $start, DateTime $end): array { $start_str = (clone $start)->setTimezone(wp_timezone())->format('Y-m-d H:i:s'); $end_str = (clone $end)->setTimezone(wp_timezone())->format('Y-m-d H:i:s'); return Db::get_results( "SELECT * FROM {$this->table} WHERE timetable_id = %d AND ( date = DATE(%s) OR ( repeat_period_in_days > 0 AND DATEDIFF(DATE(%s), date) >= 0 AND MOD(DATEDIFF(DATE(%s), date), repeat_period_in_days) = 0 ) ) AND DATE_ADD(DATE(%s), INTERVAL start_time MINUTE) < %s AND DATE_ADD(DATE(%s), INTERVAL end_time MINUTE) > %s ORDER BY start_time", [$timetable_id, $start_str, $start_str, $start_str, $start_str, $end_str, $start_str, $start_str] ); } public function get_capacities_for_date(int $timetable_id, DateTime $date) : array { $row = Db::get_results( "SELECT * FROM {$this->table} WHERE timetable_id = %d AND (date = DATE(%s) OR (repeat_period_in_days > 0 AND MOD(DATEDIFF(date, %s), repeat_period_in_days) = 0)) ORDER BY start_time ASC", [$timetable_id, $date->format('Y-m-d'), $date->format('Y-m-d')], ARRAY_A ); return array_map(fn($x) => RsvTimetableCapacity::from_array($x), $row); } public function get_available_range_for_date(int $timetable_id, DateTime $date) { if ($date === null) { throw new InvalidArgumentException('Invalid date'); } return Db::get_row( "SELECT MAX(start_time) AS `from`, MIN(end_time) AS `to` FROM {$this->table} WHERE timetable_id = %d AND (date = DATE(%s) OR (repeat_period_in_days > 0 AND MOD(DATEDIFF(date, %s), repeat_period_in_days) = 0))", [$timetable_id, $date->format('Y-m-d'), $date->format('Y-m-d')] ); } }