Completed
Push — master ( d0ff46...fed349 )
by Maxence
02:18 queued 57s
created

Live   F

Complexity

Total Complexity 76

Size/Duplication

Total Lines 732
Duplicated Lines 40.57 %

Coupling/Cohesion

Components 1
Dependencies 12

Importance

Changes 0
Metric Value
wmc 76
lcom 1
cbo 12
dl 297
loc 732
rs 2.188
c 0
b 0
f 0

15 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 17 1
A configure() 0 13 1
C execute() 0 72 11
A liveCycle() 15 34 4
F onKeyPressed() 50 50 16
A onNewIndexError() 0 4 1
A onNewIndexResult() 0 4 1
B generatePanels() 8 113 3
A generateIndexErrors() 16 16 3
A displayResult() 54 54 4
A displayError() 47 47 4
B getNavigationResult() 31 31 9
B getNavigationError() 31 31 9
B deleteError() 44 44 7
A abort() 0 8 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Live 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 Live, and based on these observations, apply Extract Interface, too.

1
<?php
2
declare(strict_types=1);
3
4
5
/**
6
 * FullTextSearch - Full text search framework for Nextcloud
7
 *
8
 * This file is licensed under the Affero General Public License version 3 or
9
 * later. See the COPYING file.
10
 *
11
 * @author Maxence Lange <[email protected]>
12
 * @copyright 2018
13
 * @license GNU AGPL version 3 or any later version
14
 *
15
 * This program is free software: you can redistribute it and/or modify
16
 * it under the terms of the GNU Affero General Public License as
17
 * published by the Free Software Foundation, either version 3 of the
18
 * License, or (at your option) any later version.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 * GNU Affero General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU Affero General Public License
26
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
27
 *
28
 */
29
30
31
namespace OCA\FullTextSearch\Command;
32
33
34
use daita\MySmallPhpTools\Traits\TArrayTools;
35
use Exception;
36
use OC\Core\Command\InterruptedException;
37
use OCA\FullTextSearch\ACommandBase;
38
use OCA\FullTextSearch\Exceptions\TickDoesNotExistException;
39
use OCA\FullTextSearch\Model\Index as ModelIndex;
40
use OCA\FullTextSearch\Model\Runner;
41
use OCA\FullTextSearch\Service\CliService;
42
use OCA\FullTextSearch\Service\ConfigService;
43
use OCA\FullTextSearch\Service\IndexService;
44
use OCA\FullTextSearch\Service\MiscService;
45
use OCA\FullTextSearch\Service\PlatformService;
46
use OCA\FullTextSearch\Service\ProviderService;
47
use OCA\FullTextSearch\Service\RunningService;
48
use OCP\IUserManager;
49
use OutOfBoundsException;
50
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
51
use Symfony\Component\Console\Input\InputInterface;
52
use Symfony\Component\Console\Input\InputOption;
53
use Symfony\Component\Console\Output\OutputInterface;
54
use Symfony\Component\Console\Terminal;
55
use Throwable;
56
57
58
/**
59
 * Class Live
60
 *
61
 * @package OCA\FullTextSearch\Command
62
 */
