Passed
Push — sheepy/introspection ( f93ae4...e91b37 )
by Simon
12:51 queued 10:13
created

SchemaService::setStore()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
4
namespace Firesphere\SolrSearch\Services;
5
6
use Exception;
7
use Firesphere\SolrSearch\Helpers\SearchIntrospection;
8
use Firesphere\SolrSearch\Helpers\Statics;
9
use Firesphere\SolrSearch\Indexes\BaseIndex;
10
use SilverStripe\Control\Director;
11
use SilverStripe\Core\Injector\Injector;
12
use SilverStripe\Core\Manifest\ModuleLoader;
13
use SilverStripe\ORM\ArrayList;
14
use SilverStripe\ORM\FieldType\DBHTMLText;
15
use SilverStripe\View\ViewableData;
16
17
class SchemaService extends ViewableData
18
{
19
20
    /**
21
     * @var bool
22
     */
23
    protected $store = false;
24
    /**
25
     * @var string ABSOLUTE Path to template
26
     */
27
    protected $template;
28
29
    /**
30
     * @var string ABSOLUTE Path to types.ss template
31
     */
32
    protected $typesTemplate;
33
    /**
34
     * @var BaseIndex
35
     */
36
    protected $index;
37
38
    /**
39
     * @var SearchIntrospection
40
     */
41
    protected $introspection;
42
43
    /**
44
     * @var SolrCoreService
45
     */
46
    protected $coreService;
47
48
    /**
49
     * SchemaService constructor.
50
     */
51 59
    public function __construct()
52
    {
53 59
        parent::__construct();
54 59
        $this->introspection = Injector::inst()->get(SearchIntrospection::class);
55 59
        $this->coreService = Injector::inst()->get(SolrCoreService::class);
56 59
    }
57
58
    /**
59
     * @return BaseIndex
60
     */
61 1
    public function getIndex()
62
    {
63 1
        return $this->index;
64
    }
65
66
    /**
67
     * @param BaseIndex $index
68
     * @return SchemaService
69
     */
70 59
    public function setIndex($index)
71
    {
72 59
        $this->index = $index;
73
        // Add the index to the introspection as well, there's no need for a separate call here
74
        // We're loading this core, why would we want the introspection from a different index?
75 59
        $this->introspection->setIndex($index);
76
77 59
        return $this;
78
    }
79
80
    /**
81
     * @return string
82
     */
83 26
    public function getIndexName()
84
    {
85 26
        return $this->index->getIndexName();
86
    }
87
88
    /**
89
     * @return string
90
     */
91 26
    public function getDefaultField()
92
    {
93 26
        return $this->index->getDefaultField();
94
    }
95
96
    /**
97
     * Get the Identifier Field for Solr
98
     *
99
     * @return string
100
     */
101 25
    public function getIDField()
102
    {
103 25
        return SolrCoreService::ID_FIELD;
104
    }
105
106
    /**
107
     * Get the Identifier Field for Solr
108
     *
109
     * @return string
110
     */
111 25
    public function getClassID()
112
    {
113 25
        return SolrCoreService::CLASS_ID_FIELD;
114
    }
115
116
    /**
117
     * @return ArrayList
118
     * @throws Exception
119
     */
120 25
    public function getFulltextFieldDefinitions()
121
    {
122 25
        $return = ArrayList::create();
123 25
        $store = $this->store;
124 25
        $this->store = true;
125 25
        foreach ($this->index->getFulltextFields() as $field) {
126 25
            $this->getFieldDefinition($field, $return);
127
        }
128
129 25
        $this->store = $store;
130
131 25
        return $return;
132
    }
133
134
    /**
135
     * @param $fieldName
136
     * @param ArrayList $return
137
     * @param null|string $copyField
138
     * @throws Exception
139
     */
140 25
    protected function getFieldDefinition($fieldName, &$return, $copyField = null)
141
    {
142 25
        $field = $this->introspection->getFieldIntrospection($fieldName);
143 25
        $typeMap = Statics::getTypeMap();
144 25
        $storeFields = $this->getStoreFields();
145 25
        foreach ($field as $name => $options) {
146
            // Temporary short-name solution until the Introspection is properly solved
147 25
            $name = explode('\\', $name);
148 25
            $name = end($name);
149
            // Boosted fields are always stored
150 25
            $store = ($this->store || array_key_exists($options['name'], $storeFields)) ? 'true' : 'false';
151
            $item = [
152 25
                'Field'       => $name,
153 25
                'Type'        => $typeMap[$options['type']],
154 25
                'Indexed'     => 'true',
155 25
                'Stored'      => $options['store'] ?? $store,
156 25
                'MultiValued' => $options['multi_valued'] ? 'true' : 'false',
157 25
                'Destination' => $copyField
158
            ];
159 25
            $return->push($item);
160
        }
161 25
    }
162
163
    /**
164
     * @return ArrayList
165
     */
166 25
    public function getCopyFields()
167
    {
168 25
        $fields = $this->index->getCopyFields();
169
170 25
        $return = ArrayList::create();
171 25
        foreach ($fields as $field => $copyFields) {
172
            $item = [
173 25
                'Field' => $field
174
            ];
175
176 25
            $return->push($item);
177
        }
178
179 25
        return $return;
180
    }
181
182
    /**
183
     * @return ArrayList
184
     * @throws Exception
185
     */
186 25
    public function getCopyFieldDefinitions()
187
    {
188 25
        $copyFields = $this->index->getCopyFields();
189
190 25
        $return = ArrayList::create();
191
192 25
        foreach ($copyFields as $field => $fields) {
193
            // Allow all fields to be in a copyfield via a shorthand
194 25
            if ($fields[0] === '*') {
195 25
                $fields = $this->index->getFulltextFields();
196
            }
197
198 25
            foreach ($fields as $copyField) {
199 25
                $this->getFieldDefinition($copyField, $return, $field);
200
            }
201
        }
202
203 25
        return $return;
204
    }
205
206
    /**
207
     * @return ArrayList
208
     * @throws Exception
209
     */
210 25
    public function getFilterFieldDefinitions()
211
    {
212 25
        $return = ArrayList::create();
213 25
        $originalStore = $this->store;
214 25
        $this->store = Director::isDev() ? true : false;
215 25
        $fields = $this->index->getFilterFields();
216 25
        foreach ($this->index->getFacetFields() as $facetField) {
217 25
            $fields[] = $facetField['Field'];
218
        }
219 25
        $fields = array_unique($fields);
220 25
        foreach ($fields as $field) {
221 25
            $this->getFieldDefinition($field, $return);
222
        }
223
224 25
        $this->store = $originalStore;
225
226 25
        return $return;
227
    }
228
229
    /**
230
     * @return DBHTMLText
231
     */
232 25
    public function getTypes()
233
    {
234 25
        if (!$this->typesTemplate) {
235 25
            $solrVersion = $this->coreService->getSolrVersion();
236 25
            $dir = ModuleLoader::getModule('firesphere/solr-search')->getPath();
237 25
            $template = sprintf('%s/Solr/%s/templates/types.ss', $dir, $solrVersion);
238 25
            $this->setTypesTemplate($template);
239
        }
240
241 25
        return $this->renderWith($this->getTypesTemplate());
242
    }
243
244
    /**
245
     * @return string
246
     */
247 25
    public function getTypesTemplate()
248
    {
249 25
        return $this->typesTemplate;
250
    }
251
252
    /**
253
     * @param string $typesTemplate
254
     * @return SchemaService
255
     */
256 25
    public function setTypesTemplate($typesTemplate)
257
    {
258 25
        $this->typesTemplate = $typesTemplate;
259
260 25
        return $this;
261
    }
262
263
    /**
264
     * @return DBHTMLText
265
     */
266 25
    public function generateSchema()
267
    {
268 25
        if (!$this->template) {
269 25
            $solrVersion = $this->coreService->getSolrVersion();
270 25
            $dir = ModuleLoader::getModule('firesphere/solr-search')->getPath();
271 25
            $template = sprintf('%s/Solr/%s/templates/schema.ss', $dir, $solrVersion);
272 25
            $this->setTemplate($template);
273
        }
274
275 25
        return $this->renderWith($this->getTemplate());
276
    }
277
278
    /**
279
     * @return string
280
     */
281 25
    public function getTemplate()
282
    {
283 25
        return $this->template;
284
    }
285
286
    /**
287
     * @param string $template
288
     * @return SchemaService
289
     */
290 25
    public function setTemplate($template)
291
    {
292 25
        $this->template = $template;
293
294 25
        return $this;
295
    }
296
297
    /**
298
     * @return string
299
     */
300 25
    public function getExtrasPath()
301
    {
302
        // @todo configurable but with default to the current absolute path
303 25
        $dir = ModuleLoader::getModule('firesphere/solr-search')->getPath();
304
305 25
        $confDirs = SolrCoreService::config()->get('paths');
306 25
        $solrVersion = $this->coreService->getSolrVersion();
307
308 25
        return sprintf($confDirs[$solrVersion]['extras'], $dir);
309
    }
310
311
    /**
312
     * @param bool $store
313
     */
314 59
    public function setStore(bool $store): void
315
    {
316 59
        $this->store = $store;
317 59
    }
318
319
    /**
320
     * @return array
321
     */
322 25
    protected function getStoreFields(): array
323
    {
324 25
        $boostedFields = $this->index->getBoostedFields();
325 25
        $storedFields = $this->index->getStoredFields();
326 25
        $facetFields = $this->index->getFacetFields();
327 25
        $facetArray = [];
328 25
        foreach ($facetFields as $key => $facetField) {
329 25
            $facetArray[] = $key . '.' . $facetField['Field'];
330
        }
331
        // Boosts, facets and obviously stored fields need to be stored
332 25
        $storeFields = array_merge($storedFields, array_keys($boostedFields), $facetArray);
333
334 25
        return $storeFields;
335
    }
336
}
337