xref: /plugin/sphinxsearch-was/SphinxSearch.php (revision 79:861f8b5b7ea3)
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($keywords)
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            if(!empty($data['title_text'])){
111                $titleText[$crc] = strip_tags($data['title_text']);
112            } else {
113                $titleText[$crc] = $data['page'];
114            }
115            $category[$crc] = $data['page'];
116        }
117
118        $starQuery = $this->starQuery($keywords);
119        $bodyExcerpt = $this->getExcerpt($body, $starQuery);
120        $titleTextExcerpt = $this->getExcerpt($titleText, $starQuery);
121        $i = 0;
122        $results = array();
123        foreach($body as $crc => $notused){
124            $results[$crc] = array(
125                'page' => $pagesIds[$crc]['page'],
126                'bodyExcerpt' => $bodyExcerpt[$i],
127                'titleTextExcerpt' => $titleTextExcerpt[$i],
128                'hid' => $pagesIds[$crc]['hid'],
129                'title' => $pagesIds[$crc]['title'],
130                'title_text' => $pagesIds[$crc]['title_text']
131            );
132            $i++;
133        }
134        return $results;
135    }
136
137    public function getPagesIds()
138    {
139        $pageMapper = new PageMapper();
140
141        return $pageMapper->getByCrc(array_keys($this->_result['matches']));
142    }
143
144    public function getOffset()
145    {
146        return $this->_offset;
147    }
148
149    public function getError()
150    {
151        return $this->_sphinx->GetLastError();
152    }
153
154    public function getTotalFound()
155    {
156        return !empty($this->_result['total_found'])?$this->_result['total_found'] : 0;
157    }
158
159    public function getExcerpt($data, $query)
160    {
161        return $this->_sphinx->BuildExcerpts($data, $this->_index, $query,
162                    array(
163                        'limit' => $this->_snippetSize,
164                        'around' => $this->_aroundKeyword,
165                        'weight_order' => 1,
166                        'sp' => 1
167                    )
168                );
169    }
170
171    public function starQuery($query)
172    {
173        $query = $this->removeStars($query);
174        $words = explode(" ", $query);
175        foreach($words as $id => $word){
176            $words[$id] = "*".$word."*";
177        }
178        return implode(" ", $words);
179    }
180
181    public function removeStars($query)
182    {
183        $words = explode(" ", $query);
184        foreach($words as $id => $word){
185            $words[$id] = trim($word, "*");
186        }
187        return implode(" ", $words);
188    }
189
190    public function getQuery()
191    {
192        return $this->_query;
193    }
194
195    public function setSnippetSize($symbols = 256)
196    {
197        $this->_snippetSize = $symbols;
198    }
199
200    public function setArroundWordsCount($words = 5)
201    {
202        $this->_aroundKeyword = $words;
203    }
204
205    public function setTitlePriority($priority)
206    {
207        $this->_titlePriority = $priority;
208    }
209
210    public function setBodyPriority($priority)
211    {
212        $this->_bodyPriority = $priority;
213    }
214
215    public function setCategoriesPriority($priority)
216    {
217        $this->_categoriesPriority = $priority;
218    }
219}
220