63
class Live extends ACommandBase {
64
65
66
	use TArrayTools;
67
68
69
	const INDEX_OPTION_NO_READLINE = '_no-readline';
70
71
	const CYCLE_DELAY = 300000;
72
73
	const PANEL_RUN = 'run';
74
	const PANEL_RUN_LINE_MEMORY = 'Memory: %_memory%';
75
76
	const PANEL_INDEX = 'indexing';
77
	const PANEL_INDEX_LINE_HEADER = '┌─ Indexing %_paused% ────';
78
	const PANEL_INDEX_LINE_ACCOUNT = '│ Provider: <info>%providerName:-20s%</info> Account: <info>%userId%</info>';
79
	const PANEL_INDEX_LINE_ACTION = '│ Action: <info>%action%</info>';
80
	const PANEL_INDEX_LINE_DOCUMENT = '│ Document: <info>%documentId%</info>';
81
	const PANEL_INDEX_LINE_INFO = '│ Info: <info>%info%</info>';
82
	const PANEL_INDEX_LINE_TITLE = '│ Title: <info>%title%</info>';
83
	const PANEL_INDEX_LINE_CONTENT = '│ Content size: <info>%content%</info>';
84
	const PANEL_INDEX_LINE_FOOTER = '└──';
85
86
	const PANEL_RESULT = 'result';
87
	const PANEL_RESULT_LINE_HEADER = '┌─ Results ────';
88
	const PANEL_RESULT_LINE_RESULT = '│ Result: <info>%resultCurrent:6s%</info>/<info>%resultTotal%</info>';
89
	const PANEL_RESULT_LINE_INDEX = '│ Index: <info>%resultIndex%</info>';
90
	const PANEL_RESULT_LINE_STATUS = '│ Status: %resultStatusColored%';
91
	const PANEL_RESULT_LINE_MESSAGE1 = '│ Message: <info>%resultMessageA%</info>';
92
	const PANEL_RESULT_LINE_MESSAGE2 = '│ <info>%resultMessageB%</info>';
93
	const PANEL_RESULT_LINE_MESSAGE3 = '│ <info>%resultMessageC%</info>';
94
	const PANEL_RESULT_LINE_FOOTER = '└──';
95
96
	const PANEL_ERRORS = 'errors';
97
	const PANEL_ERRORS_LINE_HEADER = '┌─ Errors ────';
98
	const PANEL_ERRORS_LINE_ERRORS = '│ Error: <comment>%errorCurrent:6s%</comment>/<comment>%errorTotal%</comment>';
99
	const PANEL_ERRORS_LINE_ERROR_INDEX = '│ Index: <comment>%errorIndex%</comment>';
100
	const PANEL_ERRORS_LINE_ERROR_EXCEPTION = '│ Exception: <comment>%errorException%</comment>';
101
	const PANEL_ERRORS_LINE_ERROR_MESSAGE1 = '│ Message: <comment>%errorMessageA%</comment>';
102
	const PANEL_ERRORS_LINE_ERROR_MESSAGE2 = '│ <comment>%errorMessageB%</comment>';
103
	const PANEL_ERRORS_LINE_ERROR_MESSAGE3 = '│ <comment>%errorMessageC%</comment>';
104
	const PANEL_ERRORS_LINE_FOOTER = '└──';
105
106
	const PANEL_COMMANDS_ROOT = 'root';
107
	const PANEL_COMMANDS_ROOT_LINE = '## <char>q</char>:quit ## <char>p</char>:pause ';
108
	const PANEL_COMMANDS_PAUSED = 'paused';
109
	const PANEL_COMMANDS_PAUSED_LINE = '## <char>q</char>:quit ## <char>u</char>:unpause ## <char>n</char>:next step';
110
	const PANEL_COMMANDS_DONE = 'done';
111
	const PANEL_COMMANDS_DONE_LINE = '## <char>q</char>:quit';
112
	const PANEL_COMMANDS_NAVIGATION = 'navigation';
113
	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';
114
	const PANEL_COMMANDS_RESULTS_LINE = '## <char>x</char>:first result ## <char>c</char>/<char>v</char>:prec/next result ## <char>b</char>:last result';
115
116
117
	/** @var IUserManager */
118
	private $userManager;
119
120
	/** @var ConfigService */
121
	private $configService;
122
123
	/** @var CliService */
124
	private $cliService;
125
126
	/** @var RunningService */
127
	private $runningService;
128
129
	/** @var IndexService */
130
	private $indexService;
131
132
	/** @var PlatformService */
133
	private $platformService;
134
135
	/** @var ProviderService */
136
	private $providerService;
137
138
	/** @var MiscService */
139
	private $miscService;
140
141
142
	/** @var Runner */
143
	private $runner;
144
145
	/** @var Terminal */
146
	private $terminal;
147
148
	/** @var array */
149
	private $errors = [];
150
151
	/** @var bool */
152
	private $navigateLastError = true;
153
154
	/** @var array */
155
	private $results = [];
156
157
	/** @var bool */
158
	private $navigateLastResult = true;
159
160
	/**
161
	 * Live constructor.
162
	 *
163
	 * @param IUserManager $userManager
164
	 * @param RunningService $runningService
165
	 * @param ConfigService $configService
166
	 * @param CliService $cliService
167
	 * @param IndexService $indexService
168
	 * @param PlatformService $platformService
169
	 * @param ProviderService $providerService
170
	 * @param MiscService $miscService
171
	 */
172
	public function __construct(
173
		IUserManager $userManager, RunningService $runningService, ConfigService $configService,
174
		CliService $cliService, IndexService $indexService, PlatformService $platformService,
175
		ProviderService $providerService, MiscService $miscService
176
	) {
177
		parent::__construct();
178
		$this->userManager = $userManager;
179
180
		$this->runner = new Runner($runningService, 'commandLive');
181
		$this->configService = $configService;
182
		$this->cliService = $cliService;
183
		$this->runningService = $runningService;
184
		$this->indexService = $indexService;
185
		$this->platformService = $platformService;
186
		$this->providerService = $providerService;
187
		$this->miscService = $miscService;
188
	}
189
190
191
	/**
192
	 *
193
	 */
194
	protected function configure() {
195
		parent::configure();
196
		$this->setName('fulltextsearch:live')
197
			 ->setDescription('Index files')
198
			 ->addOption(
199
				 'no-readline', 'r', InputOption::VALUE_NONE,
200
				 'disable readline - non interactive mode'
201
			 )
202
			 ->addOption(
203
				 'service', 's', InputOption::VALUE_NONE,
204
				 'disable interface'
205
			 );
206
	}
207
208
209
	/**
210
	 * @param InputInterface $input
211
	 * @param OutputInterface $output
212
	 *
213
	 * @return int|null|void
214
	 * @throws Exception
215
	 */
216
	protected function execute(InputInterface $input, OutputInterface $output) {
217
218
		if ($this->configService->getCloudVersion() < 14) {
219
			throw new Exception('This feature is only available on Nextcloud 14 or newer');
220
		}
221
222
223
		if (!$input->getOption('service') && !$input->getOption('no-readline')) {
224
			try {
225
				/** do not get stuck while waiting interactive input */
226
				readline_callback_handler_install(
227
					'', function() {
228
				}
229
				);
230
			} 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...
231
				throw new Exception('Please install php-readline, or use --no-readline');
232
			}
233
		}
234
		stream_set_blocking(STDIN, false);
235
236
		$this->terminal = new Terminal();
237
238
		$outputStyle = new OutputFormatterStyle('white', 'black', ['bold']);
239
		$output->getFormatter()
240
			   ->setStyle('char', $outputStyle);
241
242
		$this->runner = new Runner($this->runningService, 'commandIndex', ['nextStep' => 'n']);
243
244
		if (!$input->getOption('service')) {
245
			$this->runner->onKeyPress([$this, 'onKeyPressed']);
246
			$this->runner->onNewIndexError([$this, 'onNewIndexError']);
247
			$this->runner->onNewIndexResult([$this, 'onNewIndexResult']);
248
			$this->runner->sourceIsCommandLine($this, $output);
249
250
			$this->generatePanels(!$input->getOption('no-readline'));
251
		}
252
253
		$this->indexService->setRunner($this->runner);
254
		$this->cliService->setRunner($this->runner);
255
256
		while (true) {
257
			try {
258
				$this->runner->start();
259
260
				if (!$input->getOption('service')) {
261
					$this->cliService->runDisplay($output);
262
					$this->generateIndexErrors();
263
					$this->displayError();
264
					$this->displayResult();
265
				}
266
267
				$this->liveCycle();
268
269
			} catch (Exception $e) {
270
				$this->miscService->log(
271
					'Exception while live index: ' . get_class($e) . ' - ' . $e->getMessage()
272
				);
273
274
				if (!$input->getOption('service')) {
275
					throw $e;
276
				}
277
			}
278
279
			if (!$input->getOption('service')) {
280
				break;
281
			}
282
283
			sleep(120);
284
		}
285
286
		$this->runner->stop();
287
	}
