Completed
Push — master ( c3a501...d1d18b )
by Maxence
01:44
created

CirclesTest   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 196
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 0
Metric Value
wmc 18
lcom 1
cbo 9
dl 0
loc 196
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 1
A configure() 0 7 1
C execute() 0 62 10
A testRequest() 0 20 3
A saveUrl() 0 28 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\NC19Request;
34
use daita\MySmallPhpTools\Model\Request;
35
use daita\MySmallPhpTools\Traits\Nextcloud\TNC19Request;
36
use daita\MySmallPhpTools\Traits\TArrayTools;
37
use Exception;
38
use OC\Core\Command\Base;
39
use OCA\Circles\AppInfo\Application;
40
use OCA\Circles\Model\GlobalScale\GSEvent;
41
use OCA\Circles\Service\ConfigService;
42
use OCA\Circles\Service\GlobalScaleService;
43
use OCA\Circles\Service\GSUpstreamService;
44
use OCP\IL10N;
45
use OCP\IURLGenerator;
46
use Symfony\Component\Console\Input\InputInterface;
47
use Symfony\Component\Console\Input\InputOption;
48
use Symfony\Component\Console\Output\OutputInterface;
49
use Symfony\Component\Console\Question\ConfirmationQuestion;
50
51
52
/**
53
 * Class CirclesList
54
 *
55
 * @package OCA\Circles\Command
56
 */
