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