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

generateLimitPersonal()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 9.7333
c 0
b 0
f 0
cc 3
nc 3
nop 4
1
<?php
2
3
/**
4
 * Circles - Bring cloud-users closer together.
5
 *
6
 * This file is licensed under the Affero General Public License version 3 or
7
 * later. See the COPYING file.
8
 *
9
 * @author Maxence Lange <[email protected]>
10
 * @copyright 2017
11
 * @license GNU AGPL version 3 or any later version
12
 *
13
 * This program is free software: you can redistribute it and/or modify
14
 * it under the terms of the GNU Affero General Public License as
15
 * published by the Free Software Foundation, either version 3 of the
16
 * License, or (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU Affero General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU Affero General Public License
24
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
25
 *
26
 */
27
28
namespace OCA\Circles\Db;
29
30
31
use Doctrine\DBAL\Query\QueryBuilder;
32
use OCA\Circles\Exceptions\ConfigNoCircleAvailableException;
33
use OCA\Circles\Model\DeprecatedCircle;
34
use OCA\Circles\Model\DeprecatedMember;
35
use OCA\Circles\Service\ConfigService;
36
use OCA\Circles\Service\MiscService;
37
use OCA\Circles\Service\TimezoneService;
38
use OCP\DB\QueryBuilder\ICompositeExpression;
39
use OCP\DB\QueryBuilder\IQueryBuilder;
40
use OCP\IDBConnection;
41
use OCP\IL10N;
42
43
class DeprecatedCirclesRequestBuilder extends DeprecatedRequestBuilder {
44
45
46
	/** @var DeprecatedMembersRequest */
47
	protected $membersRequest;
48
49
	/**
50
	 * CirclesRequestBuilder constructor.
51
	 *
52
	 * {@inheritdoc}
53
	 * @param DeprecatedMembersRequest $membersRequest
54
	 */
55 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...
56
		IL10N $l10n, IDBConnection $connection, DeprecatedMembersRequest $membersRequest,
57
		ConfigService $configService, TimezoneService $timezoneService, MiscService $miscService
58
	) {
59
		parent::__construct($l10n, $connection, $configService, $timezoneService, $miscService);
60
		$this->membersRequest = $membersRequest;
61
	}
62
63
64
	/**
65
	 * Limit the search to a non-personal circle
66
	 *
67
	 * @param IQueryBuilder $qb
68
	 */
69
	protected function limitToNonPersonalCircle(IQueryBuilder $qb) {
70
		$expr = $qb->expr();
71
72
		$qb->andWhere(
73
			$expr->neq('c.type', $qb->createNamedParameter(DeprecatedCircle::CIRCLES_PERSONAL))
74
		);
75
	}
76
77
78
	/**
79
	 * @param IQueryBuilder $qb
80
	 * @param string $userId
81
	 * @param string $circleUniqueId
82
	 * @param $type
83
	 * @param $name
84
	 * @param bool $forceAll
85
	 *
86
	 * @throws ConfigNoCircleAvailableException
87
	 */
88
	protected function limitRegardingCircleType(
89
		IQueryBuilder $qb, string $userId, $circleUniqueId, int $type,
90
		string $name, bool $forceAll = false
91
	) {
92
		$orTypes = $this->generateLimit($qb, $circleUniqueId, $userId, $type, $name, $forceAll);
93
		if (sizeof($orTypes) === 0) {
94
			throw new ConfigNoCircleAvailableException(
95
				$this->l10n->t(
96
					'You cannot use the Circles Application until your administrator has allowed at least one type of circles'
97
				)
98
			);
99
		}
100
101
		$orXTypes = $qb->expr()
102
					   ->orX();
103
		foreach ($orTypes as $orType) {
104
			$orXTypes->add($orType);
105
		}
106
107
		$qb->andWhere($orXTypes);
108
	}
109
110
111
	/**
112
	 * @param IQueryBuilder $qb
113
	 * @param string $circleUniqueId
114
	 * @param $userId
115
	 * @param $type
116
	 * @param $name
117
	 * @param bool $forceAll
118
	 *
119
	 * @return array
120
	 */
