Completed
Push — master ( dba968...9e87bf )
by Maxence
02:27
created

Index::testPlatform()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
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\IFullTextSearchProvider;
32
use OCA\FullTextSearch\Model\ExtendedBase;
33
use OCA\FullTextSearch\Model\Index as ModelIndex;
34
use OCA\FullTextSearch\Model\IndexOptions;
35
use OCA\FullTextSearch\Model\Runner;
36
use OCA\FullTextSearch\Service\CliService;
37
use OCA\FullTextSearch\Service\IndexService;
38
use OCA\FullTextSearch\Service\MiscService;
39
use OCA\FullTextSearch\Service\PlatformService;
40
use OCA\FullTextSearch\Service\ProviderService;
41
use OCA\FullTextSearch\Service\RunningService;
42
use OCP\IUserManager;
43
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
44
use Symfony\Component\Console\Input\InputArgument;
45
use Symfony\Component\Console\Input\InputInterface;
46
use Symfony\Component\Console\Output\OutputInterface;
47
use Symfony\Component\Console\Terminal;
48
49
50
class Index extends ExtendedBase {
51
52
//			'%job:1s%%message:-40s%%current:6s%/%max:6s% [%bar%] %percent:3s%% \n %duration% %infos:-12s% %jvm:-30s%      '
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 116 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
53
	const PANEL_RUN = 'run';
54
	const PANEL_RUN_LINE_OPTIONS = 'Options: %options%';
55
	const PANEL_RUN_LINE_MEMORY = 'Memory: %_memory%';
56
57
	const PANEL_INDEX = 'indexing';
58
	const PANEL_INDEX_LINE_HEADER = '┌─ Indexing %_paused% ────';
59
	const PANEL_INDEX_LINE_ACCOUNT = '│ Provider: <info>%providerName:-20s%</info> Account: <info>%userId%</info>';
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 112 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
60
	const PANEL_INDEX_LINE_ACTION = '│ Action: <info>%action%</info>';
61
	const PANEL_INDEX_LINE_DOCUMENT = '│ Document: <info>%documentId%</info>';
62
	const PANEL_INDEX_LINE_INFO = '│ Info: <info>%info%</info>';
63
	const PANEL_INDEX_LINE_TITLE = '│ Title: <info>%title%</info>';
64
	const PANEL_INDEX_LINE_CONTENT = '│ Content size: <info>%content%</info>';
65
	const PANEL_INDEX_LINE_PROGRESS = '│ Progress: %documentCurrent:6s%/%documentTotal%';
66
	const PANEL_INDEX_LINE_FOOTER = '└──';
67
68
	const PANEL_RESULT = 'result';
69
	const PANEL_RESULT_LINE_HEADER = '┌─ Results ────';
70
	const PANEL_RESULT_LINE_RESULT = '│ Result: <info>%resultCurrent:6s%</info>/<info>%resultTotal%</info>';
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 105 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
71
	const PANEL_RESULT_LINE_INDEX = '│ Index: <info>%resultIndex%</info>';
72
	const PANEL_RESULT_LINE_STATUS = '│ Status: %resultStatusColored%';
73
	const PANEL_RESULT_LINE_MESSAGE1 = '│ Message: <info>%resultMessageA%</info>';
74
	const PANEL_RESULT_LINE_MESSAGE2 = '│ <info>%resultMessageB%</info>';
75
	const PANEL_RESULT_LINE_MESSAGE3 = '│ <info>%resultMessageC%</info>';
76
	const PANEL_RESULT_LINE_FOOTER = '└──';
77
78
	const PANEL_ERRORS = 'errors';
79
	const PANEL_ERRORS_LINE_HEADER = '┌─ Errors ────';
80
	const PANEL_ERRORS_LINE_ERRORS = '│ Error: <comment>%errorCurrent:6s%</comment>/<comment>%errorTotal%</comment>';
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 114 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
81
	const PANEL_ERRORS_LINE_ERROR_INDEX = '│ Index: <comment>%errorIndex%</comment>';
82
	const PANEL_ERRORS_LINE_ERROR_EXCEPTION = '│ Exception: <comment>%errorException%</comment>';
83
	const PANEL_ERRORS_LINE_ERROR_MESSAGE1 = '│ Message: <comment>%errorMessageA%</comment>';
84
	const PANEL_ERRORS_LINE_ERROR_MESSAGE2 = '│ <comment>%errorMessageB%</comment>';
85
	const PANEL_ERRORS_LINE_ERROR_MESSAGE3 = '│ <comment>%errorMessageC%</comment>';
86
	const PANEL_ERRORS_LINE_FOOTER = '└──';
87
88
	const PANEL_COMMANDS_ROOT = 'root';
89
	const PANEL_COMMANDS_ROOT_LINE = '## <char>q</char>:quit ## <char>p</char>:pause ';
90
	const PANEL_COMMANDS_PAUSED = 'paused';
91
	const PANEL_COMMANDS_PAUSED_LINE = '## <char>q</char>:quit ## <char>u</char>:unpause ## <char>n</char>:next step';
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 115 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
92
	const PANEL_COMMANDS_DONE = 'done';
93
	const PANEL_COMMANDS_DONE_LINE = '## <char>q</char>:quit';
94
	const PANEL_COMMANDS_NAVIGATION = 'navigation';
95
	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';
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 177 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
96
	const PANEL_COMMANDS_RESULTS_LINE = '## <char>x</char>:first result ## <char>c</char>/<char>v</char>:prec/next result ## <char>b</char>:last result';
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 150 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
97
98
	/** @var IUserManager */
99
	private $userManager;
100
101
	/** @var RunningService */
102
	private $runningService;
103
104
	/** @var CliService */
105
	private $cliService;
106
107
	/** @var IndexService */
108
	private $indexService;
109
110
	/** @var PlatformService */
111
	private $platformService;
112
113
	/** @var ProviderService */
114
	private $providerService;
115
116
	/** @var MiscService */
117
	private $miscService;
118
119
120
	/** @var Runner */
121
	private $runner;
122
123
	/** @var Terminal */
124
	private $terminal;
125
126
	/** @var array */
127
	private $results = [];
128
129
	/** @var bool */
130
	private $navigateLastResult = true;
131
132
	/** @var array */
133
	private $errors = [];
134
135
	/** @var bool */
136
	private $navigateLastError = true;
137
138
139
	/**
140
	 * Index constructor.
141
	 *
142
	 * @param IUserManager $userManager
143
	 * @param RunningService $runningService
144
	 * @param CliService $cliService
145
	 * @param IndexService $indexService
146
	 * @param PlatformService $platformService
147
	 * @param ProviderService $providerService
148
	 * @param MiscService $miscService
149
	 */
150 View Code Duplication
	public function __construct(
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...
151
		IUserManager $userManager, RunningService $runningService, CliService $cliService,
152
		IndexService $indexService, PlatformService $platformService,
153
		ProviderService $providerService, MiscService $miscService
154
	) {
155
		parent::__construct();
156
		$this->userManager = $userManager;
157
158
		$this->runningService = $runningService;
159
		$this->cliService = $cliService;
160
		$this->indexService = $indexService;
161
162
		$this->platformService = $platformService;
163
		$this->providerService = $providerService;
164
		$this->miscService = $miscService;
165
	}
166
167
168
	/**
169
	 *
170
	 */
171
	protected function configure() {
172
		parent::configure();
173
		$this->setName('fulltextsearch:index')
174
			 ->setDescription('Index files')
175
			 ->addArgument('options', InputArgument::OPTIONAL, 'options');
176
	}
177
178
179
	/**
180
	 * @throws Exception
181
	 */
182
	public function interrupted() {
183
		if ($this->hasBeenInterrupted()) {
184
			throw new \Exception('ctrl-c');
185
		}
186
	}
187
188
189
	/**
190
	 * @param InputInterface $input
191
	 * @param OutputInterface $output
192
	 *
193
	 * @return int|null|void
194
	 * @throws Exception
195
	 */
196
	protected function execute(InputInterface $input, OutputInterface $output) {
197
198
		/** do not get stuck while waiting interactive input */
199
		readline_callback_handler_install(
200
			'', function() {
201
		}
202
		);
203
		stream_set_blocking(STDIN, false);
204
205
		$this->terminal = new Terminal();
206
207
		$outputStyle = new OutputFormatterStyle('white', 'black', ['bold']);
208
		$output->getFormatter()
209
			   ->setStyle('char', $outputStyle);
210
211
		$options = $this->generateIndexOptions($input);
212
213
		$this->runner = new Runner($this->runningService, 'commandIndex', ['nextStep' => 'n']);
214
		$this->runner->onKeyPress([$this, 'onKeyPressed']);
215
		$this->runner->onNewIndexError([$this, 'onNewIndexError']);
216
		$this->runner->onNewIndexResult([$this, 'onNewIndexResult']);
217
		$this->runner->pause($options->getOption('paused', false));
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
$options->getOption('paused', false) is of type array|string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
218
219
		$this->indexService->setRunner($this->runner);
220
		$this->cliService->setRunner($this->runner);
221
222
		$this->generatePanels();
223
		$this->runner->setInfo('options', json_encode($options));
224
225
		try {
226
			$this->runner->sourceIsCommandLine($this, $output);
227
			$this->runner->start();
228
229
			if ($options->getOption('errors') === 'reset') {
230
				$this->indexService->resetErrorsAll();
231
			}
232
233
			$this->testPlatform();
234
			$this->cliService->runDisplay($output);
235
			$this->generateIndexErrors();
236
			$this->displayError();
237
			$this->displayResult();
238
239
			$providers = $this->providerService->getProviders();
240
			foreach ($providers as $provider) {
241
242
				if (!$this->isIncludedProvider($options, $provider->getId())) {
243
					continue;
244
				}
245
246
				$provider->setRunner($this->runner);
247
				$provider->setIndexOptions($options);
248
				$this->indexProvider($provider, $options);
249
			}
250
251
		} catch (Exception $e) {
252
			$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...
253
			throw $e;
254
		}
255
256
		$this->runner->setInfo('documentCurrent', 'all');
257
		$this->runner->stop();
258
259
//		while (true) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
260
//			$this->runner->updateAction('_indexOver', true);
261
//			$pressed = strtolower($this->updateAction(''));
262
//			if ($pressed === $this->keys['nextStep']) {
263
//				$this->pauseRunning(false);
264
//				break;
265
//			}
266
//			usleep(300000);
267
//		}
268
269
270
//		$output->writeLn('');
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
271
272
	}
273
274
275
	/**
276
	 * @param $key
277
	 */
278 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...
279
		$key = strtolower($key);
280
		if ($key === 'q') {
281
			try {
282
				$this->runner->stop();
283
			} catch (TickDoesNotExistException $e) {
284
				/** we do nohtin' */
285
			}
286
			exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method onKeyPressed() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
287
		}
288
289
		$current = $this->cliService->currentPanel('commands');
290
		if ($current === self::PANEL_COMMANDS_ROOT && $key === 'p') {
291
			$this->cliService->switchPanel('commands', self::PANEL_COMMANDS_PAUSED);
292
			$this->runner->pause(true);
293
		}
294
		if ($current === self::PANEL_COMMANDS_PAUSED && $key === 'u') {
295
			$this->cliService->switchPanel('commands', self::PANEL_COMMANDS_ROOT);
296
			$this->runner->pause(false);
297
		}
298
299
		if ($key === 'x') {
300
			$this->displayResult(-99);
301
		}
302
		if ($key === 'c') {
303
			$this->displayResult(-1);
304
		}
305
		if ($key === 'v') {
306
			$this->displayResult(1);
307
		}
308
		if ($key === 'b') {
309
			$this->displayResult(99);
310
		}
311
312
		if ($key === 'f') {
313
			$this->displayError(-99);
314
		}
315
		if ($key === 'h') {
316
			$this->displayError(-1);
317
		}
318
		if ($key === 'j') {
319
			$this->displayError(1);
320
		}
321
		if ($key === 'l') {
322
			$this->displayError(99);
323
		}
324
		if ($key === 'd') {
325
			$this->deleteError();
326
		}
327
	}
