Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/polls.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRené Gieling <github@dartcafe.de>2021-12-29 02:58:24 +0300
committerGitHub <noreply@github.com>2021-12-29 02:58:24 +0300
commit70d682d911f8410474709d240b767280ae80e011 (patch)
tree01939f07ecbc22118cd101ca6c4ebbadd90e2db8
parentc4e4c7cde4965c62c7b272065d4f13bb1fc8a7b8 (diff)
Adding activities (#2154)
-rw-r--r--.php-cs-fixer.dist.php2
-rw-r--r--appinfo/info.xml5
-rw-r--r--lib/Activity/PollChanges.php69
-rw-r--r--lib/AppInfo/Application.php32
-rw-r--r--lib/Db/Option.php2
-rw-r--r--lib/Db/Poll.php10
-rw-r--r--lib/Db/PollsEntity.php29
-rw-r--r--lib/Db/Preferences.php3
-rw-r--r--lib/Db/Share.php29
-rw-r--r--lib/Event/BaseEvent.php133
-rw-r--r--lib/Event/CommentAddEvent.php33
-rw-r--r--lib/Event/CommentDeleteEvent.php33
-rw-r--r--lib/Event/CommentEvent.php28
-rw-r--r--lib/Event/OptionConfirmedEvent.php9
-rw-r--r--lib/Event/OptionCreatedEvent.php9
-rw-r--r--lib/Event/OptionDeletedEvent.php9
-rw-r--r--lib/Event/OptionEvent.php36
-rw-r--r--lib/Event/OptionUnconfirmedEvent.php35
-rw-r--r--lib/Event/OptionUpdatedEvent.php9
-rw-r--r--lib/Event/PollArchivedEvent.php9
-rw-r--r--lib/Event/PollCreatedEvent.php9
-rw-r--r--lib/Event/PollDeletedEvent.php10
-rw-r--r--lib/Event/PollEvent.php55
-rw-r--r--lib/Event/PollExpiredEvent.php9
-rw-r--r--lib/Event/PollOptionReorderedEvent.php35
-rw-r--r--lib/Event/PollRestoredEvent.php9
-rw-r--r--lib/Event/PollTakeoverEvent.php9
-rw-r--r--lib/Event/PollUpdatedEvent.php9
-rw-r--r--lib/Event/ShareChangeEmailEvent.php33
-rw-r--r--lib/Event/ShareChangeRegistrationConstraintEvent.php33
-rw-r--r--lib/Event/ShareCreateEvent.php33
-rw-r--r--lib/Event/ShareDeletedEvent.php33
-rw-r--r--lib/Event/ShareEvent.php30
-rw-r--r--lib/Event/ShareRegistrationEvent.php33
-rw-r--r--lib/Event/ShareTypeChangedEvent.php33
-rw-r--r--lib/Event/VoteEvent.php34
-rw-r--r--lib/Event/VoteSetEvent.php37
-rw-r--r--lib/Exceptions/InvalidClassException.php32
-rw-r--r--lib/Helper/Container.php55
-rw-r--r--lib/Helper/Trace.php2
-rw-r--r--lib/Listener/BaseListener.php182
-rw-r--r--lib/Listener/CommentListener.php40
-rw-r--r--lib/Listener/GroupDeletedListener.php25
-rw-r--r--lib/Listener/OptionListener.php39
-rw-r--r--lib/Listener/PollListener.php53
-rw-r--r--lib/Listener/ShareListener.php40
-rw-r--r--lib/Listener/UserDeletedListener.php27
-rw-r--r--lib/Listener/VoteListener.php38
-rw-r--r--lib/Model/Mail/InvitationMail.php47
-rw-r--r--lib/Model/Mail/MailBase.php47
-rw-r--r--lib/Model/Mail/NotificationMail.php22
-rw-r--r--lib/Model/Mail/ReminderMail.php4
-rw-r--r--lib/Model/Settings/AppSettings.php27
-rw-r--r--lib/Model/UserGroup/Circle.php22
-rw-r--r--lib/Model/UserGroup/Contact.php9
-rw-r--r--lib/Model/UserGroup/ContactGroup.php11
-rw-r--r--lib/Model/UserGroup/Email.php1
-rw-r--r--lib/Model/UserGroup/GenericUser.php1
-rw-r--r--lib/Model/UserGroup/Group.php8
-rw-r--r--lib/Model/UserGroup/User.php5
-rw-r--r--lib/Model/UserGroup/UserBase.php24
-rw-r--r--lib/Provider/ActivityProvider.php138
-rw-r--r--lib/Service/ActivityService.php370
-rw-r--r--lib/Service/CommentService.php7
-rw-r--r--lib/Service/LogService.php14
-rw-r--r--lib/Service/OptionService.php17
-rw-r--r--lib/Service/SettingsService.php8
-rw-r--r--lib/Service/ShareService.php22
-rw-r--r--lib/Service/VoteService.php6
-rw-r--r--lib/Settings/ActivitySettings.php68
-rw-r--r--lib/Settings/ActivityVote.php34
-rw-r--r--package-lock.json1128
-rw-r--r--package.json1
-rw-r--r--psalm-baseline.xml52
-rw-r--r--src/js/App.vue18
-rw-r--r--src/js/assets/icons/clock-fff.svg10
-rw-r--r--src/js/assets/icons/clock.svg10
-rw-r--r--src/js/assets/icons/mail-fff.svg6
-rw-r--r--src/js/assets/icons/polls-000.svg14
-rw-r--r--src/js/assets/icons/polls-fff.svg14
-rw-r--r--src/js/components/Activity/Activities.vue49
-rw-r--r--src/js/components/Activity/ActivityItem.vue147
-rw-r--r--src/js/components/Settings/AdminMisc.vue11
-rw-r--r--src/js/components/SideBar/SideBarTabActivity.vue56
-rw-r--r--src/js/mixins/watchPolls.js2
-rw-r--r--src/js/store/modules/activity.js69
-rw-r--r--src/js/store/modules/appSettings.js1
-rw-r--r--src/js/views/SideBar.vue10
88 files changed, 3385 insertions, 626 deletions
diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php
index 71fd5690..54b0e3cf 100644
--- a/.php-cs-fixer.dist.php
+++ b/.php-cs-fixer.dist.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-require_once './vendor/autoload.php';
+require_once 'vendor/autoload.php';
use Nextcloud\CodingStandard\Config;
diff --git a/appinfo/info.xml b/appinfo/info.xml
index 79b18932..7555e6e3 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -25,6 +25,11 @@
<php min-version="7.3"/>
<nextcloud min-version="21" max-version="23" />
</dependencies>
+ <activity>
+ <providers>
+ <provider>OCA\Polls\Provider\ActivityProvider</provider>
+ </providers>
+ </activity>
<background-jobs>
<job>OCA\Polls\Cron\NotificationCron</job>
<job>OCA\Polls\Cron\JanitorCron</job>
diff --git a/lib/Activity/PollChanges.php b/lib/Activity/PollChanges.php
new file mode 100644
index 00000000..14b1956d
--- /dev/null
+++ b/lib/Activity/PollChanges.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Activity;
+
+use OCP\Activity\IFilter;
+use OCP\IL10N;
+use OCP\IURLGenerator;
+
+class PollChanges implements IFilter {
+
+ /** @var IL10N */
+ protected $trans;
+
+ /** @var IURLGenerator */
+ protected $urlGenerator;
+
+ /**
+ * @param IL10N $trans
+ * @param IURLGenerator $urlGenerator
+ */
+ public function __construct(IL10N $trans, IURLGenerator $urlGenerator) {
+ $this->trans = $trans;
+ $this->urlGenerator = $urlGenerator;
+ }
+
+ public function getIdentifier() : string {
+ return 'polls';
+ }
+
+ public function getName() : string {
+ return $this->trans->t('Poll changes');
+ }
+
+ public function getIcon() : string {
+ return $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('polls', 'polls-black.svg'));
+ }
+
+ public function getPriority() : int {
+ return 70;
+ }
+
+ public function allowedApps() : array {
+ return ['polls'];
+ }
+
+ public function filterTypes(array $types) : array {
+ return ['poll_add', 'vote_set'];
+ }
+}
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php
index 5f56415f..455cc4f5 100644
--- a/lib/AppInfo/Application.php
+++ b/lib/AppInfo/Application.php
@@ -32,11 +32,14 @@ use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\Notification\IManager as NotificationManager;
use OCP\Group\Events\GroupDeletedEvent;
use OCP\User\Events\UserDeletedEvent;
-use OCA\Polls\Event\CommentEvent;
-use OCA\Polls\Event\OptionEvent;
+use OCA\Polls\Event\CommentAddEvent;
+use OCA\Polls\Event\CommentDeleteEvent;
use OCA\Polls\Event\OptionConfirmedEvent;
use OCA\Polls\Event\OptionCreatedEvent;
use OCA\Polls\Event\OptionDeletedEvent;
+use OCA\Polls\Event\OptionUnconfirmedEvent;
+use OCA\Polls\Event\PollOptionReorderedEvent;
+use OCA\Polls\Event\OptionUpdatedEvent;
use OCA\Polls\Event\PollArchivedEvent;
use OCA\Polls\Event\PollCreatedEvent;
use OCA\Polls\Event\PollDeletedEvent;
@@ -44,8 +47,13 @@ use OCA\Polls\Event\PollExpiredEvent;
use OCA\Polls\Event\PollRestoredEvent;
use OCA\Polls\Event\PollTakeoverEvent;
use OCA\Polls\Event\PollUpdatedEvent;
-use OCA\Polls\Event\ShareEvent;
-use OCA\Polls\Event\VoteEvent;
+use OCA\Polls\Event\ShareCreateEvent;
+use OCA\Polls\Event\ShareTypeChangedEvent;
+use OCA\Polls\Event\ShareChangedEmailEvent;
+use OCA\Polls\Event\ShareChangedRegistrationConstraintEvent;
+use OCA\Polls\Event\ShareDeletedEvent;
+use OCA\Polls\Event\ShareRegistrationEvent;
+use OCA\Polls\Event\VoteSetEvent;
use OCA\Polls\Notification\Notifier;
use OCA\Polls\Listener\UserDeletedListener;
use OCA\Polls\Listener\GroupDeletedListener;
@@ -71,11 +79,14 @@ class Application extends App implements IBootstrap {
public function register(IRegistrationContext $context): void {
include_once __DIR__ . '/../../vendor/autoload.php';
- $context->registerEventListener(CommentEvent::class, CommentListener::class);
- $context->registerEventListener(OptionEvent::class, OptionListener::class);
+ $context->registerEventListener(CommentAddEvent::class, CommentListener::class);
+ $context->registerEventListener(CommentDeleteEvent::class, CommentListener::class);
$context->registerEventListener(OptionConfirmedEvent::class, OptionListener::class);
$context->registerEventListener(OptionCreatedEvent::class, OptionListener::class);
$context->registerEventListener(OptionDeletedEvent::class, OptionListener::class);
+ $context->registerEventListener(OptionUnconfirmedEvent::class, OptionListener::class);
+ $context->registerEventListener(PollOptionReorderedEvent::class, OptionListener::class);
+ $context->registerEventListener(OptionUpdatedEvent::class, OptionListener::class);
$context->registerEventListener(PollArchivedEvent::class, PollListener::class);
$context->registerEventListener(PollCreatedEvent::class, PollListener::class);
$context->registerEventListener(PollDeletedEvent::class, PollListener::class);
@@ -83,8 +94,13 @@ class Application extends App implements IBootstrap {
$context->registerEventListener(PollRestoredEvent::class, PollListener::class);
$context->registerEventListener(PollTakeoverEvent::class, PollListener::class);
$context->registerEventListener(PollUpdatedEvent::class, PollListener::class);
- $context->registerEventListener(ShareEvent::class, ShareListener::class);
- $context->registerEventListener(VoteEvent::class, VoteListener::class);
+ $context->registerEventListener(ShareChangedEmailEvent::class, ShareListener::class);
+ $context->registerEventListener(ShareChangedRegistrationConstraintEvent::class, ShareListener::class);
+ $context->registerEventListener(ShareCreateEvent::class, ShareListener::class);
+ $context->registerEventListener(ShareDeletedEvent::class, ShareListener::class);
+ $context->registerEventListener(ShareRegistrationEvent::class, ShareListener::class);
+ $context->registerEventListener(ShareTypeChangedEvent::class, ShareListener::class);
+ $context->registerEventListener(VoteSetEvent::class, VoteListener::class);
$context->registerEventListener(UserDeletedEvent::class, UserDeletedListener::class);
$context->registerEventListener(GroupDeletedEvent::class, GroupDeletedListener::class);
}
diff --git a/lib/Db/Option.php b/lib/Db/Option.php
index 8d341669..c8c3fce4 100644
--- a/lib/Db/Option.php
+++ b/lib/Db/Option.php
@@ -179,7 +179,7 @@ class Option extends Entity implements JsonSerializable {
return $this->owner;
}
- public function getDisplayName(): string {
+ public function getDisplayName(): ?string {
if (!strncmp($this->getOwner(), 'deleted_', 8)) {
return 'Deleted User';
}
diff --git a/lib/Db/Poll.php b/lib/Db/Poll.php
index 68a07636..63371877 100644
--- a/lib/Db/Poll.php
+++ b/lib/Db/Poll.php
@@ -255,6 +255,11 @@ class Poll extends Entity implements JsonSerializable {
return $this->getMiscSettingsArray()['autoReminder'] ?? false;
}
+ // alias of getId()
+ public function getPollId(): int {
+ return $this->getId();
+ }
+
public function getProposalsExpired(): bool {
return (
$this->getProposalsExpire() > 0
@@ -284,7 +289,10 @@ class Poll extends Entity implements JsonSerializable {
return json_decode($this->getMiscSettings(), true);
}
- private function setMiscSettingsByKey(string $key, $value) {
+ /**
+ * @param bool|string|int|array $value
+ */
+ private function setMiscSettingsByKey(string $key, $value): void {
$miscSettings = $this->getMiscSettingsArray();
$miscSettings[$key] = $value;
$this->setMiscSettingsArray($miscSettings);
diff --git a/lib/Db/PollsEntity.php b/lib/Db/PollsEntity.php
new file mode 100644
index 00000000..b4e8bf20
--- /dev/null
+++ b/lib/Db/PollsEntity.php
@@ -0,0 +1,29 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Kai Schröer <git@schroeer.co>
+ *
+ * @author Kai Schröer <git@schroeer.co>
+ *
+ * @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\Polls\Db;
+
+use OCP\AppFramework\Db\Entity;
+
+abstract class PollsEntity extends Entity {
+}
diff --git a/lib/Db/Preferences.php b/lib/Db/Preferences.php
index 040abe1a..b1ff1afe 100644
--- a/lib/Db/Preferences.php
+++ b/lib/Db/Preferences.php
@@ -25,6 +25,7 @@ namespace OCA\Polls\Db;
use JsonSerializable;
use OCA\Dashboard\Service\BackgroundService;
+use OCA\Polls\Helper\Container;
use OCP\AppFramework\Db\Entity;
/**
@@ -67,7 +68,7 @@ class Preferences extends Entity implements JsonSerializable {
* Fetch dashboard settings
*/
public function getDashboardBackground(): array {
- if (\OC::$server->getAppManager()->isEnabledForUser('dashboard')) {
+ if (Container::isAppEnabled('dashboard')) {
$background = \OC::$server->getConfig()->getUserValue($this->userId, 'dashboard', 'background');
return [
'isInstalled' => true,
diff --git a/lib/Db/Share.php b/lib/Db/Share.php
index 49a78bf1..9083806f 100644
--- a/lib/Db/Share.php
+++ b/lib/Db/Share.php
@@ -28,8 +28,7 @@ use JsonSerializable;
use OCP\AppFramework\Db\Entity;
use OCA\Polls\Model\UserGroup\UserBase;
use OCA\Polls\Model\Settings\AppSettings;
-use OCP\AppFramework\IAppContainer;
-use OCA\Polls\AppInfo\Application;
+use OCA\Polls\Helper\Container;
/**
* @method int getId()
@@ -191,6 +190,14 @@ class Share extends Entity implements JsonSerializable {
);
}
+ public function getRichObjectString(): array {
+ return [
+ 'type' => 'highlight',
+ 'id' => $this->getId(),
+ 'name' => $this->getType(),
+ ];
+ }
+
private function setMiscSettingsArray(array $value) : void {
$this->setMiscSettings(json_encode($value));
}
@@ -199,7 +206,10 @@ class Share extends Entity implements JsonSerializable {
return json_decode($this->getMiscSettings(), true);
}
- private function setMiscSettingsByKey(string $key, $value) {
+ /**
+ * @param bool|string|int|array $value
+ */
+ private function setMiscSettingsByKey(string $key, $value): void {
$miscSettings = $this->getMiscSettingsArray();
$miscSettings[$key] = $value;
$this->setMiscSettingsArray($miscSettings);
@@ -213,20 +223,9 @@ class Share extends Entity implements JsonSerializable {
*/
private function getDefaultPublicPollEmail() : string {
try {
- return $this->getContainer()
- ->query(PollMapper::class)
- ->find($this->getPollId())->getPublicPollEmail();
+ return Container::queryPoll($this->getPollId())->getPublicPollEmail();
} catch (\Exception $e) {
return 'optional';
}
}
-
- /**
- * remove also
- * @deprecated
- */
- protected static function getContainer() : IAppContainer {
- $app = \OC::$server->query(Application::class);
- return $app->getContainer();
- }
}
diff --git a/lib/Event/BaseEvent.php b/lib/Event/BaseEvent.php
new file mode 100644
index 00000000..dc27e8c4
--- /dev/null
+++ b/lib/Event/BaseEvent.php
@@ -0,0 +1,133 @@
+<?php
+/*
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Event;
+
+use OCP\AppFramework\Db\Entity;
+use OCP\EventDispatcher\Event;
+use OCA\Polls\Db\Comment;
+use OCA\Polls\Db\Option;
+use OCA\Polls\Db\Poll;
+use OCA\Polls\Db\Share;
+use OCA\Polls\Db\Vote;
+use OCA\Polls\Helper\Container;
+
+abstract class BaseEvent extends Event {
+ /** @var string */
+ protected $activityObject = '';
+
+ /** @var string */
+ protected $activitySubject = '';
+
+ /** @var array */
+ protected $activitySubjectParams = [];
+
+ /** @var Poll|Comment|Share|Option|Vote */
+ protected $eventObject;
+
+ /** @var Poll */
+ protected $poll;
+
+ /** @var bool */
+ protected $log = true;
+
+ public function __construct(
+ $eventObject
+ ) {
+ parent::__construct();
+ $this->eventObject = $eventObject;
+ $this->poll = Container::queryPoll($this->getPollId());
+
+ $this->activitySubjectParams['pollTitle'] = [
+ 'type' => 'highlight',
+ 'id' => $this->eventObject->getPollId(),
+ 'name' => $this->poll->getTitle(),
+ 'link' => $this->poll->getVoteUrl(),
+ ];
+ }
+
+ public function getEventObject(): Entity {
+ return $this->eventObject;
+ }
+
+ public function getPollId(): int {
+ return $this->eventObject->getPollId();
+ }
+
+ public function getPollUrl(): string {
+ return $this->poll->getVoteUrl();
+ }
+
+ public function getPollTitle(): string {
+ return $this->poll->getTitle();
+ }
+
+ public function getPollOwner(): string {
+ return $this->poll->getOwner();
+ }
+
+ public function getPoll(): Poll {
+ return $this->poll;
+ }
+
+ public function getActor(): string {
+ if (\OC::$server->getUserSession()->isLoggedIn()) {
+ return \OC::$server->getUserSession()->getUser()->getUID();
+ }
+ return $this->eventObject->getUserId();
+ }
+
+ public function getLogId(): ?string {
+ if ($this->log && $this->activitySubject) {
+ return $this->activitySubject;
+ }
+ return '';
+ }
+
+ public function getNotification(): array {
+ return [];
+ }
+
+ public function getActivityId(): string {
+ return $this->activitySubject;
+ }
+
+ public function getActivityObject(): string {
+ return $this->activityObject;
+ }
+
+ public function getActivityObjectId(): int {
+ if ($this->activityObject === 'poll') {
+ return $this->eventObject->getPollId();
+ }
+ return $this->eventObject->getId();
+ }
+
+ public function getActivitySubject(): string {
+ return $this->activitySubject;
+ }
+
+ public function getActivitySubjectParams(): array {
+ return $this->activitySubjectParams;
+ }
+}
diff --git a/lib/Event/CommentAddEvent.php b/lib/Event/CommentAddEvent.php
new file mode 100644
index 00000000..1fd930b0
--- /dev/null
+++ b/lib/Event/CommentAddEvent.php
@@ -0,0 +1,33 @@
+<?php
+/*
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Event;
+
+use OCA\Polls\Db\Comment;
+
+class CommentAddEvent extends CommentEvent {
+ public function __construct(Comment $comment) {
+ parent::__construct($comment);
+ $this->activitySubject = self::ADD;
+ }
+}
diff --git a/lib/Event/CommentDeleteEvent.php b/lib/Event/CommentDeleteEvent.php
new file mode 100644
index 00000000..f17a8c5f
--- /dev/null
+++ b/lib/Event/CommentDeleteEvent.php
@@ -0,0 +1,33 @@
+<?php
+/*
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Event;
+
+use OCA\Polls\Db\Comment;
+
+class CommentDeleteEvent extends CommentEvent {
+ public function __construct(Comment $comment) {
+ parent::__construct($comment);
+ $this->activitySubject = self::DELETE;
+ }
+}
diff --git a/lib/Event/CommentEvent.php b/lib/Event/CommentEvent.php
index 3a3beb08..7d02841f 100644
--- a/lib/Event/CommentEvent.php
+++ b/lib/Event/CommentEvent.php
@@ -23,35 +23,27 @@
namespace OCA\Polls\Event;
-use OCP\EventDispatcher\Event;
use OCA\Polls\Db\Comment;
-class CommentEvent extends Event {
+abstract class CommentEvent extends BaseEvent {
+ public const ADD = 'comment_add';
+ public const DELETE = 'comment_delete';
/** @var Comment */
private $comment;
public function __construct(Comment $comment) {
- parent::__construct();
+ parent::__construct($comment);
+ $this->activityObject = 'poll';
$this->comment = $comment;
+ $this->activitySubjectParams['comment'] = [
+ 'type' => 'highlight',
+ 'id' => $comment->getId(),
+ 'name' => $comment->getComment(),
+ ];
}
public function getComment(): Comment {
return $this->comment;
}
-
- public function getPollId(): int {
- return $this->comment->getPollId();
- }
-
- public function getLogMsg(): string {
- return '';
- }
-
- public function getActor(): string {
- if (\OC::$server->getUserSession()->isLoggedIn()) {
- return \OC::$server->getUserSession()->getUser()->getUID();
- }
- return $this->comment->getUserId();
- }
}
diff --git a/lib/Event/OptionConfirmedEvent.php b/lib/Event/OptionConfirmedEvent.php
index 44e66628..6a0c1e00 100644
--- a/lib/Event/OptionConfirmedEvent.php
+++ b/lib/Event/OptionConfirmedEvent.php
@@ -23,10 +23,13 @@
namespace OCA\Polls\Event;
-use OCA\Polls\Db\Log;
+use OCA\Polls\Db\Option;
class OptionConfirmedEvent extends OptionEvent {
- public function getLogMsg(): string {
- return Log::MSG_ID_CONFIRMOPTION;
+ public function __construct(
+ Option $option
+ ) {
+ parent::__construct($option);
+ $this->activitySubject = self::CONFIRM;
}
}
diff --git a/lib/Event/OptionCreatedEvent.php b/lib/Event/OptionCreatedEvent.php
index 4ed7acc2..44bf4027 100644
--- a/lib/Event/OptionCreatedEvent.php
+++ b/lib/Event/OptionCreatedEvent.php
@@ -23,10 +23,13 @@
namespace OCA\Polls\Event;
-use OCA\Polls\Db\Log;
+use OCA\Polls\Db\Option;
class OptionCreatedEvent extends OptionEvent {
- public function getLogMsg(): string {
- return Log::MSG_ID_ADDOPTION;
+ public function __construct(
+ Option $option
+ ) {
+ parent::__construct($option);
+ $this->activitySubject = self::ADD;
}
}
diff --git a/lib/Event/OptionDeletedEvent.php b/lib/Event/OptionDeletedEvent.php
index e5ec521e..3c8ae7e4 100644
--- a/lib/Event/OptionDeletedEvent.php
+++ b/lib/Event/OptionDeletedEvent.php
@@ -23,10 +23,13 @@
namespace OCA\Polls\Event;
-use OCA\Polls\Db\Log;
+use OCA\Polls\Db\Option;
class OptionDeletedEvent extends OptionEvent {
- public function getLogMsg(): string {
- return Log::MSG_ID_DELETEOPTION;
+ public function __construct(
+ Option $option
+ ) {
+ parent::__construct($option);
+ $this->activitySubject = self::DELETE;
}
}
diff --git a/lib/Event/OptionEvent.php b/lib/Event/OptionEvent.php
index 2413aa42..6cb4edb7 100644
--- a/lib/Event/OptionEvent.php
+++ b/lib/Event/OptionEvent.php
@@ -23,34 +23,32 @@
namespace OCA\Polls\Event;
-use OCP\EventDispatcher\Event;
use OCA\Polls\Db\Option;
-class OptionEvent extends Event {
+abstract class OptionEvent extends BaseEvent {
+ public const ADD = 'option_add';
+ public const UPDATE = 'option_update';
+ public const CONFIRM = 'option_confirm';
+ public const UNCONFIRM = 'option_unconfirm';
+ public const DELETE = 'option_delete';
+
/** @var Option */
private $option;
- public function __construct(Option $option) {
- parent::__construct();
+ public function __construct(
+ Option $option
+ ) {
+ parent::__construct($option);
+ $this->activityObject = 'poll';
$this->option = $option;
+ $this->activitySubjectParams['optionTitle'] = [
+ 'type' => 'highlight',
+ 'id' => $this->option->getId(),
+ 'name' => $this->option->getPollOptionText(),
+ ];
}
public function getOption(): Option {
return $this->option;
}
-
- public function getPollId(): int {
- return $this->option->getPollId();
- }
-
- public function getLogMsg(): string {
- return '';
- }
-
- public function getActor(): string {
- if (\OC::$server->getUserSession()->isLoggedIn()) {
- return \OC::$server->getUserSession()->getUser()->getUID();
- }
- return $this->option->getOwner();
- }
}
diff --git a/lib/Event/OptionUnconfirmedEvent.php b/lib/Event/OptionUnconfirmedEvent.php
new file mode 100644
index 00000000..996f0ec7
--- /dev/null
+++ b/lib/Event/OptionUnconfirmedEvent.php
@@ -0,0 +1,35 @@
+<?php
+/*
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Event;
+
+use OCA\Polls\Db\Option;
+
+class OptionUnconfirmedEvent extends OptionEvent {
+ public function __construct(
+ Option $option
+ ) {
+ parent::__construct($option);
+ $this->activitySubject = self::UNCONFIRM;
+ }
+}
diff --git a/lib/Event/OptionUpdatedEvent.php b/lib/Event/OptionUpdatedEvent.php
index b26d823b..248fb89e 100644
--- a/lib/Event/OptionUpdatedEvent.php
+++ b/lib/Event/OptionUpdatedEvent.php
@@ -23,10 +23,13 @@
namespace OCA\Polls\Event;
-use OCA\Polls\Db\Log;
+use OCA\Polls\Db\Option;
class OptionUpdatedEvent extends OptionEvent {
- public function getLogMsg(): string {
- return Log::MSG_ID_UPDATEOPTION;
+ public function __construct(
+ Option $option
+ ) {
+ parent::__construct($option);
+ $this->activitySubject = self::UPDATE;
}
}
diff --git a/lib/Event/PollArchivedEvent.php b/lib/Event/PollArchivedEvent.php
index 1226bb92..b2406074 100644
--- a/lib/Event/PollArchivedEvent.php
+++ b/lib/Event/PollArchivedEvent.php
@@ -23,12 +23,15 @@
namespace OCA\Polls\Event;
-use OCA\Polls\Db\Log;
use OCA\Polls\Notification\Notifier;
+use OCA\Polls\Db\Poll;
class PollArchivedEvent extends PollEvent {
- public function getLogMsg(): string {
- return Log::MSG_ID_DELETEPOLL;
+ public function __construct(
+ Poll $poll
+ ) {
+ parent::__construct($poll);
+ $this->activitySubject = self::DELETE;
}
public function getNotification(): array {
diff --git a/lib/Event/PollCreatedEvent.php b/lib/Event/PollCreatedEvent.php
index 6d9bd3bc..c91282a1 100644
--- a/lib/Event/PollCreatedEvent.php
+++ b/lib/Event/PollCreatedEvent.php
@@ -23,10 +23,13 @@
namespace OCA\Polls\Event;
-use OCA\Polls\Db\Log;
+use OCA\Polls\Db\Poll;
class PollCreatedEvent extends PollEvent {
- public function getLogMsg(): string {
- return Log::MSG_ID_ADDPOLL;
+ public function __construct(
+ Poll $poll
+ ) {
+ parent::__construct($poll);
+ $this->activitySubject = self::ADD;
}
}
diff --git a/lib/Event/PollDeletedEvent.php b/lib/Event/PollDeletedEvent.php
index 1c8e8f70..b96389ba 100644
--- a/lib/Event/PollDeletedEvent.php
+++ b/lib/Event/PollDeletedEvent.php
@@ -25,11 +25,17 @@ namespace OCA\Polls\Event;
use OCA\Polls\Notification\Notifier;
+use OCA\Polls\Db\Poll;
+
class PollDeletedEvent extends PollEvent {
- public function getLogMsg(): string {
- return '';
+ public function __construct(
+ Poll $poll
+ ) {
+ parent::__construct($poll);
+ $this->activitySubject = self::DELETE;
}
+
public function getNotification(): array {
if ($this->getActor() === $this->getPollOwner()) {
return [];
diff --git a/lib/Event/PollEvent.php b/lib/Event/PollEvent.php
index b95f4730..7de18353 100644
--- a/lib/Event/PollEvent.php
+++ b/lib/Event/PollEvent.php
@@ -23,56 +23,23 @@
namespace OCA\Polls\Event;
-use OCP\EventDispatcher\Event;
use OCA\Polls\Db\Poll;
-abstract class PollEvent extends Event {
+abstract class PollEvent extends BaseEvent {
+ public const ADD = 'poll_add';
+ public const UPDATE = 'poll_update';
+ public const DELETE = 'poll_delete';
+ public const RESTORE = 'poll_restore';
+ public const EXPIRE = 'poll_expire';
+ public const OWNER_CHANGE = 'poll_change_owner';
+ public const OPTION_REORDER = 'poll_option_reorder';
/** @var Poll */
- private $poll;
-
- /** @var string */
- private $pollOwner;
-
- /** @var int */
- private $pollId;
-
- /** @var string */
- private $pollTitle;
+ protected $poll;
public function __construct(Poll $poll) {
- parent::__construct();
+ parent::__construct($poll);
+ $this->activityObject = 'poll';
$this->poll = $poll;
- $this->pollOwner = $this->poll->getOwner();
- $this->pollId = $this->poll->getId();
- $this->pollTitle = $this->poll->getTitle();
- }
-
- public function getPoll(): Poll {
- return $this->poll;
- }
-
- public function getPollId(): int {
- return $this->pollId;
- }
-
- public function getPollTitle(): string {
- return $this->pollTitle;
- }
-
- public function getPollOwner(): string {
- return $this->pollOwner;
- }
-
- public function getLogMsg(): string {
- return '';
- }
-
- public function getNotification(): array {
- return [];
- }
-
- public function getActor(): string {
- return \OC::$server->getUserSession()->getUser()->getUID();
}
}
diff --git a/lib/Event/PollExpiredEvent.php b/lib/Event/PollExpiredEvent.php
index dfdd94a9..6990ff11 100644
--- a/lib/Event/PollExpiredEvent.php
+++ b/lib/Event/PollExpiredEvent.php
@@ -23,10 +23,13 @@
namespace OCA\Polls\Event;
-use OCA\Polls\Db\Log;
+use OCA\Polls\Db\Poll;
class PollExpiredEvent extends PollEvent {
- public function getLogMsg(): string {
- return Log::MSG_ID_EXPIREPOLL;
+ public function __construct(
+ Poll $poll
+ ) {
+ parent::__construct($poll);
+ $this->activitySubject = self::EXPIRE;
}
}
diff --git a/lib/Event/PollOptionReorderedEvent.php b/lib/Event/PollOptionReorderedEvent.php
new file mode 100644
index 00000000..c43633be
--- /dev/null
+++ b/lib/Event/PollOptionReorderedEvent.php
@@ -0,0 +1,35 @@
+<?php
+/*
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Event;
+
+use OCA\Polls\Db\Poll;
+
+class PollOptionReorderedEvent extends PollEvent {
+ public function __construct(
+ Poll $poll
+ ) {
+ parent::__construct($poll);
+ $this->activitySubject = self::OPTION_REORDER;
+ }
+}
diff --git a/lib/Event/PollRestoredEvent.php b/lib/Event/PollRestoredEvent.php
index 69a92c5a..bee13800 100644
--- a/lib/Event/PollRestoredEvent.php
+++ b/lib/Event/PollRestoredEvent.php
@@ -23,10 +23,13 @@
namespace OCA\Polls\Event;
-use OCA\Polls\Db\Log;
+use OCA\Polls\Db\Poll;
class PollRestoredEvent extends PollEvent {
- public function getLogMsg(): string {
- return Log::MSG_ID_RESTOREPOLL;
+ public function __construct(
+ Poll $poll
+ ) {
+ parent::__construct($poll);
+ $this->activitySubject = self::RESTORE;
}
}
diff --git a/lib/Event/PollTakeoverEvent.php b/lib/Event/PollTakeoverEvent.php
index 212c8003..23b945f5 100644
--- a/lib/Event/PollTakeoverEvent.php
+++ b/lib/Event/PollTakeoverEvent.php
@@ -23,12 +23,15 @@
namespace OCA\Polls\Event;
-use OCA\Polls\Db\Log;
use OCA\Polls\Notification\Notifier;
+use OCA\Polls\Db\Poll;
class PollTakeoverEvent extends PollEvent {
- public function getLogMsg(): string {
- return Log::MSG_ID_OWNERCHANGE;
+ public function __construct(
+ Poll $poll
+ ) {
+ parent::__construct($poll);
+ $this->activitySubject = self::OWNER_CHANGE;
}
public function getNotification(): array {
diff --git a/lib/Event/PollUpdatedEvent.php b/lib/Event/PollUpdatedEvent.php
index fd356b09..b976951b 100644
--- a/lib/Event/PollUpdatedEvent.php
+++ b/lib/Event/PollUpdatedEvent.php
@@ -23,10 +23,13 @@
namespace OCA\Polls\Event;
-use OCA\Polls\Db\Log;
+use OCA\Polls\Db\Poll;
class PollUpdatedEvent extends PollEvent {
- public function getLogMsg(): string {
- return Log::MSG_ID_UPDATEPOLL;
+ public function __construct(
+ Poll $poll
+ ) {
+ parent::__construct($poll);
+ $this->activitySubject = self::UPDATE;
}
}
diff --git a/lib/Event/ShareChangeEmailEvent.php b/lib/Event/ShareChangeEmailEvent.php
new file mode 100644
index 00000000..c06b7a3c
--- /dev/null
+++ b/lib/Event/ShareChangeEmailEvent.php
@@ -0,0 +1,33 @@
+<?php
+/*
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Event;
+
+use OCA\Polls\Db\Share;
+
+class ShareChangedEmailEvent extends ShareEvent {
+ public function __construct(Share $share) {
+ parent::__construct($share);
+ $this->activitySubject = self::CHANGE_EMAIL;
+ }
+}
diff --git a/lib/Event/ShareChangeRegistrationConstraintEvent.php b/lib/Event/ShareChangeRegistrationConstraintEvent.php
new file mode 100644
index 00000000..74ca7340
--- /dev/null
+++ b/lib/Event/ShareChangeRegistrationConstraintEvent.php
@@ -0,0 +1,33 @@
+<?php
+/*
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Event;
+
+use OCA\Polls\Db\Share;
+
+class ShareChangedRegistrationConstraintEvent extends ShareEvent {
+ public function __construct(Share $share) {
+ parent::__construct($share);
+ $this->activitySubject = self::CHANGE_REG_CONSTR;
+ }
+}
diff --git a/lib/Event/ShareCreateEvent.php b/lib/Event/ShareCreateEvent.php
new file mode 100644
index 00000000..f989c813
--- /dev/null
+++ b/lib/Event/ShareCreateEvent.php
@@ -0,0 +1,33 @@
+<?php
+/*
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Event;
+
+use OCA\Polls\Db\Share;
+
+class ShareCreateEvent extends ShareEvent {
+ public function __construct(Share $share) {
+ parent::__construct($share);
+ $this->activitySubject = self::ADD;
+ }
+}
diff --git a/lib/Event/ShareDeletedEvent.php b/lib/Event/ShareDeletedEvent.php
new file mode 100644
index 00000000..b88f32a1
--- /dev/null
+++ b/lib/Event/ShareDeletedEvent.php
@@ -0,0 +1,33 @@
+<?php
+/*
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Event;
+
+use OCA\Polls\Db\Share;
+
+class ShareDeletedEvent extends ShareEvent {
+ public function __construct(Share $share) {
+ parent::__construct($share);
+ $this->activitySubject = self::DELETE;
+ }
+}
diff --git a/lib/Event/ShareEvent.php b/lib/Event/ShareEvent.php
index 1644a740..4ba30336 100644
--- a/lib/Event/ShareEvent.php
+++ b/lib/Event/ShareEvent.php
@@ -23,35 +23,29 @@
namespace OCA\Polls\Event;
-use OCP\EventDispatcher\Event;
use OCA\Polls\Db\Share;
-class ShareEvent extends Event {
+abstract class ShareEvent extends BaseEvent {
+ public const ADD = 'share_add';
+ public const ADD_PUBLIC = 'share_add_public';
+ public const CHANGE_EMAIL = 'share_change_email';
+ public const CHANGE_TYPE = 'share_change_type';
+ public const CHANGE_REG_CONSTR = 'share_change_reg_const';
+ public const REGISTRATION = 'share_registration';
+ public const DELETE = 'share_delete';
/** @var Share */
private $share;
public function __construct(Share $share) {
- parent::__construct();
+ parent::__construct($share);
+ $this->activityObject = 'poll';
$this->share = $share;
+ $this->activitySubjectParams['shareType'] = $this->share->getRichObjectString();
+ $this->activitySubjectParams['sharee'] = $this->share->getUserObject()->getRichObjectString();
}
public function getShare(): Share {
return $this->share;
}
-
- public function getPollId(): int {
- return $this->share->getPollId();
- }
-
- public function getLogMsg(): string {
- return '';
- }
-
- public function getActor(): string {
- if (\OC::$server->getUserSession()->isLoggedIn()) {
- return \OC::$server->getUserSession()->getUser()->getUID();
- }
- return $this->share->getDisplayName();
- }
}
diff --git a/lib/Event/ShareRegistrationEvent.php b/lib/Event/ShareRegistrationEvent.php
new file mode 100644
index 00000000..021f3e69
--- /dev/null
+++ b/lib/Event/ShareRegistrationEvent.php
@@ -0,0 +1,33 @@
+<?php
+/*
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Event;
+
+use OCA\Polls\Db\Share;
+
+class ShareRegistrationEvent extends ShareEvent {
+ public function __construct(Share $share) {
+ parent::__construct($share);
+ $this->activitySubject = self::REGISTRATION;
+ }
+}
diff --git a/lib/Event/ShareTypeChangedEvent.php b/lib/Event/ShareTypeChangedEvent.php
new file mode 100644
index 00000000..5f7d68e4
--- /dev/null
+++ b/lib/Event/ShareTypeChangedEvent.php
@@ -0,0 +1,33 @@
+<?php
+/*
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Event;
+
+use OCA\Polls\Db\Share;
+
+class ShareTypeChangedEvent extends ShareEvent {
+ public function __construct(Share $share) {
+ parent::__construct($share);
+ $this->activitySubject = self::CHANGE_TYPE;
+ }
+}
diff --git a/lib/Event/VoteEvent.php b/lib/Event/VoteEvent.php
index b07c592f..61fedd11 100644
--- a/lib/Event/VoteEvent.php
+++ b/lib/Event/VoteEvent.php
@@ -23,43 +23,23 @@
namespace OCA\Polls\Event;
-use OCP\EventDispatcher\Event;
-use OCA\Polls\Db\Log;
use OCA\Polls\Db\Vote;
-class VoteEvent extends Event {
+abstract class VoteEvent extends BaseEvent {
+ public const SET = 'vote_set';
/** @var Vote */
private $vote;
- /** @var bool */
- private $log;
-
- public function __construct(Vote $vote, ?bool $log = true) {
- parent::__construct();
+ public function __construct(
+ Vote $vote
+ ) {
+ parent::__construct($vote);
+ $this->activityObject = 'poll';
$this->vote = $vote;
- $this->log = $log;
}
public function getVote(): Vote {
return $this->vote;
}
-
- public function getPollId(): int {
- return $this->vote->getPollId();
- }
-
- public function getLogMsg(): string {
- if ($this->log) {
- return Log::MSG_ID_SETVOTE;
- }
- return '';
- }
-
- public function getActor(): string {
- if (\OC::$server->getUserSession()->isLoggedIn()) {
- return \OC::$server->getUserSession()->getUser()->getUID();
- }
- return $this->vote->getUserId();
- }
}
diff --git a/lib/Event/VoteSetEvent.php b/lib/Event/VoteSetEvent.php
new file mode 100644
index 00000000..7290640c
--- /dev/null
+++ b/lib/Event/VoteSetEvent.php
@@ -0,0 +1,37 @@
+<?php
+/*
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Event;
+
+use OCA\Polls\Db\Vote;
+
+class VoteSetEvent extends VoteEvent {
+ public function __construct(
+ Vote $vote,
+ $log = true
+ ) {
+ parent::__construct($vote);
+ $this->log = $log;
+ $this->activitySubject = self::SET;
+ }
+}
diff --git a/lib/Exceptions/InvalidClassException.php b/lib/Exceptions/InvalidClassException.php
new file mode 100644
index 00000000..ff42864d
--- /dev/null
+++ b/lib/Exceptions/InvalidClassException.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * @copyright Copyright (c) 2020 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Exceptions;
+
+use OCP\AppFramework\Http;
+
+class InvalidClassException extends Exception {
+ public function __construct(string $e = 'Invalid class value') {
+ parent::__construct($e, Http::STATUS_CONFLICT);
+ }
+}
diff --git a/lib/Helper/Container.php b/lib/Helper/Container.php
new file mode 100644
index 00000000..d6da9697
--- /dev/null
+++ b/lib/Helper/Container.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Helper;
+
+use OCA\Polls\AppInfo\Application;
+use OCA\Polls\Db\Poll;
+use OCA\Polls\Db\PollMapper;
+use OCA\Polls\Db\Share;
+use OCA\Polls\Db\ShareMapper;
+use OCP\AppFramework\IAppContainer;
+
+abstract class Container {
+ public static function getContainer() : IAppContainer {
+ $app = \OC::$server->query(Application::class);
+ return $app->getContainer();
+ }
+
+ public static function queryClass(string $class) {
+ return self::getContainer()->query($class);
+ }
+
+ public static function queryPoll(int $pollId) : Poll {
+ return self::queryClass(PollMapper::class)->find($pollId);
+ }
+
+ public static function findShare(int $pollId, string $userId) : Share {
+ return self::queryClass(ShareMapper::class)
+ ->findByPollAndUser($pollId, $userId);
+ }
+
+ public static function isAppEnabled(string $app) : bool {
+ return \OC::$server->getAppManager()->isEnabledForUser($app);
+ }
+}
diff --git a/lib/Helper/Trace.php b/lib/Helper/Trace.php
index e6047e72..b249b9ee 100644
--- a/lib/Helper/Trace.php
+++ b/lib/Helper/Trace.php
@@ -21,7 +21,7 @@
*
*/
-namespace OCA\Polls\Model;
+namespace OCA\Polls\Helper;
class Trace implements \JsonSerializable {
diff --git a/lib/Listener/BaseListener.php b/lib/Listener/BaseListener.php
new file mode 100644
index 00000000..298cbc4f
--- /dev/null
+++ b/lib/Listener/BaseListener.php
@@ -0,0 +1,182 @@
+<?php
+/**
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Listener;
+
+use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
+use OCP\BackgroundJob\IJobList;
+use OCP\DB\Exception;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCA\Polls\Exceptions\InvalidClassException;
+use OCA\Polls\Service\ActivityService;
+use OCA\Polls\Service\LogService;
+use OCA\Polls\Service\NotificationService;
+use OCA\Polls\Service\WatchService;
+use OCA\Polls\Model\Settings\AppSettings;
+
+abstract class BaseListener implements IEventListener {
+
+ /** @var ActivityService */
+ protected $activityService;
+
+ /** @var AppSettings */
+ protected $appSettings;
+
+ /** @var IJobList */
+ protected $jobList;
+
+ /** @var LogService */
+ protected $logService;
+
+ /** @var NotificationService */
+ protected $notificationService;
+
+ /** @var WatchService */
+ protected $watchService;
+
+ /** @var Event */
+ protected $event;
+
+ /** @var array */
+ protected $watchTables = [];
+
+ public function __construct(
+ ActivityService $activityService,
+ AppSettings $appSettings,
+ IJobList $jobList,
+ LogService $logService,
+ NotificationService $notificationService,
+ WatchService $watchService
+ ) {
+ $this->appSettings = $appSettings;
+ $this->activityService = $activityService;
+ $this->jobList = $jobList;
+ $this->logService = $logService;
+ $this->notificationService = $notificationService;
+ $this->watchService = $watchService;
+ }
+
+ public function handle(Event $event) : void {
+ $this->event = $event;
+ try {
+ $this->checkClass();
+ $this->addLog();
+
+ // If addLog throws UniqueConstraintViolationException, avoid spamming in activities
+ if ($this->appSettings->getUseActivity()) {
+ $this->addActivity();
+ }
+ } catch (InvalidClassException $e) {
+ return;
+ } catch (UniqueConstraintViolationException $e) {
+ // Avoid spamming
+ // TODO: report some important events anyways
+ // deprecated NC22
+ // if ($this->appSettings->getUseActivity()) {
+ // $this->addActivity();
+ // }
+ } catch (Exception $e) {
+ if ($e->getReason() === Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
+ // Avoid spamming
+ // TODO: report some important events anyways
+ // since NC22
+ // if ($this->appSettings->getUseActivity()) {
+ // $this->addActivity();
+ // }
+ } else {
+ throw $e;
+ }
+ }
+
+ // add a cron job, if necessary (i.e. for removed users and groups)
+ $this->addCronJob();
+
+ // if a direct notification should be sent
+ $this->createNotification();
+
+ // update watch tables to inform clients about poll changes (watch polling)
+ $this->writeWatch();
+ }
+
+ /**
+ * Check the class of $event. This method has to be declared in every
+ * child class.
+ * @throws InvalidClassException
+ */
+ protected function checkClass() : void {
+ throw new InvalidClassException('child class must be checked in child class');
+ }
+
+ /**
+ * Default logging for email notifications.
+ * @throws UniqueConstraintViolationException
+ * @throws Exception
+ */
+ protected function addLog() : void {
+ if ($this->event->getLogId()) {
+ $this->logService->setLog(
+ $this->event->getPollId(),
+ $this->event->getLogId(),
+ $this->event->getActor()
+ );
+ }
+ }
+
+ /**
+ * No default, define in child class
+ */
+ protected function createNotification() : void {
+ return;
+ }
+
+ /**
+ * No default, define in child class
+ */
+ protected function addCronJob() : void {
+ return;
+ }
+
+ /**
+ * Default for activity notification.
+ */
+ protected function addActivity() : void {
+ if ($this->event->getActivityId()) {
+ $activityEvent = $this->activityService->createActivityEvent($this->event);
+ $this->activityService->publishActivityEvent($activityEvent, $this->event->getActor());
+ if ($this->event->getActor() !== $this->event->getPollOwner()) {
+ $this->activityService->publishActivityEvent($activityEvent, $this->event->getPollOwner());
+ }
+ }
+ }
+
+ /**
+ * Default for watch
+ * Tables to watch are defined in $this->watchTables
+ */
+ protected function writeWatch() : void {
+ foreach ($this->watchTables as $table) {
+ $this->watchService->writeUpdate($this->event->getPollId(), $table);
+ }
+ }
+}
diff --git a/lib/Listener/CommentListener.php b/lib/Listener/CommentListener.php
index 30663850..8ff67c5b 100644
--- a/lib/Listener/CommentListener.php
+++ b/lib/Listener/CommentListener.php
@@ -23,40 +23,22 @@
namespace OCA\Polls\Listener;
-use OCP\EventDispatcher\Event;
-use OCP\EventDispatcher\IEventListener;
-use OCA\Polls\Event\CommentEvent;
use OCA\Polls\Db\Watch;
-use OCA\Polls\Service\LogService;
-use OCA\Polls\Service\WatchService;
-
-class CommentListener implements IEventListener {
-
- /** @var LogService */
- private $logService;
-
- /** @var WatchService */
- private $watchService;
+use OCA\Polls\Event\CommentEvent;
+use OCA\Polls\Exceptions\InvalidClassException;
- /** @var string */
- private $table = Watch::OBJECT_COMMENTS;
+class CommentListener extends BaseListener {
- public function __construct(
- LogService $logService,
- WatchService $watchService
- ) {
- $this->logService = $logService;
- $this->watchService = $watchService;
- }
+ /** @var array */
+ protected $watchTables = [Watch::OBJECT_COMMENTS];
- public function handle(Event $event): void {
- if (!($event instanceof CommentEvent)) {
- return;
+ protected function checkClass() : void {
+ if (!($this->event instanceof CommentEvent)) {
+ throw new InvalidClassException;
}
+ }
- if ($event->getLogMsg()) {
- $this->logService->setLog($event->getPollId(), $event->getLogMsg(), $event->getActor());
- }
- $this->watchService->writeUpdate($event->getPollId(), $this->table);
+ protected function writeActivity() : void {
+ return;
}
}
diff --git a/lib/Listener/GroupDeletedListener.php b/lib/Listener/GroupDeletedListener.php
index 2edf2bfc..d053fe64 100644
--- a/lib/Listener/GroupDeletedListener.php
+++ b/lib/Listener/GroupDeletedListener.php
@@ -24,26 +24,17 @@
namespace OCA\Polls\Listener;
use OCA\Polls\Cron\GroupDeletedJob;
-use OCP\BackgroundJob\IJobList;
-use OCP\EventDispatcher\Event;
-use OCP\EventDispatcher\IEventListener;
use OCP\Group\Events\GroupDeletedEvent;
+use OCA\Polls\Exceptions\InvalidClassException;
-class GroupDeletedListener implements IEventListener {
-
- /** @var IJobList */
- private $jobList;
-
- public function __construct(IJobList $jobList) {
- $this->jobList = $jobList;
- }
-
- public function handle(Event $event): void {
- if (!($event instanceof GroupDeletedEvent)) {
- return;
+class GroupDeletedListener extends BaseListener {
+ protected function checkClass() : void {
+ if (!($this->event instanceof GroupDeletedEvent)) {
+ throw new InvalidClassException;
}
+ }
- // Set a Cron-Job to delete the Users Polls.
- $this->jobList->add(GroupDeletedJob::class, ['group' => $event->getGroup()->getGID()]);
+ protected function addCronJob() : void {
+ $this->jobList->add(GroupDeletedJob::class, ['group' => $this->event->getGroup()->getGID()]);
}
}
diff --git a/lib/Listener/OptionListener.php b/lib/Listener/OptionListener.php
index c6e2c084..b1e1c1bb 100644
--- a/lib/Listener/OptionListener.php
+++ b/lib/Listener/OptionListener.php
@@ -23,42 +23,19 @@
namespace OCA\Polls\Listener;
-use OCP\EventDispatcher\Event;
-use OCP\EventDispatcher\IEventListener;
use OCA\Polls\Event\OptionEvent;
use OCA\Polls\Db\Watch;
-use OCA\Polls\Service\LogService;
-use OCA\Polls\Service\WatchService;
+use OCA\Polls\Exceptions\InvalidClassException;
-class OptionListener implements IEventListener {
+class OptionListener extends BaseListener {
- /** @var LogService */
- private $logService;
+ // simulate vote change to force recalculating of votes
+ /** @var array */
+ protected $watchTables = [Watch::OBJECT_OPTIONS, Watch::OBJECT_VOTES];
- /** @var WatchService */
- private $watchService;
-
- /** @var string */
- private $table = Watch::OBJECT_OPTIONS;
-
- public function __construct(
- LogService $logService,
- WatchService $watchService
- ) {
- $this->logService = $logService;
- $this->watchService = $watchService;
- }
-
- public function handle(Event $event): void {
- if (!($event instanceof OptionEvent)) {
- return;
- }
-
- if ($event->getLogMsg()) {
- $this->logService->setLog($event->getPollId(), $event->getLogMsg(), $event->getActor());
+ protected function checkClass() : void {
+ if (!($this->event instanceof OptionEvent)) {
+ throw new InvalidClassException;
}
- $this->watchService->writeUpdate($event->getPollId(), $this->table);
- // If options are changed, simulate vote change to force recalculating of votes
- $this->watchService->writeUpdate($event->getPollId(), Watch::OBJECT_VOTES);
}
}
diff --git a/lib/Listener/PollListener.php b/lib/Listener/PollListener.php
index 60d75e1c..0aaf6e7c 100644
--- a/lib/Listener/PollListener.php
+++ b/lib/Listener/PollListener.php
@@ -23,54 +23,25 @@
namespace OCA\Polls\Listener;
-use OCP\EventDispatcher\Event;
-use OCP\EventDispatcher\IEventListener;
use OCA\Polls\Event\PollEvent;
use OCA\Polls\Db\Watch;
-use OCA\Polls\Service\LogService;
-use OCA\Polls\Service\WatchService;
-use OCA\Polls\Service\NotificationService;
+use OCA\Polls\Exceptions\InvalidClassException;
-class PollListener implements IEventListener {
+class PollListener extends BaseListener {
- /** @var LogService */
- private $logService;
+ // Simulate vote and option change due to possible configuration changes
+ /** @var array */
+ protected $watchTables = [Watch::OBJECT_POLLS, Watch::OBJECT_VOTES, Watch::OBJECT_OPTIONS];
- /** @var NotificationService */
- private $notificationService;
-
- /** @var WatchService */
- private $watchService;
-
- /** @var string */
- private $table = Watch::OBJECT_POLLS;
-
- public function __construct(
- LogService $logService,
- NotificationService $notificationService,
- WatchService $watchService
- ) {
- $this->logService = $logService;
- $this->notificationService = $notificationService;
- $this->watchService = $watchService;
- }
-
- public function handle(Event $event): void {
- if (!($event instanceof PollEvent)) {
- return;
+ protected function checkClass() : void {
+ if (!($this->event instanceof PollEvent)) {
+ throw new InvalidClassException;
}
+ }
- $this->watchService->writeUpdate($event->getPollId(), $this->table);
- // If the poll configuration is changed, simulate vote change
- $this->watchService->writeUpdate($event->getPollId(), Watch::OBJECT_VOTES);
- // If the poll configuration is changed, simulate option change
- $this->watchService->writeUpdate($event->getPollId(), Watch::OBJECT_OPTIONS);
-
- if ($event->getLogMsg()) {
- $this->logService->setLog($event->getPollId(), $event->getLogMsg(), $event->getActor());
- }
- if (!empty($event->getNotification())) {
- $this->notificationService->createNotification($event->getNotification());
+ protected function createNotification() : void {
+ if (!empty($this->event->getNotification())) {
+ $this->notificationService->createNotification($this->event->getNotification());
}
}
}
diff --git a/lib/Listener/ShareListener.php b/lib/Listener/ShareListener.php
index c76b6a12..3e4562c0 100644
--- a/lib/Listener/ShareListener.php
+++ b/lib/Listener/ShareListener.php
@@ -23,42 +23,18 @@
namespace OCA\Polls\Listener;
-use OCP\EventDispatcher\Event;
-use OCP\EventDispatcher\IEventListener;
-use OCA\Polls\Event\ShareEvent;
use OCA\Polls\Db\Watch;
-use OCA\Polls\Service\LogService;
-use OCA\Polls\Service\WatchService;
-
-class ShareListener implements IEventListener {
-
- /** @var LogService */
- private $logService;
-
- /** @var WatchService */
- private $watchService;
-
- /** @var string */
- private $table = Watch::OBJECT_SHARES;
+use OCA\Polls\Event\ShareEvent;
+use OCA\Polls\Exceptions\InvalidClassException;
- public function __construct(
- LogService $logService,
- WatchService $watchService
- ) {
- $this->logService = $logService;
- $this->watchService = $watchService;
- }
+class ShareListener extends BaseListener {
- public function handle(Event $event): void {
- if (!($event instanceof ShareEvent)) {
- return;
- }
+ /** @var array */
+ protected $watchTables = [Watch::OBJECT_SHARES, Watch::OBJECT_POLLS];
- if ($event->getLogMsg()) {
- $this->logService->setLog($event->getPollId(), $event->getLogMsg(), $event->getActor());
+ protected function checkClass() : void {
+ if (!($this->event instanceof ShareEvent)) {
+ throw new InvalidClassException;
}
- $this->watchService->writeUpdate($event->getPollId(), $this->table);
- // report polls also, to update polls list based changed shares list
- $this->watchService->writeUpdate($event->getPollId(), 'polls');
}
}
diff --git a/lib/Listener/UserDeletedListener.php b/lib/Listener/UserDeletedListener.php
index 7e8317be..5a7caadc 100644
--- a/lib/Listener/UserDeletedListener.php
+++ b/lib/Listener/UserDeletedListener.php
@@ -23,29 +23,18 @@
namespace OCA\Polls\Listener;
-use OCP\BackgroundJob\IJobList;
-use OCP\EventDispatcher\Event;
-use OCP\EventDispatcher\IEventListener;
use OCP\User\Events\UserDeletedEvent;
use OCA\Polls\Cron\UserDeletedJob;
+use OCA\Polls\Exceptions\InvalidClassException;
-class UserDeletedListener implements IEventListener {
-
- /** @var IJobList */
- private $jobList;
-
- public function __construct(
- IJobList $jobList
- ) {
- $this->jobList = $jobList;
- }
-
- public function handle(Event $event): void {
- if (!($event instanceof UserDeletedEvent)) {
- return;
+class UserDeletedListener extends BaseListener {
+ protected function checkClass() : void {
+ if (!($this->event instanceof UserDeletedEvent)) {
+ throw new InvalidClassException;
}
+ }
- // Set a Cron-Job to delete the Users Polls.
- $this->jobList->add(UserDeletedJob::class, ['owner' => $event->getUser()->getUID()]);
+ protected function addCronJob() : void {
+ $this->jobList->add(UserDeletedJob::class, ['owner' => $this->event->getUser()->getUID()]);
}
}
diff --git a/lib/Listener/VoteListener.php b/lib/Listener/VoteListener.php
index d8095bed..43c20b77 100644
--- a/lib/Listener/VoteListener.php
+++ b/lib/Listener/VoteListener.php
@@ -23,42 +23,18 @@
namespace OCA\Polls\Listener;
-use OCP\EventDispatcher\Event;
-use OCP\EventDispatcher\IEventListener;
use OCA\Polls\Event\VoteEvent;
use OCA\Polls\Db\Watch;
-use OCA\Polls\Service\LogService;
-use OCA\Polls\Service\WatchService;
+use OCA\Polls\Exceptions\InvalidClassException;
-class VoteListener implements IEventListener {
+class VoteListener extends BaseListener {
- /** @var LogService */
- private $logService;
+ /** @var array */
+ protected $watchTables = [Watch::OBJECT_VOTES, Watch::OBJECT_OPTIONS];
- /** @var WatchService */
- private $watchService;
-
- /** @var string */
- private $table = Watch::OBJECT_VOTES;
-
- public function __construct(
- LogService $logService,
- WatchService $watchService
- ) {
- $this->logService = $logService;
- $this->watchService = $watchService;
- }
-
- public function handle(Event $event): void {
- if (!($event instanceof VoteEvent)) {
- return;
- }
-
- if ($event->getLogMsg()) {
- $this->logService->setLog($event->getPollId(), $event->getLogMsg(), $event->getActor());
+ protected function checkClass() : void {
+ if (!($this->event instanceof VoteEvent)) {
+ throw new InvalidClassException;
}
- $this->watchService->writeUpdate($event->getPollId(), $this->table);
- // If a vote is changed, simulate option change to force recalculating of votes
- $this->watchService->writeUpdate($event->getPollId(), Watch::OBJECT_OPTIONS);
}
}
diff --git a/lib/Model/Mail/InvitationMail.php b/lib/Model/Mail/InvitationMail.php
index 2e1f4065..7aee3448 100644
--- a/lib/Model/Mail/InvitationMail.php
+++ b/lib/Model/Mail/InvitationMail.php
@@ -34,52 +34,55 @@ class InvitationMail extends MailBase {
protected $share;
public function __construct(
- string $userId,
+ string $recipientId,
Share $share
) {
- parent::__construct(
- $userId,
- $share->getPollId()
- );
+ parent::__construct($recipientId, $share->getPollId());
$this->share = $share;
$this->buildEmailTemplate();
}
public function buildEmailTemplate() : void {
+ $this->emailTemplate->setSubject($this->trans->t('Poll invitation "%s"', $this->poll->getTitle()));
+ $this->emailTemplate->addHeader();
+ $this->emailTemplate->addHeading($this->trans->t('Poll invitation "%s"', $this->poll->getTitle()), false);
+ $this->emailTemplate->addBodyText($this->getMainBody());
+ // TODO: Check second paramater
+ $this->emailTemplate->addBodyText($this->getRichDescription(), 'Hey');
+
+ $this->emailTemplate->addBodyButton(
+ $this->trans->t('Go to poll'),
+ $this->url
+ );
+ $this->emailTemplate->addBodyText($this->trans->t('This link gives you personal access to the poll named above. Press the button above or copy the following link and add it in your browser\'s location bar:'));
+ $this->emailTemplate->addBodyText($this->url);
+ $this->emailTemplate->addBodyText($this->trans->t('Do not share this link with other people, because it is connected to your votes.'));
+ $this->emailTemplate->addFooter($this->trans->t('This email is sent to you, because you are invited to vote in this poll by the poll owner. At least your name or your email address is recorded in this poll. If you want to get removed from this poll, contact the site administrator or the initiator of this poll, where the mail is sent from.'));
+ }
+
+ protected function getMainBody() : string {
if ($this->share->getType() === Share::TYPE_GROUP) {
- $mainBody = str_replace(
+ return str_replace(
['{owner}', '{title}', '{group_name}'],
[$this->owner->getDisplayName(), $this->poll->getTitle(), $this->share->getDisplayName()],
$this->trans->t('{owner} invited you to take part in the poll "{title}" as a member of the group {group_name}')
);
} else {
- $mainBody = str_replace(
+ return str_replace(
['{owner}', '{title}'],
[$this->owner->getDisplayName(), $this->poll->getTitle()],
$this->trans->t('{owner} invited you to take part in the poll "{title}"')
);
}
- $this->emailTemplate->setSubject($this->trans->t('Poll invitation "%s"', $this->poll->getTitle()));
- $this->emailTemplate->addHeader();
- $this->emailTemplate->addHeading($this->trans->t('Poll invitation "%s"', $this->poll->getTitle()), false);
- $this->emailTemplate->addBodyText($mainBody);
+ }
+ protected function getRichDescription() : string {
$config = [
'html_input' => 'strip',
'allow_unsafe_links' => false,
];
$converter = new CommonMarkConverter($config);
-
- $this->emailTemplate->addBodyText($converter->convertToHtml($this->poll->getDescription()), 'Hey');
-
- $this->emailTemplate->addBodyButton(
- $this->trans->t('Go to poll'),
- $this->url
- );
- $this->emailTemplate->addBodyText($this->trans->t('This link gives you personal access to the poll named above. Press the button above or copy the following link and add it in your browser\'s location bar:'));
- $this->emailTemplate->addBodyText($this->url);
- $this->emailTemplate->addBodyText($this->trans->t('Do not share this link with other people, because it is connected to your votes.'));
- $this->emailTemplate->addFooter($this->trans->t('This email is sent to you, because you are invited to vote in this poll by the poll owner. At least your name or your email address is recorded in this poll. If you want to get removed from this poll, contact the site administrator or the initiator of this poll, where the mail is sent from.'));
+ return $converter->convertToHtml($this->poll->getDescription());
}
}
diff --git a/lib/Model/Mail/MailBase.php b/lib/Model/Mail/MailBase.php
index 48b614e1..94596378 100644
--- a/lib/Model/Mail/MailBase.php
+++ b/lib/Model/Mail/MailBase.php
@@ -24,13 +24,10 @@
namespace OCA\Polls\Model\Mail;
-use OCA\Polls\AppInfo\Application;
use OCA\Polls\Model\UserGroup\UserBase;
use OCA\Polls\Model\UserGroup\User;
use OCA\Polls\Db\Poll;
-use OCA\Polls\Db\PollMapper;
-use OCA\Polls\Db\ShareMapper;
-use OCP\AppFramework\IAppContainer;
+use OCA\Polls\Helper\Container;
use OCP\IL10N;
use OCP\IUser;
use OCA\Polls\Exceptions\InvalidEmailAddress;
@@ -69,23 +66,26 @@ class MailBase {
protected $owner;
public function __construct(
- string $userId,
+ string $recipientId,
int $pollId,
string $url = null
) {
$this->poll = $this->getPoll($pollId);
- $this->recipient = $this->getUser($userId);
-
+ $this->recipient = $this->getUser($recipientId);
$this->url = $url ?? $this->poll->getVoteUrl();
+ $this->initializeClass();
+ }
+
+ protected function initializeClass(): void {
$this->owner = $this->poll->getOwnerUserObject();
if ($this->recipient->getIsNoUser()) {
$this->url = $this->getShareURL();
}
- $this->mailer = self::getContainer()->query(IMailer::class);
- $this->transFactory = self::getContainer()->query(IFactory::class);
+ $this->mailer = Container::queryClass(IMailer::class);
+ $this->transFactory = Container::queryClass(IFactory::class);
$this->trans = $this->transFactory->get(
'polls',
$this->recipient->getLanguage()
@@ -108,10 +108,7 @@ class MailBase {
}
public function send(): void {
- if (!$this->recipient->getEmailAddress()
- || !filter_var($this->recipient->getEmailAddress(), FILTER_VALIDATE_EMAIL)) {
- throw new InvalidEmailAddress('Invalid email address (' . $this->recipient->getEmailAddress() . ')');
- }
+ $this->validateEmailAddress();
try {
$message = $this->mailer->createMessage();
@@ -131,27 +128,21 @@ class MailBase {
return new User($userId);
}
// return UserBaseChild from share
- return $this->getContainer()
- ->query(ShareMapper::class)
- ->findByPollAndUser($this->poll->getId(), $userId)
- ->getUserObject();
+ return Container::findShare($this->poll->getId(), $userId)->getUserObject();
}
- private function getShareURL() : string {
- return $this->getContainer()
- ->query(ShareMapper::class)
- ->findByPollAndUser($this->poll->getId(), $this->recipient->getId())
- ->getURL();
+ protected function getShareURL() : string {
+ return Container::findShare($this->poll->getId(), $this->recipient->getId())->getURL();
}
protected function getPoll(int $pollId) : Poll {
- return $this->getContainer()
- ->query(PollMapper::class)
- ->find($pollId);
+ return Container::queryPoll($pollId);
}
- protected static function getContainer() : IAppContainer {
- $app = \OC::$server->query(Application::class);
- return $app->getContainer();
+ protected function validateEmailAddress(): void {
+ if (!$this->recipient->getEmailAddress()
+ || !filter_var($this->recipient->getEmailAddress(), FILTER_VALIDATE_EMAIL)) {
+ throw new InvalidEmailAddress('Invalid email address (' . $this->recipient->getEmailAddress() . ')');
+ }
}
}
diff --git a/lib/Model/Mail/NotificationMail.php b/lib/Model/Mail/NotificationMail.php
index 2c9e1be3..9f179dc5 100644
--- a/lib/Model/Mail/NotificationMail.php
+++ b/lib/Model/Mail/NotificationMail.php
@@ -26,6 +26,9 @@ namespace OCA\Polls\Model\Mail;
use OCA\Polls\Db\Log;
use OCA\Polls\Db\Subscription;
+use OCA\Polls\Event\PollEvent;
+use OCA\Polls\Event\OptionEvent;
+use OCA\Polls\Event\VoteEvent;
class NotificationMail extends MailBase {
private const TEMPLATE_CLASS = 'polls.Notification';
@@ -39,10 +42,7 @@ class NotificationMail extends MailBase {
public function __construct(
Subscription $subscription
) {
- parent::__construct(
- $subscription->getUserId(),
- $subscription->getPollId(),
- );
+ parent::__construct($subscription->getUserId(), $subscription->getPollId());
$this->subscription = $subscription;
$this->buildEmailTemplate();
}
@@ -72,7 +72,7 @@ class NotificationMail extends MailBase {
$this->emailTemplate->addFooter($this->trans->t('This email is sent to you, because you subscribed to notifications of this poll. To opt out, visit the poll and remove your subscription.'));
}
- private function getComposedLogString(Log $logItem, string $displayName): string {
+ protected function getComposedLogString(Log $logItem, string $displayName): string {
$logStrings = [
Log::MSG_ID_SETVOTE => $this->trans->t('%s has voted.', [$displayName]),
Log::MSG_ID_UPDATEPOLL => $this->trans->t('Updated poll configuration. Please check your votes.'),
@@ -85,6 +85,18 @@ class NotificationMail extends MailBase {
Log::MSG_ID_DELETEOPTION => $this->trans->t('A voting option has been removed.'),
Log::MSG_ID_OWNERCHANGE => $this->trans->t('The poll owner has been changed.'),
Log::MSG_ID_ADDPOLL => $this->trans->t('%s created the poll.', [$displayName]),
+ PollEvent::ADD => $this->trans->t('%s created the poll.', [$displayName]),
+ PollEvent::UPDATE => $this->trans->t('Updated poll configuration. Please check your votes.'),
+ PollEvent::DELETE => $this->trans->t('The poll has been deleted.'),
+ PollEvent::RESTORE => $this->trans->t('The poll has been restored.'),
+ PollEvent::EXPIRE => $this->trans->t('The poll has been closed.'),
+ PollEvent::OWNER_CHANGE => $this->trans->t('The poll owner has been changed.'),
+ OptionEvent::ADD => $this->trans->t('A voting option has been added.'),
+ OptionEvent::UPDATE => $this->trans->t('A voting option has been changed.'),
+ OptionEvent::CONFIRM => $this->trans->t('A voting option has been confirmed.'),
+ OptionEvent::UNCONFIRM => $this->trans->t('A voting option has been unconfirmed.'),
+ OptionEvent::DELETE => $this->trans->t('A voting option has been removed.'),
+ VoteEvent::SET => $this->trans->t('%s has voted.', [$displayName]),
];
return $logStrings[$logItem->getMessageId()] ?? $logItem->getMessageId() . " (" . $displayName . ")";
diff --git a/lib/Model/Mail/ReminderMail.php b/lib/Model/Mail/ReminderMail.php
index 15c3eb2a..30b5ac62 100644
--- a/lib/Model/Mail/ReminderMail.php
+++ b/lib/Model/Mail/ReminderMail.php
@@ -45,12 +45,12 @@ class ReminderMail extends MailBase {
protected $timeToDeadline;
public function __construct(
- string $userId,
+ string $recipientId,
int $pollId,
int $deadline,
int $timeToDeadline
) {
- parent::__construct($userId, $pollId);
+ parent::__construct($recipientId, $pollId);
$this->deadline = $deadline;
$this->timeToDeadline = $timeToDeadline;
$this->buildEmailTemplate();
diff --git a/lib/Model/Settings/AppSettings.php b/lib/Model/Settings/AppSettings.php
index 57e1d808..85989fee 100644
--- a/lib/Model/Settings/AppSettings.php
+++ b/lib/Model/Settings/AppSettings.php
@@ -24,12 +24,11 @@
namespace OCA\Polls\Model\Settings;
use JsonSerializable;
+use OCA\Polls\Model\UserGroup\Group;
+use OCA\Polls\Helper\Container;
use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IUserSession;
-use OCP\AppFramework\IAppContainer;
-use OCA\Polls\AppInfo\Application;
-use OCA\Polls\Model\UserGroup\Group;
class AppSettings implements JsonSerializable {
private const APP_NAME = 'polls';
@@ -47,12 +46,12 @@ class AppSettings implements JsonSerializable {
private $userId = '';
public function __construct() {
- $this->config = self::getContainer()->query(IConfig::class);
- $this->session = self::getContainer()->query(IUserSession::class);
+ $this->config = Container::queryClass(IConfig::class);
+ $this->session = Container::queryClass(IUserSession::class);
if ($this->session->isLoggedIn()) {
- $this->userId = self::getContainer()->query(IUserSession::class)->getUser()->getUId();
+ $this->userId = Container::queryClass(IUserSession::class)->getUser()->getUId();
}
- $this->groupManager = self::getContainer()->query(IGroupManager::class);
+ $this->groupManager = Container::queryClass(IGroupManager::class);
}
// Getters
@@ -96,6 +95,10 @@ class AppSettings implements JsonSerializable {
return $this->config->getAppValue(self::APP_NAME, 'updateType') ?: 'longPolling';
}
+ public function getUseActivity(): bool {
+ return $this->stringToBool($this->config->getAppValue(self::APP_NAME, 'useActivity'), false);
+ }
+
// Checks
public function getCreationAllowed(): bool {
if ($this->session->isLoggedIn()) {
@@ -159,6 +162,10 @@ class AppSettings implements JsonSerializable {
$this->config->setAppValue(self::APP_NAME, 'updateType', $value);
}
+ public function setUseActivity(bool $value): void {
+ $this->config->setAppValue(self::APP_NAME, 'useActivity', $this->boolToString($value));
+ }
+
public function jsonSerialize() {
// convert group ids to group objects
$publicSharesGroups = [];
@@ -188,6 +195,7 @@ class AppSettings implements JsonSerializable {
'autoArchive' => $this->getAutoArchive(),
'autoArchiveOffset' => $this->getAutoArchiveOffset(),
'updateType' => $this->getUpdateType(),
+ 'useActivity' => $this->getUseActivity(),
];
}
@@ -231,9 +239,4 @@ class AppSettings implements JsonSerializable {
}
return 'no';
}
-
- protected static function getContainer() : IAppContainer {
- $app = \OC::$server->query(Application::class);
- return $app->getContainer();
- }
}
diff --git a/lib/Model/UserGroup/Circle.php b/lib/Model/UserGroup/Circle.php
index b3426407..b7dedb50 100644
--- a/lib/Model/UserGroup/Circle.php
+++ b/lib/Model/UserGroup/Circle.php
@@ -23,10 +23,10 @@
namespace OCA\Polls\Model\UserGroup;
-use OCP\App\IAppManager;
use OCA\Circles\Api\v1\Circles;
use OCA\Circles\Model\Circle as CirclesCircle;
use OCA\Polls\Exceptions\CirclesNotEnabledException;
+use OCA\Polls\Helper\Container;
class Circle extends UserBase {
public const TYPE = 'circle';
@@ -44,19 +44,33 @@ class Circle extends UserBase {
$this->circle = Circles::detailsCircle($id);
$this->displayName = $this->circle->getName();
$this->description = \OC::$server->getL10N('polls')->t('Circle');
+ $this->richObjectType = 'circle';
} else {
throw new CirclesNotEnabledException();
}
}
- public static function isEnabled(): bool {
- return self::getContainer()->query(IAppManager::class)->isEnabledForUser('circles');
+ public static function isEnabled() : bool {
+ return Container::isAppEnabled('circles');
+ }
+
+ public function getRichObjectString() : array {
+ return [
+ 'type' => $this->richObjectType,
+ 'id' => $this->getId(),
+ 'name' => $this->getDisplayName(),
+ 'link' => $this->circle->getUrl(),
+ ];
+ }
+
+ public function getCircleUrl(): string {
+ return 'lala';
}
/**
* @return Circle[]
*/
- public static function search(string $query = '', array $skip = []): array {
+ public static function search(string $query = '', array $skip = []) : array {
$circles = [];
if (self::isEnabled()) {
foreach (Circles::listCircles(CirclesCircle::CIRCLES_ALL, $query) as $circle) {
diff --git a/lib/Model/UserGroup/Contact.php b/lib/Model/UserGroup/Contact.php
index 92df8c41..728e14e5 100644
--- a/lib/Model/UserGroup/Contact.php
+++ b/lib/Model/UserGroup/Contact.php
@@ -23,10 +23,10 @@
namespace OCA\Polls\Model\UserGroup;
-use OCP\App\IAppManager;
-use OCP\Contacts\IManager as IContactsManager;
use OCA\Polls\Exceptions\MultipleContactsFound;
use OCA\Polls\Exceptions\ContactsNotEnabledExceptions;
+use OCA\Polls\Helper\Container;
+use OCP\Contacts\IManager as IContactsManager;
class Contact extends UserBase {
public const TYPE = 'contact';
@@ -42,6 +42,7 @@ class Contact extends UserBase {
if (self::isEnabled()) {
$this->icon = self::ICON;
$this->getContact();
+ $this->richObjectType = 'addressbook-contact';
} else {
throw new ContactsNotEnabledExceptions();
}
@@ -107,7 +108,7 @@ class Contact extends UserBase {
}
public static function isEnabled(): bool {
- return self::getContainer()->query(IAppManager::class)->isEnabledForUser('contacts');
+ return Container::isAppEnabled('contacts');
}
/**
@@ -120,7 +121,7 @@ class Contact extends UserBase {
$contacts = [];
if (self::isEnabled()) {
- foreach (self::getContainer()->query(IContactsManager::class)->search($query, $queryRange) as $contact) {
+ foreach (Container::queryClass(IContactsManager::class)->search($query, $queryRange) as $contact) {
if (!array_key_exists('isLocalSystemBook', $contact) && array_key_exists('EMAIL', $contact)) {
$contacts[] = $contact;
}
diff --git a/lib/Model/UserGroup/ContactGroup.php b/lib/Model/UserGroup/ContactGroup.php
index 52790cd9..8ab50c90 100644
--- a/lib/Model/UserGroup/ContactGroup.php
+++ b/lib/Model/UserGroup/ContactGroup.php
@@ -23,9 +23,9 @@
namespace OCA\Polls\Model\UserGroup;
-use OCP\App\IAppManager;
-use OCP\Contacts\IManager as IContactsManager;
+use OCA\Polls\Helper\Container;
use OCA\Polls\Exceptions\ContactsNotEnabledExceptions;
+use OCP\Contacts\IManager as IContactsManager;
class ContactGroup extends UserBase {
public const TYPE = 'contactGroup';
@@ -38,6 +38,7 @@ class ContactGroup extends UserBase {
if (self::isEnabled()) {
$this->icon = self::ICON;
$this->description = \OC::$server->getL10N('polls')->t('Contact group');
+ $this->richObjectType = 'addressbook-contact';
} else {
throw new ContactsNotEnabledExceptions();
}
@@ -60,7 +61,7 @@ class ContactGroup extends UserBase {
public function getMembers(): array {
$contacts = [];
- foreach (self::getContainer()->query(IContactsManager::class)->search($this->id, ['CATEGORIES']) as $contact) {
+ foreach (Container::queryClass(IContactsManager::class)->search($this->id, ['CATEGORIES']) as $contact) {
if (array_key_exists('EMAIL', $contact)) {
$contacts[] = new Contact($contact['UID']);
}
@@ -70,7 +71,7 @@ class ContactGroup extends UserBase {
}
public static function isEnabled(): bool {
- return self::getContainer()->query(IAppManager::class)->isEnabledForUser('contacts');
+ return Container::isAppEnabled('contacts');
}
/**
@@ -80,7 +81,7 @@ class ContactGroup extends UserBase {
$contactGroups = [];
$categories = [];
if (self::isEnabled() && $query) {
- foreach (self::getContainer()->query(IContactsManager::class)->search($query, ['CATEGORIES']) as $contact) {
+ foreach (Container::queryClass(IContactsManager::class)->search($query, ['CATEGORIES']) as $contact) {
// get all groups from the found contact and explode to array
foreach (explode(',', $contact['CATEGORIES']) as $category) {
diff --git a/lib/Model/UserGroup/Email.php b/lib/Model/UserGroup/Email.php
index f5f7caef..671b40a7 100644
--- a/lib/Model/UserGroup/Email.php
+++ b/lib/Model/UserGroup/Email.php
@@ -37,6 +37,7 @@ class Email extends UserBase {
$this->icon = self::ICON;
$this->emailAddress = $id;
$this->displayName = $displayName ? $displayName : $this->displayName;
+ $this->richObjectType = 'email';
}
public function getDisplayName(): string {
diff --git a/lib/Model/UserGroup/GenericUser.php b/lib/Model/UserGroup/GenericUser.php
index b3bfbb15..4d57a2c5 100644
--- a/lib/Model/UserGroup/GenericUser.php
+++ b/lib/Model/UserGroup/GenericUser.php
@@ -38,6 +38,7 @@ class GenericUser extends UserBase {
parent::__construct($id, $type);
$this->displayName = $displayName;
$this->emailAddress = $emailAddress;
+ $this->richObjectType = 'guest';
if ($type === UserBase::TYPE_PUBLIC) {
$this->icon = self::ICON_PUBLIC;
diff --git a/lib/Model/UserGroup/Group.php b/lib/Model/UserGroup/Group.php
index 34f735ae..c1a9702a 100644
--- a/lib/Model/UserGroup/Group.php
+++ b/lib/Model/UserGroup/Group.php
@@ -23,6 +23,7 @@
namespace OCA\Polls\Model\UserGroup;
+use OCA\Polls\Helper\Container;
use OCP\IGroupManager;
use OCP\IGroup;
@@ -38,9 +39,10 @@ class Group extends UserBase {
) {
parent::__construct($id, self::TYPE);
$this->icon = self::ICON;
- $this->group = self::getContainer()->query(IGroupManager::class)->get($this->id);
+ $this->group = Container::queryClass(IGroupManager::class)->get($this->id);
$this->description = \OC::$server->getL10N('polls')->t('Group');
$this->displayName = $this->group->getDisplayName();
+ $this->richObjectType = 'user-group';
}
/**
@@ -49,7 +51,7 @@ class Group extends UserBase {
public function getMembers(): array {
$members = [];
- foreach (array_keys(self::getContainer()->query(IGroupManager::class)->displayNamesInGroup($this->id)) as $member) {
+ foreach (array_keys(Container::queryClass(IGroupManager::class)->displayNamesInGroup($this->id)) as $member) {
$newMember = new User($member);
if ($newMember->IsEnabled()) {
@@ -68,7 +70,7 @@ class Group extends UserBase {
public static function search(string $query = '', array $skip = []): array {
$groups = [];
- foreach (self::getContainer()->query(IGroupManager::class)->search($query) as $group) {
+ foreach (Container::queryClass(IGroupManager::class)->search($query) as $group) {
if (!in_array($group->getGID(), $skip)) {
$groups[] = new self($group->getGID());
}
diff --git a/lib/Model/UserGroup/User.php b/lib/Model/UserGroup/User.php
index 279411ba..f33bd4a0 100644
--- a/lib/Model/UserGroup/User.php
+++ b/lib/Model/UserGroup/User.php
@@ -24,6 +24,7 @@
namespace OCA\Polls\Model\UserGroup;
use DateTimeZone;
+use OCA\Polls\Helper\Container;
use OCP\IUserManager;
use OCP\IUser;
@@ -43,7 +44,7 @@ class User extends UserBase {
$this->isNoUser = false;
$this->description = \OC::$server->getL10N('polls')->t('User');
- $this->user = self::getContainer()->query(IUserManager::class)->get($this->id);
+ $this->user = Container::queryClass(IUserManager::class)->get($this->id);
$this->displayName = $this->user->getDisplayName();
$this->emailAddress = $this->user->getEmailAddress();
$this->language = \OC::$server->getConfig()->getUserValue($this->id, 'core', 'lang');
@@ -71,7 +72,7 @@ class User extends UserBase {
public static function search(string $query = '', array $skip = []): array {
$users = [];
- foreach (self::getContainer()->query(IUserManager::class)->search($query) as $user) {
+ foreach (Container::queryClass(IUserManager::class)->search($query) as $user) {
if (!in_array($user->getUID(), $skip)) {
$users[] = new self($user->getUID());
}
diff --git a/lib/Model/UserGroup/UserBase.php b/lib/Model/UserGroup/UserBase.php
index 50cdf669..4828a2f6 100644
--- a/lib/Model/UserGroup/UserBase.php
+++ b/lib/Model/UserGroup/UserBase.php
@@ -27,10 +27,9 @@ use OCA\Polls\Exceptions\InvalidShareTypeException;
use DateTimeZone;
use OCP\IL10N;
-use OCP\AppFramework\IAppContainer;
+use OCA\Polls\Helper\Container;
use OCP\Collaboration\Collaborators\ISearch;
use OCP\Share\IShare;
-use OCA\Polls\AppInfo\Application;
use OCP\IDateTimeZone;
class UserBase implements \JsonSerializable {
@@ -45,6 +44,9 @@ class UserBase implements \JsonSerializable {
public const TYPE_USER = User::TYPE;
public const TYPE_ADMIN = Admin::TYPE;
+ /** @var string */
+ protected $richObjectType = 'user';
+
/** @var IL10N */
private $l10n;
@@ -100,7 +102,7 @@ class UserBase implements \JsonSerializable {
$this->locale = $locale;
$this->icon = 'icon-share';
$this->l10n = \OC::$server->getL10N('polls');
- $this->timezone = $this->getContainer()->query(IDateTimeZone::class);
+ $this->timezone = Container::queryClass(IDateTimeZone::class);
}
public function getId(): string {
@@ -202,6 +204,14 @@ class UserBase implements \JsonSerializable {
return $this->organisation;
}
+ public function getRichObjectString() : array {
+ return [
+ 'type' => $this->richObjectType,
+ 'id' => $this->getId(),
+ 'name' => $this->getDisplayName(),
+ ];
+ }
+
/**
* search all possible sharees - use ISearch to respect autocomplete restrictions
*/
@@ -215,7 +225,7 @@ class UserBase implements \JsonSerializable {
$types[] = IShare::TYPE_CIRCLE;
}
- [$result, $more] = self::getContainer()->query(ISearch::class)->search($query, $types, false, 200, 0);
+ [$result, $more] = Container::queryClass(ISearch::class)->search($query, $types, false, 200, 0);
foreach (($result['users'] ?? []) as $item) {
$items[] = new User($item['value']['shareWith']);
@@ -257,12 +267,6 @@ class UserBase implements \JsonSerializable {
return [$this];
}
- protected static function getContainer() : IAppContainer {
- $app = \OC::$server->query(Application::class);
-
- return $app->getContainer();
- }
-
/**
* @return Circle|Contact|ContactGroup|Email|GenericUser|Group|User|Admin
*/
diff --git a/lib/Provider/ActivityProvider.php b/lib/Provider/ActivityProvider.php
new file mode 100644
index 00000000..e81f1e75
--- /dev/null
+++ b/lib/Provider/ActivityProvider.php
@@ -0,0 +1,138 @@
+<?php
+/**
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Provider;
+
+use OCP\Activity\IProvider;
+use OCP\IL10N;
+use OCP\L10N\IFactory;
+use OCP\IURLGenerator;
+use OCP\IUser;
+use OCP\IUserManager;
+use OCP\Activity\IManager as ActivityManager;
+use OCP\Activity\IEventMerger;
+use OCP\Activity\IEvent;
+use OCA\Polls\Service\ActivityService;
+use OCA\Polls\Db\ShareMapper;
+
+class ActivityProvider implements IProvider {
+ /** @var IFactory */
+ protected $transFactory;
+
+ /** @var IL10N */
+ protected $trans;
+
+ /** @var ActivityManager */
+ protected $activityManager;
+
+ /** @var ActivityService */
+ protected $activityService;
+
+ /** @var IEventMerger */
+ protected $eventMerger;
+
+ /** @var IUserManager */
+ private $userManager;
+
+ /** @var IURLGenerator */
+ protected $urlGenerator;
+
+ /** @var ShareMapper */
+ protected $shareMapper;
+
+ /**
+ * @param ActivityManager $activityManager
+ * @param ActivityService $activityService
+ * @param IEventMerger $eventMerger
+ * @param IFactory $transFactory
+ * @param IUserManager $userManager
+ * @param IURLGenerator $urlGenerator
+ * @param ShareMapper $shareMapper
+ */
+ public function __construct(
+ ActivityManager $activityManager,
+ ActivityService $activityService,
+ IEventMerger $eventMerger,
+ IFactory $transFactory,
+ IURLGenerator $urlGenerator,
+ IUserManager $userManager,
+ ShareMapper $shareMapper
+ ) {
+ $this->activityManager = $activityManager;
+ $this->activityService = $activityService;
+ $this->eventMerger = $eventMerger;
+ $this->transFactory = $transFactory;
+ $this->urlGenerator = $urlGenerator;
+ $this->userManager = $userManager;
+ $this->shareMapper = $shareMapper;
+ }
+
+ public function parse($language, IEvent $event, ?IEvent $previousEvent = null) {
+ if ($event->getApp() !== 'polls') {
+ throw new \InvalidArgumentException();
+ }
+
+ $this->trans = $this->transFactory->get($event->getApp(), $language);
+ $event->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath($event->getApp(), 'polls-black.svg')));
+ $this->setSubjects($event, $this->activityService->getActivityMessage($event, $language, $this->activityManager->isFormattingFilteredObject()));
+ return $event;
+ }
+
+ protected function setSubjects(IEvent $event, string $subject): void {
+ $parameters = $event->getSubjectParameters();
+ $actor = $this->userManager->get($event->getAuthor());
+
+ try {
+ if ($actor instanceof IUser) {
+ $parameters['actor'] = [
+ 'type' => 'user',
+ 'id' => $actor->getUID(),
+ 'name' => $actor->getDisplayName(),
+ ];
+ } else {
+ $share = $this->shareMapper->findByPollAndUser($event->getObjectId(), $event->getAuthor());
+ $parameters['actor'] = [
+ 'type' => 'guest',
+ 'id' => $share->getUserId(),
+ 'name' => $share->getDisplayName(),
+ ];
+ }
+ } catch (\Exception $e) {
+ $parameters['actor'] = [
+ 'type' => 'guest',
+ 'id' => $event->getAuthor(),
+ 'name' => 'An unknown user',
+ ];
+ }
+
+
+ $placeholders = $replacements = [];
+ foreach ($parameters as $placeholder => $parameter) {
+ $placeholders[] = '{' . $placeholder . '}';
+ $replacements[] = $parameter['name'];
+ }
+
+ $event->setParsedSubject(str_replace($placeholders, $replacements, $subject))
+ ->setRichSubject($subject, $parameters);
+ }
+}
diff --git a/lib/Service/ActivityService.php b/lib/Service/ActivityService.php
new file mode 100644
index 00000000..13f5a29c
--- /dev/null
+++ b/lib/Service/ActivityService.php
@@ -0,0 +1,370 @@
+<?php
+/**
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Service;
+
+use OCP\Activity\IManager as ActivityManager;
+use OCP\Activity\IEvent as ActivityEvent;
+use OCP\EventDispatcher\Event;
+use OCP\IL10N;
+use OCP\L10N\IFactory;
+use OCA\Polls\Db\Share;
+use OCA\Polls\Event\CommentEvent;
+use OCA\Polls\Event\PollEvent;
+use OCA\Polls\Event\OptionEvent;
+use OCA\Polls\Event\ShareEvent;
+use OCA\Polls\Event\VoteEvent;
+
+class ActivityService {
+ /** @var ActivityManager */
+ protected $activityManager;
+
+ /** @var IFactory */
+ protected $transFactory;
+
+ /** @var IL10N */
+ protected $trans;
+
+ /** @var string */
+ protected $shareType;
+
+ /** @var string */
+ protected $userIsActor;
+
+ /** @var string */
+ protected $eventType;
+
+ public function __construct(
+ IFactory $transFactory,
+ ActivityManager $activityManager
+ ) {
+ $this->transFactory = $transFactory;
+ $this->activityManager = $activityManager;
+ }
+
+ public function createActivityEvent(Event $event): ActivityEvent {
+ $activityEvent = $this->activityManager->generateEvent();
+ $activityEvent->setApp('polls')
+ ->setType($event->getActivityId())
+ ->setAuthor($event->getActor())
+ ->setObject($event->getActivityObject(), $event->getActivityObjectId())
+ ->setSubject($event->getActivitySubject(), $event->getActivitySubjectParams())
+ ->setTimestamp(time());
+ return $activityEvent;
+ }
+
+ public function publishActivityEvent(ActivityEvent $activityEvent, string $userId): void {
+ $activityEvent->setAffectedUser($userId);
+ $this->activityManager->publish($activityEvent);
+ }
+
+ public function getActivityMessage(ActivityEvent $event, string $language, bool $filtered = false) : string {
+ $this->trans = $this->transFactory->get($event->getApp(), $language);
+ $this->userIsActor = $event->getAuthor() === \OC::$server->getUserSession()->getUser()->getUID();
+ $this->eventType = $event->getType();
+ $parameters = $event->getSubjectParameters();
+ $this->shareType = $parameters['shareType']['name'] ?? '';
+
+ return $filtered
+ ? $this->getMessageFiltered()
+ : $this->getMessageFull();
+ }
+
+ private function getMessageFull() {
+ switch ($this->eventType) {
+ case CommentEvent::ADD:
+ return $this->userIsActor
+ ? $this->trans->t('You commented poll {pollTitle}')
+ : $this->trans->t('{actor} commented poll {pollTitle}');
+ case CommentEvent::DELETE:
+ return $this->userIsActor
+ ? $this->trans->t('You deleted a commented from poll {pollTitle}')
+ : $this->trans->t('{actor} deleted a commented from poll {pollTitle}');
+
+ case OptionEvent::ADD:
+ return $this->userIsActor
+ ? $this->trans->t('You added an option to poll {pollTitle}')
+ : $this->trans->t('{actor} added an option to poll {pollTitle}');
+ case OptionEvent::UPDATE:
+ return $this->userIsActor
+ ? $this->trans->t('You changed an option of poll {pollTitle}')
+ : $this->trans->t('{actor} changed an option of poll {pollTitle}');
+ case OptionEvent::CONFIRM:
+ return $this->userIsActor
+ ? $this->trans->t('You confirmed option {optionTitle} of poll {pollTitle}')
+ : $this->trans->t('{actor} confirmed option {optionTitle} of poll {pollTitle}');
+ case OptionEvent::UNCONFIRM:
+ return $this->userIsActor
+ ? $this->trans->t('You unconfirmed option {optionTitle} of poll {pollTitle}')
+ : $this->trans->t('{actor} unconfirmed option {optionTitle} of poll {pollTitle}');
+ case OptionEvent::DELETE:
+ return $this->userIsActor
+ ? $this->trans->t('You removed option {optionTitle} from poll {pollTitle}')
+ : $this->trans->t('{actor} removed option {optionTitle} from poll {pollTitle}');
+
+ case PollEvent::ADD:
+ return $this->userIsActor
+ ? $this->trans->t('You added poll {pollTitle}')
+ : $this->trans->t('{actor} added poll {pollTitle}');
+ case PollEvent::UPDATE:
+ return $this->userIsActor
+ ? $this->trans->t('You changed the configuration of poll {pollTitle}')
+ : $this->trans->t('{actor} changed the configuration of poll {pollTitle}');
+ case PollEvent::DELETE:
+ return $this->userIsActor
+ ? $this->trans->t('You archived poll {pollTitle}')
+ : $this->trans->t('{actor} archived poll {pollTitle}');
+ case PollEvent::RESTORE:
+ return $this->userIsActor
+ ? $this->trans->t('You restored poll {pollTitle}')
+ : $this->trans->t('{actor} restored poll {pollTitle}');
+ case PollEvent::EXPIRE:
+ return $this->userIsActor
+ ? $this->trans->t('Poll {pollTitle} was closed')
+ : $this->trans->t('Poll {pollTitle} was closed');
+ case PollEvent::OWNER_CHANGE:
+ return $this->userIsActor
+ ? $this->trans->t('You changed the owner of poll {pollTitle}')
+ : $this->trans->t('{actor} changed the owner of poll {pollTitle}');
+ case PollEvent::OPTION_REORDER:
+ return $this->userIsActor
+ ? $this->trans->t('You reordered the options of poll {pollTitle}')
+ : $this->trans->t('{actor} reordered the options of poll {pollTitle}');
+
+ case ShareEvent::ADD:
+ if ($this->shareType === Share::TYPE_PUBLIC) {
+ return $this->userIsActor
+ ? $this->trans->t('You added a public share to poll {pollTitle}')
+ : $this->trans->t('{actor} added a public share to poll {pollTitle}');
+ } elseif ($this->shareType === Share::TYPE_GROUP) {
+ return $this->userIsActor
+ ? $this->trans->t('You shared poll {pollTitle} with group {sharee}')
+ : $this->trans->t('{actor} You shared poll {pollTitle} with group {sharee}');
+ } elseif ($this->shareType === Share::TYPE_CIRCLE) {
+ return $this->userIsActor
+ ? $this->trans->t('You shared poll {pollTitle} with circle {sharee}')
+ : $this->trans->t('{actor} shared poll {pollTitle} with circle {sharee}');
+ } elseif ($this->shareType === Share::TYPE_CONTACTGROUP) {
+ return $this->userIsActor
+ ? $this->trans->t('You shared poll {pollTitle} with contact group {sharee}')
+ : $this->trans->t('{actor} shared poll {pollTitle} with contact group {sharee}');
+ }
+ return $this->userIsActor
+ ? $this->trans->t('You shared poll {pollTitle} with {sharee}')
+ : $this->trans->t('{actor} shared poll {pollTitle} with {sharee}');
+ case ShareEvent::CHANGE_EMAIL:
+ return $this->userIsActor
+ ? $this->trans->t('You changed your email address')
+ : $this->trans->t('{actor} changed his email address');
+ case ShareEvent::CHANGE_TYPE:
+ return $this->userIsActor
+ ? $this->trans->t('You changed the share type')
+ : $this->trans->t('{actor} changed the share type');
+ case ShareEvent::CHANGE_REG_CONSTR:
+ return $this->userIsActor
+ ? $this->trans->t('You changed the registration constraints for share {sharee}')
+ : $this->trans->t('{actor} changed the registration constraints for share {sharee}');
+ case ShareEvent::REGISTRATION:
+ return $this->userIsActor
+ ? $this->trans->t('You registered to poll {pollTitle}')
+ : $this->trans->t('{sharee} registered to poll {pollTitle}');
+ case ShareEvent::DELETE:
+ if ($this->shareType === Share::TYPE_PUBLIC) {
+ return $this->userIsActor
+ ? $this->trans->t('You deleted a public share from poll {pollTitle}')
+ : $this->trans->t('{actor} deleted a public share from poll {pollTitle}');
+ } elseif ($this->shareType === Share::TYPE_GROUP) {
+ return $this->userIsActor
+ ? $this->trans->t('You deleted the share for group {sharee} from poll {pollTitle}')
+ : $this->trans->t('{actor} deleted the share for group {sharee} from poll {pollTitle}');
+ } elseif ($this->shareType === Share::TYPE_USER) {
+ return $this->userIsActor
+ ? $this->trans->t('You deleted the share for {sharee} from poll {pollTitle}')
+ : $this->trans->t('{actor} deleted the share for {sharee} from poll {pollTitle}');
+ } elseif ($this->shareType === Share::TYPE_EMAIL) {
+ return $this->userIsActor
+ ? $this->trans->t('You deleted the share for {sharee} from poll {pollTitle}')
+ : $this->trans->t('{actor} deleted the share for {sharee} from poll {pollTitle}');
+ } elseif ($this->shareType === Share::TYPE_CONTACT) {
+ return $this->userIsActor
+ ? $this->trans->t('You deleted the share for {sharee} from poll {pollTitle}')
+ : $this->trans->t('{actor} deleted the share for {sharee} from poll {pollTitle}');
+ } elseif ($this->shareType === Share::TYPE_EXTERNAL) {
+ return $this->userIsActor
+ ? $this->trans->t('You deleted the share for {sharee} from poll {pollTitle}')
+ : $this->trans->t('{actor} deleted the share for {sharee} from poll {pollTitle}');
+ } elseif ($this->shareType === Share::TYPE_CIRCLE) {
+ return $this->userIsActor
+ ? $this->trans->t('You deleted the share for circle {sharee} from poll {pollTitle}')
+ : $this->trans->t('{actor} deleted the share for circle {sharee} from poll {pollTitle}');
+ } elseif ($this->shareType === Share::TYPE_CONTACTGROUP) {
+ return $this->userIsActor
+ ? $this->trans->t('You deleted the share for contact group {sharee} from poll {pollTitle}')
+ : $this->trans->t('{actor} deleted the share for contact group {sharee} from poll {pollTitle}');
+ }
+
+ return $this->userIsActor
+ ? $this->trans->t('You deleted a share from poll {pollTitle}')
+ : $this->trans->t('{actor} deleted a share from poll {pollTitle}');
+
+ case VoteEvent::SET:
+ return $this->userIsActor
+ ? $this->trans->t('You voted in poll {pollTitle}')
+ : $this->trans->t('{actor} voted in poll {pollTitle}');
+ }
+
+ return $this->userIsActor
+ ? $this->trans->t('You did something indescribable with poll {pollTitle}')
+ : $this->trans->t('{actor} did something indescribable with poll {pollTitle}');
+ }
+
+ private function getMessageFiltered() {
+ switch ($this->eventType) {
+ case CommentEvent::ADD:
+ return $this->userIsActor
+ ? $this->trans->t('You commented')
+ : $this->trans->t('{actor} commented');
+ case CommentEvent::DELETE:
+ return $this->userIsActor
+ ? $this->trans->t('You deleted a commented')
+ : $this->trans->t('{actor} deleted a commented');
+
+ case OptionEvent::ADD:
+ return $this->userIsActor
+ ? $this->trans->t('You added an option')
+ : $this->trans->t('{actor} added an option');
+ case OptionEvent::UPDATE:
+ return $this->userIsActor
+ ? $this->trans->t('You changed an option')
+ : $this->trans->t('{actor} changed an option');
+ case OptionEvent::CONFIRM:
+ return $this->userIsActor
+ ? $this->trans->t('You confirmed option {optionTitle}')
+ : $this->trans->t('{actor} confirmed option {optionTitle}');
+ case OptionEvent::UNCONFIRM:
+ return $this->userIsActor
+ ? $this->trans->t('You unconfirmed option {optionTitle}')
+ : $this->trans->t('{actor} unconfirmed option {optionTitle}');
+ case OptionEvent::DELETE:
+ return $this->userIsActor
+ ? $this->trans->t('You removed option {optionTitle}')
+ : $this->trans->t('{actor} removed option {optionTitle}');
+
+ case PollEvent::ADD:
+ return $this->userIsActor
+ ? $this->trans->t('You created this poll')
+ : $this->trans->t('{actor} created this poll');
+ case PollEvent::UPDATE:
+ return $this->userIsActor
+ ? $this->trans->t('You changed the configuration')
+ : $this->trans->t('{actor} changed the configuration');
+ case PollEvent::DELETE:
+ return $this->userIsActor
+ ? $this->trans->t('You archived this poll')
+ : $this->trans->t('{actor} archived this poll');
+ case PollEvent::RESTORE:
+ return $this->userIsActor
+ ? $this->trans->t('You restored this poll')
+ : $this->trans->t('{actor} restored this poll');
+ case PollEvent::EXPIRE:
+ return $this->trans->t('This poll was closed');
+ case PollEvent::OWNER_CHANGE:
+ return $this->userIsActor
+ ? $this->trans->t('You changed the poll owner')
+ : $this->trans->t('{actor} changed the poll owner');
+ case PollEvent::OPTION_REORDER:
+ return $this->userIsActor
+ ? $this->trans->t('You reordered the options')
+ : $this->trans->t('{actor} reordered the options');
+
+ case ShareEvent::ADD:
+ if ($this->shareType === Share::TYPE_PUBLIC) {
+ return $this->userIsActor
+ ? $this->trans->t('You added a public share')
+ : $this->trans->t('{actor} added a public share');
+ } elseif ($this->shareType === Share::TYPE_GROUP) {
+ return $this->userIsActor
+ ? $this->trans->t('You shared this poll with group {sharee}')
+ : $this->trans->t('{actor} You shared this poll with group {sharee}');
+ } elseif ($this->shareType === Share::TYPE_CIRCLE) {
+ return $this->userIsActor
+ ? $this->trans->t('You shared this poll with circle {sharee}')
+ : $this->trans->t('{actor} shared this poll with circle {sharee}');
+ } elseif ($this->shareType === Share::TYPE_CONTACTGROUP) {
+ return $this->userIsActor
+ ? $this->trans->t('You shared this poll with contact group {sharee}')
+ : $this->trans->t('{actor} shared this poll with contact group {sharee}');
+ }
+ return $this->userIsActor
+ ? $this->trans->t('You shared this poll with {sharee}')
+ : $this->trans->t('{actor} shared this poll with {sharee}');
+ case ShareEvent::CHANGE_EMAIL:
+ return $this->userIsActor
+ ? $this->trans->t('You changed your email address')
+ : $this->trans->t('{actor}\'s email address was changed');
+ case ShareEvent::CHANGE_TYPE:
+ return $this->userIsActor
+ ? $this->trans->t('You changed the share type')
+ : $this->trans->t('{actor} changed the share type');
+ case ShareEvent::CHANGE_REG_CONSTR:
+ return $this->userIsActor
+ ? $this->trans->t('You changed the registration constraints for share {sharee}')
+ : $this->trans->t('{actor} changed the registration constraints for share {sharee}');
+ case ShareEvent::REGISTRATION:
+ return $this->userIsActor
+ ? $this->trans->t('You registered')
+ : $this->trans->t('{sharee} registered');
+ case ShareEvent::DELETE:
+ if ($this->shareType === Share::TYPE_PUBLIC) {
+ return $this->userIsActor
+ ? $this->trans->t('You deleted a public share')
+ : $this->trans->t('{actor} deleted a public share');
+ } elseif ($this->shareType === Share::TYPE_GROUP) {
+ return $this->userIsActor
+ ? $this->trans->t('You deleted the share for group {sharee}')
+ : $this->trans->t('{actor} deleted the share for group {sharee}');
+ } elseif ($this->shareType === Share::TYPE_CIRCLE) {
+ return $this->userIsActor
+ ? $this->trans->t('You deleted the share for circle {sharee}')
+ : $this->trans->t('{actor} deleted the share for circle {sharee}');
+ } elseif ($this->shareType === Share::TYPE_CONTACTGROUP) {
+ return $this->userIsActor
+ ? $this->trans->t('You deleted the share for contact group {sharee}')
+ : $this->trans->t('{actor} deleted the share for contact group {sharee}');
+ }
+
+ return $this->userIsActor
+ ? $this->trans->t('You deleted {sharee}\'s share')
+ : $this->trans->t('{actor} deleted a share');
+
+ case VoteEvent::SET:
+ return $this->userIsActor
+ ? $this->trans->t('You voted')
+ : $this->trans->t('{actor} voted');
+ }
+
+ return $this->userIsActor
+ ? $this->trans->t('You did something indescribable with this poll')
+ : $this->trans->t('{actor} did something indescribable with this poll');
+ }
+}
diff --git a/lib/Service/CommentService.php b/lib/Service/CommentService.php
index 1ac8ccc6..e4377b02 100644
--- a/lib/Service/CommentService.php
+++ b/lib/Service/CommentService.php
@@ -26,7 +26,8 @@ namespace OCA\Polls\Service;
use OCP\EventDispatcher\IEventDispatcher;
use OCA\Polls\Db\Comment;
use OCA\Polls\Db\CommentMapper;
-use OCA\Polls\Event\CommentEvent;
+use OCA\Polls\Event\CommentAddEvent;
+use OCA\Polls\Event\CommentDeleteEvent;
use OCA\Polls\Model\Acl;
class CommentService {
@@ -95,7 +96,7 @@ class CommentService {
$this->comment->setTimestamp(time());
$this->comment = $this->commentMapper->insert($this->comment);
- $this->eventDispatcher->dispatchTyped(new CommentEvent($this->comment));
+ $this->eventDispatcher->dispatchTyped(new CommentAddEvent($this->comment));
return $this->comment;
}
@@ -118,7 +119,7 @@ class CommentService {
$this->commentMapper->delete($this->comment);
- $this->eventDispatcher->dispatchTyped(new CommentEvent($this->comment));
+ $this->eventDispatcher->dispatchTyped(new CommentDeleteEvent($this->comment));
return $this->comment;
}
diff --git a/lib/Service/LogService.php b/lib/Service/LogService.php
index 7e307a5f..fac538ed 100644
--- a/lib/Service/LogService.php
+++ b/lib/Service/LogService.php
@@ -23,8 +23,6 @@
namespace OCA\Polls\Service;
-use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
-use OCP\DB\Exception;
use OCA\Polls\Db\Log;
use OCA\Polls\Db\LogMapper;
@@ -54,16 +52,6 @@ class LogService {
$this->log->setMessageId($messageId);
$this->log->setUserId($userId ? $userId : \OC::$server->getUserSession()->getUser()->getUID());
- try {
- return $this->logMapper->insert($this->log);
- } catch (UniqueConstraintViolationException $e) {
- // deprecated NC22
- return null;
- } catch (Exception $e) {
- if ($e->getReason() === Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
- return null;
- }
- throw $e;
- }
+ return $this->logMapper->insert($this->log);
}
}
diff --git a/lib/Service/OptionService.php b/lib/Service/OptionService.php
index ed81177f..cf7fe2ab 100644
--- a/lib/Service/OptionService.php
+++ b/lib/Service/OptionService.php
@@ -39,10 +39,12 @@ use OCA\Polls\Db\VoteMapper;
use OCA\Polls\Db\Vote;
use OCA\Polls\Db\Option;
use OCA\Polls\Db\Poll;
-use OCA\Polls\Event\OptionEvent;
+use OCA\Polls\Event\OptionUpdatedEvent;
use OCA\Polls\Event\OptionConfirmedEvent;
use OCA\Polls\Event\OptionCreatedEvent;
use OCA\Polls\Event\OptionDeletedEvent;
+use OCA\Polls\Event\OptionUnconfirmedEvent;
+use OCA\Polls\Event\PollOptionReorderedEvent;
use OCA\Polls\Model\Acl;
class OptionService {
@@ -207,7 +209,7 @@ class OptionService {
$this->setOption($timestamp, $pollOptionText, $duration);
$this->option = $this->optionMapper->update($this->option);
- $this->eventDispatcher->dispatchTyped(new OptionEvent($this->option));
+ $this->eventDispatcher->dispatchTyped(new OptionUpdatedEvent($this->option));
return $this->option;
}
@@ -248,7 +250,11 @@ class OptionService {
$this->option->setConfirmed($this->option->getConfirmed() ? 0 : time());
$this->option = $this->optionMapper->update($this->option);
- $this->eventDispatcher->dispatchTyped(new OptionConfirmedEvent($this->option));
+ if ($this->option->getConfirmed()) {
+ $this->eventDispatcher->dispatchTyped(new OptionConfirmedEvent($this->option));
+ } else {
+ $this->eventDispatcher->dispatchTyped(new OptionUnconfirmedEvent($this->option));
+ }
return $this->option;
}
@@ -353,6 +359,7 @@ class OptionService {
$option->setDuration($origin->getDuration());
$option->setOrder($origin->getOrder());
$this->optionMapper->insert($option);
+ $this->eventDispatcher->dispatchTyped(new OptionCreatedEvent($option));
}
return $this->optionMapper->findByPoll($toPollId);
@@ -381,7 +388,7 @@ class OptionService {
}
}
- $this->eventDispatcher->dispatchTyped(new OptionEvent($this->option));
+ $this->eventDispatcher->dispatchTyped(new OptionUpdatedEvent($this->option));
return $this->optionMapper->findByPoll($this->acl->getPollId());
}
@@ -412,7 +419,7 @@ class OptionService {
$this->optionMapper->update($option);
}
- $this->eventDispatcher->dispatchTyped(new OptionEvent($this->option));
+ $this->eventDispatcher->dispatchTyped(new PollOptionReorderedEvent($this->acl->getPoll()));
return $this->optionMapper->findByPoll($this->acl->getPollId());
}
diff --git a/lib/Service/SettingsService.php b/lib/Service/SettingsService.php
index 5274f0ab..ab9ea7ca 100644
--- a/lib/Service/SettingsService.php
+++ b/lib/Service/SettingsService.php
@@ -24,10 +24,8 @@
namespace OCA\Polls\Service;
use OCP\IConfig;
-use OCP\AppFramework\IAppContainer;
use OCA\Polls\Model\Settings\AppSettings;
use OCA\Polls\Model\UserGroup\Group;
-use OCA\Polls\AppInfo\Application;
class SettingsService {
@@ -70,10 +68,6 @@ class SettingsService {
$this->appSettings->setPublicSharesGroups(array_column($settingsArray['publicSharesGroups'], 'id'));
$this->appSettings->setPollCreationGroups(array_column($settingsArray['pollCreationGroups'], 'id'));
$this->appSettings->setUpdateType($settingsArray['updateType']);
- }
-
- protected static function getContainer() : IAppContainer {
- $app = \OC::$server->query(Application::class);
- return $app->getContainer();
+ $this->appSettings->setUseActivity($settingsArray['useActivity']);
}
}
diff --git a/lib/Service/ShareService.php b/lib/Service/ShareService.php
index a4dde8db..cd396a6e 100644
--- a/lib/Service/ShareService.php
+++ b/lib/Service/ShareService.php
@@ -38,7 +38,12 @@ use OCA\Polls\Exceptions\NotFoundException;
use OCA\Polls\Db\PollMapper;
use OCA\Polls\Db\ShareMapper;
use OCA\Polls\Db\Share;
-use OCA\Polls\Event\ShareEvent;
+use OCA\Polls\Event\ShareCreateEvent;
+use OCA\Polls\Event\ShareTypeChangedEvent;
+use OCA\Polls\Event\ShareChangedEmailEvent;
+use OCA\Polls\Event\ShareChangedRegistrationConstraintEvent;
+use OCA\Polls\Event\ShareDeletedEvent;
+use OCA\Polls\Event\ShareRegistrationEvent;
use OCA\Polls\Model\Acl;
use OCA\Polls\Model\UserGroup\UserBase;
@@ -256,7 +261,6 @@ class ShareService {
$this->share = $this->shareMapper->insert($this->share);
- $this->eventDispatcher->dispatchTyped(new ShareEvent($this->share));
return $this->share;
}
@@ -284,6 +288,8 @@ class ShareService {
$this->create($pollId, UserBase::getUserGroupChild($type, $userId));
+ $this->eventDispatcher->dispatchTyped(new ShareCreateEvent($this->share));
+
return $this->share;
}
@@ -300,7 +306,7 @@ class ShareService {
throw new NotFoundException('Token ' . $token . ' does not exist');
}
- $this->eventDispatcher->dispatchTyped(new ShareEvent($this->share));
+ $this->eventDispatcher->dispatchTyped(new ShareTypeChangedEvent($this->share));
return $this->share;
}
@@ -317,8 +323,7 @@ class ShareService {
} catch (DoesNotExistException $e) {
throw new NotFoundException('Token ' . $token . ' does not exist');
}
-
- $this->eventDispatcher->dispatchTyped(new ShareEvent($this->share));
+ $this->eventDispatcher->dispatchTyped(new ShareChangedRegistrationConstraintEvent($this->share));
return $this->share;
}
@@ -345,7 +350,7 @@ class ShareService {
throw new InvalidShareTypeException('Email address can only be set in external shares.');
}
- $this->eventDispatcher->dispatchTyped(new ShareEvent($this->share));
+ $this->eventDispatcher->dispatchTyped(new ShareChangedEmailEvent($this->share));
return $this->share;
}
@@ -398,6 +403,7 @@ class ShareService {
UserBase::getUserGroupChild(Share::TYPE_EXTERNAL, $userName, $userName, $emailAddress),
!$emailAddress
);
+ $this->eventDispatcher->dispatchTyped(new ShareRegistrationEvent($this->share));
} elseif ($this->share->getType() === Share::TYPE_EMAIL
|| $this->share->getType() === Share::TYPE_CONTACT) {
@@ -412,8 +418,6 @@ class ShareService {
}
$this->share->setEmailAddress($emailAddress);
$this->shareMapper->update($this->share);
-
- $this->eventDispatcher->dispatchTyped(new ShareEvent($this->share));
} else {
throw new NotAuthorizedException;
}
@@ -442,7 +446,7 @@ class ShareService {
// silently catch
}
- $this->eventDispatcher->dispatchTyped(new ShareEvent($this->share));
+ $this->eventDispatcher->dispatchTyped(new ShareDeletedEvent($this->share));
return $token;
}
diff --git a/lib/Service/VoteService.php b/lib/Service/VoteService.php
index ad170236..b6b68185 100644
--- a/lib/Service/VoteService.php
+++ b/lib/Service/VoteService.php
@@ -32,7 +32,7 @@ use OCA\Polls\Db\OptionMapper;
use OCA\Polls\Db\Option;
use OCA\Polls\Db\VoteMapper;
use OCA\Polls\Db\Vote;
-use OCA\Polls\Event\VoteEvent;
+use OCA\Polls\Event\VoteSetEvent;
use OCA\Polls\Model\Acl;
class VoteService {
@@ -168,7 +168,7 @@ class VoteService {
$this->voteMapper->insert($this->vote);
}
- $this->eventDispatcher->dispatchTyped(new VoteEvent($this->vote));
+ $this->eventDispatcher->dispatchTyped(new VoteSetEvent($this->vote));
return $this->vote;
}
@@ -194,7 +194,7 @@ class VoteService {
$this->vote->setPollId($pollId);
$this->vote->setUserId($userId);
$this->voteMapper->deleteByPollAndUserId($pollId, $userId);
- $this->eventDispatcher->dispatchTyped(new VoteEvent($this->vote, false));
+ $this->eventDispatcher->dispatchTyped(new VoteSetEvent($this->vote, false));
return $userId;
}
}
diff --git a/lib/Settings/ActivitySettings.php b/lib/Settings/ActivitySettings.php
new file mode 100644
index 00000000..3298f745
--- /dev/null
+++ b/lib/Settings/ActivitySettings.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Settings;
+
+use OCP\IL10N;
+use OCP\Activity\ISetting;
+
+class ActivitySettings implements ISetting {
+
+ /** @var IL10N */
+ protected $l;
+
+ /**
+ * @param IL10N $l
+ */
+ public function __construct(IL10N $l) {
+ $this->l = $l;
+ }
+
+ public function getIdentifier() : string {
+ return 'poll';
+ }
+
+ public function getName() : string {
+ return $this->l->t('Events happening inside of a <strong>poll</strong>');
+ }
+
+ public function getPriority() : int {
+ return 90;
+ }
+
+ public function canChangeStream() : bool {
+ return true;
+ }
+
+ public function isDefaultEnabledStream() : bool {
+ return true;
+ }
+
+ public function canChangeMail() : bool {
+ return true;
+ }
+
+ public function isDefaultEnabledMail() : bool {
+ return false;
+ }
+}
diff --git a/lib/Settings/ActivityVote.php b/lib/Settings/ActivityVote.php
new file mode 100644
index 00000000..7547a5f5
--- /dev/null
+++ b/lib/Settings/ActivityVote.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ *
+ * @author René Gieling <github@dartcafe.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\Polls\Settings;
+
+class ActivityVote extends ActivitySettings {
+ public function getIdentifier() : string {
+ return 'vote_set';
+ }
+
+ public function getName() : string {
+ return $this->l->t('Someone votes inside a <strong>poll</strong>');
+ }
+}
diff --git a/package-lock.json b/package-lock.json
index b7d08353..31c9efea 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,7 @@
"version": "3.4.2",
"license": "AGPL-3.0",
"dependencies": {
+ "@juliushaertl/vue-richtext": "^1.0.1",
"@nextcloud/auth": "^1.3.0",
"@nextcloud/axios": "^1.8.0",
"@nextcloud/dialogs": "^3.1.2",
@@ -1902,6 +1903,69 @@
"integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==",
"dev": true
},
+ "node_modules/@juliushaertl/vue-richtext": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@juliushaertl/vue-richtext/-/vue-richtext-1.0.1.tgz",
+ "integrity": "sha512-h9fyBWgWEAamU2OHpQ+Irq5Y5zxqGdYc3dajh4X+r18bxqK3SY6kL39RA9msoGst5dx/dy7RBDoRemdF6M61ng==",
+ "dependencies": {
+ "clone": "^2.1.2",
+ "core-js": "^3.6.4",
+ "property-information": "^5.5.0",
+ "rehype-add-classes": "^1.0.0",
+ "rehype-react": "^6.1.0",
+ "remark-breaks": "2.0.0",
+ "remark-disable-tokenizers": "^1.0.0",
+ "remark-external-links": "^8.0.0",
+ "remark-parse": "^8.0.3",
+ "remark-rehype": "^8.0.0 ",
+ "unified": "^9.2.0",
+ "vue": "^2.6.12"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "vue": "^2.6.11"
+ }
+ },
+ "node_modules/@juliushaertl/vue-richtext/node_modules/remark-parse": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz",
+ "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==",
+ "dependencies": {
+ "ccount": "^1.0.0",
+ "collapse-white-space": "^1.0.2",
+ "is-alphabetical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-whitespace-character": "^1.0.0",
+ "is-word-character": "^1.0.0",
+ "markdown-escapes": "^1.0.0",
+ "parse-entities": "^2.0.0",
+ "repeat-string": "^1.5.4",
+ "state-toggle": "^1.0.0",
+ "trim": "0.0.1",
+ "trim-trailing-lines": "^1.0.0",
+ "unherit": "^1.0.4",
+ "unist-util-remove-position": "^2.0.0",
+ "vfile-location": "^3.0.0",
+ "xtend": "^4.0.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/@mapbox/hast-util-table-cell-style": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@mapbox/hast-util-table-cell-style/-/hast-util-table-cell-style-0.2.0.tgz",
+ "integrity": "sha512-gqaTIGC8My3LVSnU38IwjHVKJC94HSonjvFHDk8/aSrApL8v4uWgm8zJkK7MJIIbHuNOr/+Mv2KkQKcxs6LEZA==",
+ "dependencies": {
+ "unist-util-visit": "^1.4.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/@nextcloud/auth": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@nextcloud/auth/-/auth-1.3.0.tgz",
@@ -2434,7 +2498,6 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.3.tgz",
"integrity": "sha512-SXPBMnFVQg1s00dlMCc/jCdvPqdE4mXaMMCeRlxLDmTAEoegHT53xKtkDnzDTOcmMHUfcjyf36/YYZ6SxRdnsw==",
- "dev": true,
"dependencies": {
"@types/unist": "*"
}
@@ -2506,8 +2569,7 @@
"node_modules/@types/unist": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz",
- "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==",
- "dev": true
+ "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ=="
},
"node_modules/@vue/component-compiler-utils": {
"version": "3.2.2",
@@ -3424,7 +3486,6 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz",
"integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==",
- "dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
@@ -3467,6 +3528,11 @@
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
"dev": true
},
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
+ },
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -3641,6 +3707,15 @@
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
"dev": true
},
+ "node_modules/ccount": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz",
+ "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -3666,7 +3741,6 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz",
"integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==",
- "dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
@@ -3676,7 +3750,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
"integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==",
- "dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
@@ -3686,7 +3759,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz",
"integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==",
- "dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
@@ -3785,6 +3857,14 @@
"node": ">=8"
}
},
+ "node_modules/clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/clone-deep": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
@@ -3811,6 +3891,15 @@
"node": ">=6"
}
},
+ "node_modules/collapse-white-space": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz",
+ "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@@ -3851,6 +3940,15 @@
"node": ">= 0.8"
}
},
+ "node_modules/comma-separated-tokens": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz",
+ "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/commander": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
@@ -4066,6 +4164,11 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
+ "node_modules/css-selector-parser": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-1.4.1.tgz",
+ "integrity": "sha512-HYPSb7y/Z7BNDCOrakL4raGO2zltZkbeXyAd6Tg9obzix6QhzxCotdBl6VT0Dv4vZfJGVz3WL/xaEI9Ly3ul0g=="
+ },
"node_modules/cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@@ -5339,8 +5442,7 @@
"node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
- "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
- "dev": true
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
"node_modules/extsprintf": {
"version": "1.3.0",
@@ -6060,6 +6162,82 @@
"integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
"dev": true
},
+ "node_modules/hast-to-hyperscript": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz",
+ "integrity": "sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==",
+ "dependencies": {
+ "@types/unist": "^2.0.3",
+ "comma-separated-tokens": "^1.0.0",
+ "property-information": "^5.3.0",
+ "space-separated-tokens": "^1.0.0",
+ "style-to-object": "^0.3.0",
+ "unist-util-is": "^4.0.0",
+ "web-namespaces": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-has-property": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-1.0.4.tgz",
+ "integrity": "sha512-ghHup2voGfgFoHMGnaLHOjbYFACKrRh9KFttdCzMCbFoBMJXiNi2+XTrPP8+q6cDJM/RSqlCfVWrjp1H201rZg==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-is-element": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz",
+ "integrity": "sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-select": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-1.0.1.tgz",
+ "integrity": "sha1-nxWR76YroL316kKYswGqrh2tYS0=",
+ "dependencies": {
+ "camelcase": "^3.0.0",
+ "comma-separated-tokens": "^1.0.2",
+ "css-selector-parser": "^1.3.0",
+ "hast-util-has-property": "^1.0.0",
+ "hast-util-is-element": "^1.0.0",
+ "hast-util-whitespace": "^1.0.0",
+ "not": "^0.1.0",
+ "nth-check": "^1.0.1",
+ "property-information": "^3.1.0",
+ "space-separated-tokens": "^1.1.0",
+ "zwitch": "^1.0.0"
+ }
+ },
+ "node_modules/hast-util-select/node_modules/camelcase": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/hast-util-select/node_modules/property-information": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz",
+ "integrity": "sha1-/RSDyPusYYCPX+NZ52k6H0ilgzE="
+ },
+ "node_modules/hast-util-whitespace": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.4.tgz",
+ "integrity": "sha512-I5GTdSfhYfAPNztx2xJRQpG8cuDSNt599/7YUn7Gx/WxNMsG+a835k97TDkFgk123cwjfwINaZknkKkphx/f2A==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
@@ -6345,6 +6523,11 @@
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"dev": true
},
+ "node_modules/inline-style-parser": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz",
+ "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q=="
+ },
"node_modules/internal-slot": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
@@ -6382,11 +6565,18 @@
"integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
"dev": true
},
+ "node_modules/is-absolute-url": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz",
+ "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/is-alphabetical": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
"integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==",
- "dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
@@ -6396,7 +6586,6 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
"integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
- "dev": true,
"dependencies": {
"is-alphabetical": "^1.0.0",
"is-decimal": "^1.0.0"
@@ -6500,7 +6689,6 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
"integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
- "dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
@@ -6540,7 +6728,6 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
"integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==",
- "dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
@@ -6592,7 +6779,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -6715,6 +6901,24 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-whitespace-character": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz",
+ "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-word-character": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz",
+ "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -7226,6 +7430,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/markdown-escapes": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz",
+ "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/marked": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.0.8.tgz",
@@ -7262,6 +7475,45 @@
"is-buffer": "~1.1.6"
}
},
+ "node_modules/mdast-util-definitions": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz",
+ "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==",
+ "dependencies": {
+ "unist-util-visit": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-definitions/node_modules/unist-util-visit": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
+ "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0",
+ "unist-util-visit-parents": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-definitions/node_modules/unist-util-visit-parents": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz",
+ "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/mdast-util-from-markdown": {
"version": "0.8.5",
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz",
@@ -7279,6 +7531,52 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/mdast-util-to-hast": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.2.0.tgz",
+ "integrity": "sha512-JoPBfJ3gBnHZ18icCwHR50orC9kNH81tiR1gs01D8Q5YpV6adHNO9nKNuFBCJQ941/32PT1a63UF/DitmS3amQ==",
+ "dependencies": {
+ "@types/mdast": "^3.0.0",
+ "@types/unist": "^2.0.0",
+ "mdast-util-definitions": "^4.0.0",
+ "mdurl": "^1.0.0",
+ "unist-builder": "^2.0.0",
+ "unist-util-generated": "^1.0.0",
+ "unist-util-position": "^3.0.0",
+ "unist-util-visit": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-hast/node_modules/unist-util-visit": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
+ "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0",
+ "unist-util-visit-parents": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-hast/node_modules/unist-util-visit-parents": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz",
+ "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/mdast-util-to-markdown": {
"version": "0.6.5",
"resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz",
@@ -7307,6 +7605,11 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/mdurl": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+ "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
+ },
"node_modules/meow": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz",
@@ -8184,6 +8487,11 @@
"integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=",
"dev": true
},
+ "node_modules/not": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/not/-/not-0.1.0.tgz",
+ "integrity": "sha1-yWkcF0bFXc++VMvYvU/wQbwrUZ0="
+ },
"node_modules/npm-run-path": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
@@ -8211,6 +8519,14 @@
"node": "^12.13.0 || ^14.15.0 || >=16"
}
},
+ "node_modules/nth-check": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+ "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+ "dependencies": {
+ "boolbase": "~1.0.0"
+ }
+ },
"node_modules/num2fraction": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
@@ -8390,7 +8706,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz",
"integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==",
- "dev": true,
"dependencies": {
"character-entities": "^1.0.0",
"character-entities-legacy": "^1.0.0",
@@ -8985,6 +9300,18 @@
"node": ">=10"
}
},
+ "node_modules/property-information": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz",
+ "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==",
+ "dependencies": {
+ "xtend": "^4.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
@@ -9193,6 +9520,27 @@
"jsesc": "bin/jsesc"
}
},
+ "node_modules/rehype-add-classes": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/rehype-add-classes/-/rehype-add-classes-1.0.0.tgz",
+ "integrity": "sha512-Iz8t2KhCNAL+0AHKjxb+kVwsHk/pI3Cy4k0R70ZGzoQiZ7WQm3o8+3odJkMhFRfcNIK1lNShIHEdC90H5LwLdg==",
+ "dependencies": {
+ "hast-util-select": "^1.0.1"
+ }
+ },
+ "node_modules/rehype-react": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/rehype-react/-/rehype-react-6.2.1.tgz",
+ "integrity": "sha512-f9KIrjktvLvmbGc7si25HepocOg4z0MuNOtweigKzBcDjiGSTGhyz6VSgaV5K421Cq1O+z4/oxRJ5G9owo0KVg==",
+ "dependencies": {
+ "@mapbox/hast-util-table-cell-style": "^0.2.0",
+ "hast-to-hyperscript": "^9.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/remark": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/remark/-/remark-13.0.0.tgz",
@@ -9208,6 +9556,66 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/remark-breaks": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/remark-breaks/-/remark-breaks-2.0.0.tgz",
+ "integrity": "sha512-sDiB8dwX2/u42cf3PgjaGROG+q9ijh8SLbGZOU+7WNqL9M5ZQQ2hsVEfwqrJpsQTBcMkJvLACbwRpBftIiCVZQ==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-disable-tokenizers": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remark-disable-tokenizers/-/remark-disable-tokenizers-1.1.0.tgz",
+ "integrity": "sha512-49cCg4uSVKVmDHWKT5w+2mpDQ3G+xvt/GjypOqjlS0qTSs6/aBxE3iNWgX6ls2upXY17EKVlU0UpGcZjmGWI6A==",
+ "dependencies": {
+ "clone": "^2.1.2"
+ }
+ },
+ "node_modules/remark-external-links": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/remark-external-links/-/remark-external-links-8.0.0.tgz",
+ "integrity": "sha512-5vPSX0kHoSsqtdftSHhIYofVINC8qmp0nctkeU9YoJwV3YfiBRiI6cbFRJ0oI/1F9xS+bopXG0m2KS8VFscuKA==",
+ "dependencies": {
+ "extend": "^3.0.0",
+ "is-absolute-url": "^3.0.0",
+ "mdast-util-definitions": "^4.0.0",
+ "space-separated-tokens": "^1.0.0",
+ "unist-util-visit": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-external-links/node_modules/unist-util-visit": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
+ "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0",
+ "unist-util-visit-parents": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-external-links/node_modules/unist-util-visit-parents": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz",
+ "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/remark-parse": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-9.0.0.tgz",
@@ -9221,6 +9629,18 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/remark-rehype": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-8.1.0.tgz",
+ "integrity": "sha512-EbCu9kHgAxKmW1yEYjx3QafMyGY3q8noUbNUI5xyKbaFP89wbhDrKxyIQNukNYthzjNHZu6J7hwFg7hRm1svYA==",
+ "dependencies": {
+ "mdast-util-to-hast": "^10.2.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/remark-stringify": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-9.0.1.tgz",
@@ -9238,7 +9658,6 @@
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
"integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
- "dev": true,
"engines": {
"node": ">=0.10"
}
@@ -9742,6 +10161,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/space-separated-tokens": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz",
+ "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/spdx-correct": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
@@ -9831,6 +10259,15 @@
"node": ">= 8"
}
},
+ "node_modules/state-toggle": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz",
+ "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/stdout-stream": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz",
@@ -10062,6 +10499,14 @@
"integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=",
"dev": true
},
+ "node_modules/style-to-object": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz",
+ "integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==",
+ "dependencies": {
+ "inline-style-parser": "0.1.1"
+ }
+ },
"node_modules/stylelint": {
"version": "13.13.1",
"resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.13.1.tgz",
@@ -11175,6 +11620,11 @@
"resolved": "https://registry.npmjs.org/tributejs/-/tributejs-5.1.3.tgz",
"integrity": "sha512-B5CXihaVzXw+1UHhNFyAwUTMDk1EfoLP5Tj1VhD9yybZ1I8DZJEv8tZ1l0RJo0t0tk9ZhR8eG5tEsaCvRigmdQ=="
},
+ "node_modules/trim": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz",
+ "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0="
+ },
"node_modules/trim-newlines": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
@@ -11184,11 +11634,19 @@
"node": ">=8"
}
},
+ "node_modules/trim-trailing-lines": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz",
+ "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/trough": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz",
"integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==",
- "dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
@@ -11293,6 +11751,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/unherit": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz",
+ "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==",
+ "dependencies": {
+ "inherits": "^2.0.0",
+ "xtend": "^4.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/unicode-canonical-property-names-ecmascript": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
@@ -11333,7 +11804,6 @@
"version": "9.2.1",
"resolved": "https://registry.npmjs.org/unified/-/unified-9.2.1.tgz",
"integrity": "sha512-juWjuI8Z4xFg8pJbnEZ41b5xjGUWGHqXALmBZ3FC3WX0PIx1CZBIIJ6mXbYMcf6Yw4Fi0rFUTA1cdz/BglbOhA==",
- "dev": true,
"dependencies": {
"bail": "^1.0.0",
"extend": "^3.0.0",
@@ -11351,7 +11821,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
"integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -11394,6 +11863,15 @@
"imurmurhash": "^0.1.4"
}
},
+ "node_modules/unist-builder": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz",
+ "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/unist-util-find-all-after": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/unist-util-find-all-after/-/unist-util-find-all-after-3.0.2.tgz",
@@ -11407,11 +11885,67 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/unist-util-generated": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz",
+ "integrity": "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/unist-util-is": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz",
"integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==",
- "dev": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-position": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz",
+ "integrity": "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-remove-position": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz",
+ "integrity": "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==",
+ "dependencies": {
+ "unist-util-visit": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-remove-position/node_modules/unist-util-visit": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
+ "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0",
+ "unist-util-visit-parents": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-remove-position/node_modules/unist-util-visit-parents": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz",
+ "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==",
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0"
+ },
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
@@ -11421,7 +11955,6 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz",
"integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==",
- "dev": true,
"dependencies": {
"@types/unist": "^2.0.2"
},
@@ -11430,6 +11963,27 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/unist-util-visit": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz",
+ "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==",
+ "dependencies": {
+ "unist-util-visit-parents": "^2.0.0"
+ }
+ },
+ "node_modules/unist-util-visit-parents": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz",
+ "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==",
+ "dependencies": {
+ "unist-util-is": "^3.0.0"
+ }
+ },
+ "node_modules/unist-util-visit-parents/node_modules/unist-util-is": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz",
+ "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A=="
+ },
"node_modules/uri-js": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
@@ -11577,7 +12131,6 @@
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz",
"integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==",
- "dev": true,
"dependencies": {
"@types/unist": "^2.0.0",
"is-buffer": "^2.0.0",
@@ -11589,11 +12142,19 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/vfile-location": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz",
+ "integrity": "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/vfile-message": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz",
"integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==",
- "dev": true,
"dependencies": {
"@types/unist": "^2.0.0",
"unist-util-stringify-position": "^2.0.0"
@@ -11607,7 +12168,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
"integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -11869,6 +12429,15 @@
"node": ">=10.13.0"
}
},
+ "node_modules/web-namespaces": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz",
+ "integrity": "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/webpack": {
"version": "5.65.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.65.0.tgz",
@@ -12204,6 +12773,14 @@
"typedarray-to-buffer": "^3.1.5"
}
},
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
@@ -12268,7 +12845,6 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz",
"integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==",
- "dev": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
@@ -13532,6 +14108,58 @@
"integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==",
"dev": true
},
+ "@juliushaertl/vue-richtext": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@juliushaertl/vue-richtext/-/vue-richtext-1.0.1.tgz",
+ "integrity": "sha512-h9fyBWgWEAamU2OHpQ+Irq5Y5zxqGdYc3dajh4X+r18bxqK3SY6kL39RA9msoGst5dx/dy7RBDoRemdF6M61ng==",
+ "requires": {
+ "clone": "^2.1.2",
+ "core-js": "^3.6.4",
+ "property-information": "^5.5.0",
+ "rehype-add-classes": "^1.0.0",
+ "rehype-react": "^6.1.0",
+ "remark-breaks": "2.0.0",
+ "remark-disable-tokenizers": "^1.0.0",
+ "remark-external-links": "^8.0.0",
+ "remark-parse": "^8.0.3",
+ "remark-rehype": "^8.0.0 ",
+ "unified": "^9.2.0",
+ "vue": "^2.6.12"
+ },
+ "dependencies": {
+ "remark-parse": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz",
+ "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==",
+ "requires": {
+ "ccount": "^1.0.0",
+ "collapse-white-space": "^1.0.2",
+ "is-alphabetical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-whitespace-character": "^1.0.0",
+ "is-word-character": "^1.0.0",
+ "markdown-escapes": "^1.0.0",
+ "parse-entities": "^2.0.0",
+ "repeat-string": "^1.5.4",
+ "state-toggle": "^1.0.0",
+ "trim": "0.0.1",
+ "trim-trailing-lines": "^1.0.0",
+ "unherit": "^1.0.4",
+ "unist-util-remove-position": "^2.0.0",
+ "vfile-location": "^3.0.0",
+ "xtend": "^4.0.1"
+ }
+ }
+ }
+ },
+ "@mapbox/hast-util-table-cell-style": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@mapbox/hast-util-table-cell-style/-/hast-util-table-cell-style-0.2.0.tgz",
+ "integrity": "sha512-gqaTIGC8My3LVSnU38IwjHVKJC94HSonjvFHDk8/aSrApL8v4uWgm8zJkK7MJIIbHuNOr/+Mv2KkQKcxs6LEZA==",
+ "requires": {
+ "unist-util-visit": "^1.4.1"
+ }
+ },
"@nextcloud/auth": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@nextcloud/auth/-/auth-1.3.0.tgz",
@@ -13981,7 +14609,6 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.3.tgz",
"integrity": "sha512-SXPBMnFVQg1s00dlMCc/jCdvPqdE4mXaMMCeRlxLDmTAEoegHT53xKtkDnzDTOcmMHUfcjyf36/YYZ6SxRdnsw==",
- "dev": true,
"requires": {
"@types/unist": "*"
}
@@ -14045,8 +14672,7 @@
"@types/unist": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz",
- "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==",
- "dev": true
+ "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ=="
},
"@vue/component-compiler-utils": {
"version": "3.2.2",
@@ -14799,8 +15425,7 @@
"bail": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz",
- "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==",
- "dev": true
+ "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ=="
},
"balanced-match": {
"version": "1.0.0",
@@ -14833,6 +15458,11 @@
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
"dev": true
},
+ "boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
+ },
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -14969,6 +15599,11 @@
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
"dev": true
},
+ "ccount": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz",
+ "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg=="
+ },
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -14987,20 +15622,17 @@
"character-entities": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz",
- "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==",
- "dev": true
+ "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw=="
},
"character-entities-legacy": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
- "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==",
- "dev": true
+ "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA=="
},
"character-reference-invalid": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz",
- "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==",
- "dev": true
+ "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg=="
},
"charenc": {
"version": "0.0.2",
@@ -15077,6 +15709,11 @@
}
}
},
+ "clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18="
+ },
"clone-deep": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
@@ -15097,6 +15734,11 @@
"is-regexp": "^2.0.0"
}
},
+ "collapse-white-space": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz",
+ "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ=="
+ },
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@@ -15131,6 +15773,11 @@
"delayed-stream": "~1.0.0"
}
},
+ "comma-separated-tokens": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz",
+ "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw=="
+ },
"commander": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
@@ -15294,6 +15941,11 @@
}
}
},
+ "css-selector-parser": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-1.4.1.tgz",
+ "integrity": "sha512-HYPSb7y/Z7BNDCOrakL4raGO2zltZkbeXyAd6Tg9obzix6QhzxCotdBl6VT0Dv4vZfJGVz3WL/xaEI9Ly3ul0g=="
+ },
"cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@@ -16269,8 +16921,7 @@
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
- "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
- "dev": true
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
"extsprintf": {
"version": "1.3.0",
@@ -16803,6 +17454,65 @@
"integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
"dev": true
},
+ "hast-to-hyperscript": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz",
+ "integrity": "sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==",
+ "requires": {
+ "@types/unist": "^2.0.3",
+ "comma-separated-tokens": "^1.0.0",
+ "property-information": "^5.3.0",
+ "space-separated-tokens": "^1.0.0",
+ "style-to-object": "^0.3.0",
+ "unist-util-is": "^4.0.0",
+ "web-namespaces": "^1.0.0"
+ }
+ },
+ "hast-util-has-property": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-1.0.4.tgz",
+ "integrity": "sha512-ghHup2voGfgFoHMGnaLHOjbYFACKrRh9KFttdCzMCbFoBMJXiNi2+XTrPP8+q6cDJM/RSqlCfVWrjp1H201rZg=="
+ },
+ "hast-util-is-element": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz",
+ "integrity": "sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ=="
+ },
+ "hast-util-select": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-1.0.1.tgz",
+ "integrity": "sha1-nxWR76YroL316kKYswGqrh2tYS0=",
+ "requires": {
+ "camelcase": "^3.0.0",
+ "comma-separated-tokens": "^1.0.2",
+ "css-selector-parser": "^1.3.0",
+ "hast-util-has-property": "^1.0.0",
+ "hast-util-is-element": "^1.0.0",
+ "hast-util-whitespace": "^1.0.0",
+ "not": "^0.1.0",
+ "nth-check": "^1.0.1",
+ "property-information": "^3.1.0",
+ "space-separated-tokens": "^1.1.0",
+ "zwitch": "^1.0.0"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
+ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo="
+ },
+ "property-information": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-3.2.0.tgz",
+ "integrity": "sha1-/RSDyPusYYCPX+NZ52k6H0ilgzE="
+ }
+ }
+ },
+ "hast-util-whitespace": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-1.0.4.tgz",
+ "integrity": "sha512-I5GTdSfhYfAPNztx2xJRQpG8cuDSNt599/7YUn7Gx/WxNMsG+a835k97TDkFgk123cwjfwINaZknkKkphx/f2A=="
+ },
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
@@ -17027,6 +17737,11 @@
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"dev": true
},
+ "inline-style-parser": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz",
+ "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q=="
+ },
"internal-slot": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
@@ -17058,17 +17773,20 @@
"integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
"dev": true
},
+ "is-absolute-url": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz",
+ "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q=="
+ },
"is-alphabetical": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
- "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==",
- "dev": true
+ "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg=="
},
"is-alphanumerical": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
"integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
- "dev": true,
"requires": {
"is-alphabetical": "^1.0.0",
"is-decimal": "^1.0.0"
@@ -17140,8 +17858,7 @@
"is-decimal": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
- "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
- "dev": true
+ "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw=="
},
"is-extglob": {
"version": "2.1.1",
@@ -17167,8 +17884,7 @@
"is-hexadecimal": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
- "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==",
- "dev": true
+ "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw=="
},
"is-lambda": {
"version": "1.0.1",
@@ -17200,8 +17916,7 @@
"is-plain-obj": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
- "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
- "dev": true
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA=="
},
"is-plain-object": {
"version": "2.0.4",
@@ -17279,6 +17994,16 @@
"call-bind": "^1.0.0"
}
},
+ "is-whitespace-character": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz",
+ "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w=="
+ },
+ "is-word-character": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz",
+ "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA=="
+ },
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -17693,6 +18418,11 @@
"integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
"dev": true
},
+ "markdown-escapes": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz",
+ "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg=="
+ },
"marked": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.0.8.tgz",
@@ -17719,6 +18449,35 @@
"is-buffer": "~1.1.6"
}
},
+ "mdast-util-definitions": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz",
+ "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==",
+ "requires": {
+ "unist-util-visit": "^2.0.0"
+ },
+ "dependencies": {
+ "unist-util-visit": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
+ "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0",
+ "unist-util-visit-parents": "^3.0.0"
+ }
+ },
+ "unist-util-visit-parents": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz",
+ "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==",
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0"
+ }
+ }
+ }
+ },
"mdast-util-from-markdown": {
"version": "0.8.5",
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz",
@@ -17732,6 +18491,42 @@
"unist-util-stringify-position": "^2.0.0"
}
},
+ "mdast-util-to-hast": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.2.0.tgz",
+ "integrity": "sha512-JoPBfJ3gBnHZ18icCwHR50orC9kNH81tiR1gs01D8Q5YpV6adHNO9nKNuFBCJQ941/32PT1a63UF/DitmS3amQ==",
+ "requires": {
+ "@types/mdast": "^3.0.0",
+ "@types/unist": "^2.0.0",
+ "mdast-util-definitions": "^4.0.0",
+ "mdurl": "^1.0.0",
+ "unist-builder": "^2.0.0",
+ "unist-util-generated": "^1.0.0",
+ "unist-util-position": "^3.0.0",
+ "unist-util-visit": "^2.0.0"
+ },
+ "dependencies": {
+ "unist-util-visit": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
+ "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0",
+ "unist-util-visit-parents": "^3.0.0"
+ }
+ },
+ "unist-util-visit-parents": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz",
+ "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==",
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0"
+ }
+ }
+ }
+ },
"mdast-util-to-markdown": {
"version": "0.6.5",
"resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz",
@@ -17752,6 +18547,11 @@
"integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==",
"dev": true
},
+ "mdurl": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+ "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
+ },
"meow": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz",
@@ -18421,6 +19221,11 @@
"integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=",
"dev": true
},
+ "not": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/not/-/not-0.1.0.tgz",
+ "integrity": "sha1-yWkcF0bFXc++VMvYvU/wQbwrUZ0="
+ },
"npm-run-path": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
@@ -18442,6 +19247,14 @@
"set-blocking": "^2.0.0"
}
},
+ "nth-check": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+ "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+ "requires": {
+ "boolbase": "~1.0.0"
+ }
+ },
"num2fraction": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
@@ -18570,7 +19383,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz",
"integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==",
- "dev": true,
"requires": {
"character-entities": "^1.0.0",
"character-entities-legacy": "^1.0.0",
@@ -19004,6 +19816,14 @@
"retry": "^0.12.0"
}
},
+ "property-information": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz",
+ "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==",
+ "requires": {
+ "xtend": "^4.0.0"
+ }
+ },
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
@@ -19161,6 +19981,23 @@
}
}
},
+ "rehype-add-classes": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/rehype-add-classes/-/rehype-add-classes-1.0.0.tgz",
+ "integrity": "sha512-Iz8t2KhCNAL+0AHKjxb+kVwsHk/pI3Cy4k0R70ZGzoQiZ7WQm3o8+3odJkMhFRfcNIK1lNShIHEdC90H5LwLdg==",
+ "requires": {
+ "hast-util-select": "^1.0.1"
+ }
+ },
+ "rehype-react": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/rehype-react/-/rehype-react-6.2.1.tgz",
+ "integrity": "sha512-f9KIrjktvLvmbGc7si25HepocOg4z0MuNOtweigKzBcDjiGSTGhyz6VSgaV5K421Cq1O+z4/oxRJ5G9owo0KVg==",
+ "requires": {
+ "@mapbox/hast-util-table-cell-style": "^0.2.0",
+ "hast-to-hyperscript": "^9.0.0"
+ }
+ },
"remark": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/remark/-/remark-13.0.0.tgz",
@@ -19172,6 +20009,52 @@
"unified": "^9.1.0"
}
},
+ "remark-breaks": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/remark-breaks/-/remark-breaks-2.0.0.tgz",
+ "integrity": "sha512-sDiB8dwX2/u42cf3PgjaGROG+q9ijh8SLbGZOU+7WNqL9M5ZQQ2hsVEfwqrJpsQTBcMkJvLACbwRpBftIiCVZQ=="
+ },
+ "remark-disable-tokenizers": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remark-disable-tokenizers/-/remark-disable-tokenizers-1.1.0.tgz",
+ "integrity": "sha512-49cCg4uSVKVmDHWKT5w+2mpDQ3G+xvt/GjypOqjlS0qTSs6/aBxE3iNWgX6ls2upXY17EKVlU0UpGcZjmGWI6A==",
+ "requires": {
+ "clone": "^2.1.2"
+ }
+ },
+ "remark-external-links": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/remark-external-links/-/remark-external-links-8.0.0.tgz",
+ "integrity": "sha512-5vPSX0kHoSsqtdftSHhIYofVINC8qmp0nctkeU9YoJwV3YfiBRiI6cbFRJ0oI/1F9xS+bopXG0m2KS8VFscuKA==",
+ "requires": {
+ "extend": "^3.0.0",
+ "is-absolute-url": "^3.0.0",
+ "mdast-util-definitions": "^4.0.0",
+ "space-separated-tokens": "^1.0.0",
+ "unist-util-visit": "^2.0.0"
+ },
+ "dependencies": {
+ "unist-util-visit": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
+ "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0",
+ "unist-util-visit-parents": "^3.0.0"
+ }
+ },
+ "unist-util-visit-parents": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz",
+ "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==",
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0"
+ }
+ }
+ }
+ },
"remark-parse": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-9.0.0.tgz",
@@ -19181,6 +20064,14 @@
"mdast-util-from-markdown": "^0.8.0"
}
},
+ "remark-rehype": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-8.1.0.tgz",
+ "integrity": "sha512-EbCu9kHgAxKmW1yEYjx3QafMyGY3q8noUbNUI5xyKbaFP89wbhDrKxyIQNukNYthzjNHZu6J7hwFg7hRm1svYA==",
+ "requires": {
+ "mdast-util-to-hast": "^10.2.0"
+ }
+ },
"remark-stringify": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-9.0.1.tgz",
@@ -19193,8 +20084,7 @@
"repeat-string": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
- "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
- "dev": true
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
},
"request": {
"version": "2.88.2",
@@ -19552,6 +20442,11 @@
}
}
},
+ "space-separated-tokens": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz",
+ "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA=="
+ },
"spdx-correct": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
@@ -19627,6 +20522,11 @@
"minipass": "^3.1.1"
}
},
+ "state-toggle": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz",
+ "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ=="
+ },
"stdout-stream": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz",
@@ -19795,6 +20695,14 @@
"integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=",
"dev": true
},
+ "style-to-object": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz",
+ "integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==",
+ "requires": {
+ "inline-style-parser": "0.1.1"
+ }
+ },
"stylelint": {
"version": "13.13.1",
"resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.13.1.tgz",
@@ -20622,17 +21530,26 @@
"resolved": "https://registry.npmjs.org/tributejs/-/tributejs-5.1.3.tgz",
"integrity": "sha512-B5CXihaVzXw+1UHhNFyAwUTMDk1EfoLP5Tj1VhD9yybZ1I8DZJEv8tZ1l0RJo0t0tk9ZhR8eG5tEsaCvRigmdQ=="
},
+ "trim": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz",
+ "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0="
+ },
"trim-newlines": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
"integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
"dev": true
},
+ "trim-trailing-lines": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz",
+ "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ=="
+ },
"trough": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz",
- "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==",
- "dev": true
+ "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA=="
},
"true-case-path": {
"version": "1.0.3",
@@ -20717,6 +21634,15 @@
"which-boxed-primitive": "^1.0.2"
}
},
+ "unherit": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz",
+ "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==",
+ "requires": {
+ "inherits": "^2.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
"unicode-canonical-property-names-ecmascript": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
@@ -20745,7 +21671,6 @@
"version": "9.2.1",
"resolved": "https://registry.npmjs.org/unified/-/unified-9.2.1.tgz",
"integrity": "sha512-juWjuI8Z4xFg8pJbnEZ41b5xjGUWGHqXALmBZ3FC3WX0PIx1CZBIIJ6mXbYMcf6Yw4Fi0rFUTA1cdz/BglbOhA==",
- "dev": true,
"requires": {
"bail": "^1.0.0",
"extend": "^3.0.0",
@@ -20758,8 +21683,7 @@
"is-buffer": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
- "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
- "dev": true
+ "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ=="
}
}
},
@@ -20787,6 +21711,11 @@
"imurmurhash": "^0.1.4"
}
},
+ "unist-builder": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz",
+ "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw=="
+ },
"unist-util-find-all-after": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/unist-util-find-all-after/-/unist-util-find-all-after-3.0.2.tgz",
@@ -20796,21 +21725,81 @@
"unist-util-is": "^4.0.0"
}
},
+ "unist-util-generated": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz",
+ "integrity": "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg=="
+ },
"unist-util-is": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz",
- "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==",
- "dev": true
+ "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg=="
+ },
+ "unist-util-position": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz",
+ "integrity": "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA=="
+ },
+ "unist-util-remove-position": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz",
+ "integrity": "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==",
+ "requires": {
+ "unist-util-visit": "^2.0.0"
+ },
+ "dependencies": {
+ "unist-util-visit": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
+ "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0",
+ "unist-util-visit-parents": "^3.0.0"
+ }
+ },
+ "unist-util-visit-parents": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz",
+ "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==",
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0"
+ }
+ }
+ }
},
"unist-util-stringify-position": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz",
"integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==",
- "dev": true,
"requires": {
"@types/unist": "^2.0.2"
}
},
+ "unist-util-visit": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz",
+ "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==",
+ "requires": {
+ "unist-util-visit-parents": "^2.0.0"
+ }
+ },
+ "unist-util-visit-parents": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz",
+ "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==",
+ "requires": {
+ "unist-util-is": "^3.0.0"
+ },
+ "dependencies": {
+ "unist-util-is": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz",
+ "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A=="
+ }
+ }
+ },
"uri-js": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
@@ -20923,7 +21912,6 @@
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz",
"integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==",
- "dev": true,
"requires": {
"@types/unist": "^2.0.0",
"is-buffer": "^2.0.0",
@@ -20934,16 +21922,19 @@
"is-buffer": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
- "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
- "dev": true
+ "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ=="
}
}
},
+ "vfile-location": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz",
+ "integrity": "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA=="
+ },
"vfile-message": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz",
"integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==",
- "dev": true,
"requires": {
"@types/unist": "^2.0.0",
"unist-util-stringify-position": "^2.0.0"
@@ -21140,6 +22131,11 @@
"graceful-fs": "^4.1.2"
}
},
+ "web-namespaces": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz",
+ "integrity": "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw=="
+ },
"webpack": {
"version": "5.65.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.65.0.tgz",
@@ -21381,6 +22377,11 @@
"typedarray-to-buffer": "^3.1.5"
}
},
+ "xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
+ },
"y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
@@ -21431,8 +22432,7 @@
"zwitch": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz",
- "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==",
- "dev": true
+ "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw=="
}
}
}
diff --git a/package.json b/package.json
index 5b19e88a..eea65acb 100644
--- a/package.json
+++ b/package.json
@@ -35,6 +35,7 @@
"stylelint:fix": "stylelint src --fix"
},
"dependencies": {
+ "@juliushaertl/vue-richtext": "^1.0.1",
"@nextcloud/auth": "^1.3.0",
"@nextcloud/axios": "^1.8.0",
"@nextcloud/dialogs": "^3.1.2",
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index a537ec90..5439d2cf 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -1,7 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
-<files psalm-version="4.9.3@4c262932602b9bbab5020863d1eb22d49de0dbf4">
+<files psalm-version="v4.15.0@a1b5e489e6fcebe40cb804793d964e99fc347820">
<file src="lib/AppInfo/Application.php">
- <InvalidArgument occurrences="16">
+ <InvalidArgument occurrences="24">
+ <code>registerEventListener</code>
+ <code>registerEventListener</code>
+ <code>registerEventListener</code>
+ <code>registerEventListener</code>
+ <code>registerEventListener</code>
+ <code>registerEventListener</code>
+ <code>registerEventListener</code>
+ <code>registerEventListener</code>
<code>registerEventListener</code>
<code>registerEventListener</code>
<code>registerEventListener</code>
@@ -20,4 +28,44 @@
<code>registerEventListener</code>
</InvalidArgument>
</file>
+ <file src="lib/Listener/BaseListener.php">
+ <UndefinedMethod occurrences="10">
+ <code>getActivityId</code>
+ <code>getActor</code>
+ <code>getActor</code>
+ <code>getActor</code>
+ <code>getLogId</code>
+ <code>getLogId</code>
+ <code>getPollId</code>
+ <code>getPollId</code>
+ <code>getPollOwner</code>
+ <code>getPollOwner</code>
+ </UndefinedMethod>
+ </file>
+ <file src="lib/Listener/GroupDeletedListener.php">
+ <UndefinedMethod occurrences="1">
+ <code>getGroup</code>
+ </UndefinedMethod>
+ </file>
+ <file src="lib/Listener/PollListener.php">
+ <UndefinedMethod occurrences="2">
+ <code>getNotification</code>
+ <code>getNotification</code>
+ </UndefinedMethod>
+ </file>
+ <file src="lib/Listener/UserDeletedListener.php">
+ <UndefinedMethod occurrences="1">
+ <code>getUser</code>
+ </UndefinedMethod>
+ </file>
+ <file src="lib/Service/ActivityService.php">
+ <UndefinedMethod occurrences="6">
+ <code>getActivityId</code>
+ <code>getActivityObject</code>
+ <code>getActivityObjectId</code>
+ <code>getActivitySubject</code>
+ <code>getActivitySubjectParams</code>
+ <code>getActor</code>
+ </UndefinedMethod>
+ </file>
</files>
diff --git a/src/js/App.vue b/src/js/App.vue
index 4ba47262..af4cdafd 100644
--- a/src/js/App.vue
+++ b/src/js/App.vue
@@ -190,7 +190,6 @@ export default {
},
async loadPoll(silent) {
- const dispatches = []
if (!silent) {
this.loading = true
this.transitionsOff()
@@ -201,19 +200,20 @@ export default {
throw new Error('No pollId for vote page')
}
- if (this.$route.name === 'publicVote') {
- dispatches.push('share/get')
- } else if (this.$route.name === 'vote') {
- dispatches.push('shares/list')
- }
-
- dispatches.push(
+ const dispatches = [
'poll/get',
'comments/list',
'options/list',
'votes/list',
'subscription/get',
- )
+ ]
+
+ if (this.$route.name === 'publicVote') {
+ dispatches.push('share/get')
+ } else if (this.$route.name === 'vote') {
+ dispatches.push('shares/list')
+ dispatches.push('activity/list')
+ }
const requests = dispatches.map((dispatches) => this.$store.dispatch(dispatches))
await Promise.all(requests)
diff --git a/src/js/assets/icons/clock-fff.svg b/src/js/assets/icons/clock-fff.svg
index 29e5055f..ebe8c543 100644
--- a/src/js/assets/icons/clock-fff.svg
+++ b/src/js/assets/icons/clock-fff.svg
@@ -1,5 +1,5 @@
-<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" viewBox="0 0 16 16">
- <g fill="none" stroke-width="1.5" stroke="#fff" stroke-linejoin="round" stroke-linecap="round">
- <circle r="6.5" cy="8" cx="8" />
- <path d="m 8.00005,5.6251078 v 2.375 l 2.90625,2.1562502"/>
-</g></svg>
+<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" viewBox="0 0 16 16">
+ <g fill="none" stroke-width="1.5" stroke="#fff" stroke-linejoin="round" stroke-linecap="round">
+ <circle r="6.5" cy="8" cx="8" />
+ <path d="m 8.00005,5.6251078 v 2.375 l 2.90625,2.1562502"/>
+</g></svg>
diff --git a/src/js/assets/icons/clock.svg b/src/js/assets/icons/clock.svg
index 9e6ec1da..5f32a0af 100644
--- a/src/js/assets/icons/clock.svg
+++ b/src/js/assets/icons/clock.svg
@@ -1,5 +1,5 @@
-<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" viewBox="0 0 16 16">
- <g fill="none" stroke-width="1.5" stroke="#000" stroke-linejoin="round" stroke-linecap="round">
- <circle r="6.5" cy="8" cx="8" />
- <path d="m 8.00005,5.6251078 v 2.375 l 2.90625,2.1562502"/>
-</g></svg>
+<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" viewBox="0 0 16 16">
+ <g fill="none" stroke-width="1.5" stroke="#000" stroke-linejoin="round" stroke-linecap="round">
+ <circle r="6.5" cy="8" cx="8" />
+ <path d="m 8.00005,5.6251078 v 2.375 l 2.90625,2.1562502"/>
+</g></svg>
diff --git a/src/js/assets/icons/mail-fff.svg b/src/js/assets/icons/mail-fff.svg
index 8cc90b43..dda1bf96 100644
--- a/src/js/assets/icons/mail-fff.svg
+++ b/src/js/assets/icons/mail-fff.svg
@@ -1,3 +1,3 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16">
- <path d="m 0,4 v 8 c 0,0.499044 0.500214,1 1,1 H 14.984375 C 15.499152,13 16,12.499844 16,11.984375 V 4 C 16,3.4968466 15.499786,3 15,3 H 1 C 0.496234,3 0,3.5002138 0,4 Z m 15,0.5 v 7 L 10.948233,7.1105856 Z M 10.358137,7.4816038 14.5,12 H 1.5 L 5.63635,7.4876179 8,9 Z M 8,8 1.5,4 h 13 z m -7,3.5 v -7 l 4.060498,2.6103198 z"/>
-</svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16">
+ <path d="m 0,4 v 8 c 0,0.499044 0.500214,1 1,1 H 14.984375 C 15.499152,13 16,12.499844 16,11.984375 V 4 C 16,3.4968466 15.499786,3 15,3 H 1 C 0.496234,3 0,3.5002138 0,4 Z m 15,0.5 v 7 L 10.948233,7.1105856 Z M 10.358137,7.4816038 14.5,12 H 1.5 L 5.63635,7.4876179 8,9 Z M 8,8 1.5,4 h 13 z m -7,3.5 v -7 l 4.060498,2.6103198 z"/>
+</svg>
diff --git a/src/js/assets/icons/polls-000.svg b/src/js/assets/icons/polls-000.svg
index acaf7958..bc39602c 100644
--- a/src/js/assets/icons/polls-000.svg
+++ b/src/js/assets/icons/polls-000.svg
@@ -1,7 +1,7 @@
-<svg xmlns="http://www.w3.org/2000/svg" height="32" width="32" viewBox="0 0 32 32">
- <g fill="#000">
- <rect y="2" x="3" height="26" width="7" />
- <rect y="12" x="12" height="16" width="7" />
- <rect y="8" x="21" height="20" width="7" />
- </g>
-</svg>
+<svg xmlns="http://www.w3.org/2000/svg" height="32" width="32" viewBox="0 0 32 32">
+ <g fill="#000">
+ <rect y="2" x="3" height="26" width="7" />
+ <rect y="12" x="12" height="16" width="7" />
+ <rect y="8" x="21" height="20" width="7" />
+ </g>
+</svg>
diff --git a/src/js/assets/icons/polls-fff.svg b/src/js/assets/icons/polls-fff.svg
index f94d056b..5eb3149e 100644
--- a/src/js/assets/icons/polls-fff.svg
+++ b/src/js/assets/icons/polls-fff.svg
@@ -1,7 +1,7 @@
-<svg xmlns="http://www.w3.org/2000/svg" height="32" width="32" viewBox="0 0 32 32">
- <g fill="#fff">
- <rect y="2" x="3" height="26" width="7" />
- <rect y="12" x="12" height="16" width="7" />
- <rect y="8" x="21" height="20" width="7" />
- </g>
-</svg>
+<svg xmlns="http://www.w3.org/2000/svg" height="32" width="32" viewBox="0 0 32 32">
+ <g fill="#fff">
+ <rect y="2" x="3" height="26" width="7" />
+ <rect y="12" x="12" height="16" width="7" />
+ <rect y="8" x="21" height="20" width="7" />
+ </g>
+</svg>
diff --git a/src/js/components/Activity/Activities.vue b/src/js/components/Activity/Activities.vue
new file mode 100644
index 00000000..03af85c6
--- /dev/null
+++ b/src/js/components/Activity/Activities.vue
@@ -0,0 +1,49 @@
+<!--
+ - @copyright Copyright (c) 2018 René Gieling <github@dartcafe.de>
+ -
+ - @author René Gieling <github@dartcafe.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/>.
+ -
+ -->
+
+<template>
+ <transition-group name="fade" class="activities" tag="ul">
+ <ActivityItem v-for="(item) in activities"
+ :key="item.activity_id"
+ :activity="item"
+ tag="li" />
+ </transition-group>
+</template>
+
+<script>
+import ActivityItem from './ActivityItem'
+import { mapState } from 'vuex'
+
+export default {
+ name: 'Activities',
+ components: {
+ ActivityItem,
+ },
+
+ computed: {
+ ...mapState({
+ activities: (state) => state.activity.list,
+ }),
+
+ },
+}
+</script>
diff --git a/src/js/components/Activity/ActivityItem.vue b/src/js/components/Activity/ActivityItem.vue
new file mode 100644
index 00000000..d6a18991
--- /dev/null
+++ b/src/js/components/Activity/ActivityItem.vue
@@ -0,0 +1,147 @@
+<!--
+ - @copyright Copyright (c) 2021 René Gieling <github@dartcafe.de>
+ -
+ - @author René Gieling <github@dartcafe.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/>.
+ -
+ -->
+
+<template>
+ <div class="activity-item">
+ <div class="activity-item__content">
+ <span class="activity-item__date">{{ dateActivityRelative }}</span>
+ <RichText :text="message.subject" :arguments="message.parameters" />
+ </div>
+ </div>
+</template>
+
+<script>
+import moment from '@nextcloud/moment'
+import RichText from '@juliushaertl/vue-richtext'
+import { UserBubble } from '@nextcloud/vue'
+
+const InternalLink = {
+ name: 'InternalLink',
+ functional: true,
+ props: {
+ href: {
+ type: String,
+ default: '',
+ },
+ name: {
+ type: String,
+ default: '',
+ },
+ },
+ render(createElement, context) {
+ return createElement('a', { attrs: { href: context.props.href }, style: { 'font-weight': 600 } }, context.props.name)
+ },
+}
+
+export default {
+ name: 'ActivityItem',
+
+ components: {
+ RichText,
+ },
+
+ props: {
+ activity: {
+ type: Object,
+ default: null,
+ },
+ },
+
+ computed: {
+ dateActivityRelative() {
+ return moment(this.activity.datetime).fromNow()
+ },
+
+ message() {
+ const subject = this.activity.subject_rich[0]
+ const parameters = JSON.parse(JSON.stringify(this.activity.subject_rich[1]))
+ if (parameters.after && typeof parameters.after.id === 'string' && parameters.after.id.startsWith('dt:')) {
+ const dateTime = parameters.after.id.substr(3)
+ parameters.after.name = moment(dateTime).format('L LTS')
+ }
+
+ Object.keys(parameters).forEach(function(key, index) {
+ const { type } = parameters[key]
+ switch (type) {
+ case 'highlight':
+ parameters[key] = {
+ component: InternalLink,
+ props: {
+ href: parameters[key].link,
+ name: parameters[key].name,
+ },
+ }
+ break
+ case 'user':
+ parameters[key] = {
+ component: UserBubble,
+ props: {
+ user: parameters[key].id,
+ displayName: parameters[key].name,
+ },
+ }
+ break
+ case 'guest':
+ parameters[key] = {
+ component: UserBubble,
+ props: {
+ user: parameters[key].id,
+ displayName: parameters[key].name,
+ },
+ }
+ break
+ default:
+ parameters[key] = `{${key}}`
+ }
+
+ })
+
+ return {
+ subject, parameters,
+ }
+ },
+ },
+}
+</script>
+
+<style lang="scss">
+ .activity-item {
+ display: flex;
+ align-items: start;
+ margin-bottom: 24px;
+ }
+
+ .activity-item__date {
+ opacity: 0.5;
+ font-size: 0.8em;
+ text-align: right;
+ &::before {
+ content: ' ~ '
+ }
+ }
+
+ .activity-item__content {
+ margin-left: 8px;
+ flex: 1 1;
+ padding-top: 2px;
+ }
+</style>
diff --git a/src/js/components/Settings/AdminMisc.vue b/src/js/components/Settings/AdminMisc.vue
index dde5fdc8..71115701 100644
--- a/src/js/components/Settings/AdminMisc.vue
+++ b/src/js/components/Settings/AdminMisc.vue
@@ -23,6 +23,9 @@
<template>
<div>
<div class="user_settings">
+ <CheckboxRadioSwitch :checked.sync="useActivity" type="switch">
+ {{ t('polls', 'Track activities') }}
+ </CheckboxRadioSwitch>
<CheckboxRadioSwitch :checked.sync="hideLogin" type="switch">
{{ t('polls', 'Hide login option in public polls') }}
</CheckboxRadioSwitch>
@@ -97,6 +100,14 @@ export default {
this.writeValue({ showLogin: !value })
},
},
+ useActivity: {
+ get() {
+ return this.appSettings.useActivity
+ },
+ set(value) {
+ this.writeValue({ useActivity: value })
+ },
+ },
autoArchive: {
get() {
return this.appSettings.autoArchive
diff --git a/src/js/components/SideBar/SideBarTabActivity.vue b/src/js/components/SideBar/SideBarTabActivity.vue
new file mode 100644
index 00000000..ec71d0d4
--- /dev/null
+++ b/src/js/components/SideBar/SideBarTabActivity.vue
@@ -0,0 +1,56 @@
+<!--
+ - @copyright Copyright (c) 2018 René Gieling <github@dartcafe.de>
+ -
+ - @author René Gieling <github@dartcafe.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/>.
+ -
+ -->
+
+<template>
+ <div class="comments">
+ <Activities v-if="!showEmptyContent" />
+ <EmptyContent v-else icon="icon-comment">
+ {{ t('polls', 'No activity') }}
+ </EmptyContent>
+ </div>
+</template>
+
+<script>
+import Activities from '../Activity/Activities'
+import { EmptyContent } from '@nextcloud/vue'
+import { mapState } from 'vuex'
+
+export default {
+ name: 'SideBarTabActivity',
+ components: {
+ Activities,
+ EmptyContent,
+ },
+
+ computed: {
+ ...mapState({
+ acl: (state) => state.poll.acl,
+ }),
+
+ showEmptyContent() {
+ return false
+ },
+
+ },
+
+}
+</script>
diff --git a/src/js/mixins/watchPolls.js b/src/js/mixins/watchPolls.js
index df357957..b364e76a 100644
--- a/src/js/mixins/watchPolls.js
+++ b/src/js/mixins/watchPolls.js
@@ -137,7 +137,7 @@ export const watchPolls = {
},
async loadTables(tables) {
- let dispatches = []
+ let dispatches = ['activity/list']
tables.forEach((item) => {
this.lastUpdated = Math.max(item.updated, this.lastUpdated)
diff --git a/src/js/store/modules/activity.js b/src/js/store/modules/activity.js
new file mode 100644
index 00000000..8f2302f1
--- /dev/null
+++ b/src/js/store/modules/activity.js
@@ -0,0 +1,69 @@
+/* jshint esversion: 6 */
+/**
+ * @copyright Copyright (c) 2019 Rene Gieling <github@dartcafe.de>
+ *
+ * @author Rene Gieling <github@dartcafe.de>
+ *
+ * @license AGPL-3.0-or-later
+ *
+ * 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/>.
+ *
+ */
+
+import axios from '@nextcloud/axios'
+import { generateOcsUrl } from '@nextcloud/router'
+
+const defaultActivities = () => ({
+ list: [],
+})
+
+const state = defaultActivities()
+
+const namespaced = true
+
+const mutations = {
+ set(state, payload) {
+ state.list = payload
+ },
+
+ reset(state) {
+ Object.assign(state, defaultActivities())
+ },
+
+ deleteActivities(state, payload) {
+ state.list = state.list.filter((vote) => vote.userId !== payload.userId)
+ },
+
+}
+
+const actions = {
+ async list(context) {
+ const params = new URLSearchParams()
+ params.append('format', 'json')
+ params.append('since', 0)
+ params.append('limit', 50)
+ params.append('object_type', 'poll')
+ params.append('object_id', context.rootState.route.params.id)
+
+ try {
+ const response = await axios.get(generateOcsUrl('apps/activity/api/v2/activity/filter?') + params)
+ context.commit('set', response.data.ocs.data)
+ } catch {
+ context.commit('reset')
+ }
+ },
+
+}
+
+export default { namespaced, state, mutations, actions }
diff --git a/src/js/store/modules/appSettings.js b/src/js/store/modules/appSettings.js
index 9749ba0f..32d412b7 100644
--- a/src/js/store/modules/appSettings.js
+++ b/src/js/store/modules/appSettings.js
@@ -36,6 +36,7 @@ const defaultAppSettings = () => ({
autoArchive: false,
autoArchiveOffset: 30,
updateType: 'longPolling',
+ useActivity: false,
},
})
diff --git a/src/js/views/SideBar.vue b/src/js/views/SideBar.vue
index cb097f63..9533aacc 100644
--- a/src/js/views/SideBar.vue
+++ b/src/js/views/SideBar.vue
@@ -56,6 +56,14 @@
icon="icon-comment">
<SideBarTabComments />
</AppSidebarTab>
+
+ <AppSidebarTab v-if="acl.allowEdit && useActicity"
+ :id="'activity'"
+ :order="4"
+ :name="t('polls', 'Activity')"
+ icon="icon-comment">
+ <SideBarTabActivity />
+ </AppSidebarTab>
</AppSidebar>
</template>
@@ -72,6 +80,7 @@ export default {
SideBarTabComments: () => import('../components/SideBar/SideBarTabComments'),
SideBarTabOptions: () => import('../components/SideBar/SideBarTabOptions'),
SideBarTabShare: () => import('../components/SideBar/SideBarTabShare'),
+ SideBarTabActivity: () => import('../components/SideBar/SideBarTabActivity'),
// SideBarTabUserOptions: () => import('../components/SideBar/SideBarTabUserOptions'),
AppSidebar,
AppSidebarTab,
@@ -88,6 +97,7 @@ export default {
...mapState({
poll: (state) => state.poll,
acl: (state) => state.poll.acl,
+ useActivity: (state) => state.appSettings.useActivity,
}),
},
methods: {