121
	private function generateLimit(
122
		IQueryBuilder $qb, $circleUniqueId, $userId, $type, $name, $forceAll = false
123
	) {
124
		$orTypes = [];
125
		array_push($orTypes, $this->generateLimitPersonal($qb, $userId, $type, $forceAll));
126
		array_push($orTypes, $this->generateLimitSecret($qb, $circleUniqueId, $type, $name));
127
		array_push($orTypes, $this->generateLimitClosed($qb, $type));
128
		array_push($orTypes, $this->generateLimitPublic($qb, $type));
129
130
		return array_filter($orTypes);
131
	}
132
133
134
	/**
135
	 * @param IQueryBuilder $qb
136
	 * @param int|string $userId
137
	 * @param int $type
138
	 * @param bool $forceAll
139
	 *
140
	 * @return ICompositeExpression
141
	 */
142
	private function generateLimitPersonal(IQueryBuilder $qb, $userId, $type, $forceAll = false) {
143
		if (!(DeprecatedCircle::CIRCLES_PERSONAL & (int)$type)) {
144
			return null;
145
		}
146
		$expr = $qb->expr();
147
148
		$andX = $expr->andX();
149
		$andX->add($expr->eq('c.type', $qb->createNamedParameter(DeprecatedCircle::CIRCLES_PERSONAL)));
150
		$andX->add($expr->eq('o.instance', $qb->createNamedParameter('')));
151
152
		if (!$forceAll) {
153
			$andX->add($expr->eq('o.user_id', $qb->createNamedParameter((string)$userId)));
154
		}
155
156
		return $andX;
157
	}
158
159
160
	/**
161
	 * @param IQueryBuilder $qb
162
	 * @param string $circleUniqueId
163
	 * @param int $type
164
	 * @param string $name
165
	 *
166
	 * @return string
167
	 */
168
	private function generateLimitSecret(IQueryBuilder $qb, $circleUniqueId, $type, $name) {
169
		if (!(DeprecatedCircle::CIRCLES_SECRET & (int)$type)) {
170
			return null;
171
		}
172
		$expr = $qb->expr();
173
174
		$orX = $expr->orX($expr->gte('u.level', $qb->createNamedParameter(DeprecatedMember::LEVEL_MEMBER)));
175
		$orX->add($expr->eq('c.name', $qb->createNamedParameter($name)))
176
			->add($expr->eq('c.unique_id', $qb->createNamedParameter($circleUniqueId)));
177
178
		if ($name !== '') {
179
			$orX->add($expr->eq('c.alt_name', $qb->createNamedParameter($name)));
180
		}
181
182
		if ($this->leftJoinedNCGroupAndUser) {
183
			$orX->add($expr->gte('g.level', $qb->createNamedParameter(DeprecatedMember::LEVEL_MEMBER)));
184
		}
185
186
		/** @noinspection PhpMethodParametersCountMismatchInspection */
187
		return $expr->andX(
188
			$expr->eq('c.type', $qb->createNamedParameter(DeprecatedCircle::CIRCLES_SECRET)),
189
			$expr->orX($orX)
190
		);
191
	}
192
193
194
	/**
195
	 * @param IQueryBuilder $qb
196
	 * @param int $type
197
	 *
198
	 * @return string
199
	 */
200 View Code Duplication
	private function generateLimitClosed(IQueryBuilder $qb, $type) {
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...
201
		if (!(DeprecatedCircle::CIRCLES_CLOSED & (int)$type)) {
202
			return null;
203
		}
204
205
		return $qb->expr()
206
				  ->eq(
207
					  'c.type',
208
					  $qb->createNamedParameter(DeprecatedCircle::CIRCLES_CLOSED)
209
				  );
210
	}
211
212
213
	/**
214
	 * @param IQueryBuilder $qb
215
	 * @param int $type
216
	 *
217
	 * @return string
218
	 */
219 View Code Duplication
	private function generateLimitPublic(IQueryBuilder $qb, $type) {
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...
220
		if (!(DeprecatedCircle::CIRCLES_PUBLIC & (int)$type)) {
221
			return null;
222
		}
223
224
		return $qb->expr()
225
				  ->eq(
226
					  'c.type',
227
					  $qb->createNamedParameter(DeprecatedCircle::CIRCLES_PUBLIC)
228
				  );
229
	}
