diff --git a/appinfo/info.xml b/appinfo/info.xml index e4702d18..7597ad76 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -52,6 +52,7 @@ OCA\AnnouncementCenter\Command\Announce OCA\AnnouncementCenter\Command\AnnouncementList OCA\AnnouncementCenter\Command\AnnouncementDelete + OCA\AnnouncementCenter\Command\RemoveNotifications diff --git a/lib/Command/RemoveNotifications.php b/lib/Command/RemoveNotifications.php new file mode 100644 index 00000000..a1945cbb --- /dev/null +++ b/lib/Command/RemoveNotifications.php @@ -0,0 +1,79 @@ + + * + * @author Marvin Winkens + * + * @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 . + * + */ +namespace OCA\AnnouncementCenter\Command; + +use InvalidArgumentException; +use OCA\AnnouncementCenter\Manager; +use OCA\AnnouncementCenter\Model\AnnouncementDoesNotExistException; +use Psr\Log\LoggerInterface; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class RemoveNotifications extends Command { + public function __construct( + protected Manager $manager, + protected LoggerInterface $logger, + ) { + parent::__construct(); + } + + protected function configure(): void { + $this + ->setName('announcementcenter:remove-notifications') # others use minus sign as well + ->setDescription('Remove notifications of announcement by id') + ->addArgument( + 'id', + InputArgument::REQUIRED, + 'Id of announcement to remove notifications from', + ); + } + + protected function execute(InputInterface $input, OutputInterface $output): int { + try { + $removeNotId = $this->parseId($input->getArgument('id')); + $this->manager->getAnnouncement($removeNotId, true); + $this->manager->removeNotifications($removeNotId); + } catch (AnnouncementDoesNotExistException) { + $output->writeln('Announcement with #' . $removeNotId . ' does not exist!'); + return 1; + } catch (InvalidArgumentException $e) { + $output->writeln($e->getMessage()); + return 1; + } + $output->writeln('Successfully removed notifications from accouncement #' . $removeNotId); + $this->logger->info('Admin removed notifications from announcement #' . $removeNotId . ' over CLI'); + return 0; + } + + private function parseId(mixed $value) { + if (is_numeric($value)) { + return (int)$value; + } + throw new InvalidArgumentException('Id "' . $value . '" is not an integer'); + } +} diff --git a/tests/Command/RemoveNotificationsTest.php b/tests/Command/RemoveNotificationsTest.php new file mode 100644 index 00000000..6fd3d2e7 --- /dev/null +++ b/tests/Command/RemoveNotificationsTest.php @@ -0,0 +1,116 @@ + + * + * @author Marvin Winkens + * + * @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 . + * + */ +namespace OCA\AnnouncementCenter\Tests\Command; + +use OCA\AnnouncementCenter\Command\RemoveNotifications; +use OCA\AnnouncementCenter\Manager; +use OCA\AnnouncementCenter\Model\AnnouncementDoesNotExistException; +use OCA\AnnouncementCenter\Tests\TestCase; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class RemoveNotificationsTest extends TestCase { + protected Manager|MockObject $manager; + protected LoggerInterface|MockObject $logger; + protected Command $removeNotificationsCommand; + protected InputInterface|MockObject $input; + protected OutputInterface|MockObject $output; + + protected function setUp(): void { + parent::setUp(); + + $this->manager = $this->createMock(Manager::class); + $this->logger = $this->createMock(LoggerInterface::class); + + $this->input = $this->getMockBuilder(InputInterface::class) + ->setMethods([ + 'getArgument', + 'getOption', + 'getFirstArgument', + 'hasParameterOption', + 'getParameterOption', + 'bind', + 'validate', + 'getArguments', + 'setArgument', + 'hasArgument', + 'getOptions', + 'isInteractive', + 'hasOption', + 'setOption', + 'setInteractive', + ]) + ->getMock(); + $this->output = $this->createMock(OutputInterface::class); + + $this->removeNotificationsCommand = new RemoveNotifications( + $this->manager, + $this->logger, + ); + } + + public function testRemoveNotificationsSuccessfully() { + $this->input->expects($this->once()) + ->method('getArgument') + ->with('id') + ->willReturn(42); + $this->manager->expects($this->once()) + ->method('removeNotifications'); + $this->manager->expects($this->once()) + ->method('getAnnouncement'); + $this->output->expects($this->atLeastOnce()) + ->method('writeln'); + $this->logger->expects($this->atLeastOnce()) + ->method('info'); + $result = self::invokePrivate($this->removeNotificationsCommand, 'execute', [$this->input, $this->output]); + self::assertEquals(0, $result); + } + + public function testRemoveNotificationsInvalidId() { + $this->input->expects($this->once()) + ->method('getArgument') + ->with('id') + ->willReturn('invalid'); + $result = self::invokePrivate($this->removeNotificationsCommand, 'execute', [$this->input, $this->output]); + self::assertEquals(true, $result > 0); + } + + public function testRemoveNotificationsDoesNotExist() { + $this->input->expects($this->once()) + ->method('getArgument') + ->with('id') + ->willReturn(42); + $this->manager->expects($this->once()) + ->method('getAnnouncement') + ->willThrowException(new AnnouncementDoesNotExistException('message')); + $this->output->expects($this->atLeastOnce()) + ->method('writeln'); + $result = self::invokePrivate($this->removeNotificationsCommand, 'execute', [$this->input, $this->output]); + self::assertEquals(true, $result > 0); + } +}