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