230
231
232
	/**
233
	 * add a request to the members list, using the current user ID.
234
	 * will returns level and stuff.
235
	 *
236
	 * @param IQueryBuilder $qb
237
	 * @param string $userId
238
	 * @param int $type
239
	 * @param string $instanceId
240
	 */
241
	public function leftJoinUserIdAsViewer(IQueryBuilder $qb, string $userId, int $type, string $instanceId
242
	) {
243
		if ($qb->getType() !== QueryBuilder::SELECT) {
244
			return;
245
		}
246
247
		$expr = $qb->expr();
248
		$pf = '' . $this->default_select_alias . '.';
249
250
		/** @noinspection PhpMethodParametersCountMismatchInspection */
251
		$qb->selectAlias('u.user_id', 'viewer_userid')
252
		   ->selectAlias('u.user_type', 'viewer_type')
253
		   ->selectAlias('u.instance', 'viewer_instance')
254
		   ->selectAlias('u.status', 'viewer_status')
255
		   ->selectAlias('u.member_id', 'viewer_member_id')
256
		   ->selectAlias('u.cached_name', 'viewer_cached_name')
257
		   ->selectAlias('u.cached_update', 'viewer_cached_update')
258
		   ->selectAlias('u.level', 'viewer_level')
259
		   ->leftJoin(
260
			   $this->default_select_alias, DeprecatedRequestBuilder::TABLE_MEMBERS, 'u',
261
			   $expr->andX(
262
				   $expr->eq('u.circle_id', $pf . 'unique_id'),
263
				   $expr->eq('u.user_id', $qb->createNamedParameter($userId)),
264
				   $expr->eq('u.instance', $qb->createNamedParameter($instanceId)),
265
				   $expr->eq('u.user_type', $qb->createNamedParameter($type))
266
			   )
267
		   );
268
	}
269
270
271
	/**
272
	 * Left Join members table to get the owner of the circle.
273
	 *
274
	 * @param IQueryBuilder $qb
275
	 * @param string $ownerId
276
	 */
277
	public function leftJoinOwner(IQueryBuilder $qb, string $ownerId = '') {
278
279
		if ($qb->getType() !== QueryBuilder::SELECT) {
280
			return;
281
		}
282
283
		$expr = $qb->expr();
284
		$pf = $this->default_select_alias . '.';
285
286
		/** @noinspection PhpMethodParametersCountMismatchInspection */
287
		$qb->selectAlias('o.user_id', 'owner_userid')
288
		   ->selectAlias('o.member_id', 'owner_member_id')
289
		   ->selectAlias('o.instance', 'owner_instance')
290
		   ->selectAlias('o.cached_name', 'owner_cached_name')
291
		   ->selectAlias('o.cached_update', 'owner_cached_update')
292
		   ->selectAlias('o.status', 'owner_status')
293
		   ->selectAlias('o.level', 'owner_level')
294
		   ->leftJoin(
295
			   $this->default_select_alias, DeprecatedRequestBuilder::TABLE_MEMBERS, 'o',
296
			   $expr->andX(
297
				   $expr->eq('o.circle_id', $pf . 'unique_id'),
298
				   $expr->eq('o.level', $qb->createNamedParameter(DeprecatedMember::LEVEL_OWNER)),
299
				   $expr->eq('o.user_type', $qb->createNamedParameter(DeprecatedMember::TYPE_USER))
300
			   )
301
		   );
302
303
		if ($ownerId !== '') {
304
			$qb->andWhere($expr->eq('o.user_id', $qb->createNamedParameter($ownerId)));
305
		}
306
	}
307
308
309
	/**
310
	 * Base of the Sql Insert request for Shares
311
	 *
312
	 *
313
	 * @return IQueryBuilder
314
	 */
315 View Code Duplication
	protected function getCirclesInsertSql() {
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...
316
		$qb = $this->dbConnection->getQueryBuilder();
317
		$qb->insert(self::TABLE_CIRCLES)
318
		   ->setValue('creation', $qb->createNamedParameter($this->timezoneService->getUTCDate()));
319
320
		return $qb;
321
	}
