Total Complexity | 45 |
Total Lines | 243 |
Duplicated Lines | 0 % |
Changes | 13 | ||
Bugs | 2 | Features | 0 |
Complex classes like ManticoreSearch often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use ManticoreSearch, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
18 | class ManticoreSearch |
||
19 | { |
||
20 | /** |
||
21 | * @var \Illuminate\Config\Repository|mixed |
||
22 | */ |
||
23 | protected mixed $config; |
||
24 | |||
25 | protected array $connection; |
||
26 | |||
27 | public Client $manticoresearch; |
||
28 | |||
29 | public Search $search; |
||
30 | |||
31 | private ColorCLI $cli; |
||
32 | |||
33 | /** |
||
34 | * Establishes a connection to ManticoreSearch HTTP port. |
||
35 | */ |
||
36 | public function __construct() |
||
37 | { |
||
38 | $this->config = config('sphinxsearch'); |
||
39 | $this->connection = ['host' => $this->config['host'], 'port' => $this->config['port']]; |
||
40 | $this->manticoresearch = new Client($this->connection); |
||
41 | $this->search = new Search($this->manticoresearch); |
||
42 | $this->cli = new ColorCLI(); |
||
43 | } |
||
44 | |||
45 | /** |
||
46 | * Insert release into ManticoreSearch releases_rt realtime index |
||
47 | */ |
||
48 | public function insertRelease(array $parameters): void |
||
49 | { |
||
50 | if ($parameters['id']) { |
||
51 | try { |
||
52 | $this->manticoresearch->index($this->config['indexes']['releases']) |
||
53 | ->replaceDocument( |
||
54 | [ |
||
55 | 'name' => $parameters['name'], |
||
56 | 'searchname' => $parameters['searchname'], |
||
57 | 'fromname' => $parameters['fromname'], |
||
58 | 'categories_id' => (string) $parameters['categories_id'], |
||
59 | 'filename' => empty($parameters['filename']) ? "''" : $parameters['filename'], |
||
60 | ], $parameters['id']); |
||
61 | } catch (ResponseException $re) { |
||
62 | Log::error($re->getMessage()); |
||
63 | } catch (\RuntimeException $ru) { |
||
64 | Log::error($ru->getMessage()); |
||
65 | } catch (\Throwable $exception) { |
||
66 | Log::error($exception->getMessage()); |
||
67 | } |
||
68 | |||
69 | } |
||
70 | } |
||
71 | |||
72 | /** |
||
73 | * Insert release into Manticore RT table. |
||
74 | */ |
||
75 | public function insertPredb(array $parameters): void |
||
76 | { |
||
77 | try { |
||
78 | if ($parameters['id']) { |
||
79 | $this->manticoresearch->index($this->config['indexes']['predb']) |
||
80 | ->replaceDocument(['title' => $parameters['title'], 'filename' => empty($parameters['filename']) ? "''" : $parameters['filename'], 'source' => $parameters['source']], $parameters['id']); |
||
81 | } |
||
82 | } catch (ResponseException $re) { |
||
83 | Log::error($re->getMessage()); |
||
84 | } catch (\RuntimeException $ru) { |
||
85 | Log::error($ru->getMessage()); |
||
86 | } catch (\Throwable $exception) { |
||
87 | Log::error($exception->getMessage()); |
||
88 | } |
||
89 | |||
90 | } |
||
91 | |||
92 | /** |
||
93 | * Delete release from Manticore RT tables. |
||
94 | * |
||
95 | * @param array $identifiers ['g' => Release GUID(mandatory), 'id' => ReleaseID(optional, pass false)] |
||
96 | */ |
||
97 | public function deleteRelease(array $identifiers): void |
||
98 | { |
||
99 | if ($identifiers['i'] === false) { |
||
100 | $identifiers['i'] = Release::query()->where('guid', $identifiers['g'])->first(['id']); |
||
101 | if ($identifiers['i'] !== null) { |
||
102 | $identifiers['i'] = $identifiers['i']['id']; |
||
103 | } |
||
104 | } |
||
105 | if ($identifiers['i'] !== false) { |
||
106 | $this->manticoresearch->index($this->config['indexes']['releases'])->deleteDocument($identifiers['i']); |
||
107 | } |
||
108 | } |
||
109 | |||
110 | /** |
||
111 | * Escapes characters that are treated as special operators by the query language parser. |
||
112 | * |
||
113 | * @param string $string unescaped string |
||
114 | * @return string Escaped string. |
||
115 | */ |
||
116 | public static function escapeString(string $string): string |
||
117 | { |
||
118 | if ($string === '*') { |
||
119 | return ''; |
||
120 | } |
||
121 | |||
122 | $from = ['\\', '(', ')', '@', '~', '"', '&', '/', '$', '=', "'", '--', '[', ']']; |
||
123 | $to = ['\\\\', '\(', '\)', '\@', '\~', '\"', '\&', '\/', '\$', '\=', "\', '\--", '\[', '\]']; |
||
124 | |||
125 | $string = str_replace($from, $to, $string); |
||
126 | // Remove these characaters if they are the last chars in $string |
||
127 | $string = Str::of($string)->rtrim('-'); |
||
128 | $string = Str::of($string)->rtrim('!'); |
||
129 | |||
130 | return $string; |
||
131 | } |
||
132 | |||
133 | public function updateRelease(int|string $releaseID): void |
||
134 | { |
||
135 | $new = Release::query() |
||
136 | ->where('releases.id', $releaseID) |
||
137 | ->leftJoin('release_files as rf', 'releases.id', '=', 'rf.releases_id') |
||
138 | ->select(['releases.id', 'releases.name', 'releases.searchname', 'releases.fromname', 'releases.categories_id', DB::raw('IFNULL(GROUP_CONCAT(rf.name SEPARATOR " "),"") filename')]) |
||
139 | ->groupBy('releases.id') |
||
140 | ->first(); |
||
141 | |||
142 | if ($new !== null) { |
||
143 | $release = $new->toArray(); |
||
144 | $this->insertRelease($release); |
||
145 | } |
||
146 | } |
||
147 | |||
148 | /** |
||
149 | * Update Manticore Predb index for given predb_id. |
||
150 | * |
||
151 | * |
||
152 | * @throws \Exception |
||
153 | */ |
||
154 | public function updatePreDb(array $parameters): void |
||
155 | { |
||
156 | if (! empty($parameters)) { |
||
157 | $this->insertPredb($parameters); |
||
158 | } |
||
159 | } |
||
160 | |||
161 | public function truncateRTIndex(array $indexes = []): bool |
||
162 | { |
||
163 | if (empty($indexes)) { |
||
164 | $this->cli->error('You need to provide index name to truncate'); |
||
165 | |||
166 | return false; |
||
167 | } |
||
168 | foreach ($indexes as $index) { |
||
169 | if (\in_array($index, $this->config['indexes'], true)) { |
||
170 | try { |
||
171 | $this->manticoresearch->index($index)->truncate(); |
||
172 | $this->cli->info('Truncating index '.$index.' finished.'); |
||
173 | } catch (ResponseException $e) { |
||
174 | if ($e->getMessage() === 'Invalid index') { |
||
175 | if ($index === 'releases_rt') { |
||
176 | $this->manticoresearch->index($index)->create([ |
||
177 | 'name' => ['type' => 'string'], |
||
178 | 'searchname' => ['type' => 'string'], |
||
179 | 'fromname' => ['type' => 'string'], |
||
180 | 'filename' => ['type' => 'string'], |
||
181 | 'categories_id' => ['type' => 'integer'], |
||
182 | ]); |
||
183 | } elseif ($index === 'predb_rt') { |
||
184 | $this->manticoresearch->index($index)->create([ |
||
185 | 'title' => ['type' => 'string'], |
||
186 | 'filename' => ['type' => 'string'], |
||
187 | 'source' => ['type' => 'string'], |
||
188 | ]); |
||
189 | } |
||
190 | } |
||
191 | } |
||
192 | } else { |
||
193 | $this->cli->error('Unsupported index: '.$index); |
||
194 | } |
||
195 | } |
||
196 | |||
197 | return true; |
||
198 | } |
||
199 | |||
200 | /** |
||
201 | * Optimize the RT index. |
||
202 | */ |
||
203 | public function optimizeRTIndex(): void |
||
208 | } |
||
209 | } |
||
210 | |||
211 | public function searchIndexes(string $rt_index, string $searchString = '', array $column = [], array $searchArray = []): array |
||
212 | { |
||
213 | $resultId = []; |
||
214 | $resultData = []; |
||
215 | try { |
||
216 | $query = $this->search->setIndex($rt_index)->option('ranker', 'sph04')->option('sort_method', 'pq')->maxMatches(10000)->limit(10000)->sort('id', 'desc')->stripBadUtf8(true)->trackScores(true); |
||
264 |