getItemIdsFromParentPath($circlesManager, $itemId); } catch (Exception $e) { $itemEntries = [['id' => $itemId]]; } // TODO: create related item first, apply share recipient then. // cleaner way ? // should be already available in the current app $itemIds = array_values( array_filter( array_map(function (array $entry): int { return (($entry['type'] ?? 'files') === 'files') ? (int)$entry['id'] : 0; }, $itemEntries) ) ); foreach ($this->filesShareRequest->getSharesByItemIds($itemIds) as $share) { if ($related === null) { $related = $this->convertToRelatedResource($share); } $this->processShareRecipient($circlesManager, $related, $share); } $related = $this->managerGroupFolders($circlesManager, $related, $itemEntries); return $related; } public function getItemsAvailableToEntity(FederatedUser $entity): array { switch ($entity->getBasedOn()->getSource()) { case Member::TYPE_USER: $shares = $this->filesShareRequest->getSharesToUser($entity->getUserId()); break; case Member::TYPE_GROUP: $shares = $this->filesShareRequest->getSharesToGroup($entity->getUserId()); break; case Member::TYPE_CIRCLE: // We skip circle shares for related resources as they are covered by team resources return []; default: return []; } return array_map(function (FilesShare $share): string { return (string)$share->getFileId(); }, $shares); } public function improveRelatedResource(CirclesManager $circlesManager, IRelatedResource $entry): void { $current = $circlesManager->getCurrentFederatedUser(); if (!$current->isLocal() || $current->getUserType() !== Member::TYPE_USER) { return; } $paths = $this->rootFolder->getUserFolder($current->getUserId()) ->getById((int)$entry->getItemId()); if (sizeof($paths) > 0) { $entry->setTitle($paths[0]->getName()); } } private function convertToRelatedResource(FilesShare $share): IRelatedResource { $related = new RelatedResource(self::PROVIDER_ID, (string)$share->getFileId()); $related->setTitle(trim($share->getFileTarget(), '/')); $related->setSubtitle($this->l10n->t('Files')); $related->setTooltip($this->l10n->t('File "%s"', $share->getFileTarget())); $related->setIcon( $this->urlGenerator->getAbsoluteURL( $this->urlGenerator->imagePath( 'files', 'app.svg' ) ) ); $related->setPreview( $this->urlGenerator->linkToRouteAbsolute( 'core.Preview.getPreviewByFileId', ['x' => 64, 'y' => 64, 'fileId' => $share->getFileId()] ) ); $related->setUrl( $this->urlGenerator->linkToRouteAbsolute('files.View.showFile', ['fileid' => $share->getFileId()]) ); $related->setMetas( [ RelatedResource::ITEM_LAST_UPDATE => $share->getFileLastUpdate(), RelatedResource::ITEM_OWNER => $share->getFileOwner(), // RelatedResource::LINK_CREATOR => $share->getShareCreator(), RelatedResource::LINK_CREATION => $share->getShareTime() ] ); $keywords = preg_split('/[\/_\-. ]/', ltrim(strtolower($share->getFileTarget()), '/')); if (is_array($keywords)) { $related->setMetaArray(RelatedResource::ITEM_KEYWORDS, $keywords); } return $related; } /** * @param list $itemEntries */ private function managerGroupFolders( CirclesManager $circlesManager, ?IRelatedResource $related, array $itemEntries, ): ?IRelatedResource { foreach ($itemEntries as $entry) { if (($entry['type'] ?? '') !== 'groupfolder') { continue; } try { $folder = $this->groupFoldersRRProvider->getFolder($entry['id']); } catch (GroupFolderNotFoundException $e) { continue; } if ($related === null) { $related = $this->groupFoldersRRProvider->convertToRelatedResource($folder); } $this->groupFoldersRRProvider->processApplicableMap( $circlesManager, $related, $folder['groups'] ?? [] ); } return $related; } /** * @param int $itemId * * @return list * @throws InvalidPathException * @throws NotFoundException * @throws NotPermittedException * @throws NoUserException */ private function getItemIdsFromParentPath(CirclesManager $circlesManager, int $itemId): array { $current = $circlesManager->getCurrentFederatedUser(); if (!$current->isLocal() || $current->getUserType() !== Member::TYPE_USER) { return [['id' => $itemId]]; } $paths = $this->rootFolder->getUserFolder($current->getUserId()) ->getById($itemId); $itemEntries = []; foreach ($paths as $path) { while (true) { $mountPoint = $path->getMountPoint(); if ($mountPoint instanceof GroupMountPoint) { $itemEntries[] = [ 'id' => $mountPoint->getFolderId(), 'type' => 'groupfolder' ]; } if ($path->getId() === 0) { break; } $itemEntries[] = ['id' => $path->getId()]; $path = $path->getParent(); } } return $itemEntries; } /** * @param RelatedResource $related * @param FilesShare $share */ private function processShareRecipient( CirclesManager $circlesManager, RelatedResource $related, FilesShare $share, ) { try { $sharedWith = $this->convertShareRecipient( $circlesManager, $share->getShareType(), $share->getSharedWith() ); if ($share->getShareType() === IShare::TYPE_USER) { $shareCreator = $this->convertShareRecipient( $circlesManager, IShare::TYPE_USER, $share->getShareCreator() ); $related->mergeVirtualGroup( [ $sharedWith->getSingleId(), $shareCreator->getSingleId() ] ); } else { $related->addRecipient($sharedWith->getSingleId()) ->setAsGroupShared(); } } catch (Exception $e) { } } /** * @param int $shareType * @param string $sharedWith * * @return FederatedUser * @throws Exception */ private function convertShareRecipient( CirclesManager $circlesManager, int $shareType, string $sharedWith, ): FederatedUser { $type = match ($shareType) { IShare::TYPE_USER => Member::TYPE_USER, IShare::TYPE_GROUP => Member::TYPE_GROUP, IShare::TYPE_CIRCLE => Member::TYPE_SINGLE, default => throw new Exception('unknown share type (' . $shareType . ')'), }; return $circlesManager->getFederatedUser($sharedWith, $type); } }