Passed
Push — main ( b4de74...74e495 )
by Simon
01:38
created

ElasticConfigureTask   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 127
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 55
c 1
b 0
f 0
dl 0
loc 127
rs 10
wmc 12

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getMethod() 0 12 2
A configureIndex() 0 19 2
A configToJSON() 0 16 2
A run() 0 30 4
A createConfigForIndex() 0 13 2
1
<?php
2
3
namespace Firesphere\ElasticSearch\Tasks;
4
5
use Elastic\Elasticsearch\Exception\ClientResponseException;
6
use Elastic\Elasticsearch\Exception\MissingParameterException;
7
use Elastic\Elasticsearch\Exception\ServerResponseException;
8
use Exception;
9
use Firesphere\ElasticSearch\Helpers\Statics;
10
use Firesphere\ElasticSearch\Indexes\ElasticIndex;
11
use Firesphere\ElasticSearch\Services\ElasticCoreService;
12
use Firesphere\SearchBackend\Helpers\FieldResolver;
13
use Firesphere\SearchBackend\Traits\LoggerTrait;
14
use Psr\Container\NotFoundExceptionInterface;
15
use SilverStripe\Core\ClassInfo;
16
use SilverStripe\Core\Config\Config;
17
use SilverStripe\Core\Injector\Injector;
18
use SilverStripe\Dev\BuildTask;
19
20
class ElasticConfigureTask extends BuildTask
21
{
22
    use LoggerTrait;
23
24
    /**
25
     * @var string URLSegment
26
     */
27
    private static $segment = 'ElasticConfigureTask';
0 ignored issues
show
introduced by
The private property $segment is not used, and could be removed.
Loading history...
28
    /**
29
     * @var string Title
30
     */
31
    protected $title = 'Configure Elastic cores';
32
    /**
33
     * @var string Description
34
     */
35
    protected $description = 'Create or reload a Elastic Core by adding or reloading a configuration.';
36
37
38
    public function run($request)
39
    {
40
        $this->extend('onBeforeElasticConfigureTask', $request);
41
42
        /** @var ElasticCoreService $service */
43
        $service = Injector::inst()->get(ElasticCoreService::class);
44
45
        $indexes = $service->getValidIndexes();
46
47
48
        foreach ($indexes as $index) {
49
            try {
50
                if ($request->getVar('clear')) {
51
                    $this->getLogger()->info(sprintf('Clearing index %s', $index));
52
                    $service->getClient()->indices()->delete(['index' => $index]);
53
                }
54
55
                $this->configureIndex($index, $service);
56
            } catch (Exception $error) {
57
                // @codeCoverageIgnoreStart
58
                $this->getLogger()->error(sprintf('Core loading failed for %s', $index));
59
                $this->getLogger()->error($error->getMessage()); // in browser mode, it might not always show
60
                // Continue to the next index
61
                continue;
62
                // @codeCoverageIgnoreEnd
63
            }
64
            $this->extend('onAfterConfigureIndex', $index);
65
        }
66
67
        $this->extend('onAfterElasticConfigureTask');
68
    }
69
70
    /**
71
     * Update/create a store
72
     * @param string $index
73
     * @param ElasticCoreService $service
74
     * @return void
75
     * @throws ClientResponseException
76
     * @throws MissingParameterException
77
     * @throws ServerResponseException
78
     * @throws NotFoundExceptionInterface
79
     */
80
    protected function configureIndex($index, ElasticCoreService $service)
81
    {
82
        /** @var ElasticIndex $instance */
83
        $instance = Injector::inst()->get($index, false);
84
85
        $indexName = $instance->getIndexName();
86
87
88
        $instanceConfig = $this->createConfigForIndex($instance);
89
90
        $body = $this->configToJSON($instanceConfig);
91
        $body['index'] = $indexName;
92
        $client = $service->getClient();
93
94
        $method = $this->getMethod($instance, $service);
95
        if ($method === 'update') {
96
            $client->indices()->putMapping($body);
97
        } else {
98
            $client->indices()->create($body);
99
        }
100
    }
101
102
    protected function createConfigForIndex(ElasticIndex $instance)
103
    {
104
        /** @var FieldResolver $resolver */
105
        $resolver = Injector::inst()->get(FieldResolver::class);
106
        $resolver->setIndex($instance);
107
        $result = [];
108
109
        foreach ($instance->getFulltextFields() as $field) {
110
            $field = $resolver->resolveField($field);
111
            $result = array_merge($result, $field);
112
        }
113
114
        return $result;
115
    }
116
117
    protected function configToJSON($config)
118
    {
119
        $base = [];
120
        $typeMap = Statics::getTypeMap();
121
        foreach ($config as $key => &$conf) {
122
            $shortClass = ClassInfo::shortName($conf['origin']);
123
            $dotField = str_replace('_', '.', $conf['fullfield']);
124
            $conf['name'] = sprintf('%s.%s', $shortClass, $dotField);
125
            $base[$conf['name']] = [
126
                'type' => $typeMap[$conf['type'] ?? '*']
127
            ];
128
        }
129
130
        $mappings = ['properties' => $base];
131
132
        return ['body' => ['mappings' => $mappings]];
133
    }
134
135
    protected function getMethod(ElasticIndex $index, ElasticCoreService $service)
136
    {
137
        $check = $service->getClient()
138
            ->indices()
139
            ->exists(['index' => $index->getIndexName()])
140
            ->asBool();
0 ignored issues
show
Bug introduced by
The method asBool() does not exist on Http\Promise\Promise. ( Ignorable by Annotation )

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

140
            ->/** @scrutinizer ignore-call */ asBool();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
141
142
        if ($check) {
143
            return 'update';
144
        }
145
146
        return 'create';
147
    }
148
}
149
150
$params = [
151
    'index' => 'my_index',
152
    'body'  => [
153
        'mappings' => [
154
            '_source'    => [
155
                'enabled' => true
156
            ],
157
            'properties' => [
158
                'first_name' => [
159
                    'type' => 'keyword'
160
                ],
161
                'age'        => [
162
                    'type' => 'integer'
163
                ]
164
            ]
165
        ]
166
    ]
167
];
168