328
329
330
	/**
331
	 * @param array $error
332
	 */
333
	public function onNewIndexError($error) {
334
		$this->errors[] = $error;
335
		$this->displayError();
336
	}
337
338
339
	/**
340
	 * @param array $result
341
	 */
342
	public function onNewIndexResult($result) {
343
		$this->results[] = $result;
344
		$this->displayResult();
345
	}
346
347
348
	/**
349
	 * @throws Exception
350
	 */
351
	private function testPlatform() {
352
		$platform = $this->platformService->getPlatform();
353
		if (!$platform->testPlatform()) {
354
			throw new Exception('failed platform test.');
355
		}
356
	}
357
358
359
	/**
360
	 * @param IFullTextSearchProvider $provider
361
	 * @param IndexOptions $options
362
	 *
363
	 * @throws Exception
364
	 */
365
	private function indexProvider(IFullTextSearchProvider $provider, IndexOptions $options) {
366
		$platform = $this->platformService->getPlatform();
367
		$platform->initializeIndex();
368
		$provider->onInitializingIndex($platform);
369
370
		$platform->setRunner($this->runner);
371
372
		$users = $this->generateUserList($options);
373
		foreach ($users as $user) {
374
			if ($user === null) {
375
				continue;
376
			}
377
378
			$this->indexService->indexProviderContentFromUser(
379
				$platform, $provider, $user->getUID(), $options
380
			);
381
		}
382
383
		$this->providerService->setProviderAsIndexed($provider, true);
384
385
	}
