Completed
Push — master ( 40e8b4...347a51 )
by Maxence
12:33
created

Live::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.7
c 0
b 0
f 0
cc 1
nc 1
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * FullTextSearch - Full text search framework for Nextcloud
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Maxence Lange <[email protected]>
9
 * @copyright 2018
10
 * @license GNU AGPL version 3 or any later version
11
 *
12
 * This program is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License as
14
 * published by the Free Software Foundation, either version 3 of the
15
 * License, or (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU Affero General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License
23
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
 *
25
 */
26
27
namespace OCA\FullTextSearch\Command;
28
29
use Exception;
30
use OCA\FullTextSearch\Exceptions\TickDoesNotExistException;
31
use OCA\FullTextSearch\Model\ExtendedBase;
32
use OCA\FullTextSearch\Model\Index as ModelIndex;
33
use OCA\FullTextSearch\Model\Runner;
34
use OCA\FullTextSearch\Service\CliService;
35
use OCA\FullTextSearch\Service\ConfigService;
36
use OCA\FullTextSearch\Service\IndexService;
37
use OCA\FullTextSearch\Service\MiscService;
38
use OCA\FullTextSearch\Service\PlatformService;
39
use OCA\FullTextSearch\Service\ProviderService;
40
use OCA\FullTextSearch\Service\RunningService;
41
use OCP\IUserManager;
42
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
43
use Symfony\Component\Console\Input\InputInterface;
44
use Symfony\Component\Console\Input\InputOption;
45
use Symfony\Component\Console\Output\OutputInterface;
46
use Symfony\Component\Console\Terminal;
47
use Throwable;
48
49
50
class Live extends ExtendedBase {
51
52
	const INDEX_OPTION_NO_READLINE = '_no-readline';
53
54
	const CYCLE_DELAY = 300000;
55
56
	const PANEL_RUN = 'run';
57
	const PANEL_RUN_LINE_MEMORY = 'Memory: %_memory%';
58
59
	const PANEL_INDEX = 'indexing';
60
	const PANEL_INDEX_LINE_HEADER = '┌─ Indexing %_paused% ────';
61
	const PANEL_INDEX_LINE_ACCOUNT = '│ Provider: <info>%providerName:-20s%</info> Account: <info>%userId%</info>';
62
	const PANEL_INDEX_LINE_ACTION = '│ Action: <info>%action%</info>';
63
	const PANEL_INDEX_LINE_DOCUMENT = '│ Document: <info>%documentId%</info>';
64
	const PANEL_INDEX_LINE_INFO = '│ Info: <info>%info%</info>';
65
	const PANEL_INDEX_LINE_TITLE = '│ Title: <info>%title%</info>';
66
	const PANEL_INDEX_LINE_CONTENT = '│ Content size: <info>%content%</info>';
67
	const PANEL_INDEX_LINE_FOOTER = '└──';
68
69
	const PANEL_RESULT = 'result';
70
	const PANEL_RESULT_LINE_HEADER = '┌─ Results ────';
71
	const PANEL_RESULT_LINE_RESULT = '│ Result: <info>%resultCurrent:6s%</info>/<info>%resultTotal%</info>';
72
	const PANEL_RESULT_LINE_INDEX = '│ Index: <info>%resultIndex%</info>';
73
	const PANEL_RESULT_LINE_STATUS = '│ Status: %resultStatusColored%';
74
	const PANEL_RESULT_LINE_MESSAGE1 = '│ Message: <info>%resultMessageA%</info>';
75
	const PANEL_RESULT_LINE_MESSAGE2 = '│ <info>%resultMessageB%</info>';
76
	const PANEL_RESULT_LINE_MESSAGE3 = '│ <info>%resultMessageC%</info>';
77
	const PANEL_RESULT_LINE_FOOTER = '└──';
78
79
	const PANEL_ERRORS = 'errors';
80
	const PANEL_ERRORS_LINE_HEADER = '┌─ Errors ────';
81
	const PANEL_ERRORS_LINE_ERRORS = '│ Error: <comment>%errorCurrent:6s%</comment>/<comment>%errorTotal%</comment>';
82
	const PANEL_ERRORS_LINE_ERROR_INDEX = '│ Index: <comment>%errorIndex%</comment>';
83
	const PANEL_ERRORS_LINE_ERROR_EXCEPTION = '│ Exception: <comment>%errorException%</comment>';
84
	const PANEL_ERRORS_LINE_ERROR_MESSAGE1 = '│ Message: <comment>%errorMessageA%</comment>';
85
	const PANEL_ERRORS_LINE_ERROR_MESSAGE2 = '│ <comment>%errorMessageB%</comment>';
86
	const PANEL_ERRORS_LINE_ERROR_MESSAGE3 = '│ <comment>%errorMessageC%</comment>';
87
	const PANEL_ERRORS_LINE_FOOTER = '└──';
88
89
	const PANEL_COMMANDS_ROOT = 'root';
90
	const PANEL_COMMANDS_ROOT_LINE = '## <char>q</char>:quit ## <char>p</char>:pause ';
91
	const PANEL_COMMANDS_PAUSED = 'paused';
92
	const PANEL_COMMANDS_PAUSED_LINE = '## <char>q</char>:quit ## <char>u</char>:unpause ## <char>n</char>:next step';
93
	const PANEL_COMMANDS_DONE = 'done';
94
	const PANEL_COMMANDS_DONE_LINE = '## <char>q</char>:quit';
95
	const PANEL_COMMANDS_NAVIGATION = 'navigation';
96
	const PANEL_COMMANDS_ERRORS_LINE = '## <char>f</char>:first error ## <char>h</char>/<char>j</char>:prec/next error ## <char>d</char>:delete error ## <char>l</char>:last error';
97
	const PANEL_COMMANDS_RESULTS_LINE = '## <char>x</char>:first result ## <char>c</char>/<char>v</char>:prec/next result ## <char>b</char>:last result';
98
99
100
	/** @var IUserManager */
101
	private $userManager;
102
103
	/** @var ConfigService */
104
	private $configService;
105
106
	/** @var CliService */
107
	private $cliService;
108
109
	/** @var RunningService */
110
	private $runningService;
111
112
	/** @var IndexService */
113
	private $indexService;
114
115
	/** @var PlatformService */
116
	private $platformService;
117
118
	/** @var ProviderService */
119
	private $providerService;
120
121
	/** @var MiscService */
122
	private $miscService;
123
124
125
	/** @var Runner */
126
	private $runner;
127
128
	/** @var Terminal */
129
	private $terminal;
130
131
	/** @var array */
132
	private $errors = [];
133
134
	/** @var bool */
135
	private $navigateLastError = true;
136
137
	/** @var array */
138
	private $results = [];
139
140
	/** @var bool */
141
	private $navigateLastResult = true;
142
143
	/**
144
	 * Live constructor.
145
	 *
146
	 * @param IUserManager $userManager
147
	 * @param RunningService $runningService
148
	 * @param ConfigService $configService
149
	 * @param CliService $cliService
150
	 * @param IndexService $indexService
151
	 * @param PlatformService $platformService
152
	 * @param ProviderService $providerService
153
	 * @param MiscService $miscService
154
	 */
155
	public function __construct(
156
		IUserManager $userManager, RunningService $runningService, ConfigService $configService,
157
		CliService $cliService, IndexService $indexService, PlatformService $platformService,
158
		ProviderService $providerService, MiscService $miscService
159
	) {
160
		parent::__construct();
161
		$this->userManager = $userManager;
162
163
		$this->runner = new Runner($runningService, 'commandLive');
164
		$this->configService = $configService;
165
		$this->cliService = $cliService;
166
		$this->runningService = $runningService;
167
		$this->indexService = $indexService;
168
		$this->platformService = $platformService;
169
		$this->providerService = $providerService;
170
		$this->miscService = $miscService;
171
	}
172
173
174
	/**
175
	 *
176
	 */
177
	protected function configure() {
178
		parent::configure();
179
		$this->setName('fulltextsearch:live')
180
			 ->setDescription('Index files')
181
			 ->addOption(
182
				 'no-readline', 'r', InputOption::VALUE_NONE,
183
				 'disable readline - non interactive mode'
184
			 );
185
	}
186
187
188
	/**
189
	 * @param InputInterface $input
190
	 * @param OutputInterface $output
191
	 *
192
	 * @return int|null|void
193
	 * @throws Exception
194
	 */
195
	protected function execute(InputInterface $input, OutputInterface $output) {
196
197
		if ($this->configService->getCloudVersion() < 14) {
198
			throw new Exception('This feature is only available on Nextcloud 14 or newer');
199
		}
200
201
		if (!$input->getOption('no-readline')) {
202
			try {
203
				/** do not get stuck while waiting interactive input */
204
				readline_callback_handler_install(
205
					'', function() {
206
				}
207
				);
208
			} catch (Throwable $t) {
0 ignored issues
show
Bug introduced by
The class Throwable does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
209
				throw new Exception('Please install php-readline, or use --no-readline');
210
			}
211
		}
212
		stream_set_blocking(STDIN, false);
213
214
		$this->terminal = new Terminal();
215
216
		$outputStyle = new OutputFormatterStyle('white', 'black', ['bold']);
217
		$output->getFormatter()
218
			   ->setStyle('char', $outputStyle);
219
220
		$this->runner = new Runner($this->runningService, 'commandIndex', ['nextStep' => 'n']);
221
		$this->runner->onKeyPress([$this, 'onKeyPressed']);
222
		$this->runner->onNewIndexError([$this, 'onNewIndexError']);
223
		$this->runner->onNewIndexResult([$this, 'onNewIndexResult']);
224
225
226
		$this->indexService->setRunner($this->runner);
227
		$this->cliService->setRunner($this->runner);
228
229
		$this->generatePanels(!$input->getOption('no-readline'));
230
231
232
		try {
233
			$this->runner->sourceIsCommandLine($this, $output);
234
			$this->runner->start();
235
236
			$this->cliService->runDisplay($output);
237
			$this->generateIndexErrors();
238
			$this->displayError();
239
			$this->displayResult();
240
241
			$this->liveCycle();
242
243
		} catch (Exception $e) {
244
			$this->runner->exception($e->getMessage(), true);
0 ignored issues
show
Deprecated Code introduced by
The method OCA\FullTextSearch\Model\Runner::exception() has been deprecated with message: - verifier l'interet !?

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
245
			throw $e;
246
		}
247
248
		$this->runner->stop();
249
	}
250
251
252
	/**
253
	 * @throws Exception
254
	 * @throws TickDoesNotExistException
255
	 */
256
	private function liveCycle() {
257
258
		$wrapper = $this->platformService->getPlatform();
259
		$platform = $wrapper->getPlatform();
260
		$platform->setRunner($this->runner);
261
262
		while (true) {
263
264
			$indexes = $this->indexService->getQueuedIndexes();
265
266 View Code Duplication
			foreach ($indexes as $index) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
267
				$this->runner->updateAction('indexing');
268
269
				try {
270
					$providerWrapper = $this->providerService->getProvider($index->getProviderId());
271
					$provider = $providerWrapper->getProvider();
272
273
					$provider->setRunner($this->runner);
274
					$this->indexService->updateDocument($platform, $provider, $index);
275
				} catch (Exception $e) {
276
					$this->runner->exception($e->getMessage(), false);
0 ignored issues
show
Deprecated Code introduced by
The method OCA\FullTextSearch\Model\Runner::exception() has been deprecated with message: - verifier l'interet !?

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
277
					// TODO - upgrade error number - after too many errors, delete index
278
					// TODO - do not count error if elasticsearch is down.
279
				}
280
			}
281
282
			$this->runner->updateAction('waiting', true);
283
284
			usleep(self::CYCLE_DELAY);
285
		}
286
287
		$this->runner->stop();
288
289
	}
290
291
292
	/**
293
	 * @param $key
294
	 */
295 View Code Duplication
	public function onKeyPressed($key) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
296
		$key = strtolower($key);
297
		if ($key === 'q') {
298
			try {
299
				$this->runner->stop();
300
			} catch (TickDoesNotExistException $e) {
301
				/** we do nohtin' */
302
			}
303
			exit();
304
		}
305
306
		$current = $this->cliService->currentPanel('commands');
307
		if ($current === self::PANEL_COMMANDS_ROOT && $key === 'p') {
308
			$this->cliService->switchPanel('commands', self::PANEL_COMMANDS_PAUSED);
309
			$this->runner->pause(true);
310
		}
311
		if ($current === self::PANEL_COMMANDS_PAUSED && $key === 'u') {
312
			$this->cliService->switchPanel('commands', self::PANEL_COMMANDS_ROOT);
313
			$this->runner->pause(false);
314
		}
315
316
		if ($key === 'x') {
317
			$this->displayResult(-99);
318
		}
319
		if ($key === 'c') {
320
			$this->displayResult(-1);
321
		}
322
		if ($key === 'v') {
323
			$this->displayResult(1);
324
		}
325
		if ($key === 'b') {
326
			$this->displayResult(99);
327
		}
328
329
		if ($key === 'f') {
330
			$this->displayError(-99);
331
		}
332
		if ($key === 'h') {
333
			$this->displayError(-1);
334
		}
335
		if ($key === 'j') {
336
			$this->displayError(1);
337
		}
338
		if ($key === 'l') {
339
			$this->displayError(99);
340
		}
341
		if ($key === 'd') {
342
			$this->deleteError();
343
		}
344
	}
