Completed
Push — master ( 3071ad...3723f6 )
by Maxence
03:35 queued 01:12
created

CirclesRequestBuilder::generateLimitHidden()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 24
rs 8.9713
cc 2
eloc 14
nc 2
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 OC\L10N\L10N;
33
use OCA\Circles\Exceptions\ConfigNoCircleAvailable;
34
use OCA\Circles\Model\Circle;
35
use OCA\Circles\Model\FederatedLink;
36
use OCA\Circles\Model\Member;
37
use OCA\Circles\Model\SharingFrame;
38
use OCA\Circles\Service\MiscService;
39
use OCP\DB\QueryBuilder\IQueryBuilder;
40
use OCP\IDBConnection;
41
42
class CirclesRequestBuilder extends CoreRequestBuilder {
43
44
45
	/** @var MembersRequest */
46
	protected $membersRequest;
47
48
	/**
49
	 * CirclesRequestBuilder constructor.
50
	 *
51
	 * {@inheritdoc}
52
	 * @param MembersRequest $membersRequest
53
	 */
54
	public function __construct(
55
		L10N $l10n, IDBConnection $connection, MembersRequest $membersRequest,
56
		MiscService $miscService
57
	) {
58
		parent::__construct($l10n, $connection, $miscService);
59
		$this->membersRequest = $membersRequest;
60
	}
61
62
63
	/**
64
	 * Left Join the Groups table
65
	 *
66
	 * @param IQueryBuilder $qb
67
	 * @param string $field
68
	 */
69
	protected function leftJoinGroups(& $qb, $field) {
70
		$expr = $qb->expr();
71
72
		$qb->leftJoin(
73
			$this->default_select_alias, CoreRequestBuilder::TABLE_GROUPS, 'g',
74
			$expr->eq($field, 'g.circle_id')
75
		);
76
	}
77
78
//
79
//	/**
80
//	 * Link to member (userId) of circle
81
//	 *
82
//	 * @param IQueryBuilder $qb
83
//	 * @param string $field
84
//	 */
85
//	protected function leftJoinMembers(& $qb, $field) {
86
//		$expr = $qb->expr();
87
//
88
//		$qb->leftJoin(
89
//			$this->default_select_alias, CoreRequestBuilder::TABLE_MEMBERS, 'm',
90
//			$expr->eq('m.circle_id', $field)
91
//		);
92
////		$qb->from(self::TABLE_MEMBERS, 'm')
93
////		   ->andWhere($expr->eq('m.circle_id', $field));
94
//	}
95
96
97
	/**
98
	 * Limit the search to a non-personal circle
99
	 *
100
	 * @param IQueryBuilder $qb
101
	 */
102
	protected function limitToNonPersonalCircle(IQueryBuilder &$qb) {
103
		$expr = $qb->expr();
104
105
		$qb->andWhere(
106
			$expr->neq('c.type', $qb->createNamedParameter(Circle::CIRCLES_PERSONAL))
107
		);
108
	}
109
110
111
	/**
112
	 * @param IQueryBuilder $qb
113
	 * @param $circleId
114
	 * @param $userId
115
	 * @param $type
116
	 * @param $name
117
	 *
118
	 * @throws ConfigNoCircleAvailable
119
	 */
120
	protected function limitRegardingCircleType(IQueryBuilder &$qb, $userId, $circleId, $type, $name
121
	) {
122
		$orTypes = $this->generateLimit($qb, $circleId, $userId, $type, $name);
123
		if (sizeof($orTypes) === 0) {
124
			throw new ConfigNoCircleAvailable(
125
				$this->l10n->t(
126
					'You cannot use the Circles Application until your administrator has allowed at least one type of circles'
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 111 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
127
				)
128
			);
129
		}
130
131
		$orXTypes = $qb->expr()
132
					   ->orX();
133
		foreach ($orTypes as $orType) {
134
			$orXTypes->add($orType);
135
		}
136
137
		$qb->andWhere($orXTypes);
138
	}
139
140
141
	/**
142
	 * @param IQueryBuilder $qb
143
	 * @param $circleId
144
	 * @param $userId
145
	 * @param $type
146
	 * @param $name
147
	 *
148
	 * @return array
149
	 */
150
	private function generateLimit(IQueryBuilder &$qb, $circleId, $userId, $type, $name) {
151
		$orTypes = [];
152
		array_push($orTypes, $this->generateLimitPersonal($qb, $userId, $type));
153
		array_push($orTypes, $this->generateLimitHidden($qb, $circleId, $type, $name));
154
		array_push($orTypes, $this->generateLimitPrivate($qb, $type));
155
		array_push($orTypes, $this->generateLimitPublic($qb, $type));
156
157
		return array_filter($orTypes);
158
	}
159
160
161
	/**
162
	 * @param IQueryBuilder $qb
163
	 * @param int|string $userId
164
	 * @param int $type
165
	 *
166
	 * @return \OCP\DB\QueryBuilder\ICompositeExpression
167
	 */
168
	private function generateLimitPersonal(IQueryBuilder $qb, $userId, $type) {
169
		if (!(Circle::CIRCLES_PERSONAL & (int)$type)) {
170
			return null;
171
		}
172
		$expr = $qb->expr();
173
174
		/** @noinspection PhpMethodParametersCountMismatchInspection */
175
		return $expr->andX(
176
			$expr->eq('c.type', $qb->createNamedParameter(Circle::CIRCLES_PERSONAL)),
177
			$expr->eq('o.user_id', $qb->createNamedParameter((string)$userId))
178
		);
179
	}
180
181
182
	/**
183
	 * @param IQueryBuilder $qb
184
	 * @param int $circleId
185
	 * @param int $type
186
	 * @param string $name
187
	 *
188
	 * @return string
189
	 */
190
	private function generateLimitHidden(IQueryBuilder $qb, $circleId, $type, $name) {
191
		if (!(Circle::CIRCLES_HIDDEN & (int)$type)) {
192
			return null;
193
		}
194
		$expr = $qb->expr();
195
196
		/** @noinspection PhpMethodParametersCountMismatchInspection */
197
		$sqb = $expr->andX(
198
			$expr->eq('c.type', $qb->createNamedParameter(Circle::CIRCLES_HIDDEN)),
199
			$expr->orX(
200
				$expr->gte(
201
					'u.level', $qb->createNamedParameter(Member::LEVEL_MEMBER)
202
				),
203
				$expr->gte(
204
					'g.level', $qb->createNamedParameter(Member::LEVEL_MEMBER)
205
				),
206
				// TODO: Replace search on CircleID By a search on UniqueID
207
				$expr->eq('c.id', $qb->createNamedParameter($circleId)),
208
				$expr->eq('c.name', $qb->createNamedParameter($name))
209
			)
210
		);
211
212
		return $sqb;
213
	}
214
215
216
	/**
217
	 * @param IQueryBuilder $qb
218
	 * @param int $type
219
	 *
220
	 * @return string
221
	 */
222 View Code Duplication
	private function generateLimitPrivate(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...
223
		if (!(Circle::CIRCLES_PRIVATE & (int)$type)) {
224
			return null;
225
		}
226
227
		return $qb->expr()
228
				  ->eq(
229
					  'c.type',
230
					  $qb->createNamedParameter(Circle::CIRCLES_PRIVATE)
231
				  );
232
	}
233
234
235
	/**
236
	 * @param IQueryBuilder $qb
237
	 * @param int $type
238
	 *
239
	 * @return string
240
	 */
241 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...
242
		if (!(Circle::CIRCLES_PUBLIC & (int)$type)) {
243
			return null;
244
		}
245
246
		return $qb->expr()
247
				  ->eq(
248
					  'c.type',
249
					  $qb->createNamedParameter(Circle::CIRCLES_PUBLIC)
250
				  );
251
	}
