Completed
Pull Request — master (#105)
by Maxence
02:19
created

CirclesRequestBuilder::leftJoinUserIdAsViewer()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 26
Code Lines 16

Duplication

Lines 26
Ratio 100 %

Importance

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