blob: b4c49dae20aa91538afdd33770ffb546ed5c2199 [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
95 const TIME_LIMIT = 160;
96 function getStopTimes($stop, $timeLimit = self::TIME_LIMIT) {
97 $stops = $this->getPlatforms($stop);
98
99 $values = [];
100 foreach ($stops as $s) {
101 $values[] = $s["stop_id"]; // Stops
102 }
103
104 $rdow = (int)date("w");
105 $dow = self::$dow[$rdow]; // Today's day of week
106 $dow2 = self::$dow[($rdow + 1) % 7]; // Tomorrow's day of week
107
108 if (!count($stops)) return [];
109
110 $sql = "SELECT st.*, t.*, r.*, c.*, cd.*, strftime('%Y%m%d', 'now', 'localtime') as today, strftime('%Y%m%d', 'now', 'localtime', '1 day') as tomorrow, time('now', 'localtime') as now
111 FROM stop_times st
112 INNER JOIN trips t
113 ON st.trip_id = t.trip_id
114 INNER JOIN routes r
115 ON t.route_id = r.route_id
116 LEFT JOIN calendar c
117 ON t.service_id = c.service_id
118 LEFT JOIN calendar_dates cd
119 ON t.service_id = cd.service_id
120 WHERE
121 st.stop_id IN (".implode(", ", array_fill(0, count($stops), "?")).") AND
122 (
123 cd.service_id IS NULL OR
124 cd.exception_type = ".(int)Gtfs\CalendarDate\ExceptionType::ADDED."
125 ) AND
126 (
127 (
128 (
129 (
130 time(now) < time('00:00:00', '-".(int)$timeLimit." minutes') AND
131 st.departure_time BETWEEN time(now) AND time(now, '".(int)$timeLimit." minutes')
132 ) OR
133 (
134 time(now) >= time('00:00:00', '-".(int)$timeLimit." minutes') AND
135 st.departure_time BETWEEN time(now) AND strftime('24:%M:%S', now, '".(int)$timeLimit." minutes')
136 )
137 ) AND
138 (
139 c.service_id IS NULL OR
140 (
141 c.start_date <= today AND
142 c.end_date >= today AND
143 c.$dow = ".(int)Gtfs\Calendar\CalendarDay::AVAILABLE."
144 )
145 ) AND
146 (
147 cd.service_id IS NULL OR
148 cd.date = today
149 )
150 ) OR
151 (
152 (
153 (
154 time(now) < time('00:00:00', '-".(int)$timeLimit." minutes') AND
155 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'))
156 ) OR
157 (
158 time(now) >= time('00:00:00', '-".(int)$timeLimit." minutes') AND
159 st.departure_time BETWEEN time(now) AND strftime('24:%M:%S', now, '".(int)$timeLimit." minutes')
160 )
161 ) AND
162 (
163 c.service_id IS NULL OR
164 (
165 c.start_date <= tomorrow AND
166 c.end_date >= tomorrow AND
167 c.$dow2 = ".(int)Gtfs\Calendar\CalendarDay::AVAILABLE."
168 )
169 ) AND
170 (
171 cd.service_id IS NULL OR
172 cd.date = tomorrow
173 )
174 )
175 )
176 ORDER BY departure_time ASC";
177
178 $result = $this->fetchAllPrepared($sql, $values);
179 if ($result === false) {
180 echo implode("\n", $this->db->errorInfo());
181 exit();
182 }
183
184 return $result;
185 }
186
187 function __destruct() {
188 $this->db = null;
189 }
190}