252
253
254
	/**
255
	 * add a request to the members list, using the current user ID.
256
	 * will returns level and stuff.
257
	 *
258
	 * @param IQueryBuilder $qb
259
	 * @param string $userId
260
	 */
261 View Code Duplication
	protected function leftJoinUserIdAsViewer(IQueryBuilder & $qb, $userId) {
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...
262
263
		if ($qb->getType() !== QueryBuilder::SELECT) {
264
			return;
265
		}
266
267
		$expr = $qb->expr();
268
		$pf = $this->default_select_alias . '.';
269
270
		/** @noinspection PhpMethodParametersCountMismatchInspection */
271
		$qb->selectAlias('u.user_id', 'viewer_userid')
272
		   ->selectAlias('u.status', 'viewer_status')
273
		   ->selectAlias('u.level', 'viewer_level')
274
		   ->leftJoin(
275
			   $this->default_select_alias, CoreRequestBuilder::TABLE_MEMBERS, 'u',
276
			   $expr->andX(
277
				   $expr->eq($pf . 'id', 'u.circle_id'),
278
				   $expr->eq('u.user_id', $qb->createNamedParameter($userId))
279
			   )
280
		   );
281
	}
282
283
	/**
284
	 * Left Join members table to get the owner of the circle.
285
	 *
286
	 * @param IQueryBuilder $qb
287
	 */