386
387
388
	/**
389
	 * @param InputInterface $input
390
	 *
391
	 * @return IndexOptions
392
	 */
393
	private function generateIndexOptions(InputInterface $input) {
394
		$jsonOptions = $input->getArgument('options');
395
		$options = json_decode($jsonOptions, true);
396
397
		if (!is_array($options)) {
398
			$options = [];
399
		}
400
401
		return new IndexOptions($options);
402
	}
403
404
405
	/**
406
	 * @param IndexOptions $options
407
	 * @param string $providerId
408
	 *
409
	 * @return bool
410
	 */
411
	private function isIncludedProvider(IndexOptions $options, $providerId) {
412
		if ($options->getOption('provider', '') !== ''
413
			&& $options->getOption('provider') !== $providerId) {
414
			return false;
415
		}
416
417
		if ($options->getOption('providers', null) !== null
418
			&& is_array($options->getOption('providers'))) {
419
			return (in_array($providerId, $options->getOption('providers')));
420
		}
421
422
		return true;
423
	}
424
425
426
	/**
427
	 * @param IndexOptions $options
428
	 *
429
	 * @return array
430
	 */
431
	private function generateUserList(IndexOptions $options) {
432
		if ($options->getOption('user', '') !== '') {
433
			return [$this->userManager->get($options->getOption('user'))];
434
		}
435
436
		if ($options->getOption('users', null) !== null
437
			&& is_array($options->getOption('users'))) {
438
			return array_map([$this->userManager, 'get'], $options->getOption('users'));
439
		}
440
441
		return $this->userManager->search('');
442
	}
