Completed
Push — master ( 6a3d7a...383329 )
by Maxence
03:05 queued 10s
created

CirclesConfig::filterValidConfig()   A

Complexity

Conditions 3
Paths 4

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 3
nc 4
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
6
/**
7
 * Circles - Bring cloud-users closer together.
8
 *
9
 * This file is licensed under the Affero General Public License version 3 or
10
 * later. See the COPYING file.
11
 *
12
 * @author Maxence Lange <[email protected]>
13
 * @copyright 2021
14
 * @license GNU AGPL version 3 or any later version
15
 *
16
 * This program is free software: you can redistribute it and/or modify
17
 * it under the terms of the GNU Affero General Public License as
18
 * published by the Free Software Foundation, either version 3 of the
19
 * License, or (at your option) any later version.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
 * GNU Affero General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU Affero General Public License
27
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
28
 *
29
 */
30
31
32
namespace OCA\Circles\Command;
33
34
use daita\MySmallPhpTools\Exceptions\InvalidItemException;
35
use daita\MySmallPhpTools\Exceptions\RequestNetworkException;
36
use daita\MySmallPhpTools\Exceptions\SignatoryException;
37
use OC\Core\Command\Base;
38
use OCA\Circles\Exceptions\CircleNotFoundException;
39
use OCA\Circles\Exceptions\FederatedEventException;
40
use OCA\Circles\Exceptions\FederatedItemException;
41
use OCA\Circles\Exceptions\FederatedUserException;
42
use OCA\Circles\Exceptions\FederatedUserNotFoundException;
43
use OCA\Circles\Exceptions\InitiatorNotConfirmedException;
44
use OCA\Circles\Exceptions\InitiatorNotFoundException;
45
use OCA\Circles\Exceptions\InvalidIdException;
46
use OCA\Circles\Exceptions\MemberNotFoundException;
47
use OCA\Circles\Exceptions\OwnerNotFoundException;
48
use OCA\Circles\Exceptions\RemoteInstanceException;
49
use OCA\Circles\Exceptions\RemoteNotFoundException;
50
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
51
use OCA\Circles\Exceptions\RequestBuilderException;
52
use OCA\Circles\Exceptions\SingleCircleNotFoundException;
53
use OCA\Circles\Exceptions\UnknownRemoteException;
54
use OCA\Circles\Exceptions\UserTypeNotFoundException;
55
use OCA\Circles\Model\Circle;
56
use OCA\Circles\Model\Member;
57
use OCA\Circles\Service\CircleService;
58
use OCA\Circles\Service\FederatedUserService;
59
use Symfony\Component\Console\Exception\InvalidArgumentException;
60
use Symfony\Component\Console\Input\InputArgument;
61
use Symfony\Component\Console\Input\InputInterface;
62
use Symfony\Component\Console\Input\InputOption;
63
use Symfony\Component\Console\Output\OutputInterface;
64
65
66
/**
67
 * Class CirclesConfig
68
 *
69
 * @package OCA\Circles\Command
70
 */
