Skip to content

Commit

Permalink
Add CLI Commands (#779)
Browse files Browse the repository at this point in the history
* add background job and bump version

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* add group, scheduleTime and deleteTime fields to Announcements

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* add scheduleTime and deleteTime to API

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* add AnnouncementScheduler together with processing service

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* rework publishing in order to not directly publish if an Annoucement is added

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* advance frontend and add new buttons

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* improve service by filtering out jobs with 0 scheduleTime or deleteTime

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix annoucementSchedulerJob copy pasta from developer manual

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix unit tests by adding default values

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix various linting issues

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* Fix sequence

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* rename old BackgroundJob in order to reduce name confusion

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* add notification options to database in order to schedule them later

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* move notification execution into Manager

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix issues with the background job

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix typos

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix linting issues

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix new constructors

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix wrong number of argument for announce function since notificationOptions are missing

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* register services missing for proper dependency injection

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* bump version

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix annoying typo preveting background job to work

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix announcements not being updated when scheduled due to changed database id

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix linting issues

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* only allow scheduled annouce and deletion dates in the future

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* remove dependency injections

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix tests using wrong TestCase class

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* Add unittests for annoucement scheduling

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix linting

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* minor refactoring

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* Update lib/AnnouncementSchedulerJob.php

Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Signed-off-by: mwinkens <104770531+mwinkens@users.noreply.github.com>
Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* Update lib/Migration/Version6009Date20240311074015.php

Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Signed-off-by: mwinkens <104770531+mwinkens@users.noreply.github.com>
Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* Update lib/Migration/Version6009Date20240311074015.php

Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Signed-off-by: mwinkens <104770531+mwinkens@users.noreply.github.com>
Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* Update lib/Migration/Version6009Date20240311074015.php

Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Signed-off-by: mwinkens <104770531+mwinkens@users.noreply.github.com>
Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* Update tests/AnnouncementSchedulerJobTest.php

Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Signed-off-by: mwinkens <104770531+mwinkens@users.noreply.github.com>
Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* Update tests/Model/NotificationTypeTest.php

Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Signed-off-by: mwinkens <104770531+mwinkens@users.noreply.github.com>
Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* Update tests/Service/AnnouncementSchedulerProcessorTest.php

Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Signed-off-by: mwinkens <104770531+mwinkens@users.noreply.github.com>
Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* minor adjustments, adding license, linting, removing unused methods

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* Update src/Components/NewForm.vue

Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Signed-off-by: mwinkens <104770531+mwinkens@users.noreply.github.com>

* Update src/Components/NewForm.vue

Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Signed-off-by: mwinkens <104770531+mwinkens@users.noreply.github.com>

* remove logger from job construction

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* chore: update workflows from templates

Signed-off-by: skjnldsv <skjnldsv@protonmail.com>

* Fix(l10n): Update translations from Transifex

Signed-off-by: Nextcloud bot <bot@nextcloud.com>

* Updating phpunit-mysql.yml workflow from template

Signed-off-by: Nextcloud bot <bot@nextcloud.com>

* chore(deps): Bump follow-redirects from 1.15.4 to 1.15.6

Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.4 to 1.15.6.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](follow-redirects/follow-redirects@v1.15.4...v1.15.6)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore(deps): Bump @nextcloud/vue from 8.9.1 to 8.11.0

