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

CircleProviderRequestBuilder::getBaseDeleteSql()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 9
Ratio 100 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 9
loc 9
rs 9.6666
cc 1
eloc 6
nc 1
nop 0
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\Platforms\PostgreSqlPlatform;
32
use Doctrine\DBAL\Query\QueryBuilder;
33
use OCA\Circles\Model\Member;
34
use OCP\DB\QueryBuilder\IQueryBuilder;
35
use OCP\IDBConnection;
36
use OCP\Share;
37
use OCP\Share\IShare;
38
39
class CircleProviderRequestBuilder {
40
41
42
	/** @var IDBConnection */
43
	protected $dbConnection;
44
45
46
	/**
47
	 * returns the SQL request to get a specific share from the fileId and circleId
48
	 *
49
	 * @param int $fileId
50
	 * @param int $circleId
51
	 *
52
	 * @return IQueryBuilder
53
	 */
54
	protected function findShareParentSql($fileId, $circleId) {
55
56
		$qb = $this->getBaseSelectSql();
57
		$this->limitToShareParent($qb);
58
		$this->limitToCircle($qb, $circleId);
59
		$this->limitToFiles($qb, $fileId);
60
61
		return $qb;
62
	}
63
64
65
	/**
66
	 * Limit the request to a Circle.
67
	 *
68
	 * @param IQueryBuilder $qb
69
	 * @param int $circleId
70
	 */
71
	protected function limitToCircle(& $qb, $circleId) {
72
		$expr = $qb->expr();
73
		$pf = ($qb->getType() === QueryBuilder::SELECT) ? 's.' : '';
74
75
		$qb->andWhere($expr->eq($pf . 'share_with', $qb->createNamedParameter($circleId)));
76
	}
77
78
79
	/**
80
	 * Limit the request to the Share by its Id.
81
	 *
82
	 * @param IQueryBuilder $qb
83
	 * @param $shareId
84
	 */
85
	protected function limitToShare(& $qb, $shareId) {
86
		$expr = $qb->expr();
87
		$pf = ($qb->getType() === QueryBuilder::SELECT) ? 's.' : '';
88
89
		$qb->andWhere($expr->eq($pf . 'id', $qb->createNamedParameter($shareId)));
90
	}
91
92
93
	/**
94
	 * Limit the request to the top share (no children)
95
	 *
96
	 * @param IQueryBuilder $qb
97
	 */
98
	protected function limitToShareParent(& $qb) {
99
		$expr = $qb->expr();
100
101
		$qb->andWhere($expr->isNull('parent'));
102
	}
103
104
105
	/**
106
	 * limit the request to the children of a share
107
	 *
108
	 * @param IQueryBuilder $qb
109
	 * @param $userId
110
	 * @param int $parentId
111
	 */
112
	protected function limitToShareChildren(& $qb, $userId, $parentId = -1) {
113
		$expr = $qb->expr();
114
		$qb->andWhere($expr->eq('share_with', $qb->createNamedParameter($userId)));
115
116
		if ($parentId > -1) {
117
			$qb->andWhere($expr->eq('parent', $qb->createNamedParameter($parentId)));
118
		} else {
119
			$qb->andWhere($expr->isNotNull('parent'));
120
		}
121
	}
122
123
124
	/**
125
	 * limit the request to the share itself AND its children.
126
	 * perfect if you want to delete everything related to a share
127
	 *
128
	 * @param IQueryBuilder $qb
129
	 * @param $circleId
130
	 */
131
	protected function limitToShareAndChildren(& $qb, $circleId) {
132
		$expr = $qb->expr();
133
		$pf = ($qb->getType() === QueryBuilder::SELECT) ? 's.' : '';
134
135
		/** @noinspection PhpMethodParametersCountMismatchInspection */
136
		$qb->andWhere(
137
			$expr->orX(
138
				$expr->eq($pf . 'parent', $qb->createNamedParameter($circleId)),
139
				$expr->eq($pf . 'id', $qb->createNamedParameter($circleId))
140
			)
141
		);
142
	}
143
144
145
	/**
146
	 * limit the request to a fileId.
147
	 *
148
	 * @param IQueryBuilder $qb
149
	 * @param $files
150
	 *
151
	 * @internal param $fileId
152
	 */
153
	protected function limitToFiles(& $qb, $files) {
154
155
		if (!is_array($files)) {
156
			$files = array($files);
157
		}
158
159
		$expr = $qb->expr();
160
		$pf = ($qb->getType() === QueryBuilder::SELECT) ? 's.' : '';
161
		$qb->andWhere(
162
			$expr->in(
163
				$pf . 'file_source',
164
				$qb->createNamedParameter($files, IQueryBuilder::PARAM_INT_ARRAY)
165
			)
166
		);
167
	}
168
169
170
	/**
171
	 * @param IQueryBuilder $qb
172
	 * @param int $limit
173
	 * @param int $offset
174
	 */
175
	protected function limitToPage(& $qb, $limit = -1, $offset = 0) {
176
		if ($limit !== -1) {
177
			$qb->setMaxResults($limit);
178
		}
179
180
		$qb->setFirstResult($offset);
181
	}
182
183
	/**
184
	 * limit the request to a userId
185
	 *
186
	 * @param IQueryBuilder $qb
187
	 * @param string $userId
188
	 * @param bool $reShares
189
	 */
190
	protected function limitToShareOwner(& $qb, $userId, $reShares = false) {
191
		$expr = $qb->expr();
192
		$pf = ($qb->getType() === QueryBuilder::SELECT) ? 's.' : '';
193
194
		if ($reShares === false) {
195
			$qb->andWhere($expr->eq($pf . 'uid_initiator', $qb->createNamedParameter($userId)));
196
		} else {
197
			/** @noinspection PhpMethodParametersCountMismatchInspection */
198
			$qb->andWhere(
199
				$expr->orX(
200
					$expr->eq($pf . 'uid_owner', $qb->createNamedParameter($userId)),
201
					$expr->eq($pf . 'uid_initiator', $qb->createNamedParameter($userId))
202
				)
203
			);
204
		}
205
	}
206
207
208
	/**
209
	 * link circle field
210
	 *
211
	 * @deprecated
212
	 *
213
	 * @param IQueryBuilder $qb
214
	 * @param int $shareId
215
	 */
216
	protected function linkCircleField(& $qb, $shareId = -1) {
217
		$expr = $qb->expr();
218
219
		// TODO - Remove this in 12.0.1
220 View Code Duplication
		if ($qb->getConnection()
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...
221
			   ->getDatabasePlatform() instanceof PostgreSqlPlatform
222
		) {
223
			$tmpOrX = $expr->eq('s.share_with', $qb->createFunction('CAST(c.id AS TEXT)'));
224
		} else {
225
			$tmpOrX =
226
				$expr->eq('s.share_with', $expr->castColumn('c.id', IQueryBuilder::PARAM_STR));
227
		}
228
229
		$qb->from(CoreRequestBuilder::TABLE_CIRCLES, 'c');
230
231
		if ($shareId === -1) {
232
			$qb->andWhere($tmpOrX);
233
234
			return;
235
		}
236
237
		/** @noinspection PhpMethodParametersCountMismatchInspection */
238
		$qb->andWhere(
239
			$expr->orX(
240
				$tmpOrX,
241
				$expr->eq('s.parent', $qb->createNamedParameter($shareId))
242
			)
243
		);
244
		//->orderBy('c.circle_name');
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
245
	}
246
247
248
	/**
249
	 * @param IQueryBuilder $qb
250
	 */
251
	protected function linkToCircleOwner(& $qb) {
252
		$expr = $qb->expr();
253
254
		/** @noinspection PhpMethodParametersCountMismatchInspection */
255
		$qb->leftJoin(
256
			'c', 'circles_members', 'mo', $expr->andX(
257
			$expr->eq('c.id', 'mo.circle_id'),
258
			$expr->eq('mo.level', $qb->createNamedParameter(Member::LEVEL_OWNER))
259
		)
260
		);
261
	}
262
263
264
	/**
265
	 * Link to member (userId) of circle
266
	 *
267
	 * @param IQueryBuilder $qb
268
	 * @param string $userId
269
	 */
270
	protected function linkToMember(& $qb, $userId) {
271
		$expr = $qb->expr();
272
273
		// TODO - Remove this in 12.0.1
0 ignored issues
show
Unused Code Comprehensibility introduced by
49% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
274
//		if ($qb->getConnection()
275
//			   ->getDatabasePlatform() instanceof PostgreSqlPlatform
276
//		) {
277
//			$tmpAndX = $expr->eq('s.share_with', $qb->createFunction('CAST(m.circle_id AS TEXT)'));
278
//		} else {
279
//			$tmpAndX = $expr->eq(
280
//				's.share_with', $expr->castColumn('m.circle_id', IQueryBuilder::PARAM_STR)
281
//			);
282
//		}
283
//		$qb->andWhere($tmpAndX);
284
285
		$qb->from(CoreRequestBuilder::TABLE_MEMBERS, 'm');
286
		$qb->from(CoreRequestBuilder::TABLE_GROUPS, 'g');
287
		$qb->from(CoreRequestBuilder::NC_TABLE_GROUP_USER, 'ncgu');
288
289
290
		$qb->andWhere(
291
			$expr->orX(
292
			// We check if user is members of the circle with the right level
293
				$expr->andX(
294
					$expr->eq('m.user_id', $qb->createNamedParameter($userId)),
295
					$expr->gte('m.level', $qb->createNamedParameter(Member::LEVEL_MEMBER))
296
				),
297
298
				// Or if user is member of one of the group linked to the circle with the right level
299
				$expr->andX(
300
					$expr->eq('g.circle_id', 'c.id'),
301
					$expr->gte('g.level', $qb->createNamedParameter(Member::LEVEL_MEMBER)),
302
					$expr->eq('ncgu.gid', 'g.group_id'),
303
					$expr->eq('ncgu.uid', $qb->createNamedParameter($userId))
304
				)
305
			)
306
		);
307
	}
308
309
310
	/**
311
	 * left join to get more data about the initiator of the share
312
	 *
313
	 * @param IQueryBuilder $qb
314
	 */
315
	protected function leftJoinShareInitiator(IQueryBuilder &$qb) {
316
		$expr = $qb->expr();
317
318 View Code Duplication
		if ($qb->getConnection()
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...
319
			   ->getDatabasePlatform() instanceof PostgreSqlPlatform
320
		) {
321
			$req = $expr->eq('s.share_with', $qb->createFunction('CAST(fo.circle_id AS TEXT)'));
322
		} else {
323
			$req = $expr->eq(
324
				's.share_with', $expr->castColumn('fo.circle_id', IQueryBuilder::PARAM_STR)
325
			);
326
		}
327
328
		$qb->leftJoin(
329
			's', 'circles_members', 'fo', $expr->andX(
330
			$req, $expr->eq('s.uid_initiator', 'fo.user_id')
331
		)
332
		);
333
334
		$qb->selectAlias('fo.level', 'initiator_level');
335
	}
336
337
338
	/**
339
	 * Link to all members of circle
340
	 *
341
	 * @param IQueryBuilder $qb
342
	 */
343
	protected function joinCircleMembers(& $qb) {
344
		$expr = $qb->expr();
345
346
		$qb->from(CoreRequestBuilder::TABLE_MEMBERS, 'm');
347
348
		// TODO - Remove this in 12.0.1
349 View Code Duplication
		if ($qb->getConnection()
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...
350
			   ->getDatabasePlatform() instanceof PostgreSqlPlatform
0 ignored issues
show
Bug introduced by
The class Doctrine\DBAL\Platforms\PostgreSqlPlatform does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
351
		) {
352
			$qb->andWhere(
353
				$expr->eq('s.share_with', $qb->createFunction('CAST(m.circle_id AS TEXT)'))
354
			);
355
		} else {
356
357
			$qb->andWhere(
358
				$expr->eq(
359
					's.share_with', $expr->castColumn('m.circle_id', IQueryBuilder::PARAM_STR)
360
				)
361
			);
362
		}
363
	}
364
365
366
	/**
367
	 * Link to storage/filecache
368
	 *
369
	 * @param IQueryBuilder $qb
370
	 * @param string $userId
371
	 */
372
	protected function linkToFileCache(& $qb, $userId) {
373
		$expr = $qb->expr();
374
375
		/** @noinspection PhpMethodParametersCountMismatchInspection */
376
		$qb->leftJoin('s', 'filecache', 'f', $expr->eq('s.file_source', 'f.fileid'))
377
		   ->leftJoin('f', 'storages', 'st', $expr->eq('f.storage', 'st.numeric_id'))
378
		   ->leftJoin(
379
			   's', 'share', 's2', $expr->andX(
380
			   $expr->eq('s.id', 's2.parent'),
381
			   $expr->eq('s2.share_with', $qb->createNamedParameter($userId))
382
		   )
383
		   );
384
385
		$qb->selectAlias('s2.id', 'parent_id');
386
		$qb->selectAlias('s2.file_target', 'parent_target');
387
		$qb->selectAlias('s2.permissions', 'parent_perms');
388
389
	}
390
391
392
	/**
393
	 * add share to the database and return the ID
394
	 *
395
	 * @param IShare $share
396
	 *
397
	 * @return IQueryBuilder
398
	 */
399
	protected function getBaseInsertSql($share) {
400
		$qb = $this->dbConnection->getQueryBuilder();
401
		$qb->insert('share')
402
		   ->setValue('share_type', $qb->createNamedParameter(Share::SHARE_TYPE_CIRCLE))
403
		   ->setValue('item_type', $qb->createNamedParameter($share->getNodeType()))
404
		   ->setValue('item_source', $qb->createNamedParameter($share->getNodeId()))
405
		   ->setValue('file_source', $qb->createNamedParameter($share->getNodeId()))
406
		   ->setValue('file_target', $qb->createNamedParameter($share->getTarget()))
407
		   ->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()))