288 View Code Duplication
	protected function leftJoinOwner(IQueryBuilder & $qb) {
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...
289
290
		if ($qb->getType() !== QueryBuilder::SELECT) {
291
			return;
292
		}
293
294
		$expr = $qb->expr();
295
		$pf = $this->default_select_alias . '.';
296
297
		/** @noinspection PhpMethodParametersCountMismatchInspection */
298
		$qb->selectAlias('o.user_id', 'owner_userid')
299
		   ->selectAlias('o.status', 'owner_status')
300
		   ->selectAlias('o.level', 'owner_level')
301
		   ->leftJoin(
302
			   $this->default_select_alias, CoreRequestBuilder::TABLE_MEMBERS, 'o',
303
			   $expr->andX(
304
				   $expr->eq($pf . 'id', 'o.circle_id'),
305
				   $expr->eq('o.level', $qb->createNamedParameter(Member::LEVEL_OWNER))
306
			   )
307
		   );
308
	}
309
310
311
	/**
312
	 * Base of the Sql Select request for Shares
313
	 *
314
	 * @return IQueryBuilder
315
	 */
316 View Code Duplication
	protected function getLinksSelectSql() {
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...
317
		$qb = $this->dbConnection->getQueryBuilder();
318
319
		/** @noinspection PhpMethodParametersCountMismatchInspection */
320
		$qb->select('id', 'status', 'address', 'token', 'circle_id', 'unique_id', 'creation')
321
		   ->from(self::TABLE_LINKS, 's');
322
323
		$this->default_select_alias = 's';
324
325
		return $qb;
326
	}
327
328
329
	/**
330
	 * Base of the Sql Select request for Shares
331
	 *
332
	 * @return IQueryBuilder
333
	 */
334 View Code Duplication
	protected function getSharesSelectSql() {
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...
335
		$qb = $this->dbConnection->getQueryBuilder();
336
337
		/** @noinspection PhpMethodParametersCountMismatchInspection */
338
		$qb->select(
339
			'circle_id', 'source', 'type', 'author', 'cloud_id', 'payload', 'creation', 'headers',
340
			'unique_id'
341
		)
342
		   ->from(self::TABLE_SHARES, 's');
343
344
		$this->default_select_alias = 's';
345
346
		return $qb;
347
	}
348
349
	/**
350
	 * Base of the Sql Insert request for Shares
351
	 *
352
	 * @return IQueryBuilder
353
	 */
354 View Code Duplication
	protected function getSharesInsertSql() {
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...
355
		$qb = $this->dbConnection->getQueryBuilder();
356
		$qb->insert(self::TABLE_SHARES)
357
		   ->setValue('creation', $qb->createFunction('NOW()'));
358
359
		return $qb;
360
	}
361
362
363
	/**
364
	 * Base of the Sql Update request for Shares
365
	 *
366
	 * @param string $uniqueId
367
	 *
368
	 * @return IQueryBuilder
369
	 */
370 View Code Duplication
	protected function getSharesUpdateSql($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...
371
		$qb = $this->dbConnection->getQueryBuilder();
372
		$qb->update(self::TABLE_SHARES)
373
		   ->where(
374
			   $qb->expr()
375
				  ->eq('unique_id', $qb->createNamedParameter((string)$uniqueId))
376
		   );
377
378
		return $qb;
379
	}
380
381
382
	/**
383
	 * Base of the Sql Insert request for Shares
384
	 *
385
	 *
386
	 * @return IQueryBuilder
387
	 */
388 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...
389
		$qb = $this->dbConnection->getQueryBuilder();
