Passed
Push — hans/addAllFields ( 48c3f4...4a8f66 )
by Simon
05:46
created

BaseIndexTrait::addAllFields()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 10
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
4
namespace Firesphere\SolrSearch\Traits;
5
6
use Firesphere\SolrSearch\Indexes\BaseIndex;
7
use SilverStripe\Core\Config\Config;
8
use SilverStripe\Core\Injector\Injector;
9
use SilverStripe\Dev\Deprecation;
10
use SilverStripe\ORM\DataObject;
11
use SilverStripe\ORM\FieldType\DBDate;
12
use SilverStripe\ORM\FieldType\DBString;
13
use Solarium\Core\Client\Client;
14
15
/**
16
 * This is slightly cheating, but it works and also makes things more readable.
17
 *
18
 * Trait BaseIndexTrait
19
 * @package Firesphere\SolrSearch\Traits
20
 */
21
trait BaseIndexTrait
22
{
23
    /**
24
     * @var Client
25
     */
26
    protected $client;
27
    /**
28
     * @var array
29
     */
30
    protected $facetFields = [];
31
    /**
32
     * @var array
33
     */
34
    protected $fulltextFields = [];
35
    /**
36
     * @var array
37
     */
38
    protected $filterFields = [];
39
    /**
40
     * @var array
41
     */
42
    protected $sortFields = [];
43
    /**
44
     * @var string
45
     */
46
    protected $defaultField = '_text';
47
    /**
48
     * @var array
49
     */
50
    protected $storedFields = [];
51
    /**
52
     * @var array
53
     */
54
    protected $copyFields = [
55
        '_text' => [
56
            '*'
57
        ],
58
    ];
59
60
    /**
61
     * @return array
62 29
     */
63
    public function getCopyFields(): array
64 29
    {
65
        return $this->copyFields;
66
    }
67
68
    /**
69
     * @param array $copyField
70
     * @return $this
71 66
     */
72
    public function setCopyFields($copyField): self
73 66
    {
74
        $this->copyFields = $copyField;
75 66
76
        return $this;
77
    }
78
79
    /**
80
     * @return string
81 30
     */
82
    public function getDefaultField(): string
83 30
    {
84
        return $this->defaultField;
85
    }
86
87
    /**
88
     * @param string $defaultField
89
     * @return $this
90 66
     */
91
    public function setDefaultField($defaultField): self
92 66
    {
93
        $this->defaultField = $defaultField;
94 66
95
        return $this;
96
    }
97
98
    /**
99
     * @param $sortField
100
     * @return $this
101 67
     */
102
    public function addSortField($sortField): self
103 67
    {
104 67
        if (!in_array($sortField, $this->getFulltextFields(), true) &&
105
            !in_array($sortField, $this->getFilterFields(), true)
106 1
        ) {
107 1
            $this->addFulltextField($sortField);
108
            $this->sortFields[] = $sortField;
109
        }
110 67
111
        $this->setSortFields(array_unique($this->getSortFields()));
112 67
113
        return $this;
114
    }
115
116
    /**
117
     * @return array
118 67
     */
119
    public function getFulltextFields(): array
120 67
    {
121 67
        return array_values(
122 67
            array_unique(
123
                $this->fulltextFields
124
            )
125
        );
126
    }
127
128
    /**
129
     * @param array $fulltextFields
130
     * @return $this
131 66
     */
132
    public function setFulltextFields($fulltextFields): self
133 66
    {
134
        $this->fulltextFields = $fulltextFields;
135 66
136
        return $this;
137
    }
138
139
    /**
140
     * @return array
141 67
     */
142
    public function getFilterFields(): array
143 67
    {
144
        return $this->filterFields;
145
    }
146
147
    /**
148
     * @param array $filterFields
149
     * @return $this
150 66
     */
151
    public function setFilterFields($filterFields): self
152 66
    {
153
        $this->filterFields = $filterFields;
154 66
155
        return $this;
156
    }
157
158
    /**
159
     * @param string $fulltextField
160
     * @param null|string $forceType
161
     * @param array $options
162
     * @return $this
163 67
     */
164
    public function addFulltextField($fulltextField, $forceType = null, $options = []): self
165 67
    {
166
        if ($forceType) {
167
            Deprecation::notice('5.0', 'ForceType should be handled through casting');
168
        }
169 67
170
        $key = array_search($fulltextField, $this->getFilterFields(), true);
171 67
172 67
        if (!$key) {
173
            $this->fulltextFields[] = $fulltextField;
174
        }
175 67
176 1
        if (isset($options['boost'])) {
177
            $this->addBoostedField($fulltextField, [], $options['boost']);
178
        }
179 67
180 1
        if (isset($options['stored'])) {
181
            $this->storedFields[] = $fulltextField;
182
        }
183 67
184
        return $this;
185
    }
186
187
    /**
188
     * Add an abstract for the add Boosted Field to keep things consistent
189
     * @param string $field
190
     * @param array|int $options
191
     * @param null|int $boost
192
     * @return mixed
193
     */
194
    abstract public function addBoostedField($field, $options = [], $boost = null);
195
196
    /**
197
     * @return array
198 67
     */
199
    public function getSortFields(): array
200 67
    {
201
        return $this->sortFields;
202
    }
203
204
    /**
205
     * @param array $sortFields
206
     * @return $this
207 67
     */
208
    public function setSortFields($sortFields): self
209 67
    {
210
        $this->sortFields = $sortFields;
211 67
212
        return $this;
213
    }
214
215
    /**
216
     * @param bool $includeSubclasses
217
     * @throws \ReflectionException
218
     * @deprecated Please use addAllFulltextFields(). IncludeSubClasses is not used anymore
219
     */
220
    public function addFulltextFields($includeSubclasses = true)
1 ignored issue
show
Unused Code introduced by
The parameter $includeSubclasses 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

220
    public function addFulltextFields(/** @scrutinizer ignore-unused */ $includeSubclasses = true)

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...
221
    {
222
        $this->addAllFulltextFields();
223
    }
224
225
    /**
226
     * Add all database-backed text fields as fulltext searchable fields.
227
     *
228
     * For every class included in the index, examines those classes and all parent looking for "DBText" database
229
     * fields (Varchar, Text, HTMLText, etc) and adds them all as fulltext searchable fields.
230
     *
231
     * Note, there is no check on boosting etc. That needs to be done manually.
232
     * @param string $dbType
233 1
     * @throws \ReflectionException
234
     */
235 1
    protected function addAllFields($dbType = DBString::class)
0 ignored issues
show
Unused Code introduced by
The parameter $dbType 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

235
    protected function addAllFields(/** @scrutinizer ignore-unused */ $dbType = DBString::class)

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...
236 1
    {
237 1
        $classes = $this->getClasses();
0 ignored issues
show
Bug introduced by
It seems like getClasses() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

237
        /** @scrutinizer ignore-call */ 
238
        $classes = $this->getClasses();
Loading history...
238
        foreach ($classes as $key => $class) {
239 1
            $fields = DataObject::getSchema()->databaseFields($class, true);
240
241 1
            $this->addFulltextFieldsForClass($fields);
242
        }
243
    }
244
245
    /**
246
     * Add all text-type fields to the given index
247 1
     * @throws \ReflectionException
248
     */
249 1
    public function addAllFulltextFields()
250 1
    {
251 1
        $this->addAllFields(DBString::class);
252 1
    }
253
254 1
    /**
255 1
     * Add all date-type fields to the given index
256 1
     * @throws \ReflectionException
257 1
     */
258
    public function addAllDateFields()
259
    {
260 1
        $this->addAllFields(DBDate::class);
261
    }
262
263
    /**
264
     * Add all fields of a given type to the index
265
     * @param array $fields The fields on the DataObject
266
     * @param string $dbType Class type the reflection should extend
267 1
     * @throws \ReflectionException
268
     */
269 1
    protected function addFulltextFieldsForClass(array $fields, $dbType = DBString::class): void
270
    {
271 1
        foreach ($fields as $field => $type) {
272 1
            $pos = strpos($type, '(');
273
            if ($pos !== false) {
274
                $type = substr($type, 0, $pos);
275 1
            }
276
            $conf = Config::inst()->get(Injector::class, $type);
277
            $ref = new \ReflectionClass($conf['class']);
278
            if ($ref->isSubclassOf($dbType)) {
279
                $this->addFulltextField($field);
280
            }
281
        }
282 67
    }
283
284 67
    /**
285 67
     * @param $field
286 67
     * @param array $options
287
     * @return $this
288
     */
289 67
    public function addFacetField($field, $options): self
290
    {
291
        $this->facetFields[$field] = $options;
292
293
        if (!in_array($field, $this->getFilterFields(), true)) {
294
            $this->addFilterField($field);
295
        }
296
297 1
        return $this;
298
    }
299 1
300
    /**
301 1
     * @param $filterField
302
     * @return $this
303
     */
304
    public function addFilterField($filterField): self
305
    {
306
        $key = array_search($filterField, $this->getFulltextFields(), true);
307
        if ($key === false) {
308
            $this->filterFields[] = $filterField;
309
        }
310 1
311
        return $this;
312 1
    }
313 1
314
    /**
315 1
     * @param string $field Name of the copyfield
316
     * @param array $options Array of all fields that should be copied to this copyfield
317
     * @return $this
318
     */
319
    public function addCopyField($field, $options): self
320
    {
321 18
        $this->copyFields[$field] = $options;
322
323 18
        return $this;
324
    }
325
326
    /**
327
     * @param string $field
328
     * @param null|string $forceType
329
     * @param array $extraOptions
330 1
     * @return BaseIndex
331
     */
332 1
    public function addStoredField($field, $forceType = null, $extraOptions = []): self
333
    {
334 1
        $options = array_merge($extraOptions, ['stored' => 'true']);
335
        $this->addFulltextField($field, $forceType, $options);
336
337
        return $this;
338
    }
339
340 29
    /**
341
     * @return Client
342 29
     */
343
    public function getClient()
344
    {
345
        return $this->client;
346
    }
347
348
    /**
349 1
     * @param Client $client
350
     * @return $this
351 1
     */
352
    public function setClient($client): self
353 1
    {
354
        $this->client = $client;
355
356
        return $this;
357
    }
358
359
    /**
360
     * @return array
361
     */
362
    public function getStoredFields(): array
363
    {
364
        return $this->storedFields;
365
    }
366
367
    /**
368
     * @param array $storedFields
369
     * @return BaseIndex
370
     */
371
    public function setStoredFields(array $storedFields): self
372
    {
373
        $this->storedFields = $storedFields;
374
375
        return $this;
376
    }
377
}
378