345
346
347
	/**
348
	 * @param array $error
349
	 */
350
	public function onNewIndexError($error) {
351
		$this->errors[] = $error;
352
		$this->displayError();
353
	}
354
355
	/**
356
	 * @param array $result
357
	 */
358
	public function onNewIndexResult($result) {
359
		$this->results[] = $result;
360
		$this->displayResult();
361
	}
362
363
364
	/**
365
	 * @param bool $commands
366
	 */
367
	private function generatePanels(bool $commands) {
368
369
		$this->cliService->createPanel(
370
			self::PANEL_RUN,
371
			[
372
				self::PANEL_RUN_LINE_MEMORY
373
			]
374
		);
375
376
		$this->cliService->createPanel(
377
			self::PANEL_INDEX, [
378
								 self::PANEL_INDEX_LINE_HEADER,
379
								 self::PANEL_INDEX_LINE_ACTION,
380
								 self::PANEL_INDEX_LINE_ACCOUNT,
381
								 self::PANEL_INDEX_LINE_DOCUMENT,
382
								 self::PANEL_INDEX_LINE_INFO,
383
								 self::PANEL_INDEX_LINE_TITLE,
384
								 self::PANEL_INDEX_LINE_CONTENT,
385
								 self::PANEL_INDEX_LINE_FOOTER,
386
							 ]
387
		);
388
389
		$this->cliService->createPanel(
390
			self::PANEL_RESULT, [
391
								  self::PANEL_RESULT_LINE_HEADER,
392
								  self::PANEL_RESULT_LINE_RESULT,
393
								  self::PANEL_RESULT_LINE_INDEX,
394
								  self::PANEL_RESULT_LINE_STATUS,
395
								  self::PANEL_RESULT_LINE_MESSAGE1,
396
								  self::PANEL_RESULT_LINE_MESSAGE2,
397
								  self::PANEL_RESULT_LINE_MESSAGE3,
398
								  self::PANEL_RESULT_LINE_FOOTER,
399
							  ]
400
		);
401
402
		$this->cliService->createPanel(
403
			self::PANEL_ERRORS, [
404
								  self::PANEL_ERRORS_LINE_HEADER,
405
								  self::PANEL_ERRORS_LINE_ERRORS,
406
								  self::PANEL_ERRORS_LINE_ERROR_INDEX,
407
								  self::PANEL_ERRORS_LINE_ERROR_EXCEPTION,
408
								  self::PANEL_ERRORS_LINE_ERROR_MESSAGE1,
409
								  self::PANEL_ERRORS_LINE_ERROR_MESSAGE2,
410
								  self::PANEL_ERRORS_LINE_ERROR_MESSAGE3,
411
								  self::PANEL_ERRORS_LINE_FOOTER,
412
							  ]
413
		);
414
415
		$this->cliService->createPanel(
416
			self::PANEL_COMMANDS_ROOT, [
417
										 self::PANEL_COMMANDS_ROOT_LINE
418
									 ]
419
		);
420
421
		$this->cliService->createPanel(
422
			self::PANEL_COMMANDS_PAUSED, [
423
										   self::PANEL_COMMANDS_PAUSED_LINE
424
									   ]
425
		);
426
427
		$this->cliService->createPanel(
428
			self::PANEL_COMMANDS_NAVIGATION, [
429
											   self::PANEL_COMMANDS_RESULTS_LINE,
430
											   self::PANEL_COMMANDS_ERRORS_LINE
431
										   ]
432
		);
433
434
		$this->cliService->initDisplay();
435
		$this->cliService->displayPanel('run', self::PANEL_RUN);
436
		$this->cliService->displayPanel('indexPanel', self::PANEL_INDEX);
437
		$this->cliService->displayPanel('resultsPanel', self::PANEL_RESULT);
438
		$this->cliService->displayPanel('errorsPanel', self::PANEL_ERRORS);
439
440 View Code Duplication
		if ($commands) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
441
			$this->cliService->displayPanel('navigation', self::PANEL_COMMANDS_NAVIGATION);
442
			if ($this->runner->isPaused()) {
443
				$this->cliService->displayPanel('commands', self::PANEL_COMMANDS_PAUSED);
444
			} else {
445
				$this->cliService->displayPanel('commands', self::PANEL_COMMANDS_ROOT);
446
			}
447
		}
