diff options
Diffstat (limited to 'apps/comments/lib')
21 files changed, 418 insertions, 1024 deletions
diff --git a/apps/comments/lib/Activity/Filter.php b/apps/comments/lib/Activity/Filter.php index 0ad6d9bf4ac..8dcafd872d7 100644 --- a/apps/comments/lib/Activity/Filter.php +++ b/apps/comments/lib/Activity/Filter.php @@ -1,26 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> - * - * @author Joas Schilling <coding@schilljs.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Comments\Activity; use OCP\Activity\IFilter; @@ -28,64 +11,40 @@ use OCP\IL10N; use OCP\IURLGenerator; class Filter implements IFilter { - - /** @var IL10N */ - protected $l; - - /** @var IURLGenerator */ - protected $url; - - public function __construct(IL10N $l, IURLGenerator $url) { - $this->l = $l; - $this->url = $url; + public function __construct( + protected IL10N $l, + protected IURLGenerator $url, + ) { } - /** - * @return string Lowercase a-z only identifier - * @since 11.0.0 - */ - public function getIdentifier() { + public function getIdentifier(): string { return 'comments'; } - /** - * @return string A translated string - * @since 11.0.0 - */ - public function getName() { + public function getName(): string { return $this->l->t('Comments'); } - /** - * @return int - * @since 11.0.0 - */ - public function getPriority() { + public function getPriority(): int { return 40; } - /** - * @return string Full URL to an icon, empty string when none is given - * @since 11.0.0 - */ - public function getIcon() { + public function getIcon(): string { return $this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/comment.svg')); } /** * @param string[] $types * @return string[] An array of allowed apps from which activities should be displayed - * @since 11.0.0 */ - public function filterTypes(array $types) { + public function filterTypes(array $types): array { return $types; } /** * @return string[] An array of allowed apps from which activities should be displayed - * @since 11.0.0 */ - public function allowedApps() { + public function allowedApps(): array { return ['comments']; } } diff --git a/apps/comments/lib/Activity/Listener.php b/apps/comments/lib/Activity/Listener.php index 4b676b5cbb1..45064f4a6be 100644 --- a/apps/comments/lib/Activity/Listener.php +++ b/apps/comments/lib/Activity/Listener.php @@ -1,28 +1,10 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Joas Schilling <coding@schilljs.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ - namespace OCA\Comments\Activity; use OCP\Activity\IManager; @@ -36,50 +18,20 @@ use OCP\IUserSession; use OCP\Share\IShareHelper; class Listener { - /** @var IManager */ - protected $activityManager; - /** @var IUserSession */ - protected $session; - /** @var \OCP\App\IAppManager */ - protected $appManager; - /** @var \OCP\Files\Config\IMountProviderCollection */ - protected $mountCollection; - /** @var \OCP\Files\IRootFolder */ - protected $rootFolder; - /** @var IShareHelper */ - protected $shareHelper; - - /** - * Listener constructor. - * - * @param IManager $activityManager - * @param IUserSession $session - * @param IAppManager $appManager - * @param IMountProviderCollection $mountCollection - * @param IRootFolder $rootFolder - * @param IShareHelper $shareHelper - */ - public function __construct(IManager $activityManager, - IUserSession $session, - IAppManager $appManager, - IMountProviderCollection $mountCollection, - IRootFolder $rootFolder, - IShareHelper $shareHelper) { - $this->activityManager = $activityManager; - $this->session = $session; - $this->appManager = $appManager; - $this->mountCollection = $mountCollection; - $this->rootFolder = $rootFolder; - $this->shareHelper = $shareHelper; + public function __construct( + protected IManager $activityManager, + protected IUserSession $session, + protected IAppManager $appManager, + protected IMountProviderCollection $mountCollection, + protected IRootFolder $rootFolder, + protected IShareHelper $shareHelper, + ) { } - /** - * @param CommentsEvent $event - */ - public function commentEvent(CommentsEvent $event) { + public function commentEvent(CommentsEvent $event): void { if ($event->getComment()->getObjectType() !== 'files' || $event->getEvent() !== CommentsEvent::EVENT_ADD - || !$this->appManager->isInstalled('activity')) { + || !$this->appManager->isEnabledForAnyone('activity')) { // Comment not for file, not adding a comment or no activity-app enabled (save the energy) return; } @@ -115,7 +67,7 @@ class Listener { $activity->setApp('comments') ->setType('comments') ->setAuthor($actor) - ->setObject($event->getComment()->getObjectType(), (int) $event->getComment()->getObjectId()) + ->setObject($event->getComment()->getObjectType(), (int)$event->getComment()->getObjectId()) ->setMessage('add_comment_message', [ 'commentId' => $event->getComment()->getId(), ]); @@ -127,7 +79,7 @@ class Listener { $activity->setSubject('add_comment_subject', [ 'actor' => $actor, - 'fileId' => (int) $event->getComment()->getObjectId(), + 'fileId' => (int)$event->getComment()->getObjectId(), 'filePath' => trim($path, '/'), ]); $this->activityManager->publish($activity); diff --git a/apps/comments/lib/Activity/Provider.php b/apps/comments/lib/Activity/Provider.php index fca3b9e75d5..ee53357efdb 100644 --- a/apps/comments/lib/Activity/Provider.php +++ b/apps/comments/lib/Activity/Provider.php @@ -1,29 +1,12 @@ <?php + /** - * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Comments\Activity; +use OCP\Activity\Exceptions\UnknownActivityException; use OCP\Activity\IEvent; use OCP\Activity\IManager; use OCP\Activity\IProvider; @@ -31,46 +14,19 @@ use OCP\Comments\ICommentsManager; use OCP\Comments\NotFoundException; use OCP\IL10N; use OCP\IURLGenerator; -use OCP\IUser; use OCP\IUserManager; use OCP\L10N\IFactory; class Provider implements IProvider { - - /** @var IFactory */ - protected $languageFactory; - - /** @var IL10N */ - protected $l; - - /** @var IURLGenerator */ - protected $url; - - /** @var ICommentsManager */ - protected $commentsManager; - - /** @var IUserManager */ - protected $userManager; - - /** @var IManager */ - protected $activityManager; - - /** @var string[] */ - protected $displayNames = []; - - /** - * @param IFactory $languageFactory - * @param IURLGenerator $url - * @param ICommentsManager $commentsManager - * @param IUserManager $userManager - * @param IManager $activityManager - */ - public function __construct(IFactory $languageFactory, IURLGenerator $url, ICommentsManager $commentsManager, IUserManager $userManager, IManager $activityManager) { - $this->languageFactory = $languageFactory; - $this->url = $url; - $this->commentsManager = $commentsManager; - $this->userManager = $userManager; - $this->activityManager = $activityManager; + protected ?IL10N $l = null; + + public function __construct( + protected IFactory $languageFactory, + protected IURLGenerator $url, + protected ICommentsManager $commentsManager, + protected IUserManager $userManager, + protected IManager $activityManager, + ) { } /** @@ -78,12 +34,12 @@ class Provider implements IProvider { * @param IEvent $event * @param IEvent|null $previousEvent * @return IEvent - * @throws \InvalidArgumentException + * @throws UnknownActivityException * @since 11.0.0 */ - public function parse($language, IEvent $event, IEvent $previousEvent = null) { + public function parse($language, IEvent $event, ?IEvent $previousEvent = null): IEvent { if ($event->getApp() !== 'comments') { - throw new \InvalidArgumentException(); + throw new UnknownActivityException(); } $this->l = $this->languageFactory->get('comments', $language); @@ -99,49 +55,43 @@ class Provider implements IProvider { if ($this->activityManager->isFormattingFilteredObject()) { try { return $this->parseShortVersion($event); - } catch (\InvalidArgumentException $e) { + } catch (UnknownActivityException) { // Ignore and simply use the long version... } } return $this->parseLongVersion($event); - } else { - throw new \InvalidArgumentException(); } + throw new UnknownActivityException(); + } /** - * @param IEvent $event - * @return IEvent - * @throws \InvalidArgumentException + * @throws UnknownActivityException */ - protected function parseShortVersion(IEvent $event) { + protected function parseShortVersion(IEvent $event): IEvent { $subjectParameters = $this->getSubjectParameters($event); if ($event->getSubject() === 'add_comment_subject') { if ($subjectParameters['actor'] === $this->activityManager->getCurrentUserId()) { - $event->setParsedSubject($this->l->t('You commented')) - ->setRichSubject($this->l->t('You commented'), []); + $event->setRichSubject($this->l->t('You commented'), []); } else { $author = $this->generateUserParameter($subjectParameters['actor']); - $event->setParsedSubject($this->l->t('%1$s commented', [$author['name']])) - ->setRichSubject($this->l->t('{author} commented'), [ - 'author' => $author, - ]); + $event->setRichSubject($this->l->t('{author} commented'), [ + 'author' => $author, + ]); } } else { - throw new \InvalidArgumentException(); + throw new UnknownActivityException(); } return $event; } /** - * @param IEvent $event - * @return IEvent - * @throws \InvalidArgumentException + * @throws UnknownActivityException */ - protected function parseLongVersion(IEvent $event) { + protected function parseLongVersion(IEvent $event): IEvent { $subjectParameters = $this->getSubjectParameters($event); if ($event->getSubject() === 'add_comment_subject') { @@ -164,13 +114,13 @@ class Provider implements IProvider { ]); } } else { - throw new \InvalidArgumentException(); + throw new UnknownActivityException(); } return $event; } - protected function getSubjectParameters(IEvent $event) { + protected function getSubjectParameters(IEvent $event): array { $subjectParameters = $event->getSubjectParameters(); if (isset($subjectParameters['fileId'])) { return $subjectParameters; @@ -190,20 +140,17 @@ class Provider implements IProvider { ]; } - /** - * @param IEvent $event - */ - protected function parseMessage(IEvent $event) { + protected function parseMessage(IEvent $event): void { $messageParameters = $event->getMessageParameters(); if (empty($messageParameters)) { // Email return; } - $commentId = isset($messageParameters['commentId']) ? $messageParameters['commentId'] : $messageParameters[0]; + $commentId = $messageParameters['commentId'] ?? $messageParameters[0]; try { - $comment = $this->commentsManager->get((string) $commentId); + $comment = $this->commentsManager->get((string)$commentId); $message = $comment->getMessage(); $mentionCount = 1; @@ -214,7 +161,7 @@ class Provider implements IProvider { } $message = str_replace('@"' . $mention['id'] . '"', '{mention' . $mentionCount . '}', $message); - if (strpos($mention['id'], ' ') === false && strpos($mention['id'], 'guest/') !== 0) { + if (!str_contains($mention['id'], ' ') && !str_starts_with($mention['id'], 'guest/')) { $message = str_replace('@' . $mention['id'], '{mention' . $mentionCount . '}', $message); } @@ -229,46 +176,23 @@ class Provider implements IProvider { } /** - * @param int $id - * @param string $path - * @return array + * @return array<string, string> */ - protected function generateFileParameter($id, $path) { + protected function generateFileParameter(int $id, string $path): array { return [ 'type' => 'file', - 'id' => $id, + 'id' => (string)$id, 'name' => basename($path), 'path' => $path, 'link' => $this->url->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $id]), ]; } - /** - * @param string $uid - * @return array - */ - protected function generateUserParameter($uid) { - if (!isset($this->displayNames[$uid])) { - $this->displayNames[$uid] = $this->getDisplayName($uid); - } - + protected function generateUserParameter(string $uid): array { return [ 'type' => 'user', 'id' => $uid, - 'name' => $this->displayNames[$uid], + 'name' => $this->userManager->getDisplayName($uid) ?? $uid, ]; } - - /** - * @param string $uid - * @return string - */ - protected function getDisplayName($uid) { - $user = $this->userManager->get($uid); - if ($user instanceof IUser) { - return $user->getDisplayName(); - } else { - return $uid; - } - } } diff --git a/apps/comments/lib/Activity/Setting.php b/apps/comments/lib/Activity/Setting.php index fefee1ca876..7fbf4001b20 100644 --- a/apps/comments/lib/Activity/Setting.php +++ b/apps/comments/lib/Activity/Setting.php @@ -1,98 +1,53 @@ <?php + /** - * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> - * - * @author Joas Schilling <coding@schilljs.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Comments\Activity; -use OCP\Activity\ISetting; +use OCP\Activity\ActivitySettings; use OCP\IL10N; -class Setting implements ISetting { - - /** @var IL10N */ - protected $l; - - /** - * @param IL10N $l - */ - public function __construct(IL10N $l) { - $this->l = $l; +class Setting extends ActivitySettings { + public function __construct( + protected IL10N $l, + ) { } - /** - * @return string Lowercase a-z and underscore only identifier - * @since 11.0.0 - */ - public function getIdentifier() { + public function getIdentifier(): string { return 'comments'; } - /** - * @return string A translated string - * @since 11.0.0 - */ - public function getName() { + public function getName(): string { return $this->l->t('<strong>Comments</strong> for files'); } - /** - * @return int whether the filter should be rather on the top or bottom of - * the admin section. The filters are arranged in ascending order of the - * priority values. It is required to return a value between 0 and 100. - * @since 11.0.0 - */ - public function getPriority() { + public function getGroupIdentifier() { + return 'files'; + } + + public function getGroupName() { + return $this->l->t('Files'); + } + + public function getPriority(): int { return 50; } - /** - * @return bool True when the option can be changed for the stream - * @since 11.0.0 - */ - public function canChangeStream() { + public function canChangeStream(): bool { return true; } - /** - * @return bool True when the option can be changed for the stream - * @since 11.0.0 - */ - public function isDefaultEnabledStream() { + public function isDefaultEnabledStream(): bool { return true; } - /** - * @return bool True when the option can be changed for the mail - * @since 11.0.0 - */ - public function canChangeMail() { + public function canChangeMail(): bool { return true; } - /** - * @return bool True when the option can be changed for the stream - * @since 11.0.0 - */ - public function isDefaultEnabledMail() { + public function isDefaultEnabledMail(): bool { return false; } } diff --git a/apps/comments/lib/AppInfo/Application.php b/apps/comments/lib/AppInfo/Application.php index 4eb097ff001..db4a2ce614c 100644 --- a/apps/comments/lib/AppInfo/Application.php +++ b/apps/comments/lib/AppInfo/Application.php @@ -1,42 +1,18 @@ <?php + /** - * @copyright Copyright (c) 2016, Arthur Schiwon <blizzz@arthur-schiwon.de> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Comments\AppInfo; -use Closure; use OCA\Comments\Capabilities; -use OCA\Comments\Controller\Notifications; -use OCA\Comments\EventHandler; -use OCA\Comments\JSSettingsHelper; use OCA\Comments\Listener\CommentsEntityEventListener; +use OCA\Comments\Listener\CommentsEventListener; use OCA\Comments\Listener\LoadAdditionalScripts; use OCA\Comments\Listener\LoadSidebarScripts; +use OCA\Comments\MaxAutoCompleteResultsInitialState; use OCA\Comments\Notification\Notifier; -use OCA\Comments\Search\LegacyProvider; use OCA\Comments\Search\CommentsSearchProvider; use OCA\Files\Event\LoadAdditionalScriptsEvent; use OCA\Files\Event\LoadSidebar; @@ -45,10 +21,7 @@ use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\Comments\CommentsEntityEvent; -use OCP\IConfig; -use OCP\ISearch; -use OCP\IServerContainer; -use OCP\Util; +use OCP\Comments\CommentsEvent; class Application extends App implements IBootstrap { public const APP_ID = 'comments'; @@ -60,8 +33,6 @@ class Application extends App implements IBootstrap { public function register(IRegistrationContext $context): void { $context->registerCapability(Capabilities::class); - $context->registerServiceAlias('NotificationsController', Notifications::class); - $context->registerEventListener( LoadAdditionalScriptsEvent::class, LoadAdditionalScripts::class @@ -71,29 +42,21 @@ class Application extends App implements IBootstrap { LoadSidebarScripts::class ); $context->registerEventListener( - CommentsEntityEvent::EVENT_ENTITY, + CommentsEntityEvent::class, CommentsEntityEventListener::class ); - $context->registerSearchProvider(CommentsSearchProvider::class); - } - - public function boot(IBootContext $context): void { - $context->injectFn(Closure::fromCallable([$this, 'registerNotifier'])); - $context->injectFn(Closure::fromCallable([$this, 'registerCommentsEventHandler'])); + $context->registerEventListener( + CommentsEvent::class, + CommentsEventListener::class, + ); - $jsSettingsHelper = new JSSettingsHelper($context->getAppContainer()->get(IConfig::class)); - Util::connectHook('\OCP\Config', 'js', $jsSettingsHelper, 'extend'); + $context->registerSearchProvider(CommentsSearchProvider::class); - $context->getServerContainer()->get(ISearch::class)->registerProvider(LegacyProvider::class, ['apps' => ['files']]); - } + $context->registerInitialStateProvider(MaxAutoCompleteResultsInitialState::class); - protected function registerNotifier(IServerContainer $container) { - $container->getNotificationManager()->registerNotifierService(Notifier::class); + $context->registerNotifierService(Notifier::class); } - protected function registerCommentsEventHandler(IServerContainer $container) { - $container->getCommentsManager()->registerEventHandler(function () { - return $this->getContainer()->query(EventHandler::class); - }); + public function boot(IBootContext $context): void { } } diff --git a/apps/comments/lib/Capabilities.php b/apps/comments/lib/Capabilities.php index a1083c7d8f6..2057803d867 100644 --- a/apps/comments/lib/Capabilities.php +++ b/apps/comments/lib/Capabilities.php @@ -3,32 +3,17 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2020 Joas Schilling <coding@schilljs.com> - * - * @author Joas Schilling <coding@schilljs.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Comments; use OCP\Capabilities\ICapability; class Capabilities implements ICapability { + /** + * @return array{files: array{comments: bool}} + */ public function getCapabilities(): array { return [ 'files' => [ diff --git a/apps/comments/lib/Collaboration/CommentersSorter.php b/apps/comments/lib/Collaboration/CommentersSorter.php index 9fe0ed74fad..baa27155573 100644 --- a/apps/comments/lib/Collaboration/CommentersSorter.php +++ b/apps/comments/lib/Collaboration/CommentersSorter.php @@ -1,42 +1,21 @@ <?php + /** - * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Comments\Collaboration; use OCP\Collaboration\AutoComplete\ISorter; use OCP\Comments\ICommentsManager; class CommentersSorter implements ISorter { - - /** @var ICommentsManager */ - private $commentsManager; - - public function __construct(ICommentsManager $commentsManager) { - $this->commentsManager = $commentsManager; + public function __construct( + private ICommentsManager $commentsManager, + ) { } - public function getId() { + public function getId(): string { return 'commenters'; } @@ -44,10 +23,10 @@ class CommentersSorter implements ISorter { * Sorts people who commented on the given item atop (descelating) of the * others * - * @param array $sortArray + * @param array &$sortArray * @param array $context */ - public function sort(array &$sortArray, array $context) { + public function sort(array &$sortArray, array $context): void { $commenters = $this->retrieveCommentsInformation($context['itemType'], $context['itemId']); if (count($commenters) === 0) { return; @@ -79,11 +58,9 @@ class CommentersSorter implements ISorter { } /** - * @param $type - * @param $id - * @return array + * @return array<string, array<string, int>> */ - protected function retrieveCommentsInformation($type, $id) { + protected function retrieveCommentsInformation(string $type, string $id): array { $comments = $this->commentsManager->getForObject($type, $id); if (count($comments) === 0) { return []; @@ -103,12 +80,12 @@ class CommentersSorter implements ISorter { return $actors; } - protected function compare(array $a, array $b, array $commenters) { + protected function compare(array $a, array $b, array $commenters): int { $a = $a['value']['shareWith']; $b = $b['value']['shareWith']; - $valueA = isset($commenters[$a]) ? $commenters[$a] : 0; - $valueB = isset($commenters[$b]) ? $commenters[$b] : 0; + $valueA = $commenters[$a] ?? 0; + $valueB = $commenters[$b] ?? 0; return $valueB - $valueA; } diff --git a/apps/comments/lib/Controller/Notifications.php b/apps/comments/lib/Controller/Notifications.php deleted file mode 100644 index 388aab26c55..00000000000 --- a/apps/comments/lib/Controller/Notifications.php +++ /dev/null @@ -1,148 +0,0 @@ -<?php -/** - * - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -namespace OCA\Comments\Controller; - -use OCP\AppFramework\Controller; -use OCP\AppFramework\Http\NotFoundResponse; -use OCP\AppFramework\Http\RedirectResponse; -use OCP\AppFramework\Http\Response; -use OCP\Comments\IComment; -use OCP\Comments\ICommentsManager; -use OCP\Files\IRootFolder; -use OCP\IRequest; -use OCP\IURLGenerator; -use OCP\IUser; -use OCP\IUserSession; -use OCP\Notification\IManager; - -/** - * Class Notifications - * - * @package OCA\Comments\Controller - */ -class Notifications extends Controller { - /** @var IRootFolder */ - protected $rootFolder; - - /** @var ICommentsManager */ - protected $commentsManager; - - /** @var IURLGenerator */ - protected $urlGenerator; - - /** @var IManager */ - protected $notificationManager; - - /** @var IUserSession */ - protected $userSession; - - /** - * Notifications constructor. - * - * @param string $appName - * @param IRequest $request - * @param ICommentsManager $commentsManager - * @param IRootFolder $rootFolder - * @param IURLGenerator $urlGenerator - * @param IManager $notificationManager - * @param IUserSession $userSession - */ - public function __construct( - $appName, - IRequest $request, - ICommentsManager $commentsManager, - IRootFolder $rootFolder, - IURLGenerator $urlGenerator, - IManager $notificationManager, - IUserSession $userSession - ) { - parent::__construct($appName, $request); - $this->commentsManager = $commentsManager; - $this->rootFolder = $rootFolder; - $this->urlGenerator = $urlGenerator; - $this->notificationManager = $notificationManager; - $this->userSession = $userSession; - } - - /** - * @PublicPage - * @NoCSRFRequired - * - * @param string $id the comment ID - * @return Response - */ - public function view($id) { - $currentUser = $this->userSession->getUser(); - if (!$currentUser instanceof IUser) { - return new RedirectResponse( - $this->urlGenerator->linkToRoute('core.login.showLoginForm', [ - 'redirect_url' => $this->urlGenerator->linkToRoute( - 'comments.Notifications.view', - ['id' => $id] - ), - ]) - ); - } - - try { - $comment = $this->commentsManager->get($id); - if ($comment->getObjectType() !== 'files') { - return new NotFoundResponse(); - } - $userFolder = $this->rootFolder->getUserFolder($currentUser->getUID()); - $files = $userFolder->getById((int)$comment->getObjectId()); - - $this->markProcessed($comment, $currentUser); - - if (empty($files)) { - return new NotFoundResponse(); - } - - $url = $this->urlGenerator->linkToRouteAbsolute( - 'files.viewcontroller.showFile', - [ 'fileid' => $comment->getObjectId() ] - ); - - return new RedirectResponse($url); - } catch (\Exception $e) { - return new NotFoundResponse(); - } - } - - /** - * Marks the notification about a comment as processed - * @param IComment $comment - * @param IUser $currentUser - */ - protected function markProcessed(IComment $comment, IUser $currentUser) { - $notification = $this->notificationManager->createNotification(); - $notification->setApp('comments') - ->setObject('comment', $comment->getId()) - ->setSubject('mention') - ->setUser($currentUser->getUID()); - $this->notificationManager->markProcessed($notification); - } -} diff --git a/apps/comments/lib/Controller/NotificationsController.php b/apps/comments/lib/Controller/NotificationsController.php new file mode 100644 index 00000000000..0937b6929b8 --- /dev/null +++ b/apps/comments/lib/Controller/NotificationsController.php @@ -0,0 +1,103 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\Comments\Controller; + +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; +use OCP\AppFramework\Http\Attribute\OpenAPI; +use OCP\AppFramework\Http\Attribute\PublicPage; +use OCP\AppFramework\Http\NotFoundResponse; +use OCP\AppFramework\Http\RedirectResponse; +use OCP\Comments\IComment; +use OCP\Comments\ICommentsManager; +use OCP\Files\IRootFolder; +use OCP\IRequest; +use OCP\IURLGenerator; +use OCP\IUser; +use OCP\IUserSession; +use OCP\Notification\IManager; + +/** + * @package OCA\Comments\Controller + */ +#[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)] +class NotificationsController extends Controller { + public function __construct( + string $appName, + IRequest $request, + protected ICommentsManager $commentsManager, + protected IRootFolder $rootFolder, + protected IURLGenerator $urlGenerator, + protected IManager $notificationManager, + protected IUserSession $userSession, + ) { + parent::__construct($appName, $request); + } + + /** + * View a notification + * + * @param string $id ID of the notification + * + * @return RedirectResponse<Http::STATUS_SEE_OTHER, array{}>|NotFoundResponse<Http::STATUS_NOT_FOUND, array{}> + * + * 303: Redirected to notification + * 404: Notification not found + */ + #[PublicPage] + #[NoCSRFRequired] + public function view(string $id): RedirectResponse|NotFoundResponse { + $currentUser = $this->userSession->getUser(); + if (!$currentUser instanceof IUser) { + return new RedirectResponse( + $this->urlGenerator->linkToRoute('core.login.showLoginForm', [ + 'redirect_url' => $this->urlGenerator->linkToRoute( + 'comments.Notifications.view', + ['id' => $id] + ), + ]) + ); + } + + try { + $comment = $this->commentsManager->get($id); + if ($comment->getObjectType() !== 'files') { + return new NotFoundResponse(); + } + $userFolder = $this->rootFolder->getUserFolder($currentUser->getUID()); + $files = $userFolder->getById((int)$comment->getObjectId()); + + $this->markProcessed($comment, $currentUser); + + if (empty($files)) { + return new NotFoundResponse(); + } + + $url = $this->urlGenerator->linkToRouteAbsolute( + 'files.viewcontroller.showFile', + [ 'fileid' => $comment->getObjectId() ] + ); + + return new RedirectResponse($url); + } catch (\Exception $e) { + return new NotFoundResponse(); + } + } + + /** + * Marks the notification about a comment as processed + */ + protected function markProcessed(IComment $comment, IUser $currentUser): void { + $notification = $this->notificationManager->createNotification(); + $notification->setApp('comments') + ->setObject('comment', $comment->getId()) + ->setSubject('mention') + ->setUser($currentUser->getUID()); + $this->notificationManager->markProcessed($notification); + } +} diff --git a/apps/comments/lib/EventHandler.php b/apps/comments/lib/EventHandler.php deleted file mode 100644 index 20a15a9b026..00000000000 --- a/apps/comments/lib/EventHandler.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -namespace OCA\Comments; - -use OCA\Comments\Activity\Listener as ActivityListener; -use OCA\Comments\Notification\Listener as NotificationListener; -use OCP\Comments\CommentsEvent; -use OCP\Comments\ICommentsEventHandler; - -/** - * Class EventHandler - * - * @package OCA\Comments - */ -class EventHandler implements ICommentsEventHandler { - /** @var ActivityListener */ - private $activityListener; - - /** @var NotificationListener */ - private $notificationListener; - - public function __construct(ActivityListener $activityListener, NotificationListener $notificationListener) { - $this->activityListener = $activityListener; - $this->notificationListener = $notificationListener; - } - - /** - * @param CommentsEvent $event - */ - public function handle(CommentsEvent $event) { - if ($event->getComment()->getObjectType() !== 'files') { - // this is a 'files'-specific Handler - return; - } - - $eventType = $event->getEvent(); - if ($eventType === CommentsEvent::EVENT_ADD - ) { - $this->notificationHandler($event); - $this->activityHandler($event); - return; - } - - $applicableEvents = [ - CommentsEvent::EVENT_PRE_UPDATE, - CommentsEvent::EVENT_UPDATE, - CommentsEvent::EVENT_DELETE, - ]; - if (in_array($eventType, $applicableEvents)) { - $this->notificationHandler($event); - return; - } - } - - /** - * @param CommentsEvent $event - */ - private function activityHandler(CommentsEvent $event) { - $this->activityListener->commentEvent($event); - } - - /** - * @param CommentsEvent $event - */ - private function notificationHandler(CommentsEvent $event) { - $this->notificationListener->evaluate($event); - } -} diff --git a/apps/comments/lib/JSSettingsHelper.php b/apps/comments/lib/JSSettingsHelper.php deleted file mode 100644 index 19e4392d0b7..00000000000 --- a/apps/comments/lib/JSSettingsHelper.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -namespace OCA\Comments; - -use OCP\IConfig; - -class JSSettingsHelper { - /** @var IConfig */ - private $c; - - public function __construct(IConfig $c) { - $this->c = $c; - } - - public function extend(array $settings) { - $appConfig = json_decode($settings['array']['oc_appconfig'], true); - - $value = (int)$this->c->getAppValue('comments', 'maxAutoCompleteResults', 10); - $appConfig['comments']['maxAutoCompleteResults'] = $value; - - $settings['array']['oc_appconfig'] = json_encode($appConfig); - } -} diff --git a/apps/comments/lib/Listener/CommentsEntityEventListener.php b/apps/comments/lib/Listener/CommentsEntityEventListener.php index a0d5b175f0a..5aeeb3c63ea 100644 --- a/apps/comments/lib/Listener/CommentsEntityEventListener.php +++ b/apps/comments/lib/Listener/CommentsEntityEventListener.php @@ -3,42 +3,32 @@ declare(strict_types=1); /** - * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Comments\Listener; use OCP\Comments\CommentsEntityEvent; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; +use OCP\Files\IRootFolder; +/** @template-implements IEventListener<CommentsEntityEvent> */ class CommentsEntityEventListener implements IEventListener { + public function __construct( + private IRootFolder $rootFolder, + private ?string $userId = null, + ) { + } + public function handle(Event $event): void { if (!($event instanceof CommentsEntityEvent)) { // Unrelated return; } - $event->addEntityCollection('files', function ($name) { - $nodes = \OC::$server->getUserFolder()->getById((int)$name); + $event->addEntityCollection('files', function ($name): bool { + $nodes = $this->rootFolder->getUserFolder($this->userId)->getById((int)$name); return !empty($nodes); }); } diff --git a/apps/comments/lib/Listener/CommentsEventListener.php b/apps/comments/lib/Listener/CommentsEventListener.php new file mode 100644 index 00000000000..a1e44995162 --- /dev/null +++ b/apps/comments/lib/Listener/CommentsEventListener.php @@ -0,0 +1,63 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + + +namespace OCA\Comments\Listener; + +use OCA\Comments\Activity\Listener as ActivityListener; +use OCA\Comments\Notification\Listener as NotificationListener; +use OCP\Comments\CommentsEvent; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventListener; + +/** @template-implements IEventListener<CommentsEvent|Event> */ +class CommentsEventListener implements IEventListener { + public function __construct( + private ActivityListener $activityListener, + private NotificationListener $notificationListener, + ) { + } + + public function handle(Event $event): void { + if (!$event instanceof CommentsEvent) { + return; + } + + if ($event->getComment()->getObjectType() !== 'files') { + // this is a 'files'-specific Handler + return; + } + + $eventType = $event->getEvent(); + if ($eventType === CommentsEvent::EVENT_ADD + ) { + $this->notificationHandler($event); + $this->activityHandler($event); + return; + } + + $applicableEvents = [ + CommentsEvent::EVENT_PRE_UPDATE, + CommentsEvent::EVENT_UPDATE, + CommentsEvent::EVENT_DELETE, + ]; + if (in_array($eventType, $applicableEvents)) { + $this->notificationHandler($event); + return; + } + } + + private function activityHandler(CommentsEvent $event): void { + $this->activityListener->commentEvent($event); + } + + private function notificationHandler(CommentsEvent $event): void { + $this->notificationListener->evaluate($event); + } +} diff --git a/apps/comments/lib/Listener/LoadAdditionalScripts.php b/apps/comments/lib/Listener/LoadAdditionalScripts.php index 86ec097325e..81e1bfe5310 100644 --- a/apps/comments/lib/Listener/LoadAdditionalScripts.php +++ b/apps/comments/lib/Listener/LoadAdditionalScripts.php @@ -3,29 +3,9 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Comments\Listener; use OCA\Comments\AppInfo\Application; @@ -34,14 +14,14 @@ use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; use OCP\Util; +/** @template-implements IEventListener<LoadAdditionalScriptsEvent> */ class LoadAdditionalScripts implements IEventListener { public function handle(Event $event): void { if (!($event instanceof LoadAdditionalScriptsEvent)) { return; } - // TODO: make sure to only include the sidebar script when - // we properly split it between files list and sidebar - Util::addScript(Application::APP_ID, 'comments'); + // Adding init script for file list inline actions + Util::addInitScript(Application::APP_ID, 'init'); } } diff --git a/apps/comments/lib/Listener/LoadSidebarScripts.php b/apps/comments/lib/Listener/LoadSidebarScripts.php index 654482cf57e..906fe40fed2 100644 --- a/apps/comments/lib/Listener/LoadSidebarScripts.php +++ b/apps/comments/lib/Listener/LoadSidebarScripts.php @@ -3,44 +3,27 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Comments\Listener; use OCA\Comments\AppInfo\Application; use OCA\Files\Event\LoadSidebar; +use OCP\App\IAppManager; +use OCP\AppFramework\Services\IInitialState; use OCP\Comments\ICommentsManager; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; use OCP\Util; +/** @template-implements IEventListener<LoadSidebar> */ class LoadSidebarScripts implements IEventListener { - - /** @var ICommentsManager */ - private $commentsManager; - - public function __construct(ICommentsManager $commentsManager) { - $this->commentsManager = $commentsManager; + public function __construct( + private ICommentsManager $commentsManager, + private IInitialState $initialState, + private IAppManager $appManager, + ) { } public function handle(Event $event): void { @@ -50,9 +33,8 @@ class LoadSidebarScripts implements IEventListener { $this->commentsManager->load(); - // TODO: make sure to only include the sidebar script when - // we properly split it between files list and sidebar - Util::addScript(Application::APP_ID, 'comments'); - Util::addScript(Application::APP_ID, 'comments-tab'); + $this->initialState->provideInitialState('activityEnabled', $this->appManager->isEnabledForUser('activity')); + // Add comments sidebar tab script + Util::addScript(Application::APP_ID, 'comments-tab', 'files'); } } diff --git a/apps/comments/lib/MaxAutoCompleteResultsInitialState.php b/apps/comments/lib/MaxAutoCompleteResultsInitialState.php new file mode 100644 index 00000000000..b4c8f8719db --- /dev/null +++ b/apps/comments/lib/MaxAutoCompleteResultsInitialState.php @@ -0,0 +1,27 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\Comments; + +use OCP\AppFramework\Services\InitialStateProvider; +use OCP\IConfig; + +class MaxAutoCompleteResultsInitialState extends InitialStateProvider { + public function __construct( + private IConfig $config, + ) { + } + + public function getKey(): string { + return 'maxAutoCompleteResults'; + } + + public function getData(): int { + return (int)$this->config->getAppValue('comments', 'maxAutoCompleteResults', '10'); + } +} diff --git a/apps/comments/lib/Notification/Listener.php b/apps/comments/lib/Notification/Listener.php index 9f7062f9467..43922f85e59 100644 --- a/apps/comments/lib/Notification/Listener.php +++ b/apps/comments/lib/Notification/Listener.php @@ -1,59 +1,26 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ - namespace OCA\Comments\Notification; use OCP\Comments\CommentsEvent; use OCP\Comments\IComment; use OCP\IUserManager; use OCP\Notification\IManager; +use OCP\Notification\INotification; class Listener { - /** @var IManager */ - protected $notificationManager; - - /** @var IUserManager */ - protected $userManager; - - /** - * Listener constructor. - * - * @param IManager $notificationManager - * @param IUserManager $userManager - */ public function __construct( - IManager $notificationManager, - IUserManager $userManager + protected IManager $notificationManager, + protected IUserManager $userManager, ) { - $this->notificationManager = $notificationManager; - $this->userManager = $userManager; } - /** - * @param CommentsEvent $event - */ - public function evaluate(CommentsEvent $event) { + public function evaluate(CommentsEvent $event): void { $comment = $event->getComment(); $mentions = $this->extractMentions($comment->getMentions()); @@ -83,12 +50,9 @@ class Listener { } /** - * creates a notification instance and fills it with comment data - * - * @param IComment $comment - * @return \OCP\Notification\INotification + * Creates a notification instance and fills it with comment data */ - public function instantiateNotification(IComment $comment) { + public function instantiateNotification(IComment $comment): INotification { $notification = $this->notificationManager->createNotification(); $notification ->setApp('comments') @@ -100,12 +64,12 @@ class Listener { } /** - * flattens the mention array returned from comments to a list of user ids. + * Flattens the mention array returned from comments to a list of user ids. * * @param array $mentions - * @return string[] containing the mentions, e.g. ['alice', 'bob'] + * @return list<string> containing the mentions, e.g. ['alice', 'bob'] */ - public function extractMentions(array $mentions) { + public function extractMentions(array $mentions): array { if (empty($mentions)) { return []; } diff --git a/apps/comments/lib/Notification/Notifier.php b/apps/comments/lib/Notification/Notifier.php index 20e0667d143..62562bf42aa 100644 --- a/apps/comments/lib/Notification/Notifier.php +++ b/apps/comments/lib/Notification/Notifier.php @@ -1,28 +1,10 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ - namespace OCA\Comments\Notification; use OCP\Comments\IComment; @@ -30,42 +12,21 @@ use OCP\Comments\ICommentsManager; use OCP\Comments\NotFoundException; use OCP\Files\IRootFolder; use OCP\IURLGenerator; -use OCP\IUser; use OCP\IUserManager; use OCP\L10N\IFactory; use OCP\Notification\AlreadyProcessedException; use OCP\Notification\INotification; use OCP\Notification\INotifier; +use OCP\Notification\UnknownNotificationException; class Notifier implements INotifier { - - /** @var IFactory */ - protected $l10nFactory; - - /** @var IRootFolder */ - protected $rootFolder; - - /** @var ICommentsManager */ - protected $commentsManager; - - /** @var IURLGenerator */ - protected $url; - - /** @var IUserManager */ - protected $userManager; - public function __construct( - IFactory $l10nFactory, - IRootFolder $rootFolder, - ICommentsManager $commentsManager, - IURLGenerator $url, - IUserManager $userManager + protected IFactory $l10nFactory, + protected IRootFolder $rootFolder, + protected ICommentsManager $commentsManager, + protected IURLGenerator $url, + protected IUserManager $userManager, ) { - $this->l10nFactory = $l10nFactory; - $this->rootFolder = $rootFolder; - $this->commentsManager = $commentsManager; - $this->url = $url; - $this->userManager = $userManager; } /** @@ -92,27 +53,27 @@ class Notifier implements INotifier { * @param INotification $notification * @param string $languageCode The code of the language that should be used to prepare the notification * @return INotification - * @throws \InvalidArgumentException When the notification was not prepared by a notifier + * @throws UnknownNotificationException When the notification was not prepared by a notifier * @throws AlreadyProcessedException When the notification is not needed anymore and should be deleted * @since 9.0.0 */ public function prepare(INotification $notification, string $languageCode): INotification { if ($notification->getApp() !== 'comments') { - throw new \InvalidArgumentException(); + throw new UnknownNotificationException(); } try { $comment = $this->commentsManager->get($notification->getObjectId()); } catch (NotFoundException $e) { // needs to be converted to InvalidArgumentException, otherwise none Notifications will be shown at all - throw new \InvalidArgumentException('Comment not found', 0, $e); + throw new UnknownNotificationException('Comment not found', 0, $e); } $l = $this->l10nFactory->get('comments', $languageCode); $displayName = $comment->getActorId(); $isDeletedActor = $comment->getActorType() === ICommentsManager::DELETED_USER; if ($comment->getActorType() === 'users') { - $commenter = $this->userManager->get($comment->getActorId()); - if ($commenter instanceof IUser) { - $displayName = $commenter->getDisplayName(); + $commenter = $this->userManager->getDisplayName($comment->getActorId()); + if ($commenter !== null) { + $displayName = $commenter; } } @@ -120,7 +81,7 @@ class Notifier implements INotifier { case 'mention': $parameters = $notification->getSubjectParameters(); if ($parameters[0] !== 'files') { - throw new \InvalidArgumentException('Unsupported comment object'); + throw new UnknownNotificationException('Unsupported comment object'); } $userFolder = $this->rootFolder->getUserFolder($notification->getUser()); $nodes = $userFolder->getById((int)$parameters[1]); @@ -130,10 +91,10 @@ class Notifier implements INotifier { $node = $nodes[0]; $path = rtrim($node->getPath(), '/'); - if (strpos($path, '/' . $notification->getUser() . '/files/') === 0) { + if (str_starts_with($path, '/' . $notification->getUser() . '/files/')) { // Remove /user/files/... $fullPath = $path; - list(,,, $path) = explode('/', $fullPath, 4); + [,,, $path] = explode('/', $fullPath, 4); } $subjectParameters = [ 'file' => [ @@ -146,20 +107,18 @@ class Notifier implements INotifier { ]; if ($isDeletedActor) { - $subject = $l->t('You were mentioned on “{file}”, in a comment by a user that has since been deleted'); + $subject = $l->t('You were mentioned on "{file}", in a comment by an account that has since been deleted'); } else { - $subject = $l->t('{user} mentioned you in a comment on “{file}”'); + $subject = $l->t('{user} mentioned you in a comment on "{file}"'); $subjectParameters['user'] = [ 'type' => 'user', 'id' => $comment->getActorId(), 'name' => $displayName, ]; } - list($message, $messageParameters) = $this->commentToRichMessage($comment); + [$message, $messageParameters] = $this->commentToRichMessage($comment); $notification->setRichSubject($subject, $subjectParameters) - ->setParsedSubject($this->richToParsed($subject, $subjectParameters)) ->setRichMessage($message, $messageParameters) - ->setParsedMessage($this->richToParsed($message, $messageParameters)) ->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'actions/comment.svg'))) ->setLink($this->url->linkToRouteAbsolute( 'comments.Notifications.view', @@ -170,7 +129,7 @@ class Notifier implements INotifier { break; default: - throw new \InvalidArgumentException('Invalid subject'); + throw new UnknownNotificationException('Invalid subject'); } } @@ -181,8 +140,8 @@ class Notifier implements INotifier { $mentions = $comment->getMentions(); foreach ($mentions as $mention) { if ($mention['type'] === 'user') { - $user = $this->userManager->get($mention['id']); - if (!$user instanceof IUser) { + $userDisplayName = $this->userManager->getDisplayName($mention['id']); + if ($userDisplayName === null) { continue; } } @@ -196,7 +155,7 @@ class Notifier implements INotifier { // index of the mentions of that type. $mentionParameterId = 'mention-' . $mention['type'] . $mentionTypeCount[$mention['type']]; $message = str_replace('@"' . $mention['id'] . '"', '{' . $mentionParameterId . '}', $message); - if (strpos($mention['id'], ' ') === false && strpos($mention['id'], 'guest/') !== 0) { + if (!str_contains($mention['id'], ' ') && !str_starts_with($mention['id'], 'guest/')) { $message = str_replace('@' . $mention['id'], '{' . $mentionParameterId . '}', $message); } @@ -215,19 +174,4 @@ class Notifier implements INotifier { } return [$message, $messageParameters]; } - - public function richToParsed(string $message, array $parameters): string { - $placeholders = $replacements = []; - foreach ($parameters as $placeholder => $parameter) { - $placeholders[] = '{' . $placeholder . '}'; - if ($parameter['type'] === 'user') { - $replacements[] = '@' . $parameter['name']; - } elseif ($parameter['type'] === 'file') { - $replacements[] = $parameter['path']; - } else { - $replacements[] = $parameter['name']; - } - } - return str_replace($placeholders, $replacements, $message); - } } diff --git a/apps/comments/lib/Search/CommentsSearchProvider.php b/apps/comments/lib/Search/CommentsSearchProvider.php index 67c297b02ce..87a658cab1c 100644 --- a/apps/comments/lib/Search/CommentsSearchProvider.php +++ b/apps/comments/lib/Search/CommentsSearchProvider.php @@ -3,29 +3,9 @@ declare(strict_types=1); /** - * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Comments\Search; use OCP\IL10N; @@ -40,46 +20,22 @@ use function array_map; use function pathinfo; class CommentsSearchProvider implements IProvider { - - /** @var IUserManager */ - private $userManager; - - /** @var IL10N */ - private $l10n; - - /** @var IURLGenerator */ - private $urlGenerator; - - /** @var LegacyProvider */ - private $legacyProvider; - - public function __construct(IUserManager $userManager, - IL10N $l10n, - IURLGenerator $urlGenerator, - LegacyProvider $legacyProvider) { - $this->userManager = $userManager; - $this->l10n = $l10n; - $this->urlGenerator = $urlGenerator; - $this->legacyProvider = $legacyProvider; + public function __construct( + private IUserManager $userManager, + private IL10N $l10n, + private IURLGenerator $urlGenerator, + private LegacyProvider $legacyProvider, + ) { } - /** - * @inheritDoc - */ public function getId(): string { return 'comments'; } - /** - * @inheritDoc - */ public function getName(): string { return $this->l10n->t('Comments'); } - /** - * @inheritDoc - */ public function getOrder(string $route, array $routeParameters): int { if ($route === 'files.View.index') { // Files first @@ -88,9 +44,6 @@ class CommentsSearchProvider implements IProvider { return 10; } - /** - * @inheritDoc - */ public function search(IUser $user, ISearchQuery $query): SearchResult { return SearchResult::complete( $this->l10n->t('Comments'), @@ -105,7 +58,7 @@ class CommentsSearchProvider implements IProvider { $avatarUrl, $result->name, $path, - $this->urlGenerator->linkToRouteAbsolute('files.view.index',[ + $this->urlGenerator->linkToRouteAbsolute('files.view.index', [ 'dir' => $pathInfo['dirname'], 'scrollto' => $pathInfo['basename'], ]), diff --git a/apps/comments/lib/Search/LegacyProvider.php b/apps/comments/lib/Search/LegacyProvider.php index d58cc9847cf..a269c418d06 100644 --- a/apps/comments/lib/Search/LegacyProvider.php +++ b/apps/comments/lib/Search/LegacyProvider.php @@ -3,39 +3,23 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2018 Joas Schilling <coding@schilljs.com> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Comments\Search; use OCP\Comments\IComment; +use OCP\Comments\ICommentsManager; use OCP\Files\Folder; use OCP\Files\Node; use OCP\Files\NotFoundException; use OCP\IUser; +use OCP\IUserSession; use OCP\Search\Provider; +use OCP\Server; use function count; class LegacyProvider extends Provider { - /** * Search for $query * @@ -44,8 +28,8 @@ class LegacyProvider extends Provider { * @since 7.0.0 */ public function search($query): array { - $cm = \OC::$server->getCommentsManager(); - $us = \OC::$server->getUserSession(); + $cm = Server::get(ICommentsManager::class); + $us = Server::get(IUserSession::class); $user = $us->getUser(); if (!$user instanceof IUser) { @@ -103,7 +87,7 @@ class LegacyProvider extends Provider { * @throws NotFoundException */ protected function getFileForComment(Folder $userFolder, IComment $comment): Node { - $nodes = $userFolder->getById((int) $comment->getObjectId()); + $nodes = $userFolder->getById((int)$comment->getObjectId()); if (empty($nodes)) { throw new NotFoundException('File not found'); } diff --git a/apps/comments/lib/Search/Result.php b/apps/comments/lib/Search/Result.php index e154ca0277d..7478c110d63 100644 --- a/apps/comments/lib/Search/Result.php +++ b/apps/comments/lib/Search/Result.php @@ -1,28 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2018 Joas Schilling <coding@schilljs.com> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Michał Węgrzynek <michal.wegrzynek@malloc.com.pl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Comments\Search; use OCP\Comments\IComment; @@ -48,10 +29,6 @@ class Result extends BaseResult { /** * @deprecated 20.0.0 */ - public $authorName; - /** - * @deprecated 20.0.0 - */ public $path; /** * @deprecated 20.0.0 @@ -59,33 +36,31 @@ class Result extends BaseResult { public $fileName; /** - * @param string $search - * @param IComment $comment - * @param string $authorName - * @param string $path * @throws NotFoundException * @deprecated 20.0.0 */ - public function __construct(string $search, - IComment $comment, - string $authorName, - string $path) { + public function __construct( + string $search, + IComment $comment, + /** + * @deprecated 20.0.0 + */ + public string $authorName, + string $path, + ) { parent::__construct( - (int) $comment->getId(), + $comment->getId(), $comment->getMessage() - /* @todo , [link to file] */ + /* @todo , [link to file] */ ); $this->comment = $this->getRelevantMessagePart($comment->getMessage(), $search); $this->authorId = $comment->getActorId(); - $this->authorName = $authorName; $this->fileName = basename($path); $this->path = $this->getVisiblePath($path); } /** - * @param string $path - * @return string * @throws NotFoundException */ protected function getVisiblePath(string $path): string { @@ -99,9 +74,6 @@ class Result extends BaseResult { } /** - * @param string $message - * @param string $search - * @return string * @throws NotFoundException */ protected function getRelevantMessagePart(string $message, string $search): string { |