Completed
Pull Request — master (#12)
by Adam
03:38
created

Search::term()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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