xref: /plugin/sphinxsearch-was/SphinxSearch.php (revision 119:5fd51cb55608)
1<?php
2/*
3 * To change this template, choose Tools | Templates
4 * and open the template in the editor.
5 */
6
7class SphinxSearch
8{
9    private $_sphinx = null;
10    private $_result = array();
11    private $_index = null;
12    private $_query = '';
13
14    private $_snippetSize = 256;
15    private $_aroundKeyword = 5;
16    private $_resultsPerPage = 10;
17
18    private $_titlePriority = 1;
19    private $_bodyPriority = 1;
20    private $_namespacePriority = 1;
21    private $_pagenamePriority = 1;
22
23    public function  __construct($host, $port, $index)
24    {
25        $this->_sphinx = new SphinxClient();
26        $this->_sphinx->SetServer($host, $port);
27        $this->_sphinx->SetMatchMode(SPH_MATCH_EXTENDED2);
28
29        $this->_index = $index;
30    }
31
32    public function setSearchAllQuery($keywords, $categories)
33    {
34        $keywords = $this->_sphinx->EscapeString($keywords);
35        $starKeyword = $this->starQuery($keywords);
36        $this->_query = "(@(namespace,pagename) $starKeyword) | (@(body,title) {$keywords})";
37    }
38
39    public function setSearchAllQueryWithCategoryFilter($keywords, $categories)
40    {
41        $keywords = $this->_sphinx->EscapeString($keywords);
42        $starKeyword = $this->starQuery($keywords);
43        if(strpos($categories, "-") === 0){
44            $categories = '-"'.substr($categories, 1).'"';
45        }
46        $this->_query = "(@(namespace,pagename) {$categories}) & ((@(body,title) {$keywords}) | (@(namespace,pagename) {$starKeyword}))";
47    }
48
49    public function setSearchCategoryQuery($keywords, $categories)
50    {
51        $keywords = $this->_sphinx->EscapeString($keywords);
52        $starKeyword = $this->starQuery($keywords);
53        if (!empty($categories)){
54            $this->_query = "(@(namespace,pagename) $categories $starKeyword)";
55        } else {
56            $this->_query = "(@(namespace,pagename) $starKeyword)";
57        }
58
59    }
60
61    public function search($start, $resultsPerPage = 10)
62    {
63        $this->_resultsPerPage = $resultsPerPage;
64
65        $this->_sphinx->SetFieldWeights(array(
66            'namespace' => $this->_namespacePriority,
67            'pagename' => $this->_pagenamePriority,
68            'title' => $this->_titlePriority,
69            'body' => $this->_bodyPriority)
70        );
71
72        $this->_sphinx->SetLimits($start, $resultsPerPage+100);
73
74        $res = $this->_sphinx->Query($this->_query, $this->_index);
75
76        $this->_result = $res;
77
78        if (empty($res['matches'])) {
79            return false;
80	}
81        return true;
82    }
83
84    public function getPages($keywords)
85    {
86        if (empty($this->_result['matches'])) {
87            return false;
88	}
89
90        $pagesIdsAll = $this->getPagesIds();
91        $this->_offset = 0;
92        $counter = 0;
93        $tmpRes = array();
94        $pagesIds = array();
95        foreach($pagesIdsAll as $id => $pageData){
96            $this->_offset++;
97            if(auth_quickaclcheck($pageData['page']) >= AUTH_READ){
98                if(!isset($tmpRes[$pageData['page']])){
99                    $tmpRes[$pageData['page']] = 1;
100                    $counter++;
101                }
102                $pagesIds[$id] = $pageData;
103                if ($counter == $this->_resultsPerPage){
104                    break;
105                }
106            }
107        }
108        if (empty($pagesIds)){
109            return false;
110        }
111
112        $pagesList = array();
113        $body = array();
114        $titleText = array();
115        $category = array();
116        foreach ($pagesIds as $crc => $data){
117            if (!empty($data['hid'])){
118                $bodyHtml = p_render('xhtml',p_get_instructions(getSectionByTitleLevel($data['page'], $data['title'], true)),$info);
119            } else {
120                $bodyHtml = p_wiki_xhtml($data['page']);
121            }
122            $bodyHtml = preg_replace("#[\s]+?</li>#", "</li>;", $bodyHtml);
123            $bodyHtml = htmlspecialchars_decode($bodyHtml);
124            $body[$crc] = strip_tags($bodyHtml);
125            if(!empty($data['title_text'])){
126                $titleText[$crc] = strip_tags($data['title_text']);
127            } else {
128                $titleText[$crc] = $data['page'];
129            }
130            $category[$crc] = $data['page'];
131        }
132
133        //$starQuery = $this->starQuery($keywords);
134        $bodyExcerpt = $this->getExcerpt($body, $keywords);
135        $titleTextExcerpt = $this->getExcerpt($titleText, $keywords);
136        $i = 0;
137        $results = array();
138        foreach($body as $crc => $notused){
139            $results[$crc] = array(
140                'page' => $pagesIds[$crc]['page'],
141                'bodyExcerpt' => $bodyExcerpt[$i],
142                'titleTextExcerpt' => $titleTextExcerpt[$i],
143                'hid' => $pagesIds[$crc]['hid'],
144                'title' => $pagesIds[$crc]['title'],
145                'title_text' => $pagesIds[$crc]['title_text']
146            );
147            $i++;
148        }
149        return $results;
150    }
151
152    public function getPagesIds()
153    {
154        $pageMapper = new PageMapper();
155
156        return $pageMapper->getByCrc(array_keys($this->_result['matches']));
157    }
158
159    public function getOffset()
160    {
161        return $this->_offset;
162    }
163
164    public function getError()
165    {
166        return $this->_sphinx->GetLastError();
167    }
168
169    public function getTotalFound()
170    {
171        return !empty($this->_result['total_found'])?$this->_result['total_found'] : 0;
172    }
173
174    public function getExcerpt($data, $query)
175    {
176        return $this->_sphinx->BuildExcerpts($data, $this->_index, $query,
177                    array(
178                        'limit' => $this->_snippetSize,
179                        'around' => $this->_aroundKeyword,
180                        'weight_order' => 1,
181                        'sp' => 1
182                    )
183                );
184    }
185
186    public function starQuery($query)
187    {
188        $query = $this->removeStars($query);
189        $words = explode(" ", $query);
190        foreach($words as $id => $word){
191            $words[$id] = "*".$word."*";
192        }
193        return implode(" ", $words);
194    }
195
196    public function removeStars($query)
197    {
198        $words = explode(" ", $query);
199        foreach($words as $id => $word){
200            $words[$id] = trim($word, "*");
201        }
202        return implode(" ", $words);
203    }
204
205    public function getQuery()
206    {
207        return $this->_query;
208    }
209
210    public function setSnippetSize($symbols = 256)
211    {
212        $this->_snippetSize = $symbols;
213    }
214
215    public function setArroundWordsCount($words = 5)
216    {
217        $this->_aroundKeyword = $words;
218    }
219
220    public function setTitlePriority($priority)
221    {
222        $this->_titlePriority = $priority;
223    }
224
225    public function setBodyPriority($priority)
226    {
227        $this->_bodyPriority = $priority;
228    }
229
230    public function setNamespacePriority($priority)
231    {
232        $this->_namespacePriority = $priority;
233    }
234
235    public function setPagenamePriority($priority)
236    {
237        $this->_pagenamePriority = $priority;
238    }
239}
240