443
444
445
	/**
446
	 *
447
	 */
448
	private function generatePanels() {
449
450
		$this->cliService->createPanel(
451
			self::PANEL_RUN,
452
			[
453
				self::PANEL_RUN_LINE_OPTIONS,
454
				self::PANEL_RUN_LINE_MEMORY
455
			]
456
		);
457
458
		$this->cliService->createPanel(
459
			self::PANEL_INDEX, [
460
								 self::PANEL_INDEX_LINE_HEADER,
461
								 self::PANEL_INDEX_LINE_ACTION,
462
								 self::PANEL_INDEX_LINE_ACCOUNT,
463
								 self::PANEL_INDEX_LINE_DOCUMENT,
464
								 self::PANEL_INDEX_LINE_INFO,
465
								 self::PANEL_INDEX_LINE_TITLE,
466
								 self::PANEL_INDEX_LINE_CONTENT,
467
								 self::PANEL_INDEX_LINE_PROGRESS,
468
								 self::PANEL_INDEX_LINE_FOOTER,
469
							 ]
470
		);
471
472
		$this->cliService->createPanel(
473
			self::PANEL_RESULT, [
474
								  self::PANEL_RESULT_LINE_HEADER,
475
								  self::PANEL_RESULT_LINE_RESULT,
476
								  self::PANEL_RESULT_LINE_INDEX,
477
								  self::PANEL_RESULT_LINE_STATUS,
478
								  self::PANEL_RESULT_LINE_MESSAGE1,
479
								  self::PANEL_RESULT_LINE_MESSAGE2,
480
								  self::PANEL_RESULT_LINE_MESSAGE3,
481
								  self::PANEL_RESULT_LINE_FOOTER,
482
							  ]
483
		);
484
485
		$this->cliService->createPanel(
486
			self::PANEL_ERRORS, [
487
								  self::PANEL_ERRORS_LINE_HEADER,
488
								  self::PANEL_ERRORS_LINE_ERRORS,
489
								  self::PANEL_ERRORS_LINE_ERROR_INDEX,
490
								  self::PANEL_ERRORS_LINE_ERROR_EXCEPTION,
491
								  self::PANEL_ERRORS_LINE_ERROR_MESSAGE1,
492
								  self::PANEL_ERRORS_LINE_ERROR_MESSAGE2,
493
								  self::PANEL_ERRORS_LINE_ERROR_MESSAGE3,
494
								  self::PANEL_ERRORS_LINE_FOOTER,
495
							  ]
496
		);
497
498
		$this->cliService->createPanel(
499
			self::PANEL_COMMANDS_ROOT, [
500
										 self::PANEL_COMMANDS_ROOT_LINE
501
									 ]
502
		);
503
504
		$this->cliService->createPanel(
505
			self::PANEL_COMMANDS_PAUSED, [
506
										   self::PANEL_COMMANDS_PAUSED_LINE
507
									   ]
508
		);
509
510
		$this->cliService->createPanel(
511
			self::PANEL_COMMANDS_NAVIGATION, [
512
											   self::PANEL_COMMANDS_RESULTS_LINE,
513
											   self::PANEL_COMMANDS_ERRORS_LINE
514
										   ]
515
		);
516
517
		$this->cliService->initDisplay();
518
		$this->cliService->displayPanel('run', self::PANEL_RUN);
519
		$this->cliService->displayPanel('indexPanel', self::PANEL_INDEX);
520
		$this->cliService->displayPanel('resultsPanel', self::PANEL_RESULT);
521
		$this->cliService->displayPanel('errorsPanel', self::PANEL_ERRORS);
522
		$this->cliService->displayPanel('navigation', self::PANEL_COMMANDS_NAVIGATION);
523
524
		if ($this->runner->isPaused()) {
525
			$this->cliService->displayPanel('commands', self::PANEL_COMMANDS_PAUSED);
526
		} else {
527
			$this->cliService->displayPanel('commands', self::PANEL_COMMANDS_ROOT);
528
		}
529
530
		$this->runner->setInfoArray(
531
			[
532
				'userId'       => '',
533
				'providerName' => '',
534
				'_memory'      => '',
535
				'documentId'   => '',
536
				'action'       => '',
537
				'info'         => '',
538
				'title'        => '',
539
				'_paused'      => '',
540
541
				'resultIndex'         => '',
542
				'resultCurrent'       => '',
543
				'resultTotal'         => '',
544
				'resultMessageA'      => '',
545
				'resultMessageB'      => '',
546
				'resultMessageC'      => '',
547
				'resultStatus'        => '',
548
				'resultStatusColored' => '',
549
				'content'             => '',
550
				'statusColored'       => '',
551
				'documentCurrent'     => '',
552
				'documentTotal'       => '',
553
				'progressStatus'      => '',
554
				'errorCurrent'        => '0',
555
				'errorTotal'          => '0',
556
				'errorMessageA'       => '',
557
				'errorMessageB'       => '',
558
				'errorMessageC'       => '',
559
				'errorException'      => '',
560
				'errorIndex'          => ''
561
			]
562
		);
563
	}
