Completed
Push — master ( 98e766...a494e9 )
by Maxence
02:14
created

CirclesCheck::saveLoopback()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.584
c 0
b 0
f 0
cc 2
nc 2
nop 3
1
<?php declare(strict_types=1);
2
3
4
/**
5
 * Circles - Bring cloud-users closer together.
6
 *
7
 * This file is licensed under the Affero General Public License version 3 or
8
 * later. See the COPYING file.
9
 *
10
 * @author Maxence Lange <[email protected]>
11
 * @copyright 2017
12
 * @license GNU AGPL version 3 or any later version
13
 *
14
 * This program is free software: you can redistribute it and/or modify
15
 * it under the terms of the GNU Affero General Public License as
16
 * published by the Free Software Foundation, either version 3 of the
17
 * License, or (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU Affero General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU Affero General Public License
25
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
26
 *
27
 */
28
29
30
namespace OCA\Circles\Command;
31
32
use daita\MySmallPhpTools\Exceptions\RequestNetworkException;
33
use daita\MySmallPhpTools\Model\Nextcloud\nc22\NC22Request;
34
use daita\MySmallPhpTools\Model\Request;
35
use daita\MySmallPhpTools\Traits\Nextcloud\nc22\TNC22Request;
36
use daita\MySmallPhpTools\Traits\TArrayTools;
37
use daita\MySmallPhpTools\Traits\TStringTools;
38
use Exception;
39
use OC\Core\Command\Base;
40
use OCA\Circles\AppInfo\Application;
41
use OCA\Circles\AppInfo\Capabilities;
42
use OCA\Circles\Exceptions\FederatedEventException;
43
use OCA\Circles\Exceptions\FederatedItemException;
44
use OCA\Circles\Exceptions\InitiatorNotConfirmedException;
45
use OCA\Circles\Exceptions\OwnerNotFoundException;
46
use OCA\Circles\Exceptions\RemoteInstanceException;
47
use OCA\Circles\Exceptions\RemoteNotFoundException;
48
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
49
use OCA\Circles\Exceptions\RequestBuilderException;
50
use OCA\Circles\Exceptions\UnknownRemoteException;
51
use OCA\Circles\FederatedItems\LoopbackTest;
52
use OCA\Circles\Model\Federated\FederatedEvent;
53
use OCA\Circles\Service\ConfigService;
54
use OCA\Circles\Service\FederatedEventService;
55
use OCA\Circles\Service\RemoteService;
56
use OCA\Circles\Service\RemoteStreamService;
57
use OCA\Circles\Service\RemoteUpstreamService;
58
use Symfony\Component\Console\Input\InputInterface;
59
use Symfony\Component\Console\Input\InputOption;
60
use Symfony\Component\Console\Output\OutputInterface;
61
use Symfony\Component\Console\Question\ConfirmationQuestion;
62
use Symfony\Component\Console\Question\Question;
63
64
65
/**
66
 * Class CirclesCheck
67
 *
68
 * @package OCA\Circles\Command
69
 */
