Completed
Pull Request — master (#205)
by John
04:35
created

leftJoinShareInitiator()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 29
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 29
rs 8.8571
cc 1
eloc 19
nc 1
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
 * @author Vinicius Cubas Brand <[email protected]>
11
 * @author Daniel Tygel <[email protected]>
12
 *
13
 * @copyright 2017
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
namespace OCA\Circles\Db;
32
33
34
use Doctrine\DBAL\Query\QueryBuilder;
35
use OCA\Circles\Model\Circle;
36
use OCA\Circles\Model\Member;
37
use OCP\DB\QueryBuilder\IQueryBuilder;
38
use OCP\Share;
39
use OCP\Share\IShare;
40
41
class CircleProviderRequestBuilder extends CoreRequestBuilder {
42
43
44
	/**
45
	 * returns the SQL request to get a specific share from the fileId and circleId
46
	 *
47
	 * @param int $fileId
48
	 * @param int $circleId
49
	 *
50
	 * @return IQueryBuilder
51
	 */
52
	protected function findShareParentSql($fileId, $circleId) {
53
54
		$qb = $this->getBaseSelectSql();
55
		$this->limitToShareParent($qb);
56
		$this->limitToCircles($qb, [$circleId]);
57
		$this->limitToFiles($qb, $fileId);
58
59
		return $qb;
60
	}
61
62
63
	/**
64
	 * Limit the request to the given Circles.
65
	 *
66
	 * @param IQueryBuilder $qb
67
	 * @param array $circleUniqueIds
68
	 */
69 View Code Duplication
	protected function limitToCircles(IQueryBuilder &$qb, $circleUniqueIds) {
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...
70
71
		if (!is_array($circleUniqueIds)) {
72
			$circleUniqueIds = array($circleUniqueIds);
73
		}
74
75
		$expr = $qb->expr();
76
		$pf = ($qb->getType() === QueryBuilder::SELECT) ? 's.' : '';
77
		$qb->andWhere(
78
			$expr->in(
79
				$pf . 'share_with',
80
				$qb->createNamedParameter($circleUniqueIds, IQueryBuilder::PARAM_STR_ARRAY)
81
			)
82
		);
83
	}
84
85
86
	/**
87
	 * Limit the request to the Share by its Id.
88
	 *
89
	 * @param IQueryBuilder $qb
90
	 * @param $shareId
91
	 */
92
	protected function limitToShare(IQueryBuilder &$qb, $shareId) {
93
		$expr = $qb->expr();
94
		$pf = ($qb->getType() === QueryBuilder::SELECT) ? 's.' : '';
95
96
		$qb->andWhere($expr->eq($pf . 'id', $qb->createNamedParameter($shareId)));
97
	}
98
99
100
	/**
101
	 * Limit the request to the top share (no children)
102
	 *
103
	 * @param IQueryBuilder $qb
104
	 */
105
	protected function limitToShareParent(IQueryBuilder &$qb) {
106
		$expr = $qb->expr();
107
108
		$qb->andWhere($expr->isNull('parent'));
109
	}
110
111
112
	/**
113
	 * limit the request to the children of a share
114
	 *
115
	 * @param IQueryBuilder $qb
116
	 * @param $userId
117
	 * @param int $parentId
118
	 */
119
	protected function limitToShareChildren(IQueryBuilder &$qb, $userId, $parentId = -1) {
120
		$expr = $qb->expr();
121
		$qb->andWhere($expr->eq('share_with', $qb->createNamedParameter($userId)));
122
123
		if ($parentId > -1) {
124
			$qb->andWhere($expr->eq('parent', $qb->createNamedParameter($parentId)));
125
		} else {
126
			$qb->andWhere($expr->isNotNull('parent'));
127
		}
128
	}
129
130
131
	/**
132
	 * limit the request to the share itself AND its children.
133
	 * perfect if you want to delete everything related to a share
134
	 *
135
	 * @param IQueryBuilder $qb
136
	 * @param $circleId
137
	 */
138
	protected function limitToShareAndChildren(IQueryBuilder &$qb, $circleId) {
139
		$expr = $qb->expr();
140
		$pf = ($qb->getType() === QueryBuilder::SELECT) ? 's.' : '';
141
142
		/** @noinspection PhpMethodParametersCountMismatchInspection */
143
		$qb->andWhere(
144
			$expr->orX(
145
				$expr->eq($pf . 'parent', $qb->createNamedParameter($circleId)),
146
				$expr->eq($pf . 'id', $qb->createNamedParameter($circleId))
147
			)
148
		);
149
	}
150
151
152
	/**
153
	 * limit the request to a fileId.
154
	 *
155
	 * @param IQueryBuilder $qb
156
	 * @param $files
157
	 */
158 View Code Duplication
	protected function limitToFiles(IQueryBuilder &$qb, $files) {
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...
159
160
		if (!is_array($files)) {
161
			$files = array($files);
162
		}
163
164
		$expr = $qb->expr();
165
		$pf = ($qb->getType() === QueryBuilder::SELECT) ? 's.' : '';
166
		$qb->andWhere(
167
			$expr->in(
168
				$pf . 'file_source',
169
				$qb->createNamedParameter($files, IQueryBuilder::PARAM_INT_ARRAY)
170
			)
171
		);
172
	}
173
174
175
	/**
176
	 * @param IQueryBuilder $qb
177
	 * @param int $limit
178
	 * @param int $offset
179
	 */
180
	protected function limitToPage(IQueryBuilder &$qb, $limit = -1, $offset = 0) {
181
		if ($limit !== -1) {
182
			$qb->setMaxResults($limit);
183
		}
184
185
		$qb->setFirstResult($offset);
186
	}
187
188
189
	/**
190
	 * limit the request to a userId
191
	 *
192
	 * @param IQueryBuilder $qb
193
	 * @param string $userId
194
	 * @param bool $reShares
195
	 */
196
	protected function limitToShareOwner(IQueryBuilder &$qb, $userId, $reShares = false) {
197
		$expr = $qb->expr();
198
		$pf = ($qb->getType() === QueryBuilder::SELECT) ? 's.' : '';
199
200
		if ($reShares === false) {
201
			$qb->andWhere($expr->eq($pf . 'uid_initiator', $qb->createNamedParameter($userId)));
202
		} else {
203
			/** @noinspection PhpMethodParametersCountMismatchInspection */
204
			$qb->andWhere(
205
				$expr->orX(
206
					$expr->eq($pf . 'uid_owner', $qb->createNamedParameter($userId)),
207
					$expr->eq($pf . 'uid_initiator', $qb->createNamedParameter($userId))
208
				)
209
			);
210
		}
211
	}
212
213
214
	/**
215
	 * link circle field
216
	 *
217
	 * @deprecated
218
	 *
219
	 * @param IQueryBuilder $qb
220
	 * @param int $shareId
221
	 */
222
	protected function linkCircleField(IQueryBuilder &$qb, $shareId = -1) {
223
		$expr = $qb->expr();
224
225
		$qb->from(CoreRequestBuilder::TABLE_CIRCLES, 'c');
226
227
		$tmpOrX = $expr->eq(
228
			's.share_with',
229
			$qb->createFunction('SUBSTR(`c`.`unique_id`, 1, ' . Circle::SHORT_UNIQUE_ID_LENGTH . ')')
230
		);
231
232
		if ($shareId === -1) {
233
			$qb->andWhere($tmpOrX);
234
235
			return;
236
		}
237
238
		/** @noinspection PhpMethodParametersCountMismatchInspection */
239
		$qb->andWhere(
240
			$expr->orX(
241
				$tmpOrX,
242
				$expr->eq('s.parent', $qb->createNamedParameter($shareId))
243
			)
244
		);
245
	}
246
247
248
	/**
249
	 * @param IQueryBuilder $qb
250
	 */
251 View Code Duplication
	protected function linkToCircleOwner(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...
252
		$expr = $qb->expr();
253
254
		$qb->selectAlias('mo.user_id', 'circle_owner');
255
		/** @noinspection PhpMethodParametersCountMismatchInspection */
256
		$qb->leftJoin(
257
			'c', CoreRequestBuilder::TABLE_MEMBERS, 'mo', $expr->andX(
258
			$expr->eq(
259
				'mo.circle_id',
260
        $qb->createFunction('SUBSTR(`c`.`unique_id`, 1, ' . Circle::SHORT_UNIQUE_ID_LENGTH . ')')
261
			), $expr->eq('mo.user_type', $qb->createNamedParameter(Member::TYPE_USER)),
262
			$expr->eq('mo.level', $qb->createNamedParameter(Member::LEVEL_OWNER))
263
		)
264
		);
265
	}
266
267
268
	/**
269
	 * Link to member (userId) of circle
270
	 *
271
	 * @param IQueryBuilder $qb
272
	 * @param string $userId
273
	 * @param bool $groupMemberAllowed
274
	 */
275
	protected function linkToMember(IQueryBuilder &$qb, $userId, $groupMemberAllowed) {
276
		$expr = $qb->expr();
277
278
		$qb->from(CoreRequestBuilder::TABLE_MEMBERS, 'm');
279
280
		$orX = $expr->orX();
281
		$orX->add($this->exprLinkToMemberAsCircleMember($qb, $userId));
282
		if ($groupMemberAllowed === true) {
283
			$orX->add($this->exprLinkToMemberAsGroupMember($qb, $userId));
284
		}
285
286
		$qb->andWhere($orX);
287
288
	}
289
290
291
	/**
292
	 * generate CompositeExpression to link to a Member as a Real Circle Member
293
	 *
294
	 * @param IQueryBuilder $qb
295
	 * @param string $userId
296
	 *
297
	 * @return \OCP\DB\QueryBuilder\ICompositeExpression
298
	 */
299
	private function exprLinkToMemberAsCircleMember(IQueryBuilder &$qb, $userId) {
300
301
		$expr = $qb->expr();
302
		$andX = $expr->andX();
303
304
		$andX->add($expr->eq('m.user_id', $qb->createNamedParameter($userId)));
305
		$andX->add($expr->eq('m.user_type', $qb->createNamedParameter(Member::TYPE_USER)));
306
		$andX->add(
307
			$expr->eq(
308
				'm.circle_id',
309
				$qb->createFunction(
310
					'SUBSTR(`c`.`unique_id`, 1, ' . Circle::SHORT_UNIQUE_ID_LENGTH . ')'
311
				)
312
			)
313
		);
314
315
		return $andX;
316
	}
317
318
319
	/**
320
	 * generate CompositeExpression to link to a Member as a Group Member (core NC)
321
	 *
322
	 * @param IQueryBuilder $qb
323
	 * @param string $userId
324
	 *
325
	 * @return \OCP\DB\QueryBuilder\ICompositeExpression
326
	 */
327 View Code Duplication
	private function exprLinkToMemberAsGroupMember(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...
328
		$expr = $qb->expr();
329
330
		/** @noinspection PhpMethodParametersCountMismatchInspection */
331
		$qb->leftJoin(
332
			'c', CoreRequestBuilder::TABLE_GROUPS, 'g',
333
			$expr->andX(
334
				$expr->eq(
335
					'g.circle_id',
336
					$qb->createFunction('SUBSTR(`c`.`unique_id`, 1, ' . Circle::SHORT_UNIQUE_ID_LENGTH . ')')
337
				)
338
			)
339
		);
340
341
		$qb->leftJoin(
342
			'g', CoreRequestBuilder::NC_TABLE_GROUP_USER, 'ncgu',
343
			$expr->eq('ncgu.gid', 'g.group_id')
344
		);
345
346
		return $expr->andX($expr->eq('ncgu.uid', $qb->createNamedParameter($userId)));
347
	}
348
349
350
	/**
351
	 * Link to all members of circle
352
	 *
353
	 * @param IQueryBuilder $qb
354
	 */
355
	protected function joinCircleMembers(IQueryBuilder &$qb) {
356
		$expr = $qb->expr();
357
358
		/** @noinspection PhpMethodParametersCountMismatchInspection */
359
		$qb->addSelect('m.user_id')
360
		   ->from(CoreRequestBuilder::TABLE_MEMBERS, 'm')
361
		   ->andWhere(
362
			   $expr->andX(
363
				   $expr->eq('s.share_with', 'm.circle_id'),
364
				   $expr->eq('m.user_type', $qb->createNamedParameter(Member::TYPE_USER))
365
			   )
366
		   );
367
	}
368
369
370
	/**
371
	 * Link to storage/filecache
372
	 *
373
	 * @param IQueryBuilder $qb
374
	 * @param string $userId
375
	 */
376
	protected function linkToFileCache(IQueryBuilder &$qb, $userId) {
377
		$expr = $qb->expr();
378
379
		/** @noinspection PhpMethodParametersCountMismatchInspection */
380
		$qb->leftJoin('s', 'filecache', 'f', $expr->eq('s.file_source', 'f.fileid'))
381
		   ->leftJoin('f', 'storages', 'st', $expr->eq('f.storage', 'st.numeric_id'))
382
		   ->leftJoin(
383
			   's', 'share', 's2', $expr->andX(
384
			   $expr->eq('s.id', 's2.parent'),
385
			   $expr->eq('s2.share_with', $qb->createNamedParameter($userId))
386
		   )
387
		   );
388
389
		$qb->selectAlias('s2.id', 'parent_id');
390
		$qb->selectAlias('s2.file_target', 'parent_target');
391
		$qb->selectAlias('s2.permissions', 'parent_perms');
392
393
	}
394
395
396
	/**
397
	 * add share to the database and return the ID
398
	 *
399
	 * @param IShare $share
400
	 *
401
	 * @return IQueryBuilder
402
	 */
403
	protected function getBaseInsertSql($share) {
404
		$qb = $this->dbConnection->getQueryBuilder();
405
		$qb->insert('share')
406
		   ->setValue('share_type', $qb->createNamedParameter(Share::SHARE_TYPE_CIRCLE))
407
		   ->setValue('item_type', $qb->createNamedParameter($share->getNodeType()))
408
		   ->setValue('item_source', $qb->createNamedParameter($share->getNodeId()))
409
		   ->setValue('file_source', $qb->createNamedParameter($share->getNodeId()))
410
		   ->setValue('file_target', $qb->createNamedParameter($share->getTarget()))
411
		   ->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()))
412
		   ->setValue('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
413
		   ->setValue('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
414
		   ->setValue('permissions', $qb->createNamedParameter($share->getPermissions()))
415
		   ->setValue('token', $qb->createNamedParameter($share->getToken()))
416
		   ->setValue('stime', $qb->createFunction('UNIX_TIMESTAMP()'));
417
418
		return $qb;
419
	}
420
421
422
	/**
423
	 * generate and return a base sql request.
424
	 *
425
	 * @param int $shareId
426
	 *
427
	 * @return IQueryBuilder
428
	 */
429
	protected function getBaseSelectSql($shareId = -1) {
430
		$qb = $this->dbConnection->getQueryBuilder();
431
432
		/** @noinspection PhpMethodParametersCountMismatchInspection */
433
		$qb->select(
434
			's.id', 's.share_type', 's.share_with', 's.uid_owner', 's.uid_initiator',
435
			's.parent', 's.item_type', 's.item_source', 's.item_target', 's.permissions', 's.stime',
436
			's.accepted', 's.expiration',
437
			's.token', 's.mail_send', 'c.type AS circle_type', 'c.name AS circle_name'
438
		);
439
		$this->linkToCircleOwner($qb);
440
		$this->joinShare($qb);
441
442
		// TODO: Left-join circle and REMOVE this line
443
		$this->linkCircleField($qb, $shareId);
0 ignored issues
show
Deprecated Code introduced by
The method OCA\Circles\Db\CirclePro...lder::linkCircleField() has been deprecated.

This method has been deprecated.

Loading history...
444
445
		return $qb;
446
	}
447
448
449
	/**
450
	 * Generate and return a base sql request
451
	 * This one should be used to retrieve a complete list of users (ie. access list).
452
	 *
453
	 * @return IQueryBuilder
454
	 */
455
	protected function getAccessListBaseSelectSql() {
456
		$qb = $this->dbConnection->getQueryBuilder();
457
458
		/** @noinspection PhpMethodParametersCountMismatchInspection */
459
		$this->joinCircleMembers($qb);
460
		$this->joinShare($qb);
461
462
		return $qb;
463
	}
464
465
466
	/**
467
	 * @return IQueryBuilder
468
	 */
469
	protected function getCompleteSelectSql() {
470
		$qb = $this->dbConnection->getQueryBuilder();
471
472
		/** @noinspection PhpMethodParametersCountMismatchInspection */
473
		$qb->selectDistinct('s.id')
474
		   ->addSelect(
475
			   's.*', 'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage',
476
			   'f.path_hash', 'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart',
477
			   'f.size', 'f.mtime', 'f.storage_mtime', 'f.encrypted', 'f.unencrypted_size',
478
			   'f.etag', 'f.checksum', 'c.type AS circle_type', 'c.name AS circle_name'
479
		   )
480
		   ->selectAlias('st.id', 'storage_string_id');
481
482
483
		$this->linkToCircleOwner($qb);
484
		$this->joinShare($qb);
485
		$this->linkCircleField($qb);
0 ignored issues
show
Deprecated Code introduced by
The method OCA\Circles\Db\CirclePro...lder::linkCircleField() has been deprecated.

This method has been deprecated.

Loading history...
486
487
488
		return $qb;
489
	}
490
491
492
	/**
493
	 * @param IQueryBuilder $qb
494
	 */
495
	private function joinShare(IQueryBuilder &$qb) {
496
		$expr = $qb->expr();
497
498
		/** @noinspection PhpMethodParametersCountMismatchInspection */
499
		$qb->addSelect('s.file_source', 's.file_target');
500
		/** @noinspection PhpMethodParametersCountMismatchInspection */
501
		$qb->from('share', 's')
502
		   ->andWhere($expr->eq('s.share_type', $qb->createNamedParameter(Share::SHARE_TYPE_CIRCLE)))
503
		   ->andWhere(
504
			   $expr->orX(
505
				   $expr->eq('s.item_type', $qb->createNamedParameter('file')),
506
				   $expr->eq('s.item_type', $qb->createNamedParameter('folder'))
507
			   )
508
		   );
509
	}
510
511
512
	/**
513
	 * generate and return a base sql request.
514
	 *
515
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder
516
	 */
517 View Code Duplication
	protected function getBaseDeleteSql() {
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...
518
		$qb = $this->dbConnection->getQueryBuilder();
519
		$expr = $qb->expr();
520
521
		$qb->delete('share')
522
		   ->where($expr->eq('share_type', $qb->createNamedParameter(Share::SHARE_TYPE_CIRCLE)));
523
524
		return $qb;
525
	}
526
527
528
	/**
529
	 * generate and return a base sql request.
530
	 *
531
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder
532
	 */
533 View Code Duplication
	protected function getBaseUpdateSql() {
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...
534
		$qb = $this->dbConnection->getQueryBuilder();
535
		$expr = $qb->expr();
536
537
		$qb->update('share')
538
		   ->where($expr->eq('share_type', $qb->createNamedParameter(Share::SHARE_TYPE_CIRCLE)));
539
540
		return $qb;
541
	}
542
}
543