288
289
290
	/**
291
	 * @throws Exception
292
	 * @throws TickDoesNotExistException
293
	 */
294
	private function liveCycle() {
295
296
		$wrapper = $this->platformService->getPlatform();
297
		$platform = $wrapper->getPlatform();
298
		$platform->setRunner($this->runner);
299
300
		while (true) {
301
302
			$indexes = $this->indexService->getQueuedIndexes();
303
304 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...
305
				$this->runner->updateAction('indexing');
306
307
				try {
308
					$providerWrapper = $this->providerService->getProvider($index->getProviderId());
309
					$provider = $providerWrapper->getProvider();
310
311
					$provider->setRunner($this->runner);
312
					$this->indexService->updateDocument($platform, $provider, $index);
313
				} catch (Exception $e) {
314
					$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...
315
					// TODO - upgrade error number - after too many errors, delete index
316
					// TODO - do not count error if elasticsearch is down.
317
				}
318
			}
319
320
			$this->runner->updateAction('waiting', true);
321
322
			usleep(self::CYCLE_DELAY);
323
		}
324
325
		$this->runner->stop();
326
327
	}
328
329
330
	/**
331
	 * @param string $key
332
	 */
333 View Code Duplication
	public function onKeyPressed(string $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...
334
		$key = strtolower($key);
335
		if ($key === 'q') {
336
			try {
337
				$this->runner->stop();
338
			} catch (TickDoesNotExistException $e) {
339
				/** we do nohtin' */
340
			}
341
			exit();
342
		}
343
344
		$current = $this->cliService->currentPanel('commands');
345
		if ($current === self::PANEL_COMMANDS_ROOT && $key === 'p') {
346
			$this->cliService->switchPanel('commands', self::PANEL_COMMANDS_PAUSED);
347
			$this->runner->pause(true);
348
		}
349
		if ($current === self::PANEL_COMMANDS_PAUSED && $key === 'u') {
350
			$this->cliService->switchPanel('commands', self::PANEL_COMMANDS_ROOT);
351
			$this->runner->pause(false);
352
		}
353
354
		if ($key === 'x') {
355
			$this->displayResult(-99);
356
		}
357
		if ($key === 'c') {
358
			$this->displayResult(-1);
359
		}
360
		if ($key === 'v') {
361
			$this->displayResult(1);
362
		}
363
		if ($key === 'b') {
364
			$this->displayResult(99);
365
		}
366
367
		if ($key === 'f') {
368
			$this->displayError(-99);
369
		}
370
		if ($key === 'h') {
371
			$this->displayError(-1);
372
		}
373
		if ($key === 'j') {
374
			$this->displayError(1);
375
		}
376
		if ($key === 'l') {
377
			$this->displayError(99);
378
		}
379
		if ($key === 'd') {
380
			$this->deleteError();
381
		}
382
	}
