Completed
Push — master ( 0ed437...d532b6 )
by Adam
02:22
created

Search::mapWhereArray()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

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