BaseIndexTrait::getClient()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 1
cts 1
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
/**
3
 * Trait BaseIndexTrait|Firesphere\SolrSearch\Traits\BaseIndexTrait Used to extract methods from the
4
 * {@link \Firesphere\SolrSearch\Indexes\BaseIndex} to make the code more readable
5
 *
6
 * @package Firesphere\Solr\Search
7
 * @author Simon `Firesphere` Erkelens; Marco `Sheepy` Hermo
8
 * @copyright Copyright (c) 2018 - now() Firesphere & Sheepy
9
 */
10
11
12
namespace Firesphere\SolrSearch\Traits;
13
14
use Firesphere\SolrSearch\Indexes\BaseIndex as SolrIndex;
15
use ReflectionClass;
16
use ReflectionException;
17
use SilverStripe\Core\Config\Config;
18
use SilverStripe\Core\Injector\Injector;
19
use SilverStripe\Dev\Deprecation;
20
use SilverStripe\ORM\DataObject;
21
use SilverStripe\ORM\FieldType\DBDate;
22
use SilverStripe\ORM\FieldType\DBString;
23
use Solarium\Core\Client\Client;
24
25
26
/**
27
 * This is slightly cheating, but it works and also makes things more readable.
28
 *
29
 * This is slightly cheating, but it works and also makes things more readable.
30
 *
31
 * @package Firesphere\Solr\Search
32
 */