383
384
385
	/**
386
	 * @param array $error
387
	 */
388
	public function onNewIndexError(array $error) {
389
		$this->errors[] = $error;
390
		$this->displayError();
391
	}
392
393
	/**
394
	 * @param array $result
395
	 */
396
	public function onNewIndexResult(array $result) {
397
		$this->results[] = $result;
398
		$this->displayResult();
399
	}
400
401
402
	/**
403
	 * @param bool $commands
404
	 */
405
	private function generatePanels(bool $commands) {
406
407
		$this->cliService->createPanel(
408
			self::PANEL_RUN,
409
			[
410
				self::PANEL_RUN_LINE_MEMORY
411
			]
412
		);
413
414
		$this->cliService->createPanel(
415
			self::PANEL_INDEX, [
416
								 self::PANEL_INDEX_LINE_HEADER,
417
								 self::PANEL_INDEX_LINE_ACTION,
418
								 self::PANEL_INDEX_LINE_ACCOUNT,
419
								 self::PANEL_INDEX_LINE_DOCUMENT,
420
								 self::PANEL_INDEX_LINE_INFO,
421
								 self::PANEL_INDEX_LINE_TITLE,
422
								 self::PANEL_INDEX_LINE_CONTENT,
423
								 self::PANEL_INDEX_LINE_FOOTER,
424
							 ]
425
		);
426
427
		$this->cliService->createPanel(
428
			self::PANEL_RESULT, [
429
								  self::PANEL_RESULT_LINE_HEADER,
430
								  self::PANEL_RESULT_LINE_RESULT,
431
								  self::PANEL_RESULT_LINE_INDEX,
432
								  self::PANEL_RESULT_LINE_STATUS,
433
								  self::PANEL_RESULT_LINE_MESSAGE1,
434
								  self::PANEL_RESULT_LINE_MESSAGE2,
435
								  self::PANEL_RESULT_LINE_MESSAGE3,
436
								  self::PANEL_RESULT_LINE_FOOTER,
437
							  ]
438
		);
439
440
		$this->cliService->createPanel(
441
			self::PANEL_ERRORS, [
442
								  self::PANEL_ERRORS_LINE_HEADER,
443
								  self::PANEL_ERRORS_LINE_ERRORS,
444
								  self::PANEL_ERRORS_LINE_ERROR_INDEX,
445
								  self::PANEL_ERRORS_LINE_ERROR_EXCEPTION,
446
								  self::PANEL_ERRORS_LINE_ERROR_MESSAGE1,
447
								  self::PANEL_ERRORS_LINE_ERROR_MESSAGE2,
448
								  self::PANEL_ERRORS_LINE_ERROR_MESSAGE3,
449
								  self::PANEL_ERRORS_LINE_FOOTER,
450
							  ]
451
		);
452
453
		$this->cliService->createPanel(
454
			self::PANEL_COMMANDS_ROOT, [
455
										 self::PANEL_COMMANDS_ROOT_LINE
456
									 ]
457
		);
458
459
		$this->cliService->createPanel(
460
			self::PANEL_COMMANDS_PAUSED, [
461
										   self::PANEL_COMMANDS_PAUSED_LINE
462
									   ]
463
		);
464
465
		$this->cliService->createPanel(
466
			self::PANEL_COMMANDS_NAVIGATION, [
467
											   self::PANEL_COMMANDS_RESULTS_LINE,
468
											   self::PANEL_COMMANDS_ERRORS_LINE
469
										   ]
470
		);
471
472
		$this->cliService->initDisplay();
473
		$this->cliService->displayPanel('run', self::PANEL_RUN);
474
		$this->cliService->displayPanel('indexPanel', self::PANEL_INDEX);
475
		$this->cliService->displayPanel('resultsPanel', self::PANEL_RESULT);
476
		$this->cliService->displayPanel('errorsPanel', self::PANEL_ERRORS);
477
478 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...
479
			$this->cliService->displayPanel('navigation', self::PANEL_COMMANDS_NAVIGATION);
480
			if ($this->runner->isPaused()) {
481
				$this->cliService->displayPanel('commands', self::PANEL_COMMANDS_PAUSED);
482
			} else {
483
				$this->cliService->displayPanel('commands', self::PANEL_COMMANDS_ROOT);
484
			}
485
		}
