Completed
Push — master ( c57b95...1d3e11 )
by Maxence
30s queued 14s
created

ShareWrapper::getStatus()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
6
/**
7
 * Circles - Bring cloud-users closer together.
8
 *
9
 * This file is licensed under the Affero General Public License version 3 or
10
 * later. See the COPYING file.
11
 *
12
 * @author Maxence Lange <[email protected]>
13
 * @copyright 2021
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
32
namespace OCA\Circles\Model;
33
34
use daita\MySmallPhpTools\Db\Nextcloud\nc22\INC22QueryRow;
35
use daita\MySmallPhpTools\Exceptions\InvalidItemException;
36
use daita\MySmallPhpTools\IDeserializable;
37
use daita\MySmallPhpTools\Traits\Nextcloud\nc22\TNC22Deserialize;
38
use daita\MySmallPhpTools\Traits\TArrayTools;
39
use DateTime;
40
use JsonSerializable;
41
use OC;
42
use OC\Files\Cache\Cache;
43
use OC\Share20\Share;
44
use OCA\Circles\AppInfo\Application;
45
use OCA\Circles\ShareByCircleProvider;
46
use OCP\Files\IRootFolder;
47
use OCP\IURLGenerator;
48
use OCP\IUserManager;
49
use OCP\Share\Exceptions\IllegalIDChangeException;
50
use OCP\Share\IShare;
51
52
53
/**
54
 * Class ShareWrapper
55
 *
56
 * @package OCA\Circles\Model
57
 */
