Completed
Push — master ( cce487...102796 )
by Adam
04:22 queued 02:04
created

Search::term()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 2
crap 1
1
<?php
2
3
namespace BestServedCold\LaravelZendSearch\Lucene;
4
5
use ZendSearch\Lucene\Index\Term;
6
use ZendSearch\Lucene\Search\Query\Boolean;
7
use ZendSearch\Lucene\Search\Query\Fuzzy;
8
use ZendSearch\Lucene\Search\Query\MultiTerm;
9
use ZendSearch\Lucene\Search\Query\Phrase;
10
use ZendSearch\Lucene\Search\Query\Wildcard;
11
use ZendSearch\Lucene\Search\Query\Term as QueryTerm;
12
use ZendSearch\Lucene\Search\QueryHit;
13
use ZendSearch\Lucene\Search\QueryParser;
14
15
/**
16
 * Class Search
17
 * @package BestServedCold\LaravelZendSearch\Lucene
18
 */
19
class Search
20
{
21
    /**
22
     * @var Index $index
23
     */
24
    protected $index;
25
26
    /**
27
     * @var Query $query
28
     */
29
    protected $query;
30
31
    /**
32
     * @var string|boolean $path
33
     */
34
    private $path;
35
36
    /**
37
     * @var int $limit
38
     */
39
    private $limit = 25;
40
41
    /**
42
     * @var int $offset
43
     */
44
    private $offset = 0;
45
46
    /**
47
     * @var Boolean
48
     */
49
    private static $boolean;
50
51
    /**
52
     * Search constructor.
53
     *
54
     * @param Index $index
55
     * @param Query $query
56
     */
57 32
    public function __construct(Index $index, Query $query)
58
    {
59 32
        $this->index = $index;
60 32
        $this->query = $query;
61 32
        QueryParser::setDefaultEncoding('UTF-8');
62 32
    }
63
64
    /**
65
     * @param  $name
66
     * @param  $arguments
67
     * @return $this
68
     * @throws \BadMethodCallException
69
     */
70 2
    public function __call($name, $arguments)
71
    {
72 2
        if (method_exists($this->query, $name)) {
73 1
            $this->query->$name($arguments);
74 1
            return $this;
75
        }
76
77 1
        throw new \BadMethodCallException;
78
    }
79
80
    /**
81
     * @param  integer $limit
82
     * @return $this
83
     */
84 1
    public function limit($limit)
85
    {
86 1
        $this->limit = $limit;
87 1
        return $this;
88
    }
89
90
    /**
91
     * @param  integer $offset
92
     * @return $this
93
     */
94 1
    public function offset($offset)
95
    {
96 1
        $this->offset = $offset;
97 1
        return $this;
98
    }
99
100
    /**
101
     * @param bool|string $path
102
     * @return $this
103
     */
104 21
    public function path($path = false)
105
    {
106 21
        $this->path = $path;
107 21
        return $this;
108
    }
109
110
    /**
111
     * @param $string
112
     * @return $this
113
     */
114 1
    public function raw($string)
115
    {
116 1
        $this->query->add(QueryParser::parse($string));
117 1
        return $this;
118
    }
119
120
    /**
121
     * @param $string
122
     * @param null|string $field
123
     * @param null        $offsets
124
     * @return $this
125
     * @return $this
126
     */
127 2
    public function phrase($string, $field = null, $offsets = null)
128
    {
129 2
        $this->query->add(new Phrase(explode(' ', $string), $offsets, $field));
130 2
        return $this;
131
    }
132
133
    /**
134
     * @param $string
135
     * @param null|string   $field
136
     * @return $this
137
     */
138 1
    public function fuzzy($string, $field = null)
139
    {
140 1
        $this->query->add(new Fuzzy($this->indexTerm($field, $string)));
141 1
        return $this;
142
    }
143
144
    /**
145
     * @param $string
146
     * @param null|string   $field
147
     * @return Term
148
     */
149 4
    protected function indexTerm($string, $field = null)
150
    {
151 4
        return new Term(strtolower($string), $field);
152
    }
153
154
    /**
155
     * @param  $string
156
     * @param  null|string $field
157
     * @return $this
158
     */
159 1
    public function wildcard($string, $field = null)
160
    {
161 1
        $this->query->add(new Wildcard($this->indexTerm($string, $field)));
162 1
        return $this;
163
    }
164
165
    /**
166
     * Where
167
     *
168
     * A helper method to access phrase or to pass multiple fields.  Phrase doesn't "match" exactly and
169
     * allows searching within the text field rather than matching the whole string.
170
     *
171
     * @param boolean|$string
172
     * @param null|string $field
173
     * @return $this|bool
174
     */
175 2
    public function where($string, $field = null)
176
    {
177 2
        is_array($field)
178 2
            ? $this->multiTerm($this->mapWhereArray($string, $field))
179 2
            : $this->phrase($string, $field);
180
181 2
        return $this;
182
    }
183
184
    /**
185
     * Match
186
     *
187
     * Provides an exact pattern match.
188
     *
189
     * @param  $string
190
     * @param  null $field
191
     * @return $this
192
     */
193 2
    public function match($string, $field = null)
194
    {
195 2
        $this->query->add($this->term($string, $field));
196 2
        return $this;
197
    }
198
199
    /**
200
     * @param array $terms
201
     * @return $this
202
     */
203 1
    public function multiTerm(array $terms)
204
    {
205 1
        $multiTerm = new MultiTerm;
206 1
        foreach ($terms as $field => $value) {
207 1
            $multiTerm->addTerm($this->indexTerm($value, $field), null);
208 1
        }
209
210 1
        $this->query->add($multiTerm);
211
212 1
        return $this;
213
    }
214
215
    /**
216
     * @param string $string
217
     * @param array  $array
218
     * @return mixed
219
     */
220 1
    private function mapWhereArray($string, array $array)
221
    {
222 1
        return array_map(
223
            function() use ($string) {
224 1
                return $string;
225 1
            },
226 1
            array_flip($array)
227 1
        );
228
    }
229
230
    /**
231
     * @param string         $string
232
     * @param string|null $field
233
     * @return QueryTerm
234
     */
235 3
    public function term($string, $field = null)
236
    {
237 3
        return new QueryTerm($this->indexTerm($string, $field));
238
    }
239
240
    /**
241
     * @return mixed
242
     */
243 2
    public function hits()
244
    {
245 2
        $index = $this->index->limit($this->limit + $this->offset)->open($this->path)->get();
246 2
        self::$boolean = $this->query->getBoolean();
247 2
        return $this->slice($this->mapIds($index->find(self::$boolean)));
248
    }
249
250
    /**
251
     * Slice
252
     *
253
     * This may look nasty, but there really isn't another way of offsetting results Lucene, and nor would
254
     * you want to really, that's not what it's designed for.  It will be quick up to a thousand and after
255
     * that you should be asking the user to "refine their search".
256
     *
257
     * @param  mixed $hits
258
     * @return array
259
     */
260 2
    public function slice($hits)
261
    {
262 2
        return $this->offset ? array_slice($hits, $this->offset) : $hits;
263
    }
264
265
    /**
266
     * @param  array|QueryHit $array
267
     * @return mixed
268
     */
269 3
    private function mapIds($array)
270
    {
271 3
        return array_map(
272 3
            function(QueryHit $hit) {
273 3
                return isset($hit->xref_id) ? $hit->xref_id : null;
274 3
            },
275
            $array
276 3
        );
277
    }
278
279
    /**
280
     * @return mixed
281
     */
282 1
    public static function getLastQuery()
283
    {
284 1
        return self::$boolean;
285
    }
286
}
287