Completed
Push — master ( 703448...70edb2 )
by Maxence
02:33
created

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