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