448
449
		$this->runner->setInfoArray(
450
			[
451
				'userId'              => '',
452
				'providerName'        => '',
453
				'_memory'             => '',
454
				'documentId'          => '',
455
				'action'              => '',
456
				'info'                => '',
457
				'title'               => '',
458
				'_paused'             => '',
459
				'resultIndex'         => '',
460
				'resultCurrent'       => '',
461
				'resultTotal'         => '',
462
				'resultMessageA'      => '',
463
				'resultMessageB'      => '',
464
				'resultMessageC'      => '',
465
				'resultStatus'        => '',
466
				'resultStatusColored' => '',
467
				'content'             => '',
468
				'statusColored'       => '',
469
				'progressStatus'      => '',
470
				'errorCurrent'        => '0',
471
				'errorTotal'          => '0',
472
				'errorMessageA'       => '',
473
				'errorMessageB'       => '',
474
				'errorMessageC'       => '',
475
				'errorException'      => '',
476
				'errorIndex'          => ''
477
			]
478
		);
479
	}
480
481
482
	/**
483
	 *
484
	 */
485 View Code Duplication
	private function generateIndexErrors() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
486
		$indexes = $this->indexService->getErrorIndexes();
487
488
		foreach ($indexes as $index) {
489
			foreach ($index->getErrors() as $error) {
490
				$this->errors[] = [
491
					'index'     => $index,
492
					'message'   => $error['message'],
493
					'exception' => $error['exception'],
494
					'severity'  => $error['severity']
495
				];
496
			}
497
498
		}