57
class CirclesTest extends Base {
58
59
60
	use TArrayTools;
61
	use TNC19Request;
62
63
64
	/** @var IL10N */
65
	private $l10n;
66
67
	/** @var IURLGenerator */
68
	private $urlGenerator;
69
70
	/** @var GlobalScaleService */
71
	private $globalScaleService;
72
73
	/** @var GSUpstreamService */
74
	private $gsUpstreamService;
75
76
	/** @var ConfigService */
77
	private $configService;
78
79
80
	/** @var int */
81
	private $delay = 5;
82
83
84
	/**
85
	 * CirclesList constructor.
86
	 *
87
	 * @param IL10N $l10n
88
	 * @param IURLGenerator $urlGenerator
89
	 * @param GlobalScaleService $globalScaleService
90
	 * @param GSUpstreamService $gsUpstreamService
91
	 * @param ConfigService $configService
92
	 */
93
	public function __construct(
94
		IL10N $l10n, IURLGenerator $urlGenerator, GlobalScaleService $globalScaleService,
95
		GSUpstreamService $gsUpstreamService, ConfigService $configService
96
	) {
97
		parent::__construct();
98
99
		$this->l10n = $l10n;
100
		$this->urlGenerator = $urlGenerator;
101
		$this->gsUpstreamService = $gsUpstreamService;
102
		$this->globalScaleService = $globalScaleService;
103
		$this->configService = $configService;
104
	}
105
106
107
	protected function configure() {
108
		parent::configure();
109
		$this->setName('circles:test')
110
			 ->setDescription('testing some features')
111
			 ->addOption('delay', 'd', InputOption::VALUE_REQUIRED, 'delay before checking result')
112
			 ->addOption('url', '', InputOption::VALUE_REQUIRED, 'specify a source url', '');
113
	}
114
115
116
	/**
117
	 * @param InputInterface $input
118
	 * @param OutputInterface $output
119
	 *
120
	 * @return int
121
	 * @throws Exception
122
	 */
123
	protected function execute(InputInterface $input, OutputInterface $output): int {
124
		if ($input->getOption('delay')) {
125
			$this->delay = (int)$input->getOption('delay');
126
		}
127
128
		$this->configService->setAppValue(ConfigService::TEST_NC_BASE, '');
129
		$this->configService->setAppValue(ConfigService::TEST_NC_BASE, $input->getOption('url'));
130
131
		if (!$this->testRequest($output, 'GET', 'core.CSRFToken.index')) {
132
			$this->configService->setAppValue(ConfigService::TEST_NC_BASE, '');
133
134
			return 0;
135
		}
136
137
		if (!$this->testRequest(
138
			$output, 'POST', 'circles.GlobalScale.asyncBroadcast',
139
			['token' => 'test-dummy-token']
140
		)) {
141
			$this->configService->setAppValue(ConfigService::TEST_NC_BASE, '');
142
143
			return 0;
144
		}
145
146
		$test = new GSEvent(GSEvent::TEST, true, true);
147
		$test->setAsync(true);
148
		$token = $this->gsUpstreamService->newEvent($test);
149
150
		$output->writeln('- Async request is sent, now waiting ' . $this->delay . ' seconds');
151
		sleep($this->delay);
152
		$output->writeln('- Pause is over, checking results for ' . $token);
153
154
		$wrappers = $this->gsUpstreamService->getEventsByToken($token);
155
156
		$result = [];
157
		$instances = array_merge($this->globalScaleService->getInstances(true));
158
		foreach ($wrappers as $wrapper) {
159
			$result[$wrapper->getInstance()] = $wrapper->getEvent();
160
		}
161
162
		$localLooksGood = false;
163
		foreach ($instances as $instance) {
164
			$output->write($instance . ' ');
165
			if (array_key_exists($instance, $result)
166
				&& $result[$instance]->getResult()
167
									 ->gInt('status') === 1) {
168
				$output->writeln('<info>ok</info>');
169
				if ($this->configService->isLocalInstance($instance)) {
170
					$localLooksGood = true;
171
				}
172
			} else {
173
				$output->writeln('<error>fail</error>');
174
			}
175
		}
176
177
		$this->configService->setAppValue(ConfigService::TEST_NC_BASE, '');
178
179
		if ($localLooksGood) {
180
			$this->saveUrl($input, $output, $input->getOption('url'));
181
		}
182
183
		return 0;
184
	}
185
186
187
	/**
188
	 * @param OutputInterface $o
189
	 * @param string $type
190
	 * @param string $route
191
	 * @param array $args
192
	 *
193
	 * @return bool
194
	 * @throws RequestNetworkException
195
	 */
196
	private function testRequest(OutputInterface $o, string $type, string $route, array $args = []): bool {
197
		$request = new NC19Request('', Request::type($type));
198
		$this->configService->configureRequest($request, $route, $args);
199
		$request->setFollowLocation(false);
200
201
		$o->write('- ' . $type . ' request on ' . $request->getCompleteUrl() . ': ');
202
		$this->doRequest($request);
203
204
		$color = 'error';
205
		if ($request->getResultCode() === 200) {
206
			$color = 'info';
207
		}
208
		$o->writeln('<' . $color . '>' . $request->getResultCode() . '</' . $color . '>');
209
210
		if ($request->getResultCode() === 200) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return $request->getResultCode() === 200;.
Loading history...
211
			return true;
212
		}
213
214
		return false;
215
	}
216
217
218
	/**
219
	 * @param InputInterface $input
220
	 * @param OutputInterface $output
221
	 * @param string $address
222
	 */
223
	private function saveUrl(InputInterface $input, OutputInterface $output, string $address): void {
224
		if ($address === '') {
225
			return;
226
		}
227
228
		$output->writeln('');
229
		$output->writeln(
230
			'The address <info>' . $address . '</info> seems to reach your local Nextcloud.'
231
		);
232
233
		$helper = $this->getHelper('question');
234
		$output->writeln('');
235
		$question = new ConfirmationQuestion(
236
			'<info>Do you want to store this address in database ?</info> (y/N) ', false, '/^(y|Y)/i'
237
		);
238
239
		if (!$helper->ask($input, $output, $question)) {
240
			$output->writeln('Configuration NOT saved');
241
242
			return;
243
		}
244
245
		$this->configService->setAppValue(ConfigService::FORCE_NC_BASE, $address);
246
		$output->writeln(
247
			'New configuration <info>' . Application::APP_NAME . '.' . ConfigService::FORCE_NC_BASE . '=\''
248
			. $address . '\'</info> stored in database'
249
		);
250
	}
251
252
}
253
254