Bumps [@nextcloud/vue](https://github.com/nextcloud-libraries/nextcloud-vue) from 8.9.1 to 8.11.0.
- [Release notes](https://github.com/nextcloud-libraries/nextcloud-vue/releases)
- [Changelog](https://github.com/nextcloud-libraries/nextcloud-vue/blob/master/CHANGELOG.md)
- [Commits](nextcloud-libraries/nextcloud-vue@v8.9.1...v8.11.0)

---
updated-dependencies:
- dependency-name: "@nextcloud/vue"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore(deps-dev): Bump psalm/phar from 5.22.2 to 5.23.1

Bumps [psalm/phar](https://github.com/psalm/phar) from 5.22.2 to 5.23.1.
- [Release notes](https://github.com/psalm/phar/releases)
- [Commits](psalm/phar@5.22.2...5.23.1)

---
updated-dependencies:
- dependency-name: psalm/phar
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix(settings): Fix missing admin settings

Signed-off-by: Joas Schilling <coding@schilljs.com>

* fix(UI): Fix missing names after vue lib update

Signed-off-by: Joas Schilling <coding@schilljs.com>

* fix(form): Fix event-trigger for searching more groups

Signed-off-by: Joas Schilling <coding@schilljs.com>

* fix(form): Add label for accessibility

Signed-off-by: Joas Schilling <coding@schilljs.com>

* chore(release): Bump version to 6.8.1

Signed-off-by: Joas Schilling <coding@schilljs.com>

* fix(form): Fix accessibility label option

Signed-off-by: Joas Schilling <coding@schilljs.com>

* Fix(l10n): Update translations from Transifex

Signed-off-by: Nextcloud bot <bot@nextcloud.com>

* chore(deps): Bump @nextcloud/vue from 8.11.0 to 8.11.1

Bumps [@nextcloud/vue](https://github.com/nextcloud-libraries/nextcloud-vue) from 8.11.0 to 8.11.1.
- [Release notes](https://github.com/nextcloud-libraries/nextcloud-vue/releases)
- [Changelog](https://github.com/nextcloud-libraries/nextcloud-vue/blob/master/CHANGELOG.md)
- [Commits](nextcloud-libraries/nextcloud-vue@v8.11.0...v8.11.1)

---
updated-dependencies:
- dependency-name: "@nextcloud/vue"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore(deps-dev): Bump webpack-dev-middleware from 5.3.3 to 5.3.4

Bumps [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) from 5.3.3 to 5.3.4.
- [Release notes](https://github.com/webpack/webpack-dev-middleware/releases)
- [Changelog](https://github.com/webpack/webpack-dev-middleware/blob/v5.3.4/CHANGELOG.md)
- [Commits](webpack/webpack-dev-middleware@v5.3.3...v5.3.4)

---
updated-dependencies:
- dependency-name: webpack-dev-middleware
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore(deps-dev): Bump phpunit/phpunit from 9.6.17 to 9.6.18

Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.6.17 to 9.6.18.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/9.6.18/ChangeLog-9.6.md)
- [Commits](sebastianbergmann/phpunit@9.6.17...9.6.18)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Add CLI commands for annonce, list and delete

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* add limit to the optional parameters of list

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* overengineer table output

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* Switch from left to right pad

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* make a lot of parameters optional, properly handle boolean type parameters and make group an array like option

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* properly catch if the announcement ID which should get deleted exists

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix formatting

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* Send user schedule and deletion date if entered

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* add check, that the announcement has any notification option

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix description

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* add license

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* Capitalize description

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* add missing psalm classes

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* add unit tests for CLI commands

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* add symfony dev dependency

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* remove smyfony composer dependency and remove symfony static integer due to not working on older versions

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* remove callHidden helper function and use self::invokePrivate instead

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* Update lib/Command/Announce.php

Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Signed-off-by: mwinkens <104770531+mwinkens@users.noreply.github.com>

* Update lib/Command/Announce.php

Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Signed-off-by: mwinkens <104770531+mwinkens@users.noreply.github.com>

* Update lib/Command/Announce.php

Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Signed-off-by: mwinkens <104770531+mwinkens@users.noreply.github.com>

* Update lib/Command/Announce.php

Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Signed-off-by: mwinkens <104770531+mwinkens@users.noreply.github.com>

* Update lib/Command/Announce.php

Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Signed-off-by: mwinkens <104770531+mwinkens@users.noreply.github.com>

* return an error value instead of throwing an exception

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* test for result values bigger than zero and not for exceptions

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix composer issues

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix test being broken due to removed exception

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* remove restriction on notification types for CLI

This allows to add announcements without a notification type, which the API allows, these notifications will still appear in the notification app listed

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* Update lib/Command/AnnouncementList.php

Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Signed-off-by: mwinkens <104770531+mwinkens@users.noreply.github.com>

* remove linebreaks from list command

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

* fix test not properly setting non exististing user

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>

---------

Signed-off-by: Marvin Winkens <m.winkens@fz-juelich.de>
Signed-off-by: mwinkens <104770531+mwinkens@users.noreply.github.com>
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Joas Schilling <coding@schilljs.com>
Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Co-authored-by: skjnldsv <skjnldsv@protonmail.com>
Co-authored-by: Nextcloud bot <bot@nextcloud.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Joas Schilling <coding@schilljs.com>
  • Loading branch information
6 people authored Sep 12, 2024
1 parent a62ccb5 commit 911153c
Show file tree
Hide file tree
Showing 8 changed files with 783 additions and 0 deletions.
6 changes: 6 additions & 0 deletions appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@
</post-migration>
</repair-steps>

<commands>
<command>OCA\AnnouncementCenter\Command\Announce</command>
<command>OCA\AnnouncementCenter\Command\AnnouncementList</command>
<command>OCA\AnnouncementCenter\Command\AnnouncementDelete</command>
</commands>

<settings>
<admin>OCA\AnnouncementCenter\Settings\Admin</admin>
</settings>
Expand Down
200 changes: 200 additions & 0 deletions lib/Command/Announce.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
<?php
/**
* @copyright Copyright (c) 2024 Marvin Winkens <m.winkens@fz-juelich.de>
*
* @author Marvin Winkens <m.winkens@fz-juelich.de>
*
* @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\AnnouncementCenter\Command;

use OCA\AnnouncementCenter\Manager;
use OCA\AnnouncementCenter\Model\NotificationType;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IUserManager;
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\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class Announce extends Command {
protected IUserManager $userManager;
protected ITimeFactory $time;
protected Manager $manager;
protected NotificationType $notificationType;
protected LoggerInterface $logger;
public function __construct(IUserManager $userManager, ITimeFactory $time, Manager $manager, NotificationType $notificationType, LoggerInterface $logger) {
parent::__construct();
$this->userManager = $userManager;
$this->time = $time;
$this->manager = $manager;
$this->notificationType = $notificationType;
$this->logger = $logger;
}

protected function configure(): void {
$this
->setName('announcementcenter:announce')
->setDescription('Create an announcement')
->addArgument(
'user',
InputArgument::REQUIRED,
'User who creates the announcement',
)
->addArgument(
'subject',
InputArgument::REQUIRED,
'Subject of the announcement',
)
->addArgument(
'message',
InputArgument::REQUIRED,
'Message of the announcement (supports markdown)',
)
->addOption(
'activities',
null,
InputOption::VALUE_NONE,
'Generate activities',
)
->addOption(
'notifications',
null,
InputOption::VALUE_NONE,
'Generate notifications',
)
->addOption(
'emails',
null,
InputOption::VALUE_NONE,
'Notify users via email',
)
->addOption(
'comments',
null,
InputOption::VALUE_NONE,
'Allow comments',
)
->addOption(
'schedule-time',
's',
InputOption::VALUE_OPTIONAL,
'Publishing time of the announcement (see php strtotime)',
null,
)
->addOption(
'delete-time',
'd',
InputOption::VALUE_OPTIONAL,
'Deletion time of the announcement (see php strtotime)',
null,
)
->addOption(
'group',
'g',
InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
'Group to set send announcement to (default "everyone", multiple allowed)',
['everyone'],
);
}

private function plainifyMessage(string $message) {
# TODO use Parsedown or Markdownify here
return $message;
}

protected function execute(InputInterface $input, OutputInterface $output): int {
// required
$user = $input->getArgument('user');
if (!$this->userManager->userExists($user)) {
$output->writeln("User <$user> in unknown.");
return 1;
}
$subject = $input->getArgument('subject');
$message = $input->getArgument('message');

// options
$groups = $input->getOption('group');

// notification types
$activities = $input->getOption('activities');
$notifications = $input->getOption('notifications');
$emails = $input->getOption('emails');
$comments = $input->getOption('comments');

// times
try {
$scheduleTime = $this->parseTimestamp($input->getOption('schedule-time'));
$deleteTime = $this->parseTimestamp($input->getOption('delete-time'));
} catch(\InvalidArgumentException $e) {
$output->writeln($e->getMessage());
return 2;
}

// validation
if ($scheduleTime && $deleteTime && $deleteTime < $scheduleTime) {
$output->writeln('Publishing time is after deletion time');
return 2;
}

$plainMessage = $this->plainifyMessage($message);
$notificationOptions = $this->notificationType->setNotificationTypes($activities, $notifications, $emails);

$result = $this->manager->announce($subject, $message, $plainMessage, $user, $this->time->getTime(), $groups, $comments, $notificationOptions, $scheduleTime, $deleteTime);
$output->writeln("Created announcement #" . $result->getId() . ": " . $result->getSubject());

if ($scheduleTime) {
$output->writeln("Scheduled announcement for '" . date("D M j G:i:s T Y", $scheduleTime) . "'");
}

if ($deleteTime) {
$output->writeln("Scheduled deletion for '" . date("D M j G:i:s T Y", $deleteTime) . "'");
}

$this->logger->info('Admin ' . $user . ' posted a new announcement: "' . $result->getSubject() . '" over CLI');
return 0;
}

/**
* Parses an arbitrary $argument into a timestamp
* @param null|int|string $argument argument provided by CLI for a time
* Examples 1:
* '1711440621' a plain unix timestamp
* Examples 2 see strtotime (https://www.php.net/manual/de/function.strtotime.php):
* 'now', 10 September 200', '+1 day', 'tomorrow'
* @return int|null a timestamp, returns null if $argument is null
* @throws \InvalidArgumentException If the time could not be interpreted or the time is in the past
*/
private function parseTimestamp(null|int|string $argument): int|null {
if (is_null($argument)) {
return null;
} elseif (is_numeric($argument)) {
$timestamp = intval($argument);
} elseif (($convTime = strtotime($argument)) !== false) {
$timestamp = $convTime;
} else {
throw new \InvalidArgumentException("Could not interprete time '" . $argument . "'");
}

if ($timestamp < $this->time->getTime()) {
throw new \InvalidArgumentException("Time '" . $argument . "' is not allowed, because it's in the past");
}
return $timestamp;
}
}
76 changes: 76 additions & 0 deletions lib/Command/AnnouncementDelete.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php
/**
* @copyright Copyright (c) 2024 Marvin Winkens <m.winkens@fz-juelich.de>
*
* @author Marvin Winkens <m.winkens@fz-juelich.de>
*
* @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\AnnouncementCenter\Command;

use InvalidArgumentException;
use OCA\AnnouncementCenter\Manager;
use OCP\AppFramework\Db\DoesNotExistException;
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 AnnouncementDelete extends Command {
protected Manager $manager;
protected LoggerInterface $logger;
public function __construct(Manager $manager, LoggerInterface $logger) {
parent::__construct();
$this->manager = $manager;
$this->logger = $logger;
}

protected function configure(): void {
$this
->setName('announcementcenter:delete')
->setDescription('Delete announcement by id')
->addArgument(
'id',
InputArgument::REQUIRED,
'Id of announcement to delete',
);
}

protected function execute(InputInterface $input, OutputInterface $output): int {
try {
$deleteId = $this->parseId($input->getArgument('id'));
$this->manager->delete($deleteId);
} catch (DoesNotExistException) {
$output->writeln("Announcement with #" . $deleteId . " does not exist!");
return 1;
} catch (InvalidArgumentException $e) {
$output->writeln($e->getMessage());
return 1;
}
$output->writeln("Successfully deleted #" . $deleteId);
$this->logger->info('Admin deleted announcement #' . $deleteId . ' over CLI');
return 0;
}

private function parseId(mixed $value) {
if (is_numeric($value)) {
return intval($value);
}
throw new InvalidArgumentException('Id "' . $value . '" is not an integer');
}
}
105 changes: 105 additions & 0 deletions lib/Command/AnnouncementList.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php
/**
* @copyright Copyright (c) 2024 Marvin Winkens <m.winkens@fz-juelich.de>
*
* @author Marvin Winkens <m.winkens@fz-juelich.de>
*
* @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\AnnouncementCenter\Command;

use OCA\AnnouncementCenter\Manager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Terminal;

class AnnouncementList extends Command {
protected Manager $manager;
public function __construct(Manager $manager) {
parent::__construct();
$this->manager = $manager;
}

protected function configure(): void {
$this
->setName('announcementcenter:list')
->setDescription('List all announcements')
->addArgument(
'limit',
InputArgument::OPTIONAL,
'Maximal number of announcements listed',
10,
);
}

protected function execute(InputInterface $input, OutputInterface $output): int {
$ulimit = $input->getArgument('limit');
if (!is_numeric($ulimit)) {
$output->writeln('"' . $ulimit . '" is not numeric');
return 1;
}
$ulimit = intval($ulimit);
$announcements = $this->manager->getAnnouncements(0, $ulimit + 1);

// Calculate table size
$terminal = new Terminal();
$width = $terminal->getWidth();
$minimalWidth = 6;
$minimalWidthText = 10;
$widthSubject = max($minimalWidthText, intdiv($width - $minimalWidth, 3));
$widthMessage = max($minimalWidthText, $width - $minimalWidth - $widthSubject);

$widths = [$minimalWidth - 2, $widthSubject, $widthMessage];
$text = $this->formatTableRow(["ID", "Subject", "Message"], $widths);
$output->writeln($text);
$text = $this->formatTableRow(["", "", ""], $widths, "-");
$output->writeln($text);

foreach ($announcements as $index => $ann) {
if ($index === $ulimit) {
$output->writeln("And more ...");
break;
}
$texts = [$ann->getId(), $ann->getParsedSubject(), $ann->getPlainMessage()];

$text = $this->formatTableRow($texts, $widths);
$output->writeln($text);
}
return 0;
}

private function ellipseAndPadText(string $text, int $width, string $sep = " "): string {
$text = str_replace(["\r", "\n"], ' ', $text);
$text = str_pad($text, $width, $sep, STR_PAD_RIGHT);
$text = strlen($text) > $width ? substr($text, 0, $width - 2) . "" : $text;
return $text;
}

private function formatTableRow(array $texts, array $widths, string $sep = " "): string {
$callback = function ($a, $b) use ($sep) {
return $this->ellipseAndPadText($a, $b, $sep);
};
$formattedTexts = array_map(
$callback,
$texts,
$widths
);
return implode("|", $formattedTexts);
}
}
Loading

0 comments on commit 911153c

Please sign in to comment.