Completed
Pull Request — master (#551)
by Maxence
02:35
created

CirclesMemberships::displayLeaf()   B

Complexity

Conditions 7
Paths 12

Size

Total Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 32
rs 8.4746
c 0
b 0
f 0
cc 7
nc 12
nop 2
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\ItemNotFoundException;
36
use daita\MySmallPhpTools\Exceptions\RequestNetworkException;
37
use daita\MySmallPhpTools\Exceptions\SignatoryException;
38
use daita\MySmallPhpTools\Exceptions\UnknownTypeException;
39
use daita\MySmallPhpTools\Model\Nextcloud\nc21\NC21TreeNode;
40
use daita\MySmallPhpTools\Model\SimpleDataStore;
41
use daita\MySmallPhpTools\Traits\Nextcloud\nc21\TNC21ConsoleTree;
42
use daita\MySmallPhpTools\Traits\TArrayTools;
43
use OC\Core\Command\Base;
44
use OCA\Circles\Db\MemberRequest;
45
use OCA\Circles\Db\MembershipRequest;
46
use OCA\Circles\Exceptions\CircleNotFoundException;
47
use OCA\Circles\Exceptions\FederatedUserException;
48
use OCA\Circles\Exceptions\FederatedUserNotFoundException;
49
use OCA\Circles\Exceptions\InvalidIdException;
50
use OCA\Circles\Exceptions\OwnerNotFoundException;
51
use OCA\Circles\Exceptions\RemoteInstanceException;
52
use OCA\Circles\Exceptions\RemoteNotFoundException;
53
use OCA\Circles\Exceptions\RemoteResourceNotFoundException;
54
use OCA\Circles\Exceptions\UnknownRemoteException;
55
use OCA\Circles\Exceptions\UserTypeNotFoundException;
56
use OCA\Circles\Model\FederatedUser;
57
use OCA\Circles\Model\Member;
58
use OCA\Circles\Service\FederatedUserService;
59
use OCP\IUserManager;
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 CirclesMembershipsIndex
68
 *
69
 * @package OCA\Circles\Command
70
 */
71
class CirclesMemberships extends Base {
72
73
74
	use TArrayTools;
75
	use TNC21ConsoleTree;
76
77
78
	/** @var IUserManager */
79
	private $userManager;
80
81
	/** @var MemberRequest */
82
	private $memberRequest;
83
84
	/** @var MembershipRequest */
85
	private $membershipRequest;
86
87
	/** @var FederatedUserService */
88
	private $federatedUserService;
89
90
91
	/** @var array */
92
	private $knownId = [];
93
94
95
	/**
96
	 * CirclesList constructor.
97
	 *
98
	 * @param IUserManager $userManager
99
	 * @param MembershipRequest $membershipRequest
100
	 * @param MemberRequest $memberRequest
101
	 * @param FederatedUserService $federatedUserService
102
	 */
103
	public function __construct(
104
		IUserManager $userManager,
105
		MembershipRequest $membershipRequest,
106
		MemberRequest $memberRequest,
107
		FederatedUserService $federatedUserService
108
	) {
109
		parent::__construct();
110
		$this->userManager = $userManager;
111
		$this->memberRequest = $memberRequest;
112
		$this->membershipRequest = $membershipRequest;
113
		$this->federatedUserService = $federatedUserService;
114
	}
115
116
117
	protected function configure() {
118
		parent::configure();
119
		$this->setName('circles:memberships')
120
			 ->setDescription('index and display memberships for local and federated users')
121
			 ->addArgument('userId', InputArgument::OPTIONAL, 'userId to generate memberships', '')
122
			 ->addOption('all', '', InputOption::VALUE_NONE, 'index all local users')
123
			 ->addOption(
124
				 'type', '', InputOption::VALUE_REQUIRED, 'type of the user',
125
				 Member::$DEF_TYPE[Member::TYPE_USER]
126
			 );
127
	}
128
129
130
	/**
131
	 * @param InputInterface $input
132
	 * @param OutputInterface $output
133
	 *
134
	 * @return int
135
	 * @throws CircleNotFoundException
136
	 * @throws InvalidItemException
137
	 * @throws UserTypeNotFoundException
138
	 * @throws FederatedUserException
139
	 * @throws FederatedUserNotFoundException
140
	 * @throws InvalidIdException
141
	 * @throws OwnerNotFoundException
142
	 * @throws RemoteInstanceException
143
	 * @throws RemoteNotFoundException
144
	 * @throws RemoteResourceNotFoundException
145
	 * @throws UnknownRemoteException
146
	 * @throws RequestNetworkException
147
	 * @throws SignatoryException
148
	 */
149
	protected function execute(InputInterface $input, OutputInterface $output): int {
150
		$all = $input->getOption('all');
151
		$userId = $input->getArgument('userId');
152
153
		if (!$all && $userId === '') {
154
			$output->writeln('<error>specify a user, or use --all</error>');
155
156
			return 0;
157
		}
158
159
		$type = Member::parseTypeString($input->getOption('type'));
160
		$federatedUser = $this->federatedUserService->getFederatedUser($userId, (int)$type);
161
162
		$output->writeln('UserId: <info>' . $federatedUser->getUserId() . '</info>');
163
		$output->writeln('Instance: <info>' . $federatedUser->getInstance() . '</info>');
164
		$output->writeln('UserType: <info>' . Member::$DEF_TYPE[$federatedUser->getUserType()] . '</info>');
165
		$output->writeln('SingleId: <info>' . $federatedUser->getSingleId() . '</info>');
166
		$output->writeln('');
167
168
		$tree = new NC21TreeNode(null, new SimpleDataStore(['federatedUser' => $federatedUser]));
169
		$this->generateMemberships($federatedUser->getSingleId(), $tree);
170
		$this->drawTree($tree, [$this, 'displayLeaf'], 3);
171
172
		return 0;
173
	}
174
175
176
	/**
177
	 * @param string $id
178
	 * @param NC21TreeNode $tree
179
	 * @param array $knownIds
180
	 */
181
	private function generateMemberships(string $id, NC21TreeNode $tree, array $knownIds = []) {
182
		$members = $this->memberRequest->getMembersBySingleId($id);
183
		foreach ($members as $member) {
184
			$item = new NC21TreeNode(
185
				$tree, new SimpleDataStore(
186
						 [
187
							 'member'  => $member,
188
							 'cycling' => in_array($member->getCircleId(), $knownIds)
189
						 ]
190
					 )
191
			);
192
			if (in_array($member->getCircleId(), $knownIds)) {
193
				continue;
194
			}
195
			$knownIds[] = $id;
196
			$this->generateMemberships($member->getCircleId(), $item, $knownIds);
197
			$knownIds = [];
198
		}
199
	}
200
201
202
	/**
203
	 * @param SimpleDataStore $data
204
	 * @param int $line
205
	 *
206
	 * @return string
207
	 */
208
	public function displayLeaf(SimpleDataStore $data, int $line): string {
209
		if ($line === 2) {
210
			return '';
211
		}
212
213
		if ($line === 3) {
214
			$cycle = '';
215
			if ($data->gBool('cycling')) {
216
				$cycle = ' (loop detected)';
217
			}
218
			return $cycle;
219
		}
220
		try {
221
222
			if ($data->hasKey('federatedUser')) {
223
				/** @var FederatedUser $federatedUser */
224
				$federatedUser = $data->gObj('federatedUser', FederatedUser::class);
225
226
				return '<info>' . $federatedUser->getSingleId() . '</info>';
227
			}
228
229
			if ($data->hasKey('member')) {
230
				/** @var Member $member */
231
				$member = $data->gObj('member', Member::class);
232
233
				return ' <info>' . $member->getCircleId() . '</info>';
234
			}
235
		} catch (InvalidItemException | ItemNotFoundException | UnknownTypeException $e) {
236
		}
237
238
		return '';
239
	}
240
241
}
242
243