phpBB
Statistics
| Revision:

root / trunk / phpBB / includes / search / fulltext_native.php

History | View | Annotate | Download (48.1 kB)

1 5850 grahamje
<?php
2 8147 acydburn
/**
3 5850 grahamje
*
4 5850 grahamje
* @package search
5 8147 acydburn
* @copyright (c) 2005 phpBB Group
6 11653 git-gate
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
7 5850 grahamje
*
8 5850 grahamje
*/
9 5850 grahamje
10 5850 grahamje
/**
11 8147 acydburn
* @ignore
12 5850 grahamje
*/
13 5850 grahamje
if (!defined('IN_PHPBB'))
14 5850 grahamje
{
15 5850 grahamje
        exit;
16 5850 grahamje
}
17 5850 grahamje
18 5850 grahamje
/**
19 5850 grahamje
* fulltext_native
20 6211 naderman
* phpBB's own db driven fulltext search, version 2
21 6058 acydburn
* @package search
22 5850 grahamje
*/
23 11557 git-gate
class phpbb_search_fulltext_native extends phpbb_search_base
24 5850 grahamje
{
25 6211 naderman
        var $stats = array();
26 6211 naderman
        var $word_length = array();
27 6211 naderman
        var $search_query;
28 6211 naderman
        var $common_words = array();
29 5850 grahamje
30 6211 naderman
        var $must_contain_ids = array();
31 6211 naderman
        var $must_not_contain_ids = array();
32 6211 naderman
        var $must_exclude_one_ids = array();
33 6211 naderman
34 6211 naderman
        /**
35 6211 naderman
        * Initialises the fulltext_native search backend with min/max word length and makes sure the UTF-8 normalizer is loaded.
36 6211 naderman
        *
37 6595 acydburn
        * @param        boolean|string        &$error        is passed by reference and should either be set to false on success or an error message on failure.
38 6211 naderman
        */
39 11557 git-gate
        public function __construct(&$error)
40 5850 grahamje
        {
41 6211 naderman
                global $phpbb_root_path, $phpEx, $config;
42 5850 grahamje
43 5850 grahamje
                $this->word_length = array('min' => $config['fulltext_native_min_chars'], 'max' => $config['fulltext_native_max_chars']);
44 5850 grahamje
45 6211 naderman
                /**
46 6211 naderman
                * Load the UTF tools
47 6211 naderman
                */
48 6211 naderman
                if (!class_exists('utf_normalizer'))
49 6211 naderman
                {
50 6211 naderman
                        include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx);
51 6211 naderman
                }
52 6211 naderman
53 5850 grahamje
                $error = false;
54 5850 grahamje
        }
55 5850 grahamje
56 5850 grahamje
        /**
57 11557 git-gate
        * Returns the name of this search backend to be displayed to administrators
58 11557 git-gate
        *
59 11557 git-gate
        * @return string Name
60 11557 git-gate
        */
61 11557 git-gate
        public function get_name()
62 11557 git-gate
        {
63 11557 git-gate
                return 'phpBB Native Fulltext';
64 11557 git-gate
        }
65 11557 git-gate
66 11557 git-gate
        /**
67 6211 naderman
        * This function fills $this->search_query with the cleaned user search query.
68 5850 grahamje
        *
69 6211 naderman
        * If $terms is 'any' then the words will be extracted from the search query
70 6211 naderman
        * and combined with | inside brackets. They will afterwards be treated like
71 6211 naderman
        * an standard search query.
72 6211 naderman
        *
73 6211 naderman
        * Then it analyses the query and fills the internal arrays $must_not_contain_ids,
74 6211 naderman
        * $must_contain_ids and $must_exclude_one_ids which are later used by keyword_search().
75 6211 naderman
        *
76 6211 naderman
        * @param        string        $keywords        contains the search query string as entered by the user
77 6211 naderman
        * @param        string        $terms                is either 'all' (use search query as entered, default words to 'must be contained in post')
78 6211 naderman
        *         or 'any' (find all posts containing at least one of the given words)
79 6211 naderman
        * @return        boolean                                false if no valid keywords were found and otherwise true
80 6211 naderman
        *
81 6211 naderman
        * @access        public
82 5850 grahamje
        */
83 6211 naderman
        function split_keywords($keywords, $terms)