486
487
		$this->runner->setInfoArray(
488
			[
489
				'userId'              => '',
490
				'providerName'        => '',
491
				'_memory'             => '',
492
				'documentId'          => '',
493
				'action'              => '',
494
				'info'                => '',
495
				'title'               => '',
496
				'_paused'             => '',
497
				'resultIndex'         => '',
498
				'resultCurrent'       => '',
499
				'resultTotal'         => '',
500
				'resultMessageA'      => '',
501
				'resultMessageB'      => '',
502
				'resultMessageC'      => '',
503
				'resultStatus'        => '',
504
				'resultStatusColored' => '',
505
				'content'             => '',
506
				'statusColored'       => '',
507
				'progressStatus'      => '',
508
				'errorCurrent'        => '0',
509
				'errorTotal'          => '0',
510
				'errorMessageA'       => '',
511
				'errorMessageB'       => '',
512
				'errorMessageC'       => '',
513
				'errorException'      => '',
514
				'errorIndex'          => ''
515
			]
516
		);
517
	}
518
519
520
	/**
521
	 *
522
	 */
523 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...
524
		$indexes = $this->indexService->getErrorIndexes();
525
526
		foreach ($indexes as $index) {
527
			foreach ($index->getErrors() as $error) {
528
				$this->errors[] = [
529
					'index'     => $index,
530
					'message'   => $error['message'],
531
					'exception' => $error['exception'],
532
					'severity'  => $error['severity']
533
				];
534
			}
535
536
		}