499
500
	}
501
502
503
	/**
504
	 * @param int $pos
505
	 */
506 View Code Duplication
	private function displayResult($pos = 0) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
507
		$total = sizeof($this->results);
508
509
		if ($total === 0) {
510
			$this->runner->setInfoArray(
511
				[
512
					'resultCurrent' => 0,
513
					'resultTotal'   => 0,
514
				]
515
			);
516
517
			return;
518
		}
519
520
		$current = key($this->results) + 1;
521
		$result = $this->getNavigationResult($pos, ($current === 1), ($current === $total));
522
		$current = key($this->results) + 1;
523
524
		if ($result === false) {
525
			return;
526
		}
527
528
		/** @var ModelIndex $index */
529
		$index = $result['index'];
530
		$resultIndex = '';
531
		if ($index !== null) {
532
			$resultIndex = $index->getProviderId() . ':' . $index->getDocumentId();
533
		}
534
535
536
		$width = $this->terminal->getWidth() - 13;
537
		$message = MiscService::get('message', $result, '');
538
		$msg1 = substr($message, 0, $width);
539
		$msg2 = substr($message, $width, $width + 10);
540
		$msg3 = substr($message, $width + $width + 10, $width + 10);
541
542
543
		$status = MiscService::get('status', $result, '');
544
		$type = MiscService::get('type', $result, '');