70
class CirclesCheck extends Base {
71
72
73
	use TStringTools;
74
	use TArrayTools;
75
	use TNC22Request;
76
77
78
	static $checks = [
79
		'internal',
80
		'frontal',
81
		'loopback'
82
	];
83
84
	/** @var Capabilities */
85
	private $capabilities;
86
87
	/** @var FederatedEventService */
88
	private $federatedEventService;
89
90
	/** @var RemoteService */
91
	private $remoteService;
92
93
	/** @var RemoteStreamService */
94
	private $remoteStreamService;
95
96
	/** @var RemoteUpstreamService */
97
	private $remoteUpstreamService;
98
99
	/** @var ConfigService */
100
	private $configService;
101
102
103
	/** @var int */
104
	private $delay = 5;
105
106
	/** @var array */
107
	private $sessions = [];
108
109
110
	/**
111
	 * CirclesCheck constructor.
112
	 *
113
	 * @param Capabilities $capabilities
114
	 * @param FederatedEvent $federatedEventService
115
	 * @param RemoteService $remoteService
116
	 * @param RemoteStreamService $remoteStreamService
117
	 * @param RemoteUpstreamService $remoteUpstreamService
118
	 * @param ConfigService $configService
119
	 */
120
	public function __construct(
121
		Capabilities $capabilities,
122
		FederatedEventService $federatedEventService,
123
		RemoteService $remoteService,
124
		RemoteStreamService $remoteStreamService,
125
		RemoteUpstreamService $remoteUpstreamService,
126
		ConfigService $configService
127
	) {
128
		parent::__construct();
129
130
		$this->capabilities = $capabilities;
131
		$this->federatedEventService = $federatedEventService;
132
		$this->remoteService = $remoteService;
133
		$this->remoteStreamService = $remoteStreamService;
134
		$this->remoteUpstreamService = $remoteUpstreamService;
135
		$this->configService = $configService;
136
	}
137
138
139
	protected function configure() {
140
		parent::configure();
141
		$this->setName('circles:check')
142
			 ->setDescription('Checking your configuration')
143
			 ->addOption('delay', 'd', InputOption::VALUE_REQUIRED, 'delay before checking result')
144
			 ->addOption('capabilities', '', InputOption::VALUE_NONE, 'listing app\'s capabilities')
145
			 ->addOption('type', '', InputOption::VALUE_REQUIRED, 'configuration to check', '')
146
			 ->addOption('test', '', InputOption::VALUE_REQUIRED, 'specify an url to test', '');
147
	}
148
149
150
	/**
151
	 * @param InputInterface $input
152
	 * @param OutputInterface $output
153
	 *
154
	 * @return int
155
	 * @throws Exception
156
	 */
157
	protected function execute(InputInterface $input, OutputInterface $output): int {
158
		if ($input->getOption('capabilities')) {
159
			$capabilities = $this->getArray('circles', $this->capabilities->getCapabilities(true));
160
			$output->writeln(json_encode($capabilities, JSON_PRETTY_PRINT));
161
162
			return 0;
163
		}
164
165
		if ($input->getOption('delay')) {
166
			$this->delay = (int)$input->getOption('delay');
167
		}
168
169
		$this->configService->setAppValue(ConfigService::TEST_NC_BASE, '');
170
		$test = $input->getOption('test');
171
		$type = $input->getOption('type');
172
		if ($test !== '' && $type === '') {
173
			throw new Exception('Please specify a --type for the test');
174
		}
175
		if ($test !== '' && !in_array($type, self::$checks)) {
176
			throw new Exception('Unknown type: ' . implode(', ', self::$checks));
177
		}
178
179
//		$this->configService->setAppValue(ConfigService::TEST_NC_BASE, $test);
180
181
		if ($type === '' || $type === 'loopback') {
182
			$output->writeln('### Checking <info>loopback</info> address.');
183
			$this->checkLoopback($input, $output, $test);
184
			$output->writeln('');
185
			$output->writeln('');
186
		}
187
		if ($type === '' || $type === 'internal') {
188
			$output->writeln('### Testing <info>internal</info> address.');
189
			$this->checkInternal($input, $output, $test);
190
			$output->writeln('');
191
			$output->writeln('');
192
		}
193
		if ($type === '' || $type === 'frontal') {
194
			$output->writeln('### Testing <info>frontal</info> address.');
195
			$this->checkFrontal($input, $output, $test);
196
			$output->writeln('');
197
		}
198
199
200
//
201
//		if (!$this->testRequest($output, 'GET', 'core.CSRFToken.index')) {
202
//			$this->configService->setAppValue(ConfigService::TEST_NC_BASE, '');
203
//
204
//			return 0;
205
//		}
206
//
207
//		if (!$this->testRequest(
208
//			$output, 'POST', 'circles.EventWrapper.asyncBroadcast',
209
//			['token' => 'test-dummy-token']
210
//		)) {
211
//			$this->configService->setAppValue(ConfigService::TEST_NC_BASE, '');
212
//
213
//			return 0;
214
//		}
215
//
216
//		$test = new GSEvent(GSEvent::TEST, true, true);
217
//		$test->setAsync(true);
218
//		$token = $this->gsUpstreamService->newEvent($test);
219
//
220
//		$output->writeln('- Async request is sent, now waiting ' . $this->delay . ' seconds');
221
//		sleep($this->delay);
222
//		$output->writeln('- Pause is over, checking results for ' . $token);
223
//
224
//		$wrappers = $this->gsUpstreamService->getEventsByToken($token);
225
//
226
//		$result = [];
227
//		$instances = array_merge($this->globalScaleService->getInstances(true));
228
//		foreach ($wrappers as $wrapper) {
229
//			$result[$wrapper->getInstance()] = $wrapper->getEvent();
230
//		}
231
//
232
//		$localLooksGood = false;
233
//		foreach ($instances as $instance) {
234
//			$output->write($instance . ' ');
235
//			if (array_key_exists($instance, $result)
236
//				&& $result[$instance]->getResult()
237
//									 ->gInt('status') === 1) {
238
//				$output->writeln('<info>ok</info>');
239
//				if ($this->configService->isLocalInstance($instance)) {
240
//					$localLooksGood = true;
241
//				}
242
//			} else {
243
//				$output->writeln('<error>fail</error>');
244
//			}
245
//		}
246
//
247
//		$this->configService->setAppValue(ConfigService::TEST_NC_BASE, '');
248
//
249
//		if ($localLooksGood) {
250
//			$this->saveUrl($input, $output, $input->getOption('url'));
251
//		}
252
253
		return 0;
254
	}
255
256
257
	/**
258
	 * @param InputInterface $input
259
	 * @param OutputInterface $output
260
	 * @param string $test
261
	 *
262
	 * @throws Exception
263
	 */
264
	private function checkLoopback(InputInterface $input, OutputInterface $output, string $test = ''): void {
265
		$output->writeln('. The <info>loopback</info> setting is mandatory and can be checked locally.');
266
		$output->writeln(
267
			'. The address you need to define here must be a reachable url of your Nextcloud from the hosting server itself.'
268
		);
269
		$output->writeln(
270
			'. By default, the App will use the entry \'overwrite.cli.url\' from \'config/config.php\'.'
271
		);
272
273
		$notDefault = false;
274
		if ($test === '') {
275
			$test = $this->configService->getLoopbackPath();
276
		} else {
277
			$notDefault = true;
278
		}
279
280
		$output->writeln('');
281
		$output->writeln('* testing current address: ' . $test);
282
283
		try {
284
			$this->setupLoopback($input, $output, $test);
285
			$output->writeln('* <info>Loopback</info> address looks good');
286
			if ($notDefault) {
287
				$this->saveLoopback($input, $output, $test);
288
			}
289
290
			return;
291
		} catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
292
		}
293
294
		$output->writeln('');
295
		$output->writeln('- <comment>You do not have a valid loopback address setup right now.</comment>');
296
		$output->writeln('');
297
298
		$helper = $this->getHelper('question');
299
		while (true) {
300
			$question = new Question(
301
				'<info>Please write down a new loopback address to test</info>: ', ''
302
			);
303
304
			$loopback = $helper->ask($input, $output, $question);
305
			if (is_null($loopback) || $loopback === '') {
306
				$output->writeln('exiting.');
307
				throw new Exception('Your Circles App is not fully configured.');
308
			}
309
310
			try {
311
				[$scheme, $cloudId] = $this->parseAddress($loopback);
0 ignored issues
show
Bug introduced by
The variable $scheme does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $cloudId does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
312
			} catch (Exception $e) {
313
				$output->writeln('<error>format must be http[s]://domain.name[:post]</error>');
314
				continue;
315
			}
316
317
			$loopback = $scheme . '://' . $cloudId;
318
			$output->write('* testing address: ' . $loopback . ' ');
319
320
			if ($this->testLoopback($input, $output, $loopback)) {
321
				$output->writeln('* <info>Loopback</info> address looks good');
322
				$this->saveLoopback($input, $output, $loopback);
323
324
				return;
325
			}
326
		}
327
	}