33
trait BaseIndexTrait
34
{
35
    /**
36
     * @var Client Query client
37
     */
38
    protected $client;
39
    /**
40
     * @var array Facet fields
41
     */
42
    protected $facetFields = [];
43
    /**
44
     * @var array Fulltext fields
45
     */
46
    protected $fulltextFields = [];
47
    /**
48
     * @var array Filterable fields
49
     */
50
    protected $filterFields = [];
51
    /**
52
     * @var array Sortable fields
53
     */
54
    protected $sortFields = [];
55
    /**
56
     * @var string Default search field
57
     */
58
    protected $defaultField = '_text';
59
    /**
60
     * @var array Stored fields
61
     */
62
    protected $storedFields = [];
63
    /**
64
     * @var array Fields to copy to the default fields
65
     */
66
    protected $copyFields = [
67
        '_text' => [
68
            '*',
69
        ],
70
    ];
71
    /**
72
     * usedAllFields is used to determine if the addAllFields method has been called
73
     * This is to prevent a notice if there is no yml.
74
     *
75
     * @var bool
76
     */
77
    protected $usedAllFields = false;
78
79
    /**
80
     * Return the copy fields
81
     *
82
     * @return array
83 36
     */
84
    public function getCopyFields(): array
85 36
    {
86
        return $this->copyFields;
87
    }
88
89
    /**
90
     * Set the copy fields
91
     *
92
     * @param array $copyField
93
     * @return $this
94 42
     */
95
    public function setCopyFields($copyField): self
96 42
    {
97
        $this->copyFields = $copyField;
98 42
99
        return $this;
100
    }
101
102
    /**
103
     * Return the default field for this index
104
     *
105
     * @return string
106 37
     */
107
    public function getDefaultField(): string
108 37
    {
109
        return $this->defaultField;
110
    }
111
112
    /**
113
     * Set the default field for this index
114
     *
115
     * @param string $defaultField
116
     * @return $this
117 42
     */
118
    public function setDefaultField($defaultField): self
119 42
    {
120
        $this->defaultField = $defaultField;
121 42
122
        return $this;
123
    }
124
125
    /**
126
     * Add a field to sort on
127
     *
128
     * @param $sortField
129
     * @return $this
130 45
     */
131
    public function addSortField($sortField): self
132 45
    {
133 45
        if (!in_array($sortField, $this->getFulltextFields(), true) &&
134
            !in_array($sortField, $this->getFilterFields(), true)
135 1
        ) {
136 1
            $this->addFulltextField($sortField);
137
            $this->sortFields[] = $sortField;
138
        }
139 45
140
        $this->setSortFields(array_unique($this->getSortFields()));
141 45
142
        return $this;
143
    }
144
145
    /**
146
     * Get the fulltext fields
147
     *
148
     * @return array
149 45
     */
150
    public function getFulltextFields(): array
151 45
    {
152 45
        return array_values(
153 45
            array_unique(
154
                $this->fulltextFields
155
            )
156
        );
157
    }
158
159
    /**
160
     * Set the fulltext fields
161
     *
162
     * @param array $fulltextFields
163
     * @return $this
164 42
     */
165
    public function setFulltextFields($fulltextFields): self
166 42
    {
167
        $this->fulltextFields = $fulltextFields;
168 42
169
        return $this;
170
    }
171
172
    /**
173
     * Get the filter fields
174
     *
175
     * @return array
176 54
     */
177
    public function getFilterFields(): array
178 54
    {
179
        return $this->filterFields;
180
    }
181
182
    /**
183
     * Set the filter fields
184
     *
185
     * @param array $filterFields
186
     * @return $this
187 42
     */
188
    public function setFilterFields($filterFields): self
189 42
    {
190
        $this->filterFields = $filterFields;
191 42
192
        return $this;
193
    }
194
195
    /**
196
     * Add a single Fulltext field
197
     *
198
     * @param string $fulltextField
199
     * @param null|string $forceType
200
     * @param array $options
201
     * @return $this
202 54
     */
203
    public function addFulltextField($fulltextField, $forceType = null, $options = []): self
204 54
    {
205
        if ($forceType) {
206
            Deprecation::notice('5.0', 'ForceType should be handled through casting');
207
        }
208 54
209
        $key = array_search($fulltextField, $this->getFilterFields(), true);
210 54
211 54
        if (!$key) {
212
            $this->fulltextFields[] = $fulltextField;
213
        }
214 54
215 1
        if (isset($options['boost'])) {
216
            $this->addBoostedField($fulltextField, [], $options['boost']);
217
        }
218 54
219 1
        if (isset($options['stored'])) {
220
            $this->storedFields[] = $fulltextField;
221
        }
222 54
223
        return $this;
224
    }
225
226
    /**
227
     * Add an abstract for the add Boosted Field to keep things consistent
228
     *
229
     * @param string $field
230
     * @param array|int $options
231
     * @param null|int $boost
232
     * @return mixed
233
     */
234
    abstract public function addBoostedField($field, $options = [], $boost = null);
235
236
    /**
237
     * Get the sortable fields
238
     *
239
     * @return array
240 45
     */
241
    public function getSortFields(): array
242 45
    {
243
        return $this->sortFields;
244
    }
245
246
    /**
247
     * Set/override the sortable fields
248
     *
249
     * @param array $sortFields
250
     * @return $this
251 46
     */
252
    public function setSortFields($sortFields): self
253 46
    {
254
        $this->sortFields = $sortFields;
255 46
256
        return $this;
257
    }
258
259
    /**
260
     * Add all text-type fields to the given index
261
     *
262
     * @throws ReflectionException
263 1
     */
264
    public function addAllFulltextFields()
265 1
    {
266 1
        $this->addAllFieldsByType(DBString::class);
267
    }
268
269
    /**
270
     * Add all database-backed text fields as fulltext searchable fields.
271
     *
272
     * For every class included in the index, examines those classes and all parent looking for "DBText" database
273
     * fields (Varchar, Text, HTMLText, etc) and adds them all as fulltext searchable fields.
274
     *
275
     * Note, there is no check on boosting etc. That needs to be done manually.
276
     *
277
     * @param string $dbType
278
     * @throws ReflectionException
279 1
     */
280
    protected function addAllFieldsByType($dbType = DBString::class): void
281 1
    {
282 1
        $this->usedAllFields = true;
283 1
        $classes = $this->getClasses();
284 1
        foreach ($classes as $key => $class) {
285
            $fields = DataObject::getSchema()->databaseFields($class, true);
286 1
287
            $this->addFulltextFieldsForClass($fields, $dbType);
288 1
        }
289
    }
290
291
    /**
292
     * This trait requires classes to be set, so getClasses can be called.
293
     *
294
     * @return array
295
     */
296
    abstract public function getClasses(): array;
297
298
    /**
299
     * Add all fields of a given type to the index
300
     *
301
     * @param array $fields The fields on the DataObject
302
     * @param string $dbType Class type the reflection should extend
303
     * @throws ReflectionException
304 1
     */
305
    protected function addFulltextFieldsForClass(array $fields, $dbType = DBString::class): void
306 1
    {
307 1
        foreach ($fields as $field => $type) {
308 1
            $pos = strpos($type, '(');
309 1
            if ($pos !== false) {
310
                $type = substr($type, 0, $pos);
311 1
            }
312 1
            $conf = Config::inst()->get(Injector::class, $type);
313 1
            $ref = new ReflectionClass($conf['class']);
314 1
            if ($ref->isSubclassOf($dbType)) {
315
                $this->addFulltextField($field);
316
            }
317 1
        }
318
    }
319
320
    /**
321
     * Add all date-type fields to the given index
322
     *
323
     * @throws ReflectionException
324 1
     */
325
    public function addAllDateFields()
326 1
    {
327 1
        $this->addAllFieldsByType(DBDate::class);
328
    }
329
330
    /**
331
     * Add a facet field
332
     *
333
     * @param $field
334
     * @param array $options
335
     * @return $this
336 45
     */
337
    public function addFacetField($field, $options): self
338 45
    {
339
        $this->facetFields[$field] = $options;
340 45
341 45
        if (!in_array($options['Field'], $this->getFilterFields(), true)) {
342
            $this->addFilterField($options['Field']);
343
        }
344 45
345
        return $this;
346
    }
347
348
    /**
349
     * Add a filterable field
350
     *
351
     * @param $filterField
352
     * @return $this
353 45
     */
354
    public function addFilterField($filterField): self
355 45
    {
356 45
        $key = array_search($filterField, $this->getFulltextFields(), true);
357 45
        if ($key === false) {
358
            $this->filterFields[] = $filterField;
359
        }
360 45
361
        return $this;
362
    }
363
364
    /**
365
     * Add a copy field
366
     *
367
     * @param string $field Name of the copyfield
368
     * @param array $options Array of all fields that should be copied to this copyfield
369
     * @return $this
370 1
     */
371
    public function addCopyField($field, $options): self
372 1
    {
373
        $this->copyFields[$field] = $options;
374 1
375
        return $this;
376
    }
377
378
    /**
379
     * Add a stored/fulltext field
380
     *
381
     * @param string $field
382
     * @param null|string $forceType
383
     * @param array $extraOptions
384
     * @return SolrIndex
385 1
     */
386
    public function addStoredField($field, $forceType = null, $extraOptions = []): self
387 1
    {
388 1
        $options = array_merge($extraOptions, ['stored' => 'true']);
389
        $this->addFulltextField($field, $forceType, $options);
390 1
391
        return $this;
392
    }
393
394
    /**
395
     * Get the client
396
     *
397
     * @return Client
398 14
     */
399
    public function getClient()
400 14
    {
401
        return $this->client;
402
    }
403
404
    /**
405
     * Set/override the client
406
     *
407
     * @param Client $client
408
     * @return $this
409 1
     */
410
    public function setClient($client): self
411 1
    {
412
        $this->client = $client;
413 1
414
        return $this;
415
    }
416
417
    /**
418
     * Get the stored field list
419
     *
420
     * @return array
421 2
     */
422
    public function getStoredFields(): array
423 2
    {
424
        return $this->storedFields;
425
    }
426
427
    /**
428
     * Set/override the stored field list
429
     *
430
     * @param array $storedFields
431
     * @return SolrIndex
432 1
     */
433
    public function setStoredFields(array $storedFields): self
434 1
    {
435
        $this->storedFields = $storedFields;
436 1
437
        return $this;
438
    }
439
}
440