537
538
	}
539
540
541
	/**
542
	 * @param int $pos
543
	 */
544 View Code Duplication
	private function displayResult(int $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...
545
		$total = sizeof($this->results);
546
547
		if ($total === 0) {
548
			$this->runner->setInfoArray(
549
				[
550
					'resultCurrent' => 0,
551
					'resultTotal'   => 0,
552
				]
553
			);
554
555
			return;
556
		}
557
558
		try {
559
			$current = key($this->results) + 1;
560
			$result = $this->getNavigationResult($pos, ($current === 1), ($current === $total));
561
			$current = key($this->results) + 1;
562
		} catch (OutOfBoundsException $e) {
563
			return;
564
		}
565
566
		/** @var ModelIndex $index */
567
		$index = $result['index'];
568
		$resultIndex = '';
569
		if ($index !== null) {
570
			$resultIndex = $index->getProviderId() . ':' . $index->getDocumentId();
571
		}
572
573
574
		$width = $this->terminal->getWidth() - 13;
575
		$message = $this->get('message', $result, '');
576
		$msg1 = (string)substr($message, 0, $width);
577
		$msg2 = (string)substr($message, $width, $width + 10);
578
		$msg3 = (string)substr($message, $width + $width + 10, $width + 10);
579
580
581
		$status = $this->get('status', $result, '');
582
		$type = $this->getInt('type', $result, 0);
583
584
585
		$this->runner->setInfoArray(
586
			[
587
				'resultCurrent'  => $current,
588
				'resultTotal'    => $total,
589
				'resultMessageA' => trim($msg1),
590
				'resultMessageB' => trim($msg2),
591
				'resultMessageC' => trim($msg3),
592
				'resultStatus'   => $status,
593
				'resultIndex'    => $resultIndex
594
			]
595
		);
596
		$this->runner->setInfoColored('resultStatus', $type);
597
	}
598
599
	/**
600
	 * @param int $pos
601
	 */
602 View Code Duplication
	private function displayError(int $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...
603
		$total = sizeof($this->errors);
604
605
		if ($total === 0) {
606
			$this->runner->setInfoArray(
607
				[
608
					'errorCurrent' => 0,
609
					'errorTotal'   => 0,
610
				]
611
			);
612
613
			return;
614
		}
615
616
		try {
617
			$current = key($this->errors) + 1;
618
			$error = $this->getNavigationError($pos, ($current === 1), ($current === $total));
619
			$current = key($this->errors) + 1;
620
		} catch (OutOfBoundsException $e) {
621
			return;
622
		}
623
624
		/** @var ModelIndex $index */
625
		$index = $error['index'];
626
		$errorIndex = '';
627
		if ($index !== null) {
628
			$errorIndex = $index->getProviderId() . ':' . $index->getDocumentId();
629
		}
630
631
		$width = $this->terminal->getWidth() - 13;
632
		$message = $this->get('message', $error, '');
633
		$err1 = (string)substr($message, 0, $width);
634
		$err2 = (string)substr($message, $width, $width + 10);
635
		$err3 = (string)substr($message, $width + $width + 10, $width + 10);
636
637
		$this->runner->setInfoArray(
638
			[
639
				'errorCurrent'   => $current,
640
				'errorTotal'     => $total,
641
				'errorMessageA'  => trim($err1),
642
				'errorMessageB'  => trim($err2),
643
				'errorMessageC'  => trim($err3),
644
				'errorException' => $this->get('exception', $error, ''),
645
				'errorIndex'     => $errorIndex
646
			]
647
		);
648
	}