328
329
330
	/**
331
	 * @throws Exception
332
	 */
333
	private function setupLoopback(InputInterface $input, OutputInterface $output, string $address): void {
334
		$e = null;
335
		try {
336
			[$scheme, $cloudId] = $this->parseAddress($address);
0 ignored issues
show
Bug introduced by
The variable $scheme does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $cloudId does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
337
338
			$this->configService->setAppValue(ConfigService::LOOPBACK_TMP_SCHEME, $scheme);
339
			$this->configService->setAppValue(ConfigService::LOOPBACK_TMP_ID, $cloudId);
340
			if (!$this->testLoopback($input, $output, $address)) {
341
				throw new Exception();
342
			}
343
		} catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
344
		}
345
346
		$this->configService->setAppValue(ConfigService::LOOPBACK_TMP_SCHEME, '');
347
		$this->configService->setAppValue(ConfigService::LOOPBACK_TMP_ID, '');
348
349
		if (!is_null($e)) {
350
			throw $e;
351
		}
352
	}
353
354
355
	/**
356
	 * @param InputInterface $input
357
	 * @param OutputInterface $output
358
	 * @param string $address
359
	 *
360
	 * @return bool
361
	 * @throws RequestNetworkException
362
	 * @throws FederatedEventException
363
	 * @throws FederatedItemException
364
	 * @throws InitiatorNotConfirmedException
365
	 * @throws OwnerNotFoundException
366
	 * @throws RemoteInstanceException
367
	 * @throws RemoteNotFoundException
368
	 * @throws RemoteResourceNotFoundException
369
	 * @throws UnknownRemoteException
370
	 * @throws RequestBuilderException
371
	 */