564
565
566
	/**
567
	 * @param int $pos
568
	 */
569 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...
570
		$total = sizeof($this->errors);
571
572
		if ($total === 0) {
573
			$this->runner->setInfoArray(
574
				[
575
					'errorCurrent' => 0,
576
					'errorTotal'   => 0,
577
				]
578
			);
579
580
			return;
581
		}
582
583
		$current = key($this->errors) + 1;
584
		$error = $this->getNavigationError($pos, ($current === 1), ($current === $total));
585
		$current = key($this->errors) + 1;
586
587
		if ($error === false) {
588
			return;
589
		}
590
591
		/** @var ModelIndex $index */
592
		$index = $error['index'];
593
		$errorIndex = '';
594
		if ($index !== null) {
595
			$errorIndex = $index->getProviderId() . ':' . $index->getDocumentId();
596
		}
597
598
		$width = $this->terminal->getWidth() - 13;
599
		$message = MiscService::get('message', $error, '');
600
		$err1 = substr($message, 0, $width);
601
		$err2 = substr($message, $width, $width + 10);
602
		$err3 = substr($message, $width + $width + 10, $width + 10);
603
604
		$this->runner->setInfoArray(
605
			[
606
				'errorCurrent'   => $current,
607
				'errorTotal'     => $total,
608
				'errorMessageA'  => trim($err1),
609
				'errorMessageB'  => trim($err2),
610
				'errorMessageC'  => trim($err3),
611
				'errorException' => MiscService::get('exception', $error, ''),
612
				'errorIndex'     => $errorIndex
613
			]
614
		);
