]> git.openstreetmap.org Git - nominatim.git/blob - lib/TokenList.php
introduce classes for token list and token types
[nominatim.git] / lib / TokenList.php
1 <?php
2
3 namespace Nominatim;
4
5 require_once(CONST_BasePath.'/lib/TokenCountry.php');
6 require_once(CONST_BasePath.'/lib/TokenHousenumber.php');
7 require_once(CONST_BasePath.'/lib/TokenPostcode.php');
8 require_once(CONST_BasePath.'/lib/TokenSpecialTerm.php');
9 require_once(CONST_BasePath.'/lib/TokenWord.php');
10 require_once(CONST_BasePath.'/lib/SpecialSearchOperator.php');
11
12 /**
13  * Saves information about the tokens that appear in a search query.
14  *
15  */
16 class TokenList
17 {
18     // List of list of tokens indexed by their word_token.
19     private $aTokens = array();
20
21     public function contains($sWord)
22     {
23         return isset($this->aTokens[$sWord]);
24     }
25
26     public function get($sWord)
27     {
28         return isset($this->aTokens[$sWord]) ? $this->aTokens[$sWord] : array();
29     }
30
31     /**
32      * Add token information from the word table in the database.
33      *
34      * @param object   $oDB           Database connection.
35      * @param string[] $aTokens       List of tokens to look up in the database.
36      * @param string[] $aCountryCodes List of country restrictions.
37      * @param string   $sNormQuery    Normalized query string.
38      * @param object   $oNormalizer   Normalizer function to use on tokens.
39      *
40      * @return void
41      */
42     public function addTokensFromDB(&$oDB, &$aTokens, &$aCountryCodes, $sNormQuery, $oNormalizer)
43     {
44         // Check which tokens we have, get the ID numbers
45         $sSQL = 'SELECT word_id, word_token, word, class, type, country_code,';
46         $sSQL .= ' operator, coalesce(search_name_count, 0) as count';
47         $sSQL .= ' FROM word WHERE word_token in (';
48         $sSQL .= join(',', array_map('getDBQuoted', $aTokens)).')';
49
50         Debug::printSQL($sSQL);
51
52         $aDBWords = chksql($oDB->getAll($sSQL), 'Could not get word tokens.');
53
54         foreach ($aDBWords as $aWord) {
55             $oToken = null;
56             $iId = (int) $aWord['word_id'];
57
58             if ($aWord['class']) {
59                 // Special terms need to appear in their normalized form.
60                 if ($aWord['word']) {
61                     $sNormWord = $aWord['word'];
62                     if ($oNormalizer != null) {
63                         $sNormWord = $oNormalizer->transliterate($aWord['word']);
64                     }
65                     if (strpos($sNormQuery, $sNormWord) === false) {
66                         continue;
67                     }
68                 }
69
70                 if ($aWord['class'] == 'place' && $aWord['type'] == 'house') {
71                     $oToken = new Token\HouseNumber($iId, trim($aWord['word_token']));
72                 } elseif ($aWord['class'] == 'place' && $aWord['type'] == 'postcode') {
73                     if ($aWord['word']
74                         && pg_escape_string($aWord['word']) == $aWord['word']
75                     ) {
76                         $oToken = new Token\Postcode(
77                             $iId,
78                             $aWord['word'],
79                             $aWord['country_code']
80                         );
81                     }
82                 } else {
83                     // near and in operator the same at the moment
84                     $oToken = new Token\SpecialTerm(
85                         $iId,
86                         $aWord['class'],
87                         $aWord['type'],
88                         $aWord['operator'] ? Operator::NONE : Operator::NEAR
89                     );
90                 }
91             } elseif ($aWord['country_code']) {
92                 // Filter country tokens that do not match restricted countries.
93                 if (!$aCountryCodes
94                     || in_array($aWord['country_code'], $aCountryCodes)
95                 ) {
96                     $oToken = new Token\Country($iId, $aWord['country_code']);
97                 }
98             } else {
99                 $oToken = new Token\Word(
100                     $iId,
101                     $aWord['word'][0] != ' ',
102                     (int) $aWord['count']
103                 );
104             }
105
106             if ($oToken) {
107                 $this->addToken($aWord['word_token'], $oToken);
108             }
109         }
110     }
111
112     /**
113      * Add a new token for the given word.
114      *
115      * @param string $sWord  Word the token describes.
116      * @param object $oToken Token object to add.
117      *
118      * @return void
119      */
120     public function addToken($sWord, $oToken)
121     {
122         if (isset($this->aTokens[$sWord])) {
123             $this->aTokens[$sWord][] = $oToken;
124         } else {
125             $this->aTokens[$sWord] = array($oToken);
126         }
127     }
128
129     public function debugTokenByWordIdList()
130     {
131         $aWordsIDs = array();
132         foreach ($this->aTokens as $sToken => $aWords) {
133             foreach ($aWords as $aToken) {
134                 if ($aToken->iId !== null) {
135                     $aWordsIDs[$aToken->iId] =
136                         '#'.$sToken.'('.$aToken->iId.')#';
137                 }
138             }
139         }
140
141         return $aWordsIDs;
142     }
143
144     public function debugInfo()
145     {
146         return $this->aTokens;
147     }
148 }