545
546
		$this->runner->setInfoArray(
547
			[
548
				'resultCurrent'  => $current,
549
				'resultTotal'    => $total,
550
				'resultMessageA' => trim($msg1),
551
				'resultMessageB' => trim($msg2),
552
				'resultMessageC' => trim($msg3),
553
				'resultStatus'   => $status,
554
				'resultIndex'    => $resultIndex
555
			]
556
		);
557
		$this->runner->setInfoColored('resultStatus', $type);
558
	}
559
560
	/**
561
	 * @param int $pos
562
	 */
563 View Code Duplication
	private function displayError($pos = 0) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
564
		$total = sizeof($this->errors);
565
566
		if ($total === 0) {
567
			$this->runner->setInfoArray(
568
				[
569
					'errorCurrent' => 0,
570
					'errorTotal'   => 0,
571
				]
572
			);
573
574
			return;
575
		}
576
577
		$current = key($this->errors) + 1;
578
		$error = $this->getNavigationError($pos, ($current === 1), ($current === $total));
579
		$current = key($this->errors) + 1;
580
581
		if ($error === false) {
582
			return;
583
		}
584
585
		/** @var ModelIndex $index */
586
		$index = $error['index'];
587
		$errorIndex = '';
588
		if ($index !== null) {
589
			$errorIndex = $index->getProviderId() . ':' . $index->getDocumentId();
590
		}
