blob: ae33d501817cf0d9ac0f8f6b3efafb0987114d6b [file] [log] [blame]
avm9996399bb77c2020-01-27 03:15:08 +01001<?php
2class gtfs {
3 //private static $files = ["calendar_dates", "calendar", "routes", "stop_times", "stops", "trips"];
4
5 private $db;
6
7 private static $dow = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
8
9 function __construct($path = null) {
10 global $conf;
11
12 try {
13 $this->db = new PDO('sqlite:'.($conf["databaseFile"]));
14 } catch (PDOException $e) {
15 die("SQLite error: $e\n");
16 }
17 }
18
19 static function timeSinceMidnight() {
20 //return 8*60*60 + 9*60; //TESTING
21 return (time() - mktime(0, 0, 0));
22 }
23
24 static function today() {
25 return date("Ymd");
26 }
27
28 static function time2seconds($time) {
29 $timeSinceMidnight = self::timeSinceMidnight();
30
31 $boom = explode(":", $time);
32 if (count($boom) != 3) return null;
33
34 return ((($boom[0]*60) + $boom[1])*60 + $boom[2]) % (24*60*60);
35 }
36
37 private function fetchAll($sql) {
38 $query = $this->db->query($sql);
39 if (!$query) return false;
40
41 return $query->fetchAll(PDO::FETCH_ASSOC);
42 }
43
44 private function fetchAllPrepared($sql, $values) {
45 $query = $this->db->prepare($sql);
46 if (!$query) return false;
47
48 $query->execute($values);
49 return $query->fetchAll(PDO::FETCH_ASSOC);
50 }
51
52 private function fetchTable($table, $filters = [], $orderedField = null) {
53 $order = ($orderedField === null ? "" : " ORDER BY $orderedField");
54
55 if (!count($filters)) {
56 return $this->fetchAll("SELECT * FROM $table".$order);
57 }
58
59 $whereConditions = [];
60 $values = [];
61 foreach ($filters as $filter) {
62 $whereConditions[] = $filter[0]." = ?";
63 $values[] = $filter[1];
64 }
65
66 return $this->fetchAllPrepared("SELECT * FROM $table WHERE ".implode(" AND ", $whereConditions).$order, $values);
67 }
68
69 function getRoutes() {
70 return $this->fetchTable("routes");
71 }
72
73 function getTrips($route) {
74 return $this->fetchTable("trips", [["route_id", $route]]);
75 }
76
77 function getStations($ordered = false) {
78 return $this->fetchTable("stops", [["location_type", Gtfs\Stop\LocationType::STATION]], ($ordered ? "stop_name" : null));
79 }
80
81 function getStop($stop) {
82 $results = $this->fetchTable("stops", [["stop_id", $stop]]);
83
84 if (!count($results)) return null;
85
86 return $results[0];
87 }
88
89 function getPlatforms($stop) {
90 $results = $this->fetchTable("stops", [["parent_station", $stop], ["location_type", Gtfs\Stop\LocationType::STOP]], "stop_id");
91
92 return $results;
93 }
94
avm99963dfd7bd52020-01-27 03:37:54 +010095 const TIME_LIMIT = 30;
avm9996399bb77c2020-01-27 03:15:08 +010096 function getStopTimes($stop, $timeLimit = self::TIME_LIMIT) {
avm9996378011ca2020-07-05 13:49:26 +020097 $platforms = $this->getPlatforms($stop);
avm9996399bb77c2020-01-27 03:15:08 +010098
99 $values = [];
avm9996378011ca2020-07-05 13:49:26 +0200100 foreach ($platforms as $i => $s) {
101 $values[":stop".(int)$i] = $s["stop_id"]; // Stops
avm9996399bb77c2020-01-27 03:15:08 +0100102 }
103
avm9996378011ca2020-07-05 13:49:26 +0200104 $stopParameters = array_keys($values);
105
106 $rdow = (int)(new DateTime("now"))->format("w");
avm9996399bb77c2020-01-27 03:15:08 +0100107 $dow = self::$dow[$rdow]; // Today's day of week
108 $dow2 = self::$dow[($rdow + 1) % 7]; // Tomorrow's day of week
109
avm9996378011ca2020-07-05 13:49:26 +0200110 $values[":today"] = (int)(new DateTime("now"))->format("Ymd"); // Today's date
111 $values[":tomorrow"] = (int)(new DateTime("tomorrow"))->format("Ymd"); // Tomorrow's date
112 $values[":now"] = (new DateTime("now"))->format("H:i:s");
avm9996399bb77c2020-01-27 03:15:08 +0100113
avm9996378011ca2020-07-05 13:49:26 +0200114 if (!count($platforms)) return [];
115
116 $sql = "SELECT st.*, t.*, r.*, c.*, cd.*
avm9996399bb77c2020-01-27 03:15:08 +0100117 FROM stop_times st
118 INNER JOIN trips t
119 ON st.trip_id = t.trip_id
120 INNER JOIN routes r
121 ON t.route_id = r.route_id
122 LEFT JOIN calendar c
123 ON t.service_id = c.service_id
124 LEFT JOIN calendar_dates cd
125 ON t.service_id = cd.service_id
126 WHERE
avm9996378011ca2020-07-05 13:49:26 +0200127 st.stop_id IN (".implode(", ", $stopParameters).") AND
avm9996399bb77c2020-01-27 03:15:08 +0100128 (
129 cd.service_id IS NULL OR
130 cd.exception_type = ".(int)Gtfs\CalendarDate\ExceptionType::ADDED."
131 ) AND
132 (
133 (
134 (
135 (
avm9996378011ca2020-07-05 13:49:26 +0200136 time(:now) < time('00:00:00', '-".(int)$timeLimit." minutes') AND
137 st.departure_time BETWEEN time(:now) AND time(:now, '".(int)$timeLimit." minutes')
avm9996399bb77c2020-01-27 03:15:08 +0100138 ) OR
139 (
avm9996378011ca2020-07-05 13:49:26 +0200140 time(:now) >= time('00:00:00', '-".(int)$timeLimit." minutes') AND
141 st.departure_time BETWEEN time(:now) AND strftime('24:%M:%S', :now, '".(int)$timeLimit." minutes')
avm9996399bb77c2020-01-27 03:15:08 +0100142 )
143 ) AND
144 (
145 c.service_id IS NULL OR
146 (
avm9996378011ca2020-07-05 13:49:26 +0200147 c.start_date <= :today AND
148 c.end_date >= :today AND
avm9996399bb77c2020-01-27 03:15:08 +0100149 c.$dow = ".(int)Gtfs\Calendar\CalendarDay::AVAILABLE."
150 )
151 ) AND
152 (
153 cd.service_id IS NULL OR
avm9996378011ca2020-07-05 13:49:26 +0200154 cd.date = :today
avm9996399bb77c2020-01-27 03:15:08 +0100155 )
156 ) OR
157 (
158 (
159 (
avm9996378011ca2020-07-05 13:49:26 +0200160 time(:now) < time('00:00:00', '-".(int)$timeLimit." minutes') AND
161 st.departure_time BETWEEN ((strftime('%H', :now) + 24) || strftime(':%M:%S', :now)) AND ((strftime('%H', :now, '".(int)$timeLimit." minutes') + 24) || strftime(':%M:%S', :now, '".(int)$timeLimit." minutes'))
avm9996399bb77c2020-01-27 03:15:08 +0100162 ) OR
163 (
avm9996378011ca2020-07-05 13:49:26 +0200164 time(:now) >= time('00:00:00', '-".(int)$timeLimit." minutes') AND
165 st.departure_time BETWEEN time(:now) AND strftime('24:%M:%S', :now, '".(int)$timeLimit." minutes')
avm9996399bb77c2020-01-27 03:15:08 +0100166 )
167 ) AND
168 (
169 c.service_id IS NULL OR
170 (
avm9996378011ca2020-07-05 13:49:26 +0200171 c.start_date <= :tomorrow AND
172 c.end_date >= :tomorrow AND
avm9996399bb77c2020-01-27 03:15:08 +0100173 c.$dow2 = ".(int)Gtfs\Calendar\CalendarDay::AVAILABLE."
174 )
175 ) AND
176 (
177 cd.service_id IS NULL OR
avm9996378011ca2020-07-05 13:49:26 +0200178 cd.date = :tomorrow
avm9996399bb77c2020-01-27 03:15:08 +0100179 )
180 )
181 )
182 ORDER BY departure_time ASC";
183
184 $result = $this->fetchAllPrepared($sql, $values);
185 if ($result === false) {
186 echo implode("\n", $this->db->errorInfo());
187 exit();
188 }
189
190 return $result;
191 }
192
193 function __destruct() {
194 $this->db = null;
195 }
196}