372
	private function testLoopback(InputInterface $input, OutputInterface $output, string $address): bool {
373
		if (!$this->testRequest($output, 'GET', 'core.CSRFToken.index')) {
374
			return false;
375
		}
376
377
		if (!$this->testRequest(
378
			$output, 'POST', 'circles.EventWrapper.asyncBroadcast',
379
			['token' => 'test-dummy-token']
380
		)) {
381
			return false;
382
		}
383
384
		$output->write('- Creating async FederatedEvent ');
385
		$test = new FederatedEvent(LoopbackTest::class);
386
		$this->federatedEventService->newEvent($test);
387
388
		$output->writeln('<info>' . $test->getWrapperToken() . '</info>');
389
390
		$output->writeln('- Waiting for async process to finish (' . $this->delay . 's)');
391
		sleep($this->delay);
392
393
		$output->write('- Checking status on FederatedEvent ');
394
		$wrappers = $this->remoteUpstreamService->getEventsByToken($test->getWrapperToken());
395
		if (count($wrappers) !== 1) {
396
			$output->writeln('<error>Event created too many Wrappers</error>');
397
			$output->writeln('<error>Event created too many Wrappers</error>');
398
		}
399
400
		$wrapper = array_shift($wrappers);
401
402
		$checkVerify = $wrapper->getEvent()->getData()->gInt('verify');
403
		if ($checkVerify === LoopbackTest::VERIFY) {
404
			$output->write('<info>verify=' . $checkVerify . '</info> ');
405
		} else {
406
			$output->writeln('<error>verify=' . $checkVerify . '</error>');
407
408
			return false;
409
		}
410
411
		$checkManage = $wrapper->getResult()->gInt('manage');
412
		if ($checkManage === LoopbackTest::MANAGE) {
413
			$output->write('<info>manage=' . $checkManage . '</info> ');
414
		} else {
415
			$output->writeln('<error>manage=' . $checkManage . '</error>');
416
417
			return false;
418
		}
419
420
		$output->writeln('');
421
422
		return true;
423
	}