58
class ShareWrapper extends ManagedModel implements IDeserializable, INC22QueryRow, JsonSerializable {
59
60
61
	use TArrayTools;
62
	use TNC22Deserialize;
63
64
65
	/** @var string */
66
	private $id = '';
67
68
	/** @var int */
69
	private $permissions = 0;
70
71
	/** @var string */
72
	private $itemType = '';
73
74
	/** @var int */
75
	private $itemSource = 0;
76
77
	/** @var string */
78
	private $itemTarget = '';
79
80
	/** @var int */
81
	private $fileSource = 0;
82
83
	/** @var string */
84
	private $fileTarget = '';
85
86
	/** @var string */
87
	private $token = '';
88
89
	/** @var int */
90
	private $status = 0;
91
92
	/** @var string */
93
	private $providerId = '';
94
95
	/** @var DateTime */
96
	private $shareTime = '';
97
98
	/** @var string */
99
	private $sharedWith = '';
100
101
	/** @var string */
102
	private $sharedBy = '';
103
104
	/** @var string */
105
	private $shareOwner = '';
106
107
	/** @var int */
108
	private $shareType = 0;
109
110
	/** @var Circle */
111
	private $circle;
112
113
	/** @var int */
114
	private $childId = 0;
115
116
	/** @var string */
117
	private $childFileTarget = '';
118
119
	/** @var FileCacheWrapper */
120
	private $fileCache;
121
122
	/** @var Member */
123
	private $initiator;
124
125
	/** @var Member */
126
	private $owner;
127
128
129
	/**
130
	 * @param string $id
131
	 *
132
	 * @return ShareWrapper
133
	 */
134
	public function setId(string $id): self {
135
		$this->id = $id;
136
137
		return $this;
138
	}
139
140
	/**
141
	 * @return string
142
	 */
143
	public function getId(): string {
144
		return $this->id;
145
	}
146
147
148
	/**
149
	 * @param int $permissions
150
	 *
151
	 * @return ShareWrapper
152
	 */
153
	public function setPermissions(int $permissions): self {
154
		$this->permissions = $permissions;
155
156
		return $this;
157
	}
158
159
	/**
160
	 * @return int
161
	 */
162
	public function getPermissions(): int {
163
		return $this->permissions;
164
	}
165
166
167
	/**
168
	 * @param string $itemType
169
	 *
170
	 * @return ShareWrapper
171
	 */
172
	public function setItemType(string $itemType): self {
173
		$this->itemType = $itemType;
174
175
		return $this;
176
	}
177
178
	/**
179
	 * @return string
180
	 */
181
	public function getItemType(): string {
182
		return $this->itemType;
183
	}
184
185
186
	/**
187
	 * @param int $itemSource
188
	 *
189
	 * @return ShareWrapper
190
	 */
191
	public function setItemSource(int $itemSource): self {
192
		$this->itemSource = $itemSource;
193
194
		return $this;
195
	}
196
197
	/**
198
	 * @return int
199
	 */
200
	public function getItemSource(): int {
201
		return $this->itemSource;
202
	}
203
204
205
	/**
206
	 * @param string $itemTarget
207
	 *
208
	 * @return ShareWrapper
209
	 */
210
	public function setItemTarget(string $itemTarget): self {
211
		$this->itemTarget = $itemTarget;
212
213
		return $this;
214
	}
215
216
	/**
217
	 * @return string
218
	 */
219
	public function getItemTarget(): string {
220
		return $this->itemTarget;
221
	}
222
223
224
	/**
225
	 * @param int $fileSource
226
	 *
227
	 * @return ShareWrapper
228
	 */
229
	public function setFileSource(int $fileSource): self {
230
		$this->fileSource = $fileSource;
231
232
		return $this;
233
	}
234
235
	/**
236
	 * @return int
237
	 */
238
	public function getFileSource(): int {
239
		return $this->fileSource;
240
	}
241
242
243
	/**
244
	 * @param string $fileTarget
245
	 *
246
	 * @return ShareWrapper
247
	 */
248
	public function setFileTarget(string $fileTarget): self {
249
		$this->fileTarget = $fileTarget;
250
251
		return $this;
252
	}
253
254
	/**
255
	 * @return string
256
	 */
257
	public function getFileTarget(): string {
258
		return $this->fileTarget;
259
	}
260
261
262
	/**
263
	 * @param string $token
264
	 *
265
	 * @return ShareWrapper
266
	 */
267
	public function setToken(string $token): self {
268
		$this->token = $token;
269
270
		return $this;
271
	}
272
273
	/**
274
	 * @return string
275
	 */
276
	public function getToken(): string {
277
		return $this->token;
278
	}
279
280
281
	/**
282
	 * @param int $status
283
	 *
284
	 * @return ShareWrapper
285
	 */
286
	public function setStatus(int $status): self {
287
		$this->status = $status;
288
289
		return $this;
290
	}
291
292
	/**
293
	 * @return int
294
	 */
295
	public function getStatus(): int {
296
		return $this->status;
297
	}
298
299
300
	/**
301
	 * @param string $providerId
302
	 *
303
	 * @return $this
304
	 */
305
	public function setProviderId(string $providerId): self {
306
		$this->providerId = $providerId;
307
308
		return $this;
309
	}
310
311
	/**
312
	 * @return string
313
	 */
314
	public function getProviderId(): string {
315
		return $this->providerId;
316
	}
317
318
319
	/**
320
	 * @param DateTime $shareTime
321
	 *
322
	 * @return ShareWrapper
323
	 */
324
	public function setShareTime(DateTime $shareTime): self {
325
		$this->shareTime = $shareTime;
326
327
		return $this;
328
	}
329
330
	/**
331
	 * @return DateTime
332
	 */
333
	public function getShareTime(): DateTime {
334
		return $this->shareTime;
335
	}
336
337
338
	/**
339
	 * @param string $sharedWith
340
	 *
341
	 * @return ShareWrapper
342
	 */
343
	public function setSharedWith(string $sharedWith): self {
344
		$this->sharedWith = $sharedWith;
345
346
		return $this;
347
	}
348
349
	/**
350
	 * @return string
351
	 */
352
	public function getSharedWith(): string {
353
		return $this->sharedWith;
354
	}
355
356
	/**
357
	 * @param string $sharedBy
358
	 *
359
	 * @return ShareWrapper
360
	 */
361
	public function setSharedBy(string $sharedBy): self {
362
		$this->sharedBy = $sharedBy;
363
364
		return $this;
365
	}
366
367
	/**
368
	 * @return string
369
	 */
370
	public function getSharedBy(): string {
371
		return $this->sharedBy;
372
	}
373
374
375
	/**
376
	 * @param string $shareOwner
377
	 *
378
	 * @return ShareWrapper
379
	 */
380
	public function setShareOwner(string $shareOwner): self {
381
		$this->shareOwner = $shareOwner;
382
383
		return $this;
384
	}
385
386
	/**
387
	 * @return string
388
	 */
389
	public function getShareOwner(): string {
390
		return $this->shareOwner;
391
	}
392
393
394
	/**
395
	 * @param int $shareType
396
	 *
397
	 * @return ShareWrapper
398
	 */
399
	public function setShareType(int $shareType): self {
400
		$this->shareType = $shareType;
401
402
		return $this;
403
	}
404
405
	/**
406
	 * @return int
407
	 */
408
	public function getShareType(): int {
409
		return $this->shareType;
410
	}
411
412
413
	/**
414
	 * @param Circle $circle
415
	 *
416
	 * @return ShareWrapper
417
	 */
418
	public function setCircle(Circle $circle): self {
419
		$this->circle = $circle;
420
421
		return $this;
422
	}
423
424
	/**
425
	 * @return Circle
426
	 */
427
	public function getCircle(): Circle {
428
		return $this->circle;
429
	}
430
431
	/**
432
	 * @return bool
433
	 */
434
	public function hasCircle(): bool {
435
		return (!is_null($this->circle));
436
	}
437
438
439
	/**
440
	 * @param int $childId
441
	 *
442
	 * @return ShareWrapper
443
	 */
444
	public function setChildId(int $childId): self {
445
		$this->childId = $childId;
446
447
		return $this;
448
	}
449
450
	/**
451
	 * @return int
452
	 */
453
	public function getChildId(): int {
454
		return $this->childId;
455
	}
456
457
458
	/**
459
	 * @param string $childFileTarget
460
	 *
461
	 * @return ShareWrapper
462
	 */
463
	public function setChildFileTarget(string $childFileTarget): self {
464
		$this->childFileTarget = $childFileTarget;
465
466
		return $this;
467
	}
468
469
	/**
470
	 * @return string
471
	 */
472
	public function getChildFileTarget(): string {
473
		return $this->childFileTarget;
474
	}
475
476
477
	/**
478
	 * @param FileCacheWrapper $fileCache
479
	 *
480
	 * @return $this
481
	 */
482
	public function setFileCache(FileCacheWrapper $fileCache): self {
483
		$this->fileCache = $fileCache;
484
485
		return $this;
486
	}
487
488
	/**
489
	 * @return FileCacheWrapper
490
	 */
491
	public function getFileCache(): FileCacheWrapper {
492
		return $this->fileCache;
493
	}
494
495
	/**
496
	 * @return bool
497
	 */
498
	public function hasFileCache(): bool {
499
		return (!is_null($this->fileCache));
500
	}
501
502
503
	/**
504
	 * @param Member $initiator
505
	 *
506
	 * @return ShareWrapper
507
	 */
508
	public function setInitiator(Member $initiator): self {
509
		$this->initiator = $initiator;
510
511
		return $this;
512
	}
513
514
	/**
515
	 * @return Member
516
	 */
517
	public function getInitiator(): Member {
518
		return $this->initiator;
519
	}
520
521
	/**
522
	 * @return bool
523
	 */
524
	public function hasViewer(): bool {
525
		return (!is_null($this->initiator));
526
	}
527
528
529
	/**
530
	 * @param Member $owner
531
	 *
532
	 * @return ShareWrapper
533
	 */
534
	public function setOwner(Member $owner): self {
535
		$this->owner = $owner;
536
537
		return $this;
538
	}
539
540
	/**
541
	 * @return Member
542
	 */
543
	public function getOwner(): Member {
544
		return $this->owner;
545
	}
546
547
	/**
548
	 * @return bool
549
	 */
550
	public function hasOwner(): bool {
551
		return (!is_null($this->owner));
552
	}
553
554
555
	/**
556
	 * @param IRootFolder $rootFolder
557
	 * @param IUserManager $userManager
558
	 * @param IURLGenerator $urlGenerator
559
	 *
560
	 * @return IShare
561
	 * @throws IllegalIDChangeException
562
	 */
563
	public function getShare(
564
		IRootFolder $rootFolder,
565
		IUserManager $userManager,
566
		IURLGenerator $urlGenerator
567
	): ?IShare {
568
		$share = new Share($rootFolder, $userManager);
569
		$share->setId($this->getId());
570
		$share->setPermissions($this->getPermissions());
571
		$share->setNodeType($this->getItemType());
572
		$share->setNodeId($this->getFileSource());
573
		$share->setTarget($this->getFileTarget());
574
		$share->setProviderId($this->getProviderId());
575
		$share->setStatus($this->getStatus());
576
577
		$share->setShareTime($this->getShareTime())
578
			  ->setSharedWith($this->getSharedWith())
579
			  ->setSharedBy($this->getSharedBy())
580
			  ->setShareOwner($this->getShareOwner())
581
			  ->setShareType($this->getShareType());
582
583
		if ($this->getChildId() > 0) {
584
			$share->setTarget($this->getChildFileTarget());
585
		}
586
587
		$this->setShareDisplay($share, $urlGenerator);
588
589
		if ($this->hasFileCache()) {
590
			if (!$this->getFileCache()->isAccessible()) {
591
				return null;
592
			}
593
			$share->setNodeCacheEntry(
594
				Cache::cacheEntryFromData($this->getFileCache()->toCache(), OC::$server->getMimeTypeLoader())
595
			);
596
		}
597
598
		return $share;
599
	}
600
601
602
	/**
603
	 * @param IShare $share
604
	 * @param IURLGenerator $urlGenerator
605
	 */
606
	private function setShareDisplay(IShare $share, IURLGenerator $urlGenerator) {
607
		if (!$this->hasCircle()) {
608
			return;
609
		}
610
611
		$circle = $this->getCircle();
612
		$display = $circle->getDisplayName();
613
		if ($circle->getSource() === 0) {
614
			$display .= ' (Circle owned by ' . $circle->getOwner()->getDisplayName() . ')';
615
		} else {
616
			$display .= ' (' . Circle::$DEF_SOURCE[$circle->getSource()] . ')';
617
		}
618
619
		$share->setSharedWithDisplayName($display);
620
621
		$icon = $urlGenerator->getAbsoluteURL(
622
			$urlGenerator->imagePath(Application::APP_ID, 'black_circle.svg')
623
		);
624
		$share->setSharedWithAvatar($icon);
625
626
627
//		if (array_key_exists('circle_type', $data)
628
//			&& method_exists($share, 'setSharedWithDisplayName')) {
629
//			$name = $data['circle_name'];
630
//			if ($data['circle_alt_name'] !== '') {
631
//				$name = $data['circle_alt_name'];
632
//			}
633
//
634
//			$share->setSharedWithAvatar(CirclesService::getCircleIcon($data['circle_type']))
635
//				  ->setSharedWithDisplayName(
636
//					  sprintf(
637
//						  ' % s(%s, %s)', $name,
638
//						  $this->l10n->t(DeprecatedCircle::TypeLongString($data['circle_type'])),
639
//						  $this->miscService->getDisplayName($data['circle_owner'], true)
640
//					  )
641
//				  );
642
//		}
643
	}
644
645
646
	public function import(array $data): IDeserializable {
647
		$shareTime = new DateTime();
648
		$shareTime->setTimestamp($this->getInt('shareTime', $data));
649
650
		$this->setId($this->get('id', $data))
651
			 ->setShareType($this->getInt('shareType', $data))
652
			 ->setPermissions($this->getInt('permissions', $data))
653
			 ->setItemType($this->get('itemType', $data))
654
			 ->setItemSource($this->getInt('itemSource', $data))
655
			 ->setItemTarget($this->get('itemTarget', $data))
656
			 ->setFileSource($this->getInt('fileSource', $data))
657
			 ->setFileTarget($this->get('fileTarget', $data))
658
			 ->setSharedWith($this->get('shareWith', $data))
659
			 ->setSharedBy($this->get('uidInitiator', $data))
660
			 ->setShareOwner($this->get('uidOwner', $data))
661
			 ->setToken($this->get('token', $data))
662
			 ->setShareTime($shareTime);
663
664
		$this->setChildId($this->getInt('childId', $data))
665
			 ->setChildFileTarget($this->get('childFileTarget', $data))
666
			 ->setProviderId(ShareByCircleProvider::IDENTIFIER)
667
			 ->setStatus(Ishare::STATUS_ACCEPTED);
668
669
		try {
670
			$circle = new Circle();
671
			$this->setCircle($circle->import($this->getArray('circle', $data)));
672
		} catch (InvalidItemException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
673
		}
674
675
		try {
676
			$fileCache = new FileCacheWrapper();
677
			$this->setFileCache($fileCache->import($this->getArray('fileCache', $data)));
678
		} catch (InvalidItemException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
679
		}
680
681
		try {
682
			$owner = new Member();
683
			$this->setOwner($owner->import($this->getArray('owner', $data)));
684
		} catch (InvalidItemException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
685
		}
686
687
		try {
688
			$member = new Member();
689
			$this->setInitiator($member->import($this->getArray('viewer', $data)));
690
		} catch (InvalidItemException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
691
		}
692
693
		return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (OCA\Circles\Model\ShareWrapper) is incompatible with the return type declared by the interface daita\MySmallPhpTools\IDeserializable::import of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
694
	}
695
696
697
	/**
698
	 * @param array $data
699
	 * @param string $prefix
700
	 *
701
	 * @return INC22QueryRow
702
	 */
703
	public function importFromDatabase(array $data, string $prefix = ''): INC22QueryRow {
704
		$shareTime = new DateTime();
705
		$shareTime->setTimestamp($this->getInt($prefix . 'stime', $data));
706
707
		$this->setId($this->get($prefix . 'id', $data))
708
			 ->setShareType($this->getInt($prefix . 'share_type', $data))
709
			 ->setPermissions($this->getInt($prefix . 'permissions', $data))
710
			 ->setItemType($this->get($prefix . 'item_type', $data))
711
			 ->setItemSource($this->getInt($prefix . 'item_source', $data))
712
			 ->setItemTarget($this->get($prefix . 'item_target', $data))
713
			 ->setFileSource($this->getInt($prefix . 'file_source', $data))
714
			 ->setFileTarget($this->get($prefix . 'file_target', $data))
715
			 ->setSharedWith($this->get($prefix . 'share_with', $data))
716
			 ->setSharedBy($this->get($prefix . 'uid_initiator', $data))
717
			 ->setShareOwner($this->get($prefix . 'uid_owner', $data))
718
			 ->setToken($this->get($prefix . 'token', $data))
719
			 ->setShareTime($shareTime);
720
721
//		if (($password = $this->get('personal_password', $data, '')) !== '') {
722
//			$share->setPassword($this->get('personal_password', $data, ''));
723
//		} else if (($password = $this->get('password', $data, '')) !== '') {
724
//			$share->setPassword($this->get('password', $data, ''));
725
//		}
726
727
		$this->setChildId($this->getInt($prefix . 'child_id', $data))
728
			 ->setChildFileTarget($this->get($prefix . 'child_file_target', $data))
729
			 ->setProviderId(ShareByCircleProvider::IDENTIFIER)
730
			 ->setStatus(Ishare::STATUS_ACCEPTED);
731
732
		$this->getManager()->manageImportFromDatabase($this, $data, $prefix);
733
734
		return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (OCA\Circles\Model\ShareWrapper) is incompatible with the return type declared by the interface daita\MySmallPhpTools\Db...Row::importFromDatabase of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
735
	}
736
737
738
	/**
739
	 * @return string[]
740
	 */
741
	public function jsonSerialize(): array {
742
		$arr = [
743
			'id'              => $this->getId(),
744
			'shareType'       => $this->getShareType(),
745
			'providerId'      => $this->getProviderId(),
746
			'permissions'     => $this->getPermissions(),
747
			'itemType'        => $this->getItemType(),
748
			'itemSource'      => $this->getItemSource(),
749
			'itemTarget'      => $this->getItemTarget(),
750
			'fileSource'      => $this->getFileSource(),
751
			'fileTarget'      => $this->getFileTarget(),
752
			'status'          => $this->getStatus(),
753
			'shareTime'       => $this->getShareTime()->getTimestamp(),
754
			'sharedWith'      => $this->getSharedWith(),
755
			'sharedBy'        => $this->getSharedBy(),
756
			'shareOwner'      => $this->getShareOwner(),
757
			'token'           => $this->getToken(),
758
			'childId'         => $this->getChildId(),
759
			'childFileTarget' => $this->getChildFileTarget()
760
		];
761
762
		if ($this->hasOwner()) {
763
			$arr['owner'] = $this->getOwner();
764
		}
765
766
		if ($this->hasCircle()) {
767
			$arr['circle'] = $this->getCircle();
768
		}
769
770
		if ($this->hasViewer()) {
771
			$arr['viewer'] = $this->getInitiator();
772
		}
773
774
		if ($this->hasFileCache()) {
775
			$arr['fileCache'] = $this->getFileCache();
776
		}
777
778
		return $arr;
779
	}
780
781
}
782
783