Passed
Push — master ( 53203f...160c08 )
by Gordon
02:23
created

IndexCreator::createIndex()   F

Complexity

Conditions 18
Paths 742

Size

Total Lines 146
Code Lines 79

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 18
eloc 79
c 4
b 0
f 0
nc 742
nop 1
dl 0
loc 146
rs 1.0583

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php declare(strict_types = 1);
2
3
/**
4
 * Created by PhpStorm.
5
 * User: gordon
6
 * Date: 24/3/2561
7
 * Time: 21:14 น.
8
 */
9
10
namespace Suilven\ManticoreSearch\Service;
11
12
use Suilven\FreeTextSearch\Exception\UnsupportedException;
0 ignored issues
show
Bug introduced by
The type Suilven\FreeTextSearch\E...on\UnsupportedException 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...
13
use Suilven\FreeTextSearch\Indexes;
14
use Suilven\FreeTextSearch\Types\FieldTypes;
15
use Suilven\FreeTextSearch\Types\LanguageTypes;
0 ignored issues
show
Bug introduced by
The type Suilven\FreeTextSearch\Types\LanguageTypes 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...
16
use Suilven\FreeTextSearch\Types\TokenizerTypes;
0 ignored issues
show
Bug introduced by
The type Suilven\FreeTextSearch\Types\TokenizerTypes 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...
17
18
// @phpcs:disable Generic.Files.LineLength.TooLong
19
// @phpcs:disable SlevomatCodingStandard.Files.LineLength.LineTooLong
20
class IndexCreator extends \Suilven\FreeTextSearch\Base\IndexCreator implements \Suilven\FreeTextSearch\Interfaces\IndexCreator
21
{
22
    /**
23
     * Create an index
24
     *
25
     * @todo Refactor into Indexer base
26
     * @param string $indexName the name of the index
27
     */
28
    public function createIndex(string $indexName): void
29
    {
30
        $fields = $this->getFields($indexName);
31
        $storedFields = $this->getStoredFields($indexName);
32
        $specs = $this->getFieldSpecs($indexName);
33
34
        \error_log('SPECS');
35
        \print_r($specs);
36
37
        $columns = [];
38
        foreach ($fields as $field) {
39
            /*
40
            if ($field === 'Link') {
41
                error_log('Skipping link field');
42
               continue;
43
            }
44
            */
45
46
            // this will be the most common
47
            $indexType = 'text';
48
            $options = [];
49
50
            if (isset($specs[$field])) {
51
                $fieldType = $specs[$field];
52
53
                // @todo configure index to strip HTML
54
                switch ($fieldType) {
55
                    case FieldTypes::FOREIGN_KEY:
56
                        // @todo this perhaps needs to be a token
57
                        // See https://docs.manticoresearch.com/3.4.0/html/indexing/data_types.html
58
59
                        // @todo also how to mark strings for tokenizing?
60
                        $indexType = 'bigint';
61
62
                        break;
63
                    case FieldTypes::INTEGER:
64
                        $indexType = 'integer';
65
66
                        break;
67
                    case FieldTypes::FLOAT:
68
                        $indexType = 'float';
69
70
                        break;
71
                    case FieldTypes::TIME:
72
                        $indexType = 'timestamp';
73
74
                        break;
75
                    case FieldTypes::BOOLEAN:
76
                        // @todo is there a better type?
77
                        $indexType = 'integer';
78
79
                        break;
80
                }
81
82
                if ($indexType === 'text') {
83
                    $options = ['indexed', 'stored'];
84
                }
85
            }
86
87
88
            // override for Link, do not index it.  The storing of the Link URL is to save on database hierarchy
89
            // traversal when rendering search results
90
            //if ($field === 'Link' || \in_array($field, $storedFields, true)) {
91
            if ($field === 'Link') {
92
                $indexType = 'text';
93
                $options = ['stored'];
94
            }
95
96
            if (\in_array($field, $storedFields, true)) {
97
                $options = ['stored'];
98
            }
99
            $columns[$field] = ['type' => $indexType, 'options' => $options];
100
        }
101
102
103
        // @todo Add has one
104
105
        $indexes = new Indexes();
106
        $index = $indexes->getIndex($indexName);
107
        $mvaFields = $index->getHasManyFields();
108
109
        \error_log(\print_r($mvaFields, true));
110
111
        foreach (\array_keys($mvaFields) as $mvaColumnName) {
112
            $columns[$mvaColumnName] = ['type' => 'multi'];
113
        }
114
115
        $client = new Client();
116
        $manticoreClient = $client->getConnection();
117
118
        $settings = [
119
            'rt_mem_limit' => '256M',
120
            'dict' => 'keywords',
121
            'min_infix_len' => 2,
122
            'html_strip' => 1,
123
            'bigram_index' => 'all',
124
        ];
125
126
        $manticoreTokenizer = null;
127
128
        // @todo this may need refactored
129
        $manticoreLanguage = $index->getLanguage();
0 ignored issues
show
Bug introduced by
The method getLanguage() does not exist on Suilven\FreeTextSearch\Index. ( Ignorable by Annotation )

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

129
        /** @scrutinizer ignore-call */ 
130
        $manticoreLanguage = $index->getLanguage();

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...
130
131
        $tokenizer = $index->getTokenizer();
0 ignored issues
show
Bug introduced by
The method getTokenizer() does not exist on Suilven\FreeTextSearch\Index. Did you maybe mean getTokens()? ( Ignorable by Annotation )

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

131
        /** @scrutinizer ignore-call */ 
132
        $tokenizer = $index->getTokenizer();

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...
132
        if ($tokenizer !== TokenizerTypes::NONE) {
133
            switch ($tokenizer) {
134
                case TokenizerTypes::PORTER:
135
                    $manticoreTokenizer = 'porter';
136
137
                    break;
138
                case TokenizerTypes::SNOWBALL:
139
                    $manticoreTokenizer = 'snowball';
140
141
                    break;
142
                case TokenizerTypes::METAPHONE:
143
                    $manticoreTokenizer = 'metaphone';
144
145
                    break;
146
                case TokenizerTypes::SOUNDEX:
147
                    $manticoreTokenizer = 'soundex';
148
149
                    break;
150
                case TokenizerTypes::LEMMATIZER:
151
                    $manticoreTokenizer = 'lemmatizer';
152
                    $settings['lemmatizer_base'] = '/usr/local/share';
153
154
                    break;
155
            }
156
157
            $settings['morphology'] = $this->getMorphology($manticoreTokenizer, $manticoreLanguage);
158
        }
159
160
161
        // drop index, and updating an existing one does not effect change
162
        $manticoreClient->indices()->drop(['index' => $indexName, 'body'=>['silent'=>true]]);
163
164
165
        $manticoreIndex = new \Manticoresearch\Index($manticoreClient, $indexName);
166
167
        \error_log('----- payload -----');
168
        \error_log(\print_r($columns, true));
169
170
        $manticoreIndex->create(
171
            $columns,
172
            $settings,
173
            true
174
        );
175
    }
176
177
178
    /**
179
     * @TODO Increase range of languages
180
     * @return string the name of the tokenizer to use at the Manticore config level
181
     * @throws \Suilven\FreeTextSearch\Exception\UnsupportedException if the combination of tokenizer and language cannot be used
182
     */
183
    private function getMorphology(?string $tokenizer, string $language): string
184
    {
185
        // @TODO add other languages, this is to get things up and rolling
186
        if ($language !== LanguageTypes::ENGLISH) {
187
            throw new UnsupportedException('Only English is supported for now #WorkInProgress');
188
        }
189
190
        $result = TokenizerTypes::NONE;
191
192
        switch ($tokenizer) {
193
            case TokenizerTypes::PORTER:
194
                $result = 'stem_en';
195
196
                break;
197
            case TokenizerTypes::LEMMATIZER:
198
                // @todo make the _all configurable
199
                $result = 'lemmatize_en_all';
200
201
                break;
202
            case TokenizerTypes::SOUNDEX:
203
                $result = 'soundex';
204
205
                break;
206
            case TokenizerTypes::METAPHONE:
207
                $result = 'metaphone';
208
209
                break;
210
        }
211
212
        return $result;
213
    }
214
}
215