424
425
426
	/**
427
	 * @param InputInterface $input
428
	 * @param OutputInterface $output
429
	 * @param string $loopback
430
	 *
431
	 * @throws Exception
432
	 */
433
	private function saveLoopback(InputInterface $input, OutputInterface $output, string $loopback): void {
434
		[$scheme, $cloudId] = $this->parseAddress($loopback);
0 ignored issues
show
Bug introduced by
The variable $scheme does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $cloudId does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
435
436
		$question = new ConfirmationQuestion(
437
			'- Do you want to save <info>'. $loopback . '</info> as your <info>loopback</info> address ? (y/N) ', false, '/^(y|Y)/i'
438
		);
439
440
		$helper = $this->getHelper('question');
441
		if (!$helper->ask($input, $output, $question)) {
442
			$output->writeln('skipping.');
443
444
			return;
445
		}
446
447
		$this->configService->setAppValue(ConfigService::LOOPBACK_CLOUD_SCHEME, $scheme);
448
		$this->configService->setAppValue(ConfigService::LOOPBACK_CLOUD_ID, $cloudId);
449
		$output->writeln(
450
			'- Address <info>' . $loopback . '</info> is now used as <info>loopback</info>'
451
		);
452
453
	}
454
455
	/**
456
	 * @param InputInterface $input
457
	 * @param OutputInterface $output
458
	 * @param string $test
459
	 */
460
	private function checkInternal(InputInterface $input, OutputInterface $output, string $test): void {
461
		$output->writeln(
462
			'. The <info>internal</info> setting is mandatory only if you are willing to use Circles in a GlobalScale setup on a local network.'
463
		);
464
		$output->writeln(
465
			'. The address you need to define here is the local address of your Nextcloud, reachable by all other instances of our GlobalScale.'
466
		);
467
468
469
	}
470
471
472
	/**
473
	 * @param InputInterface $input
474
	 * @param OutputInterface $output
475
	 * @param string $test
476
	 */