390
		$qb->insert(self::TABLE_CIRCLES)
391
		   ->setValue('creation', $qb->createFunction('NOW()'));
392
393
		return $qb;
394
	}
395
396
397
	/**
398
	 * Base of the Sql Update request for Shares
399
	 *
400
	 * @param int $circleId
401
	 *
402
	 * @return IQueryBuilder
403
	 */
404
	protected function getCirclesUpdateSql($circleId) {
405
		$qb = $this->dbConnection->getQueryBuilder();
406
		$qb->update(self::TABLE_CIRCLES)
407
		   ->where(
408
			   $qb->expr()
409
				  ->eq('id', $qb->createNamedParameter($circleId))
410
		   );
411
412
		return $qb;
413
	}
414
415
416
	/**
417
	 * Base of the Sql Delete request
418
	 *
419
	 * @return IQueryBuilder
420
	 */
421
	protected function getCirclesDeleteSql() {
422
		$qb = $this->dbConnection->getQueryBuilder();
423
		$qb->delete(self::TABLE_CIRCLES);
424
425
		return $qb;
426
	}
427
428
429
	/**
430
	 * @return IQueryBuilder
431
	 */
432
	protected function getCirclesSelectSql() {
433
		$qb = $this->dbConnection->getQueryBuilder();
434
435
		/** @noinspection PhpMethodParametersCountMismatchInspection */
436
		$qb
437
			->selectDistinct('c.unique_id')
438
			->addSelect(
439
				'c.id', 'c.name', 'c.description', 'c.settings', 'c.type', 'c.creation'
440
			)
441
			->from(CoreRequestBuilder::TABLE_CIRCLES, 'c');
442
		$this->default_select_alias = 'c';
443
444
		return $qb;
445
	}
446
447
448
	/**
449
	 * @param array $data
450
	 *
451
	 * @return Circle
452
	 */
453
	protected function parseCirclesSelectSql($data) {
454
455
		$circle = new Circle($this->l10n);
456
		$circle->setId($data['id']);
457
		$circle->setUniqueId($data['unique_id']);
458
		$circle->setName($data['name']);
459
		$circle->setDescription($data['description']);
460
		$circle->setSettings($data['settings']);
461
		$circle->setType($data['type']);
462
		$circle->setCreation($data['creation']);
463
464 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...
465
			$user = new Member($this->l10n);
466
			$user->setStatus($data['viewer_status']);
467
			$user->setCircleId($circle->getId());
468
			$user->setUserId($data['viewer_userid']);
469
			$user->setLevel($data['viewer_level']);
470
			$circle->setViewer($user);
471
		}
472
473 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...
474
			$owner = new Member($this->l10n);
475
			$owner->setStatus($data['owner_status']);
476
			$owner->setCircleId($circle->getId());
477
			$owner->setUserId($data['owner_userid']);
478
			$owner->setLevel($data['owner_level']);
479
			$circle->setOwner($owner);
480
		}
481
482
		return $circle;
483
	}
484
485
486
	/**
487
	 * @param array $data
488
	 *
489
	 * @return SharingFrame
490
	 */
491
	protected function parseSharesSelectSql($data) {
492
		$frame = new SharingFrame($data['source'], $data['type']);
493
		$frame->setCircleId($data['circle_id']);
494
		$frame->setAuthor($data['author']);
495
		$frame->setCloudId($data['cloud_id']);
496
		$frame->setPayload(json_decode($data['payload'], true));
497
		$frame->setCreation($data['creation']);
498
		$frame->setHeaders(json_decode($data['headers'], true));
499
		$frame->setUniqueId($data['unique_id']);
500
501
		return $frame;
502
	}
503
504
505
	/**
506
	 * @param array $data
507
	 *
508
	 * @return FederatedLink
509
	 */
510
	protected function parseLinksSelectSql($data) {
511
		$link = new FederatedLink();
512
		$link->setId($data['id'])
513
			 ->setUniqueId($data['unique_id'])
514
			 ->setStatus($data['status'])
515
			 ->setCreation($data['creation'])
516
			 ->setAddress($data['address'])
517
			 ->setToken($data['token'])
518
			 ->setCircleId($data['circle_id']);
519
520
		return $link;
521
	}
522
523
524
}