71
class CirclesConfig extends Base {
72
73
74
	/** @var FederatedUserService */
75
	private $federatedUserService;
76
77
	/** @var CircleService */
78
	private $circleService;
79
80
81
	/**
82
	 * CirclesConfig constructor.
83
	 *
84
	 * @param FederatedUserService $federatedUserService
85
	 * @param CircleService $circlesService
86
	 */
87
	public function __construct(FederatedUserService $federatedUserService, CircleService $circlesService) {
88
		parent::__construct();
89
90
		$this->federatedUserService = $federatedUserService;
91
		$this->circleService = $circlesService;
92
	}
93
94
95
	/**
96
	 *
97
	 */
98 View Code Duplication
	protected function configure() {
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...
99
		parent::configure();
100
		$this->setName('circles:manage:config')
101
			 ->setDescription('edit config/type of a Circle')
102
			 ->addArgument('circle_id', InputArgument::REQUIRED, 'ID of the circle')
103
			 ->addArgument(
104
				 'config', InputArgument::IS_ARRAY,
105
				 'list of value to change in the configuration of the Circle'
106
			 )
107
			 ->addOption('initiator', '', InputOption::VALUE_REQUIRED, 'set an initiator to the request', '')
108
			 ->addOption('initiator-type', '', InputOption::VALUE_REQUIRED, 'set initiator type', '0')
109
			 ->addOption('status-code', '', InputOption::VALUE_NONE, 'display status code on exception');
110
	}
111
112
113
	/**
114
	 * @param InputInterface $input
115
	 * @param OutputInterface $output
116
	 *
117
	 * @return int
118
	 * @throws FederatedEventException
119
	 * @throws FederatedItemException
120
	 * @throws InitiatorNotFoundException
121
	 * @throws RequestBuilderException
122
	 * @throws CircleNotFoundException
123
	 * @throws FederatedUserException
124
	 * @throws FederatedUserNotFoundException
125
	 * @throws InitiatorNotConfirmedException
126
	 * @throws InvalidIdException
127
	 * @throws MemberNotFoundException
128
	 * @throws OwnerNotFoundException
129
	 * @throws RemoteInstanceException
130
	 * @throws RemoteNotFoundException
131
	 * @throws RemoteResourceNotFoundException
132
	 * @throws SingleCircleNotFoundException
133
	 * @throws UnknownRemoteException
134
	 * @throws UserTypeNotFoundException
135
	 */
136
	protected function execute(InputInterface $input, OutputInterface $output): int {
137
		$circleId = (string)$input->getArgument('circle_id');
138
139
		try {
140
			$this->federatedUserService->commandLineInitiator(
141
				$input->getOption('initiator'),
142
				Member::parseTypeString($input->getOption('initiator-type')),
143
				$circleId,
144
				false
145
			);
146
147
			$circle = $this->circleService->getCircle($circleId);
148
149
			if (empty($input->getArgument('config'))) {
150
				$output->writeln(
151
					json_encode(Circle::getCircleFlags($circle, Circle::FLAGS_LONG), JSON_PRETTY_PRINT)
152
				);
153
154
				return 0;
155
			}
156
157
			$new = $this->generateConfig($circle, $input->getArgument('config'));
158
			$outcome = $this->circleService->updateConfig($circleId, $new);
159
		} catch (FederatedItemException $e) {
160
			if ($input->getOption('status-code')) {
161
				throw new FederatedItemException(
162
					' [' . get_class($e) . ', ' . $e->getStatus() . ']' . "\n" . $e->getMessage()
163
				);
164
			}
165
166
			throw $e;
167
		}
168
169
		if (strtolower($input->getOption('output')) === 'json') {
170
			$output->writeln(json_encode($outcome, JSON_PRETTY_PRINT));
171
		}
172
173
		return 0;
174
	}
175
176
177
	/**
178
	 * @param Circle $circle
179
	 * @param array $listing
180
	 *
181
	 * @return int
182
	 */
183
	private function generateConfig(Circle $circle, array $listing): int {
184
		$current = clone $circle;
185
		$valid = $this->filterValidConfig($current);
186
		foreach ($listing as $item) {
187
			$add = true;
188
			if (substr($item, 0, 1) === '_') {
189
				$add = false;
190
				$item = substr($item, 1);
191
			}
192
193
			$value = array_search(strtoupper($item), $valid);
194
			if (!$value) {
195
				throw new InvalidArgumentException(
196
					'Invalid config \'' . $item . '\'. Available values: '
197
					. implode(', ', array_values($valid)) . '. '
198
					. 'To disable a config, start the value with an underscore'
199
				);
200
			}
201
202
			if ($add) {
203
				$current->addConfig($value);
204
			} else {
205
				$current->remConfig($value);
206
			}
207
		}
208
209
		return $current->getConfig();
210
	}
211
212
213
	private function filterValidConfig(Circle $circle): array {
214
		$listing = Circle::$DEF_CFG;
215
		$filters = Circle::$DEF_CFG_CORE_FILTER;
216
		if (!$circle->isConfig(Circle::CFG_SYSTEM)) {
217
			$filters = array_merge($filters, Circle::$DEF_CFG_SYSTEM_FILTER);
218
		}
219
220
		foreach ($filters as $filter) {
221
			unset($listing[$filter]);
222
		}
223
224
		array_walk(
225
			$listing,
226
			function(string &$v): void {
227
				list(, $long) = explode('|', $v);
228
				$v = strtoupper(str_replace(' ', '', $long));
229
			}
230
		);
231
232
		return $listing;
233
	}
234
235
}
236
237