477
	private function checkFrontal(InputInterface $input, OutputInterface $output, string $test): void {
478
		$output->writeln('. The <info>frontal</info> setting is optional.');
479
		$output->writeln(
480
			'. The purpose of this address is for your Federated Circle to reach other instances of Nextcloud over the Internet.'
481
		);
482
		$output->writeln(
483
			'. The address you need to define here must be reachable from the Internet.'
484
		);
485
		$output->writeln(
486
			'. By default, this feature is disabled (and is considered ALPHA in Nextcloud 22).'
487
		);
488
489
		$question = new ConfirmationQuestion(
490
			'- <comment>Do you want to enable this feature ?</comment> (y/N) ', false, '/^(y|Y)/i'
491
		);
492
493
		$helper = $this->getHelper('question');
494
		if (!$helper->ask($input, $output, $question)) {
495
			$output->writeln('skipping.');
496
497
			return;
498
		}
499
500
501
		while (true) {
502
503
			$question = new Question(
504
				'<info>Please write down a new frontal address to test</info>: ', ''
505
			);
506
507
			$frontal = $helper->ask($input, $output, $question);
508
			if (is_null($frontal) || $frontal === '') {
509
				$output->writeln('skipping.');
510
511
				return;
512
			}
513
514
			try {
515
				[$scheme, $cloudId] = $this->parseAddress($frontal);
0 ignored issues
show
Bug introduced by
The variable $scheme does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $cloudId does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
516
			} catch (Exception $e) {
517
				$output->writeln('<error>format must be http[s]://domain.name[:post]</error>');
518
				continue;
519
			}
520
521
			$frontal = $scheme . '://' . $cloudId;
522
			break;
523
		}
524
525
		$question = new ConfirmationQuestion(
526
			'<comment>Do you want to check the validity of this frontal address?</comment> (y/N) ', false,
527
			'/^(y|Y)/i'
528
		);
529
530
		if ($helper->ask($input, $output, $question)) {
531
			$output->writeln(
532
				'You will need to run this <info>curl</info> command from a remote terminal and paste its result: '
533
			);
534
			$output->writeln(
535
				'     curl ' . $frontal . '/.well-known/webfinger?resource=http://nextcloud.com/'
0 ignored issues
show
Bug introduced by
The variable $frontal does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
536
			);
537
538
			$question = new Question('result: ', '');
539
			$pasteWebfinger = $helper->ask($input, $output, $question);
540
541
			echo '__ ' . $pasteWebfinger;
542
543
			$output->writeln('TESTING !!');
544
			$output->writeln('TESTING !!');
545
			$output->writeln('TESTING !!');
546
		}
547
548
		$output->writeln('saved');
549
550
551
//		$output->writeln('.  1) The automatic way, requiring a valid remote instance of Nextcloud.');
552
//		$output->writeln(
553
//			'.  2) The manual way, using the <comment>curl</comment> command from a remote terminal.'
554
//		);
555
//		$output->writeln(
556
//			'. If you prefer the automatic way, you will need to enter the valid remote instance of Nextcloud you want to use.'
557
//		);
558
//		$output->writeln('. If you want the manual way, just enter an empty field.');
559
//		$output->writeln('');
560
//		$output->writeln(
561
//			'. If you do not known a valid remote instance of Nextcloud, you can use <comment>\'https://circles.artificial-owl.com/\'</comment>'
562
//		);
563
//		$output->writeln(
564
//			'. Please note that no critical information will be shared during the process, and any data (ie. public key and address)'
565
//		);
566
//		$output->writeln(
567
//			'  generated during the process will be wiped of the remote instance after few minutes.'
568
//		);
569
//		$output->writeln('');
570
571
//		$question = new Question(
572
//			'- <comment>Which remote instance of Nextcloud do you want to use in order to test your setup:</comment> (empty to bypass this step): '
573
//		);
574
//		$helper = $this->getHelper('question');
575
//		$remote = $helper->ask($input, $output, $question);
576
//		if (is_null($frontal) || $frontal === '') {
577
//			$output->writeln('skipping.');
578
//
579
//			return;
580
//		}
581
//
582
//		$output->writeln('. The confirmation step is optional and can be done in 2 different ways:');
583
//
584
//
585
//		$output->writeln('');
586
//		$question = new Question(
587
//			'- <comment>Enter the <info>frontal</info> address you want to be used to identify your instance of Nextcloud over the Internet</comment>: '
588
//		);
589
//		$helper = $this->getHelper('question');
590
//		$frontal = $helper->ask($input, $output, $question);
591
592
//		while (true) {
593
//			$question = new Question(
594
//				'<info>Please write down a new frontal address to test</info>: ', ''
595
//			);
596
//
597
//			$frontal = $helper->ask($input, $output, $question);
598
//			if (is_null($frontal) || $frontal === '') {
599
//				$output->writeln('skipping.');
600
//
601
//				return;
602
//			}
603
//
604
//			try {
605
//				[$scheme, $cloudId] = $this->parseAddress($test);
606
//			} catch (Exception $e) {
607
//				$output->writeln('<error>format must be http[s]://domain.name[:post]</error>');
608
//				continue;
609
//			}
610
//
611
//			$frontal = $scheme . '://' . $cloudId;
612
//
613
//			$output->write('* testing address: ' . $frontal . ' ');
614
//
615
//			if ($remote === '') {
616
//				$output->writeln('remote empty, please run this curl request and paste the result in here');
617
//				$output->writeln(
618
//					'  curl ' . $frontal . '/.well-known/webfinger?resource=http://nextcloud.com/'
619
//				);
620
//				$question = new Question('result: ', '');
621
//
622
//				$resultWebfinger = $helper->ask($input, $output, $question);
623
//
624
//			} else {
625
//			}
626
//		}
627
628
629
//		if ($remote === '') {
630
//			$output->writeln('');
631
//		}
632
633
//		$output->writeln('');
634
//		$output->writeln(
635
//			'. By default, this feature is disabled. You will need to setup a valid entry to enabled it.'
636
//		);
637
638
//		$output->writeln('');
639
//		$output->write('* testing current address: ' . $this->configService->getLoopbackPath() . ' ');
640
641
642
//		$this->configService->getAppValue(ConfigService::CHECK_FRONTAL_USING);
643
	}