84 5850 grahamje
        {
85 9471 acydburn
                global $db, $user, $config;
86 5850 grahamje
87 10751 git-gate
                $tokens = '+-|()*';
88 5850 grahamje
89 10751 git-gate
                $keywords = trim($this->cleanup($keywords, $tokens));
90 10751 git-gate
91 6380 naderman
                // allow word|word|word without brackets
92 6380 naderman
                if ((strpos($keywords, ' ') === false) && (strpos($keywords, '|') !== false) && (strpos($keywords, '(') === false))
93 6380 naderman
                {
94 6380 naderman
                        $keywords = '(' . $keywords . ')';
95 6380 naderman
                }
96 5850 grahamje
97 6380 naderman
                $open_bracket = $space = false;
98 6562 acydburn
                for ($i = 0, $n = strlen($keywords); $i < $n; $i++)
99 6380 naderman
                {
100 6380 naderman
                        if ($open_bracket !== false)
101 6380 naderman
                        {
102 6380 naderman
                                switch ($keywords[$i])
103 6380 naderman
                                {
104 6380 naderman
                                        case ')':
105 6380 naderman
                                                if ($open_bracket + 1 == $i)
106 6380 naderman
                                                {
107 6380 naderman
                                                        $keywords[$i - 1] = '|';
108 6380 naderman
                                                        $keywords[$i] = '|';
109 6380 naderman
                                                }
110 6380 naderman
                                                $open_bracket = false;
111 6380 naderman
                                        break;
112 6380 naderman
                                        case '(':
113 6380 naderman
                                                $keywords[$i] = '|';
114 6380 naderman
                                        break;
115 6380 naderman
                                        case '+':
116 6380 naderman
                                        case '-':
117 6380 naderman
                                        case ' ':
118 6380 naderman
                                                $keywords[$i] = '|';
119 6380 naderman
                                        break;
120 10751 git-gate
                                        case '*':
121 10751 git-gate
                                                if ($i === 0 || ($keywords[$i - 1] !== '*' && strcspn($keywords[$i - 1], $tokens) === 0))
122 10751 git-gate
                                                {
123 10751 git-gate
                                                        if ($i === $n - 1 || ($keywords[$i + 1] !== '*' && strcspn($keywords[$i + 1], $tokens) === 0))
124 10751 git-gate
                                                        {
125 10751 git-gate
                                                                $keywords = substr($keywords, 0, $i) . substr($keywords, $i + 1);
126 10751 git-gate
                                                        }
127 10751 git-gate
                                                }
128 10751 git-gate
                                        break;
129 6380 naderman
                                }
130 6380 naderman
                        }
131 6380 naderman
                        else
132 6380 naderman
                        {
133 6380 naderman
                                switch ($keywords[$i])
134 6380 naderman
                                {
135 6380 naderman
                                        case ')':
136 6380 naderman
                                                $keywords[$i] = ' ';
137 6380 naderman
                                        break;
138 6380 naderman
                                        case '(':
139 6380 naderman
                                                $open_bracket = $i;
140 7559 naderman
                                                $space = false;
141 6380 naderman
                                        break;
142 6380 naderman
                                        case '|':
143 6380 naderman
                                                $keywords[$i] = ' ';
144 6380 naderman
                                        break;
145 6380 naderman
                                        case '-':
146 6380 naderman
                                        case '+':
147 6380 naderman
                                                $space = $keywords[$i];
148 6380 naderman
                                        break;
149 6380 naderman
                                        case ' ':
150 6380 naderman
                                                if ($space !== false)
151 6380 naderman
                                                {
152 6380 naderman
                                                        $keywords[$i] = $space;
153 6380 naderman
                                                }
154 6380 naderman
                                        break;
155 6380 naderman
                                        default:
156 6380 naderman
                                                $space = false;
157 6380 naderman
                                }
158 6380 naderman
                        }
159 6380 naderman
                }
160 5850 grahamje
161 6380 naderman
                if ($open_bracket)
162 6380 naderman
                {
163 6380 naderman
                        $keywords .= ')';
164 6380 naderman
                }
165 5850 grahamje
166 6380 naderman
                $match = array(
167 6380 naderman
                        '#  +#',
168 6380 naderman
                        '#\|\|+#',
169 6380 naderman
                        '#(\+|\-)(?:\+|\-)+#',
170 6380 naderman
                        '#\(\|#',
171 6380 naderman
                        '#\|\)#',
172 6211 naderman
                );
173 6211 naderman
                $replace = array(
174 6211 naderman
                        ' ',
175 6380 naderman
                        '|',
176 6211 naderman
                        '$1',
177 6380 naderman
                        '(',
178 6380 naderman
                        ')',
179 6211 naderman
                );
180 5853 naderman
181 6380 naderman
                $keywords = preg_replace($match, $replace, $keywords);
182 9438 acydburn
                $num_keywords = sizeof(explode(' ', $keywords));
183 5850 grahamje
184 9438 acydburn
                // We limit the number of allowed keywords to minimize load on the database
185 9438 acydburn
                if ($config['max_num_search_keywords'] && $num_keywords > $config['max_num_search_keywords'])
186 9438 acydburn
                {
187 9438 acydburn
                        trigger_error($user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', $config['max_num_search_keywords'], $num_keywords));
188 9438 acydburn
                }
189 9438 acydburn
190 6915 acydburn
                // $keywords input format: each word separated by a space, words in a bracket are not separated
191 5850 grahamje
192 6211 naderman
                // the user wants to search for any word, convert the search query
193 6211 naderman
                if ($terms == 'any')
194 5850 grahamje
                {
195 6211 naderman
                        $words = array();
196 5850 grahamje
197 6674 acydburn
                        preg_match_all('#([^\\s+\\-|()]+)(?:$|[\\s+\\-|()])#u', $keywords, $words);
198 6211 naderman
                        if (sizeof($words[1]))
199 6211 naderman
                        {
200 6211 naderman
                                $keywords = '(' . implode('|', $words[1]) . ')';
201 6211 naderman
                        }
202 5850 grahamje
                }
203 5850 grahamje
204 6211 naderman
                // set the search_query which is shown to the user
205 6380 naderman
                $this->search_query = $keywords;
206 5981 naderman
207 6211 naderman
                $exact_words = array();
208 6674 acydburn
                preg_match_all('#([^\\s+\\-|*()]+)(?:$|[\\s+\\-|()])#u', $keywords, $exact_words);
209 6211 naderman
                $exact_words = $exact_words[1];
210 5981 naderman
211 7310 naderman
                $common_ids = $words = array();
212 6708 naderman
213 6211 naderman
                if (sizeof($exact_words))
214 5850 grahamje
                {
215 6211 naderman
                        $sql = 'SELECT word_id, word_text, word_common
216 6211 naderman
                                FROM ' . SEARCH_WORDLIST_TABLE . '
217 10558 git-gate
                                WHERE ' . $db->sql_in_set('word_text', $exact_words) . '
218 10558 git-gate
                                ORDER BY word_count ASC';
219 5850 grahamje
                        $result = $db->sql_query($sql);
220 6944 naderman
221 6211 naderman
                        // store an array of words and ids, remove common words
222 5850 grahamje
                        while ($row = $db->sql_fetchrow($result))
223 5850 grahamje
                        {
224 6211 naderman
                                if ($row['word_common'])
225 5850 grahamje
                                {
226 6511 acydburn
                                        $this->common_words[] = $row['word_text'];
227 6708 naderman
                                        $common_ids[$row['word_text']] = (int) $row['word_id'];
228 6211 naderman
                                        continue;
229 5850 grahamje
                                }
230 6211 naderman
231 6211 naderman
                                $words[$row['word_text']] = (int) $row['word_id'];
232 5850 grahamje
                        }
233 5850 grahamje
                        $db->sql_freeresult($result);
234 5850 grahamje
                }
235 6211 naderman
                unset($exact_words);
236 5850 grahamje
237 6211 naderman
                // now analyse the search query, first split it using the spaces
238 6211 naderman
                $query = explode(' ', $keywords);
239 5850 grahamje
240 6211 naderman
                $this->must_contain_ids = array();
241 6211 naderman
                $this->must_not_contain_ids = array();
242 6211 naderman
                $this->must_exclude_one_ids = array();
243 5853 naderman
244 6211 naderman
                $mode = '';
245 6211 naderman
                $ignore_no_id = true;
246 5850 grahamje
247 6211 naderman
                foreach ($query as $word)
248 5850 grahamje
                {
249 6211 naderman
                        if (empty($word))
250 6211 naderman
                        {
251 6211 naderman
                                continue;
252 6211 naderman
                        }
253 5850 grahamje
254 6211 naderman
                        // words which should not be included
255 6211 naderman
                        if ($word[0] == '-')
256 6211 naderman
                        {
257 6211 naderman
                                $word = substr($word, 1);
258 5850 grahamje
259 6211 naderman
                                // a group of which at least one may not be in the resulting posts
260 6211 naderman
                                if ($word[0] == '(')
261 6211 naderman
                                {
262 6321 naderman
                                        $word = array_unique(explode('|', substr($word, 1, -1)));
263 6211 naderman
                                        $mode = 'must_exclude_one';
264 6211 naderman
                                }
265 6211 naderman
                                // one word which should not be in the resulting posts
266 6211 naderman
                                else
267 6211 naderman
                                {
268 6211 naderman
                                        $mode = 'must_not_contain';
269 6211 naderman
                                }
270 6211 naderman
                                $ignore_no_id = true;
271 6211 naderman
                        }
272 6211 naderman
                        // words which have to be included
273 6211 naderman
                        else
274 6211 naderman
                        {
275 6211 naderman
                                // no prefix is the same as a +prefix
276 6211 naderman
                                if ($word[0] == '+')
277 6211 naderman
                                {
278 6211 naderman
                                        $word = substr($word, 1);
279 6211 naderman
                                }
280 5850 grahamje
281 6211 naderman
                                // a group of words of which at least one word should be in every resulting post
282 6211 naderman
                                if ($word[0] == '(')
283 6211 naderman
                                {
284 6321 naderman
                                        $word = array_unique(explode('|', substr($word, 1, -1)));
285 6211 naderman
                                }
286 6211 naderman
                                $ignore_no_id = false;
287 6211 naderman
                                $mode = 'must_contain';
288 6211 naderman
                        }
289 5850 grahamje
290 6380 naderman
                        if (empty($word))
291 6380 naderman
                        {
292 6380 naderman
                                continue;
293 6380 naderman
                        }
294 6380 naderman
295 6211 naderman
                        // if this is an array of words then retrieve an id for each
296 6211 naderman
                        if (is_array($word))
297 6211 naderman
                        {
298 6886 naderman
                                $non_common_words = array();
299 6211 naderman
                                $id_words = array();
300 6211 naderman
                                foreach ($word as $i => $word_part)
301 6211 naderman
                                {
302 6211 naderman
                                        if (strpos($word_part, '*') !== false)
303 6211 naderman
                                        {
304 6211 naderman
                                                $id_words[] = '\'' . $db->sql_escape(str_replace('*', '%', $word_part)) . '\'';
305 6886 naderman
                                                $non_common_words[] = $word_part;
306 6211 naderman
                                        }
307 6886 naderman
                                        else if (isset($words[$word_part]))
308 6211 naderman
                                        {
309 6211 naderman
                                                $id_words[] = $words[$word_part];
310 6886 naderman
                                                $non_common_words[] = $word_part;
311 6211 naderman
                                        }
312 7310 naderman
                                        else
313 7310 naderman
                                        {
314 7310 naderman
                                                $len = utf8_strlen($word_part);
315 7310 naderman
                                                if ($len < $this->word_length['min'] || $len > $this->word_length['max'])
316 7310 naderman
                                                {
317 7310 naderman
                                                        $this->common_words[] = $word_part;
318 7310 naderman
                                                }
319 7310 naderman
                                        }
320 6211 naderman
                                }
321 6211 naderman
                                if (sizeof($id_words))
322 6211 naderman
                                {
323 6211 naderman
                                        sort($id_words);
324 6211 naderman
                                        if (sizeof($id_words) > 1)
325 6211 naderman
                                        {
326 6211 naderman
                                                $this->{$mode . '_ids'}[] = $id_words;
327 6211 naderman
                                        }
328 6211 naderman
                                        else
329 6211 naderman
                                        {
330 6211 naderman
                                                $mode = ($mode == 'must_exclude_one') ? 'must_not_contain' : $mode;
331 6211 naderman
                                                $this->{$mode . '_ids'}[] = $id_words[0];
332 6211 naderman
                                        }
333 6211 naderman
                                }
334 6211 naderman
                                // throw an error if we shall not ignore unexistant words
335 6886 naderman
                                else if (!$ignore_no_id && sizeof($non_common_words))
336 6211 naderman
                                {
337 6886 naderman
                                        trigger_error(sprintf($user->lang['WORDS_IN_NO_POST'], implode(', ', $non_common_words)));
338 6211 naderman
                                }
339 6886 naderman
                                unset($non_common_words);
340 6211 naderman
                        }
341 6211 naderman
                        // else we only need one id
342 6211 naderman
                        else if (($wildcard = strpos($word, '*') !== false) || isset($words[$word]))
343 6211 naderman
                        {
344 6211 naderman
                                if ($wildcard)
345 6211 naderman
                                {
346 6944 naderman
                                        $len = utf8_strlen(str_replace('*', '', $word));
347 6944 naderman
                                        if ($len >= $this->word_length['min'] && $len <= $this->word_length['max'])
348 6944 naderman
                                        {
349 6944 naderman
                                                $this->{$mode . '_ids'}[] = '\'' . $db->sql_escape(str_replace('*', '%', $word)) . '\'';
350 6944 naderman
                                        }
351 6944 naderman
                                        else
352 6944 naderman
                                        {
353 7041 davidmj
                                                $this->common_words[] = $word;
354 6944 naderman
                                        }
355 6211 naderman
                                }
356 6211 naderman
                                else
357 6211 naderman
                                {
358 6211 naderman
                                        $this->{$mode . '_ids'}[] = $words[$word];
359 6211 naderman
                                }
360 6211 naderman
                        }
361 6211 naderman
                        // throw an error if we shall not ignore unexistant words
362 6211 naderman
                        else if (!$ignore_no_id)
363 6211 naderman
                        {
364 6708 naderman
                                if (!isset($common_ids[$word]))
365 6708 naderman
                                {
366 6944 naderman
                                        $len = utf8_strlen($word);
367 6944 naderman
                                        if ($len >= $this->word_length['min'] && $len <= $this->word_length['max'])
368 6944 naderman
                                        {
369 6944 naderman
                                                trigger_error(sprintf($user->lang['WORD_IN_NO_POST'], $word));
370 6944 naderman
                                        }
371 6944 naderman
                                        else
372 6944 naderman
                                        {
373 6944 naderman
                                                $this->common_words[] = $word;
374 6944 naderman
                                        }
375 6708 naderman
                                }
376 6211 naderman
                        }
377 6944 naderman
                        else
378 6944 naderman
                        {
379 6944 naderman
                                $len = utf8_strlen($word);
380 6944 naderman
                                if ($len < $this->word_length['min'] || $len > $this->word_length['max'])
381 6944 naderman
                                {
382 6944 naderman
                                        $this->common_words[] = $word;
383 6944 naderman
                                }
384 6944 naderman
                        }
385 5850 grahamje
                }
386 5850 grahamje
387 6211 naderman
                // we can't search for negatives only
388 6211 naderman
                if (!sizeof($this->must_contain_ids))
389 5850 grahamje
                {
390 6211 naderman
                        return false;
391 5850 grahamje
                }
392 5850 grahamje
393 6211 naderman
                if (!empty($this->search_query))
394 5850 grahamje
                {
395 6211 naderman
                        return true;
396 5850 grahamje
                }
397 6211 naderman
                return false;
398 5850 grahamje
        }
399 5850 grahamje
400 5850 grahamje
        /**
401 6211 naderman
        * Performs a search on keywords depending on display specific params. You have to run split_keywords() first.
402 5850 grahamje
        *
403 6211 naderman
        * @param        string                $type                                contains either posts or topics depending on what should be searched for
404 9713 nickvergessen
        * @param        string                $fields                                contains either titleonly (topic titles should be searched), msgonly (only message bodies should be searched), firstpost (only subject and body of the first post should be searched) or all (all post bodies and subjects should be searched)
405 9713 nickvergessen
        * @param        string                $terms                                is either 'all' (use query as entered, words without prefix should default to "have to be in field") or 'any' (ignore search query parts and just return all posts that contain any of the specified words)
406 9713 nickvergessen
        * @param        array                $sort_by_sql                contains SQL code for the ORDER BY part of a query
407 9713 nickvergessen
        * @param        string                $sort_key                        is the key of $sort_by_sql for the selected sorting
408 9713 nickvergessen
        * @param        string                $sort_dir                        is either a or d representing ASC and DESC
409 9713 nickvergessen
        * @param        string                $sort_days                        specifies the maximum amount of days a post may be old
410 9713 nickvergessen
        * @param        array                $ex_fid_ary                        specifies an array of forum ids which should not be searched
411 9713 nickvergessen
        * @param        array                $m_approve_fid_ary        specifies an array of forum ids in which the searcher is allowed to view unapproved posts
412 9713 nickvergessen
        * @param        int                        $topic_id                        is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched
413 9713 nickvergessen
        * @param        array                $author_ary                        an array of author ids if the author should be ignored during the search the array is empty
414 9713 nickvergessen
        * @param        string                $author_name                specifies the author match, when ANONYMOUS is also a search-match
415 6595 acydburn
        * @param        array                &$id_ary                        passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered
416 6211 naderman
        * @param        int                        $start                                indicates the first index of the page
417 6211 naderman
        * @param        int                        $per_page                        number of ids each page is supposed to contain
418 6211 naderman
        * @return        boolean|int                                                total number of results
419 6211 naderman
        *
420 6211 naderman
        * @access        public
421 5850 grahamje
        */
422 9713 nickvergessen
        function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
423 5850 grahamje
        {
424 5850 grahamje
                global $config, $db;
425 5850 grahamje
426 5850 grahamje
                // No keywords? No posts.
427 6211 naderman
                if (empty($this->search_query))
428 5850 grahamje
                {
429 5850 grahamje
                        return false;
430 5850 grahamje
                }
431 5850 grahamje
432 10558 git-gate
                $must_contain_ids = $this->must_contain_ids;
433 10558 git-gate
                $must_not_contain_ids = $this->must_not_contain_ids;
434 10558 git-gate
                $must_exclude_one_ids = $this->must_exclude_one_ids;
435 10558 git-gate
436 10558 git-gate
                sort($must_contain_ids);
437 10558 git-gate
                sort($must_not_contain_ids);
438 10558 git-gate
                sort($must_exclude_one_ids);
439 10558 git-gate
440 5850 grahamje
                // generate a search_key from all the options to identify the results
441 5850 grahamje
                $search_key = md5(implode('#', array(
442 10558 git-gate
                        serialize($must_contain_ids),
443 10558 git-gate
                        serialize($must_not_contain_ids),
444 10558 git-gate
                        serialize($must_exclude_one_ids),
445 5850 grahamje
                        $type,
446 5850 grahamje
                        $fields,
447 5850 grahamje
                        $terms,
448 5850 grahamje
                        $sort_days,
449 5850 grahamje
                        $sort_key,
450 5850 grahamje
                        $topic_id,
451 5850 grahamje
                        implode(',', $ex_fid_ary),
452 5850 grahamje
                        implode(',', $m_approve_fid_ary),
453 9713 nickvergessen
                        implode(',', $author_ary),
454 9713 nickvergessen
                        $author_name,
455 5850 grahamje
                )));
456 5850 grahamje
457 5850 grahamje
                // try reading the results from cache
458 6211 naderman
                $total_results = 0;
459 6211 naderman
                if ($this->obtain_ids($search_key, $total_results, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE)
460 5850 grahamje
                {
461 6211 naderman
                        return $total_results;
462 5850 grahamje
                }
463 5850 grahamje
464 5850 grahamje
                $id_ary = array();
465 5850 grahamje
466 6211 naderman
                $sql_where = array();
467 6211 naderman
                $group_by = false;
468 6211 naderman
                $m_num = 0;
469 6211 naderman
                $w_num = 0;
470 6073 acydburn
471 6211 naderman
                $sql_array = array(
472 6211 naderman
                        'SELECT'        => ($type == 'posts') ? 'p.post_id' : 'p.topic_id',
473 6211 naderman
                        'FROM'                => array(
474 6211 naderman
                                SEARCH_WORDMATCH_TABLE        => array(),
475 6211 naderman
                                SEARCH_WORDLIST_TABLE        => array(),
476 6211 naderman
                        ),
477 8878 acydburn
                        'LEFT_JOIN' => array(array(
478 8878 acydburn
                                'FROM'        => array(POSTS_TABLE => 'p'),
479 8878 acydburn
                                'ON'        => 'm0.post_id = p.post_id',
480 8878 acydburn
                        )),
481 6211 naderman
                );
482 6073 acydburn
483 6211 naderman
                $title_match = '';
484 9172 naderman
                $left_join_topics = false;
485 6254 naderman
                $group_by = true;
486 5850 grahamje
                // Build some display specific sql strings
487 5850 grahamje
                switch ($fields)
488 5850 grahamje
                {
489 5850 grahamje
                        case 'titleonly':
490 6211 naderman
                                $title_match = 'title_match = 1';
491 6254 naderman
                                $group_by = false;
492 6211 naderman
                        // no break
493 6211 naderman
                        case 'firstpost':
494 9172 naderman
                                $left_join_topics = true;
495 6211 naderman
                                $sql_where[] = 'p.post_id = t.topic_first_post_id';
496 5850 grahamje
                        break;
497 5850 grahamje
498 5850 grahamje
                        case 'msgonly':
499 6211 naderman
                                $title_match = 'title_match = 0';
500 6254 naderman
                                $group_by = false;
501 5850 grahamje
                        break;
502 6211 naderman
                }
503 5850 grahamje
504 6289 naderman
                if ($type == 'topics')
505 6289 naderman
                {
506 9172 naderman
                        $left_join_topics = true;
507 6289 naderman
                        $group_by = true;
508 6289 naderman
                }
509 6289 naderman
510 6211 naderman
                /**
511 6211 naderman
                * @todo Add a query optimizer (handle stuff like "+(4|3) +4")
512 6211 naderman
                */
513 5850 grahamje
514 6211 naderman
                foreach ($this->must_contain_ids as $subquery)
515 5850 grahamje
                {
516 6211 naderman
                        if (is_array($subquery))
517 6211 naderman
                        {
518 6211 naderman
                                $group_by = true;
519 5850 grahamje
520 6211 naderman
                                $word_id_sql = array();
521 6211 naderman
                                $word_ids = array();
522 6211 naderman
                                foreach ($subquery as $id)
523 6211 naderman
                                {
524 6211 naderman
                                        if (is_string($id))
525 6211 naderman
                                        {
526 6211 naderman
                                                $sql_array['LEFT_JOIN'][] = array(
527 6211 naderman
                                                        'FROM'        => array(SEARCH_WORDLIST_TABLE => 'w' . $w_num),
528 6211 naderman
                                                        'ON'        => "w$w_num.word_text LIKE $id"
529 6211 naderman
                                                );
530 6211 naderman
                                                $word_ids[] = "w$w_num.word_id";
531 6944 naderman
532 6211 naderman
                                                $w_num++;
533 6211 naderman
                                        }
534 6211 naderman
                                        else
535 6211 naderman
                                        {
536 6211 naderman
                                                $word_ids[] = $id;
537 6211 naderman
                                        }
538 6211 naderman
                                }
539 5850 grahamje
540 6271 acydburn
                                $sql_where[] = $db->sql_in_set("m$m_num.word_id", $word_ids);
541 5850 grahamje
542 6211 naderman
                                unset($word_id_sql);
543 6211 naderman
                                unset($word_ids);
544 6211 naderman
                        }
545 6211 naderman
                        else if (is_string($subquery))
546 5850 grahamje
                        {
547 6211 naderman
                                $sql_array['FROM'][SEARCH_WORDLIST_TABLE][] = 'w' . $w_num;
548 6073 acydburn
549 6211 naderman
                                $sql_where[] = "w$w_num.word_text LIKE $subquery";
550 6211 naderman
                                $sql_where[] = "m$m_num.word_id = w$w_num.word_id";
551 6073 acydburn
552 6211 naderman
                                $group_by = true;
553 6211 naderman
                                $w_num++;
554 6211 naderman
                        }
555 6211 naderman
                        else
556 6211 naderman
                        {
557 6211 naderman
                                $sql_where[] = "m$m_num.word_id = $subquery";
558 6211 naderman
                        }
559 6944 naderman
560 6211 naderman
                        $sql_array['FROM'][SEARCH_WORDMATCH_TABLE][] = 'm' . $m_num;
561 6073 acydburn
562 6211 naderman
                        if ($title_match)
563 6211 naderman
                        {
564 6211 naderman
                                $sql_where[] = "m$m_num.$title_match";
565 5850 grahamje
                        }
566 6211 naderman
567 6211 naderman
                        if ($m_num != 0)
568 6211 naderman
                        {
569 6211 naderman
                                $sql_where[] = "m$m_num.post_id = m0.post_id";
570 6211 naderman
                        }
571 6211 naderman
                        $m_num++;
572 5850 grahamje
                }
573 5850 grahamje
574 6211 naderman
                foreach ($this->must_not_contain_ids as $key => $subquery)
575 5850 grahamje
                {
576 6211 naderman
                        if (is_string($subquery))
577 5850 grahamje
                        {
578 6211 naderman
                                $sql_array['LEFT_JOIN'][] = array(
579 6211 naderman
                                        'FROM'        => array(SEARCH_WORDLIST_TABLE => 'w' . $w_num),
580 6211 naderman
                                        'ON'        => "w$w_num.word_text LIKE $subquery"
581 6211 naderman
                                );
582 5850 grahamje
583 6211 naderman
                                $this->must_not_contain_ids[$key] = "w$w_num.word_id";
584 5850 grahamje
585 6211 naderman
                                $group_by = true;
586 6211 naderman
                                $w_num++;
587 5850 grahamje
                        }
588 6211 naderman
                }
589 5850 grahamje
590 6211 naderman
                if (sizeof($this->must_not_contain_ids))
591 6211 naderman
                {
592 6211 naderman
                        $sql_array['LEFT_JOIN'][] = array(
593 6211 naderman
                                'FROM'        => array(SEARCH_WORDMATCH_TABLE => 'm' . $m_num),
594 6273 naderman
                                'ON'        => $db->sql_in_set("m$m_num.word_id", $this->must_not_contain_ids) . (($title_match) ? " AND m$m_num.$title_match" : '') . " AND m$m_num.post_id = m0.post_id"
595 6211 naderman
                        );
596 6211 naderman
597 6211 naderman
                        $sql_where[] = "m$m_num.word_id IS NULL";
598 6211 naderman
                        $m_num++;
599 6211 naderman
                }
600 6211 naderman
601 6211 naderman
                foreach ($this->must_exclude_one_ids as $ids)
602 6211 naderman
                {
603 6211 naderman
                        $is_null_joins = array();
604 6211 naderman
                        foreach ($ids as $id)
605 5850 grahamje
                        {
606 6211 naderman
                                if (is_string($id))
607 5850 grahamje
                                {
608 6211 naderman
                                        $sql_array['LEFT_JOIN'][] = array(
609 6211 naderman
                                                'FROM'        => array(SEARCH_WORDLIST_TABLE => 'w' . $w_num),
610 6211 naderman
                                                'ON'        => "w$w_num.word_text LIKE $id"
611 6211 naderman
                                        );
612 6211 naderman
                                        $id = "w$w_num.word_id";
613 5850 grahamje
614 6211 naderman
                                        $group_by = true;
615 6211 naderman
                                        $w_num++;
616 5850 grahamje
                                }
617 5850 grahamje
618 6211 naderman
                                $sql_array['LEFT_JOIN'][] = array(
619 6211 naderman
                                        'FROM'        => array(SEARCH_WORDMATCH_TABLE => 'm' . $m_num),
620 6273 naderman
                                        'ON'        => "m$m_num.word_id = $id AND m$m_num.post_id = m0.post_id" . (($title_match) ? " AND m$m_num.$title_match" : '')
621 6211 naderman
                                );
622 6211 naderman
                                $is_null_joins[] = "m$m_num.word_id IS NULL";
623 6211 naderman
624 6211 naderman
                                $m_num++;
625 5850 grahamje
                        }
626 6211 naderman
                        $sql_where[] = '(' . implode(' OR ', $is_null_joins) . ')';
627 5850 grahamje
                }
628 5850 grahamje
629 6211 naderman
                if (!sizeof($m_approve_fid_ary))
630 5850 grahamje
                {
631 6211 naderman
                        $sql_where[] = 'p.post_approved = 1';
632 6211 naderman
                }
633 6211 naderman
                else if ($m_approve_fid_ary !== array(-1))
634 6211 naderman
                {
635 6273 naderman
                        $sql_where[] = '(p.post_approved = 1 OR ' . $db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
636 6211 naderman
                }
637 5850 grahamje
638 6211 naderman
                if ($topic_id)
639 6211 naderman
                {
640 6211 naderman
                        $sql_where[] = 'p.topic_id = ' . $topic_id;
641 6211 naderman
                }
642 5850 grahamje
643 6211 naderman
                if (sizeof($author_ary))
644 6211 naderman
                {
645 9713 nickvergessen
                        if ($author_name)
646 9713 nickvergessen
                        {
647 9713 nickvergessen
                                // first one matches post of registered users, second one guests and deleted users
648 9931 nickvergessen
                                $sql_author = '(' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
649 9713 nickvergessen
                        }
650 9713 nickvergessen
                        else
651 9713 nickvergessen
                        {
652 9713 nickvergessen
                                $sql_author = $db->sql_in_set('p.poster_id', $author_ary);
653 9713 nickvergessen
                        }
654 9713 nickvergessen
                        $sql_where[] = $sql_author;
655 5850 grahamje
                }
656 5850 grahamje
657 6211 naderman
                if (sizeof($ex_fid_ary))
658 5850 grahamje
                {
659 6271 acydburn
                        $sql_where[] = $db->sql_in_set('p.forum_id', $ex_fid_ary, true);
660 5850 grahamje
                }
661 6211 naderman
662 6211 naderman
                if ($sort_days)
663 5850 grahamje
                {
664 6211 naderman
                        $sql_where[] = 'p.post_time >= ' . (time() - ($sort_days * 86400));
665 5850 grahamje
                }
666 5850 grahamje
667 6211 naderman
                $sql_array['WHERE'] = implode(' AND ', $sql_where);
668 5850 grahamje
669 6211 naderman
                $is_mysql = false;
670 6211 naderman
                // if the total result count is not cached yet, retrieve it from the db
671 6211 naderman
                if (!$total_results)
672 5850 grahamje
                {
673 6211 naderman
                        $sql = '';
674 6211 naderman
                        $sql_array_count = $sql_array;
675 6211 naderman
676 9473 acydburn
                        if ($left_join_topics)
677 9473 acydburn
                        {
678 9473 acydburn
                                $sql_array_count['LEFT_JOIN'][] = array(
679 9473 acydburn
                                        'FROM'        => array(TOPICS_TABLE => 't'),
680 9473 acydburn
                                        'ON'        => 'p.topic_id = t.topic_id'
681 9473 acydburn
                                );
682 9473 acydburn
                        }
683 9473 acydburn
684 6497 acydburn
                        switch ($db->sql_layer)
685 5850 grahamje
                        {
686 6211 naderman
                                case 'mysql4':
687 6211 naderman
                                case 'mysqli':
688 6497 acydburn
689 6380 naderman
                                        // 3.x does not support SQL_CALC_FOUND_ROWS
690 9440 acydburn
                                        // $sql_array['SELECT'] = 'SQL_CALC_FOUND_ROWS ' . $sql_array['SELECT'];
691 6497 acydburn
                                        $is_mysql = true;
692 6211 naderman
693 6497 acydburn
                                break;
694 6380 naderman
695 6211 naderman
                                case 'sqlite':
696 6211 naderman
                                        $sql_array_count['SELECT'] = ($type == 'posts') ? 'DISTINCT p.post_id' : 'DISTINCT p.topic_id';
697 6211 naderman
                                        $sql = 'SELECT COUNT(' . (($type == 'posts') ? 'post_id' : 'topic_id') . ') as total_results
698 6211 naderman
                                                        FROM (' . $db->sql_build_query('SELECT', $sql_array_count) . ')';
699 6497 acydburn
700 6211 naderman
                                // no break
701 6497 acydburn
702 6211 naderman
                                default:
703 6211 naderman
                                        $sql_array_count['SELECT'] = ($type == 'posts') ? 'COUNT(DISTINCT p.post_id) AS total_results' : 'COUNT(DISTINCT p.topic_id) AS total_results';
704 6211 naderman
                                        $sql = (!$sql) ? $db->sql_build_query('SELECT', $sql_array_count) : $sql;
705 6944 naderman
706 6211 naderman
                                        $result = $db->sql_query($sql);
707 6211 naderman
                                        $total_results = (int) $db->sql_fetchfield('total_results');
708 6211 naderman
                                        $db->sql_freeresult($result);
709 6944 naderman
710 6211 naderman
                                        if (!$total_results)
711 6211 naderman
                                        {
712 6211 naderman
                                                return false;
713 6211 naderman
                                        }
714 6211 naderman
                                break;
715 6211 naderman
                        }
716 6211 naderman
717 6211 naderman
                        unset($sql_array_count, $sql);
718 6211 naderman
                }
719 6211 naderman
720 6211 naderman
                // Build sql strings for sorting
721 6211 naderman
                $sql_sort = $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC');
722 6211 naderman
723 6211 naderman
                switch ($sql_sort[0])
724 6211 naderman
                {
725 6211 naderman
                        case 'u':
726 6211 naderman
                                $sql_array['FROM'][USERS_TABLE] = 'u';
727 6211 naderman
                                $sql_where[] = 'u.user_id = p.poster_id ';
728 6211 naderman
                        break;
729 6211 naderman
730 6211 naderman
                        case 't':
731 9172 naderman
                                $left_join_topics = true;
732 6211 naderman
                        break;
733 5850 grahamje
734 6211 naderman
                        case 'f':
735 6211 naderman
                                $sql_array['FROM'][FORUMS_TABLE] = 'f';
736 6211 naderman
                                $sql_where[] = 'f.forum_id = p.forum_id';
737 6211 naderman
                        break;
738 5850 grahamje
                }
739 9438 acydburn
740 9172 naderman
                if ($left_join_topics)
741 9172 naderman
                {
742 9472 acydburn
                        $sql_array['LEFT_JOIN'][] = array(
743 9173 naderman
                                'FROM'        => array(TOPICS_TABLE => 't'),
744 9172 naderman
                                'ON'        => 'p.topic_id = t.topic_id'
745 9172 naderman
                        );
746 9172 naderman
                }
747 5850 grahamje
748 6211 naderman
                $sql_array['WHERE'] = implode(' AND ', $sql_where);
749 6211 naderman
                $sql_array['GROUP_BY'] = ($group_by) ? (($type == 'posts') ? 'p.post_id' : 'p.topic_id') . ', ' . $sort_by_sql[$sort_key] : '';
750 6211 naderman
                $sql_array['ORDER_BY'] = $sql_sort;
751 6211 naderman
752 6211 naderman
                unset($sql_where, $sql_sort, $group_by);
753 6211 naderman
754 6211 naderman
                $sql = $db->sql_build_query('SELECT', $sql_array);
755 6211 naderman
                $result = $db->sql_query_limit($sql, $config['search_block_size'], $start);
756 6211 naderman
757 6211 naderman
                while ($row = $db->sql_fetchrow($result))
758 5850 grahamje
                {
759 10558 git-gate
                        $id_ary[] = (int) $row[(($type == 'posts') ? 'post_id' : 'topic_id')];
760 5850 grahamje
                }
761 6211 naderman
                $db->sql_freeresult($result);
762 5850 grahamje
763 5850 grahamje
                if (!sizeof($id_ary))
764 5850 grahamje
                {
765 5850 grahamje
                        return false;
766 5850 grahamje
                }
767 5850 grahamje
768 6211 naderman
                // if we use mysql and the total result count is not cached yet, retrieve it from the db
769 9472 acydburn
                if (!$total_results && $is_mysql)
770 6211 naderman
                {
771 9472 acydburn
                        // Count rows for the executed queries. Replace $select within $sql with SQL_CALC_FOUND_ROWS, and run it.
772 9472 acydburn
                        $sql_array_copy = $sql_array;
773 9472 acydburn
                        $sql_array_copy['SELECT'] = 'SQL_CALC_FOUND_ROWS p.post_id ';
774 9472 acydburn
775 9440 acydburn
                        $sql = $db->sql_build_query('SELECT', $sql_array_copy);
776 9440 acydburn
                        unset($sql_array_copy);
777 9440 acydburn
778 9440 acydburn
                        $db->sql_query($sql);
779 9440 acydburn
                        $db->sql_freeresult($result);
780 9440 acydburn
781 6211 naderman
                        $sql = 'SELECT FOUND_ROWS() as total_results';
782 6211 naderman
                        $result = $db->sql_query($sql);
783 6211 naderman
                        $total_results = (int) $db->sql_fetchfield('total_results');
784 6211 naderman
                        $db->sql_freeresult($result);
785 5850 grahamje
786 6211 naderman
                        if (!$total_results)
787 6211 naderman
                        {
788 6211 naderman
                                return false;
789 6211 naderman
                        }
790 6211 naderman
                }
791 6211 naderman
792 5850 grahamje
                // store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page
793 6211 naderman
                $this->save_ids($search_key, $this->search_query, $author_ary, $total_results, $id_ary, $start, $sort_dir);
794 5850 grahamje
                $id_ary = array_slice($id_ary, 0, (int) $per_page);
795 5850 grahamje
796 6211 naderman
                return $total_results;
797 5850 grahamje
        }
798 5850 grahamje
799 5850 grahamje
        /**
800 5850 grahamje
        * Performs a search on an author's posts without caring about message contents. Depends on display specific params
801 5850 grahamje
        *
802 6211 naderman
        * @param        string                $type                                contains either posts or topics depending on what should be searched for
803 7931 kellanved
        * @param        boolean                $firstpost_only                if true, only topic starting posts will be considered
804 9713 nickvergessen
        * @param        array                $sort_by_sql                contains SQL code for the ORDER BY part of a query
805 9713 nickvergessen
        * @param        string                $sort_key                        is the key of $sort_by_sql for the selected sorting
806 9713 nickvergessen
        * @param        string                $sort_dir                        is either a or d representing ASC and DESC
807 9713 nickvergessen
        * @param        string                $sort_days                        specifies the maximum amount of days a post may be old
808 9713 nickvergessen
        * @param        array                $ex_fid_ary                        specifies an array of forum ids which should not be searched
809 9713 nickvergessen
        * @param        array                $m_approve_fid_ary        specifies an array of forum ids in which the searcher is allowed to view unapproved posts
810 9713 nickvergessen
        * @param        int                        $topic_id                        is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched
811 9713 nickvergessen
        * @param        array                $author_ary                        an array of author ids
812 9713 nickvergessen
        * @param        string                $author_name                specifies the author match, when ANONYMOUS is also a search-match
813 6595 acydburn
        * @param        array                &$id_ary                        passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered
814 6211 naderman
        * @param        int                        $start                                indicates the first index of the page
815 6211 naderman
        * @param        int                        $per_page                        number of ids each page is supposed to contain
816 6211 naderman
        * @return        boolean|int                                                total number of results
817 6211 naderman
        *
818 6211 naderman
        * @access        public
819 5850 grahamje
        */
820 9713 nickvergessen
        function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
821 5850 grahamje
        {
822 5850 grahamje
                global $config, $db;
823 5850 grahamje
824 5850 grahamje
                // No author? No posts.
825 5850 grahamje
                if (!sizeof($author_ary))
826 5850 grahamje
                {
827 5850 grahamje
                        return 0;
828 5850 grahamje
                }
829 5850 grahamje
830 5850 grahamje
                // generate a search_key from all the options to identify the results
831 5850 grahamje
                $search_key = md5(implode('#', array(
832 5850 grahamje
                        '',
833 5850 grahamje
                        $type,
834 7930 kellanved
                        ($firstpost_only) ? 'firstpost' : '',
835 5850 grahamje
                        '',
836 5850 grahamje
                        '',
837 5850 grahamje
                        $sort_days,
838 5850 grahamje
                        $sort_key,
839 5850 grahamje
                        $topic_id,
840 5850 grahamje
                        implode(',', $ex_fid_ary),
841 5850 grahamje
                        implode(',', $m_approve_fid_ary),
842 9713 nickvergessen
                        implode(',', $author_ary),
843 9713 nickvergessen
                        $author_name,
844 5850 grahamje
                )));
845 5850 grahamje
846 5850 grahamje
                // try reading the results from cache
847 6211 naderman
                $total_results = 0;
848 6211 naderman
                if ($this->obtain_ids($search_key, $total_results, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE)
849 5850 grahamje
                {
850 6211 naderman
                        return $total_results;
851 5850 grahamje
                }
852 5850 grahamje
853 5850 grahamje
                $id_ary = array();
854 5850 grahamje
855 5850 grahamje
                // Create some display specific sql strings
856 9713 nickvergessen
                if ($author_name)
857 9713 nickvergessen
                {
858 9713 nickvergessen
                        // first one matches post of registered users, second one guests and deleted users
859 9931 nickvergessen
                        $sql_author = '(' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
860 9713 nickvergessen
                }
861 9713 nickvergessen
                else
862 9713 nickvergessen
                {
863 9713 nickvergessen
                        $sql_author = $db->sql_in_set('p.poster_id', $author_ary);
864 9713 nickvergessen
                }
865 6271 acydburn
                $sql_fora                = (sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
866 5850 grahamje
                $sql_time                = ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
867 5850 grahamje
                $sql_topic_id        = ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : '';
868 7930 kellanved
                $sql_firstpost = ($firstpost_only) ? ' AND p.post_id = t.topic_first_post_id' : '';
869 5850 grahamje
870 5850 grahamje
                // Build sql strings for sorting
871 5850 grahamje
                $sql_sort = $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC');
872 5850 grahamje
                $sql_sort_table = $sql_sort_join = '';
873 5850 grahamje
                switch ($sql_sort[0])
874 5850 grahamje
                {
875 5850 grahamje
                        case 'u':
876 5850 grahamje
                                $sql_sort_table        = USERS_TABLE . ' u, ';
877 5850 grahamje
                                $sql_sort_join        = ' AND u.user_id = p.poster_id ';
878 5850 grahamje
                        break;
879 5850 grahamje
880 5850 grahamje
                        case 't':
881 8604 naderman
                                $sql_sort_table        = ($type == 'posts' && !$firstpost_only) ? TOPICS_TABLE . ' t, ' : '';
882 8604 naderman
                                $sql_sort_join        = ($type == 'posts' && !$firstpost_only) ? ' AND t.topic_id = p.topic_id ' : '';
883 5850 grahamje
                        break;
884 5850 grahamje
885 5850 grahamje
                        case 'f':
886 5850 grahamje
                                $sql_sort_table        = FORUMS_TABLE . ' f, ';
887 5850 grahamje
                                $sql_sort_join        = ' AND f.forum_id = p.forum_id ';
888 5850 grahamje
                        break;
889 5850 grahamje
                }
890 5850 grahamje
891 5850 grahamje
                if (!sizeof($m_approve_fid_ary))
892 5850 grahamje
                {
893 5850 grahamje
                        $m_approve_fid_sql = ' AND p.post_approved = 1';
894 5850 grahamje
                }
895 5850 grahamje
                else if ($m_approve_fid_ary == array(-1))
896 5850 grahamje
                {
897 5850 grahamje
                        $m_approve_fid_sql = '';
898 5850 grahamje
                }
899 5850 grahamje
                else
900 5850 grahamje
                {
901 6273 naderman
                        $m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
902 5850 grahamje
                }
903 5850 grahamje
904 6211 naderman
                $select = ($type == 'posts') ? 'p.post_id' : 't.topic_id';
905 6211 naderman
                $is_mysql = false;
906 6211 naderman
907 5850 grahamje
                // If the cache was completely empty count the results
908 6211 naderman
                if (!$total_results)
909 5850 grahamje
                {
910 6497 acydburn
                        switch ($db->sql_layer)
911 5850 grahamje
                        {
912 6211 naderman
                                case 'mysql4':
913 6211 naderman
                                case 'mysqli':
914 9440 acydburn
//                                        $select = 'SQL_CALC_FOUND_ROWS ' . $select;
915 6211 naderman
                                        $is_mysql = true;
916 6211 naderman
                                break;
917 5850 grahamje
918 6211 naderman
                                default:
919 6211 naderman
                                        if ($type == 'posts')
920 6211 naderman
                                        {
921 6211 naderman
                                                $sql = 'SELECT COUNT(p.post_id) as total_results
922 7930 kellanved
                                                        FROM ' . POSTS_TABLE . ' p' . (($firstpost_only) ? ', ' . TOPICS_TABLE . ' t ' : ' ') . "
923 6211 naderman
                                                        WHERE $sql_author
924 6211 naderman
                                                                $sql_topic_id
925 7930 kellanved
                                                                $sql_firstpost
926 6211 naderman
                                                                $m_approve_fid_sql
927 6211 naderman
                                                                $sql_fora
928 6211 naderman
                                                                $sql_time";
929 6211 naderman
                                        }
930 6211 naderman
                                        else
931 6211 naderman
                                        {
932 6497 acydburn
                                                if ($db->sql_layer == 'sqlite')
933 6211 naderman
                                                {
934 6211 naderman
                                                        $sql = 'SELECT COUNT(topic_id) as total_results
935 6211 naderman
                                                                FROM (SELECT DISTINCT t.topic_id';
936 6211 naderman
                                                }
937 6211 naderman
                                                else
938 6211 naderman
                                                {
939 6211 naderman
                                                        $sql = 'SELECT COUNT(DISTINCT t.topic_id) as total_results';
940 6211 naderman
                                                }
941 6211 naderman
942 6225 naderman
                                                $sql .= ' FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p
943 6211 naderman
                                                        WHERE $sql_author
944 6211 naderman
                                                                $sql_topic_id
945 7930 kellanved
                                                                $sql_firstpost
946 6211 naderman
                                                                $m_approve_fid_sql
947 6211 naderman
                                                                $sql_fora
948 6211 naderman
                                                                AND t.topic_id = p.topic_id
949 6497 acydburn
                                                                $sql_time" . (($db->sql_layer == 'sqlite') ? ')' : '');
950 6211 naderman
                                        }
951 6211 naderman
                                        $result = $db->sql_query($sql);
952 6944 naderman
953 6211 naderman
                                        $total_results = (int) $db->sql_fetchfield('total_results');
954 6211 naderman
                                        $db->sql_freeresult($result);
955 6944 naderman
956 6211 naderman
                                        if (!$total_results)
957 6211 naderman
                                        {
958 6211 naderman
                                                return false;
959 6211 naderman
                                        }
960 6211 naderman
                                break;
961 5850 grahamje
                        }
962 5850 grahamje
                }
963 5850 grahamje
964 5850 grahamje
                // Build the query for really selecting the post_ids
965 5850 grahamje
                if ($type == 'posts')
966 5850 grahamje
                {
967 6211 naderman
                        $sql = "SELECT $select
968 8604 naderman
                                FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (($firstpost_only) ? ', ' . TOPICS_TABLE . ' t' : '') . "
969 5850 grahamje
                                WHERE $sql_author
970 5850 grahamje
                                        $sql_topic_id
971 7930 kellanved
                                        $sql_firstpost
972 5850 grahamje
                                        $m_approve_fid_sql
973 5850 grahamje
                                        $sql_fora
974 5850 grahamje
                                        $sql_sort_join
975 5850 grahamje
                                        $sql_time
976 5850 grahamje
                                ORDER BY $sql_sort";
977 5850 grahamje
                        $field = 'post_id';
978 5850 grahamje
                }
979 5850 grahamje
                else
980 5850 grahamje
                {
981 6211 naderman
                        $sql = "SELECT $select
982 6211 naderman
                                FROM " . $sql_sort_table . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p
983 5850 grahamje
                                WHERE $sql_author
984 5850 grahamje
                                        $sql_topic_id
985 7930 kellanved
                                        $sql_firstpost
986 5850 grahamje
                                        $m_approve_fid_sql
987 5850 grahamje
                                        $sql_fora
988 5850 grahamje
                                        AND t.topic_id = p.topic_id
989 5850 grahamje
                                        $sql_sort_join
990 5850 grahamje
                                        $sql_time
991 5850 grahamje
                                GROUP BY t.topic_id, " . $sort_by_sql[$sort_key] . '
992 5850 grahamje
                                ORDER BY ' . $sql_sort;
993 5850 grahamje
                        $field = 'topic_id';
994 5850 grahamje
                }
995 5850 grahamje
996 5850 grahamje
                // Only read one block of posts from the db and then cache it
997 5850 grahamje
                $result = $db->sql_query_limit($sql, $config['search_block_size'], $start);
998 5850 grahamje
999 5850 grahamje
                while ($row = $db->sql_fetchrow($result))
1000 5850 grahamje
                {
1001 10558 git-gate
                        $id_ary[] = (int) $row[$field];
1002 5850 grahamje
                }
1003 5850 grahamje
                $db->sql_freeresult($result);
1004 5850 grahamje
1005 6211 naderman
                if (!$total_results && $is_mysql)
1006 6211 naderman
                {
1007 9440 acydburn
                        // Count rows for the executed queries. Replace $select within $sql with SQL_CALC_FOUND_ROWS, and run it.
1008 9440 acydburn
                        $sql = str_replace('SELECT ' . $select, 'SELECT DISTINCT SQL_CALC_FOUND_ROWS p.post_id', $sql);
1009 9440 acydburn
1010 9440 acydburn
                        $db->sql_query($sql);
1011 9440 acydburn
                        $db->sql_freeresult($result);
1012 9440 acydburn
1013 6211 naderman
                        $sql = 'SELECT FOUND_ROWS() as total_results';
1014 6211 naderman
                        $result = $db->sql_query($sql);
1015 6211 naderman
                        $total_results = (int) $db->sql_fetchfield('total_results');
1016 6211 naderman
                        $db->sql_freeresult($result);
1017 6211 naderman
1018 6211 naderman
                        if (!$total_results)
1019 6211 naderman
                        {
1020 6211 naderman
                                return false;
1021 6211 naderman
                        }
1022 6211 naderman
                }
1023 6211 naderman
1024 5850 grahamje
                if (sizeof($id_ary))
1025 5850 grahamje
                {
1026 6211 naderman
                        $this->save_ids($search_key, '', $author_ary, $total_results, $id_ary, $start, $sort_dir);
1027 5850 grahamje
                        $id_ary = array_slice($id_ary, 0, $per_page);
1028 5850 grahamje
1029 6211 naderman
                        return $total_results;
1030 5850 grahamje
                }
1031 5850 grahamje
                return false;
1032 5850 grahamje
        }
1033 5850 grahamje
1034 5850 grahamje
        /**
1035 6211 naderman
        * Split a text into words of a given length
1036 6211 naderman
        *
1037 6211 naderman
        * The text is converted to UTF-8, cleaned up, and split. Then, words that
1038 6211 naderman
        * conform to the defined length range are returned in an array.
1039 6211 naderman
        *
1040 6211 naderman
        * NOTE: duplicates are NOT removed from the return array
1041 6211 naderman
        *
1042 6380 naderman
        * @param        string        $text        Text to split, encoded in UTF-8
1043 6211 naderman
        * @return        array                        Array of UTF-8 words
1044 6211 naderman
        *
1045 6211 naderman
        * @access        private
1046 6211 naderman
        */
1047 6211 naderman
        function split_message($text)
1048 6211 naderman
        {
1049 6886 naderman
                global $phpbb_root_path, $phpEx, $user;
1050 6211 naderman
1051 6211 naderman
                $match = $words = array();
1052 6211 naderman
1053 6211 naderman
                /**
1054 6211 naderman
                * Taken from the original code
1055 6211 naderman
                */
1056 6211 naderman
                // Do not index code
1057 6211 naderman
                $match[] = '#\[code(?:=.*?)?(\:?[0-9a-z]{5,})\].*?\[\/code(\:?[0-9a-z]{5,})\]#is';
1058 6211 naderman
                // BBcode
1059 6321 naderman
                $match[] = '#\[\/?[a-z0-9\*\+\-]+(?:=.*?)?(?::[a-z])?(\:?[0-9a-z]{5,})\]#';
1060 6211 naderman
1061 6886 naderman
                $min = $this->word_length['min'];
1062 6886 naderman
                $max = $this->word_length['max'];
1063 6211 naderman
1064 6211 naderman
                $isset_min = $min - 1;
1065 6211 naderman
1066 6211 naderman
                /**
1067 6211 naderman
                * Clean up the string, remove HTML tags, remove BBCodes
1068 6211 naderman
                */
1069 6380 naderman
                $word = strtok($this->cleanup(preg_replace($match, ' ', strip_tags($text)), -1), ' ');
1070 6211 naderman
1071 6800 davidmj
                while (strlen($word))
1072 6211 naderman
                {
1073 6800 davidmj
                        if (strlen($word) > 255 || strlen($word) <= $isset_min)
1074 6211 naderman
                        {
1075 6211 naderman
                                /**
1076 6422 davidmj
                                * Words longer than 255 bytes are ignored. This will have to be
1077 6211 naderman
                                * changed whenever we change the length of search_wordlist.word_text
1078 6211 naderman
                                *
1079 6211 naderman
                                * Words shorter than $isset_min bytes are ignored, too
1080 6211 naderman
                                */
1081 6211 naderman
                                $word = strtok(' ');
1082 6211 naderman
                                continue;
1083 6211 naderman
                        }
1084 6211 naderman
1085 6211 naderman
                        $len = utf8_strlen($word);
1086 6211 naderman
1087 6211 naderman
                        /**
1088 6211 naderman
                        * Test whether the word is too short to be indexed.
1089 6211 naderman
                        *
1090 6211 naderman
                        * Note that this limit does NOT apply to CJK and Hangul
1091 6211 naderman
                        */
1092 6211 naderman
                        if ($len < $min)
1093 6211 naderman
                        {
1094 6211 naderman
                                /**
1095 6211 naderman
                                * Note: this could be optimized. If the codepoint is lower than Hangul's range
1096 6211 naderman
                                * we know that it will also be lower than CJK ranges
1097 6211 naderman
                                */
1098 6211 naderman
                                if ((strncmp($word, UTF8_HANGUL_FIRST, 3) < 0 || strncmp($word, UTF8_HANGUL_LAST, 3) > 0)
1099 6211 naderman
                                 && (strncmp($word, UTF8_CJK_FIRST, 3) < 0 || strncmp($word, UTF8_CJK_LAST, 3) > 0)
1100 6211 naderman
                                 && (strncmp($word, UTF8_CJK_B_FIRST, 4) < 0 || strncmp($word, UTF8_CJK_B_LAST, 4) > 0))
1101 6211 naderman
                                {
1102 6211 naderman
                                        $word = strtok(' ');
1103 6211 naderman
                                        continue;
1104 6211 naderman
                                }
1105 6211 naderman
                        }
1106 6211 naderman
1107 6211 naderman
                        $words[] = $word;
1108 6211 naderman
                        $word = strtok(' ');
1109 6211 naderman
                }
1110 6211 naderman
1111 6211 naderman
                return $words;
1112 6211 naderman
        }
1113 6211 naderman
1114 6211 naderman
        /**
1115 5850 grahamje
        * Updates wordlist and wordmatch tables when a message is posted or changed
1116 5850 grahamje
        *
1117 6211 naderman
        * @param        string        $mode                Contains the post mode: edit, post, reply, quote
1118 6211 naderman
        * @param        int                $post_id        The id of the post which is modified/created
1119 6595 acydburn
        * @param        string        &$message        New or updated post content
1120 6595 acydburn
        * @param        string        &$subject        New or updated post subject
1121 6211 naderman
        * @param        int                $poster_id        Post author's user id
1122 6211 naderman
        * @param        int                $forum_id        The id of the forum in which the post is located
1123 6211 naderman
        *
1124 6211 naderman
        * @access        public
1125 5850 grahamje
        */
1126 6380 naderman
        function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id)
1127 5850 grahamje
        {
1128 6211 naderman
                global $config, $db, $user;
1129 5850 grahamje
1130 5850 grahamje
                if (!$config['fulltext_native_load_upd'])
1131 5850 grahamje
                {
1132 6211 naderman
                        /**
1133 6211 naderman
                        * The search indexer is disabled, return
1134 6211 naderman
                        */
1135 5850 grahamje
                        return;
1136 5850 grahamje
                }
1137 5850 grahamje
1138 5850 grahamje
                // Split old and new post/subject to obtain array of 'words'
1139 5850 grahamje
                $split_text = $this->split_message($message);
1140 6211 naderman
                $split_title = $this->split_message($subject);
1141 6211 naderman
1142 5850 grahamje
                $cur_words = array('post' => array(), 'title' => array());
1143 5850 grahamje
1144 5850 grahamje
                $words = array();
1145 5850 grahamje
                if ($mode == 'edit')
1146 5850 grahamje
                {
1147 5850 grahamje
                        $words['add']['post'] = array();
1148 5850 grahamje
                        $words['add']['title'] = array();
1149 5850 grahamje
                        $words['del']['post'] = array();
1150 5850 grahamje
                        $words['del']['title'] = array();
1151 5850 grahamje
1152 5850 grahamje
                        $sql = 'SELECT w.word_id, w.word_text, m.title_match
1153 6021 acydburn
                                FROM ' . SEARCH_WORDLIST_TABLE . ' w, ' . SEARCH_WORDMATCH_TABLE . " m
1154 5850 grahamje
                                WHERE m.post_id = $post_id
1155 5850 grahamje
                                        AND w.word_id = m.word_id";
1156 5850 grahamje
                        $result = $db->sql_query($sql);
1157 5850 grahamje
1158 5850 grahamje
                        while ($row = $db->sql_fetchrow($result))
1159 5850 grahamje
                        {
1160 5850 grahamje
                                $which = ($row['title_match']) ? 'title' : 'post';
1161 5850 grahamje
                                $cur_words[$which][$row['word_text']] = $row['word_id'];
1162 5850 grahamje
                        }
1163 5850 grahamje
                        $db->sql_freeresult($result);
1164 5850 grahamje
1165 5850 grahamje
                        $words['add']['post'] = array_diff($split_text, array_keys($cur_words['post']));
1166 5850 grahamje
                        $words['add']['title'] = array_diff($split_title, array_keys($cur_words['title']));
1167 5850 grahamje
                        $words['del']['post'] = array_diff(array_keys($cur_words['post']), $split_text);
1168 5850 grahamje
                        $words['del']['title'] = array_diff(array_keys($cur_words['title']), $split_title);
1169 5850 grahamje
                }
1170 5850 grahamje
                else
1171 5850 grahamje
                {
1172 5850 grahamje
                        $words['add']['post'] = $split_text;
1173 5850 grahamje
                        $words['add']['title'] = $split_title;
1174 5850 grahamje
                        $words['del']['post'] = array();
1175 5850 grahamje
                        $words['del']['title'] = array();
1176 5850 grahamje
                }
1177 5850 grahamje
                unset($split_text);
1178 5850 grahamje
                unset($split_title);
1179 5850 grahamje
1180 5850 grahamje
                // Get unique words from the above arrays
1181 5850 grahamje
                $unique_add_words = array_unique(array_merge($words['add']['post'], $words['add']['title']));
1182 9438 acydburn
1183 5850 grahamje
                // We now have unique arrays of all words to be added and removed and
1184 5850 grahamje
                // individual arrays of added and removed words for text and title. What
1185 5850 grahamje
                // we need to do now is add the new words (if they don't already exist)
1186 5850 grahamje
                // and then add (or remove) matches between the words and this post
1187 5850 grahamje
                if (sizeof($unique_add_words))
1188 5850 grahamje
                {
1189 5850 grahamje
                        $sql = 'SELECT word_id, word_text
1190 6271 acydburn
                                FROM ' . SEARCH_WORDLIST_TABLE . '
1191 6271 acydburn
                                WHERE ' . $db->sql_in_set('word_text', $unique_add_words);
1192 5850 grahamje
                        $result = $db->sql_query($sql);
1193 5850 grahamje
1194 5850 grahamje
                        $word_ids = array();
1195 5850 grahamje
                        while ($row = $db->sql_fetchrow($result))
1196 5850 grahamje
                        {
1197 5850 grahamje
                                $word_ids[$row['word_text']] = $row['word_id'];
1198 5850 grahamje
                        }
1199 5850 grahamje
                        $db->sql_freeresult($result);
1200 6271 acydburn
                        $new_words = array_diff($unique_add_words, array_keys($word_ids));
1201 5850 grahamje
1202 7182 naderman
                        $db->sql_transaction('begin');
1203 5850 grahamje
                        if (sizeof($new_words))
1204 5850 grahamje
                        {
1205 6497 acydburn
                                $sql_ary = array();
1206 5850 grahamje
1207 6497 acydburn
                                foreach ($new_words as $word)
1208 6497 acydburn
                                {
1209 7961 acydburn
                                        $sql_ary[] = array('word_text' => (string) $word, 'word_count' => 0);
1210 5850 grahamje
                                }
1211 7469 acydburn
                                $db->sql_return_on_error(true);
1212 6497 acydburn
                                $db->sql_multi_insert(SEARCH_WORDLIST_TABLE, $sql_ary);
1213 7469 acydburn
                                $db->sql_return_on_error(false);
1214 5850 grahamje
                        }
1215 6497 acydburn
                        unset($new_words, $sql_ary);
1216 5850 grahamje
                }
1217 7182 naderman
                else
1218 7182 naderman
                {
1219 7182 naderman
                        $db->sql_transaction('begin');
1220 7182 naderman
                }
1221 5850 grahamje
1222 5850 grahamje
                // now update the search match table, remove links to removed words and add links to new words
1223 5850 grahamje
                foreach ($words['del'] as $word_in => $word_ary)
1224 5850 grahamje
                {
1225 5850 grahamje
                        $title_match = ($word_in == 'title') ? 1 : 0;
1226 5850 grahamje
1227 5850 grahamje
                        if (sizeof($word_ary))
1228 5850 grahamje
                        {
1229 5850 grahamje
                                $sql_in = array();
1230 5850 grahamje
                                foreach ($word_ary as $word)
1231 5850 grahamje
                                {
1232 5850 grahamje
                                        $sql_in[] = $cur_words[$word_in][$word];
1233 5850 grahamje
                                }
1234 5850 grahamje
1235 6021 acydburn
                                $sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . '
1236 6271 acydburn
                                        WHERE ' . $db->sql_in_set('word_id', $sql_in) . '
1237 5850 grahamje
                                                AND post_id = ' . intval($post_id) . "
1238 5850 grahamje
                                                AND title_match = $title_match";
1239 5850 grahamje
                                $db->sql_query($sql);
1240 7182 naderman
1241 7182 naderman
                                $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
1242 7182 naderman
                                        SET word_count = word_count - 1
1243 7378 davidmj
                                        WHERE ' . $db->sql_in_set('word_id', $sql_in) . '
1244 7378 davidmj
                                                AND word_count > 0';
1245 7182 naderman
                                $db->sql_query($sql);
1246 7182 naderman
1247 5850 grahamje
                                unset($sql_in);
1248 5850 grahamje
                        }
1249 5850 grahamje
                }
1250 5850 grahamje
1251 7469 acydburn
                $db->sql_return_on_error(true);
1252 5850 grahamje
                foreach ($words['add'] as $word_in => $word_ary)
1253 5850 grahamje
                {
1254 5850 grahamje
                        $title_match = ($word_in == 'title') ? 1 : 0;
1255 5850 grahamje
1256 5850 grahamje
                        if (sizeof($word_ary))
1257 5850 grahamje
                        {
1258 7961 acydburn
                                $sql = 'INSERT INTO ' . SEARCH_WORDMATCH_TABLE . ' (post_id, word_id, title_match)
1259 7961 acydburn
                                        SELECT ' . (int) $post_id . ', word_id, ' . (int) $title_match . '
1260 7961 acydburn
                                        FROM ' . SEARCH_WORDLIST_TABLE . '
1261 6271 acydburn
                                        WHERE ' . $db->sql_in_set('word_text', $word_ary);
1262 5850 grahamje
                                $db->sql_query($sql);
1263 7182 naderman
1264 7182 naderman
                                $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
1265 7182 naderman
                                        SET word_count = word_count + 1
1266 7182 naderman
                                        WHERE ' . $db->sql_in_set('word_text', $word_ary);
1267 7182 naderman
                                $db->sql_query($sql);
1268 5850 grahamje
                        }
1269 5850 grahamje
                }
1270 7469 acydburn
                $db->sql_return_on_error(false);
1271 5850 grahamje
1272 7182 naderman
                $db->sql_transaction('commit');
1273 7182 naderman
1274 5850 grahamje
                // destroy cached search results containing any of the words removed or added
1275 6814 naderman
                $this->destroy_cache(array_unique(array_merge($words['add']['post'], $words['add']['title'], $words['del']['post'], $words['del']['title'])), array($poster_id));
1276 5850 grahamje
1277 5850 grahamje
                unset($unique_add_words);
1278 5850 grahamje
                unset($words);
1279 5850 grahamje
                unset($cur_words);
1280 5850 grahamje
        }
1281 5850 grahamje
1282 5850 grahamje
        /**
1283 5850 grahamje
        * Removes entries from the wordmatch table for the specified post_ids
1284 5850 grahamje
        */
1285 6152 naderman
        function index_remove($post_ids, $author_ids, $forum_ids)
1286 5850 grahamje
        {
1287 5850 grahamje
                global $db;
1288 5850 grahamje
1289 6271 acydburn
                if (sizeof($post_ids))
1290 6271 acydburn
                {
1291 7190 naderman
                        $sql = 'SELECT w.word_id, w.word_text, m.title_match
1292 7182 naderman
                                FROM ' . SEARCH_WORDMATCH_TABLE . ' m, ' . SEARCH_WORDLIST_TABLE . ' w
1293 7182 naderman
                                WHERE ' . $db->sql_in_set('m.post_id', $post_ids) . '
1294 7182 naderman
                                        AND w.word_id = m.word_id';
1295 7182 naderman
                        $result = $db->sql_query($sql);
1296 7182 naderman
1297 7182 naderman
                        $message_word_ids = $title_word_ids = $word_texts = array();
1298 7182 naderman
                        while ($row = $db->sql_fetchrow($result))
1299 7182 naderman
                        {
1300 7182 naderman
                                if ($row['title_match'])
1301 7182 naderman
                                {
1302 7182 naderman
                                        $title_word_ids[] = $row['word_id'];
1303 7182 naderman
                                }
1304 7182 naderman
                                else
1305 7182 naderman
                                {
1306 7182 naderman
                                        $message_word_ids[] = $row['word_id'];
1307 7182 naderman
                                }
1308 7182 naderman
                                $word_texts[] = $row['word_text'];
1309 7182 naderman
                        }
1310 7182 naderman
                        $db->sql_freeresult($result);
1311 7182 naderman
1312 7186 davidmj
                        if (sizeof($title_word_ids))
1313 7186 davidmj
                        {
1314 7186 davidmj
                                $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
1315 7186 davidmj
                                        SET word_count = word_count - 1
1316 7378 davidmj
                                        WHERE ' . $db->sql_in_set('word_id', $title_word_ids) . '
1317 7378 davidmj
                                                AND word_count > 0';
1318 7186 davidmj
                                $db->sql_query($sql);
1319 7186 davidmj
                        }
1320 7182 naderman
1321 7186 davidmj
                        if (sizeof($message_word_ids))
1322 7186 davidmj
                        {
1323 7186 davidmj
                                $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
1324 7186 davidmj
                                        SET word_count = word_count - 1
1325 7378 davidmj
                                        WHERE ' . $db->sql_in_set('word_id', $message_word_ids) . '
1326 7378 davidmj
                                                AND word_count > 0';
1327 7186 davidmj
                                $db->sql_query($sql);
1328 7186 davidmj
                        }
1329 7186 davidmj
1330 7182 naderman
                        unset($title_word_ids);
1331 7182 naderman
                        unset($message_word_ids);
1332 7182 naderman
1333 6271 acydburn
                        $sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . '
1334 6271 acydburn
                                WHERE ' . $db->sql_in_set('post_id', $post_ids);
1335 6271 acydburn
                        $db->sql_query($sql);
1336 6271 acydburn
                }
1337 5850 grahamje
1338 7182 naderman
                $this->destroy_cache(array_unique($word_texts), $author_ids);
1339 5850 grahamje
        }
1340 5850 grahamje
1341 5850 grahamje
        /**
1342 5850 grahamje
        * Tidy up indexes: Tag 'common words' and remove
1343 5850 grahamje
        * words no longer referenced in the match table
1344 5850 grahamje
        */
1345 5850 grahamje
        function tidy()
1346 5850 grahamje
        {
1347 5850 grahamje
                global $db, $config;
1348 5850 grahamje
1349 5850 grahamje
                // Is the fulltext indexer disabled? If yes then we need not
1350 5850 grahamje
                // carry on ... it's okay ... I know when I'm not wanted boo hoo
1351 5850 grahamje
                if (!$config['fulltext_native_load_upd'])
1352 5850 grahamje
                {
1353 5929 acydburn
                        set_config('search_last_gc', time(), true);
1354 5850 grahamje
                        return;
1355 5850 grahamje
                }
1356 5850 grahamje
1357 5850 grahamje
                $destroy_cache_words = array();
1358 5850 grahamje
1359 6814 naderman
                // Remove common words
1360 6814 naderman
                if ($config['num_posts'] >= 100 && $config['fulltext_native_common_thres'])
1361 5850 grahamje
                {
1362 6814 naderman
                        $common_threshold = ((double) $config['fulltext_native_common_thres']) / 100.0;
1363 6168 ludovic_arnaud
                        // First, get the IDs of common words
1364 7182 naderman
                        $sql = 'SELECT word_id, word_text
1365 7182 naderman
                                FROM ' . SEARCH_WORDLIST_TABLE . '
1366 7182 naderman
                                WHERE word_count > ' . floor($config['num_posts'] * $common_threshold) . '
1367 7182 naderman
                                        OR word_common = 1';
1368 5850 grahamje
                        $result = $db->sql_query($sql);
1369 5850 grahamje
1370 6271 acydburn
                        $sql_in = array();
1371 6271 acydburn
                        while ($row = $db->sql_fetchrow($result))
1372 5850 grahamje
                        {
1373 6271 acydburn
                                $sql_in[] = $row['word_id'];
1374 7182 naderman
                                $destroy_cache_words[] = $row['word_text'];
1375 6271 acydburn
                        }
1376 6271 acydburn
                        $db->sql_freeresult($result);
1377 5850 grahamje
1378 6271 acydburn
                        if (sizeof($sql_in))
1379 6271 acydburn
                        {
1380 6168 ludovic_arnaud
                                // Flag the words
1381 6271 acydburn
                                $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . '
1382 5850 grahamje
                                        SET word_common = 1
1383 6271 acydburn
                                        WHERE ' . $db->sql_in_set('word_id', $sql_in);
1384 5850 grahamje
                                $db->sql_query($sql);
1385 5850 grahamje
1386 7182 naderman
                                // by setting search_last_gc to the new time here we make sure that if a user reloads because the
1387 7182 naderman
                                // following query takes too long, he won't run into it again
1388 7182 naderman
                                set_config('search_last_gc', time(), true);
1389 7182 naderman
1390 6168 ludovic_arnaud
                                // Delete the matches
1391 6271 acydburn
                                $sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . '
1392 6271 acydburn
                                        WHERE ' . $db->sql_in_set('word_id', $sql_in);
1393 5850 grahamje
                                $db->sql_query($sql);
1394 5850 grahamje
                        }
1395 6271 acydburn
                        unset($sql_in);
1396 5850 grahamje
                }
1397 5850 grahamje
1398 7182 naderman
                if (sizeof($destroy_cache_words))
1399 7182 naderman
                {
1400 7182 naderman
                        // destroy cached search results containing any of the words that are now common or were removed
1401 7182 naderman
                        $this->destroy_cache(array_unique($destroy_cache_words));
1402 7182 naderman
                }
1403 5929 acydburn
1404 5929 acydburn
                set_config('search_last_gc', time(), true);
1405 5850 grahamje
        }
1406 5850 grahamje
1407 5850 grahamje
        /**
1408 5850 grahamje
        * Deletes all words from the index
1409 5850 grahamje
        */
1410 5850 grahamje
        function delete_index($acp_module, $u_action)
1411 5850 grahamje
        {
1412 5850 grahamje
                global $db;
1413 5850 grahamje
1414 6954 davidmj
                switch ($db->sql_layer)
1415 6954 davidmj
                {
1416 6954 davidmj
                        case 'sqlite':
1417 6954 davidmj
                        case 'firebird':
1418 6954 davidmj
                                $db->sql_query('DELETE FROM ' . SEARCH_WORDLIST_TABLE);
1419 6954 davidmj
                                $db->sql_query('DELETE FROM ' . SEARCH_WORDMATCH_TABLE);
1420 6954 davidmj
                                $db->sql_query('DELETE FROM ' . SEARCH_RESULTS_TABLE);
1421 6954 davidmj
                        break;
1422 6954 davidmj
1423 6954 davidmj
                        default:
1424 7036 davidmj
                                $db->sql_query('TRUNCATE TABLE ' . SEARCH_WORDLIST_TABLE);
1425 7036 davidmj
                                $db->sql_query('TRUNCATE TABLE ' . SEARCH_WORDMATCH_TABLE);
1426 6954 davidmj
                                $db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
1427 6954 davidmj
                        break;
1428 6954 davidmj
                }
1429 5850 grahamje
        }
1430 5850 grahamje
1431 5850 grahamje
        /**
1432 5850 grahamje
        * Returns true if both FULLTEXT indexes exist
1433 5850 grahamje
        */
1434 5850 grahamje
        function index_created()
1435 5850 grahamje
        {
1436 6211 naderman
                if (!sizeof($this->stats))
1437 5850 grahamje
                {
1438 5850 grahamje
                        $this->get_stats();
1439 5850 grahamje
                }
1440 5850 grahamje
1441 5850 grahamje
                return ($this->stats['total_words'] && $this->stats['total_matches']) ? true : false;
1442 5850 grahamje
        }
1443 5850 grahamje
1444 5850 grahamje
        /**
1445 5850 grahamje
        * Returns an associative array containing information about the indexes
1446 5850 grahamje
        */
1447 5850 grahamje
        function index_stats()
1448 5850 grahamje
        {
1449 5850 grahamje
                global $user;
1450 5850 grahamje
1451 6211 naderman
                if (!sizeof($this->stats))
1452 5850 grahamje
                {
1453 5850 grahamje
                        $this->get_stats();
1454 5850 grahamje
                }
1455 5850 grahamje
1456 5850 grahamje
                return array(
1457 5850 grahamje
                        $user->lang['TOTAL_WORDS']                => $this->stats['total_words'],
1458 5850 grahamje
                        $user->lang['TOTAL_MATCHES']        => $this->stats['total_matches']);
1459 5850 grahamje
        }
1460 5850 grahamje
1461 5850 grahamje
        function get_stats()
1462 5850 grahamje
        {
1463 5850 grahamje
                global $db;
1464 5850 grahamje
1465 5850 grahamje
                $sql = 'SELECT COUNT(*) as total_words
1466 6021 acydburn
                        FROM ' . SEARCH_WORDLIST_TABLE;
1467 5850 grahamje
                $result = $db->sql_query($sql);
1468 5850 grahamje
                $this->stats['total_words'] = (int) $db->sql_fetchfield('total_words');
1469 5850 grahamje
                $db->sql_freeresult($result);
1470 5850 grahamje
1471 5850 grahamje
                $sql = 'SELECT COUNT(*) as total_matches
1472 6021 acydburn
                        FROM ' . SEARCH_WORDMATCH_TABLE;
1473 5850 grahamje
                $result = $db->sql_query($sql);
1474 5850 grahamje
                $this->stats['total_matches'] = (int) $db->sql_fetchfield('total_matches');
1475 5850 grahamje
                $db->sql_freeresult($result);
1476 5850 grahamje
        }
1477 5850 grahamje
1478 5850 grahamje
        /**
1479 6211 naderman
        * Clean up a text to remove non-alphanumeric characters
1480 6211 naderman
        *
1481 6211 naderman
        * This method receives a UTF-8 string, normalizes and validates it, replaces all
1482 6211 naderman
        * non-alphanumeric characters with strings then returns the result.
1483 6211 naderman
        *
1484 6211 naderman
        * Any number of "allowed chars" can be passed as a UTF-8 string in NFC.
1485 6211 naderman
        *
1486 6211 naderman
        * @param        string        $text                        Text to split, in UTF-8 (not normalized or sanitized)
1487 6211 naderman
        * @param        string        $allowed_chars        String of special chars to allow
1488 6211 naderman
        * @param        string        $encoding                Text encoding
1489 6211 naderman
        * @return        string                                        Cleaned up text, only alphanumeric chars are left
1490 6584 acydburn
        *
1491 6584 acydburn
        * @todo normalizer::cleanup being able to be used?
1492 6211 naderman
        */
1493 6380 naderman
        function cleanup($text, $allowed_chars = null, $encoding = 'utf-8')
1494 6211 naderman
        {
1495 6211 naderman
                global $phpbb_root_path, $phpEx;
1496 6211 naderman
                static $conv = array(), $conv_loaded = array();
1497 6211 naderman
                $words = $allow = array();
1498 6211 naderman
1499 6584 acydburn
                // Convert the text to UTF-8
1500 6211 naderman
                $encoding = strtolower($encoding);
1501 6211 naderman
                if ($encoding != 'utf-8')
1502 6211 naderman
                {
1503 6211 naderman
                        $text = utf8_recode($text, $encoding);
1504 6211 naderman
                }
1505 6211 naderman
1506 6211 naderman
                $utf_len_mask = array(
1507 6211 naderman
                        "\xC0"        =>        2,
1508 6211 naderman
                        "\xD0"        =>        2,
1509 6211 naderman
                        "\xE0"        =>        3,
1510 6211 naderman
                        "\xF0"        =>        4
1511 6211 naderman
                );
1512 6211 naderman
1513 6211 naderman
                /**
1514 6211 naderman
                * Replace HTML entities and NCRs
1515 6211 naderman
                */
1516 6548 acydburn
                $text = htmlspecialchars_decode(utf8_decode_ncr($text), ENT_QUOTES);
1517 6211 naderman
1518 6211 naderman
                /**
1519 6211 naderman
                * Load the UTF-8 normalizer
1520 6211 naderman
                *
1521 6211 naderman
                * If we use it more widely, an instance of that class should be held in a
1522 6211 naderman
                * a global variable instead
1523 6211 naderman
                */
1524 6584 acydburn
                utf_normalizer::nfc($text);
1525 6211 naderman
1526 6211 naderman
                /**
1527 6211 naderman
                * The first thing we do is:
1528 6211 naderman
                *
1529 6211 naderman
                * - convert ASCII-7 letters to lowercase
1530 6211 naderman
                * - remove the ASCII-7 non-alpha characters
1531 6211 naderman
                * - remove the bytes that should not appear in a valid UTF-8 string: 0xC0,
1532 6211 naderman
                *   0xC1 and 0xF5-0xFF
1533 6211 naderman
                *
1534 6211 naderman
                * @todo in theory, the third one is already taken care of during normalization and those chars should have been replaced by Unicode replacement chars
1535 6211 naderman
                */
1536 6211 naderman
                $sb_match        = "ISTCPAMELRDOJBNHFGVWUQKYXZ\r\n\t!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\xC0\xC1\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF";
1537 6211 naderman
                $sb_replace        = 'istcpamelrdojbnhfgvwuqkyxz                                                                              ';
1538 6211 naderman
1539 6211 naderman
                /**
1540 6211 naderman
                * This is the list of legal ASCII chars, it is automatically extended
1541 6211 naderman
                * with ASCII chars from $allowed_chars
1542 6211 naderman
                */
1543 6211 naderman
                $legal_ascii = ' eaisntroludcpmghbfvq10xy2j9kw354867z';
1544 6211 naderman
1545 6211 naderman
                /**
1546 6211 naderman
                * Prepare an array containing the extra chars to allow
1547 6211 naderman
                */
1548 6211 naderman
                if (isset($allowed_chars[0]))
1549 6211 naderman
                {
1550 6211 naderman
                        $pos = 0;
1551 6211 naderman
                        $len = strlen($allowed_chars);
1552 6211 naderman
                        do
1553 6211 naderman
                        {
1554 6211 naderman
                                $c = $allowed_chars[$pos];
1555 6211 naderman
1556 6211 naderman
                                if ($c < "\x80")
1557 6211 naderman
                                {
1558 6211 naderman
                                        /**
1559 6211 naderman
                                        * ASCII char
1560 6211 naderman
                                        */
1561 6211 naderman
                                        $sb_pos = strpos($sb_match, $c);
1562 6211 naderman
                                        if (is_int($sb_pos))
1563 6211 naderman
                                        {
1564 6211 naderman
                                                /**
1565 6211 naderman
                                                * Remove the char from $sb_match and its corresponding
1566 6211 naderman
                                                * replacement in $sb_replace
1567 6211 naderman
                                                */
1568 6211 naderman
                                                $sb_match = substr($sb_match, 0, $sb_pos) . substr($sb_match, $sb_pos + 1);
1569 6211 naderman
                                                $sb_replace = substr($sb_replace, 0, $sb_pos) . substr($sb_replace, $sb_pos + 1);
1570 6211 naderman
                                                $legal_ascii .= $c;
1571 6211 naderman
                                        }
1572 6211 naderman
1573 6211 naderman
                                        ++$pos;
1574 6211 naderman
                                }
1575 6211 naderman
                                else
1576 6211 naderman
                                {
1577 6211 naderman
                                        /**
1578 6211 naderman
                                        * UTF-8 char
1579 6211 naderman
                                        */
1580 6211 naderman
                                        $utf_len = $utf_len_mask[$c & "\xF0"];
1581 6211 naderman
                                        $allow[substr($allowed_chars, $pos, $utf_len)] = 1;
1582 6211 naderman
                                        $pos += $utf_len;
1583 6211 naderman
                                }
1584 6211 naderman
                        }
1585 6211 naderman
                        while ($pos < $len);
1586 6211 naderman
                }
1587 6211 naderman
1588 6211 naderman
                $text = strtr($text, $sb_match, $sb_replace);
1589 6211 naderman
                $ret = '';
1590 6211 naderman
1591 6211 naderman
                $pos = 0;
1592 6211 naderman
                $len = strlen($text);
1593 6211 naderman
1594 6211 naderman
                do
1595 6211 naderman
                {
1596 6211 naderman
                        /**
1597 6211 naderman
                        * Do all consecutive ASCII chars at once
1598 6211 naderman
                        */
1599 6211 naderman
                        if ($spn = strspn($text, $legal_ascii, $pos))
1600 6211 naderman
                        {
1601 6211 naderman
                                $ret .= substr($text, $pos, $spn);
1602 6211 naderman
                                $pos += $spn;
1603 6211 naderman
                        }
1604 6211 naderman
1605 6211 naderman
                        if ($pos >= $len)
1606 6211 naderman
                        {
1607 6211 naderman
                                return $ret;
1608 6211 naderman
                        }
1609 6211 naderman
1610 6211 naderman
                        /**
1611 6211 naderman
                        * Capture the UTF char
1612 6211 naderman
                        */
1613 6211 naderman
                        $utf_len = $utf_len_mask[$text[$pos] & "\xF0"];
1614 6211 naderman
                        $utf_char = substr($text, $pos, $utf_len);
1615 6211 naderman
                        $pos += $utf_len;
1616 6211 naderman
1617 6211 naderman
                        if (($utf_char >= UTF8_HANGUL_FIRST && $utf_char <= UTF8_HANGUL_LAST)
1618 6211 naderman
                         || ($utf_char >= UTF8_CJK_FIRST && $utf_char <= UTF8_CJK_LAST)
1619 6211 naderman
                         || ($utf_char >= UTF8_CJK_B_FIRST && $utf_char <= UTF8_CJK_B_LAST))
1620 6211 naderman
                        {
1621 6211 naderman
                                /**
1622 6211 naderman
                                * All characters within these ranges are valid
1623 6211 naderman
                                *
1624 6211 naderman
                                * We separate them with a space in order to index each character
1625 6211 naderman
                                * individually
1626 6211 naderman
                                */
1627 6211 naderman
                                $ret .= ' ' . $utf_char . ' ';
1628 6211 naderman
                                continue;
1629 6211 naderman
                        }
1630 6211 naderman
1631 6211 naderman
                        if (isset($allow[$utf_char]))
1632 6211 naderman
                        {
1633 6211 naderman
                                /**
1634 6211 naderman
                                * The char is explicitly allowed
1635 6211 naderman
                                */
1636 6211 naderman
                                $ret .= $utf_char;
1637 6211 naderman
                                continue;
1638 6211 naderman
                        }
1639 6211 naderman
1640 6211 naderman
                        if (isset($conv[$utf_char]))
1641 6211 naderman
                        {
1642 6211 naderman
                                /**
1643 6211 naderman
                                * The char is mapped to something, maybe to itself actually
1644 6211 naderman
                                */
1645 6211 naderman
                                $ret .= $conv[$utf_char];
1646 6211 naderman
                                continue;
1647 6211 naderman
                        }
1648 6211 naderman
1649 6211 naderman
                        /**
1650 6211 naderman
                        * The char isn't mapped, but did we load its conversion table?
1651 6211 naderman
                        *
1652 6211 naderman
                        * The search indexer table is split into blocks. The block number of
1653 6211 naderman
                        * each char is equal to its codepoint right-shifted for 11 bits. It
1654 6211 naderman
                        * means that out of the 11, 16 or 21 meaningful bits of a 2-, 3- or
1655 6211 naderman
                        * 4- byte sequence we only keep the leftmost 0, 5 or 10 bits. Thus,
1656 6211 naderman
                        * all UTF chars encoded in 2 bytes are in the same first block.
1657 6211 naderman
                        */
1658 6211 naderman
                        if (isset($utf_char[2]))
1659 6211 naderman
                        {
1660 6211 naderman
                                if (isset($utf_char[3]))
1661 6211 naderman
                                {
1662 6211 naderman
                                        /**
1663 6211 naderman
                                        * 1111 0nnn 10nn nnnn 10nx xxxx 10xx xxxx
1664 6211 naderman
                                        * 0000 0111 0011 1111 0010 0000
1665 6211 naderman
                                        */
1666 6211 naderman
                                        $idx = ((ord($utf_char[0]) & 0x07) << 7) | ((ord($utf_char[1]) & 0x3F) << 1) | ((ord($utf_char[2]) & 0x20) >> 5);
1667 6211 naderman
                                }
1668 6211 naderman
                                else
1669 6211 naderman
                                {
1670 6211 naderman
                                        /**
1671 6211 naderman
                                        * 1110 nnnn 10nx xxxx 10xx xxxx
1672 6211 naderman
                                        * 0000 0111 0010 0000
1673 6211 naderman
                                        */
1674 6211 naderman
                                        $idx = ((ord($utf_char[0]) & 0x07) << 1) | ((ord($utf_char[1]) & 0x20) >> 5);
1675 6211 naderman
                                }
1676 6211 naderman
                        }
1677 6211 naderman
                        else
1678 6211 naderman
                        {
1679 6211 naderman
                                /**
1680 6211 naderman
                                * 110x xxxx 10xx xxxx
1681 6211 naderman
                                * 0000 0000 0000 0000
1682 6211 naderman
                                */
1683 6211 naderman
                                $idx = 0;
1684 6211 naderman
                        }
1685 6211 naderman
1686 6211 naderman
                        /**
1687 6211 naderman
                        * Check if the required conv table has been loaded already
1688 6211 naderman
                        */
1689 6211 naderman
                        if (!isset($conv_loaded[$idx]))
1690 6211 naderman
                        {
1691 6211 naderman
                                $conv_loaded[$idx] = 1;
1692 6211 naderman
                                $file = $phpbb_root_path . 'includes/utf/data/search_indexer_' . $idx . '.' . $phpEx;
1693 6211 naderman
1694 6211 naderman
                                if (file_exists($file))
1695 6211 naderman
                                {
1696 6211 naderman
                                        $conv += include($file);
1697 6211 naderman
                                }
1698 6211 naderman
                        }
1699 6211 naderman
1700 6211 naderman
                        if (isset($conv[$utf_char]))
1701 6211 naderman
                        {
1702 6211 naderman
                                $ret .= $conv[$utf_char];
1703 6211 naderman
                        }
1704 6211 naderman
                        else
1705 6211 naderman
                        {
1706 6211 naderman
                                /**
1707 6211 naderman
                                * We add an entry to the conversion table so that we
1708 6211 naderman
                                * don't have to convert to codepoint and perform the checks
1709 6211 naderman
                                * that are above this block
1710 6211 naderman
                                */
1711 6211 naderman
                                $conv[$utf_char] = ' ';
1712 6211 naderman
                                $ret .= ' ';
1713 6211 naderman
                        }
1714 6211 naderman
                }
1715 6211 naderman
                while (1);
1716 6211 naderman
1717 6211 naderman
                return $ret;
1718 6211 naderman
        }
1719 6211 naderman
1720 6211 naderman
        /**
1721 5850 grahamje
        * Returns a list of options for the ACP to display
1722 5850 grahamje
        */
1723 5850 grahamje
        function acp()
1724 5850 grahamje
        {
1725 5850 grahamje
                global $user, $config;
1726 5850 grahamje
1727 6211 naderman
1728 6211 naderman
                /**
1729 6211 naderman
                * if we need any options, copied from fulltext_native for now, will have to be adjusted or removed
1730 6211 naderman
                */
1731 6211 naderman
1732 5850 grahamje
                $tpl = '
1733 5850 grahamje
                <dl>
1734 5850 grahamje
                        <dt><label for="fulltext_native_load_upd">' . $user->lang['YES_SEARCH_UPDATE'] . ':</label><br /><span>' . $user->lang['YES_SEARCH_UPDATE_EXPLAIN'] . '</span></dt>
1735 7608 acydburn
                        <dd><label><input type="radio" id="fulltext_native_load_upd" name="config[fulltext_native_load_upd]" value="1"' . (($config['fulltext_native_load_upd']) ? ' checked="checked"' : '') . ' class="radio" /> ' . $user->lang['YES'] . '</label><label><input type="radio" name="config[fulltext_native_load_upd]" value="0"' . ((!$config['fulltext_native_load_upd']) ? ' checked="checked"' : '') . ' class="radio" /> ' . $user->lang['NO'] . '</label></dd>
1736 5850 grahamje
                </dl>
1737 5850 grahamje
                <dl>
1738 5850 grahamje
                        <dt><label for="fulltext_native_min_chars">' . $user->lang['MIN_SEARCH_CHARS'] . ':</label><br /><span>' . $user->lang['MIN_SEARCH_CHARS_EXPLAIN'] . '</span></dt>
1739 5850 grahamje
                        <dd><input id="fulltext_native_min_chars" type="text" size="3" maxlength="3" name="config[fulltext_native_min_chars]" value="' . (int) $config['fulltext_native_min_chars'] . '" /></dd>
1740 5850 grahamje
                </dl>
1741 5850 grahamje
                <dl>
1742 5850 grahamje
                        <dt><label for="fulltext_native_max_chars">' . $user->lang['MAX_SEARCH_CHARS'] . ':</label><br /><span>' . $user->lang['MAX_SEARCH_CHARS_EXPLAIN'] . '</span></dt>
1743 5850 grahamje
                        <dd><input id="fulltext_native_max_chars" type="text" size="3" maxlength="3" name="config[fulltext_native_max_chars]" value="' . (int) $config['fulltext_native_max_chars'] . '" /></dd>
1744 5850 grahamje
                </dl>
1745 6814 naderman
                <dl>
1746 6814 naderman
                        <dt><label for="fulltext_native_common_thres">' . $user->lang['COMMON_WORD_THRESHOLD'] . ':</label><br /><span>' . $user->lang['COMMON_WORD_THRESHOLD_EXPLAIN'] . '</span></dt>
1747 9126 naderman
                        <dd><input id="fulltext_native_common_thres" type="text" size="3" maxlength="3" name="config[fulltext_native_common_thres]" value="' . (double) $config['fulltext_native_common_thres'] . '" /> %</dd>
1748 6814 naderman
                </dl>
1749 5850 grahamje
                ';
1750 5850 grahamje
1751 5850 grahamje
                // These are fields required in the config table
1752 5850 grahamje
                return array(
1753 5850 grahamje
                        'tpl'                => $tpl,
1754 6814 naderman
                        'config'        => array('fulltext_native_load_upd' => 'bool', 'fulltext_native_min_chars' => 'integer:0:255', 'fulltext_native_max_chars' => 'integer:0:255', 'fulltext_native_common_thres' => 'double:0:100')
1755 5850 grahamje
                );
1756 5850 grahamje
        }
1757 5850 grahamje
}