322
323
324
	/**
325
	 * Base of the Sql Update request for Shares
326
	 *
327
	 * @param int $uniqueId
328
	 *
329
	 * @return IQueryBuilder
330
	 */
331 View Code Duplication
	protected function getCirclesUpdateSql($uniqueId) {
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...
332
		$qb = $this->dbConnection->getQueryBuilder();
333
		$qb->update(self::TABLE_CIRCLES)
334
		   ->where(
335
			   $qb->expr()
336
				  ->eq('unique_id', $qb->createNamedParameter($uniqueId))
337
		   );
338
339
		return $qb;
340
	}
341
342
343
	/**
344
	 * Base of the Sql Delete request
345
	 *
346
	 * @param string $circleUniqueId
347
	 *
348
	 * @return IQueryBuilder
349
	 */
350 View Code Duplication
	protected function getCirclesDeleteSql($circleUniqueId) {
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...
351
		$qb = $this->dbConnection->getQueryBuilder();
352
		$qb->delete(self::TABLE_CIRCLES)
353
		   ->where(
354
			   $qb->expr()
355
				  ->eq('unique_id', $qb->createNamedParameter($circleUniqueId))
356
		   );
357
358
		return $qb;
359
	}
360
361
362
	/**
363
	 * @return IQueryBuilder
364
	 */
365
	protected function getCirclesSelectSql() {
366
		$qb = $this->dbConnection->getQueryBuilder();
367
368
		/** @noinspection PhpMethodParametersCountMismatchInspection */
369
		$qb->selectDistinct('c.unique_id')
370
		   ->addSelect(
371
			   'c.id', 'c.name', 'c.alt_name', 'c.description', 'c.settings', 'c.type', 'contact_addressbook',
372
			   'contact_groupname', 'c.creation'
373
		   )
374
		   ->from(DeprecatedRequestBuilder::TABLE_CIRCLES, 'c');
375
		$this->default_select_alias = 'c';
376
377
		return $qb;
378
	}
379
380
381
	/**
382
	 * @param array $data
383
	 * @param bool $allSettings
384
	 *
385
	 * @return DeprecatedCircle
386
	 */
387
	protected function parseCirclesSelectSql($data, bool $allSettings = false) {
388
389
		$circle = new DeprecatedCircle();
390
		$circle->setId($data['id']);
391
		$circle->setUniqueId($data['unique_id']);
392
		$circle->setName($data['name']);
393
		$circle->setAltName($data['alt_name']);
394
		$circle->setDescription($data['description']);
395
		if ($data['contact_addressbook'] !== null) {
396
			$circle->setContactAddressBook($data['contact_addressbook']);
397
		}
398
		if ($data['contact_groupname'] !== null) {
399
			$circle->setContactGroupName($data['contact_groupname']);
400
		}
401
		$circle->setSettings($data['settings'], $allSettings);
402
		$circle->setType($data['type']);
403
		$circle->setCreation($data['creation']);
404
405 View Code Duplication
		if (key_exists('viewer_level', $data)) {
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...
406
			$user = new DeprecatedMember($data['viewer_userid'], DeprecatedMember::TYPE_USER, $circle->getUniqueId());
407
			$user->setStatus($data['viewer_status']);
408
			$user->setMemberId($data['viewer_member_id']);
409
			$user->setCachedName($data['viewer_cached_name']);
410
			$user->setType($data['viewer_type']);
411
			$user->setInstance($data['viewer_instance']);
412
			$user->setLevel($data['viewer_level']);
413
			$circle->setViewer($user);
414
		}
415
416 View Code Duplication
		if (key_exists('owner_level', $data)) {
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...
417
			$owner = new DeprecatedMember($data['owner_userid'], DeprecatedMember::TYPE_USER, $circle->getUniqueId());
418
			$owner->setCachedName($data['owner_cached_name']);
419
			$owner->setMemberId($data['owner_member_id']);
420
			$owner->setStatus($data['owner_status']);
421
			$owner->setInstance($data['owner_instance']);
422
			$owner->setLevel($data['owner_level']);
423
			$circle->setOwner($owner);
424
		}
425
426
		return $circle;
427
	}
428
429
430
}
431