649
650
651
	/**
652
	 * @param int $pos
653
	 * @param bool $isFirst
654
	 * @param bool $isLast
655
	 *
656
	 * @return array
657
	 * @throws OutOfBoundsException
658
	 */
659 View Code Duplication
	private function getNavigationResult(int $pos, bool $isFirst, bool $isLast): array {
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->navigateLastResult === true) {
663
				return end($this->results);
664
			} else {
665
				return current($this->results);
666
			}
667
		}
668
669
		$this->navigateLastResult = false;
670
		if ($pos === -99) {
671
			return reset($this->results);
672
		}
673
674
		if ($pos === -1 && !$isFirst) {
675
			return prev($this->results);
676
		}
677
678
		if ($pos === 1 && !$isLast) {
679
			return next($this->results);
680
		}
681
682
		if ($pos === 99) {
683
			$this->navigateLastResult = true;
684
685
			return end($this->results);
686
		}
687
688
		throw new OutOfBoundsException();
689
	}
690
691
692
	/**
693
	 * @param int $pos
694
	 * @param bool $isFirst
695
	 * @param bool $isLast
696
	 *
697
	 * @return array
698
	 */
699 View Code Duplication
	private function getNavigationError(int $pos, bool $isFirst, bool $isLast): array {
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...
700
701
		if ($pos === 0) {
702
			if ($this->navigateLastError === true) {
703
				return end($this->errors);
704
			} else {
705
				return current($this->errors);
706
			}
707
		}
708
709
		$this->navigateLastError = false;
710
		if ($pos === -99) {
711
			return reset($this->errors);
712
		}
713
714
		if ($pos === -1 && !$isFirst) {
715
			return prev($this->errors);
716
		}
717
718
		if ($pos === 1 && !$isLast) {
719
			return next($this->errors);
720
		}
721
722
		if ($pos === 99) {
723
			$this->navigateLastError = true;
724
725
			return end($this->errors);
726
		}
727
728
		throw new OutOfBoundsException();
729
	}
730
731
732
	/**
733
	 *
734
	 */
735 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...
736
		$current = current($this->errors);
737
		if ($current === false) {
738
			return;
739
		}
740
741
		$this->runner->setInfoArray(
742
			[
743
				'errorMessageA'  => '',
744
				'errorMessageB'  => '',
745
				'errorMessageC'  => '',
746
				'errorException' => '',
747
				'errorIndex'     => ''
748
			]
749
		);
750
751
		$pos = key($this->errors);
752
753
		/** @var ModelIndex $index */
754
		$index = $current['index'];
755
		$this->indexService->resetErrorFromIndex($index);
756
757
		$errors = [];
758
		foreach ($this->errors as $error) {
759
			/** @var ModelIndex $errorIndex */
760
			$errorIndex = $error['index'];
761
			if ($index->getProviderId() === $errorIndex->getProviderId()
762
				&& $index->getDocumentId() === $errorIndex->getDocumentId()) {
763
				continue;
764
			}
765
766
			$errors[] = $error;
767
		}
768
769
		$this->errors = $errors;
770
		while (key($this->errors) < $pos) {
771
			if (next($this->errors) === false) {
772
				end($this->errors);
773
				break;
774
			}
775
		}
776
777
		$this->displayError();
778
	}
779
780
781
	/**
782
	 * @throws TickDoesNotExistException
783
	 */
784
	public function abort() {
785
		try {
786
			$this->abortIfInterrupted();
787
		} catch (InterruptedException $e) {
0 ignored issues
show
Bug introduced by
The class OC\Core\Command\InterruptedException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
788
			$this->runner->stop();
789
			exit();
790
		}
791
	}
792
793
794
}
795
796