1<?php 2 3declare(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 <maxence@artificial-owl.com> 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 32namespace OCA\Circles\Model; 33 34use ArtificialOwl\MySmallPhpTools\Db\Nextcloud\nc22\INC22QueryRow; 35use ArtificialOwl\MySmallPhpTools\Exceptions\InvalidItemException; 36use ArtificialOwl\MySmallPhpTools\IDeserializable; 37use ArtificialOwl\MySmallPhpTools\Traits\Nextcloud\nc22\TNC22Deserialize; 38use ArtificialOwl\MySmallPhpTools\Traits\TArrayTools; 39use DateTime; 40use JsonSerializable; 41use OC; 42use OC\Files\Cache\Cache; 43use OC\Share20\Share; 44use OCA\Circles\AppInfo\Application; 45use OCA\Circles\ShareByCircleProvider; 46use OCP\Files\IRootFolder; 47use OCP\IURLGenerator; 48use OCP\IUserManager; 49use OCP\Share\Exceptions\IllegalIDChangeException; 50use OCP\Share\IShare; 51 52/** 53 * Class ShareWrapper 54 * 55 * @package OCA\Circles\Model 56 */ 57class ShareWrapper extends ManagedModel implements IDeserializable, INC22QueryRow, JsonSerializable { 58 use TArrayTools; 59 use TNC22Deserialize; 60 61 62 /** @var string */ 63 private $id = ''; 64 65 /** @var int */ 66 private $permissions = 0; 67 68 /** @var string */ 69 private $itemType = ''; 70 71 /** @var int */ 72 private $itemSource = 0; 73 74 /** @var string */ 75 private $itemTarget = ''; 76 77 /** @var int */ 78 private $fileSource = 0; 79 80 /** @var string */ 81 private $fileTarget = ''; 82 83 /** @var string */ 84 private $token = ''; 85 86 /** @var int */ 87 private $status = 0; 88 89 /** @var string */ 90 private $providerId = ''; 91 92 /** @var DateTime */ 93 private $shareTime = ''; 94 95 /** @var string */ 96 private $sharedWith = ''; 97 98 /** @var string */ 99 private $sharedBy = ''; 100 101 /** @var string */ 102 private $shareOwner = ''; 103 104 /** @var int */ 105 private $shareType = 0; 106 107 /** @var Circle */ 108 private $circle; 109 110 /** @var int */ 111 private $childId = 0; 112 113 /** @var string */ 114 private $childFileTarget = ''; 115 116 /** @var int */ 117 private $childPermissions = 0; 118 119 /** @var FileCacheWrapper */ 120 private $fileCache; 121 122 /** @var Member */ 123 private $initiator; 124 125 /** @var Member */ 126 private $owner; 127 128 /** @var ShareToken */ 129 private $shareToken; 130 131 132 /** 133 * @param string $id 134 * 135 * @return ShareWrapper 136 */ 137 public function setId(string $id): self { 138 $this->id = $id; 139 140 return $this; 141 } 142 143 /** 144 * @return string 145 */ 146 public function getId(): string { 147 return $this->id; 148 } 149 150 151 /** 152 * @param int $permissions 153 * 154 * @return ShareWrapper 155 */ 156 public function setPermissions(int $permissions): self { 157 $this->permissions = $permissions; 158 159 return $this; 160 } 161 162 /** 163 * @return int 164 */ 165 public function getPermissions(): int { 166 return $this->permissions; 167 } 168 169 170 /** 171 * @param string $itemType 172 * 173 * @return ShareWrapper 174 */ 175 public function setItemType(string $itemType): self { 176 $this->itemType = $itemType; 177 178 return $this; 179 } 180 181 /** 182 * @return string 183 */ 184 public function getItemType(): string { 185 return $this->itemType; 186 } 187 188 189 /** 190 * @param int $itemSource 191 * 192 * @return ShareWrapper 193 */ 194 public function setItemSource(int $itemSource): self { 195 $this->itemSource = $itemSource; 196 197 return $this; 198 } 199 200 /** 201 * @return int 202 */ 203 public function getItemSource(): int { 204 return $this->itemSource; 205 } 206 207 208 /** 209 * @param string $itemTarget 210 * 211 * @return ShareWrapper 212 */ 213 public function setItemTarget(string $itemTarget): self { 214 $this->itemTarget = $itemTarget; 215 216 return $this; 217 } 218 219 /** 220 * @return string 221 */ 222 public function getItemTarget(): string { 223 return $this->itemTarget; 224 } 225 226 227 /** 228 * @param int $fileSource 229 * 230 * @return ShareWrapper 231 */ 232 public function setFileSource(int $fileSource): self { 233 $this->fileSource = $fileSource; 234 235 return $this; 236 } 237 238 /** 239 * @return int 240 */ 241 public function getFileSource(): int { 242 return $this->fileSource; 243 } 244 245 246 /** 247 * @param string $fileTarget 248 * 249 * @return ShareWrapper 250 */ 251 public function setFileTarget(string $fileTarget): self { 252 $this->fileTarget = $fileTarget; 253 254 return $this; 255 } 256 257 /** 258 * @return string 259 */ 260 public function getFileTarget(): string { 261 return $this->fileTarget; 262 } 263 264 265 /** 266 * @param string $token 267 * 268 * @return ShareWrapper 269 */ 270 public function setToken(string $token): self { 271 $this->token = $token; 272 273 return $this; 274 } 275 276 /** 277 * @return string 278 */ 279 public function getToken(): string { 280 return $this->token; 281 } 282 283 284 /** 285 * @param int $status 286 * 287 * @return ShareWrapper 288 */ 289 public function setStatus(int $status): self { 290 $this->status = $status; 291 292 return $this; 293 } 294 295 /** 296 * @return int 297 */ 298 public function getStatus(): int { 299 return $this->status; 300 } 301 302 303 /** 304 * @param string $providerId 305 * 306 * @return $this 307 */ 308 public function setProviderId(string $providerId): self { 309 $this->providerId = $providerId; 310 311 return $this; 312 } 313 314 /** 315 * @return string 316 */ 317 public function getProviderId(): string { 318 return $this->providerId; 319 } 320 321 322 /** 323 * @param DateTime $shareTime 324 * 325 * @return ShareWrapper 326 */ 327 public function setShareTime(DateTime $shareTime): self { 328 $this->shareTime = $shareTime; 329 330 return $this; 331 } 332 333 /** 334 * @return DateTime 335 */ 336 public function getShareTime(): DateTime { 337 return $this->shareTime; 338 } 339 340 341 /** 342 * @param string $sharedWith 343 * 344 * @return ShareWrapper 345 */ 346 public function setSharedWith(string $sharedWith): self { 347 $this->sharedWith = $sharedWith; 348 349 return $this; 350 } 351 352 /** 353 * @return string 354 */ 355 public function getSharedWith(): string { 356 return $this->sharedWith; 357 } 358 359 /** 360 * @param string $sharedBy 361 * 362 * @return ShareWrapper 363 */ 364 public function setSharedBy(string $sharedBy): self { 365 $this->sharedBy = $sharedBy; 366 367 return $this; 368 } 369 370 /** 371 * @return string 372 */ 373 public function getSharedBy(): string { 374 return $this->sharedBy; 375 } 376 377 378 /** 379 * @param string $shareOwner 380 * 381 * @return ShareWrapper 382 */ 383 public function setShareOwner(string $shareOwner): self { 384 $this->shareOwner = $shareOwner; 385 386 return $this; 387 } 388 389 /** 390 * @return string 391 */ 392 public function getShareOwner(): string { 393 return $this->shareOwner; 394 } 395 396 397 /** 398 * @param int $shareType 399 * 400 * @return ShareWrapper 401 */ 402 public function setShareType(int $shareType): self { 403 $this->shareType = $shareType; 404 405 return $this; 406 } 407 408 /** 409 * @return int 410 */ 411 public function getShareType(): int { 412 return $this->shareType; 413 } 414 415 416 /** 417 * @param Circle $circle 418 * 419 * @return ShareWrapper 420 */ 421 public function setCircle(Circle $circle): self { 422 $this->circle = $circle; 423 424 return $this; 425 } 426 427 /** 428 * @return Circle 429 */ 430 public function getCircle(): Circle { 431 return $this->circle; 432 } 433 434 /** 435 * @return bool 436 */ 437 public function hasCircle(): bool { 438 return (!is_null($this->circle)); 439 } 440 441 442 /** 443 * @param int $childId 444 * 445 * @return ShareWrapper 446 */ 447 public function setChildId(int $childId): self { 448 $this->childId = $childId; 449 450 return $this; 451 } 452 453 /** 454 * @return int 455 */ 456 public function getChildId(): int { 457 return $this->childId; 458 } 459 460 461 /** 462 * @param string $childFileTarget 463 * 464 * @return ShareWrapper 465 */ 466 public function setChildFileTarget(string $childFileTarget): self { 467 $this->childFileTarget = $childFileTarget; 468 469 return $this; 470 } 471 472 /** 473 * @return string 474 */ 475 public function getChildFileTarget(): string { 476 return $this->childFileTarget; 477 } 478 479 480 /** 481 * @param int $childPermissions 482 * 483 * @return ShareWrapper 484 */ 485 public function setChildPermissions(int $childPermissions): self { 486 $this->childPermissions = $childPermissions; 487 488 return $this; 489 } 490 491 /** 492 * @return int 493 */ 494 public function getChildPermissions(): int { 495 return $this->childPermissions; 496 } 497 498 499 /** 500 * @param FileCacheWrapper $fileCache 501 * 502 * @return $this 503 */ 504 public function setFileCache(FileCacheWrapper $fileCache): self { 505 $this->fileCache = $fileCache; 506 507 return $this; 508 } 509 510 /** 511 * @return FileCacheWrapper 512 */ 513 public function getFileCache(): FileCacheWrapper { 514 return $this->fileCache; 515 } 516 517 /** 518 * @return bool 519 */ 520 public function hasFileCache(): bool { 521 return (!is_null($this->fileCache)); 522 } 523 524 525 /** 526 * @param Member $initiator 527 * 528 * @return ShareWrapper 529 */ 530 public function setInitiator(Member $initiator): self { 531 $this->initiator = $initiator; 532 533 return $this; 534 } 535 536 /** 537 * @return Member 538 */ 539 public function getInitiator(): Member { 540 return $this->initiator; 541 } 542 543 /** 544 * @return bool 545 */ 546 public function hasInitiator(): bool { 547 return (!is_null($this->initiator)); 548 } 549 550 551 /** 552 * @param Member $owner 553 * 554 * @return ShareWrapper 555 */ 556 public function setOwner(Member $owner): self { 557 $this->owner = $owner; 558 559 return $this; 560 } 561 562 /** 563 * @return Member 564 */ 565 public function getOwner(): Member { 566 return $this->owner; 567 } 568 569 /** 570 * @return bool 571 */ 572 public function hasOwner(): bool { 573 return (!is_null($this->owner)); 574 } 575 576 577 /** 578 * @param ShareToken $shareToken 579 * 580 * @return ShareWrapper 581 */ 582 public function setShareToken(ShareToken $shareToken): self { 583 $this->shareToken = $shareToken; 584 585 return $this; 586 } 587 588 /** 589 * @return ShareToken 590 */ 591 public function getShareToken(): ShareToken { 592 return $this->shareToken; 593 } 594 595 /** 596 * @return bool 597 */ 598 public function hasShareToken(): bool { 599 return !is_null($this->shareToken); 600 } 601 602 603 /** 604 * @param IRootFolder $rootFolder 605 * @param IUserManager $userManager 606 * @param IURLGenerator $urlGenerator 607 * @param bool $nullOnMissingFileCache 608 * 609 * @return IShare 610 * @throws IllegalIDChangeException 611 */ 612 public function getShare( 613 IRootFolder $rootFolder, 614 IUserManager $userManager, 615 IURLGenerator $urlGenerator, 616 bool $nullOnMissingFileCache = false 617 ): ?IShare { 618 $share = new Share($rootFolder, $userManager); 619 $share->setId($this->getId()); 620 $share->setPermissions($this->getPermissions()); 621 $share->setNodeType($this->getItemType()); 622 $share->setNodeId($this->getFileSource()); 623 $share->setTarget($this->getFileTarget()); 624 $share->setProviderId($this->getProviderId()); 625 $share->setStatus($this->getStatus()); 626 627 $share->setShareTime($this->getShareTime()) 628 ->setSharedWith($this->getSharedWith()) 629 ->setSharedBy($this->getSharedBy()) 630 ->setShareOwner($this->getShareOwner()) 631 ->setShareType($this->getShareType()); 632 633 if ($this->getChildId() > 0) { 634 $share->setTarget($this->getChildFileTarget()); 635 if ($this->getChildPermissions() < $this->getPermissions()) { 636 $share->setPermissions($this->getChildPermissions()); 637 } 638 } 639 640 $this->setShareDisplay($share, $urlGenerator); 641 642 if ($this->hasFileCache()) { 643 if (!$this->getFileCache()->isAccessible()) { 644 return null; 645 } 646 $share->setNodeCacheEntry( 647 Cache::cacheEntryFromData($this->getFileCache()->toCache(), OC::$server->getMimeTypeLoader()) 648 ); 649 } elseif ($nullOnMissingFileCache) { 650 return null; 651 } 652 653 return $share; 654 } 655 656 657 /** 658 * @param IShare $share 659 * @param IURLGenerator $urlGenerator 660 */ 661 private function setShareDisplay(IShare $share, IURLGenerator $urlGenerator) { 662 if (!$this->hasCircle()) { 663 return; 664 } 665 666 $circle = $this->getCircle(); 667 if ($circle->isConfig(Circle::CFG_PERSONAL) 668 && $this->hasInitiator() 669 && $circle->getOwner()->getSingleId() !== $this->getInitiator()->getSingleId()) { 670 $share->setSharedWithDisplayName(' '); 671 672 return; 673 } 674 675 $display = $circle->getDisplayName(); 676 if ($circle->getSource() === Member::TYPE_CIRCLE) { 677 $display .= ' (Circle owned by ' . $circle->getOwner()->getDisplayName() . ')'; 678 } else { 679 $display .= ' (' . Circle::$DEF_SOURCE[$circle->getSource()] . ')'; 680 } 681 682 $share->setSharedWithDisplayName($display); 683 684 $icon = $urlGenerator->getAbsoluteURL( 685 $urlGenerator->imagePath(Application::APP_ID, 'circles.svg') 686 ); 687 $share->setSharedWithAvatar($icon); 688 689 690// if (array_key_exists('circle_type', $data) 691// && method_exists($share, 'setSharedWithDisplayName')) { 692// $name = $data['circle_name']; 693// if ($data['circle_alt_name'] !== '') { 694// $name = $data['circle_alt_name']; 695// } 696// 697// $share->setSharedWithAvatar(CirclesService::getCircleIcon($data['circle_type'])) 698// ->setSharedWithDisplayName( 699// sprintf( 700// ' % s(%s, %s)', $name, 701// $this->l10n->t(DeprecatedCircle::TypeLongString($data['circle_type'])), 702// $this->miscService->getDisplayName($data['circle_owner'], true) 703// ) 704// ); 705// } 706 } 707 708 709 /** 710 * @param array $data 711 * 712 * @return IDeserializable 713 * @throws InvalidItemException 714 */ 715 public function import(array $data): IDeserializable { 716 if ($this->getInt('id', $data) === 0) { 717 throw new InvalidItemException(); 718 } 719 720 $shareTime = new DateTime(); 721 $shareTime->setTimestamp($this->getInt('shareTime', $data)); 722 723 $this->setId($this->get('id', $data)) 724 ->setShareType($this->getInt('shareType', $data)) 725 ->setPermissions($this->getInt('permissions', $data)) 726 ->setItemType($this->get('itemType', $data)) 727 ->setItemSource($this->getInt('itemSource', $data)) 728 ->setItemTarget($this->get('itemTarget', $data)) 729 ->setFileSource($this->getInt('fileSource', $data)) 730 ->setFileTarget($this->get('fileTarget', $data)) 731 ->setSharedWith($this->get('sharedWith', $data)) 732 ->setSharedBy($this->get('uidInitiator', $data)) 733 ->setShareOwner($this->get('uidOwner', $data)) 734 ->setToken($this->get('token', $data)) 735 ->setShareTime($shareTime); 736 737 $this->setChildId($this->getInt('childId', $data)) 738 ->setChildFileTarget($this->get('childFileTarget', $data)) 739 ->setChildPermissions($this->getInt('childPermissions', $data)) 740 ->setProviderId(ShareByCircleProvider::IDENTIFIER) 741 ->setStatus(Ishare::STATUS_ACCEPTED); 742 743 try { 744 $circle = new Circle(); 745 $this->setCircle($circle->import($this->getArray('circle', $data))); 746 } catch (InvalidItemException $e) { 747 } 748 749 try { 750 $fileCache = new FileCacheWrapper(); 751 $this->setFileCache($fileCache->import($this->getArray('fileCache', $data))); 752 } catch (InvalidItemException $e) { 753 } 754 755 try { 756 $owner = new Member(); 757 $this->setOwner($owner->import($this->getArray('owner', $data))); 758 } catch (InvalidItemException $e) { 759 } 760 761 try { 762 $member = new Member(); 763 $this->setInitiator($member->import($this->getArray('viewer', $data))); 764 } catch (InvalidItemException $e) { 765 } 766 767 try { 768 $shareToken = new ShareToken(); 769 $this->setShareToken($shareToken->import($this->getArray('shareToken', $data))); 770 } catch (InvalidItemException $e) { 771 } 772 773 return $this; 774 } 775 776 777 /** 778 * @param array $data 779 * @param string $prefix 780 * 781 * @return INC22QueryRow 782 */ 783 public function importFromDatabase(array $data, string $prefix = ''): INC22QueryRow { 784 $shareTime = new DateTime(); 785 $shareTime->setTimestamp($this->getInt($prefix . 'stime', $data)); 786 787 $this->setId($this->get($prefix . 'id', $data)) 788 ->setShareType($this->getInt($prefix . 'share_type', $data)) 789 ->setPermissions($this->getInt($prefix . 'permissions', $data)) 790 ->setItemType($this->get($prefix . 'item_type', $data)) 791 ->setItemSource($this->getInt($prefix . 'item_source', $data)) 792 ->setItemTarget($this->get($prefix . 'item_target', $data)) 793 ->setFileSource($this->getInt($prefix . 'file_source', $data)) 794 ->setFileTarget($this->get($prefix . 'file_target', $data)) 795 ->setSharedWith($this->get($prefix . 'share_with', $data)) 796 ->setSharedBy($this->get($prefix . 'uid_initiator', $data)) 797 ->setShareOwner($this->get($prefix . 'uid_owner', $data)) 798 ->setToken($this->get($prefix . 'token', $data)) 799 ->setShareTime($shareTime); 800 801// if (($password = $this->get('personal_password', $data, '')) !== '') { 802// $share->setPassword($this->get('personal_password', $data, '')); 803// } else if (($password = $this->get('password', $data, '')) !== '') { 804// $share->setPassword($this->get('password', $data, '')); 805// } 806 807 $this->setChildId($this->getInt($prefix . 'child_id', $data)) 808 ->setChildFileTarget($this->get($prefix . 'child_file_target', $data)) 809 ->setChildPermissions($this->getInt($prefix . 'child_permissions', $data)) 810 ->setProviderId(ShareByCircleProvider::IDENTIFIER) 811 ->setStatus(Ishare::STATUS_ACCEPTED); 812 813 $this->getManager()->manageImportFromDatabase($this, $data, $prefix); 814 815 return $this; 816 } 817 818 819 /** 820 * @return string[] 821 */ 822 public function jsonSerialize(): array { 823 $arr = [ 824 'id' => $this->getId(), 825 'shareType' => $this->getShareType(), 826 'providerId' => $this->getProviderId(), 827 'permissions' => $this->getPermissions(), 828 'itemType' => $this->getItemType(), 829 'itemSource' => $this->getItemSource(), 830 'itemTarget' => $this->getItemTarget(), 831 'fileSource' => $this->getFileSource(), 832 'fileTarget' => $this->getFileTarget(), 833 'status' => $this->getStatus(), 834 'shareTime' => $this->getShareTime()->getTimestamp(), 835 'sharedWith' => $this->getSharedWith(), 836 'sharedBy' => $this->getSharedBy(), 837 'shareOwner' => $this->getShareOwner(), 838 'token' => $this->getToken(), 839 'childId' => $this->getChildId(), 840 'childFileTarget' => $this->getChildFileTarget(), 841 'childPermissions' => $this->getChildPermissions() 842 ]; 843 844 if ($this->hasOwner()) { 845 $arr['owner'] = $this->getOwner(); 846 } 847 848 if ($this->hasCircle()) { 849 $arr['circle'] = $this->getCircle(); 850 } 851 852 if ($this->hasInitiator()) { 853 $arr['viewer'] = $this->getInitiator(); 854 } 855 856 if ($this->hasFileCache()) { 857 $arr['fileCache'] = $this->getFileCache(); 858 } 859 860 if ($this->hasShareToken()) { 861 $arr['shareToken'] = $this->getShareToken(); 862 } 863 864 return $arr; 865 } 866} 867