615
	}
616
617
618
	/**
619
	 * @param int $pos
620
	 */
621 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...
622
		$total = sizeof($this->results);
623
624
		if ($total === 0) {
625
			$this->runner->setInfoArray(
626
				[
627
					'resultCurrent' => 0,
628
					'resultTotal'   => 0,
629
				]
630
			);
631
632
			return;
633
		}
634
635
		$current = key($this->results) + 1;
636
		$result = $this->getNavigationResult($pos, ($current === 1), ($current === $total));
637
		$current = key($this->results) + 1;
638
639
		if ($result === false) {
640
			return;
641
		}
642
643
		/** @var ModelIndex $index */
644
		$index = $result['index'];
645
		$resultIndex = '';
646
		if ($index !== null) {
647
			$resultIndex = $index->getProviderId() . ':' . $index->getDocumentId();
648
		}
649
650
651
		$width = $this->terminal->getWidth() - 13;
652
		$message = MiscService::get('message', $result, '');
653
		$msg1 = substr($message, 0, $width);
654
		$msg2 = substr($message, $width, $width + 10);
655
		$msg3 = substr($message, $width + $width + 10, $width + 10);
656
657
658
		$status = MiscService::get('status', $result, '');
659
		$type = MiscService::get('type', $result, '');
660
661
		$this->runner->setInfoArray(
662
			[
663
				'resultCurrent'  => $current,
664
				'resultTotal'    => $total,
665
				'resultMessageA' => trim($msg1),
666
				'resultMessageB' => trim($msg2),
667
				'resultMessageC' => trim($msg3),
668
				'resultStatus'   => $status,
669
				'resultIndex'    => $resultIndex
670
			]
671
		);
