xref: /plugin/sphinxsearch-was/SphinxSearch.php (revision 97:dfcc5c0823af)
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        $this->_result = $res;
76
77        if (empty($res['matches'])) {
78            return false;
79	}
80        return true;
81    }
82
83    public function getPages($keywords)
84    {
85        if (empty($this->_result['matches'])) {
86            return false;
87	}
88        $pagesIdsAll = $this->getPagesIds();
89        $this->_offset = 0;
90        $counter = 0;
91        $tmpRes = array();
92        $pagesIds = array();
93        foreach($pagesIdsAll as $id => $pageData){
94            $this->_offset++;
95            if(auth_quickaclcheck($pageData['page']) >= AUTH_READ){
96                if(!isset($tmpRes[$pageData['page']])){
97                    $tmpRes[$pageData['page']] = 1;
98                    $counter++;
99                }
100                $pagesIds[$id] = $pageData;
101                if ($counter == $this->_resultsPerPage){
102                    break;
103                }
104            }
105        }
106        if (empty($pagesIds)){
107            return false;
108        }
109
110        $pagesList = array();
111        $body = array();
112        $titleText = array();
113        $category = array();
114        foreach ($pagesIds as $crc => $data){
115            if (!empty($data['hid'])){
116                $bodyHtml = p_render('xhtml',p_get_instructions(getSectionByTitleLevel($data['page'], $data['title'], true)),$info);
117            } else {
118                $bodyHtml = p_wiki_xhtml($data['page']);
119            }
120            $bodyHtml = preg_replace("#[\s]+?</li>#", "</li>;", $bodyHtml);
121            $bodyHtml = htmlspecialchars_decode($bodyHtml);
122            $body[$crc] = strip_tags($bodyHtml);
123            if(!empty($data['title_text'])){
124                $titleText[$crc] = strip_tags($data['title_text']);
125            } else {
126                $titleText[$crc] = $data['page'];
127            }
128            $category[$crc] = $data['page'];
129        }
130
131        //$starQuery = $this->starQuery($keywords);
132        $bodyExcerpt = $this->getExcerpt($body, $keywords);
133        $titleTextExcerpt = $this->getExcerpt($titleText, $keywords);
134        $i = 0;
135        $results = array();
136        foreach($body as $crc => $notused){
137            $results[$crc] = array(
138                'page' => $pagesIds[$crc]['page'],
139                'bodyExcerpt' => $bodyExcerpt[$i],
140                'titleTextExcerpt' => $titleTextExcerpt[$i],
141                'hid' => $pagesIds[$crc]['hid'],
142                'title' => $pagesIds[$crc]['title'],
143                'title_text' => $pagesIds[$crc]['title_text']
144            );
145            $i++;
146        }
147        return $results;
148    }
149
150    public function getPagesIds()
151    {
152        $pageMapper = new PageMapper();
153
154        return $pageMapper->getByCrc(array_keys($this->_result['matches']));
155    }
156
157    public function getOffset()
158    {
159        return $this->_offset;
160    }
161
162    public function getError()
163    {
164        return $this->_sphinx->GetLastError();
165    }
166
167    public function getTotalFound()
168    {
169        return !empty($this->_result['total_found'])?$this->_result['total_found'] : 0;
170    }
171
172    public function getExcerpt($data, $query)
173    {
174        return $this->_sphinx->BuildExcerpts($data, $this->_index, $query,
175                    array(
176                        'limit' => $this->_snippetSize,
177                        'around' => $this->_aroundKeyword,
178                        'weight_order' => 1,
179                        'sp' => 1
180                    )
181                );
182    }
183
184    public function starQuery($query)
185    {
186        $query = $this->removeStars($query);
187        $words = explode(" ", $query);
188        foreach($words as $id => $word){
189            $words[$id] = "*".$word."*";
190        }
191        return implode(" ", $words);
192    }
193
194    public function removeStars($query)
195    {
196        $words = explode(" ", $query);
197        foreach($words as $id => $word){
198            $words[$id] = trim($word, "*");
199        }
200        return implode(" ", $words);
201    }
202
203    public function getQuery()
204    {
205        return $this->_query;
206    }
207
208    public function setSnippetSize($symbols = 256)
209    {
210        $this->_snippetSize = $symbols;
211    }
212
213    public function setArroundWordsCount($words = 5)
214    {
215        $this->_aroundKeyword = $words;
216    }
217
218    public function setTitlePriority($priority)
219    {
220        $this->_titlePriority = $priority;
221    }
222
223    public function setBodyPriority($priority)
224    {
225        $this->_bodyPriority = $priority;
226    }
227
228    public function setNamespacePriority($priority)
229    {
230        $this->_namespacePriority = $priority;
231    }
232
233    public function setPagenamePriority($priority)
234    {
235        $this->_pagenamePriority = $priority;
236    }
237}
238