Improved www.ttss.krakow.pl
Jacek Kowalski
2019-07-07 ae517065da8e530f3964b0cbf4ecf90c2c71b948
commit | author | age
cbce8b 1 <?php
JK 2 include('common.php');
3 include('stops.php');
4
5 try {
6     // Reject invalid input
7     if(!isset($_GET['query'])) throw new UnexpectedValueException();
8     if(empty($_GET['query'])) throw new UnexpectedValueException();
9     if(strlen($_GET['query']) > 50) throw new UnexpectedValueException();
10     
11     // Split stop name into words
12     $words = split_stop_name($_GET['query']);
13     $find_ondemand = in_array('nz', $words);
14     
15     // Initialize a DB connection and a query
16     $pdo = new PDO('sqlite:stops.db', NULL, NULL, array(
17         PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
18     ));
19     $st = $pdo->prepare('SELECT DISTINCT id FROM stop_search WHERE word LIKE ?'.($find_ondemand ? '' : ' AND word != \'nz\'').' ORDER BY id DESC');
20     
21     // Find matching stops (their IDs)
22     $ids = NULL;
23     foreach($words as $word) {
24         if(empty($word)) continue;
25         
26         // Find stop IDs with names matching the word
27         $st->execute(array($word.'%'));
28         $results = $st->fetchAll(PDO::FETCH_COLUMN);
29         $st->closeCursor();
30         
31         if(is_array($ids)) {
32             // Merge results with list for previous words
33             $ids = array_intersect($ids, $results);
34         } else {
35             // First search - initialize results list
36             $ids = $results;
37         }
38         
39         // No results will be found
40         if(count($ids) == 0) break;
41     }
42     
43     // Close a DB connection
44     unset($st, $pdo);
45     
46     // No query was executed - return empty list
47     if(!is_array($ids)) throw new UnexpectedValueException();
48     
49     // Build a structure for the UI
50     $stop_list = [];
ca42d3 51     $query_lower = normalize_name_cmp($_GET['query']);
cbce8b 52     foreach($ids as $id) {
d87cf0 53         $letters = similar_text(
cbce8b 54             $query_lower,
ca42d3 55             normalize_name_cmp($stops[$id]),
cbce8b 56             $percent
JK 57         );
d87cf0 58         $percent += $letters * 100;
cbce8b 59         // -5 due to UTF-8
JK 60         if(substr($stops[$id], -5) == '(nż)' && !$find_ondemand) {
61             $percent /= 2;
62         }
63         $stop_list[] = [
64             'id' => $id,
ca42d3 65             'name' => normalize_name($stops[$id]),
cbce8b 66             'type' => 'stop',
JK 67             'relevance' => $percent,
68         ];
69     }
70     
71     // Sort stops by relevance
72     usort($stop_list, function($a, $b) {
73         $rel = $b['relevance'] - $a['relevance'];
74         if($rel == 0) return strcasecmp($a['name'], $b['name']);
75         return $rel;
76     });
77     
78     // Return JSON
79     header('Content-Type: application/json');
80     echo json_encode($stop_list);
81 } catch(UnexpectedValueException $e) {
82     header('Content-Type: application/json');
83     echo '[]';
84 } catch(Exception $e) {
85     header('HTTP/1.1 503 Service Unavailable');
86     echo $e->getMessage();
87 }