672
		$this->runner->setInfoColored('resultStatus', $type);
673
	}
674
675
676
	/**
677
	 * @param int $pos
678
	 * @param bool $isFirst
679
	 * @param bool $isLast
680
	 *
681
	 * @return bool|array
682
	 */
683 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...
684
685
		if ($pos === 0) {
686
			if ($this->navigateLastError === true) {
687
				return end($this->errors);
688
			} else {
689
				return current($this->errors);
690
			}
691
		}
692
693
		$this->navigateLastError = false;
694
		if ($pos === -99) {
695
			return reset($this->errors);
696
		}
697
698
		if ($pos === -1 && !$isFirst) {
699
			return prev($this->errors);
700
		}
701
702
		if ($pos === 1 && !$isLast) {
703
			return next($this->errors);
704
		}
705
706
		if ($pos === 99) {
707
			$this->navigateLastError = true;
708
709
			return end($this->errors);
710
		}
711
712
		return false;
713
	}
714
715
716
	/**
717
	 * @param int $pos
718
	 * @param bool $isFirst
719
	 * @param bool $isLast
720
	 *
721
	 * @return bool|array
722
	 */
723
	private function getNavigationResult($pos, $isFirst, $isLast) {
724
725 View Code Duplication
		if ($pos === 0) {
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...
726
			if ($this->navigateLastResult === true) {
727
				return end($this->results);
728
			} else {
729
				return current($this->results);
730
			}
731
		}
732
733
		$this->navigateLastResult = false;
734
		if ($pos === -99) {
735
			return reset($this->results);
736
		}
737
738
		if ($pos === -1 && !$isFirst) {
739
			return prev($this->results);
740
		}
741
742
		if ($pos === 1 && !$isLast) {
743
			return next($this->results);
744
		}
745
746
		if ($pos === 99) {
747
			$this->navigateLastResult = true;
748
749
			return end($this->results);
750
		}
751
752
		return false;
753
	}
754
755
756
	/**
757
	 *
758
	 */
759 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...
760
		$indexes = $this->indexService->getErrorIndexes();
761
762
		foreach ($indexes as $index) {
763
			foreach ($index->getErrors() as $error) {
764
				$this->errors[] = [
765
					'index'     => $index,
766
					'message'   => $error['message'],
767
					'exception' => $error['exception'],
768
					'severity'  => $error['sev']
769
				];
770
			}
771
772
		}
773
774
775
	}
776
777
778
	/**
779
	 *
780
	 */
781 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...
782
		$current = current($this->errors);
783
		if ($current === false) {
784
			return;
785
		}
786
787
		$this->runner->setInfoArray(
788
			[
789
				'errorMessageA'  => '',
790
				'errorMessageB'  => '',
791
				'errorMessageC'  => '',
792
				'errorException' => '',
793
				'errorIndex'     => ''
794
			]
795
		);
796
797
		$pos = key($this->errors);
798
799
		/** @var ModelIndex $index */
800
		$index = $current['index'];
801
		$this->indexService->resetErrorFromIndex($index);
802
803
		$errors = [];
804
		foreach ($this->errors as $error) {
805
			/** @var ModelIndex $errorIndex */
806
			$errorIndex = $error['index'];
807
			if ($index->getProviderId() === $errorIndex->getProviderId()
808
				&& $index->getDocumentId() === $errorIndex->getDocumentId()) {
809
				continue;
810
			}
811
812
			$errors[] = $error;
813
		}
814
815
		$this->errors = $errors;
816
		while (key($this->errors) < $pos) {
817
			if (next($this->errors) === false) {
818
				end($this->errors);
819
				break;
820
			}
821
		}
822
823
		$this->displayError();
824
	}
825
826
}
827
828
829
830