CoreIndexTrait::addFulltextFieldsForClass()   A
last analyzed

Complexity

Conditions 4
Paths 5

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 8
nc 5
nop 2
dl 0
loc 11
rs 10
c 1
b 0
f 0
1
<?php
2
/**
3
 * Trait CoreIndexTrait|Firesphere\SearchBackend\Traits\CoreIndexTrait Used to extract methods from the
4
 * {@link \Firesphere\SearchBackend\Indexes\CoreIndex} to make the code more readable
5
 *
6
 * @package Firesphere\Search\Backend
7
 * @author Simon `Firesphere` Erkelens; Marco `Sheepy` Hermo
8
 * @copyright Copyright (c) 2018 - now() Firesphere & Sheepy
9
 */
10
11
namespace Firesphere\SearchBackend\Traits\IndexingTraits;
12
13
use ReflectionClass;
14
use ReflectionException;
15
use SilverStripe\Core\Config\Config;
16
use SilverStripe\Core\Injector\Injector;
17
use SilverStripe\ORM\DataObject;
18
use SilverStripe\ORM\FieldType\DBDate;
19
use SilverStripe\ORM\FieldType\DBString;
20
use Solarium\Core\Client\Client as SolrClient;
0 ignored issues
show
Bug introduced by
The type Solarium\Core\Client\Client was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
21
22
/**
23
 * Trait CoreIndexTrait
24
 * Getters and Setters for the  SolrIndex
25
 *
26
 * @package Firesphere\Search\Backend
27
 */
