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