644
645
646
	/**
647
	 * @param OutputInterface $o
0 ignored issues
show
Bug introduced by
There is no parameter named $o. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
648
	 * @param string $type
649
	 * @param string $route
650
	 * @param array $args
651
	 *
652
	 * @return bool
653
	 */
654
	private function testRequest(
655
		OutputInterface $output,
656
		string $type,
657
		string $route,
658
		array $args = []
659
	): bool {
660
		$request = new NC22Request('', Request::type($type));
661
		$this->configService->configureLoopbackRequest($request, $route, $args);
662
		$request->setFollowLocation(false);
663
664
		$output->write('- ' . $type . ' request on ' . $request->getCompleteUrl() . ': ');
665
666
		try {
667
			$this->doRequest($request);
668
			$result = $request->getResult();
669
670
			$color = 'error';
671
			if ($result->getStatusCode() === 200) {
672
				$color = 'info';
673
			}
674
675
			$output->writeln('<' . $color . '>' . $result->getStatusCode() . '</' . $color . '>');
676
			if ($result->getStatusCode() === 200) {
677
				return true;
678
			}
679
		} catch (RequestNetworkException $e) {
680
			$output->writeln('<error>fail</error>');
681
		}
682
683
		return false;
684
	}
685
686
687
	/**
688
	 * @param InputInterface $input
689
	 * @param OutputInterface $output
690
	 * @param string $address
691
	 */
692
	private function saveUrl(InputInterface $input, OutputInterface $output, string $address): void {
693
		if ($address === '') {
694
			return;
695
		}
696
697
		$output->writeln('');
698
		$output->writeln(
699
			'The address <info>' . $address . '</info> seems to reach your local Nextcloud.'
700
		);
701
702
		$helper = $this->getHelper('question');
703
		$output->writeln('');
704
		$question = new ConfirmationQuestion(
705
			'<info>Do you want to store this address in database ?</info> (y/N) ', false, '/^(y|Y)/i'
706
		);
707
708
		if (!$helper->ask($input, $output, $question)) {
709
			$output->writeln('Configuration NOT saved');
710
711
			return;
712
		}
713
714
		$this->configService->setAppValue(ConfigService::FORCE_NC_BASE, $address);
715
		$output->writeln(
716
			'New configuration <info>' . Application::APP_ID . '.' . ConfigService::FORCE_NC_BASE . '=\''
717
			. $address . '\'</info> stored in database'
718
		);
719
	}
720
721
722
	/**
723
	 * @param string $test
724
	 *
725
	 * @return array
726
	 * @throws Exception
727
	 */
728
	private function parseAddress(string $test): array {
729
		$scheme = parse_url($test, PHP_URL_SCHEME);
730
		$cloudId = parse_url($test, PHP_URL_HOST);
731
		$cloudIdPort = parse_url($test, PHP_URL_PORT);
732
733
		if (is_null($scheme) || is_null($cloudId)) {
734
			throw new Exception();
735
		}
736
737
		if (!is_null($cloudIdPort)) {
738
			$cloudId = $cloudId . ':' . $cloudIdPort;
739
		}
740
741
		return [$scheme, $cloudId];
742
	}
743
744
}
745
746