28
trait CoreIndexTrait
29
{
30
    /**
31
     * @var SolrClient Query client
32
     */
33
    protected $client;
34
    /**
35
     * @var string[] Classes to index
36
     */
37
    protected $class = [];
38
    /**
39
     * @var array Facet fields
40
     */
41
    protected $facetFields = [];
42
    /**
43
     * @var array Fulltext fields
44
     */
45
    protected $fulltextFields = [];
46
    /**
47
     * @var array Filterable fields
48
     */
49
    protected $filterFields = [];
50
    /**
51
     * @var array Sortable fields
52
     */
53
    protected $sortFields = [];
54
    /**
55
     * @var array Stored fields
56
     */
57
    protected $storedFields = [];
58
59
    /**
60
     * @var array Fields to copy to the default fields
61
     */
62
    protected $copyFields = [
63
        '_text' => [
64
            '*',
65
        ],
66
    ];
67
68
69
    /**
70
     * usedAllFields is used to determine if the addAllFields method has been called
71
     * This is to prevent a notice if there is no yml.
72
     *
73
     * @var bool
74
     */
75
    protected $usedAllFields = false;
76
77
    /**
78
     * Add a class to index or query
79
     * $options is not used anymore, added for backward compatibility
80
     *
81
     * @param $class
82
     * @param array $options unused
83
     * @return self
84
     */
85
    public function addClass($class, $options = []): self
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

85
    public function addClass($class, /** @scrutinizer ignore-unused */ $options = []): self

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
86
    {
87
        $this->class[] = $class;
88
89
        return $this;
90
    }
91
92
    /**
93
     * Set the classes
94
     *
95
     * @param array $class
96
     * @return $this
97
     */
98
    public function setClasses($class): self
99
    {
100
        $this->class = $class;
101
102
        return $this;
103
    }
104
105
    /**
106
     * Get the client
107
     *
108
     * @return SolrClient
109
     */
110
    public function getClient()
111
    {
112
        return $this->client;
113
    }
114
115
    /**
116
     * Set/override the client
117
     *
118
     * @param SolrClient $client
119
     * @return $this
120
     */
121
    public function setClient($client): self
122
    {
123
        $this->client = $client;
124
125
        return $this;
126
    }
127
128
    /**
129
     * Add a facet field
130
     *
131
     * @param $field
132
     * @param array $options
133
     * @return $this
134
     */
135
    public function addFacetField($field, $options): self
136
    {
137
        $this->facetFields[$field] = $options;
138
139
        if (!in_array($options['Field'], $this->getFilterFields(), true)) {
140
            $this->addFilterField($options['Field']);
141
        }
142
143
        return $this;
144
    }
145
146
    /**
147
     * Get the filter fields
148
     *
149
     * @return array
150
     */
151
    public function getFilterFields(): array
152
    {
153
        return $this->filterFields;
154
    }
155
156
    /**
157
     * Set the filter fields
158
     *
159
     * @param array $filterFields
160
     * @return $this
161
     */
162
    public function setFilterFields($filterFields): self
163
    {
164
        $this->filterFields = $filterFields;
165
        foreach ($filterFields as $filterField) {
166
            $this->addFulltextField($filterField);
167
        }
168
169
        return $this;
170
    }
171
172
    /**
173
     * Add a filterable field
174
     *
175
     * @param $filterField
176
     * @return $this
177
     */
178
    public function addFilterField($filterField): self
179
    {
180
        $key = array_search($filterField, $this->getFulltextFields(), true);
181
        if ($key === false) {
182
            $this->filterFields[] = $filterField;
183
        }
184
185
        return $this;
186
    }
187
188
    /**
189
     * Get the fulltext fields
190
     *
191
     * @return array
192
     */
193
    public function getFulltextFields(): array
194
    {
195
        return array_values(
196
            array_unique(
197
                $this->fulltextFields
198
            )
199
        );
200
    }
201
202
    /**
203
     * Set the fulltext fields
204
     *
205
     * @param array $fulltextFields
206
     * @return $this
207
     */
208
    public function setFulltextFields($fulltextFields): self
209
    {
210
        $this->fulltextFields = $fulltextFields;
211
212
        return $this;
213
    }
214
215
    /**
216
     * @return array
217
     */
218
    public function getFacetFields()
219
    {
220
        return $this->facetFields;
221
    }
222
223
    /**
224
     * Set the fields to use for faceting
225
     * @param $fields
226
     * @return $this
227
     */
228
    public function setFacetFields($fields)
229
    {
230
        $this->facetFields = $fields;
231
        foreach ($fields as $field => $option) {
232
            $this->addFulltextField($option['Field']);
233
        }
234
235
        return $this;
236
    }
237
238
    /**
239
     * Add a single Fulltext field
240
     *
241
     * @param string $fulltextField
242
     * @param array $options
243
     * @return $this
244
     */
245
    abstract public function addFulltextField($fulltextField, $options = []): self;
246
247
    /**
248
     * Add all text-type fields to the given index
249
     *
250
     * @throws ReflectionException
251
     */
252
    public function addAllFulltextFields()
253
    {
254
        $this->addAllFieldsByType(DBString::class);
255
    }
256
257
    /**
258
     * Add all database-backed text fields as fulltext searchable fields.
259
     *
260
     * For every class included in the index, examines those classes and all parent looking for "DBText" database
261
     * fields (Varchar, Text, HTMLText, etc) and adds them all as fulltext searchable fields.
262
     *
263
     * Note, there is no check on boosting etc. That needs to be done manually.
264
     *
265
     * @param string $dbType
266
     * @throws ReflectionException
267
     */
268
    protected function addAllFieldsByType($dbType = DBString::class): void
269
    {
270
        $this->usedAllFields = true;
271
        $classes = $this->getClasses();
272
        foreach ($classes as $key => $class) {
273
            $fields = DataObject::getSchema()->databaseFields($class, true);
274
275
            $this->addFulltextFieldsForClass($fields, $dbType);
276
        }
277
    }
278
279
    /**
280
     * Get classes
281
     *
282
     * @return array
283
     */
284
    public function getClasses(): array
285
    {
286
        return $this->class;
287
    }
288
289
    /**
290
     * Add all fields of a given type to the index
291
     *
292
     * @param array $fields The fields on the DataObject
293
     * @param string $dbType Class type the reflection should extend
294
     * @throws ReflectionException
295
     */
296
    protected function addFulltextFieldsForClass(array $fields, $dbType = DBString::class): void
297
    {
298
        foreach ($fields as $field => $type) {
299
            $pos = strpos($type, '(');
300
            if ($pos !== false) {
301
                $type = substr($type, 0, $pos);
302
            }
303
            $conf = Config::inst()->get(Injector::class, $type);
304
            $ref = new ReflectionClass($conf['class']);
305
            if ($ref->isSubclassOf($dbType)) {
306
                $this->addFulltextField($field);
307
            }
308
        }
309
    }
310
311
    /**
312
     * Add all date-type fields to the given index
313
     *
314
     * @throws ReflectionException
315
     */
316
    public function addAllDateFields()
317
    {
318
        $this->addAllFieldsByType(DBDate::class);
319
    }
320
321
    /**
322
     * Add a field to sort on
323
     *
324
     * @param $sortField
325
     * @return $this
326
     */
327
    public function addSortField($sortField): self
328
    {
329
        if (!in_array($sortField, $this->getFulltextFields(), true) &&
330
            !in_array($sortField, $this->getFilterFields(), true)
331
        ) {
332
            $this->addFulltextField($sortField);
333
            $this->sortFields[] = $sortField;
334
        }
335
336
        $this->setSortFields(array_unique($this->getSortFields()));
337
338
        return $this;
339
    }
340
341
    /**
342
     * Get the sortable fields
343
     *
344
     * @return array
345
     */
346
    public function getSortFields(): array
347
    {
348
        return $this->sortFields;
349
    }
350
351
    /**
352
     * Set/override the sortable fields
353
     *
354
     * @param array $sortFields
355
     * @return $this
356
     */
357
    public function setSortFields($sortFields): self
358
    {
359
        $this->sortFields = $sortFields;
360
        foreach ($sortFields as $sortField) {
361
            $this->addFulltextField($sortField);
362
        }
363
364
        return $this;
365
    }
366
367
    /**
368
     * @return array
369
     */
370
    public function getStoredFields(): array
371
    {
372
        return $this->storedFields;
373
    }
374
375
    /**
376
     * Stub to be compatible with Solr.
377
     * @param array $storedFields
378
     * @return $this
379
     */
380
    public function setStoredFields(array $storedFields)
381
    {
382
        $this->storedFields = $storedFields;
383
        foreach ($storedFields as $storedField) {
384
            $this->addFulltextField($storedField);
385
        }
386
387
        return $this;
388
    }
389
390
    /**
391
     * Add a copy field
392
     *
393
     * @param string $field Name of the copyfield
394
     * @param array $options Array of all fields that should be copied to this copyfield
395
     * @return $this
396
     */
397
    public function addCopyField($field, $options): self
398
    {
399
        $this->copyFields[$field] = $options;
400
401
        return $this;
402
    }
403
404
    /**
405
     * Return the copy fields
406
     *
407
     * @return array
408
     */
409
    public function getCopyFields(): array
410
    {
411
        return $this->copyFields;
412
    }
413
414
    /**
415
     * Set the copy fields
416
     *
417
     * @param array $copyField
418
     * @return $this
419
     */
420
    public function setCopyFields($copyField): self
421
    {
422
        $this->copyFields = $copyField;
423
424
        return $this;
425
    }
426
427
}
428