591
592
		$width = $this->terminal->getWidth() - 13;
593
		$message = MiscService::get('message', $error, '');
594
		$err1 = substr($message, 0, $width);
595
		$err2 = substr($message, $width, $width + 10);
596
		$err3 = substr($message, $width + $width + 10, $width + 10);
597
598
		$this->runner->setInfoArray(
599
			[
600
				'errorCurrent'   => $current,
601
				'errorTotal'     => $total,
602
				'errorMessageA'  => trim($err1),
603
				'errorMessageB'  => trim($err2),
604
				'errorMessageC'  => trim($err3),
605
				'errorException' => MiscService::get('exception', $error, ''),
606
				'errorIndex'     => $errorIndex
607
			]
608
		);
609
	}
610
611
612
	/**
613
	 * @param int $pos
614
	 * @param bool $isFirst
615
	 * @param bool $isLast
616
	 *
617
	 * @return bool|array
618
	 */
619 View Code Duplication
	private function getNavigationResult($pos, $isFirst, $isLast) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
620
621
		if ($pos === 0) {
622
			if ($this->navigateLastResult === true) {
623
				return end($this->results);
624
			} else {
625
				return current($this->results);
626
			}
627
		}
628
629
		$this->navigateLastResult = false;
630
		if ($pos === -99) {
631
			return reset($this->results);
632
		}
633
634
		if ($pos === -1 && !$isFirst) {
635
			return prev($this->results);
636
		}
637
638
		if ($pos === 1 && !$isLast) {
639
			return next($this->results);
640
		}
641
642
		if ($pos === 99) {
643
			$this->navigateLastResult = true;
644
645
			return end($this->results);
646
		}
647
648
		return false;
649
	}
650
651
652
	/**
653
	 * @param int $pos
654
	 * @param bool $isFirst
655
	 * @param bool $isLast
656
	 *
657
	 * @return bool|array
658
	 */
659 View Code Duplication
	private function getNavigationError($pos, $isFirst, $isLast) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
660
661
		if ($pos === 0) {
662
			if ($this->navigateLastError === true) {
663
				return end($this->errors);
664
			} else {
665
				return current($this->errors);
666
			}
667
		}
668
669
		$this->navigateLastError = false;
670
		if ($pos === -99) {
671
			return reset($this->errors);
672
		}
673
674
		if ($pos === -1 && !$isFirst) {
675
			return prev($this->errors);
676
		}
677
678
		if ($pos === 1 && !$isLast) {
679
			return next($this->errors);
680
		}
681
682
		if ($pos === 99) {
683
			$this->navigateLastError = true;
684
685
			return end($this->errors);
686
		}
687
688
		return false;
689
	}
690
691
692
	/**
693
	 *
694
	 */
695 View Code Duplication
	private function deleteError() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
696
		$current = current($this->errors);
697
		if ($current === false) {
698
			return;
699
		}
700
701
		$this->runner->setInfoArray(
702
			[
703
				'errorMessageA'  => '',
704
				'errorMessageB'  => '',
705
				'errorMessageC'  => '',
706
				'errorException' => '',
707
				'errorIndex'     => ''
708
			]
709
		);
710
711
		$pos = key($this->errors);
712
713
		/** @var ModelIndex $index */
714
		$index = $current['index'];
715
		$this->indexService->resetErrorFromIndex($index);
716
717
		$errors = [];
718
		foreach ($this->errors as $error) {
719
			/** @var ModelIndex $errorIndex */
720
			$errorIndex = $error['index'];
721
			if ($index->getProviderId() === $errorIndex->getProviderId()
722
				&& $index->getDocumentId() === $errorIndex->getDocumentId()) {
723
				continue;
724
			}
725
726
			$errors[] = $error;
727
		}
728
729
		$this->errors = $errors;
730
		while (key($this->errors) < $pos) {
731
			if (next($this->errors) === false) {
732
				end($this->errors);
733
				break;
734
			}
735
		}
736
737
		$this->displayError();
738
	}
739
}
740
741
742
743