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