408
		   ->setValue('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
409
		   ->setValue('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
410
		   ->setValue('permissions', $qb->createNamedParameter($share->getPermissions()))
411
		   ->setValue('token', $qb->createNamedParameter($share->getToken()))
412
		   ->setValue('stime', $qb->createFunction('UNIX_TIMESTAMP()'));
413
414
		return $qb;
415
	}
416
417
418
	/**
419
	 * generate and return a base sql request.
420
	 *
421
	 * @param int $shareId
422
	 *
423
	 * @return IQueryBuilder
424
	 */
425 View Code Duplication
	protected function getBaseSelectSql($shareId = -1) {
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...
426
		$qb = $this->dbConnection->getQueryBuilder();
427
428
		/** @noinspection PhpMethodParametersCountMismatchInspection */
429
		$qb->select(
430
			's.id', 's.share_type', 's.share_with', 's.uid_owner', 's.uid_initiator',
431
			's.parent', 's.item_type', 's.item_source', 's.item_target', 's.file_source',
432
			's.file_target', 's.permissions', 's.stime', 's.accepted', 's.expiration',
433
			's.token', 's.mail_send', 'c.type AS circle_type', 'c.name AS circle_name',
434
			'mo.user_id AS circle_owner'
435
		);
436
		$this->linkToCircleOwner($qb);
437
		$this->joinShare($qb);
438
439
		// TODO: Left-join circle and REMOVE this line
440
		$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...
441
442
		return $qb;
443
	}
444
445
446
	/**
447
	 * Generate and return a base sql request
448
	 * This one should be used to retrieve a complete list of users (ie. access list).
449
	 *
450
	 * @return IQueryBuilder
451
	 */
452
	protected function getAccessListBaseSelectSql() {
453
		$qb = $this->dbConnection->getQueryBuilder();
454
455
		/** @noinspection PhpMethodParametersCountMismatchInspection */
456
		$qb->select(
457
			'm.user_id', 's.file_source', 's.file_target'
458
		);
459
		$this->joinCircleMembers($qb);
460
		$this->joinShare($qb);
461
462
		return $qb;
463
	}
464
465
466 View Code Duplication
	protected function getCompleteSelectSql() {
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...
467
		$qb = $this->dbConnection->getQueryBuilder();
468
469
		/** @noinspection PhpMethodParametersCountMismatchInspection */
470
		$qb->select(
471
			's.*', 'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage',
472
			'f.path_hash', 'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart',
473
			'f.size', 'f.mtime', 'f.storage_mtime', 'f.encrypted', 'f.unencrypted_size',
474
			'f.etag', 'f.checksum', 'c.type AS circle_type', 'c.name AS circle_name',
475
			'mo.user_id AS circle_owner'
476
		)
477
		   ->selectAlias('st.id', 'storage_string_id');
478
479
		$this->linkToCircleOwner($qb);
480
		$this->joinShare($qb);
481
		$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...
482
483
484
		return $qb;
485
	}
486
487
488
	/**
489
	 * @param IQueryBuilder $qb
490
	 */
491
	private function joinShare(& $qb) {
492
		$expr = $qb->expr();
493
494
		/** @noinspection PhpMethodParametersCountMismatchInspection */
495
		$qb->from('share', 's')
496
		   ->where($expr->eq('s.share_type', $qb->createNamedParameter(Share::SHARE_TYPE_CIRCLE)))
497
		   ->andWhere(
498
			   $expr->orX(
499
				   $expr->eq('s.item_type', $qb->createNamedParameter('file')),
500
				   $expr->eq('s.item_type', $qb->createNamedParameter('folder'))
501
			   )
502
		   );
503
	}
504
505
506
	/**
507
	 * generate and return a base sql request.
508
	 *
509
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder
510
	 */
511 View Code Duplication
	protected function getBaseDeleteSql() {
512
		$qb = $this->dbConnection->getQueryBuilder();
513
		$expr = $qb->expr();
514
515
		$qb->delete('share')
516
		   ->where($expr->eq('share_type', $qb->createNamedParameter(Share::SHARE_TYPE_CIRCLE)));
517
518
		return $qb;
519
	}
520
521
522
	/**
523
	 * generate and return a base sql request.
524
	 *
525
	 * @return \OCP\DB\QueryBuilder\IQueryBuilder
526
	 */
527 View Code Duplication
	protected function getBaseUpdateSql() {
528
		$qb = $this->dbConnection->getQueryBuilder();
529
		$expr = $qb->expr();
530
531
		$qb->update('share')
532
		   ->where($expr->eq('share_type', $qb->createNamedParameter(Share::SHARE_TYPE_CIRCLE)));
533
534
		return $qb;
535
	}
536
}
537