summaryrefslogtreecommitdiffstats
path: root/apps/dav
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dav')
-rw-r--r--apps/dav/appinfo/v1/caldav.php2
-rw-r--r--apps/dav/appinfo/v1/carddav.php3
-rw-r--r--apps/dav/bin/chunkperf.php79
-rw-r--r--apps/dav/composer/composer/autoload_classmap.php6
-rw-r--r--apps/dav/composer/composer/autoload_static.php6
-rw-r--r--apps/dav/l10n/bg.js2
-rw-r--r--apps/dav/l10n/bg.json2
-rw-r--r--apps/dav/l10n/ca.js2
-rw-r--r--apps/dav/l10n/ca.json2
-rw-r--r--apps/dav/l10n/cs.js5
-rw-r--r--apps/dav/l10n/cs.json5
-rw-r--r--apps/dav/l10n/da.js2
-rw-r--r--apps/dav/l10n/da.json2
-rw-r--r--apps/dav/l10n/de.js5
-rw-r--r--apps/dav/l10n/de.json5
-rw-r--r--apps/dav/l10n/de_DE.js5
-rw-r--r--apps/dav/l10n/de_DE.json5
-rw-r--r--apps/dav/l10n/el.js2
-rw-r--r--apps/dav/l10n/el.json2
-rw-r--r--apps/dav/l10n/eo.js2
-rw-r--r--apps/dav/l10n/eo.json2
-rw-r--r--apps/dav/l10n/es.js25
-rw-r--r--apps/dav/l10n/es.json25
-rw-r--r--apps/dav/l10n/eu.js23
-rw-r--r--apps/dav/l10n/eu.json23
-rw-r--r--apps/dav/l10n/fi.js2
-rw-r--r--apps/dav/l10n/fi.json2
-rw-r--r--apps/dav/l10n/fr.js16
-rw-r--r--apps/dav/l10n/fr.json16
-rw-r--r--apps/dav/l10n/gl.js2
-rw-r--r--apps/dav/l10n/gl.json2
-rw-r--r--apps/dav/l10n/he.js2
-rw-r--r--apps/dav/l10n/he.json2
-rw-r--r--apps/dav/l10n/hr.js2
-rw-r--r--apps/dav/l10n/hr.json2
-rw-r--r--apps/dav/l10n/hu.js5
-rw-r--r--apps/dav/l10n/hu.json5
-rw-r--r--apps/dav/l10n/is.js2
-rw-r--r--apps/dav/l10n/is.json2
-rw-r--r--apps/dav/l10n/it.js16
-rw-r--r--apps/dav/l10n/it.json16
-rw-r--r--apps/dav/l10n/ja.js2
-rw-r--r--apps/dav/l10n/ja.json2
-rw-r--r--apps/dav/l10n/ko.js2
-rw-r--r--apps/dav/l10n/ko.json2
-rw-r--r--apps/dav/l10n/lt_LT.js2
-rw-r--r--apps/dav/l10n/lt_LT.json2
-rw-r--r--apps/dav/l10n/mk.js2
-rw-r--r--apps/dav/l10n/mk.json2
-rw-r--r--apps/dav/l10n/nb.js2
-rw-r--r--apps/dav/l10n/nb.json2
-rw-r--r--apps/dav/l10n/nl.js6
-rw-r--r--apps/dav/l10n/nl.json6
-rw-r--r--apps/dav/l10n/pl.js5
-rw-r--r--apps/dav/l10n/pl.json5
-rw-r--r--apps/dav/l10n/pt_BR.js19
-rw-r--r--apps/dav/l10n/pt_BR.json19
-rw-r--r--apps/dav/l10n/ru.js4
-rw-r--r--apps/dav/l10n/ru.json4
-rw-r--r--apps/dav/l10n/sc.js2
-rw-r--r--apps/dav/l10n/sc.json2
-rw-r--r--apps/dav/l10n/sk.js2
-rw-r--r--apps/dav/l10n/sk.json2
-rw-r--r--apps/dav/l10n/sl.js6
-rw-r--r--apps/dav/l10n/sl.json6
-rw-r--r--apps/dav/l10n/sr.js2
-rw-r--r--apps/dav/l10n/sr.json2
-rw-r--r--apps/dav/l10n/sv.js2
-rw-r--r--apps/dav/l10n/sv.json2
-rw-r--r--apps/dav/l10n/tr.js5
-rw-r--r--apps/dav/l10n/tr.json5
-rw-r--r--apps/dav/l10n/uk.js2
-rw-r--r--apps/dav/l10n/uk.json2
-rw-r--r--apps/dav/l10n/zh_CN.js2
-rw-r--r--apps/dav/l10n/zh_CN.json2
-rw-r--r--apps/dav/l10n/zh_HK.js5
-rw-r--r--apps/dav/l10n/zh_HK.json5
-rw-r--r--apps/dav/l10n/zh_TW.js5
-rw-r--r--apps/dav/l10n/zh_TW.json5
-rw-r--r--apps/dav/lib/AppInfo/Application.php114
-rw-r--r--apps/dav/lib/CalDAV/Activity/Backend.php2
-rw-r--r--apps/dav/lib/CalDAV/Activity/Provider/Event.php4
-rw-r--r--apps/dav/lib/CalDAV/CalDavBackend.php122
-rw-r--r--apps/dav/lib/CalDAV/Calendar.php9
-rw-r--r--apps/dav/lib/CalDAV/PublicCalendar.php2
-rw-r--r--apps/dav/lib/CalDAV/Reminder/NotificationProvider/EmailProvider.php11
-rw-r--r--apps/dav/lib/CalDAV/Reminder/ReminderService.php41
-rw-r--r--apps/dav/lib/CalDAV/Schedule/Plugin.php44
-rw-r--r--apps/dav/lib/CalDAV/WebcalCaching/RefreshWebcalService.php52
-rw-r--r--apps/dav/lib/CardDAV/Activity/Backend.php18
-rw-r--r--apps/dav/lib/CardDAV/AddressBookImpl.php3
-rw-r--r--apps/dav/lib/CardDAV/CardDavBackend.php60
-rw-r--r--apps/dav/lib/CardDAV/PhotoCache.php2
-rw-r--r--apps/dav/lib/Command/CreateCalendar.php2
-rw-r--r--apps/dav/lib/Connector/Sabre/CommentPropertiesPlugin.php14
-rw-r--r--apps/dav/lib/Connector/Sabre/ExceptionLoggerPlugin.php11
-rw-r--r--apps/dav/lib/Connector/Sabre/File.php29
-rw-r--r--apps/dav/lib/Connector/Sabre/MaintenancePlugin.php5
-rw-r--r--apps/dav/lib/Events/CalendarPublishedEvent.php13
-rw-r--r--apps/dav/lib/Events/CalendarUnpublishedEvent.php9
-rw-r--r--apps/dav/lib/Exception/ServerMaintenanceMode.php31
-rw-r--r--apps/dav/lib/Listener/BirthdayListener.php54
-rw-r--r--apps/dav/lib/Listener/CalendarPublicationListener.php65
-rw-r--r--apps/dav/lib/Listener/CalendarShareUpdateListener.php62
-rw-r--r--apps/dav/lib/Listener/ClearPhotoCacheListener.php48
-rw-r--r--apps/dav/lib/Listener/SubscriptionListener.php85
-rw-r--r--apps/dav/lib/RootCollection.php7
-rw-r--r--apps/dav/lib/UserMigration/CalendarMigrator.php29
-rw-r--r--apps/dav/lib/UserMigration/ContactsMigrator.php25
-rw-r--r--apps/dav/src/views/Availability.vue27
-rw-r--r--apps/dav/src/views/CalDavSettings.spec.js6
-rw-r--r--apps/dav/src/views/CalDavSettings.vue91
-rw-r--r--apps/dav/src/views/__snapshots__/CalDavSettings.spec.js.snap364
-rw-r--r--apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php8
-rw-r--r--apps/dav/tests/unit/CalDAV/CalDavBackendTest.php9
-rw-r--r--apps/dav/tests/unit/CalDAV/Listener/CalendarPublicationListenerTest.php79
-rw-r--r--apps/dav/tests/unit/CalDAV/Listener/CalendarShareUpdateListenerTest.php70
-rw-r--r--apps/dav/tests/unit/CalDAV/Listener/SubscriptionListenerTest.php95
-rw-r--r--apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php3
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php120
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php30
-rw-r--r--apps/dav/tests/unit/CalDAV/Schedule/PluginTest.php85
-rw-r--r--apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php21
-rw-r--r--apps/dav/tests/unit/CardDAV/Activity/BackendTest.php503
-rw-r--r--apps/dav/tests/unit/CardDAV/CardDavBackendTest.php66
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php7
-rw-r--r--apps/dav/tests/unit/Listener/ActivityUpdaterListenerTest.php104
127 files changed, 2257 insertions, 894 deletions
diff --git a/apps/dav/appinfo/v1/caldav.php b/apps/dav/appinfo/v1/caldav.php
index eccd3186196..1f55266a21f 100644
--- a/apps/dav/appinfo/v1/caldav.php
+++ b/apps/dav/appinfo/v1/caldav.php
@@ -63,7 +63,6 @@ $userManager = \OC::$server->getUserManager();
$random = \OC::$server->getSecureRandom();
$logger = \OC::$server->get(LoggerInterface::class);
$dispatcher = \OC::$server->get(\OCP\EventDispatcher\IEventDispatcher::class);
-$legacyDispatcher = \OC::$server->getEventDispatcher();
$config = \OC::$server->get(\OCP\IConfig::class);
$calDavBackend = new CalDavBackend(
@@ -74,7 +73,6 @@ $calDavBackend = new CalDavBackend(
$random,
$logger,
$dispatcher,
- $legacyDispatcher,
$config,
true
);
diff --git a/apps/dav/appinfo/v1/carddav.php b/apps/dav/appinfo/v1/carddav.php
index 8cf42af9a6c..293ae4293d4 100644
--- a/apps/dav/appinfo/v1/carddav.php
+++ b/apps/dav/appinfo/v1/carddav.php
@@ -8,6 +8,7 @@
* @author John Molakvoæ <skjnldsv@protonmail.com>
* @author Lukas Reschke <lukas@statuscode.ch>
* @author Morris Jobke <hey@morrisjobke.de>
+ * @author Thomas Citharel <nextcloud@tcit.fr>
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @license AGPL-3.0
@@ -62,7 +63,7 @@ $principalBackend = new Principal(
'principals/'
);
$db = \OC::$server->getDatabaseConnection();
-$cardDavBackend = new CardDavBackend($db, $principalBackend, \OC::$server->getUserManager(), \OC::$server->getGroupManager(), \OC::$server->get(\OCP\EventDispatcher\IEventDispatcher::class), \OC::$server->getEventDispatcher());
+$cardDavBackend = new CardDavBackend($db, $principalBackend, \OC::$server->getUserManager(), \OC::$server->getGroupManager(), \OC::$server->get(\OCP\EventDispatcher\IEventDispatcher::class));
$debugging = \OC::$server->getConfig()->getSystemValue('debug', false);
diff --git a/apps/dav/bin/chunkperf.php b/apps/dav/bin/chunkperf.php
deleted file mode 100644
index a8652654bca..00000000000
--- a/apps/dav/bin/chunkperf.php
+++ /dev/null
@@ -1,79 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-require '../../../../3rdparty/autoload.php';
-
-if ($argc !== 6) {
- echo "Invalid number of arguments" . PHP_EOL;
- exit;
-}
-
-/**
- * @param \Sabre\DAV\Client $client
- * @param $uploadUrl
- * @return mixed
- */
-function request($client, $method, $uploadUrl, $data = null, $headers = []) {
- echo "$method $uploadUrl ... ";
- $t0 = microtime(true);
- $result = $client->request($method, $uploadUrl, $data, $headers);
- $t1 = microtime(true);
- echo $result['statusCode'] . " - " . ($t1 - $t0) . ' seconds' . PHP_EOL;
- if (!in_array($result['statusCode'], [200, 201])) {
- echo $result['body'] . PHP_EOL;
- }
- return $result;
-}
-
-$baseUri = $argv[1];
-$userName = $argv[2];
-$password = $argv[3];
-$file = $argv[4];
-$chunkSize = $argv[5] * 1024 * 1024;
-
-$client = new \Sabre\DAV\Client([
- 'baseUri' => $baseUri,
- 'userName' => $userName,
- 'password' => $password
-]);
-
-$transfer = uniqid('transfer', true);
-$uploadUrl = "$baseUri/uploads/$userName/$transfer";
-
-request($client, 'MKCOL', $uploadUrl);
-
-$size = filesize($file);
-$stream = fopen($file, 'r');
-
-$index = 0;
-while (!feof($stream)) {
- request($client, 'PUT', "$uploadUrl/$index", fread($stream, $chunkSize));
- $index++;
-}
-
-$destination = pathinfo($file, PATHINFO_BASENAME);
-//echo "Moving $uploadUrl/.file to it's final destination $baseUri/files/$userName/$destination" . PHP_EOL;
-request($client, 'MOVE', "$uploadUrl/.file", null, [
- 'Destination' => "$baseUri/files/$userName/$destination",
- 'OC-Total-Length' => filesize($file),
- 'X-OC-MTime' => filemtime($file)
-]);
diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php
index 0583b94a86c..f40917fbd01 100644
--- a/apps/dav/composer/composer/autoload_classmap.php
+++ b/apps/dav/composer/composer/autoload_classmap.php
@@ -224,6 +224,7 @@ return array(
'OCA\\DAV\\Events\\SubscriptionCreatedEvent' => $baseDir . '/../lib/Events/SubscriptionCreatedEvent.php',
'OCA\\DAV\\Events\\SubscriptionDeletedEvent' => $baseDir . '/../lib/Events/SubscriptionDeletedEvent.php',
'OCA\\DAV\\Events\\SubscriptionUpdatedEvent' => $baseDir . '/../lib/Events/SubscriptionUpdatedEvent.php',
+ 'OCA\\DAV\\Exception\\ServerMaintenanceMode' => $baseDir . '/../lib/Exception/ServerMaintenanceMode.php',
'OCA\\DAV\\Exception\\UnsupportedLimitOnInitialSyncException' => $baseDir . '/../lib/Exception/UnsupportedLimitOnInitialSyncException.php',
'OCA\\DAV\\Files\\BrowserErrorPagePlugin' => $baseDir . '/../lib/Files/BrowserErrorPagePlugin.php',
'OCA\\DAV\\Files\\FileSearchBackend' => $baseDir . '/../lib/Files/FileSearchBackend.php',
@@ -235,10 +236,15 @@ return array(
'OCA\\DAV\\HookManager' => $baseDir . '/../lib/HookManager.php',
'OCA\\DAV\\Listener\\ActivityUpdaterListener' => $baseDir . '/../lib/Listener/ActivityUpdaterListener.php',
'OCA\\DAV\\Listener\\AddressbookListener' => $baseDir . '/../lib/Listener/AddressbookListener.php',
+ 'OCA\\DAV\\Listener\\BirthdayListener' => $baseDir . '/../lib/Listener/BirthdayListener.php',
'OCA\\DAV\\Listener\\CalendarContactInteractionListener' => $baseDir . '/../lib/Listener/CalendarContactInteractionListener.php',
'OCA\\DAV\\Listener\\CalendarDeletionDefaultUpdaterListener' => $baseDir . '/../lib/Listener/CalendarDeletionDefaultUpdaterListener.php',
'OCA\\DAV\\Listener\\CalendarObjectReminderUpdaterListener' => $baseDir . '/../lib/Listener/CalendarObjectReminderUpdaterListener.php',
+ 'OCA\\DAV\\Listener\\CalendarPublicationListener' => $baseDir . '/../lib/Listener/CalendarPublicationListener.php',
+ 'OCA\\DAV\\Listener\\CalendarShareUpdateListener' => $baseDir . '/../lib/Listener/CalendarShareUpdateListener.php',
'OCA\\DAV\\Listener\\CardListener' => $baseDir . '/../lib/Listener/CardListener.php',
+ 'OCA\\DAV\\Listener\\ClearPhotoCacheListener' => $baseDir . '/../lib/Listener/ClearPhotoCacheListener.php',
+ 'OCA\\DAV\\Listener\\SubscriptionListener' => $baseDir . '/../lib/Listener/SubscriptionListener.php',
'OCA\\DAV\\Migration\\BuildCalendarSearchIndex' => $baseDir . '/../lib/Migration/BuildCalendarSearchIndex.php',
'OCA\\DAV\\Migration\\BuildCalendarSearchIndexBackgroundJob' => $baseDir . '/../lib/Migration/BuildCalendarSearchIndexBackgroundJob.php',
'OCA\\DAV\\Migration\\BuildSocialSearchIndex' => $baseDir . '/../lib/Migration/BuildSocialSearchIndex.php',
diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php
index 301be38246a..60b437c9fac 100644
--- a/apps/dav/composer/composer/autoload_static.php
+++ b/apps/dav/composer/composer/autoload_static.php
@@ -239,6 +239,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Events\\SubscriptionCreatedEvent' => __DIR__ . '/..' . '/../lib/Events/SubscriptionCreatedEvent.php',
'OCA\\DAV\\Events\\SubscriptionDeletedEvent' => __DIR__ . '/..' . '/../lib/Events/SubscriptionDeletedEvent.php',
'OCA\\DAV\\Events\\SubscriptionUpdatedEvent' => __DIR__ . '/..' . '/../lib/Events/SubscriptionUpdatedEvent.php',
+ 'OCA\\DAV\\Exception\\ServerMaintenanceMode' => __DIR__ . '/..' . '/../lib/Exception/ServerMaintenanceMode.php',
'OCA\\DAV\\Exception\\UnsupportedLimitOnInitialSyncException' => __DIR__ . '/..' . '/../lib/Exception/UnsupportedLimitOnInitialSyncException.php',
'OCA\\DAV\\Files\\BrowserErrorPagePlugin' => __DIR__ . '/..' . '/../lib/Files/BrowserErrorPagePlugin.php',
'OCA\\DAV\\Files\\FileSearchBackend' => __DIR__ . '/..' . '/../lib/Files/FileSearchBackend.php',
@@ -250,10 +251,15 @@ class ComposerStaticInitDAV
'OCA\\DAV\\HookManager' => __DIR__ . '/..' . '/../lib/HookManager.php',
'OCA\\DAV\\Listener\\ActivityUpdaterListener' => __DIR__ . '/..' . '/../lib/Listener/ActivityUpdaterListener.php',
'OCA\\DAV\\Listener\\AddressbookListener' => __DIR__ . '/..' . '/../lib/Listener/AddressbookListener.php',
+ 'OCA\\DAV\\Listener\\BirthdayListener' => __DIR__ . '/..' . '/../lib/Listener/BirthdayListener.php',
'OCA\\DAV\\Listener\\CalendarContactInteractionListener' => __DIR__ . '/..' . '/../lib/Listener/CalendarContactInteractionListener.php',
'OCA\\DAV\\Listener\\CalendarDeletionDefaultUpdaterListener' => __DIR__ . '/..' . '/../lib/Listener/CalendarDeletionDefaultUpdaterListener.php',
'OCA\\DAV\\Listener\\CalendarObjectReminderUpdaterListener' => __DIR__ . '/..' . '/../lib/Listener/CalendarObjectReminderUpdaterListener.php',
+ 'OCA\\DAV\\Listener\\CalendarPublicationListener' => __DIR__ . '/..' . '/../lib/Listener/CalendarPublicationListener.php',
+ 'OCA\\DAV\\Listener\\CalendarShareUpdateListener' => __DIR__ . '/..' . '/../lib/Listener/CalendarShareUpdateListener.php',
'OCA\\DAV\\Listener\\CardListener' => __DIR__ . '/..' . '/../lib/Listener/CardListener.php',
+ 'OCA\\DAV\\Listener\\ClearPhotoCacheListener' => __DIR__ . '/..' . '/../lib/Listener/ClearPhotoCacheListener.php',
+ 'OCA\\DAV\\Listener\\SubscriptionListener' => __DIR__ . '/..' . '/../lib/Listener/SubscriptionListener.php',
'OCA\\DAV\\Migration\\BuildCalendarSearchIndex' => __DIR__ . '/..' . '/../lib/Migration/BuildCalendarSearchIndex.php',
'OCA\\DAV\\Migration\\BuildCalendarSearchIndexBackgroundJob' => __DIR__ . '/..' . '/../lib/Migration/BuildCalendarSearchIndexBackgroundJob.php',
'OCA\\DAV\\Migration\\BuildSocialSearchIndex' => __DIR__ . '/..' . '/../lib/Migration/BuildSocialSearchIndex.php',
diff --git a/apps/dav/l10n/bg.js b/apps/dav/l10n/bg.js
index e9fba5286ba..f4842a46d30 100644
--- a/apps/dav/l10n/bg.js
+++ b/apps/dav/l10n/bg.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} сподели календар {calendar} с група {group}",
"You unshared calendar {calendar} from group {group}" : "Отказахте споделянето на календара {calendar} от група {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} отказа споделяне с календар {calendar} от група {group}",
+ "Untitled event" : "Събитие без заглавие",
"{actor} created event {event} in calendar {calendar}" : "{actor} създаде събитие {event} в календар {calendar}",
"You created event {event} in calendar {calendar}" : "Създадохте събитие {event} в календар {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} изтри събитие {event} от календар {calendar}",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "Дата:",
"Where:" : "Къде:",
"Description:" : "Описание:",
- "Untitled event" : "Събитие без заглавие",
"_%n year_::_%n years_" : ["%n години","%d години"],
"_%n month_::_%n months_" : ["%n месеци","%n месеци"],
"_%n day_::_%n days_" : ["%n дни","%n дни"],
diff --git a/apps/dav/l10n/bg.json b/apps/dav/l10n/bg.json
index cfb4220cb5d..3a6ffd3e5fe 100644
--- a/apps/dav/l10n/bg.json
+++ b/apps/dav/l10n/bg.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} сподели календар {calendar} с група {group}",
"You unshared calendar {calendar} from group {group}" : "Отказахте споделянето на календара {calendar} от група {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} отказа споделяне с календар {calendar} от група {group}",
+ "Untitled event" : "Събитие без заглавие",
"{actor} created event {event} in calendar {calendar}" : "{actor} създаде събитие {event} в календар {calendar}",
"You created event {event} in calendar {calendar}" : "Създадохте събитие {event} в календар {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} изтри събитие {event} от календар {calendar}",
@@ -52,7 +53,6 @@
"Date:" : "Дата:",
"Where:" : "Къде:",
"Description:" : "Описание:",
- "Untitled event" : "Събитие без заглавие",
"_%n year_::_%n years_" : ["%n години","%d години"],
"_%n month_::_%n months_" : ["%n месеци","%n месеци"],
"_%n day_::_%n days_" : ["%n дни","%n дни"],
diff --git a/apps/dav/l10n/ca.js b/apps/dav/l10n/ca.js
index 34b52ab1c9e..63d0d35c797 100644
--- a/apps/dav/l10n/ca.js
+++ b/apps/dav/l10n/ca.js
@@ -23,6 +23,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} ha compartit el calendari {calendar} amb el grup {group}",
"You unshared calendar {calendar} from group {group}" : "Heu desactivat el calendari {calendar} del grup {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} calendari no publicat {calendar} del grup {grup}",
+ "Untitled event" : "Esdeveniment sense títol",
"{actor} created event {event} in calendar {calendar}" : "{actor} ha creat l'esdeveniment {event} al calendari {calendar}",
"You created event {event} in calendar {calendar}" : "Heu creat l'esdeveniment {event} al calendari {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} ha suprimit l'esdeveniment {esdeveniment} del calendari {calendar}",
@@ -49,7 +50,6 @@ OC.L10N.register(
"Date:" : "Data:",
"Where:" : "On:",
"Description:" : "Descripció:",
- "Untitled event" : "Esdeveniment sense títol",
"_%n year_::_%n years_" : ["%n any","%n anys"],
"_%n month_::_%n months_" : ["%n mes","%n mesos"],
"_%n day_::_%n days_" : ["%n dia","%n dies"],
diff --git a/apps/dav/l10n/ca.json b/apps/dav/l10n/ca.json
index 7635d06b1cc..0952b65181b 100644
--- a/apps/dav/l10n/ca.json
+++ b/apps/dav/l10n/ca.json
@@ -21,6 +21,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} ha compartit el calendari {calendar} amb el grup {group}",
"You unshared calendar {calendar} from group {group}" : "Heu desactivat el calendari {calendar} del grup {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} calendari no publicat {calendar} del grup {grup}",
+ "Untitled event" : "Esdeveniment sense títol",
"{actor} created event {event} in calendar {calendar}" : "{actor} ha creat l'esdeveniment {event} al calendari {calendar}",
"You created event {event} in calendar {calendar}" : "Heu creat l'esdeveniment {event} al calendari {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} ha suprimit l'esdeveniment {esdeveniment} del calendari {calendar}",
@@ -47,7 +48,6 @@
"Date:" : "Data:",
"Where:" : "On:",
"Description:" : "Descripció:",
- "Untitled event" : "Esdeveniment sense títol",
"_%n year_::_%n years_" : ["%n any","%n anys"],
"_%n month_::_%n months_" : ["%n mes","%n mesos"],
"_%n day_::_%n days_" : ["%n dia","%n dies"],
diff --git a/apps/dav/l10n/cs.js b/apps/dav/l10n/cs.js
index e9406f6c3a2..5dfc5bcd147 100644
--- a/apps/dav/l10n/cs.js
+++ b/apps/dav/l10n/cs.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} nasdílel(a) kalendář {calendar} skupině {group}",
"You unshared calendar {calendar} from group {group}" : "Zrušili jste sdílení kalendáře {calendar} skupině {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} přestal(a) sdílet kalendář {calendar} se skupinou {group}",
+ "Untitled event" : "Událost bez názvu",
"{actor} created event {event} in calendar {calendar}" : "{actor} vytvořil(a) událost {event} v kalendáři {calendar}",
"You created event {event} in calendar {calendar}" : "V kalendáři {calendar} jste vytvořili událost {event}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} z kalendáře {calendar} smazal(a) událost {event}",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "Datum:",
"Where:" : "Kde:",
"Description:" : "Popis:",
- "Untitled event" : "Událost bez názvu",
"_%n year_::_%n years_" : ["%n rok","%n roky","%n let","%n roky"],
"_%n month_::_%n months_" : ["%n měsíc","%n měsíce","%n měsíců","%n měsíce"],
"_%n day_::_%n days_" : ["%n den","%n dny","%n dnů","%n dny"],
@@ -156,6 +156,9 @@ OC.L10N.register(
"Saturday" : "sobota",
"Sunday" : "neděle",
"Save" : "Uložit",
+ "Failed to load availability" : "Nepodařilo se načíst dostupnost",
+ "Saved availability" : "Uložena dostupnost",
+ "Failed to save availability" : "Nepodařilo se uložit dostupnost",
"Calendar server" : "Kalendářový server",
"Send invitations to attendees" : "Poslat pozvánky na adresy účastníků",
"Automatically generate a birthday calendar" : "Automaticky vytvořit kalendář s narozeninami",
diff --git a/apps/dav/l10n/cs.json b/apps/dav/l10n/cs.json
index 66a899594d3..12df93f770d 100644
--- a/apps/dav/l10n/cs.json
+++ b/apps/dav/l10n/cs.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} nasdílel(a) kalendář {calendar} skupině {group}",
"You unshared calendar {calendar} from group {group}" : "Zrušili jste sdílení kalendáře {calendar} skupině {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} přestal(a) sdílet kalendář {calendar} se skupinou {group}",
+ "Untitled event" : "Událost bez názvu",
"{actor} created event {event} in calendar {calendar}" : "{actor} vytvořil(a) událost {event} v kalendáři {calendar}",
"You created event {event} in calendar {calendar}" : "V kalendáři {calendar} jste vytvořili událost {event}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} z kalendáře {calendar} smazal(a) událost {event}",
@@ -52,7 +53,6 @@
"Date:" : "Datum:",
"Where:" : "Kde:",
"Description:" : "Popis:",
- "Untitled event" : "Událost bez názvu",
"_%n year_::_%n years_" : ["%n rok","%n roky","%n let","%n roky"],
"_%n month_::_%n months_" : ["%n měsíc","%n měsíce","%n měsíců","%n měsíce"],
"_%n day_::_%n days_" : ["%n den","%n dny","%n dnů","%n dny"],
@@ -154,6 +154,9 @@
"Saturday" : "sobota",
"Sunday" : "neděle",
"Save" : "Uložit",
+ "Failed to load availability" : "Nepodařilo se načíst dostupnost",
+ "Saved availability" : "Uložena dostupnost",
+ "Failed to save availability" : "Nepodařilo se uložit dostupnost",
"Calendar server" : "Kalendářový server",
"Send invitations to attendees" : "Poslat pozvánky na adresy účastníků",
"Automatically generate a birthday calendar" : "Automaticky vytvořit kalendář s narozeninami",
diff --git a/apps/dav/l10n/da.js b/apps/dav/l10n/da.js
index 2fecf5fe6d8..ec7ca67b4c7 100644
--- a/apps/dav/l10n/da.js
+++ b/apps/dav/l10n/da.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} delte kalenderen {calendar} med gruppen {group}",
"You unshared calendar {calendar} from group {group}" : "Du fjernede delingen af {calendar} fra gruppen {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} fjernede deling af kalenderen {calendar} fra gruppen {group}",
+ "Untitled event" : "Unavngiven begivenhed",
"{actor} created event {event} in calendar {calendar}" : "{actor} oprettede begivenheden {event} i kalenderen {calendar}",
"You created event {event} in calendar {calendar}" : "Du oprettede begivenheden {event} i kalenderen {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} slettede begivenheden {event} fra kalenderen {calendar}",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "Dato:",
"Where:" : "Hvor:",
"Description:" : "Beskrivelse:",
- "Untitled event" : "Unavngiven begivenhed",
"_%n year_::_%n years_" : ["%n år","%n år"],
"_%n month_::_%n months_" : ["%n måned","%n måneder"],
"_%n day_::_%n days_" : ["%n dag","%n dage"],
diff --git a/apps/dav/l10n/da.json b/apps/dav/l10n/da.json
index 1a70d847ccc..56cbfd455cd 100644
--- a/apps/dav/l10n/da.json
+++ b/apps/dav/l10n/da.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} delte kalenderen {calendar} med gruppen {group}",
"You unshared calendar {calendar} from group {group}" : "Du fjernede delingen af {calendar} fra gruppen {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} fjernede deling af kalenderen {calendar} fra gruppen {group}",
+ "Untitled event" : "Unavngiven begivenhed",
"{actor} created event {event} in calendar {calendar}" : "{actor} oprettede begivenheden {event} i kalenderen {calendar}",
"You created event {event} in calendar {calendar}" : "Du oprettede begivenheden {event} i kalenderen {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} slettede begivenheden {event} fra kalenderen {calendar}",
@@ -52,7 +53,6 @@
"Date:" : "Dato:",
"Where:" : "Hvor:",
"Description:" : "Beskrivelse:",
- "Untitled event" : "Unavngiven begivenhed",
"_%n year_::_%n years_" : ["%n år","%n år"],
"_%n month_::_%n months_" : ["%n måned","%n måneder"],
"_%n day_::_%n days_" : ["%n dag","%n dage"],
diff --git a/apps/dav/l10n/de.js b/apps/dav/l10n/de.js
index 3a2898785cf..7f60996b78e 100644
--- a/apps/dav/l10n/de.js
+++ b/apps/dav/l10n/de.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} teilt den Kalender {calendar} mit der Gruppe {group}",
"You unshared calendar {calendar} from group {group}" : "Du teilst den Kalender {calendar} nicht mehr mit der Gruppe {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} teilt den Kalender {calendar} nicht mehr mit der Gruppe {group}",
+ "Untitled event" : "Termin ohne Titel",
"{actor} created event {event} in calendar {calendar}" : "{actor} hat den Termin {event} im Kalender {calendar} erstellt",
"You created event {event} in calendar {calendar}" : "Du hast den Termin {event} im Kalender {calendar} erstellt",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} hat den Termin {event} im Kalender {calendar} gelöscht",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "Datum:",
"Where:" : "Wo:",
"Description:" : "Beschreibung:",
- "Untitled event" : "Termin ohne Titel",
"_%n year_::_%n years_" : ["%n Jahr","%n Jahre"],
"_%n month_::_%n months_" : ["%n Monat","%n Monate"],
"_%n day_::_%n days_" : ["%n Tag","%n Tage"],
@@ -156,6 +156,9 @@ OC.L10N.register(
"Saturday" : "Samstag",
"Sunday" : "Sonntag",
"Save" : "Speichern",
+ "Failed to load availability" : "Fehler beim Laden der Verfügbarkeit",
+ "Saved availability" : "Verfügbarkeit gespeichert",
+ "Failed to save availability" : "Fehler beim Speichern der Verfügbarkeit",
"Calendar server" : "Kalender-Server",
"Send invitations to attendees" : "Einladungen an die Teilnehmer versenden",
"Automatically generate a birthday calendar" : "Automatisch einen Kalender für Geburtstage erstellen",
diff --git a/apps/dav/l10n/de.json b/apps/dav/l10n/de.json
index a02efad8b27..a53bd9f0473 100644
--- a/apps/dav/l10n/de.json
+++ b/apps/dav/l10n/de.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} teilt den Kalender {calendar} mit der Gruppe {group}",
"You unshared calendar {calendar} from group {group}" : "Du teilst den Kalender {calendar} nicht mehr mit der Gruppe {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} teilt den Kalender {calendar} nicht mehr mit der Gruppe {group}",
+ "Untitled event" : "Termin ohne Titel",
"{actor} created event {event} in calendar {calendar}" : "{actor} hat den Termin {event} im Kalender {calendar} erstellt",
"You created event {event} in calendar {calendar}" : "Du hast den Termin {event} im Kalender {calendar} erstellt",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} hat den Termin {event} im Kalender {calendar} gelöscht",
@@ -52,7 +53,6 @@
"Date:" : "Datum:",
"Where:" : "Wo:",
"Description:" : "Beschreibung:",
- "Untitled event" : "Termin ohne Titel",
"_%n year_::_%n years_" : ["%n Jahr","%n Jahre"],
"_%n month_::_%n months_" : ["%n Monat","%n Monate"],
"_%n day_::_%n days_" : ["%n Tag","%n Tage"],
@@ -154,6 +154,9 @@
"Saturday" : "Samstag",
"Sunday" : "Sonntag",
"Save" : "Speichern",
+ "Failed to load availability" : "Fehler beim Laden der Verfügbarkeit",
+ "Saved availability" : "Verfügbarkeit gespeichert",
+ "Failed to save availability" : "Fehler beim Speichern der Verfügbarkeit",
"Calendar server" : "Kalender-Server",
"Send invitations to attendees" : "Einladungen an die Teilnehmer versenden",
"Automatically generate a birthday calendar" : "Automatisch einen Kalender für Geburtstage erstellen",
diff --git a/apps/dav/l10n/de_DE.js b/apps/dav/l10n/de_DE.js
index 677c38aaf82..3c230ad7d00 100644
--- a/apps/dav/l10n/de_DE.js
+++ b/apps/dav/l10n/de_DE.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} teilt den Kalender {calendar} mit der Gruppe {group}",
"You unshared calendar {calendar} from group {group}" : "Sie teilen den Kalender {calendar} nicht mehr mit der Gruppe {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} teilt den Kalender {calendar} nicht mehr mit der Gruppe {group}",
+ "Untitled event" : "Termin ohne Titel",
"{actor} created event {event} in calendar {calendar}" : "{actor} hat den Termin {event} im Kalender {calendar} erstellt",
"You created event {event} in calendar {calendar}" : "Sie haben den Termin {event} im Kalender {calendar} erstellt",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} hat den Termin {event} im Kalender {calendar} gelöscht",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "Datum:",
"Where:" : "Wo:",
"Description:" : "Beschreibung:",
- "Untitled event" : "Termin ohne Titel",
"_%n year_::_%n years_" : ["%n Jahr","%n Jahre"],
"_%n month_::_%n months_" : ["%n Monat","%n Monate"],
"_%n day_::_%n days_" : ["%n Tag","%n Tage"],
@@ -156,6 +156,9 @@ OC.L10N.register(
"Saturday" : "Samstag",
"Sunday" : "Sonntag",
"Save" : "Speichern",
+ "Failed to load availability" : "Laden der Verfügbarkeit fehlgeschlagen",
+ "Saved availability" : "Verfügbarkeit gespeichert",
+ "Failed to save availability" : "Fehler beim Speichern der Verfügbarkeit",
"Calendar server" : "Kalender-Server",
"Send invitations to attendees" : "Einladungen an die Teilnehmer versenden",
"Automatically generate a birthday calendar" : "Automatisch einen Kalender für Geburtstage erstellen",
diff --git a/apps/dav/l10n/de_DE.json b/apps/dav/l10n/de_DE.json
index ea3c15aa90f..9921f64e22b 100644
--- a/apps/dav/l10n/de_DE.json
+++ b/apps/dav/l10n/de_DE.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} teilt den Kalender {calendar} mit der Gruppe {group}",
"You unshared calendar {calendar} from group {group}" : "Sie teilen den Kalender {calendar} nicht mehr mit der Gruppe {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} teilt den Kalender {calendar} nicht mehr mit der Gruppe {group}",
+ "Untitled event" : "Termin ohne Titel",
"{actor} created event {event} in calendar {calendar}" : "{actor} hat den Termin {event} im Kalender {calendar} erstellt",
"You created event {event} in calendar {calendar}" : "Sie haben den Termin {event} im Kalender {calendar} erstellt",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} hat den Termin {event} im Kalender {calendar} gelöscht",
@@ -52,7 +53,6 @@
"Date:" : "Datum:",
"Where:" : "Wo:",
"Description:" : "Beschreibung:",
- "Untitled event" : "Termin ohne Titel",
"_%n year_::_%n years_" : ["%n Jahr","%n Jahre"],
"_%n month_::_%n months_" : ["%n Monat","%n Monate"],
"_%n day_::_%n days_" : ["%n Tag","%n Tage"],
@@ -154,6 +154,9 @@
"Saturday" : "Samstag",
"Sunday" : "Sonntag",
"Save" : "Speichern",
+ "Failed to load availability" : "Laden der Verfügbarkeit fehlgeschlagen",
+ "Saved availability" : "Verfügbarkeit gespeichert",
+ "Failed to save availability" : "Fehler beim Speichern der Verfügbarkeit",
"Calendar server" : "Kalender-Server",
"Send invitations to attendees" : "Einladungen an die Teilnehmer versenden",
"Automatically generate a birthday calendar" : "Automatisch einen Kalender für Geburtstage erstellen",
diff --git a/apps/dav/l10n/el.js b/apps/dav/l10n/el.js
index 84f5dcf04f3..e9a8c403943 100644
--- a/apps/dav/l10n/el.js
+++ b/apps/dav/l10n/el.js
@@ -23,6 +23,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "Ο {actor} διαμοιράστηκε το ημερολόγιο {calendar} με την ομάδα {group}",
"You unshared calendar {calendar} from group {group}" : "Σταματήσατε τον διαμοιρασμό του ημερολογίου {calendar} από την ομάδα {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} σταμάτησε το διαμοιρασμένο ημερολόγιο {calendar} από την ομάδα {group}",
+ "Untitled event" : "Συμβάν χωρίς τίτλο",
"{actor} created event {event} in calendar {calendar}" : "Ο {actor} δημιούργησε το γεγονός {event} στο ημερολόγιο {calendar}",
"You created event {event} in calendar {calendar}" : "Δημιουργήσατε το γεγονός {event} στο ημερολόγιο {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "Ο {actor} διέγραψε το γεγονός {event} από το ημερολόγιο {calendar}",
@@ -49,7 +50,6 @@ OC.L10N.register(
"Date:" : "Ημερομηνία:",
"Where:" : "Που:",
"Description:" : "Περιγραφή:",
- "Untitled event" : "Συμβάν χωρίς τίτλο",
"_%n year_::_%n years_" : ["%n χρόνος/χρονιά","%n χρόνια"],
"_%n month_::_%n months_" : ["%n μήνας","%d μήνες"],
"_%n day_::_%n days_" : ["%n ημέρα","%n ημέρες"],
diff --git a/apps/dav/l10n/el.json b/apps/dav/l10n/el.json
index 523c7d7ef08..79151b2d754 100644
--- a/apps/dav/l10n/el.json
+++ b/apps/dav/l10n/el.json
@@ -21,6 +21,7 @@
"{actor} shared calendar {calendar} with group {group}" : "Ο {actor} διαμοιράστηκε το ημερολόγιο {calendar} με την ομάδα {group}",
"You unshared calendar {calendar} from group {group}" : "Σταματήσατε τον διαμοιρασμό του ημερολογίου {calendar} από την ομάδα {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} σταμάτησε το διαμοιρασμένο ημερολόγιο {calendar} από την ομάδα {group}",
+ "Untitled event" : "Συμβάν χωρίς τίτλο",
"{actor} created event {event} in calendar {calendar}" : "Ο {actor} δημιούργησε το γεγονός {event} στο ημερολόγιο {calendar}",
"You created event {event} in calendar {calendar}" : "Δημιουργήσατε το γεγονός {event} στο ημερολόγιο {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "Ο {actor} διέγραψε το γεγονός {event} από το ημερολόγιο {calendar}",
@@ -47,7 +48,6 @@
"Date:" : "Ημερομηνία:",
"Where:" : "Που:",
"Description:" : "Περιγραφή:",
- "Untitled event" : "Συμβάν χωρίς τίτλο",
"_%n year_::_%n years_" : ["%n χρόνος/χρονιά","%n χρόνια"],
"_%n month_::_%n months_" : ["%n μήνας","%d μήνες"],
"_%n day_::_%n days_" : ["%n ημέρα","%n ημέρες"],
diff --git a/apps/dav/l10n/eo.js b/apps/dav/l10n/eo.js
index f17ea331a7f..63861008c39 100644
--- a/apps/dav/l10n/eo.js
+++ b/apps/dav/l10n/eo.js
@@ -23,6 +23,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} kunhavigis kalendaron {calendar} kun grupo {group}",
"You unshared calendar {calendar} from group {group}" : "Vi malkunhavigis kalendaron {calendar} kun grupo {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} malkunhavigis kalendaron {calendar} kun grupo {group}",
+ "Untitled event" : "Sentitola okazaĵo",
"{actor} created event {event} in calendar {calendar}" : "{actor} kreis okazaĵon {event} en kalendaro {calendar}",
"You created event {event} in calendar {calendar}" : "Vi kreis okazaĵon {event} en kalendaro {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} forigis okazaĵon {event} en kalendaro {calendar}",
@@ -49,7 +50,6 @@ OC.L10N.register(
"Date:" : "Dato:",
"Where:" : "Kie:",
"Description:" : "Priskribo:",
- "Untitled event" : "Sentitola okazaĵo",
"_%n year_::_%n years_" : ["%n jaro","%n jaroj"],
"_%n month_::_%n months_" : ["%n monato","%n monatoj"],
"_%n day_::_%n days_" : ["%n tago","%n tagoj"],
diff --git a/apps/dav/l10n/eo.json b/apps/dav/l10n/eo.json
index 3f616e499b4..2eb6017f344 100644
--- a/apps/dav/l10n/eo.json
+++ b/apps/dav/l10n/eo.json
@@ -21,6 +21,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} kunhavigis kalendaron {calendar} kun grupo {group}",
"You unshared calendar {calendar} from group {group}" : "Vi malkunhavigis kalendaron {calendar} kun grupo {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} malkunhavigis kalendaron {calendar} kun grupo {group}",
+ "Untitled event" : "Sentitola okazaĵo",
"{actor} created event {event} in calendar {calendar}" : "{actor} kreis okazaĵon {event} en kalendaro {calendar}",
"You created event {event} in calendar {calendar}" : "Vi kreis okazaĵon {event} en kalendaro {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} forigis okazaĵon {event} en kalendaro {calendar}",
@@ -47,7 +48,6 @@
"Date:" : "Dato:",
"Where:" : "Kie:",
"Description:" : "Priskribo:",
- "Untitled event" : "Sentitola okazaĵo",
"_%n year_::_%n years_" : ["%n jaro","%n jaroj"],
"_%n month_::_%n months_" : ["%n monato","%n monatoj"],
"_%n day_::_%n days_" : ["%n tago","%n tagoj"],
diff --git a/apps/dav/l10n/es.js b/apps/dav/l10n/es.js
index 027fe077699..375abc0f62b 100644
--- a/apps/dav/l10n/es.js
+++ b/apps/dav/l10n/es.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
"You unshared calendar {calendar} from group {group}" : "Usted dejó de compartir el calendario {calendar} del grupo {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendario {calendar} del grupo {group}",
+ "Untitled event" : "Evento sin título",
"{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
"You created event {event} in calendar {calendar}" : "Usted creó el evento {event} en el calendario {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} eliminó el evento {event} del calendario {calendar}",
@@ -54,12 +55,11 @@ OC.L10N.register(
"Date:" : "Fecha:",
"Where:" : "Dónde:",
"Description:" : "Descripción:",
- "Untitled event" : "Evento sin título",
- "_%n year_::_%n years_" : ["%n año","%n años"],
- "_%n month_::_%n months_" : ["%n mes","%n meses"],
- "_%n day_::_%n days_" : ["%n día","%n días"],
- "_%n hour_::_%n hours_" : ["%n hora","%n horas"],
- "_%n minute_::_%n minutes_" : ["%n minuto","%n minutos"],
+ "_%n year_::_%n years_" : ["%n año","%n años","%n años"],
+ "_%n month_::_%n months_" : ["%n mes","%n meses","%n meses"],
+ "_%n day_::_%n days_" : ["%n día","%n días","%n días"],
+ "_%n hour_::_%n hours_" : ["%n hora","%n horas","%n horas"],
+ "_%n minute_::_%n minutes_" : ["%n minuto","%n minutos","%n minutos"],
"%s (in %s)" : "%s (en %s)",
"%s (%s ago)" : "%s (hace %s)",
"Calendar: %s" : "Calendario: %s",
@@ -109,15 +109,21 @@ OC.L10N.register(
"You updated contact {card} in address book {addressbook}" : "Has actualizado el contacto {card} en la libreta de direcciones {addressbook}",
"A <strong>contact</strong> or <strong>address book</strong> was modified" : "Se ha modificado un <strong>contacto</strong> o una <strong>libreta de direcciones</strong> ",
"File is not updatable: %1$s" : "El archivo no se puede actualizar: %1$s",
+ "Could not write to final file, canceled by hook" : "No se pudo escribir en el archivo final, cancelado por el sistema.",
"Could not write file contents" : "No se han podido escribir los contenidos del archivo",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
+ "_%n byte_::_%n bytes_" : ["%n byte","%n bytes","%n bytes"],
"Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Error al copiar el archivo al destino (copiado: %1$s, tamaño esperado: %2$s)",
+ "Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side." : "Se esperaba un tamaño de archivo de %1$s pero se leyó (desde el cliente Nextcloud) y se escribió (en el almacenamiento Nextcloud) %2$s. Podría ser un problema de red en el lado del envío o un problema de escritura en el almacenamiento en el lado del servidor.",
+ "Could not rename part file to final file, canceled by hook" : "No se pudo escribir en el archivo final, cancelado por el sistema.",
"Could not rename part file to final file" : "No se ha podido renombrar el archivo parcial como el archivo final",
"Failed to check file size: %1$s" : "Fallo al comprobar el tamaño del archivo: %1$s",
"Could not open file" : "No se ha podido abrir el archivo",
+ "Encryption not ready: %1$s" : "El cifrado no está listo: %1$s",
"Failed to open file: %1$s" : "Fallo al abrir el archivo: %1$s",
"Failed to unlink: %1$s" : "Fallo al desenlazar: %1$s",
+ "Invalid chunk name" : "Nombre de trozo inválido",
"Could not rename part file assembled from chunks" : "No se ha podido renombrar el archivo parcial formado por los fragmentos",
+ "Failed to write file contents: %1$s" : "Fallo al escribir el contenido del archivo: %1$s",
"File not found: %1$s" : "Archivo no encontrado: %1$s",
"System is in maintenance mode." : "Sistema está en modo de mantenimiento.",
"Upgrade needed" : "Se necesita actualizar",
@@ -150,6 +156,9 @@ OC.L10N.register(
"Saturday" : "Sábado",
"Sunday" : "Domingo",
"Save" : "Guardar",
+ "Failed to load availability" : "No se ha podido cargar la disponibilidad",
+ "Saved availability" : "Disponibilidad guardada",
+ "Failed to save availability" : "No se ha podido guardar la disponibilidad",
"Calendar server" : "Servidor de calendario",
"Send invitations to attendees" : "Enviar invitaciones a los asistentes",
"Automatically generate a birthday calendar" : "Generar automáticamente un calendario de cumpleaños",
@@ -170,4 +179,4 @@ OC.L10N.register(
"Comment" : "Comentario",
"Your attendance was updated successfully." : "Tu asistencia se ha actualizado con éxito."
},
-"nplurals=2; plural=(n != 1);");
+"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/dav/l10n/es.json b/apps/dav/l10n/es.json
index 70e1da43123..350c64df063 100644
--- a/apps/dav/l10n/es.json
+++ b/apps/dav/l10n/es.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
"You unshared calendar {calendar} from group {group}" : "Usted dejó de compartir el calendario {calendar} del grupo {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendario {calendar} del grupo {group}",
+ "Untitled event" : "Evento sin título",
"{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
"You created event {event} in calendar {calendar}" : "Usted creó el evento {event} en el calendario {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} eliminó el evento {event} del calendario {calendar}",
@@ -52,12 +53,11 @@
"Date:" : "Fecha:",
"Where:" : "Dónde:",
"Description:" : "Descripción:",
- "Untitled event" : "Evento sin título",
- "_%n year_::_%n years_" : ["%n año","%n años"],
- "_%n month_::_%n months_" : ["%n mes","%n meses"],
- "_%n day_::_%n days_" : ["%n día","%n días"],
- "_%n hour_::_%n hours_" : ["%n hora","%n horas"],
- "_%n minute_::_%n minutes_" : ["%n minuto","%n minutos"],
+ "_%n year_::_%n years_" : ["%n año","%n años","%n años"],
+ "_%n month_::_%n months_" : ["%n mes","%n meses","%n meses"],
+ "_%n day_::_%n days_" : ["%n día","%n días","%n días"],
+ "_%n hour_::_%n hours_" : ["%n hora","%n horas","%n horas"],
+ "_%n minute_::_%n minutes_" : ["%n minuto","%n minutos","%n minutos"],
"%s (in %s)" : "%s (en %s)",
"%s (%s ago)" : "%s (hace %s)",
"Calendar: %s" : "Calendario: %s",
@@ -107,15 +107,21 @@
"You updated contact {card} in address book {addressbook}" : "Has actualizado el contacto {card} en la libreta de direcciones {addressbook}",
"A <strong>contact</strong> or <strong>address book</strong> was modified" : "Se ha modificado un <strong>contacto</strong> o una <strong>libreta de direcciones</strong> ",
"File is not updatable: %1$s" : "El archivo no se puede actualizar: %1$s",
+ "Could not write to final file, canceled by hook" : "No se pudo escribir en el archivo final, cancelado por el sistema.",
"Could not write file contents" : "No se han podido escribir los contenidos del archivo",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
+ "_%n byte_::_%n bytes_" : ["%n byte","%n bytes","%n bytes"],
"Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Error al copiar el archivo al destino (copiado: %1$s, tamaño esperado: %2$s)",
+ "Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side." : "Se esperaba un tamaño de archivo de %1$s pero se leyó (desde el cliente Nextcloud) y se escribió (en el almacenamiento Nextcloud) %2$s. Podría ser un problema de red en el lado del envío o un problema de escritura en el almacenamiento en el lado del servidor.",
+ "Could not rename part file to final file, canceled by hook" : "No se pudo escribir en el archivo final, cancelado por el sistema.",
"Could not rename part file to final file" : "No se ha podido renombrar el archivo parcial como el archivo final",
"Failed to check file size: %1$s" : "Fallo al comprobar el tamaño del archivo: %1$s",
"Could not open file" : "No se ha podido abrir el archivo",
+ "Encryption not ready: %1$s" : "El cifrado no está listo: %1$s",
"Failed to open file: %1$s" : "Fallo al abrir el archivo: %1$s",
"Failed to unlink: %1$s" : "Fallo al desenlazar: %1$s",
+ "Invalid chunk name" : "Nombre de trozo inválido",
"Could not rename part file assembled from chunks" : "No se ha podido renombrar el archivo parcial formado por los fragmentos",
+ "Failed to write file contents: %1$s" : "Fallo al escribir el contenido del archivo: %1$s",
"File not found: %1$s" : "Archivo no encontrado: %1$s",
"System is in maintenance mode." : "Sistema está en modo de mantenimiento.",
"Upgrade needed" : "Se necesita actualizar",
@@ -148,6 +154,9 @@
"Saturday" : "Sábado",
"Sunday" : "Domingo",
"Save" : "Guardar",
+ "Failed to load availability" : "No se ha podido cargar la disponibilidad",
+ "Saved availability" : "Disponibilidad guardada",
+ "Failed to save availability" : "No se ha podido guardar la disponibilidad",
"Calendar server" : "Servidor de calendario",
"Send invitations to attendees" : "Enviar invitaciones a los asistentes",
"Automatically generate a birthday calendar" : "Generar automáticamente un calendario de cumpleaños",
@@ -167,5 +176,5 @@
"Number of guests" : "Número de invitados",
"Comment" : "Comentario",
"Your attendance was updated successfully." : "Tu asistencia se ha actualizado con éxito."
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
+},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
} \ No newline at end of file
diff --git a/apps/dav/l10n/eu.js b/apps/dav/l10n/eu.js
index 09931f17cd1..d9e0da425a1 100644
--- a/apps/dav/l10n/eu.js
+++ b/apps/dav/l10n/eu.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} {group} taldearekin {calendar} egutegia partekatu du",
"You unshared calendar {calendar} from group {group}" : "{group} taldearekin {calendar} egutegia partekatzeari utzi dio.",
"{actor} unshared calendar {calendar} from group {group}" : "{actor}-rk {group} taldearekin {calendar} egutegia partekatzeari utzi dio.",
+ "Untitled event" : "Izenik gabeko gertaera",
"{actor} created event {event} in calendar {calendar}" : "{actor} erabiltzaileak {event} gertaera sortu du {calendar} egutegian.",
"You created event {event} in calendar {calendar}" : "{calendar} egutegian {event} gertaera sortu duzu",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} erabiltzaileak {event} gertaera ezabatu du {calendar} egutegitik",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "Data:",
"Where:" : "Non:",
"Description:" : "Deskribapena:",
- "Untitled event" : "Izenik gabeko gertaera",
"_%n year_::_%n years_" : ["Urte %n","%n urte"],
"_%n month_::_%n months_" : ["Hilabete %n","%n hilabete"],
"_%n day_::_%n days_" : ["Egun %n","%n egun"],
@@ -108,9 +108,23 @@ OC.L10N.register(
"{actor} updated contact {card} in address book {addressbook}" : "{actor}-(e)k eguneratu du {card} kontaktua {addressbook} helbide-liburuan",
"You updated contact {card} in address book {addressbook}" : "Eguneratu duzu {card} kontaktua {addressbook} helbide-liburuan",
"A <strong>contact</strong> or <strong>address book</strong> was modified" : "<strong>kontaktu</strong> edo <strong>helbide-liburu</strong>bat aldatu da",
+ "File is not updatable: %1$s" : "Fitxategia ez da eguneragarria: %1$s",
+ "Could not write to final file, canceled by hook" : "Ezin izan da azken fitxategian idatzi, kakoaren bidez bertan behera utzi da",
"Could not write file contents" : "Ezin izan dira fitxategiaren edukiak idatzi",
"_%n byte_::_%n bytes_" : ["Byte %n","%n byte"],
+ "Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Errore bat gertatu da fitxategia helburuko kokapenera kopiatzean (kopiatua: %1$s, espero den fitxategiaren tamaina: %2$s)",
+ "Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side." : "%1$sfitxategi-tamaina espero zen baina irakurri (Nextcloud bezerotik) eta idatzita (Nextcloud biltegian) %2$s. Bidaltzailearen aldean sareko arazo bat izan daiteke edo zerbitzariaren biltegian idazteko arazo bat izan daiteke.",
+ "Could not rename part file to final file, canceled by hook" : "Ezin izan da zati-fitxategiaren izena aldatu azken fitxategira, kakoaren bidez bertan behera utzi da",
+ "Could not rename part file to final file" : "Ezin izan da zatiaren fitxategia azken fitxategira aldatu",
+ "Failed to check file size: %1$s" : "Ezin izan da egiaztatu fitxategiaren tamaina:%1$s",
"Could not open file" : "Ezin izan da fitxategia ireki",
+ "Encryption not ready: %1$s" : "Enkriptatzea ez dago prest:%1$s",
+ "Failed to open file: %1$s" : "Ezin izan da fitxategia ireki:%1$s",
+ "Failed to unlink: %1$s" : "Ezin izan da deskonektatu:%1$s",
+ "Invalid chunk name" : "Zati izen baliogabea",
+ "Could not rename part file assembled from chunks" : "Ezin izan da zati-fitxategiaren izena aldatu zenbait zatiz osatuta dagoelako",
+ "Failed to write file contents: %1$s" : "Ezin izan dira fitxategiaren edukiak idatzi:%1$s",
+ "File not found: %1$s" : "Ez da fitxategirik aurkitu:%1$s",
"System is in maintenance mode." : "Sistema mantentze moduan dago.",
"Upgrade needed" : "Bertsio-berritzea beharrezkoa",
"Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Zure %s HTTPS erabiltzeko konfiguratu behar da CalDAV eta CardDAV erabiltzeko iOS eta macOSrekin.",
@@ -122,6 +136,8 @@ OC.L10N.register(
"Completed on %s" : "%s-an osatua",
"Due on %s by %s" : "%s-(e)tik %s-(e)an epemuga",
"Due on %s" : "%s-(e)an epemuga",
+ "Migrated calendar (%1$s)" : "Migratutako egutegia (%1$s)",
+ "Calendars including events, details and attendees" : "Egutegiak, ekitaldiak, xehetasunak eta parte-hartzaileak barne ditu",
"Contacts and groups" : "Kontaktuak eta taldeak",
"WebDAV" : "WebDAV",
"WebDAV endpoint" : "WebDAV amaiera-puntua",
@@ -140,6 +156,9 @@ OC.L10N.register(
"Saturday" : "Larunbata",
"Sunday" : "Igandea",
"Save" : "Gorde",
+ "Failed to load availability" : "Ezin izan da kargatu erabilgarritasuna",
+ "Saved availability" : "Gordetako erabilgarritasuna",
+ "Failed to save availability" : "Ezin izan da gorde erabilgarritasuna",
"Calendar server" : "Egutegi-zerbitzaria",
"Send invitations to attendees" : "Gonbidatutakoei gonbidapenak bidali",
"Automatically generate a birthday calendar" : "Automatikoki sortu urtebetetzeen egutegia",
@@ -147,6 +166,8 @@ OC.L10N.register(
"Hence they will not be available immediately after enabling but will show up after some time." : "Beraz ez dira gaitu ostean agertuko baina denbora pasa ahala agertuko dira.",
"Send notifications for events" : "Bidali jakinarazpenak gertaerentzako",
"Notifications are sent via background jobs, so these must occur often enough." : "Jakinarazpenak atzealdeko lanen bidez bidaliko dira, beraz sarri gertatu behar dira.",
+ "Send reminder notifications to calendar sharees as well" : "Bidali abisuaren jakinarazpenak egutegi partekatzeetara ere",
+ "Reminders are always sent to organizers and attendees." : "Abisuak beti bidaltzen zaizkie antolatzaileei eta bertaratutakoei.",
"Enable notifications for events via push" : "Gaitu push bidezko jakinarazpenak gertaerentzat",
"Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Instalatu ezazu {calendarappstoreopen}Egutegi aplikazioa{linkclose} ere, edo {calendardocopen}konektatu zure ordenagailua eta mugikorra sinkronizatzeko ↗{linkclose}.",
"Please make sure to properly set up {emailopen}the email server{linkclose}." : "Mesedez egiaztatu {emailopen}posta elektroniko zerbitzaria{linkclose} ondo konfiguratuta dagoela.",
diff --git a/apps/dav/l10n/eu.json b/apps/dav/l10n/eu.json
index 83384237f8b..bda903e0899 100644
--- a/apps/dav/l10n/eu.json
+++ b/apps/dav/l10n/eu.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} {group} taldearekin {calendar} egutegia partekatu du",
"You unshared calendar {calendar} from group {group}" : "{group} taldearekin {calendar} egutegia partekatzeari utzi dio.",
"{actor} unshared calendar {calendar} from group {group}" : "{actor}-rk {group} taldearekin {calendar} egutegia partekatzeari utzi dio.",
+ "Untitled event" : "Izenik gabeko gertaera",
"{actor} created event {event} in calendar {calendar}" : "{actor} erabiltzaileak {event} gertaera sortu du {calendar} egutegian.",
"You created event {event} in calendar {calendar}" : "{calendar} egutegian {event} gertaera sortu duzu",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} erabiltzaileak {event} gertaera ezabatu du {calendar} egutegitik",
@@ -52,7 +53,6 @@
"Date:" : "Data:",
"Where:" : "Non:",
"Description:" : "Deskribapena:",
- "Untitled event" : "Izenik gabeko gertaera",
"_%n year_::_%n years_" : ["Urte %n","%n urte"],
"_%n month_::_%n months_" : ["Hilabete %n","%n hilabete"],
"_%n day_::_%n days_" : ["Egun %n","%n egun"],
@@ -106,9 +106,23 @@
"{actor} updated contact {card} in address book {addressbook}" : "{actor}-(e)k eguneratu du {card} kontaktua {addressbook} helbide-liburuan",
"You updated contact {card} in address book {addressbook}" : "Eguneratu duzu {card} kontaktua {addressbook} helbide-liburuan",
"A <strong>contact</strong> or <strong>address book</strong> was modified" : "<strong>kontaktu</strong> edo <strong>helbide-liburu</strong>bat aldatu da",
+ "File is not updatable: %1$s" : "Fitxategia ez da eguneragarria: %1$s",
+ "Could not write to final file, canceled by hook" : "Ezin izan da azken fitxategian idatzi, kakoaren bidez bertan behera utzi da",
"Could not write file contents" : "Ezin izan dira fitxategiaren edukiak idatzi",
"_%n byte_::_%n bytes_" : ["Byte %n","%n byte"],
+ "Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Errore bat gertatu da fitxategia helburuko kokapenera kopiatzean (kopiatua: %1$s, espero den fitxategiaren tamaina: %2$s)",
+ "Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side." : "%1$sfitxategi-tamaina espero zen baina irakurri (Nextcloud bezerotik) eta idatzita (Nextcloud biltegian) %2$s. Bidaltzailearen aldean sareko arazo bat izan daiteke edo zerbitzariaren biltegian idazteko arazo bat izan daiteke.",
+ "Could not rename part file to final file, canceled by hook" : "Ezin izan da zati-fitxategiaren izena aldatu azken fitxategira, kakoaren bidez bertan behera utzi da",
+ "Could not rename part file to final file" : "Ezin izan da zatiaren fitxategia azken fitxategira aldatu",
+ "Failed to check file size: %1$s" : "Ezin izan da egiaztatu fitxategiaren tamaina:%1$s",
"Could not open file" : "Ezin izan da fitxategia ireki",
+ "Encryption not ready: %1$s" : "Enkriptatzea ez dago prest:%1$s",
+ "Failed to open file: %1$s" : "Ezin izan da fitxategia ireki:%1$s",
+ "Failed to unlink: %1$s" : "Ezin izan da deskonektatu:%1$s",
+ "Invalid chunk name" : "Zati izen baliogabea",
+ "Could not rename part file assembled from chunks" : "Ezin izan da zati-fitxategiaren izena aldatu zenbait zatiz osatuta dagoelako",
+ "Failed to write file contents: %1$s" : "Ezin izan dira fitxategiaren edukiak idatzi:%1$s",
+ "File not found: %1$s" : "Ez da fitxategirik aurkitu:%1$s",
"System is in maintenance mode." : "Sistema mantentze moduan dago.",
"Upgrade needed" : "Bertsio-berritzea beharrezkoa",
"Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Zure %s HTTPS erabiltzeko konfiguratu behar da CalDAV eta CardDAV erabiltzeko iOS eta macOSrekin.",
@@ -120,6 +134,8 @@
"Completed on %s" : "%s-an osatua",
"Due on %s by %s" : "%s-(e)tik %s-(e)an epemuga",
"Due on %s" : "%s-(e)an epemuga",
+ "Migrated calendar (%1$s)" : "Migratutako egutegia (%1$s)",
+ "Calendars including events, details and attendees" : "Egutegiak, ekitaldiak, xehetasunak eta parte-hartzaileak barne ditu",
"Contacts and groups" : "Kontaktuak eta taldeak",
"WebDAV" : "WebDAV",
"WebDAV endpoint" : "WebDAV amaiera-puntua",
@@ -138,6 +154,9 @@
"Saturday" : "Larunbata",
"Sunday" : "Igandea",
"Save" : "Gorde",
+ "Failed to load availability" : "Ezin izan da kargatu erabilgarritasuna",
+ "Saved availability" : "Gordetako erabilgarritasuna",
+ "Failed to save availability" : "Ezin izan da gorde erabilgarritasuna",
"Calendar server" : "Egutegi-zerbitzaria",
"Send invitations to attendees" : "Gonbidatutakoei gonbidapenak bidali",
"Automatically generate a birthday calendar" : "Automatikoki sortu urtebetetzeen egutegia",
@@ -145,6 +164,8 @@
"Hence they will not be available immediately after enabling but will show up after some time." : "Beraz ez dira gaitu ostean agertuko baina denbora pasa ahala agertuko dira.",
"Send notifications for events" : "Bidali jakinarazpenak gertaerentzako",
"Notifications are sent via background jobs, so these must occur often enough." : "Jakinarazpenak atzealdeko lanen bidez bidaliko dira, beraz sarri gertatu behar dira.",
+ "Send reminder notifications to calendar sharees as well" : "Bidali abisuaren jakinarazpenak egutegi partekatzeetara ere",
+ "Reminders are always sent to organizers and attendees." : "Abisuak beti bidaltzen zaizkie antolatzaileei eta bertaratutakoei.",
"Enable notifications for events via push" : "Gaitu push bidezko jakinarazpenak gertaerentzat",
"Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Instalatu ezazu {calendarappstoreopen}Egutegi aplikazioa{linkclose} ere, edo {calendardocopen}konektatu zure ordenagailua eta mugikorra sinkronizatzeko ↗{linkclose}.",
"Please make sure to properly set up {emailopen}the email server{linkclose}." : "Mesedez egiaztatu {emailopen}posta elektroniko zerbitzaria{linkclose} ondo konfiguratuta dagoela.",
diff --git a/apps/dav/l10n/fi.js b/apps/dav/l10n/fi.js
index c40748c2141..07a8eb95b8d 100644
--- a/apps/dav/l10n/fi.js
+++ b/apps/dav/l10n/fi.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} jakoi kalenterin {calendar} ryhmälle {group}",
"You unshared calendar {calendar} from group {group}" : "Lopetit kalenterin {calendar} jakamisen ryhmälle {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} lopetti kalenterin {calendar} jakamisen ryhmälle {group}",
+ "Untitled event" : "Nimetön tapahtuma",
"{actor} created event {event} in calendar {calendar}" : "{actor} loi tapahtuman {event} kalenteriin {calendar}",
"You created event {event} in calendar {calendar}" : "Loit tapahtuman {event} kalenteriin {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} poisti tapahtuman {event} kalenterista {calendar}",
@@ -52,7 +53,6 @@ OC.L10N.register(
"Date:" : "Päiväys:",
"Where:" : "Missä:",
"Description:" : "Kuvaus:",
- "Untitled event" : "Nimetön tapahtuma",
"_%n year_::_%n years_" : ["%n vuosi","%n vuotta"],
"_%n month_::_%n months_" : ["%n kuukausi","%n kuukautta"],
"_%n day_::_%n days_" : ["%n päivä","%n päivää"],
diff --git a/apps/dav/l10n/fi.json b/apps/dav/l10n/fi.json
index 47e7fd9a9e6..5398895b76f 100644
--- a/apps/dav/l10n/fi.json
+++ b/apps/dav/l10n/fi.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} jakoi kalenterin {calendar} ryhmälle {group}",
"You unshared calendar {calendar} from group {group}" : "Lopetit kalenterin {calendar} jakamisen ryhmälle {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} lopetti kalenterin {calendar} jakamisen ryhmälle {group}",
+ "Untitled event" : "Nimetön tapahtuma",
"{actor} created event {event} in calendar {calendar}" : "{actor} loi tapahtuman {event} kalenteriin {calendar}",
"You created event {event} in calendar {calendar}" : "Loit tapahtuman {event} kalenteriin {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} poisti tapahtuman {event} kalenterista {calendar}",
@@ -50,7 +51,6 @@
"Date:" : "Päiväys:",
"Where:" : "Missä:",
"Description:" : "Kuvaus:",
- "Untitled event" : "Nimetön tapahtuma",
"_%n year_::_%n years_" : ["%n vuosi","%n vuotta"],
"_%n month_::_%n months_" : ["%n kuukausi","%n kuukautta"],
"_%n day_::_%n days_" : ["%n päivä","%n päivää"],
diff --git a/apps/dav/l10n/fr.js b/apps/dav/l10n/fr.js
index c0582dfc01a..3d9caf69ef0 100644
--- a/apps/dav/l10n/fr.js
+++ b/apps/dav/l10n/fr.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} a partagé l'agenda {calendar} avec le groupe {group}",
"You unshared calendar {calendar} from group {group}" : "Vous avez cessé de partager l'agenda {calendar} avec le groupe {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} a cessé de partager l'agenda {calendar} avec le groupe {group}",
+ "Untitled event" : "Événement sans titre",
"{actor} created event {event} in calendar {calendar}" : "{actor} a créé l'évènement {event} dans l'agenda {calendar}",
"You created event {event} in calendar {calendar}" : "Vous avez créé l'évènement {event} dans l'agenda {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} a supprimé l'évènement {event} de l'agenda {calendar}",
@@ -54,12 +55,11 @@ OC.L10N.register(
"Date:" : "Date:",
"Where:" : "Où :",
"Description:" : "Description :",
- "Untitled event" : "Événement sans titre",
- "_%n year_::_%n years_" : ["%n an","%n ans"],
- "_%n month_::_%n months_" : ["%n mois","%n mois"],
- "_%n day_::_%n days_" : ["%n jour","%n jours"],
- "_%n hour_::_%n hours_" : ["%n heure","%n heures"],
- "_%n minute_::_%n minutes_" : ["%n minute","%n minutes"],
+ "_%n year_::_%n years_" : ["%n an","%n ans","%n ans"],
+ "_%n month_::_%n months_" : ["%n mois","%n mois","%n mois"],
+ "_%n day_::_%n days_" : ["%n jour","%n jours","%n jours"],
+ "_%n hour_::_%n hours_" : ["%n heure","%n heures","%n heures"],
+ "_%n minute_::_%n minutes_" : ["%n minute","%n minutes","%n minutes"],
"%s (in %s)" : "%s (dans %s)",
"%s (%s ago)" : "%s (il y a %s)",
"Calendar: %s" : "Agenda: %s",
@@ -111,7 +111,7 @@ OC.L10N.register(
"File is not updatable: %1$s" : "Ce fichier ne peut pas être mis à jour : %1$s",
"Could not write to final file, canceled by hook" : "Impossible d'écrire dans le fichier final, annulé par le hook",
"Could not write file contents" : "Impossible d'écrire le contenu du fichier",
- "_%n byte_::_%n bytes_" : ["%n octet","%n octets"],
+ "_%n byte_::_%n bytes_" : ["%n octet","%n octets","%n octets"],
"Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Erreur en copiant le fichier à destination (copié : %1$s, taille du fichier attendue : %2$s)",
"Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side." : "Taille du fichier attendue : %1$s mais taille du fichier lue (depuis le client Nextcloud) et écrit (dans le stockage Nextcloud) : %2$s. Cela peut être un problème de réseau au niveau du client ou un problème de stockage au niveau du serveur.",
"Could not rename part file to final file, canceled by hook" : "Impossible de renommer le fichier partiel en fichier final, annulé par le hook",
@@ -175,4 +175,4 @@ OC.L10N.register(
"Comment" : "Commentaire",
"Your attendance was updated successfully." : "Votre présence a été mise à jour avec succès."
},
-"nplurals=2; plural=(n > 1);");
+"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/dav/l10n/fr.json b/apps/dav/l10n/fr.json
index 51364131d95..7134ea75384 100644
--- a/apps/dav/l10n/fr.json
+++ b/apps/dav/l10n/fr.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} a partagé l'agenda {calendar} avec le groupe {group}",
"You unshared calendar {calendar} from group {group}" : "Vous avez cessé de partager l'agenda {calendar} avec le groupe {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} a cessé de partager l'agenda {calendar} avec le groupe {group}",
+ "Untitled event" : "Événement sans titre",
"{actor} created event {event} in calendar {calendar}" : "{actor} a créé l'évènement {event} dans l'agenda {calendar}",
"You created event {event} in calendar {calendar}" : "Vous avez créé l'évènement {event} dans l'agenda {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} a supprimé l'évènement {event} de l'agenda {calendar}",
@@ -52,12 +53,11 @@
"Date:" : "Date:",
"Where:" : "Où :",
"Description:" : "Description :",
- "Untitled event" : "Événement sans titre",
- "_%n year_::_%n years_" : ["%n an","%n ans"],
- "_%n month_::_%n months_" : ["%n mois","%n mois"],
- "_%n day_::_%n days_" : ["%n jour","%n jours"],
- "_%n hour_::_%n hours_" : ["%n heure","%n heures"],
- "_%n minute_::_%n minutes_" : ["%n minute","%n minutes"],
+ "_%n year_::_%n years_" : ["%n an","%n ans","%n ans"],
+ "_%n month_::_%n months_" : ["%n mois","%n mois","%n mois"],
+ "_%n day_::_%n days_" : ["%n jour","%n jours","%n jours"],
+ "_%n hour_::_%n hours_" : ["%n heure","%n heures","%n heures"],
+ "_%n minute_::_%n minutes_" : ["%n minute","%n minutes","%n minutes"],
"%s (in %s)" : "%s (dans %s)",
"%s (%s ago)" : "%s (il y a %s)",
"Calendar: %s" : "Agenda: %s",
@@ -109,7 +109,7 @@
"File is not updatable: %1$s" : "Ce fichier ne peut pas être mis à jour : %1$s",
"Could not write to final file, canceled by hook" : "Impossible d'écrire dans le fichier final, annulé par le hook",
"Could not write file contents" : "Impossible d'écrire le contenu du fichier",
- "_%n byte_::_%n bytes_" : ["%n octet","%n octets"],
+ "_%n byte_::_%n bytes_" : ["%n octet","%n octets","%n octets"],
"Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Erreur en copiant le fichier à destination (copié : %1$s, taille du fichier attendue : %2$s)",
"Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side." : "Taille du fichier attendue : %1$s mais taille du fichier lue (depuis le client Nextcloud) et écrit (dans le stockage Nextcloud) : %2$s. Cela peut être un problème de réseau au niveau du client ou un problème de stockage au niveau du serveur.",
"Could not rename part file to final file, canceled by hook" : "Impossible de renommer le fichier partiel en fichier final, annulé par le hook",
@@ -172,5 +172,5 @@
"Number of guests" : "Nombre d'invités",
"Comment" : "Commentaire",
"Your attendance was updated successfully." : "Votre présence a été mise à jour avec succès."
-},"pluralForm" :"nplurals=2; plural=(n > 1);"
+},"pluralForm" :"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
} \ No newline at end of file
diff --git a/apps/dav/l10n/gl.js b/apps/dav/l10n/gl.js
index 0d823cd2031..cdc03edca59 100644
--- a/apps/dav/l10n/gl.js
+++ b/apps/dav/l10n/gl.js
@@ -23,6 +23,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} compartiu o calendario {calendar} co grupo {group}",
"You unshared calendar {calendar} from group {group}" : "Vostede deixou de compartir o calendario {calendar} do grupo {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} deixou de compartir o calendario {calendar} do grupo {group}",
+ "Untitled event" : "Evento sen título",
"{actor} created event {event} in calendar {calendar}" : "{actor} creou o evento {event} no calendario {calendar}",
"You created event {event} in calendar {calendar}" : "Vostede creou o evento {event} no calendario {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} eliminou o evento {event} do calendario {calendar}",
@@ -49,7 +50,6 @@ OC.L10N.register(
"Date:" : "Data:",
"Where:" : "Onde:",
"Description:" : "Descrición:",
- "Untitled event" : "Evento sen título",
"_%n year_::_%n years_" : ["%n ano","%n anos"],
"_%n month_::_%n months_" : ["%n mes","%n meses"],
"_%n day_::_%n days_" : ["%n día","%n días"],
diff --git a/apps/dav/l10n/gl.json b/apps/dav/l10n/gl.json
index 168bc295599..f00a9f4e7ae 100644
--- a/apps/dav/l10n/gl.json
+++ b/apps/dav/l10n/gl.json
@@ -21,6 +21,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} compartiu o calendario {calendar} co grupo {group}",
"You unshared calendar {calendar} from group {group}" : "Vostede deixou de compartir o calendario {calendar} do grupo {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} deixou de compartir o calendario {calendar} do grupo {group}",
+ "Untitled event" : "Evento sen título",
"{actor} created event {event} in calendar {calendar}" : "{actor} creou o evento {event} no calendario {calendar}",
"You created event {event} in calendar {calendar}" : "Vostede creou o evento {event} no calendario {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} eliminou o evento {event} do calendario {calendar}",
@@ -47,7 +48,6 @@
"Date:" : "Data:",
"Where:" : "Onde:",
"Description:" : "Descrición:",
- "Untitled event" : "Evento sen título",
"_%n year_::_%n years_" : ["%n ano","%n anos"],
"_%n month_::_%n months_" : ["%n mes","%n meses"],
"_%n day_::_%n days_" : ["%n día","%n días"],
diff --git a/apps/dav/l10n/he.js b/apps/dav/l10n/he.js
index 0d336501956..1e15402036f 100644
--- a/apps/dav/l10n/he.js
+++ b/apps/dav/l10n/he.js
@@ -23,6 +23,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "לוח השנה {calendar} שותף עם הקבוצה {group} על ידי {actor}",
"You unshared calendar {calendar} from group {group}" : "הפסקת את שיתוף לוח השנה {calendar} עם הקבוצה {group}",
"{actor} unshared calendar {calendar} from group {group}" : "השיתוף של לוח השנה {calendar} עם {group} הופסק על ידי {actor}",
+ "Untitled event" : "אירוע ללא כותרת",
"{actor} created event {event} in calendar {calendar}" : "האירוע {event} נוצר בלוח השנה {calendar} על ידי {actor}",
"You created event {event} in calendar {calendar}" : "יצרת אירוע {event} בלוח השנה {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "האירוע {event} נמחק מלוח השנה {calendar} על ידי {actor}",
@@ -49,7 +50,6 @@ OC.L10N.register(
"Date:" : "תאריך:",
"Where:" : "איפה:",
"Description:" : "תיאור:",
- "Untitled event" : "אירוע ללא כותרת",
"_%n year_::_%n years_" : ["שנה","שנתיים","%n שנים","%n שנים"],
"_%n month_::_%n months_" : ["חודש","חודשיים","%n חודשים","%n חודשים"],
"_%n day_::_%n days_" : ["יום","יומיים","%n ימים","%n ימים"],
diff --git a/apps/dav/l10n/he.json b/apps/dav/l10n/he.json
index b6625202618..f344047fa78 100644
--- a/apps/dav/l10n/he.json
+++ b/apps/dav/l10n/he.json
@@ -21,6 +21,7 @@
"{actor} shared calendar {calendar} with group {group}" : "לוח השנה {calendar} שותף עם הקבוצה {group} על ידי {actor}",
"You unshared calendar {calendar} from group {group}" : "הפסקת את שיתוף לוח השנה {calendar} עם הקבוצה {group}",
"{actor} unshared calendar {calendar} from group {group}" : "השיתוף של לוח השנה {calendar} עם {group} הופסק על ידי {actor}",
+ "Untitled event" : "אירוע ללא כותרת",
"{actor} created event {event} in calendar {calendar}" : "האירוע {event} נוצר בלוח השנה {calendar} על ידי {actor}",
"You created event {event} in calendar {calendar}" : "יצרת אירוע {event} בלוח השנה {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "האירוע {event} נמחק מלוח השנה {calendar} על ידי {actor}",
@@ -47,7 +48,6 @@
"Date:" : "תאריך:",
"Where:" : "איפה:",
"Description:" : "תיאור:",
- "Untitled event" : "אירוע ללא כותרת",
"_%n year_::_%n years_" : ["שנה","שנתיים","%n שנים","%n שנים"],
"_%n month_::_%n months_" : ["חודש","חודשיים","%n חודשים","%n חודשים"],
"_%n day_::_%n days_" : ["יום","יומיים","%n ימים","%n ימים"],
diff --git a/apps/dav/l10n/hr.js b/apps/dav/l10n/hr.js
index 047ce219120..fcb376918ff 100644
--- a/apps/dav/l10n/hr.js
+++ b/apps/dav/l10n/hr.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} dijeli kalendar {calendar} s grupom {group}",
"You unshared calendar {calendar} from group {group}" : "Više ne dijelite kalendar {calendar} s grupom {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} više ne dijeli kalendar {calendar} s grupom {group}",
+ "Untitled event" : "Događaj bez naslova",
"{actor} created event {event} in calendar {calendar}" : "{actor} je stvorio događaj {event} u kalendaru {calendar}",
"You created event {event} in calendar {calendar}" : "Stvorili ste događaj {event} u kalendaru {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} je izbrisao događaj {event} iz kalendara {calendar}",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "Datum:",
"Where:" : "Gdje:",
"Description:" : "Opis:",
- "Untitled event" : "Događaj bez naslova",
"_%n year_::_%n years_" : ["%n godina","%n godina","%n godina"],
"_%n month_::_%n months_" : ["%n mjesec","%n mjeseci","%n mjeseci"],
"_%n day_::_%n days_" : ["%n dan","%n dana","%n dana"],
diff --git a/apps/dav/l10n/hr.json b/apps/dav/l10n/hr.json
index d717a37a4a6..0956dcb6afb 100644
--- a/apps/dav/l10n/hr.json
+++ b/apps/dav/l10n/hr.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} dijeli kalendar {calendar} s grupom {group}",
"You unshared calendar {calendar} from group {group}" : "Više ne dijelite kalendar {calendar} s grupom {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} više ne dijeli kalendar {calendar} s grupom {group}",
+ "Untitled event" : "Događaj bez naslova",
"{actor} created event {event} in calendar {calendar}" : "{actor} je stvorio događaj {event} u kalendaru {calendar}",
"You created event {event} in calendar {calendar}" : "Stvorili ste događaj {event} u kalendaru {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} je izbrisao događaj {event} iz kalendara {calendar}",
@@ -52,7 +53,6 @@
"Date:" : "Datum:",
"Where:" : "Gdje:",
"Description:" : "Opis:",
- "Untitled event" : "Događaj bez naslova",
"_%n year_::_%n years_" : ["%n godina","%n godina","%n godina"],
"_%n month_::_%n months_" : ["%n mjesec","%n mjeseci","%n mjeseci"],
"_%n day_::_%n days_" : ["%n dan","%n dana","%n dana"],
diff --git a/apps/dav/l10n/hu.js b/apps/dav/l10n/hu.js
index 8ed50e1dbc3..6ef5eeebe67 100644
--- a/apps/dav/l10n/hu.js
+++ b/apps/dav/l10n/hu.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} megosztotta a(z) {calendar} naptárt a következő csoporttal: {group}",
"You unshared calendar {calendar} from group {group}" : "Visszavonta a(z) {calendar} naptár magosztását a következő csoporttól: {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} visszavonta a(z) {calendar} naptár megosztását a következő csoporttól: {group}",
+ "Untitled event" : "Névtelen esemény",
"{actor} created event {event} in calendar {calendar}" : "{actor} létrehozta a(z) {event} eseményt a következő naptárban: {calendar}",
"You created event {event} in calendar {calendar}" : "Létrehozta a(z) {event} eseményt a következő naptárban: {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} törölte a(z) {event} eseményt a következő naptárból: {calendar}",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "Dátum:",
"Where:" : "Hol:",
"Description:" : "Leírás:",
- "Untitled event" : "Névtelen esemény",
"_%n year_::_%n years_" : ["%n év","%n év"],
"_%n month_::_%n months_" : ["%n hónap","%n hónap"],
"_%n day_::_%n days_" : ["%n nap","%n nap"],
@@ -156,6 +156,9 @@ OC.L10N.register(
"Saturday" : "Szombat",
"Sunday" : "Vasárnap",
"Save" : "Mentés",
+ "Failed to load availability" : "Az elérhetőség betöltése sikertelen",
+ "Saved availability" : "Elérhetőség mentve",
+ "Failed to save availability" : "Az elérhetőség mentése sikertelen",
"Calendar server" : "Naptárkiszolgáló",
"Send invitations to attendees" : "Meghívó küldése a résztvevőknek",
"Automatically generate a birthday calendar" : "Születésnapokat tartalmazó naptár automatikus létrehozása",
diff --git a/apps/dav/l10n/hu.json b/apps/dav/l10n/hu.json
index 4eb239a2502..b6907f61630 100644
--- a/apps/dav/l10n/hu.json
+++ b/apps/dav/l10n/hu.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} megosztotta a(z) {calendar} naptárt a következő csoporttal: {group}",
"You unshared calendar {calendar} from group {group}" : "Visszavonta a(z) {calendar} naptár magosztását a következő csoporttól: {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} visszavonta a(z) {calendar} naptár megosztását a következő csoporttól: {group}",
+ "Untitled event" : "Névtelen esemény",
"{actor} created event {event} in calendar {calendar}" : "{actor} létrehozta a(z) {event} eseményt a következő naptárban: {calendar}",
"You created event {event} in calendar {calendar}" : "Létrehozta a(z) {event} eseményt a következő naptárban: {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} törölte a(z) {event} eseményt a következő naptárból: {calendar}",
@@ -52,7 +53,6 @@
"Date:" : "Dátum:",
"Where:" : "Hol:",
"Description:" : "Leírás:",
- "Untitled event" : "Névtelen esemény",
"_%n year_::_%n years_" : ["%n év","%n év"],
"_%n month_::_%n months_" : ["%n hónap","%n hónap"],
"_%n day_::_%n days_" : ["%n nap","%n nap"],
@@ -154,6 +154,9 @@
"Saturday" : "Szombat",
"Sunday" : "Vasárnap",
"Save" : "Mentés",
+ "Failed to load availability" : "Az elérhetőség betöltése sikertelen",
+ "Saved availability" : "Elérhetőség mentve",
+ "Failed to save availability" : "Az elérhetőség mentése sikertelen",
"Calendar server" : "Naptárkiszolgáló",
"Send invitations to attendees" : "Meghívó küldése a résztvevőknek",
"Automatically generate a birthday calendar" : "Születésnapokat tartalmazó naptár automatikus létrehozása",
diff --git a/apps/dav/l10n/is.js b/apps/dav/l10n/is.js
index 2032bb7d5b3..6e03824ae14 100644
--- a/apps/dav/l10n/is.js
+++ b/apps/dav/l10n/is.js
@@ -23,6 +23,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} deildi dagatalinu {calendar} með hópnum {group}",
"You unshared calendar {calendar} from group {group}" : "Þú tókst af deilingu á dagatalinu {calendar} frá hópnum {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} tók af deilingu á dagatalinu {calendar} frá hópnum {group}",
+ "Untitled event" : "Ónefndur atburður",
"{actor} created event {event} in calendar {calendar}" : "{actor} bjó til atburðinn {event} í dagatalinu {calendar}",
"You created event {event} in calendar {calendar}" : "Þú bjóst til atburðinn {event} í dagatalinu {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} eyddi atburðinum {event} úr dagatalinu {calendar}",
@@ -48,7 +49,6 @@ OC.L10N.register(
"Date:" : "Dagsetning:",
"Where:" : "Hvar:",
"Description:" : "Lýsing:",
- "Untitled event" : "Ónefndur atburður",
"_%n year_::_%n years_" : ["%n ár","%n ár"],
"_%n month_::_%n months_" : ["%n mánuður","%n mánuðir"],
"_%n day_::_%n days_" : ["%n dagur","%n dagar"],
diff --git a/apps/dav/l10n/is.json b/apps/dav/l10n/is.json
index d17d83e207e..d7b6bda37f6 100644
--- a/apps/dav/l10n/is.json
+++ b/apps/dav/l10n/is.json
@@ -21,6 +21,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} deildi dagatalinu {calendar} með hópnum {group}",
"You unshared calendar {calendar} from group {group}" : "Þú tókst af deilingu á dagatalinu {calendar} frá hópnum {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} tók af deilingu á dagatalinu {calendar} frá hópnum {group}",
+ "Untitled event" : "Ónefndur atburður",
"{actor} created event {event} in calendar {calendar}" : "{actor} bjó til atburðinn {event} í dagatalinu {calendar}",
"You created event {event} in calendar {calendar}" : "Þú bjóst til atburðinn {event} í dagatalinu {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} eyddi atburðinum {event} úr dagatalinu {calendar}",
@@ -46,7 +47,6 @@
"Date:" : "Dagsetning:",
"Where:" : "Hvar:",
"Description:" : "Lýsing:",
- "Untitled event" : "Ónefndur atburður",
"_%n year_::_%n years_" : ["%n ár","%n ár"],
"_%n month_::_%n months_" : ["%n mánuður","%n mánuðir"],
"_%n day_::_%n days_" : ["%n dagur","%n dagar"],
diff --git a/apps/dav/l10n/it.js b/apps/dav/l10n/it.js
index ce377ba761a..1d90a506fe8 100644
--- a/apps/dav/l10n/it.js
+++ b/apps/dav/l10n/it.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} ha condiviso il calendario {calendar} con il gruppo {group}",
"You unshared calendar {calendar} from group {group}" : "Hai rimosso la condivisione del calendario {calendar} con il gruppo {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} ha rimosso la condivisione del calendario {calendar} con il gruppo {group}",
+ "Untitled event" : "Evento senza titolo",
"{actor} created event {event} in calendar {calendar}" : "{actor} ha creato l'evento {event} nel calendario {calendar}",
"You created event {event} in calendar {calendar}" : "Hai creato l'evento {event} nel calendario {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} ha eliminato l'evento {event} dal calendario {calendar}",
@@ -54,12 +55,11 @@ OC.L10N.register(
"Date:" : "Data:",
"Where:" : "Dove:",
"Description:" : "Descrizione:",
- "Untitled event" : "Evento senza titolo",
- "_%n year_::_%n years_" : ["%n anno","%n anni"],
- "_%n month_::_%n months_" : ["%n mese","%n mesi"],
- "_%n day_::_%n days_" : ["%n giorno","%n giorni"],
- "_%n hour_::_%n hours_" : ["%n ora","%n ore"],
- "_%n minute_::_%n minutes_" : ["%n minuto","%n minuti"],
+ "_%n year_::_%n years_" : ["%n anno","%n anni","%n anni"],
+ "_%n month_::_%n months_" : ["%n mese","%n mesi","%n mesi"],
+ "_%n day_::_%n days_" : ["%n giorno","%n giorni","%n giorni"],
+ "_%n hour_::_%n hours_" : ["%n ora","%n ore","%n ore"],
+ "_%n minute_::_%n minutes_" : ["%n minuto","%n minuti","%n minuti"],
"%s (in %s)" : "%s (in %s)",
"%s (%s ago)" : "%s (%s fa)",
"Calendar: %s" : "Calendario: %s",
@@ -111,7 +111,7 @@ OC.L10N.register(
"File is not updatable: %1$s" : "Il file non è aggiornabile: %1$s",
"Could not write to final file, canceled by hook" : "Impossibile scrivere nel file finale, annullato da hook",
"Could not write file contents" : "Impossibile scrivere il contenuto del file",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
+ "_%n byte_::_%n bytes_" : ["%n byte","%n bytes","%n bytes"],
"Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Errore durante la copia del file nella destinazione (copiato: %1$s, dimensione prevista del file: %2$s)",
"Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side." : "Dimensione prevista del file %1$s, letto (dal client Nextcloud) e scritto (nell'archivio Nextcloud) %2$s. Potrebbe trattarsi di un problema di rete sul lato d'invio o di un problema di scrittura nell'archivio sul lato server.",
"Could not rename part file to final file, canceled by hook" : "Impossibile rinominare il file di parte in file finale, annullato da hook",
@@ -173,4 +173,4 @@ OC.L10N.register(
"Comment" : "Commento",
"Your attendance was updated successfully." : "La tua partecipazione è stata aggiornata correttamente."
},
-"nplurals=2; plural=(n != 1);");
+"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/dav/l10n/it.json b/apps/dav/l10n/it.json
index f740ad47c56..5bbdb84d88f 100644
--- a/apps/dav/l10n/it.json
+++ b/apps/dav/l10n/it.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} ha condiviso il calendario {calendar} con il gruppo {group}",
"You unshared calendar {calendar} from group {group}" : "Hai rimosso la condivisione del calendario {calendar} con il gruppo {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} ha rimosso la condivisione del calendario {calendar} con il gruppo {group}",
+ "Untitled event" : "Evento senza titolo",
"{actor} created event {event} in calendar {calendar}" : "{actor} ha creato l'evento {event} nel calendario {calendar}",
"You created event {event} in calendar {calendar}" : "Hai creato l'evento {event} nel calendario {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} ha eliminato l'evento {event} dal calendario {calendar}",
@@ -52,12 +53,11 @@
"Date:" : "Data:",
"Where:" : "Dove:",
"Description:" : "Descrizione:",
- "Untitled event" : "Evento senza titolo",
- "_%n year_::_%n years_" : ["%n anno","%n anni"],
- "_%n month_::_%n months_" : ["%n mese","%n mesi"],
- "_%n day_::_%n days_" : ["%n giorno","%n giorni"],
- "_%n hour_::_%n hours_" : ["%n ora","%n ore"],
- "_%n minute_::_%n minutes_" : ["%n minuto","%n minuti"],
+ "_%n year_::_%n years_" : ["%n anno","%n anni","%n anni"],
+ "_%n month_::_%n months_" : ["%n mese","%n mesi","%n mesi"],
+ "_%n day_::_%n days_" : ["%n giorno","%n giorni","%n giorni"],
+ "_%n hour_::_%n hours_" : ["%n ora","%n ore","%n ore"],
+ "_%n minute_::_%n minutes_" : ["%n minuto","%n minuti","%n minuti"],
"%s (in %s)" : "%s (in %s)",
"%s (%s ago)" : "%s (%s fa)",
"Calendar: %s" : "Calendario: %s",
@@ -109,7 +109,7 @@
"File is not updatable: %1$s" : "Il file non è aggiornabile: %1$s",
"Could not write to final file, canceled by hook" : "Impossibile scrivere nel file finale, annullato da hook",
"Could not write file contents" : "Impossibile scrivere il contenuto del file",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
+ "_%n byte_::_%n bytes_" : ["%n byte","%n bytes","%n bytes"],
"Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Errore durante la copia del file nella destinazione (copiato: %1$s, dimensione prevista del file: %2$s)",
"Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side." : "Dimensione prevista del file %1$s, letto (dal client Nextcloud) e scritto (nell'archivio Nextcloud) %2$s. Potrebbe trattarsi di un problema di rete sul lato d'invio o di un problema di scrittura nell'archivio sul lato server.",
"Could not rename part file to final file, canceled by hook" : "Impossibile rinominare il file di parte in file finale, annullato da hook",
@@ -170,5 +170,5 @@
"Number of guests" : "Numero di ospiti",
"Comment" : "Commento",
"Your attendance was updated successfully." : "La tua partecipazione è stata aggiornata correttamente."
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
+},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
} \ No newline at end of file
diff --git a/apps/dav/l10n/ja.js b/apps/dav/l10n/ja.js
index 1415a38c9c9..07c1086f404 100644
--- a/apps/dav/l10n/ja.js
+++ b/apps/dav/l10n/ja.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : " {actor}がカレンダー{calendar} を グループ{group} と共有しました",
"You unshared calendar {calendar} from group {group}" : "グループ{group}からカレンダー{calendar}の共有を解除しました",
"{actor} unshared calendar {calendar} from group {group}" : "{actor}がグループ{group}からカレンダー{calendar}の共有を解除しました",
+ "Untitled event" : "無題のイベント",
"{actor} created event {event} in calendar {calendar}" : "{actor}はカレンダー {calendar} のイベント{event}を作成しました",
"You created event {event} in calendar {calendar}" : "カレンダー {calendar} のイベント{event}を作成しました",
"{actor} deleted event {event} from calendar {calendar}" : "{actor}はカレンダー {calendar} のイベント{event}を削除しました",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "日付:",
"Where:" : "場所:",
"Description:" : "説明:",
- "Untitled event" : "無題のイベント",
"_%n year_::_%n years_" : ["%n年"],
"_%n month_::_%n months_" : ["%nヶ月"],
"_%n day_::_%n days_" : ["%n日"],
diff --git a/apps/dav/l10n/ja.json b/apps/dav/l10n/ja.json
index 46b1babf468..46748402cd9 100644
--- a/apps/dav/l10n/ja.json
+++ b/apps/dav/l10n/ja.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : " {actor}がカレンダー{calendar} を グループ{group} と共有しました",
"You unshared calendar {calendar} from group {group}" : "グループ{group}からカレンダー{calendar}の共有を解除しました",
"{actor} unshared calendar {calendar} from group {group}" : "{actor}がグループ{group}からカレンダー{calendar}の共有を解除しました",
+ "Untitled event" : "無題のイベント",
"{actor} created event {event} in calendar {calendar}" : "{actor}はカレンダー {calendar} のイベント{event}を作成しました",
"You created event {event} in calendar {calendar}" : "カレンダー {calendar} のイベント{event}を作成しました",
"{actor} deleted event {event} from calendar {calendar}" : "{actor}はカレンダー {calendar} のイベント{event}を削除しました",
@@ -52,7 +53,6 @@
"Date:" : "日付:",
"Where:" : "場所:",
"Description:" : "説明:",
- "Untitled event" : "無題のイベント",
"_%n year_::_%n years_" : ["%n年"],
"_%n month_::_%n months_" : ["%nヶ月"],
"_%n day_::_%n days_" : ["%n日"],
diff --git a/apps/dav/l10n/ko.js b/apps/dav/l10n/ko.js
index 1b8d00636d1..9bb56bd1782 100644
--- a/apps/dav/l10n/ko.js
+++ b/apps/dav/l10n/ko.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} 님이 달력 {calendar}을(를) 그룹 {group}와(과) 공유함",
"You unshared calendar {calendar} from group {group}" : "달력 {calendar}을(를) 그룹 {group}와(과) 공유하지 않음",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} 님이 달력 {calendar}을(를) 그룹 {group}와(과) 공유하지 않음",
+ "Untitled event" : "제목없는 이벤트",
"{actor} created event {event} in calendar {calendar}" : "{actor} 님이 행사 {event}을(를) 달력 {calendar}에 생성함",
"You created event {event} in calendar {calendar}" : "행사 {event}을(를) 달력 {calendar}에 생성함",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} 님이 행사 {event}을(를) 달력 {calendar}에서 삭제함",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "날짜:",
"Where:" : "장소:",
"Description:" : "설명:",
- "Untitled event" : "제목없는 이벤트",
"_%n year_::_%n years_" : ["%n년"],
"_%n month_::_%n months_" : ["%d개월"],
"_%n day_::_%n days_" : ["%n일"],
diff --git a/apps/dav/l10n/ko.json b/apps/dav/l10n/ko.json
index 149394220c7..e4ee28abcbc 100644
--- a/apps/dav/l10n/ko.json
+++ b/apps/dav/l10n/ko.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} 님이 달력 {calendar}을(를) 그룹 {group}와(과) 공유함",
"You unshared calendar {calendar} from group {group}" : "달력 {calendar}을(를) 그룹 {group}와(과) 공유하지 않음",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} 님이 달력 {calendar}을(를) 그룹 {group}와(과) 공유하지 않음",
+ "Untitled event" : "제목없는 이벤트",
"{actor} created event {event} in calendar {calendar}" : "{actor} 님이 행사 {event}을(를) 달력 {calendar}에 생성함",
"You created event {event} in calendar {calendar}" : "행사 {event}을(를) 달력 {calendar}에 생성함",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} 님이 행사 {event}을(를) 달력 {calendar}에서 삭제함",
@@ -52,7 +53,6 @@
"Date:" : "날짜:",
"Where:" : "장소:",
"Description:" : "설명:",
- "Untitled event" : "제목없는 이벤트",
"_%n year_::_%n years_" : ["%n년"],
"_%n month_::_%n months_" : ["%d개월"],
"_%n day_::_%n days_" : ["%n일"],
diff --git a/apps/dav/l10n/lt_LT.js b/apps/dav/l10n/lt_LT.js
index 759cf679524..1b060dbd492 100644
--- a/apps/dav/l10n/lt_LT.js
+++ b/apps/dav/l10n/lt_LT.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} pradėjo bendrinti kalendorių {calendar} su grupe {group}",
"You unshared calendar {calendar} from group {group}" : "Jūs nustojote bendrinti kalendorių {calendar} su grupe {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} nustojo bendrinti kalendorių {calendar} su grupe {group}",
+ "Untitled event" : "Įvykis be pavadinimo",
"{actor} created event {event} in calendar {calendar}" : "{actor} kalendoriuje {calendar} sukūrė įvykį {event}",
"You created event {event} in calendar {calendar}" : "Jūs kalendoriuje {calendar} sukūrėte įvykį {event}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} ištrynė įvykį {event} iš kalendoriaus {calendar}",
@@ -53,7 +54,6 @@ OC.L10N.register(
"Date:" : "Data:",
"Where:" : "Kur:",
"Description:" : "Aprašas:",
- "Untitled event" : "Įvykis be pavadinimo",
"_%n year_::_%n years_" : ["%n metai","%n metai","%n metų","%n metai"],
"_%n month_::_%n months_" : ["%n mėnesis","%n mėnesiai","%n mėnesių","%n mėnesis"],
"_%n day_::_%n days_" : ["%n diena","%n dienos","%n dienų","%n diena"],
diff --git a/apps/dav/l10n/lt_LT.json b/apps/dav/l10n/lt_LT.json
index 6803eecef9d..0b6d8f25c1c 100644
--- a/apps/dav/l10n/lt_LT.json
+++ b/apps/dav/l10n/lt_LT.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} pradėjo bendrinti kalendorių {calendar} su grupe {group}",
"You unshared calendar {calendar} from group {group}" : "Jūs nustojote bendrinti kalendorių {calendar} su grupe {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} nustojo bendrinti kalendorių {calendar} su grupe {group}",
+ "Untitled event" : "Įvykis be pavadinimo",
"{actor} created event {event} in calendar {calendar}" : "{actor} kalendoriuje {calendar} sukūrė įvykį {event}",
"You created event {event} in calendar {calendar}" : "Jūs kalendoriuje {calendar} sukūrėte įvykį {event}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} ištrynė įvykį {event} iš kalendoriaus {calendar}",
@@ -51,7 +52,6 @@
"Date:" : "Data:",
"Where:" : "Kur:",
"Description:" : "Aprašas:",
- "Untitled event" : "Įvykis be pavadinimo",
"_%n year_::_%n years_" : ["%n metai","%n metai","%n metų","%n metai"],
"_%n month_::_%n months_" : ["%n mėnesis","%n mėnesiai","%n mėnesių","%n mėnesis"],
"_%n day_::_%n days_" : ["%n diena","%n dienos","%n dienų","%n diena"],
diff --git a/apps/dav/l10n/mk.js b/apps/dav/l10n/mk.js
index 95b8683df38..d7f9310f519 100644
--- a/apps/dav/l10n/mk.js
+++ b/apps/dav/l10n/mk.js
@@ -23,6 +23,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} сподели календар {calendar} со група {group}",
"You unshared calendar {calendar} from group {group}" : "Отстранивте споделување на календар {calendar} од група {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} отстрани споделување на календар {calendar} од група {group}",
+ "Untitled event" : "Неименуван настан",
"{actor} created event {event} in calendar {calendar}" : "{actor} креираше настан {event} во календар {calendar}",
"You created event {event} in calendar {calendar}" : "Креиравте настан {event} во календар {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} избриша настан {event} од календар {calendar}",
@@ -52,7 +53,6 @@ OC.L10N.register(
"Date:" : "Датум:",
"Where:" : "Каде: ",
"Description:" : "Опис:",
- "Untitled event" : "Неименуван настан",
"_%n year_::_%n years_" : ["една година","%n години"],
"_%n month_::_%n months_" : ["еден месец","%n месеци"],
"_%n day_::_%n days_" : ["еден ден","%n дена"],
diff --git a/apps/dav/l10n/mk.json b/apps/dav/l10n/mk.json
index a858e30132b..f37a3724984 100644
--- a/apps/dav/l10n/mk.json
+++ b/apps/dav/l10n/mk.json
@@ -21,6 +21,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} сподели календар {calendar} со група {group}",
"You unshared calendar {calendar} from group {group}" : "Отстранивте споделување на календар {calendar} од група {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} отстрани споделување на календар {calendar} од група {group}",
+ "Untitled event" : "Неименуван настан",
"{actor} created event {event} in calendar {calendar}" : "{actor} креираше настан {event} во календар {calendar}",
"You created event {event} in calendar {calendar}" : "Креиравте настан {event} во календар {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} избриша настан {event} од календар {calendar}",
@@ -50,7 +51,6 @@
"Date:" : "Датум:",
"Where:" : "Каде: ",
"Description:" : "Опис:",
- "Untitled event" : "Неименуван настан",
"_%n year_::_%n years_" : ["една година","%n години"],
"_%n month_::_%n months_" : ["еден месец","%n месеци"],
"_%n day_::_%n days_" : ["еден ден","%n дена"],
diff --git a/apps/dav/l10n/nb.js b/apps/dav/l10n/nb.js
index 83b6a368d30..b2169406345 100644
--- a/apps/dav/l10n/nb.js
+++ b/apps/dav/l10n/nb.js
@@ -23,6 +23,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} delte kalenderen {calendar} med gruppe {group}",
"You unshared calendar {calendar} from group {group}" : "Du opphevde deling av kalenderen {calendar} med gruppe {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} opphevde deling av kalenderen {calendar} med gruppe {group}",
+ "Untitled event" : "Hendelse uten tittel",
"{actor} created event {event} in calendar {calendar}" : "{actor} opprettet en hendelse {event} i kalenderen {calendar}",
"You created event {event} in calendar {calendar}" : "Du opprettet en hendelse {event} i kalenderen {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} slettet hendelsen {event} fra kalenderen {calendar}",
@@ -49,7 +50,6 @@ OC.L10N.register(
"Date:" : "Dato:",
"Where:" : "Hvor:",
"Description:" : "Beskrivelse:",
- "Untitled event" : "Hendelse uten tittel",
"_%n year_::_%n years_" : ["%n år","%n år"],
"_%n month_::_%n months_" : ["%n måned","%n måneder"],
"_%n day_::_%n days_" : ["%n dag","%n dager"],
diff --git a/apps/dav/l10n/nb.json b/apps/dav/l10n/nb.json
index 2d18c5b28c6..9998d2be238 100644
--- a/apps/dav/l10n/nb.json
+++ b/apps/dav/l10n/nb.json
@@ -21,6 +21,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} delte kalenderen {calendar} med gruppe {group}",
"You unshared calendar {calendar} from group {group}" : "Du opphevde deling av kalenderen {calendar} med gruppe {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} opphevde deling av kalenderen {calendar} med gruppe {group}",
+ "Untitled event" : "Hendelse uten tittel",
"{actor} created event {event} in calendar {calendar}" : "{actor} opprettet en hendelse {event} i kalenderen {calendar}",
"You created event {event} in calendar {calendar}" : "Du opprettet en hendelse {event} i kalenderen {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} slettet hendelsen {event} fra kalenderen {calendar}",
@@ -47,7 +48,6 @@
"Date:" : "Dato:",
"Where:" : "Hvor:",
"Description:" : "Beskrivelse:",
- "Untitled event" : "Hendelse uten tittel",
"_%n year_::_%n years_" : ["%n år","%n år"],
"_%n month_::_%n months_" : ["%n måned","%n måneder"],
"_%n day_::_%n days_" : ["%n dag","%n dager"],
diff --git a/apps/dav/l10n/nl.js b/apps/dav/l10n/nl.js
index 8d4f56ae2b2..6a1f9ee6efd 100644
--- a/apps/dav/l10n/nl.js
+++ b/apps/dav/l10n/nl.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} deelde agenda {calendar} met groep {group}",
"You unshared calendar {calendar} from group {group}" : "Je stopte het delen van agenda {calendar} van groep {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} stopte het delen van agenda {calendar} met groep {group}",
+ "Untitled event" : "Afspraken zonder naam",
"{actor} created event {event} in calendar {calendar}" : "{actor} creëerde afspraak {event} in agenda {calendar}",
"You created event {event} in calendar {calendar}" : "Je creëerde afspraak {event} in agenda {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} verwijderde afspraak {event} uit agenda {calendar}",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "Datum",
"Where:" : "Waar:",
"Description:" : "Omschrijving:",
- "Untitled event" : "Afspraken zonder naam",
"_%n year_::_%n years_" : ["%n jaar","%n jaar"],
"_%n month_::_%n months_" : ["%n maand","%n maanden"],
"_%n day_::_%n days_" : ["%n dag","%n dagen"],
@@ -108,6 +108,9 @@ OC.L10N.register(
"{actor} updated contact {card} in address book {addressbook}" : "{actor} wijzigde contact {card} in adresboek {addressbook}",
"You updated contact {card} in address book {addressbook}" : "Je wijzigde contact {card} in adresboek {addressbook}",
"A <strong>contact</strong> or <strong>address book</strong> was modified" : "Een <strong>contact</strong> uit adresboek </strong> is gewijzigd",
+ "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
+ "Could not open file" : "Kan het bestand niet openen",
+ "Failed to open file: %1$s" : "Kon het bestand %1$s niet openen",
"System is in maintenance mode." : "Systeem in onderhoudsmodus.",
"Upgrade needed" : "Upgrade vereist",
"Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Je %s moet worden geconfigureerd voor gebruik van HTTPS om CalDAV en CardDAV met iOS/macOS te kunnen gebruiken.",
@@ -137,6 +140,7 @@ OC.L10N.register(
"Saturday" : "zaterdag",
"Sunday" : "zondag",
"Save" : "Opslaan",
+ "Failed to load availability" : "Kon beschikbaarheid niet laden",
"Calendar server" : "Agendaserver",
"Send invitations to attendees" : "Verzend uitnodigingen naar deelnemers",
"Automatically generate a birthday calendar" : "Genereer verjaardagskalender automatisch",
diff --git a/apps/dav/l10n/nl.json b/apps/dav/l10n/nl.json
index c4651d31984..6ef31be82d9 100644
--- a/apps/dav/l10n/nl.json
+++ b/apps/dav/l10n/nl.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} deelde agenda {calendar} met groep {group}",
"You unshared calendar {calendar} from group {group}" : "Je stopte het delen van agenda {calendar} van groep {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} stopte het delen van agenda {calendar} met groep {group}",
+ "Untitled event" : "Afspraken zonder naam",
"{actor} created event {event} in calendar {calendar}" : "{actor} creëerde afspraak {event} in agenda {calendar}",
"You created event {event} in calendar {calendar}" : "Je creëerde afspraak {event} in agenda {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} verwijderde afspraak {event} uit agenda {calendar}",
@@ -52,7 +53,6 @@
"Date:" : "Datum",
"Where:" : "Waar:",
"Description:" : "Omschrijving:",
- "Untitled event" : "Afspraken zonder naam",
"_%n year_::_%n years_" : ["%n jaar","%n jaar"],
"_%n month_::_%n months_" : ["%n maand","%n maanden"],
"_%n day_::_%n days_" : ["%n dag","%n dagen"],
@@ -106,6 +106,9 @@
"{actor} updated contact {card} in address book {addressbook}" : "{actor} wijzigde contact {card} in adresboek {addressbook}",
"You updated contact {card} in address book {addressbook}" : "Je wijzigde contact {card} in adresboek {addressbook}",
"A <strong>contact</strong> or <strong>address book</strong> was modified" : "Een <strong>contact</strong> uit adresboek </strong> is gewijzigd",
+ "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
+ "Could not open file" : "Kan het bestand niet openen",
+ "Failed to open file: %1$s" : "Kon het bestand %1$s niet openen",
"System is in maintenance mode." : "Systeem in onderhoudsmodus.",
"Upgrade needed" : "Upgrade vereist",
"Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Je %s moet worden geconfigureerd voor gebruik van HTTPS om CalDAV en CardDAV met iOS/macOS te kunnen gebruiken.",
@@ -135,6 +138,7 @@
"Saturday" : "zaterdag",
"Sunday" : "zondag",
"Save" : "Opslaan",
+ "Failed to load availability" : "Kon beschikbaarheid niet laden",
"Calendar server" : "Agendaserver",
"Send invitations to attendees" : "Verzend uitnodigingen naar deelnemers",
"Automatically generate a birthday calendar" : "Genereer verjaardagskalender automatisch",
diff --git a/apps/dav/l10n/pl.js b/apps/dav/l10n/pl.js
index 93f1e06069c..a66f5a394da 100644
--- a/apps/dav/l10n/pl.js
+++ b/apps/dav/l10n/pl.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} udostępnił kalendarz {calendar} dla grupy {group}",
"You unshared calendar {calendar} from group {group}" : "Zakończyłeś udostępnianie kalendarza {calendar} dla grupy {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} zakończył udostępnianie kalendarza {calendar} dla grupy {group} .",
+ "Untitled event" : "Wydarzenie bez tytułu",
"{actor} created event {event} in calendar {calendar}" : "{actor} utworzył wydarzenie {event} w kalendarzu {calendar}",
"You created event {event} in calendar {calendar}" : "Utworzyłeś wydarzenie {event} w kalendarzu {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} usunął wydarzenie {event} z kalendarza {calendar}",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "Data:",
"Where:" : "Gdzie:",
"Description:" : "Opis:",
- "Untitled event" : "Wydarzenie bez tytułu",
"_%n year_::_%n years_" : ["%n rok","%n lata","%n lat","%n lat"],
"_%n month_::_%n months_" : ["%n miesiąc","%n miesiące","%n miesięcy","%n miesięcy"],
"_%n day_::_%n days_" : ["%n dzień","%n dni","%n dni","%n dni"],
@@ -156,6 +156,9 @@ OC.L10N.register(
"Saturday" : "Sobota",
"Sunday" : "Niedziela",
"Save" : "Zapisz",
+ "Failed to load availability" : "Nie udało się wczytać dostępności",
+ "Saved availability" : "Zapisana dostępność",
+ "Failed to save availability" : "Nie udało się zapisać dostępności",
"Calendar server" : "Serwer kalendarza",
"Send invitations to attendees" : "Wyślij zaproszenia do uczestników",
"Automatically generate a birthday calendar" : "Automatycznie generuj kalendarz urodzin",
diff --git a/apps/dav/l10n/pl.json b/apps/dav/l10n/pl.json
index 25dde4e2304..c6096000fad 100644
--- a/apps/dav/l10n/pl.json
+++ b/apps/dav/l10n/pl.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} udostępnił kalendarz {calendar} dla grupy {group}",
"You unshared calendar {calendar} from group {group}" : "Zakończyłeś udostępnianie kalendarza {calendar} dla grupy {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} zakończył udostępnianie kalendarza {calendar} dla grupy {group} .",
+ "Untitled event" : "Wydarzenie bez tytułu",
"{actor} created event {event} in calendar {calendar}" : "{actor} utworzył wydarzenie {event} w kalendarzu {calendar}",
"You created event {event} in calendar {calendar}" : "Utworzyłeś wydarzenie {event} w kalendarzu {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} usunął wydarzenie {event} z kalendarza {calendar}",
@@ -52,7 +53,6 @@
"Date:" : "Data:",
"Where:" : "Gdzie:",
"Description:" : "Opis:",
- "Untitled event" : "Wydarzenie bez tytułu",
"_%n year_::_%n years_" : ["%n rok","%n lata","%n lat","%n lat"],
"_%n month_::_%n months_" : ["%n miesiąc","%n miesiące","%n miesięcy","%n miesięcy"],
"_%n day_::_%n days_" : ["%n dzień","%n dni","%n dni","%n dni"],
@@ -154,6 +154,9 @@
"Saturday" : "Sobota",
"Sunday" : "Niedziela",
"Save" : "Zapisz",
+ "Failed to load availability" : "Nie udało się wczytać dostępności",
+ "Saved availability" : "Zapisana dostępność",
+ "Failed to save availability" : "Nie udało się zapisać dostępności",
"Calendar server" : "Serwer kalendarza",
"Send invitations to attendees" : "Wyślij zaproszenia do uczestników",
"Automatically generate a birthday calendar" : "Automatycznie generuj kalendarz urodzin",
diff --git a/apps/dav/l10n/pt_BR.js b/apps/dav/l10n/pt_BR.js
index 14bf46617fb..8c56afa1708 100644
--- a/apps/dav/l10n/pt_BR.js
+++ b/apps/dav/l10n/pt_BR.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} compartilhou o calendário {calendar} com o grupo {group}",
"You unshared calendar {calendar} from group {group}" : "Você descompartilhou o calendário {calendar} do grupo {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} descompartilhou o calendário {calendar} do grupo {group}",
+ "Untitled event" : "Evento sem título",
"{actor} created event {event} in calendar {calendar}" : "{actor} criou o evento {event} no calendário {calendar}",
"You created event {event} in calendar {calendar}" : "Você criou o evento {event} no calendário {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} excluiu o evento {event} do calendário {calendar}",
@@ -54,12 +55,11 @@ OC.L10N.register(
"Date:" : "Data:",
"Where:" : "Onde:",
"Description:" : "Descrição:",
- "Untitled event" : "Evento sem título",
- "_%n year_::_%n years_" : ["%n ano","%n anos"],
- "_%n month_::_%n months_" : ["%n mês","%n meses"],
- "_%n day_::_%n days_" : ["%n dia","%n dias"],
- "_%n hour_::_%n hours_" : ["%n hora","%n horas"],
- "_%n minute_::_%n minutes_" : ["%n minuto","%n minutos"],
+ "_%n year_::_%n years_" : ["%n ano","%n anos","%n anos"],
+ "_%n month_::_%n months_" : ["%n mês","%n meses","%n meses"],
+ "_%n day_::_%n days_" : ["%n dia","%n dias","%n dias"],
+ "_%n hour_::_%n hours_" : ["%n hora","%n horas","%n horas"],
+ "_%n minute_::_%n minutes_" : ["%n minuto","%n minutos","%n minutos"],
"%s (in %s)" : "%s (em %s)",
"%s (%s ago)" : "%s (%s atrás)",
"Calendar: %s" : "Calendário: %s",
@@ -111,7 +111,7 @@ OC.L10N.register(
"File is not updatable: %1$s" : "O arquivo não é atualizável: %1$s",
"Could not write to final file, canceled by hook" : "Não foi possível gravar no arquivo final, cancelado pelo gancho",
"Could not write file contents" : "Não foi possível gravar o conteúdo do arquivo",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
+ "_%n byte_::_%n bytes_" : ["%n byte","%n bytes","%n bytes"],
"Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Erro ao copiar o arquivo para o local de destino (copiado: %1$s, tamanho de arquivo esperado: %2$s)",
"Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side." : "Tamanho de arquivo esperado de %1$s mas lido (do cliente Nextcloud) e gravado (no armazenamento Nextcloud) %2$s. Pode ser um problema de rede no lado de envio ou um problema de gravação no armazenamento no lado do servidor.",
"Could not rename part file to final file, canceled by hook" : "Não foi possível renomear o arquivo de parte para o arquivo final, cancelado pelo gancho",
@@ -156,6 +156,9 @@ OC.L10N.register(
"Saturday" : "Sábado ",
"Sunday" : "Domingo",
"Save" : "Salvar",
+ "Failed to load availability" : "Falha ao carregar a disponibilidade",
+ "Saved availability" : "Disponibilidade salva",
+ "Failed to save availability" : "Falha ao salvar a disponibilidade",
"Calendar server" : "Servidor de calendário",
"Send invitations to attendees" : "Enviar convites aos participantes",
"Automatically generate a birthday calendar" : "Gerar um calendário de aniversários automaticamente",
@@ -176,4 +179,4 @@ OC.L10N.register(
"Comment" : "Comentário",
"Your attendance was updated successfully." : "Sua presença foi atualizada com sucesso."
},
-"nplurals=2; plural=(n > 1);");
+"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/dav/l10n/pt_BR.json b/apps/dav/l10n/pt_BR.json
index 00ab3a5788e..852dac798ba 100644
--- a/apps/dav/l10n/pt_BR.json
+++ b/apps/dav/l10n/pt_BR.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} compartilhou o calendário {calendar} com o grupo {group}",
"You unshared calendar {calendar} from group {group}" : "Você descompartilhou o calendário {calendar} do grupo {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} descompartilhou o calendário {calendar} do grupo {group}",
+ "Untitled event" : "Evento sem título",
"{actor} created event {event} in calendar {calendar}" : "{actor} criou o evento {event} no calendário {calendar}",
"You created event {event} in calendar {calendar}" : "Você criou o evento {event} no calendário {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} excluiu o evento {event} do calendário {calendar}",
@@ -52,12 +53,11 @@
"Date:" : "Data:",
"Where:" : "Onde:",
"Description:" : "Descrição:",
- "Untitled event" : "Evento sem título",
- "_%n year_::_%n years_" : ["%n ano","%n anos"],
- "_%n month_::_%n months_" : ["%n mês","%n meses"],
- "_%n day_::_%n days_" : ["%n dia","%n dias"],
- "_%n hour_::_%n hours_" : ["%n hora","%n horas"],
- "_%n minute_::_%n minutes_" : ["%n minuto","%n minutos"],
+ "_%n year_::_%n years_" : ["%n ano","%n anos","%n anos"],
+ "_%n month_::_%n months_" : ["%n mês","%n meses","%n meses"],
+ "_%n day_::_%n days_" : ["%n dia","%n dias","%n dias"],
+ "_%n hour_::_%n hours_" : ["%n hora","%n horas","%n horas"],
+ "_%n minute_::_%n minutes_" : ["%n minuto","%n minutos","%n minutos"],
"%s (in %s)" : "%s (em %s)",
"%s (%s ago)" : "%s (%s atrás)",
"Calendar: %s" : "Calendário: %s",
@@ -109,7 +109,7 @@
"File is not updatable: %1$s" : "O arquivo não é atualizável: %1$s",
"Could not write to final file, canceled by hook" : "Não foi possível gravar no arquivo final, cancelado pelo gancho",
"Could not write file contents" : "Não foi possível gravar o conteúdo do arquivo",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
+ "_%n byte_::_%n bytes_" : ["%n byte","%n bytes","%n bytes"],
"Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Erro ao copiar o arquivo para o local de destino (copiado: %1$s, tamanho de arquivo esperado: %2$s)",
"Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side." : "Tamanho de arquivo esperado de %1$s mas lido (do cliente Nextcloud) e gravado (no armazenamento Nextcloud) %2$s. Pode ser um problema de rede no lado de envio ou um problema de gravação no armazenamento no lado do servidor.",
"Could not rename part file to final file, canceled by hook" : "Não foi possível renomear o arquivo de parte para o arquivo final, cancelado pelo gancho",
@@ -154,6 +154,9 @@
"Saturday" : "Sábado ",
"Sunday" : "Domingo",
"Save" : "Salvar",
+ "Failed to load availability" : "Falha ao carregar a disponibilidade",
+ "Saved availability" : "Disponibilidade salva",
+ "Failed to save availability" : "Falha ao salvar a disponibilidade",
"Calendar server" : "Servidor de calendário",
"Send invitations to attendees" : "Enviar convites aos participantes",
"Automatically generate a birthday calendar" : "Gerar um calendário de aniversários automaticamente",
@@ -173,5 +176,5 @@
"Number of guests" : "Número de convidados",
"Comment" : "Comentário",
"Your attendance was updated successfully." : "Sua presença foi atualizada com sucesso."
-},"pluralForm" :"nplurals=2; plural=(n > 1);"
+},"pluralForm" :"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
} \ No newline at end of file
diff --git a/apps/dav/l10n/ru.js b/apps/dav/l10n/ru.js
index 9f61a676680..a2a21aa535f 100644
--- a/apps/dav/l10n/ru.js
+++ b/apps/dav/l10n/ru.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} предоставил(а) группе {group} общий доступ к календарю «{calendar}»",
"You unshared calendar {calendar} from group {group}" : "Вы закрыли группе {group} общий доступ к календарю «{calendar}»",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} закрыл(а) группе {group} общий доступ к календарю «{calendar}»",
+ "Untitled event" : "Событие без названия",
"{actor} created event {event} in calendar {calendar}" : "{actor} создал(а) событие «{event}» в календаре «{calendar}»",
"You created event {event} in calendar {calendar}" : "Вы создали событие «{event}» в календаре «{calendar}»",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} удалил(а) событие «{event}» из календаря «{calendar}»",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "Дата:",
"Where:" : "Где:",
"Description:" : "Описание:",
- "Untitled event" : "Событие без названия",
"_%n year_::_%n years_" : ["%n год","%n года","%n лет","%n лет"],
"_%n month_::_%n months_" : ["%n месяц","%n месяца","%n месяцев","%n месяцев"],
"_%n day_::_%n days_" : ["%n день","%n дня","%n дней","%n дней"],
@@ -108,6 +108,8 @@ OC.L10N.register(
"{actor} updated contact {card} in address book {addressbook}" : "{actor} изменил(а) запись {card} в адресной книге {addressbook}",
"You updated contact {card} in address book {addressbook}" : "Вы изменили запись {card} в адресной книге {addressbook}",
"A <strong>contact</strong> or <strong>address book</strong> was modified" : "Изменение <strong>контакта</strong> или <strong>адресной книги</strong>",
+ "File is not updatable: %1$s" : "Файл не подлежит обновлению: %1$s",
+ "Could not write file contents" : "Не удалось записать содержимое файла",
"System is in maintenance mode." : "Сервер находится в режиме обслуживания.",
"Upgrade needed" : "Требуется обновление",
"Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Ваш %s должен быть настроен на использование протокола HTTPS, чтобы можно было использовать CalDAV и CardDAV на iOS/macOS.",
diff --git a/apps/dav/l10n/ru.json b/apps/dav/l10n/ru.json
index 76b46d546a1..ef6fd3e653a 100644
--- a/apps/dav/l10n/ru.json
+++ b/apps/dav/l10n/ru.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} предоставил(а) группе {group} общий доступ к календарю «{calendar}»",
"You unshared calendar {calendar} from group {group}" : "Вы закрыли группе {group} общий доступ к календарю «{calendar}»",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} закрыл(а) группе {group} общий доступ к календарю «{calendar}»",
+ "Untitled event" : "Событие без названия",
"{actor} created event {event} in calendar {calendar}" : "{actor} создал(а) событие «{event}» в календаре «{calendar}»",
"You created event {event} in calendar {calendar}" : "Вы создали событие «{event}» в календаре «{calendar}»",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} удалил(а) событие «{event}» из календаря «{calendar}»",
@@ -52,7 +53,6 @@
"Date:" : "Дата:",
"Where:" : "Где:",
"Description:" : "Описание:",
- "Untitled event" : "Событие без названия",
"_%n year_::_%n years_" : ["%n год","%n года","%n лет","%n лет"],
"_%n month_::_%n months_" : ["%n месяц","%n месяца","%n месяцев","%n месяцев"],
"_%n day_::_%n days_" : ["%n день","%n дня","%n дней","%n дней"],
@@ -106,6 +106,8 @@
"{actor} updated contact {card} in address book {addressbook}" : "{actor} изменил(а) запись {card} в адресной книге {addressbook}",
"You updated contact {card} in address book {addressbook}" : "Вы изменили запись {card} в адресной книге {addressbook}",
"A <strong>contact</strong> or <strong>address book</strong> was modified" : "Изменение <strong>контакта</strong> или <strong>адресной книги</strong>",
+ "File is not updatable: %1$s" : "Файл не подлежит обновлению: %1$s",
+ "Could not write file contents" : "Не удалось записать содержимое файла",
"System is in maintenance mode." : "Сервер находится в режиме обслуживания.",
"Upgrade needed" : "Требуется обновление",
"Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Ваш %s должен быть настроен на использование протокола HTTPS, чтобы можно было использовать CalDAV и CardDAV на iOS/macOS.",
diff --git a/apps/dav/l10n/sc.js b/apps/dav/l10n/sc.js
index 897f96f71d9..caeaa8654aa 100644
--- a/apps/dav/l10n/sc.js
+++ b/apps/dav/l10n/sc.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} at cumpartzidu su calendàriu {calendar} cun su grupu {group}",
"You unshared calendar {calendar} from group {group}" : "As annulladu su calendàriu {calendar} cun su grupu {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} at annulladu sa cumpartzidura de su calendàriu {calendar} cun su grupu {group}",
+ "Untitled event" : "Eventu sena tìtulu ",
"{actor} created event {event} in calendar {calendar}" : "{actor} at creadu s'eventu {event} in su calendàriu {calendar}",
"You created event {event} in calendar {calendar}" : "As creadu un'eventu {event} in su calendàriu {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} at cantzelladu s'eventu {event} dae su calendàriu {calendar}",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "Data:",
"Where:" : "Ue:",
"Description:" : "Descritzione:",
- "Untitled event" : "Eventu sena tìtulu ",
"_%n year_::_%n years_" : ["%n annu","%n annos"],
"_%n month_::_%n months_" : ["%n meses","%n meses"],
"_%n day_::_%n days_" : ["%n die","%n days"],
diff --git a/apps/dav/l10n/sc.json b/apps/dav/l10n/sc.json
index 0dd83ab8392..77c14b27fa2 100644
--- a/apps/dav/l10n/sc.json
+++ b/apps/dav/l10n/sc.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} at cumpartzidu su calendàriu {calendar} cun su grupu {group}",
"You unshared calendar {calendar} from group {group}" : "As annulladu su calendàriu {calendar} cun su grupu {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} at annulladu sa cumpartzidura de su calendàriu {calendar} cun su grupu {group}",
+ "Untitled event" : "Eventu sena tìtulu ",
"{actor} created event {event} in calendar {calendar}" : "{actor} at creadu s'eventu {event} in su calendàriu {calendar}",
"You created event {event} in calendar {calendar}" : "As creadu un'eventu {event} in su calendàriu {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} at cantzelladu s'eventu {event} dae su calendàriu {calendar}",
@@ -52,7 +53,6 @@
"Date:" : "Data:",
"Where:" : "Ue:",
"Description:" : "Descritzione:",
- "Untitled event" : "Eventu sena tìtulu ",
"_%n year_::_%n years_" : ["%n annu","%n annos"],
"_%n month_::_%n months_" : ["%n meses","%n meses"],
"_%n day_::_%n days_" : ["%n die","%n days"],
diff --git a/apps/dav/l10n/sk.js b/apps/dav/l10n/sk.js
index d6d1908c05d..7b1a92c26bb 100644
--- a/apps/dav/l10n/sk.js
+++ b/apps/dav/l10n/sk.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} vyzdieľal kalendár {calendar} so skupinou {group}",
"You unshared calendar {calendar} from group {group}" : "Zrušili ste zdieľanie kalendára {calendar} so skupinou {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} zrušil zdieľanie kalendára {calendar} so skupinou {group}",
+ "Untitled event" : "Udalosť bez názvu",
"{actor} created event {event} in calendar {calendar}" : "{actor} vytvoril udalosť {event} v kalendári {calendar}",
"You created event {event} in calendar {calendar}" : "Vytvorili ste udalosť {event} v kalendári {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} zmazal udalosť {event} from z kalendára {calendar}",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "Dátum:",
"Where:" : "Kde:",
"Description:" : "Popis:",
- "Untitled event" : "Udalosť bez názvu",
"_%n year_::_%n years_" : ["%n rokov","%n rokov","%n rokov","%n rokov"],
"_%n month_::_%n months_" : ["%n mesiac","%n mesiace","%n mesiacov","%n mesiacov"],
"_%n day_::_%n days_" : ["%n deň","%n dni","%n dní","%n dní"],
diff --git a/apps/dav/l10n/sk.json b/apps/dav/l10n/sk.json
index f7c11d213f3..fc9ffea27ad 100644
--- a/apps/dav/l10n/sk.json
+++ b/apps/dav/l10n/sk.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} vyzdieľal kalendár {calendar} so skupinou {group}",
"You unshared calendar {calendar} from group {group}" : "Zrušili ste zdieľanie kalendára {calendar} so skupinou {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} zrušil zdieľanie kalendára {calendar} so skupinou {group}",
+ "Untitled event" : "Udalosť bez názvu",
"{actor} created event {event} in calendar {calendar}" : "{actor} vytvoril udalosť {event} v kalendári {calendar}",
"You created event {event} in calendar {calendar}" : "Vytvorili ste udalosť {event} v kalendári {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} zmazal udalosť {event} from z kalendára {calendar}",
@@ -52,7 +53,6 @@
"Date:" : "Dátum:",
"Where:" : "Kde:",
"Description:" : "Popis:",
- "Untitled event" : "Udalosť bez názvu",
"_%n year_::_%n years_" : ["%n rokov","%n rokov","%n rokov","%n rokov"],
"_%n month_::_%n months_" : ["%n mesiac","%n mesiace","%n mesiacov","%n mesiacov"],
"_%n day_::_%n days_" : ["%n deň","%n dni","%n dní","%n dní"],
diff --git a/apps/dav/l10n/sl.js b/apps/dav/l10n/sl.js
index 7c1f367a468..bb07ed9b9f0 100644
--- a/apps/dav/l10n/sl.js
+++ b/apps/dav/l10n/sl.js
@@ -23,6 +23,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} omogoči souporabo koledarja {calendar} s skupino {group}",
"You unshared calendar {calendar} from group {group}" : "Onemogočite souporabo koledarja {calendar} s skupino {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} onemogoči souporabo koledarja {calendar} s skupino {group}",
+ "Untitled event" : "Neimenovan dogodek¨",
"{actor} created event {event} in calendar {calendar}" : "{actor} ustvari dogodek {event} v koledarju {calendar}",
"You created event {event} in calendar {calendar}" : "Ustvarite dogodek {event} v koledarju {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} izbriše dogodek {event} iz koledarja {calendar}",
@@ -50,7 +51,6 @@ OC.L10N.register(
"Date:" : "Datum:",
"Where:" : "Kje:",
"Description:" : "Opis:",
- "Untitled event" : "Neimenovan dogodek¨",
"_%n year_::_%n years_" : ["%n leto","%n leti","%n leta","%n let"],
"_%n month_::_%n months_" : ["%n mesec","%n meseca","%n meseci","%n mesecev"],
"_%n day_::_%n days_" : ["%n dan","%n dneva","%n dni","%n dni"],
@@ -81,6 +81,7 @@ OC.L10N.register(
"More options at %s" : "Več možnosti je na %s",
"Contacts" : "Stiki",
"You deleted address book {addressbook}" : "Izbrišete imenik {addressbook}",
+ "Could not write file contents" : "Ni mogoče zapisati vsebine datoteke",
"System is in maintenance mode." : "Sistem je v vzdrževalnem načinu.",
"Upgrade needed" : "Zahtevana je posodobitev",
"Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Za uporabo CalDAV in CardDAV v okoljih iOS/macOS je treba %s nastaviti za uporabo HTTPS.",
@@ -100,7 +101,7 @@ OC.L10N.register(
"to" : "do",
"Delete slot" : "Izbriši možnost",
"No working hours set" : "Ni navedenih delovnih ur",
- "Add slot" : "Dodaj polje",
+ "Add slot" : "Dodaj možnost",
"Monday" : "ponedeljek",
"Tuesday" : "torek",
"Wednesday" : "sreda",
@@ -109,6 +110,7 @@ OC.L10N.register(
"Saturday" : "sobota",
"Sunday" : "nedelja",
"Save" : "Shrani",
+ "Failed to load availability" : "Nalaganje seznama razpoložljivih polj je spodletelo",
"Calendar server" : "Strežnik koledarja",
"Send invitations to attendees" : "Pošlji povabilo udeležencem",
"Automatically generate a birthday calendar" : "Samodejno ustvari koledar rojstnih dni",
diff --git a/apps/dav/l10n/sl.json b/apps/dav/l10n/sl.json
index 8703fddc54a..cecfc2cb0c4 100644
--- a/apps/dav/l10n/sl.json
+++ b/apps/dav/l10n/sl.json
@@ -21,6 +21,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} omogoči souporabo koledarja {calendar} s skupino {group}",
"You unshared calendar {calendar} from group {group}" : "Onemogočite souporabo koledarja {calendar} s skupino {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} onemogoči souporabo koledarja {calendar} s skupino {group}",
+ "Untitled event" : "Neimenovan dogodek¨",
"{actor} created event {event} in calendar {calendar}" : "{actor} ustvari dogodek {event} v koledarju {calendar}",
"You created event {event} in calendar {calendar}" : "Ustvarite dogodek {event} v koledarju {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} izbriše dogodek {event} iz koledarja {calendar}",
@@ -48,7 +49,6 @@
"Date:" : "Datum:",
"Where:" : "Kje:",
"Description:" : "Opis:",
- "Untitled event" : "Neimenovan dogodek¨",
"_%n year_::_%n years_" : ["%n leto","%n leti","%n leta","%n let"],
"_%n month_::_%n months_" : ["%n mesec","%n meseca","%n meseci","%n mesecev"],
"_%n day_::_%n days_" : ["%n dan","%n dneva","%n dni","%n dni"],
@@ -79,6 +79,7 @@
"More options at %s" : "Več možnosti je na %s",
"Contacts" : "Stiki",
"You deleted address book {addressbook}" : "Izbrišete imenik {addressbook}",
+ "Could not write file contents" : "Ni mogoče zapisati vsebine datoteke",
"System is in maintenance mode." : "Sistem je v vzdrževalnem načinu.",
"Upgrade needed" : "Zahtevana je posodobitev",
"Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Za uporabo CalDAV in CardDAV v okoljih iOS/macOS je treba %s nastaviti za uporabo HTTPS.",
@@ -98,7 +99,7 @@
"to" : "do",
"Delete slot" : "Izbriši možnost",
"No working hours set" : "Ni navedenih delovnih ur",
- "Add slot" : "Dodaj polje",
+ "Add slot" : "Dodaj možnost",
"Monday" : "ponedeljek",
"Tuesday" : "torek",
"Wednesday" : "sreda",
@@ -107,6 +108,7 @@
"Saturday" : "sobota",
"Sunday" : "nedelja",
"Save" : "Shrani",
+ "Failed to load availability" : "Nalaganje seznama razpoložljivih polj je spodletelo",
"Calendar server" : "Strežnik koledarja",
"Send invitations to attendees" : "Pošlji povabilo udeležencem",
"Automatically generate a birthday calendar" : "Samodejno ustvari koledar rojstnih dni",
diff --git a/apps/dav/l10n/sr.js b/apps/dav/l10n/sr.js
index b1f8a03574c..4412a3999bf 100644
--- a/apps/dav/l10n/sr.js
+++ b/apps/dav/l10n/sr.js
@@ -23,6 +23,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} подели календар {calendar} са групом {group}",
"You unshared calendar {calendar} from group {group}" : "Укинули сте дељење календара {calendar} са групом {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} укину дељење календара {calendar} са групом {group}",
+ "Untitled event" : "Неименовани догађај",
"{actor} created event {event} in calendar {calendar}" : "{actor} је направио догађај {event} у календару {calendar}",
"You created event {event} in calendar {calendar}" : "Креирали сте догађај {event} у календару {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} је обрисао догађај {event} из календара {calendar}",
@@ -49,7 +50,6 @@ OC.L10N.register(
"Date:" : "Датум:",
"Where:" : "Место:",
"Description:" : "Опис:",
- "Untitled event" : "Неименовани догађај",
"_%n year_::_%n years_" : ["%n година","%n године","%n година"],
"_%n month_::_%n months_" : ["%n месец","%n месеца","%n месеци"],
"_%n day_::_%n days_" : ["%n дан","%n дана","%n дана"],
diff --git a/apps/dav/l10n/sr.json b/apps/dav/l10n/sr.json
index 19749cf34da..b0d59d93232 100644
--- a/apps/dav/l10n/sr.json
+++ b/apps/dav/l10n/sr.json
@@ -21,6 +21,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} подели календар {calendar} са групом {group}",
"You unshared calendar {calendar} from group {group}" : "Укинули сте дељење календара {calendar} са групом {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} укину дељење календара {calendar} са групом {group}",
+ "Untitled event" : "Неименовани догађај",
"{actor} created event {event} in calendar {calendar}" : "{actor} је направио догађај {event} у календару {calendar}",
"You created event {event} in calendar {calendar}" : "Креирали сте догађај {event} у календару {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} је обрисао догађај {event} из календара {calendar}",
@@ -47,7 +48,6 @@
"Date:" : "Датум:",
"Where:" : "Место:",
"Description:" : "Опис:",
- "Untitled event" : "Неименовани догађај",
"_%n year_::_%n years_" : ["%n година","%n године","%n година"],
"_%n month_::_%n months_" : ["%n месец","%n месеца","%n месеци"],
"_%n day_::_%n days_" : ["%n дан","%n дана","%n дана"],
diff --git a/apps/dav/l10n/sv.js b/apps/dav/l10n/sv.js
index 89ec7716a2e..6508c8fc33b 100644
--- a/apps/dav/l10n/sv.js
+++ b/apps/dav/l10n/sv.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} delade kalender {calendar} med grupp {group}",
"You unshared calendar {calendar} from group {group}" : "Du slutade dela kalender {calendar} med gruppen {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} slutade dela kalender {calendar} med gruppen {group}",
+ "Untitled event" : "Namnlös händelse",
"{actor} created event {event} in calendar {calendar}" : "{actor} skapade händelse {event} i kalender {calendar}",
"You created event {event} in calendar {calendar}" : "Du skapade händelse {event} i kalender {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} tog bort händelse {event} från kalender {calendar}",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "Datum:",
"Where:" : "Var:",
"Description:" : "Beskrivning:",
- "Untitled event" : "Namnlös händelse",
"_%n year_::_%n years_" : ["%n år","%n år"],
"_%n month_::_%n months_" : ["%n månad","%n månader"],
"_%n day_::_%n days_" : ["%n dag","%n dagar"],
diff --git a/apps/dav/l10n/sv.json b/apps/dav/l10n/sv.json
index 1458687f6ee..8040b5f3f34 100644
--- a/apps/dav/l10n/sv.json
+++ b/apps/dav/l10n/sv.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} delade kalender {calendar} med grupp {group}",
"You unshared calendar {calendar} from group {group}" : "Du slutade dela kalender {calendar} med gruppen {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} slutade dela kalender {calendar} med gruppen {group}",
+ "Untitled event" : "Namnlös händelse",
"{actor} created event {event} in calendar {calendar}" : "{actor} skapade händelse {event} i kalender {calendar}",
"You created event {event} in calendar {calendar}" : "Du skapade händelse {event} i kalender {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} tog bort händelse {event} från kalender {calendar}",
@@ -52,7 +53,6 @@
"Date:" : "Datum:",
"Where:" : "Var:",
"Description:" : "Beskrivning:",
- "Untitled event" : "Namnlös händelse",
"_%n year_::_%n years_" : ["%n år","%n år"],
"_%n month_::_%n months_" : ["%n månad","%n månader"],
"_%n day_::_%n days_" : ["%n dag","%n dagar"],
diff --git a/apps/dav/l10n/tr.js b/apps/dav/l10n/tr.js
index 70d3736f931..bd11fb3dada 100644
--- a/apps/dav/l10n/tr.js
+++ b/apps/dav/l10n/tr.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor}, {calendar} takvimini {group} grubu ile paylaştı",
"You unshared calendar {calendar} from group {group}" : "{calendar} takviminin {group} grubu ile paylaşımını kaldırdınız",
"{actor} unshared calendar {calendar} from group {group}" : "{actor}, {calendar} takviminin {group} grubu ile paylaşımını kaldırdı",
+ "Untitled event" : "Adsız etkinlik",
"{actor} created event {event} in calendar {calendar}" : "{actor}, {calendar} takvimine {event} etkinliğini ekledi",
"You created event {event} in calendar {calendar}" : "{calendar} takvimine {event} etkinliğini eklediniz",
"{actor} deleted event {event} from calendar {calendar}" : "{actor}, {calendar} takviminden {event} etkinliğini sildi",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "Tarih:",
"Where:" : "Yer:",
"Description:" : "Açıklama:",
- "Untitled event" : "Adsız etkinlik",
"_%n year_::_%n years_" : ["%n yıl","%n yıl"],
"_%n month_::_%n months_" : ["%n ay","%n ay"],
"_%n day_::_%n days_" : ["%n gün","%n gün"],
@@ -156,6 +156,9 @@ OC.L10N.register(
"Saturday" : "Cumartesi",
"Sunday" : "Pazar",
"Save" : "Kaydet",
+ "Failed to load availability" : "Uygunluk yüklenemedi",
+ "Saved availability" : "Uygunluk kaydedildi",
+ "Failed to save availability" : "Uygunluk kaydedilemedi",
"Calendar server" : "Takvim sunucusu",
"Send invitations to attendees" : "Katılımcılara çağrıları gönder",
"Automatically generate a birthday calendar" : "Doğum günü takvimi otomatik oluşturulsun",
diff --git a/apps/dav/l10n/tr.json b/apps/dav/l10n/tr.json
index b1ba8a73d64..5767d918f7a 100644
--- a/apps/dav/l10n/tr.json
+++ b/apps/dav/l10n/tr.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor}, {calendar} takvimini {group} grubu ile paylaştı",
"You unshared calendar {calendar} from group {group}" : "{calendar} takviminin {group} grubu ile paylaşımını kaldırdınız",
"{actor} unshared calendar {calendar} from group {group}" : "{actor}, {calendar} takviminin {group} grubu ile paylaşımını kaldırdı",
+ "Untitled event" : "Adsız etkinlik",
"{actor} created event {event} in calendar {calendar}" : "{actor}, {calendar} takvimine {event} etkinliğini ekledi",
"You created event {event} in calendar {calendar}" : "{calendar} takvimine {event} etkinliğini eklediniz",
"{actor} deleted event {event} from calendar {calendar}" : "{actor}, {calendar} takviminden {event} etkinliğini sildi",
@@ -52,7 +53,6 @@
"Date:" : "Tarih:",
"Where:" : "Yer:",
"Description:" : "Açıklama:",
- "Untitled event" : "Adsız etkinlik",
"_%n year_::_%n years_" : ["%n yıl","%n yıl"],
"_%n month_::_%n months_" : ["%n ay","%n ay"],
"_%n day_::_%n days_" : ["%n gün","%n gün"],
@@ -154,6 +154,9 @@
"Saturday" : "Cumartesi",
"Sunday" : "Pazar",
"Save" : "Kaydet",
+ "Failed to load availability" : "Uygunluk yüklenemedi",
+ "Saved availability" : "Uygunluk kaydedildi",
+ "Failed to save availability" : "Uygunluk kaydedilemedi",
"Calendar server" : "Takvim sunucusu",
"Send invitations to attendees" : "Katılımcılara çağrıları gönder",
"Automatically generate a birthday calendar" : "Doğum günü takvimi otomatik oluşturulsun",
diff --git a/apps/dav/l10n/uk.js b/apps/dav/l10n/uk.js
index 1f4e0a085be..22de431e2e0 100644
--- a/apps/dav/l10n/uk.js
+++ b/apps/dav/l10n/uk.js
@@ -23,6 +23,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} поширив календар {calendar} з групою {group}",
"You unshared calendar {calendar} from group {group}" : "Ви припинили поширення календаря {calendar} з групою {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} припинив поширення календаря {calendar} з групою {group}",
+ "Untitled event" : "Подія без назви",
"{actor} created event {event} in calendar {calendar}" : "{actor} створив подію {event} у календарі {calendar}",
"You created event {event} in calendar {calendar}" : "Ви створили подію {event} у календарі {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} вилучив подію {event} з календаря {calendar}",
@@ -49,7 +50,6 @@ OC.L10N.register(
"Date:" : "Дата:",
"Where:" : "Місце:",
"Description:" : "Опис:",
- "Untitled event" : "Подія без назви",
"_%n year_::_%n years_" : ["%n рік","%n років","%n років","%n роки "],
"_%n month_::_%n months_" : ["%n місяць","%n місяців","%n місяців","%n місяці"],
"_%n day_::_%n days_" : ["%n день","%n днів","%n днів","%n дні"],
diff --git a/apps/dav/l10n/uk.json b/apps/dav/l10n/uk.json
index 177d7e8f2b0..f1ec48b299b 100644
--- a/apps/dav/l10n/uk.json
+++ b/apps/dav/l10n/uk.json
@@ -21,6 +21,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} поширив календар {calendar} з групою {group}",
"You unshared calendar {calendar} from group {group}" : "Ви припинили поширення календаря {calendar} з групою {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} припинив поширення календаря {calendar} з групою {group}",
+ "Untitled event" : "Подія без назви",
"{actor} created event {event} in calendar {calendar}" : "{actor} створив подію {event} у календарі {calendar}",
"You created event {event} in calendar {calendar}" : "Ви створили подію {event} у календарі {calendar}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} вилучив подію {event} з календаря {calendar}",
@@ -47,7 +48,6 @@
"Date:" : "Дата:",
"Where:" : "Місце:",
"Description:" : "Опис:",
- "Untitled event" : "Подія без назви",
"_%n year_::_%n years_" : ["%n рік","%n років","%n років","%n роки "],
"_%n month_::_%n months_" : ["%n місяць","%n місяців","%n місяців","%n місяці"],
"_%n day_::_%n days_" : ["%n день","%n днів","%n днів","%n дні"],
diff --git a/apps/dav/l10n/zh_CN.js b/apps/dav/l10n/zh_CN.js
index 64dea9f2d17..f661cd87bf9 100644
--- a/apps/dav/l10n/zh_CN.js
+++ b/apps/dav/l10n/zh_CN.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} 通过组 {group} 共享了日历 {calendar}",
"You unshared calendar {calendar} from group {group}" : "群组 {group} 取消了你共享的日历 {calendar}",
"{actor} unshared calendar {calendar} from group {group}" : "群组 {group} 取消了 {actor} 共享的日历 {calendar}",
+ "Untitled event" : "未命名事件",
"{actor} created event {event} in calendar {calendar}" : "{actor} 在日历 {calendar} 中创建了事件 {event}",
"You created event {event} in calendar {calendar}" : "您在日历 {calendar} 中创建了事件 {event}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} 在日历 {calendar} 中删除了事件 {event}",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "日期:",
"Where:" : "地点:",
"Description:" : "描述:",
- "Untitled event" : "未命名事件",
"_%n year_::_%n years_" : ["%n 年"],
"_%n month_::_%n months_" : ["%n 月"],
"_%n day_::_%n days_" : ["%n 天"],
diff --git a/apps/dav/l10n/zh_CN.json b/apps/dav/l10n/zh_CN.json
index 44f361cbedc..77ddaaf5f58 100644
--- a/apps/dav/l10n/zh_CN.json
+++ b/apps/dav/l10n/zh_CN.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} 通过组 {group} 共享了日历 {calendar}",
"You unshared calendar {calendar} from group {group}" : "群组 {group} 取消了你共享的日历 {calendar}",
"{actor} unshared calendar {calendar} from group {group}" : "群组 {group} 取消了 {actor} 共享的日历 {calendar}",
+ "Untitled event" : "未命名事件",
"{actor} created event {event} in calendar {calendar}" : "{actor} 在日历 {calendar} 中创建了事件 {event}",
"You created event {event} in calendar {calendar}" : "您在日历 {calendar} 中创建了事件 {event}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} 在日历 {calendar} 中删除了事件 {event}",
@@ -52,7 +53,6 @@
"Date:" : "日期:",
"Where:" : "地点:",
"Description:" : "描述:",
- "Untitled event" : "未命名事件",
"_%n year_::_%n years_" : ["%n 年"],
"_%n month_::_%n months_" : ["%n 月"],
"_%n day_::_%n days_" : ["%n 天"],
diff --git a/apps/dav/l10n/zh_HK.js b/apps/dav/l10n/zh_HK.js
index 737d7491564..abc214c3cdf 100644
--- a/apps/dav/l10n/zh_HK.js
+++ b/apps/dav/l10n/zh_HK.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} 與群組 {group} 分享了日曆 {calendar}",
"You unshared calendar {calendar} from group {group}" : "您已停止與群組 {group} 分享日曆 {calendar}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} 從 {group} 群組中取消了分享日曆 {calendar}",
+ "Untitled event" : "無標題活動",
"{actor} created event {event} in calendar {calendar}" : "{actor} 新增了日曆 {calendar} 中的活動 {event}",
"You created event {event} in calendar {calendar}" : "您新增了日曆 {calendar} 中的活動 {event}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} 從日曆 {calendar} 中刪除了活動 {event}",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "日期:",
"Where:" : "地點:",
"Description:" : "描述:",
- "Untitled event" : "無標題活動",
"_%n year_::_%n years_" : ["%n 年"],
"_%n month_::_%n months_" : ["%n 月"],
"_%n day_::_%n days_" : ["%n 天"],
@@ -156,6 +156,9 @@ OC.L10N.register(
"Saturday" : "星期六",
"Sunday" : "星期日",
"Save" : "儲存",
+ "Failed to load availability" : "加載可得性失敗",
+ "Saved availability" : "已保存可得性",
+ "Failed to save availability" : "保存可得性失敗",
"Calendar server" : "日曆伺服器",
"Send invitations to attendees" : "發送邀請函給參加者",
"Automatically generate a birthday calendar" : "自動建立生日日曆",
diff --git a/apps/dav/l10n/zh_HK.json b/apps/dav/l10n/zh_HK.json
index 4e48e518ae6..8ca935a748a 100644
--- a/apps/dav/l10n/zh_HK.json
+++ b/apps/dav/l10n/zh_HK.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} 與群組 {group} 分享了日曆 {calendar}",
"You unshared calendar {calendar} from group {group}" : "您已停止與群組 {group} 分享日曆 {calendar}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} 從 {group} 群組中取消了分享日曆 {calendar}",
+ "Untitled event" : "無標題活動",
"{actor} created event {event} in calendar {calendar}" : "{actor} 新增了日曆 {calendar} 中的活動 {event}",
"You created event {event} in calendar {calendar}" : "您新增了日曆 {calendar} 中的活動 {event}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} 從日曆 {calendar} 中刪除了活動 {event}",
@@ -52,7 +53,6 @@
"Date:" : "日期:",
"Where:" : "地點:",
"Description:" : "描述:",
- "Untitled event" : "無標題活動",
"_%n year_::_%n years_" : ["%n 年"],
"_%n month_::_%n months_" : ["%n 月"],
"_%n day_::_%n days_" : ["%n 天"],
@@ -154,6 +154,9 @@
"Saturday" : "星期六",
"Sunday" : "星期日",
"Save" : "儲存",
+ "Failed to load availability" : "加載可得性失敗",
+ "Saved availability" : "已保存可得性",
+ "Failed to save availability" : "保存可得性失敗",
"Calendar server" : "日曆伺服器",
"Send invitations to attendees" : "發送邀請函給參加者",
"Automatically generate a birthday calendar" : "自動建立生日日曆",
diff --git a/apps/dav/l10n/zh_TW.js b/apps/dav/l10n/zh_TW.js
index b0d273abc34..d822b523b26 100644
--- a/apps/dav/l10n/zh_TW.js
+++ b/apps/dav/l10n/zh_TW.js
@@ -25,6 +25,7 @@ OC.L10N.register(
"{actor} shared calendar {calendar} with group {group}" : "{actor} 與群組 {group} 分享了日曆 {calendar}",
"You unshared calendar {calendar} from group {group}" : "您已停止與群組 {group} 分享日曆 {calendar}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} 已停止與群組 {group} 分享日曆 {calendar}",
+ "Untitled event" : "未命名活動",
"{actor} created event {event} in calendar {calendar}" : "{actor} 在日曆 {calendar} 中建立了 {event} 活動",
"You created event {event} in calendar {calendar}" : "您在日曆 {calendar} 中建立了 {event} 活動",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} 在日曆 {calendar} 中刪除了 {event} 活動",
@@ -54,7 +55,6 @@ OC.L10N.register(
"Date:" : "日期:",
"Where:" : "地點:",
"Description:" : "描述:",
- "Untitled event" : "未命名活動",
"_%n year_::_%n years_" : ["%n年"],
"_%n month_::_%n months_" : ["%n月"],
"_%n day_::_%n days_" : ["%n天"],
@@ -156,6 +156,9 @@ OC.L10N.register(
"Saturday" : "週六",
"Sunday" : "週日",
"Save" : "儲存",
+ "Failed to load availability" : "載入可用性失敗",
+ "Saved availability" : "已儲存可用性",
+ "Failed to save availability" : "儲存可用性失敗",
"Calendar server" : "日曆伺服器",
"Send invitations to attendees" : "發送邀請函給參加者",
"Automatically generate a birthday calendar" : "自動生成生日日曆",
diff --git a/apps/dav/l10n/zh_TW.json b/apps/dav/l10n/zh_TW.json
index 09330f45a9c..a0786132472 100644
--- a/apps/dav/l10n/zh_TW.json
+++ b/apps/dav/l10n/zh_TW.json
@@ -23,6 +23,7 @@
"{actor} shared calendar {calendar} with group {group}" : "{actor} 與群組 {group} 分享了日曆 {calendar}",
"You unshared calendar {calendar} from group {group}" : "您已停止與群組 {group} 分享日曆 {calendar}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} 已停止與群組 {group} 分享日曆 {calendar}",
+ "Untitled event" : "未命名活動",
"{actor} created event {event} in calendar {calendar}" : "{actor} 在日曆 {calendar} 中建立了 {event} 活動",
"You created event {event} in calendar {calendar}" : "您在日曆 {calendar} 中建立了 {event} 活動",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} 在日曆 {calendar} 中刪除了 {event} 活動",
@@ -52,7 +53,6 @@
"Date:" : "日期:",
"Where:" : "地點:",
"Description:" : "描述:",
- "Untitled event" : "未命名活動",
"_%n year_::_%n years_" : ["%n年"],
"_%n month_::_%n months_" : ["%n月"],
"_%n day_::_%n days_" : ["%n天"],
@@ -154,6 +154,9 @@
"Saturday" : "週六",
"Sunday" : "週日",
"Save" : "儲存",
+ "Failed to load availability" : "載入可用性失敗",
+ "Saved availability" : "已儲存可用性",
+ "Failed to save availability" : "儲存可用性失敗",
"Calendar server" : "日曆伺服器",
"Send invitations to attendees" : "發送邀請函給參加者",
"Automatically generate a birthday calendar" : "自動生成生日日曆",
diff --git a/apps/dav/lib/AppInfo/Application.php b/apps/dav/lib/AppInfo/Application.php
index 580918a6450..e4eeed61dbe 100644
--- a/apps/dav/lib/AppInfo/Application.php
+++ b/apps/dav/lib/AppInfo/Application.php
@@ -35,18 +35,14 @@ namespace OCA\DAV\AppInfo;
use Exception;
use OCA\DAV\BackgroundJob\UpdateCalendarResourcesRoomsBackgroundJob;
use OCA\DAV\CalDAV\Activity\Backend;
-use OCA\DAV\CalDAV\BirthdayService;
-use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\CalendarManager;
use OCA\DAV\CalDAV\CalendarProvider;
-use OCA\DAV\CalDAV\Reminder\Backend as ReminderBackend;
use OCA\DAV\CalDAV\Reminder\NotificationProvider\AudioProvider;
use OCA\DAV\CalDAV\Reminder\NotificationProvider\EmailProvider;
use OCA\DAV\CalDAV\Reminder\NotificationProvider\PushProvider;
use OCA\DAV\CalDAV\Reminder\NotificationProviderManager;
use OCA\DAV\CalDAV\Reminder\Notifier;
-use OCA\DAV\CalDAV\WebcalCaching\RefreshWebcalService;
use OCA\DAV\Capabilities;
use OCA\DAV\CardDAV\CardDavBackend;
use OCA\DAV\CardDAV\ContactsManager;
@@ -64,19 +60,28 @@ use OCA\DAV\Events\CalendarObjectDeletedEvent;
use OCA\DAV\Events\CalendarObjectMovedToTrashEvent;
use OCA\DAV\Events\CalendarObjectRestoredEvent;
use OCA\DAV\Events\CalendarObjectUpdatedEvent;
+use OCA\DAV\Events\CalendarPublishedEvent;
use OCA\DAV\Events\CalendarRestoredEvent;
use OCA\DAV\Events\CalendarShareUpdatedEvent;
+use OCA\DAV\Events\CalendarUnpublishedEvent;
use OCA\DAV\Events\CalendarUpdatedEvent;
use OCA\DAV\Events\CardCreatedEvent;
use OCA\DAV\Events\CardDeletedEvent;
use OCA\DAV\Events\CardUpdatedEvent;
+use OCA\DAV\Events\SubscriptionCreatedEvent;
+use OCA\DAV\Events\SubscriptionDeletedEvent;
use OCA\DAV\HookManager;
use OCA\DAV\Listener\ActivityUpdaterListener;
use OCA\DAV\Listener\AddressbookListener;
+use OCA\DAV\Listener\BirthdayListener;
use OCA\DAV\Listener\CalendarContactInteractionListener;
use OCA\DAV\Listener\CalendarDeletionDefaultUpdaterListener;
use OCA\DAV\Listener\CalendarObjectReminderUpdaterListener;
+use OCA\DAV\Listener\CalendarPublicationListener;
+use OCA\DAV\Listener\CalendarShareUpdateListener;
use OCA\DAV\Listener\CardListener;
+use OCA\DAV\Listener\ClearPhotoCacheListener;
+use OCA\DAV\Listener\SubscriptionListener;
use OCA\DAV\Search\ContactsSearchProvider;
use OCA\DAV\Search\EventsSearchProvider;
use OCA\DAV\Search\TasksSearchProvider;
@@ -154,6 +159,12 @@ class Application extends App implements IBootstrap {
$context->registerEventListener(CalendarObjectRestoredEvent::class, ActivityUpdaterListener::class);
$context->registerEventListener(CalendarObjectRestoredEvent::class, CalendarObjectReminderUpdaterListener::class);
$context->registerEventListener(CalendarShareUpdatedEvent::class, CalendarContactInteractionListener::class);
+ $context->registerEventListener(CalendarPublishedEvent::class, CalendarPublicationListener::class);
+ $context->registerEventListener(CalendarUnpublishedEvent::class, CalendarPublicationListener::class);
+ $context->registerEventListener(CalendarShareUpdatedEvent::class, CalendarShareUpdateListener::class);
+
+ $context->registerEventListener(SubscriptionCreatedEvent::class, SubscriptionListener::class);
+ $context->registerEventListener(SubscriptionDeletedEvent::class, SubscriptionListener::class);
$context->registerEventListener(AddressBookCreatedEvent::class, AddressbookListener::class);
@@ -163,6 +174,11 @@ class Application extends App implements IBootstrap {
$context->registerEventListener(CardCreatedEvent::class, CardListener::class);
$context->registerEventListener(CardDeletedEvent::class, CardListener::class);
$context->registerEventListener(CardUpdatedEvent::class, CardListener::class);
+ $context->registerEventListener(CardCreatedEvent::class, BirthdayListener::class);
+ $context->registerEventListener(CardDeletedEvent::class, BirthdayListener::class);
+ $context->registerEventListener(CardUpdatedEvent::class, BirthdayListener::class);
+ $context->registerEventListener(CardDeletedEvent::class, ClearPhotoCacheListener::class);
+ $context->registerEventListener(CardUpdatedEvent::class, ClearPhotoCacheListener::class);
$context->registerNotifierService(Notifier::class);
@@ -195,44 +211,6 @@ class Application extends App implements IBootstrap {
}
});
- $birthdayListener = function ($event) use ($container): void {
- if ($event instanceof GenericEvent) {
- /** @var BirthdayService $b */
- $b = $container->query(BirthdayService::class);
- $b->onCardChanged(
- (int) $event->getArgument('addressBookId'),
- (string) $event->getArgument('cardUri'),
- (string) $event->getArgument('cardData')
- );
- }
- };
-
- $dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::createCard', $birthdayListener);
- $dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::updateCard', $birthdayListener);
- $dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::deleteCard', function ($event) use ($container) {
- if ($event instanceof GenericEvent) {
- /** @var BirthdayService $b */
- $b = $container->query(BirthdayService::class);
- $b->onCardDeleted(
- (int) $event->getArgument('addressBookId'),
- (string) $event->getArgument('cardUri')
- );
- }
- });
-
- $clearPhotoCache = function ($event) use ($container): void {
- if ($event instanceof GenericEvent) {
- /** @var PhotoCache $p */
- $p = $container->query(PhotoCache::class);
- $p->delete(
- $event->getArgument('addressBookId'),
- $event->getArgument('cardUri')
- );
- }
- };
- $dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::updateCard', $clearPhotoCache);
- $dispatcher->addListener('\OCA\DAV\CardDAV\CardDavBackend::deleteCard', $clearPhotoCache);
-
$dispatcher->addListener('OC\AccountManager::userUpdated', function (GenericEvent $event) use ($container) {
$user = $event->getSubject();
/** @var SyncService $syncService */
@@ -254,16 +232,6 @@ class Application extends App implements IBootstrap {
// Here we should recalculate if reminders should be sent to new or old sharees
});
- $dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::publishCalendar', function (GenericEvent $event) use ($container) {
- /** @var Backend $backend */
- $backend = $container->query(Backend::class);
- $backend->onCalendarPublication(
- $event->getArgument('calendarData'),
- $event->getArgument('public')
- );
- });
-
-
$dispatcher->addListener('OCP\Federation\TrustedServerEvent::remove',
function (GenericEvent $event) {
/** @var CardDavBackend $cardDavBackend */
@@ -276,48 +244,6 @@ class Application extends App implements IBootstrap {
}
);
- $dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::createSubscription',
- function (GenericEvent $event) use ($container, $serverContainer) {
- $jobList = $serverContainer->getJobList();
- $subscriptionData = $event->getArgument('subscriptionData');
-
- /**
- * Initial subscription refetch
- *
- * @var RefreshWebcalService $refreshWebcalService
- */
- $refreshWebcalService = $container->query(RefreshWebcalService::class);
- $refreshWebcalService->refreshSubscription(
- (string) $subscriptionData['principaluri'],
- (string) $subscriptionData['uri']
- );
-
- $jobList->add(\OCA\DAV\BackgroundJob\RefreshWebcalJob::class, [
- 'principaluri' => $subscriptionData['principaluri'],
- 'uri' => $subscriptionData['uri']
- ]);
- }
- );
-
- $dispatcher->addListener('\OCA\DAV\CalDAV\CalDavBackend::deleteSubscription',
- function (GenericEvent $event) use ($container, $serverContainer) {
- $jobList = $serverContainer->getJobList();
- $subscriptionData = $event->getArgument('subscriptionData');
-
- $jobList->remove(\OCA\DAV\BackgroundJob\RefreshWebcalJob::class, [
- 'principaluri' => $subscriptionData['principaluri'],
- 'uri' => $subscriptionData['uri']
- ]);
-
- /** @var CalDavBackend $calDavBackend */
- $calDavBackend = $container->get(CalDavBackend::class);
- $calDavBackend->purgeAllCachedEventsForSubscription($subscriptionData['id']);
- /** @var ReminderBackend $calDavBackend */
- $reminderBackend = $container->get(ReminderBackend::class);
- $reminderBackend->cleanRemindersForCalendar((int) $subscriptionData['id']);
- }
- );
-
$eventHandler = function () use ($container, $serverContainer): void {
try {
/** @var UpdateCalendarResourcesRoomsBackgroundJob $job */
diff --git a/apps/dav/lib/CalDAV/Activity/Backend.php b/apps/dav/lib/CalDAV/Activity/Backend.php
index 84ba50b8c37..af2d790e10d 100644
--- a/apps/dav/lib/CalDAV/Activity/Backend.php
+++ b/apps/dav/lib/CalDAV/Activity/Backend.php
@@ -119,7 +119,7 @@ class Backend {
* @param array $calendarData
* @param bool $publishStatus
*/
- public function onCalendarPublication(array $calendarData, $publishStatus) {
+ public function onCalendarPublication(array $calendarData, bool $publishStatus): void {
$this->triggerCalendarActivity($publishStatus ? Calendar::SUBJECT_PUBLISH : Calendar::SUBJECT_UNPUBLISH, $calendarData);
}
diff --git a/apps/dav/lib/CalDAV/Activity/Provider/Event.php b/apps/dav/lib/CalDAV/Activity/Provider/Event.php
index 96366f54942..3ed591219af 100644
--- a/apps/dav/lib/CalDAV/Activity/Provider/Event.php
+++ b/apps/dav/lib/CalDAV/Activity/Provider/Event.php
@@ -88,9 +88,9 @@ class Event extends Base {
$params = [
'type' => 'calendar-event',
'id' => $eventData['id'],
- 'name' => $eventData['name'],
-
+ 'name' => trim($eventData['name']) !== '' ? $eventData['name'] : $this->l->t('Untitled event'),
];
+
if (isset($eventData['link']) && is_array($eventData['link']) && $this->appManager->isEnabledForUser('calendar')) {
try {
// The calendar app needs to be manually loaded for the routes to be loaded
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php
index 3253d41a5cd..f445382ce8c 100644
--- a/apps/dav/lib/CalDAV/CalDavBackend.php
+++ b/apps/dav/lib/CalDAV/CalDavBackend.php
@@ -95,8 +95,6 @@ use Sabre\VObject\ParseException;
use Sabre\VObject\Property;
use Sabre\VObject\Reader;
use Sabre\VObject\Recur\EventIterator;
-use Symfony\Component\EventDispatcher\EventDispatcherInterface;
-use Symfony\Component\EventDispatcher\GenericEvent;
use function array_column;
use function array_merge;
use function array_values;
@@ -150,7 +148,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
* @var array
* @psalm-var array<string, string[]>
*/
- public $propertyMap = [
+ public array $propertyMap = [
'{DAV:}displayname' => ['displayname', 'string'],
'{urn:ietf:params:xml:ns:caldav}calendar-description' => ['description', 'string'],
'{urn:ietf:params:xml:ns:caldav}calendar-timezone' => ['timezone', 'string'],
@@ -164,7 +162,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
*
* @var array
*/
- public $subscriptionPropertyMap = [
+ public array $subscriptionPropertyMap = [
'{DAV:}displayname' => ['displayname', 'string'],
'{http://apple.com/ns/ical/}refreshrate' => ['refreshrate', 'string'],
'{http://apple.com/ns/ical/}calendar-order' => ['calendarorder', 'int'],
@@ -195,7 +193,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
];
/** @var array parameters to index */
- public static $indexParameters = [
+ public static array $indexParameters = [
'ATTENDEE' => ['CN'],
'ORGANIZER' => ['CN'],
];
@@ -203,43 +201,19 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
/**
* @var string[] Map of uid => display name
*/
- protected $userDisplayNames;
-
- /** @var IDBConnection */
- private $db;
-
- /** @var Backend */
- private $calendarSharingBackend;
-
- /** @var Principal */
- private $principalBackend;
-
- /** @var IUserManager */
- private $userManager;
-
- /** @var ISecureRandom */
- private $random;
+ protected array $userDisplayNames;
+ private IDBConnection $db;
+ private Backend $calendarSharingBackend;
+ private Principal $principalBackend;
+ private IUserManager $userManager;
+ private ISecureRandom $random;
private LoggerInterface $logger;
+ private IEventDispatcher $dispatcher;
+ private IConfig $config;
+ private bool $legacyEndpoint;
+ private string $dbObjectPropertiesTable = 'calendarobjects_props';
- /** @var IEventDispatcher */
- private $dispatcher;
-
- /** @var EventDispatcherInterface */
- private $legacyDispatcher;
-
- /** @var IConfig */
- private $config;
-
- /** @var bool */
- private $legacyEndpoint;
-
- /** @var string */
- private $dbObjectPropertiesTable = 'calendarobjects_props';
-
- /**
- * CalDavBackend constructor.
- */
public function __construct(IDBConnection $db,
Principal $principalBackend,
IUserManager $userManager,
@@ -247,7 +221,6 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
ISecureRandom $random,
LoggerInterface $logger,
IEventDispatcher $dispatcher,
- EventDispatcherInterface $legacyDispatcher,
IConfig $config,
bool $legacyEndpoint = false) {
$this->db = $db;
@@ -257,7 +230,6 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$this->random = $random;
$this->logger = $logger;
$this->dispatcher = $dispatcher;
- $this->legacyDispatcher = $legacyDispatcher;
$this->config = $config;
$this->legacyEndpoint = $legacyEndpoint;
}
@@ -1139,7 +1111,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
*/
public function getCalendarObject($calendarId, $objectUri, int $calendarType = self::CALENDAR_TYPE_CALENDAR) {
$query = $this->db->getQueryBuilder();
- $query->select(['id', 'uri', 'lastmodified', 'etag', 'calendarid', 'size', 'calendardata', 'componenttype', 'classification'])
+ $query->select(['id', 'uri', 'lastmodified', 'etag', 'calendarid', 'size', 'calendardata', 'componenttype', 'classification', 'deleted_at'])
->from('calendarobjects')
->where($query->expr()->eq('calendarid', $query->createNamedParameter($calendarId)))
->andWhere($query->expr()->eq('uri', $query->createNamedParameter($objectUri)))
@@ -1161,7 +1133,8 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'size' => (int)$row['size'],
'calendardata' => $this->readBlob($row['calendardata']),
'component' => strtolower($row['componenttype']),
- 'classification' => (int)$row['classification']
+ 'classification' => (int)$row['classification'],
+ '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => $row['deleted_at'] === null ? $row['deleted_at'] : (int) $row['deleted_at'],
];
}
@@ -1300,15 +1273,6 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$subscriptionRow = $this->getSubscriptionById($calendarId);
$this->dispatcher->dispatchTyped(new CachedCalendarObjectCreatedEvent((int)$calendarId, $subscriptionRow, [], $objectRow));
- $this->legacyDispatcher->dispatch('\OCA\DAV\CalDAV\CalDavBackend::createCachedCalendarObject', new GenericEvent(
- '\OCA\DAV\CalDAV\CalDavBackend::createCachedCalendarObject',
- [
- 'subscriptionId' => $calendarId,
- 'calendarData' => $subscriptionRow,
- 'shares' => [],
- 'objectData' => $objectRow,
- ]
- ));
}
return '"' . $extraData['etag'] . '"';
@@ -1365,15 +1329,6 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$subscriptionRow = $this->getSubscriptionById($calendarId);
$this->dispatcher->dispatchTyped(new CachedCalendarObjectUpdatedEvent((int)$calendarId, $subscriptionRow, [], $objectRow));
- $this->legacyDispatcher->dispatch('\OCA\DAV\CalDAV\CalDavBackend::updateCachedCalendarObject', new GenericEvent(
- '\OCA\DAV\CalDAV\CalDavBackend::updateCachedCalendarObject',
- [
- 'subscriptionId' => $calendarId,
- 'calendarData' => $subscriptionRow,
- 'shares' => [],
- 'objectData' => $objectRow,
- ]
- ));
}
}
@@ -1481,15 +1436,6 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$subscriptionRow = $this->getSubscriptionById($calendarId);
$this->dispatcher->dispatchTyped(new CachedCalendarObjectDeletedEvent((int)$calendarId, $subscriptionRow, [], $data));
- $this->legacyDispatcher->dispatch('\OCA\DAV\CalDAV\CalDavBackend::deleteCachedCalendarObject', new GenericEvent(
- '\OCA\DAV\CalDAV\CalDavBackend::deleteCachedCalendarObject',
- [
- 'subscriptionId' => $calendarId,
- 'calendarData' => $subscriptionRow,
- 'shares' => [],
- 'objectData' => $data,
- ]
- ));
}
} else {
$pathInfo = pathinfo($data['uri']);
@@ -2500,12 +2446,6 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$subscriptionRow = $this->getSubscriptionById($subscriptionId);
$this->dispatcher->dispatchTyped(new SubscriptionCreatedEvent($subscriptionId, $subscriptionRow));
- $this->legacyDispatcher->dispatch('\OCA\DAV\CalDAV\CalDavBackend::createSubscription', new GenericEvent(
- '\OCA\DAV\CalDAV\CalDavBackend::createSubscription',
- [
- 'subscriptionId' => $subscriptionId,
- 'subscriptionData' => $subscriptionRow,
- ]));
return $subscriptionId;
}
@@ -2553,13 +2493,6 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$subscriptionRow = $this->getSubscriptionById($subscriptionId);
$this->dispatcher->dispatchTyped(new SubscriptionUpdatedEvent((int)$subscriptionId, $subscriptionRow, [], $mutations));
- $this->legacyDispatcher->dispatch('\OCA\DAV\CalDAV\CalDavBackend::updateSubscription', new GenericEvent(
- '\OCA\DAV\CalDAV\CalDavBackend::updateSubscription',
- [
- 'subscriptionId' => $subscriptionId,
- 'subscriptionData' => $subscriptionRow,
- 'propertyMutations' => $mutations,
- ]));
return true;
});
@@ -2574,13 +2507,6 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
public function deleteSubscription($subscriptionId) {
$subscriptionRow = $this->getSubscriptionById($subscriptionId);
- $this->legacyDispatcher->dispatch('\OCA\DAV\CalDAV\CalDavBackend::deleteSubscription', new GenericEvent(
- '\OCA\DAV\CalDAV\CalDavBackend::deleteSubscription',
- [
- 'subscriptionId' => $subscriptionId,
- 'subscriptionData' => $this->getSubscriptionById($subscriptionId),
- ]));
-
$query = $this->db->getQueryBuilder();
$query->delete('calendarsubscriptions')
->where($query->expr()->eq('id', $query->createNamedParameter($subscriptionId)))
@@ -2878,15 +2804,6 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$calendarRow = $this->getCalendarById($calendarId);
$oldShares = $this->getShares($calendarId);
- $this->legacyDispatcher->dispatch('\OCA\DAV\CalDAV\CalDavBackend::updateShares', new GenericEvent(
- '\OCA\DAV\CalDAV\CalDavBackend::updateShares',
- [
- 'calendarId' => $calendarId,
- 'calendarData' => $calendarRow,
- 'shares' => $oldShares,
- 'add' => $add,
- 'remove' => $remove,
- ]));
$this->calendarSharingBackend->updateShares($shareable, $add, $remove);
$this->dispatcher->dispatchTyped(new CalendarShareUpdatedEvent((int)$calendarId, $calendarRow, $oldShares, $add, $remove));
@@ -2908,13 +2825,6 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
public function setPublishStatus($value, $calendar) {
$calendarId = $calendar->getResourceId();
$calendarData = $this->getCalendarById($calendarId);
- $this->legacyDispatcher->dispatch('\OCA\DAV\CalDAV\CalDavBackend::publishCalendar', new GenericEvent(
- '\OCA\DAV\CalDAV\CalDavBackend::updateShares',
- [
- 'calendarId' => $calendarId,
- 'calendarData' => $calendarData,
- 'public' => $value,
- ]));
$query = $this->db->getQueryBuilder();
if ($value) {
diff --git a/apps/dav/lib/CalDAV/Calendar.php b/apps/dav/lib/CalDAV/Calendar.php
index 75c815c3b0a..79d2244b42c 100644
--- a/apps/dav/lib/CalDAV/Calendar.php
+++ b/apps/dav/lib/CalDAV/Calendar.php
@@ -400,7 +400,7 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IRestorable, IShareable
return isset($this->calendarInfo['{http://owncloud.org/ns}public']);
}
- protected function isShared() {
+ public function isShared() {
if (!isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal'])) {
return false;
}
@@ -412,6 +412,13 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IRestorable, IShareable
return isset($this->calendarInfo['{http://calendarserver.org/ns/}source']);
}
+ public function isDeleted(): bool {
+ if (!isset($this->calendarInfo[TrashbinPlugin::PROPERTY_DELETED_AT])) {
+ return false;
+ }
+ return $this->calendarInfo[TrashbinPlugin::PROPERTY_DELETED_AT] !== null;
+ }
+
/**
* @inheritDoc
*/
diff --git a/apps/dav/lib/CalDAV/PublicCalendar.php b/apps/dav/lib/CalDAV/PublicCalendar.php
index 4a29c8d237a..16c7f86917d 100644
--- a/apps/dav/lib/CalDAV/PublicCalendar.php
+++ b/apps/dav/lib/CalDAV/PublicCalendar.php
@@ -84,7 +84,7 @@ class PublicCalendar extends Calendar {
* public calendars are always shared
* @return bool
*/
- protected function isShared() {
+ public function isShared() {
return true;
}
}
diff --git a/apps/dav/lib/CalDAV/Reminder/NotificationProvider/EmailProvider.php b/apps/dav/lib/CalDAV/Reminder/NotificationProvider/EmailProvider.php
index c147b47860e..d4aea6215ea 100644
--- a/apps/dav/lib/CalDAV/Reminder/NotificationProvider/EmailProvider.php
+++ b/apps/dav/lib/CalDAV/Reminder/NotificationProvider/EmailProvider.php
@@ -260,7 +260,10 @@ class EmailProvider extends AbstractProvider {
$emailAddressesOfDelegates = $delegates->getParts();
foreach ($emailAddressesOfDelegates as $addressesOfDelegate) {
if (strcasecmp($addressesOfDelegate, 'mailto:') === 0) {
- $emailAddresses[substr($addressesOfDelegate, 7)] = [];
+ $delegateEmail = substr($addressesOfDelegate, 7);
+ if ($delegateEmail !== false && $this->mailer->validateMailAddress($delegateEmail)) {
+ $emailAddresses[$delegateEmail] = [];
+ }
}
}
@@ -317,8 +320,12 @@ class EmailProvider extends AbstractProvider {
if (!$this->hasAttendeeMailURI($attendee)) {
return null;
}
+ $attendeeEMail = substr($attendee->getValue(), 7);
+ if ($attendeeEMail === false || !$this->mailer->validateMailAddress($attendeeEMail)) {
+ return null;
+ }
- return substr($attendee->getValue(), 7);
+ return $attendeeEMail;
}
/**
diff --git a/apps/dav/lib/CalDAV/Reminder/ReminderService.php b/apps/dav/lib/CalDAV/Reminder/ReminderService.php
index b33bc8a175a..2a065469052 100644
--- a/apps/dav/lib/CalDAV/Reminder/ReminderService.php
+++ b/apps/dav/lib/CalDAV/Reminder/ReminderService.php
@@ -38,6 +38,7 @@ use OCP\IGroup;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserManager;
+use Psr\Log\LoggerInterface;
use Sabre\VObject;
use Sabre\VObject\Component\VAlarm;
use Sabre\VObject\Component\VEvent;
@@ -46,6 +47,7 @@ use Sabre\VObject\ParseException;
use Sabre\VObject\Recur\EventIterator;
use Sabre\VObject\Recur\MaxInstancesExceededException;
use Sabre\VObject\Recur\NoInstancesException;
+use function count;
use function strcasecmp;
class ReminderService {
@@ -71,6 +73,9 @@ class ReminderService {
/** @var IConfig */
private $config;
+ /** @var LoggerInterface */
+ private $logger;
+
public const REMINDER_TYPE_EMAIL = 'EMAIL';
public const REMINDER_TYPE_DISPLAY = 'DISPLAY';
public const REMINDER_TYPE_AUDIO = 'AUDIO';
@@ -86,24 +91,14 @@ class ReminderService {
self::REMINDER_TYPE_AUDIO
];
- /**
- * ReminderService constructor.
- *
- * @param Backend $backend
- * @param NotificationProviderManager $notificationProviderManager
- * @param IUserManager $userManager
- * @param IGroupManager $groupManager
- * @param CalDavBackend $caldavBackend
- * @param ITimeFactory $timeFactory
- * @param IConfig $config
- */
public function __construct(Backend $backend,
NotificationProviderManager $notificationProviderManager,
IUserManager $userManager,
IGroupManager $groupManager,
CalDavBackend $caldavBackend,
ITimeFactory $timeFactory,
- IConfig $config) {
+ IConfig $config,
+ LoggerInterface $logger) {
$this->backend = $backend;
$this->notificationProviderManager = $notificationProviderManager;
$this->userManager = $userManager;
@@ -111,6 +106,7 @@ class ReminderService {
$this->caldavBackend = $caldavBackend;
$this->timeFactory = $timeFactory;
$this->config = $config;
+ $this->logger = $logger;
}
/**
@@ -119,8 +115,11 @@ class ReminderService {
* @throws NotificationProvider\ProviderNotAvailableException
* @throws NotificationTypeDoesNotExistException
*/
- public function processReminders():void {
+ public function processReminders() :void {
$reminders = $this->backend->getRemindersToProcess();
+ $this->logger->debug('{numReminders} reminders to process', [
+ 'numReminders' => count($reminders),
+ ]);
foreach ($reminders as $reminder) {
$calendarData = is_resource($reminder['calendardata'])
@@ -133,22 +132,34 @@ class ReminderService {
$vcalendar = $this->parseCalendarData($calendarData);
if (!$vcalendar) {
+ $this->logger->debug('Reminder {id} does not belong to a valid calendar', [
+ 'id' => $reminder['id'],
+ ]);
$this->backend->removeReminder($reminder['id']);
continue;
}
$vevent = $this->getVEventByRecurrenceId($vcalendar, $reminder['recurrence_id'], $reminder['is_recurrence_exception']);
if (!$vevent) {
+ $this->logger->debug('Reminder {id} does not belong to a valid event', [
+ 'id' => $reminder['id'],
+ ]);
$this->backend->removeReminder($reminder['id']);
continue;
}
if ($this->wasEventCancelled($vevent)) {
+ $this->logger->debug('Reminder {id} belongs to a cancelled event', [
+ 'id' => $reminder['id'],
+ ]);
$this->deleteOrProcessNext($reminder, $vevent);
continue;
}
if (!$this->notificationProviderManager->hasProvider($reminder['type'])) {
+ $this->logger->debug('Reminder {id} does not belong to a valid notification provider', [
+ 'id' => $reminder['id'],
+ ]);
$this->deleteOrProcessNext($reminder, $vevent);
continue;
}
@@ -164,6 +175,10 @@ class ReminderService {
$users[] = $user;
}
+ $this->logger->debug('Reminder {id} will be sent to {numUsers} users', [
+ 'id' => $reminder['id'],
+ 'numUsers' => count($users),
+ ]);
$notificationProvider = $this->notificationProviderManager->getProvider($reminder['type']);
$notificationProvider->send($vevent, $reminder['displayname'], $users);
diff --git a/apps/dav/lib/CalDAV/Schedule/Plugin.php b/apps/dav/lib/CalDAV/Schedule/Plugin.php
index 96bacce4454..74865297944 100644
--- a/apps/dav/lib/CalDAV/Schedule/Plugin.php
+++ b/apps/dav/lib/CalDAV/Schedule/Plugin.php
@@ -30,6 +30,7 @@ namespace OCA\DAV\CalDAV\Schedule;
use DateTimeZone;
use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\CalDAV\Calendar;
use OCA\DAV\CalDAV\CalendarHome;
use OCP\IConfig;
use Sabre\CalDAV\ICalendar;
@@ -299,12 +300,14 @@ EOF;
return null;
}
+ $isResourceOrRoom = strpos($principalUrl, 'principals/calendar-resources') === 0 ||
+ strpos($principalUrl, 'principals/calendar-rooms') === 0;
+
if (strpos($principalUrl, 'principals/users') === 0) {
[, $userId] = split($principalUrl);
$uri = $this->config->getUserValue($userId, 'dav', 'defaultCalendar', CalDavBackend::PERSONAL_CALENDAR_URI);
$displayName = CalDavBackend::PERSONAL_CALENDAR_NAME;
- } elseif (strpos($principalUrl, 'principals/calendar-resources') === 0 ||
- strpos($principalUrl, 'principals/calendar-rooms') === 0) {
+ } elseif ($isResourceOrRoom) {
$uri = CalDavBackend::RESOURCE_BOOKING_CALENDAR_URI;
$displayName = CalDavBackend::RESOURCE_BOOKING_CALENDAR_NAME;
} else {
@@ -316,9 +319,40 @@ EOF;
/** @var CalendarHome $calendarHome */
$calendarHome = $this->server->tree->getNodeForPath($calendarHomePath);
if (!$calendarHome->childExists($uri)) {
- $calendarHome->getCalDAVBackend()->createCalendar($principalUrl, $uri, [
- '{DAV:}displayname' => $displayName,
- ]);
+ // If the default calendar doesn't exist
+ if ($isResourceOrRoom) {
+ $calendarHome->getCalDAVBackend()->createCalendar($principalUrl, $uri, [
+ '{DAV:}displayname' => $displayName,
+ ]);
+ } else {
+ // And we're not handling scheduling on resource/room booking
+ $userCalendars = [];
+ /**
+ * If the default calendar of the user isn't set and the
+ * fallback doesn't match any of the user's calendar
+ * try to find the first "personal" calendar we can write to
+ * instead of creating a new one.
+ * A appropriate personal calendar to receive invites:
+ * - isn't a calendar subscription
+ * - user can write to it (no virtual/3rd-party calendars)
+ * - calendar isn't a share
+ */
+ foreach ($calendarHome->getChildren() as $node) {
+ if ($node instanceof Calendar && !$node->isSubscription() && $node->canWrite() && !$node->isShared() && !$node->isDeleted()) {
+ $userCalendars[] = $node;
+ }
+ }
+
+ if (count($userCalendars) > 0) {
+ // Calendar backend returns calendar by calendarorder property
+ $uri = $userCalendars[0]->getName();
+ } else {
+ // Otherwise if we have really nothing, create a new calendar
+ $calendarHome->getCalDAVBackend()->createCalendar($principalUrl, $uri, [
+ '{DAV:}displayname' => $displayName,
+ ]);
+ }
+ }
}
$result = $this->server->getPropertiesForPath($calendarHomePath . '/' . $uri, [], 1);
diff --git a/apps/dav/lib/CalDAV/WebcalCaching/RefreshWebcalService.php b/apps/dav/lib/CalDAV/WebcalCaching/RefreshWebcalService.php
index 49f66735345..eadeea3457c 100644
--- a/apps/dav/lib/CalDAV/WebcalCaching/RefreshWebcalService.php
+++ b/apps/dav/lib/CalDAV/WebcalCaching/RefreshWebcalService.php
@@ -56,14 +56,15 @@ use function count;
class RefreshWebcalService {
/** @var CalDavBackend */
- private $calDavBackend;
+ private CalDavBackend $calDavBackend;
/** @var IClientService */
- private $clientService;
+ private IClientService $clientService;
/** @var IConfig */
- private $config;
+ private IConfig $config;
+ /** @var LoggerInterface */
private LoggerInterface $logger;
public const REFRESH_RATE = '{http://apple.com/ns/ical/}refreshrate';
@@ -71,13 +72,7 @@ class RefreshWebcalService {
public const STRIP_ATTACHMENTS = '{http://calendarserver.org/ns/}subscribed-strip-attachments';
public const STRIP_TODOS = '{http://calendarserver.org/ns/}subscribed-strip-todos';
- /**
- * RefreshWebcalJob constructor.
- */
- public function __construct(CalDavBackend $calDavBackend,
- IClientService $clientService,
- IConfig $config,
- LoggerInterface $logger) {
+ public function __construct(CalDavBackend $calDavBackend, IClientService $clientService, IConfig $config, LoggerInterface $logger) {
$this->calDavBackend = $calDavBackend;
$this->clientService = $clientService;
$this->config = $config;
@@ -131,12 +126,12 @@ class RefreshWebcalService {
continue;
}
- $uri = $this->getRandomCalendarObjectUri();
+ $objectUri = $this->getRandomCalendarObjectUri();
$calendarData = $vObject->serialize();
try {
- $this->calDavBackend->createCalendarObject($subscription['id'], $uri, $calendarData, CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION);
+ $this->calDavBackend->createCalendarObject($subscription['id'], $objectUri, $calendarData, CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION);
} catch (NoInstancesException | BadRequest $ex) {
- $this->logger->error($ex->getMessage(), ['exception' => $ex]);
+ $this->logger->error('Unable to create calendar object from subscription {subscriptionId}', ['exception' => $ex, 'subscriptionId' => $subscription['id'], 'source' => $subscription['source']]);
}
}
@@ -147,20 +142,14 @@ class RefreshWebcalService {
$this->updateSubscription($subscription, $mutations);
} catch (ParseException $ex) {
- $subscriptionId = $subscription['id'];
-
- $this->logger->error("Subscription $subscriptionId could not be refreshed due to a parsing error", ['exception' => $ex]);
+ $this->logger->error("Subscription {subscriptionId} could not be refreshed due to a parsing error", ['exception' => $ex, 'subscriptionId' => $subscription['id']]);
}
}
/**
* loads subscription from backend
- *
- * @param string $principalUri
- * @param string $uri
- * @return array|null
*/
- public function getSubscription(string $principalUri, string $uri) {
+ public function getSubscription(string $principalUri, string $uri): ?array {
$subscriptions = array_values(array_filter(
$this->calDavBackend->getSubscriptionsForUser($principalUri),
function ($sub) use ($uri) {
@@ -177,12 +166,8 @@ class RefreshWebcalService {
/**
* gets webcal feed from remote server
- *
- * @param array $subscription
- * @param array &$mutations
- * @return null|string
*/
- private function queryWebcalFeed(array $subscription, array &$mutations) {
+ private function queryWebcalFeed(array $subscription, array &$mutations): ?string {
$client = $this->clientService->newClient();
$didBreak301Chain = false;
@@ -192,7 +177,7 @@ class RefreshWebcalService {
$handlerStack->push(Middleware::mapRequest(function (RequestInterface $request) {
return $request
->withHeader('Accept', 'text/calendar, application/calendar+json, application/calendar+xml')
- ->withHeader('User-Agent', 'Nextcloud Webcal Crawler');
+ ->withHeader('User-Agent', 'Nextcloud Webcal Service');
}));
$handlerStack->push(Middleware::mapResponse(function (ResponseInterface $response) use (&$didBreak301Chain, &$latestLocation) {
if (!$didBreak301Chain) {
@@ -244,7 +229,7 @@ class RefreshWebcalService {
$jCalendar = Reader::readJson($body, Reader::OPTION_FORGIVING);
} catch (Exception $ex) {
// In case of a parsing error return null
- $this->logger->debug("Subscription $subscriptionId could not be parsed");
+ $this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]);
return null;
}
return $jCalendar->serialize();
@@ -254,7 +239,7 @@ class RefreshWebcalService {
$xCalendar = Reader::readXML($body);
} catch (Exception $ex) {
// In case of a parsing error return null
- $this->logger->debug("Subscription $subscriptionId could not be parsed");
+ $this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]);
return null;
}
return $xCalendar->serialize();
@@ -265,7 +250,7 @@ class RefreshWebcalService {
$vCalendar = Reader::read($body);
} catch (Exception $ex) {
// In case of a parsing error return null
- $this->logger->debug("Subscription $subscriptionId could not be parsed");
+ $this->logger->warning("Subscription $subscriptionId could not be parsed", ['exception' => $ex]);
return null;
}
return $vCalendar->serialize();
@@ -291,11 +276,8 @@ class RefreshWebcalService {
* - the webcal feed suggests a refreshrate
* - return suggested refreshrate if user didn't set a custom one
*
- * @param array $subscription
- * @param string $webcalData
- * @return string|null
*/
- private function checkWebcalDataForRefreshRate($subscription, $webcalData) {
+ private function checkWebcalDataForRefreshRate(array $subscription, string $webcalData): ?string {
// if there is no refreshrate stored in the database, check the webcal feed
// whether it suggests any refresh rate and store that in the database
if (isset($subscription[self::REFRESH_RATE]) && $subscription[self::REFRESH_RATE] !== null) {
@@ -353,7 +335,7 @@ class RefreshWebcalService {
* @param string $url
* @return string|null
*/
- private function cleanURL(string $url) {
+ private function cleanURL(string $url): ?string {
$parsed = parse_url($url);
if ($parsed === false) {
return null;
diff --git a/apps/dav/lib/CardDAV/Activity/Backend.php b/apps/dav/lib/CardDAV/Activity/Backend.php
index b713284e182..184b3f0cb10 100644
--- a/apps/dav/lib/CardDAV/Activity/Backend.php
+++ b/apps/dav/lib/CardDAV/Activity/Backend.php
@@ -103,7 +103,14 @@ class Backend {
return;
}
- $principal = explode('/', $addressbookData['principaluri']);
+ $principalUri = $addressbookData['principaluri'];
+
+ // We are not interested in changes from the system addressbook
+ if ($principalUri === 'principals/system/system') {
+ return;
+ }
+
+ $principal = explode('/', $principalUri);
$owner = array_pop($principal);
$currentUser = $this->userSession->getUser();
@@ -393,7 +400,14 @@ class Backend {
return;
}
- $principal = explode('/', $addressbookData['principaluri']);
+ $principalUri = $addressbookData['principaluri'];
+
+ // We are not interested in changes from the system addressbook
+ if ($principalUri === 'principals/system/system') {
+ return;
+ }
+
+ $principal = explode('/', $principalUri);
$owner = array_pop($principal);
$currentUser = $this->userSession->getUser();
diff --git a/apps/dav/lib/CardDAV/AddressBookImpl.php b/apps/dav/lib/CardDAV/AddressBookImpl.php
index 3db20cb4220..2f7f0a22900 100644
--- a/apps/dav/lib/CardDAV/AddressBookImpl.php
+++ b/apps/dav/lib/CardDAV/AddressBookImpl.php
@@ -12,6 +12,7 @@
* @author Joas Schilling <coding@schilljs.com>
* @author John Molakvoæ <skjnldsv@protonmail.com>
* @author Julius Härtl <jus@bitgrid.net>
+ * @author Thomas Citharel <nextcloud@tcit.fr>
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @license AGPL-3.0
@@ -206,7 +207,7 @@ class AddressBookImpl implements IAddressBook {
}
/**
- * @param object $id the unique identifier to a contact
+ * @param int $id the unique identifier to a contact
* @return bool successful or not
* @since 5.0.0
*/
diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php
index 864f3da9367..745ca7801b7 100644
--- a/apps/dav/lib/CardDAV/CardDavBackend.php
+++ b/apps/dav/lib/CardDAV/CardDavBackend.php
@@ -58,30 +58,19 @@ use Sabre\CardDAV\Plugin;
use Sabre\DAV\Exception\BadRequest;
use Sabre\VObject\Component\VCard;
use Sabre\VObject\Reader;
-use Symfony\Component\EventDispatcher\EventDispatcherInterface;
-use Symfony\Component\EventDispatcher\GenericEvent;
class CardDavBackend implements BackendInterface, SyncSupport {
public const PERSONAL_ADDRESSBOOK_URI = 'contacts';
public const PERSONAL_ADDRESSBOOK_NAME = 'Contacts';
- /** @var Principal */
- private $principalBackend;
-
- /** @var string */
- private $dbCardsTable = 'cards';
-
- /** @var string */
- private $dbCardsPropertiesTable = 'cards_properties';
-
- /** @var IDBConnection */
- private $db;
-
- /** @var Backend */
- private $sharingBackend;
+ private Principal $principalBackend;
+ private string $dbCardsTable = 'cards';
+ private string $dbCardsPropertiesTable = 'cards_properties';
+ private IDBConnection $db;
+ private Backend $sharingBackend;
/** @var array properties to index */
- public static $indexProperties = [
+ public static array $indexProperties = [
'BDAY', 'UID', 'N', 'FN', 'TITLE', 'ROLE', 'NOTE', 'NICKNAME',
'ORG', 'CATEGORIES', 'EMAIL', 'TEL', 'IMPP', 'ADR', 'URL', 'GEO',
'CLOUD', 'X-SOCIALPROFILE'];
@@ -89,18 +78,10 @@ class CardDavBackend implements BackendInterface, SyncSupport {
/**
* @var string[] Map of uid => display name
*/
- protected $userDisplayNames;
-
- /** @var IUserManager */
- private $userManager;
-
- /** @var IEventDispatcher */
- private $dispatcher;
-
- /** @var EventDispatcherInterface */
- private $legacyDispatcher;
-
- private $etagCache = [];
+ protected array $userDisplayNames;
+ private IUserManager $userManager;
+ private IEventDispatcher $dispatcher;
+ private array $etagCache = [];
/**
* CardDavBackend constructor.
@@ -110,19 +91,16 @@ class CardDavBackend implements BackendInterface, SyncSupport {
* @param IUserManager $userManager
* @param IGroupManager $groupManager
* @param IEventDispatcher $dispatcher
- * @param EventDispatcherInterface $legacyDispatcher
*/
public function __construct(IDBConnection $db,
Principal $principalBackend,
IUserManager $userManager,
IGroupManager $groupManager,
- IEventDispatcher $dispatcher,
- EventDispatcherInterface $legacyDispatcher) {
+ IEventDispatcher $dispatcher) {
$this->db = $db;
$this->principalBackend = $principalBackend;
$this->userManager = $userManager;
$this->dispatcher = $dispatcher;
- $this->legacyDispatcher = $legacyDispatcher;
$this->sharingBackend = new Backend($this->db, $this->userManager, $groupManager, $principalBackend, 'addressbook');
}
@@ -692,11 +670,6 @@ class CardDavBackend implements BackendInterface, SyncSupport {
$shares = $this->getShares($addressBookId);
$objectRow = $this->getCard($addressBookId, $cardUri);
$this->dispatcher->dispatchTyped(new CardCreatedEvent($addressBookId, $addressBookData, $shares, $objectRow));
- $this->legacyDispatcher->dispatch('\OCA\DAV\CardDAV\CardDavBackend::createCard',
- new GenericEvent(null, [
- 'addressBookId' => $addressBookId,
- 'cardUri' => $cardUri,
- 'cardData' => $cardData]));
return '"' . $etag . '"';
}
@@ -756,12 +729,6 @@ class CardDavBackend implements BackendInterface, SyncSupport {
$shares = $this->getShares($addressBookId);
$objectRow = $this->getCard($addressBookId, $cardUri);
$this->dispatcher->dispatchTyped(new CardUpdatedEvent($addressBookId, $addressBookData, $shares, $objectRow));
- $this->legacyDispatcher->dispatch('\OCA\DAV\CardDAV\CardDavBackend::updateCard',
- new GenericEvent(null, [
- 'addressBookId' => $addressBookId,
- 'cardUri' => $cardUri,
- 'cardData' => $cardData]));
-
return '"' . $etag . '"';
}
@@ -793,11 +760,6 @@ class CardDavBackend implements BackendInterface, SyncSupport {
if ($ret === 1) {
if ($cardId !== null) {
$this->dispatcher->dispatchTyped(new CardDeletedEvent($addressBookId, $addressBookData, $shares, $objectRow));
- $this->legacyDispatcher->dispatch('\OCA\DAV\CardDAV\CardDavBackend::deleteCard',
- new GenericEvent(null, [
- 'addressBookId' => $addressBookId,
- 'cardUri' => $cardUri]));
-
$this->purgeProperties($addressBookId, $cardId);
}
return true;
diff --git a/apps/dav/lib/CardDAV/PhotoCache.php b/apps/dav/lib/CardDAV/PhotoCache.php
index 777a0b0e169..101111f9310 100644
--- a/apps/dav/lib/CardDAV/PhotoCache.php
+++ b/apps/dav/lib/CardDAV/PhotoCache.php
@@ -133,7 +133,7 @@ class PhotoCache {
throw new NotFoundException;
}
- $photo = new \OC_Image();
+ $photo = new \OCP\Image();
/** @var ISimpleFile $file */
$file = $folder->getFile('photo.' . $ext);
$photo->loadFromData($file->getContent());
diff --git a/apps/dav/lib/Command/CreateCalendar.php b/apps/dav/lib/Command/CreateCalendar.php
index 8a945f32eba..08f937dff9d 100644
--- a/apps/dav/lib/Command/CreateCalendar.php
+++ b/apps/dav/lib/Command/CreateCalendar.php
@@ -96,7 +96,6 @@ class CreateCalendar extends Command {
$random = \OC::$server->getSecureRandom();
$logger = \OC::$server->get(LoggerInterface::class);
$dispatcher = \OC::$server->get(IEventDispatcher::class);
- $legacyDispatcher = \OC::$server->getEventDispatcher();
$config = \OC::$server->get(IConfig::class);
$name = $input->getArgument('name');
@@ -108,7 +107,6 @@ class CreateCalendar extends Command {
$random,
$logger,
$dispatcher,
- $legacyDispatcher,
$config
);
$caldav->createCalendar("principals/users/$user", $name, []);
diff --git a/apps/dav/lib/Connector/Sabre/CommentPropertiesPlugin.php b/apps/dav/lib/Connector/Sabre/CommentPropertiesPlugin.php
index 4a1205e8606..eaa7f1bc2d2 100644
--- a/apps/dav/lib/Connector/Sabre/CommentPropertiesPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/CommentPropertiesPlugin.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -115,30 +116,27 @@ class CommentPropertiesPlugin extends ServerPlugin {
return $this->commentsManager->getNumberOfCommentsForObject('files', (string)$node->getId());
});
- $propFind->handle(self::PROPERTY_NAME_HREF, function () use ($node) {
+ $propFind->handle(self::PROPERTY_NAME_HREF, function () use ($node): ?string {
return $this->getCommentsLink($node);
});
- $propFind->handle(self::PROPERTY_NAME_UNREAD, function () use ($node): ?bool {
+ $propFind->handle(self::PROPERTY_NAME_UNREAD, function () use ($node): ?int {
return $this->cachedUnreadCount[$node->getId()] ?? $this->getUnreadCount($node);
});
}
/**
* Returns a reference to the comments node
- *
- * @return array|string|null
*/
- public function getCommentsLink(Node $node) {
+ public function getCommentsLink(Node $node): ?string {
$href = $this->server->getBaseUri();
$entryPoint = strpos($href, '/remote.php/');
if ($entryPoint === false) {
// in case we end up somewhere else, unexpectedly.
return null;
}
- $commentsPart = 'dav/comments/files/' . rawurldecode($node->getId());
- $href = substr_replace($href, $commentsPart, $entryPoint + strlen('/remote.php/'));
- return $href;
+ $commentsPart = 'dav/comments/files/' . rawurldecode((string)$node->getId());
+ return substr_replace($href, $commentsPart, $entryPoint + strlen('/remote.php/'));
}
/**
diff --git a/apps/dav/lib/Connector/Sabre/ExceptionLoggerPlugin.php b/apps/dav/lib/Connector/Sabre/ExceptionLoggerPlugin.php
index ea94b5c8933..ebf3e4021eb 100644
--- a/apps/dav/lib/Connector/Sabre/ExceptionLoggerPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/ExceptionLoggerPlugin.php
@@ -29,6 +29,7 @@ namespace OCA\DAV\Connector\Sabre;
use OCA\DAV\Connector\Sabre\Exception\FileLocked;
use OCA\DAV\Connector\Sabre\Exception\PasswordLoginForbidden;
+use OCA\DAV\Exception\ServerMaintenanceMode;
use OCP\Files\StorageNotAvailableException;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Exception\BadRequest;
@@ -81,6 +82,7 @@ class ExceptionLoggerPlugin extends \Sabre\DAV\ServerPlugin {
FileLocked::class => true,
// An invalid range is requested
RequestedRangeNotSatisfiable::class => true,
+ ServerMaintenanceMode::class => true,
];
private string $appName;
@@ -114,17 +116,12 @@ class ExceptionLoggerPlugin extends \Sabre\DAV\ServerPlugin {
*/
public function logException(\Throwable $ex) {
$exceptionClass = get_class($ex);
- if (isset($this->nonFatalExceptions[$exceptionClass]) ||
- (
- $exceptionClass === ServiceUnavailable::class &&
- $ex->getMessage() === 'System in maintenance mode.'
- )
- ) {
+ if (isset($this->nonFatalExceptions[$exceptionClass])) {
$this->logger->debug($ex->getMessage(), [
'app' => $this->appName,
'exception' => $ex,
]);
- return;
+ return;
}
$this->logger->critical($ex->getMessage(), [
diff --git a/apps/dav/lib/Connector/Sabre/File.php b/apps/dav/lib/Connector/Sabre/File.php
index 37fb109a3bd..ebcfdabc6b3 100644
--- a/apps/dav/lib/Connector/Sabre/File.php
+++ b/apps/dav/lib/Connector/Sabre/File.php
@@ -215,15 +215,26 @@ class File extends Node implements IFile {
$data = $tmpData;
}
- $data = HashWrapper::wrap($data, 'md5', function ($hash) {
- $this->header('X-Hash-MD5: ' . $hash);
- });
- $data = HashWrapper::wrap($data, 'sha1', function ($hash) {
- $this->header('X-Hash-SHA1: ' . $hash);
- });
- $data = HashWrapper::wrap($data, 'sha256', function ($hash) {
- $this->header('X-Hash-SHA256: ' . $hash);
- });
+ if ($this->request->getHeader('X-HASH') !== '') {
+ $hash = $this->request->getHeader('X-HASH');
+ if ($hash === 'all' || $hash === 'md5') {
+ $data = HashWrapper::wrap($data, 'md5', function ($hash) {
+ $this->header('X-Hash-MD5: ' . $hash);
+ });
+ }
+
+ if ($hash === 'all' || $hash === 'sha1') {
+ $data = HashWrapper::wrap($data, 'sha1', function ($hash) {
+ $this->header('X-Hash-SHA1: ' . $hash);
+ });
+ }
+
+ if ($hash === 'all' || $hash === 'sha256') {
+ $data = HashWrapper::wrap($data, 'sha256', function ($hash) {
+ $this->header('X-Hash-SHA256: ' . $hash);
+ });
+ }
+ }
if ($partStorage->instanceOfStorage(Storage\IWriteStreamStorage::class)) {
$isEOF = false;
diff --git a/apps/dav/lib/Connector/Sabre/MaintenancePlugin.php b/apps/dav/lib/Connector/Sabre/MaintenancePlugin.php
index e7e3b273b98..1fc02320805 100644
--- a/apps/dav/lib/Connector/Sabre/MaintenancePlugin.php
+++ b/apps/dav/lib/Connector/Sabre/MaintenancePlugin.php
@@ -27,6 +27,7 @@
*/
namespace OCA\DAV\Connector\Sabre;
+use OCA\DAV\Exception\ServerMaintenanceMode;
use OCP\IConfig;
use OCP\IL10N;
use OCP\Util;
@@ -82,10 +83,10 @@ class MaintenancePlugin extends ServerPlugin {
*/
public function checkMaintenanceMode() {
if ($this->config->getSystemValueBool('maintenance')) {
- throw new ServiceUnavailable($this->l10n->t('System is in maintenance mode.'));
+ throw new ServerMaintenanceMode($this->l10n->t('System is in maintenance mode.'));
}
if (Util::needUpgrade()) {
- throw new ServiceUnavailable($this->l10n->t('Upgrade needed'));
+ throw new ServerMaintenanceMode($this->l10n->t('Upgrade needed'));
}
return true;
diff --git a/apps/dav/lib/Events/CalendarPublishedEvent.php b/apps/dav/lib/Events/CalendarPublishedEvent.php
index 7b3b95f2f77..a95e9f294c1 100644
--- a/apps/dav/lib/Events/CalendarPublishedEvent.php
+++ b/apps/dav/lib/Events/CalendarPublishedEvent.php
@@ -6,6 +6,7 @@ declare(strict_types=1);
* @copyright Copyright (c) 2020, Georg Ehrke
*
* @author Georg Ehrke <oc.list@georgehrke.com>
+ * @author Thomas Citharel <nextcloud@tcit.fr>
*
* @license GNU AGPL version 3 or any later version
*
@@ -34,15 +35,9 @@ use OCP\EventDispatcher\Event;
* @since 20.0.0
*/
class CalendarPublishedEvent extends Event {
-
- /** @var int */
- private $calendarId;
-
- /** @var array */
- private $calendarData;
-
- /** @var string */
- private $publicUri;
+ private int $calendarId;
+ private array $calendarData;
+ private string $publicUri;
/**
* CalendarPublishedEvent constructor.
diff --git a/apps/dav/lib/Events/CalendarUnpublishedEvent.php b/apps/dav/lib/Events/CalendarUnpublishedEvent.php
index 0cea53c6f0d..b2536fc7aef 100644
--- a/apps/dav/lib/Events/CalendarUnpublishedEvent.php
+++ b/apps/dav/lib/Events/CalendarUnpublishedEvent.php
@@ -6,6 +6,7 @@ declare(strict_types=1);
* @copyright Copyright (c) 2020, Georg Ehrke
*
* @author Georg Ehrke <oc.list@georgehrke.com>
+ * @author Thomas Citharel <nextcloud@tcit.fr>
*
* @license GNU AGPL version 3 or any later version
*
@@ -34,12 +35,8 @@ use OCP\EventDispatcher\Event;
* @since 20.0.0
*/
class CalendarUnpublishedEvent extends Event {
-
- /** @var int */
- private $calendarId;
-
- /** @var array */
- private $calendarData;
+ private int $calendarId;
+ private array $calendarData;
/**
* CalendarUnpublishedEvent constructor.
diff --git a/apps/dav/lib/Exception/ServerMaintenanceMode.php b/apps/dav/lib/Exception/ServerMaintenanceMode.php
new file mode 100644
index 00000000000..9dad9f2d4d1
--- /dev/null
+++ b/apps/dav/lib/Exception/ServerMaintenanceMode.php
@@ -0,0 +1,31 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2022 Joas Schilling <coding@schilljs.com>
+ *
+ * @author Joas Schilling <coding@schilljs.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+namespace OCA\DAV\Exception;
+
+use Sabre\DAV\Exception\ServiceUnavailable;
+
+class ServerMaintenanceMode extends ServiceUnavailable {
+
+}
diff --git a/apps/dav/lib/Listener/BirthdayListener.php b/apps/dav/lib/Listener/BirthdayListener.php
new file mode 100644
index 00000000000..43ad782fa9e
--- /dev/null
+++ b/apps/dav/lib/Listener/BirthdayListener.php
@@ -0,0 +1,54 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2022 Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @author Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @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\DAV\Listener;
+
+use OCA\DAV\CalDAV\BirthdayService;
+use OCA\DAV\Events\CardCreatedEvent;
+use OCA\DAV\Events\CardDeletedEvent;
+use OCA\DAV\Events\CardUpdatedEvent;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+
+class BirthdayListener implements IEventListener {
+ private BirthdayService $birthdayService;
+
+ public function __construct(BirthdayService $birthdayService) {
+ $this->birthdayService = $birthdayService;
+ }
+
+ public function handle(Event $event): void {
+ if ($event instanceof CardCreatedEvent || $event instanceof CardUpdatedEvent) {
+ $cardData = $event->getCardData();
+
+ $this->birthdayService->onCardChanged($event->getAddressBookId(), $cardData['uri'], $cardData['carddata']);
+ }
+
+ if ($event instanceof CardDeletedEvent) {
+ $cardData = $event->getCardData();
+ $this->birthdayService->onCardDeleted($event->getAddressBookId(), $cardData['uri']);
+ }
+ }
+}
diff --git a/apps/dav/lib/Listener/CalendarPublicationListener.php b/apps/dav/lib/Listener/CalendarPublicationListener.php
new file mode 100644
index 00000000000..1453694d6fb
--- /dev/null
+++ b/apps/dav/lib/Listener/CalendarPublicationListener.php
@@ -0,0 +1,65 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2022 Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @author Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @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\DAV\Listener;
+
+use OCA\DAV\CalDAV\Activity\Backend;
+use OCA\DAV\Events\CalendarPublishedEvent;
+use OCA\DAV\Events\CalendarUnpublishedEvent;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use Psr\Log\LoggerInterface;
+
+class CalendarPublicationListener implements IEventListener {
+ private Backend $activityBackend;
+ private LoggerInterface $logger;
+
+ public function __construct(Backend $activityBackend,
+ LoggerInterface $logger) {
+ $this->activityBackend = $activityBackend;
+ $this->logger = $logger;
+ }
+
+ /**
+ * In case the user has set their default calendar to the deleted one
+ */
+ public function handle(Event $event): void {
+ if ($event instanceof CalendarPublishedEvent) {
+ $this->logger->debug('Creating activity for Calendar being published');
+
+ $this->activityBackend->onCalendarPublication(
+ $event->getCalendarData(),
+ true
+ );
+ } elseif ($event instanceof CalendarUnpublishedEvent) {
+ $this->logger->debug('Creating activity for Calendar being unpublished');
+
+ $this->activityBackend->onCalendarPublication(
+ $event->getCalendarData(),
+ false
+ );
+ }
+ }
+}
diff --git a/apps/dav/lib/Listener/CalendarShareUpdateListener.php b/apps/dav/lib/Listener/CalendarShareUpdateListener.php
new file mode 100644
index 00000000000..88865759162
--- /dev/null
+++ b/apps/dav/lib/Listener/CalendarShareUpdateListener.php
@@ -0,0 +1,62 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2022 Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @author Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @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\DAV\Listener;
+
+use OCA\DAV\CalDAV\Activity\Backend;
+use OCA\DAV\Events\CalendarShareUpdatedEvent;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use Psr\Log\LoggerInterface;
+
+class CalendarShareUpdateListener implements IEventListener {
+ private Backend $activityBackend;
+ private LoggerInterface $logger;
+
+ public function __construct(Backend $activityBackend,
+ LoggerInterface $logger) {
+ $this->activityBackend = $activityBackend;
+ $this->logger = $logger;
+ }
+
+ /**
+ * In case the user has set their default calendar to the deleted one
+ */
+ public function handle(Event $event): void {
+ if (!($event instanceof CalendarShareUpdatedEvent)) {
+ // Not what we subscribed to
+ return;
+ }
+
+ $this->logger->debug("Creating activity for Calendar having it's shares updated");
+
+ $this->activityBackend->onCalendarUpdateShares(
+ $event->getCalendarData(),
+ $event->getOldShares(),
+ $event->getAdded(),
+ $event->getRemoved()
+ );
+ }
+}
diff --git a/apps/dav/lib/Listener/ClearPhotoCacheListener.php b/apps/dav/lib/Listener/ClearPhotoCacheListener.php
new file mode 100644
index 00000000000..ed02770e35d
--- /dev/null
+++ b/apps/dav/lib/Listener/ClearPhotoCacheListener.php
@@ -0,0 +1,48 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2022 Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @author Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @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\DAV\Listener;
+
+use OCA\DAV\CardDAV\PhotoCache;
+use OCA\DAV\Events\CardDeletedEvent;
+use OCA\DAV\Events\CardUpdatedEvent;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+
+class ClearPhotoCacheListener implements IEventListener {
+ private PhotoCache $photoCache;
+
+ public function __construct(PhotoCache $photoCache) {
+ $this->photoCache = $photoCache;
+ }
+
+ public function handle(Event $event): void {
+ if ($event instanceof CardUpdatedEvent || $event instanceof CardDeletedEvent) {
+ $cardData = $event->getCardData();
+
+ $this->photoCache->delete($event->getAddressBookId(), $cardData['uri']);
+ }
+ }
+}
diff --git a/apps/dav/lib/Listener/SubscriptionListener.php b/apps/dav/lib/Listener/SubscriptionListener.php
new file mode 100644
index 00000000000..36db234aa05
--- /dev/null
+++ b/apps/dav/lib/Listener/SubscriptionListener.php
@@ -0,0 +1,85 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2022 Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @author Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @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\DAV\Listener;
+
+use OCA\DAV\BackgroundJob\RefreshWebcalJob;
+use OCA\DAV\CalDAV\Reminder\Backend as ReminderBackend;
+use OCA\DAV\CalDAV\WebcalCaching\RefreshWebcalService;
+use OCA\DAV\Events\SubscriptionCreatedEvent;
+use OCA\DAV\Events\SubscriptionDeletedEvent;
+use OCP\BackgroundJob\IJobList;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use Psr\Log\LoggerInterface;
+
+class SubscriptionListener implements IEventListener {
+ private IJobList $jobList;
+ private RefreshWebcalService $refreshWebcalService;
+ private ReminderBackend $reminderBackend;
+ private LoggerInterface $logger;
+
+ public function __construct(IJobList $jobList, RefreshWebcalService $refreshWebcalService, ReminderBackend $reminderBackend,
+ LoggerInterface $logger) {
+ $this->jobList = $jobList;
+ $this->refreshWebcalService = $refreshWebcalService;
+ $this->reminderBackend = $reminderBackend;
+ $this->logger = $logger;
+ }
+
+ /**
+ * In case the user has set their default calendar to the deleted one
+ */
+ public function handle(Event $event): void {
+ if ($event instanceof SubscriptionCreatedEvent) {
+ $subscriptionId = $event->getSubscriptionId();
+ $subscriptionData = $event->getSubscriptionData();
+
+ $this->logger->debug('Refreshing webcal data for subscription ' . $subscriptionId);
+ $this->refreshWebcalService->refreshSubscription(
+ (string)$subscriptionData['principaluri'],
+ (string)$subscriptionData['uri']
+ );
+
+ $this->logger->debug('Scheduling webcal data refreshment for subscription ' . $subscriptionId);
+ $this->jobList->add(RefreshWebcalJob::class, [
+ 'principaluri' => $subscriptionData['principaluri'],
+ 'uri' => $subscriptionData['uri']
+ ]);
+ } elseif ($event instanceof SubscriptionDeletedEvent) {
+ $subscriptionId = $event->getSubscriptionId();
+ $subscriptionData = $event->getSubscriptionData();
+
+ $this->logger->debug('Removing refresh webcal job for subscription ' . $subscriptionId);
+ $this->jobList->remove(RefreshWebcalJob::class, [
+ 'principaluri' => $subscriptionData['principaluri'],
+ 'uri' => $subscriptionData['uri']
+ ]);
+
+ $this->logger->debug('Cleaning all reminders for subscription ' . $subscriptionId);
+ $this->reminderBackend->cleanRemindersForCalendar($subscriptionId);
+ }
+ }
+}
diff --git a/apps/dav/lib/RootCollection.php b/apps/dav/lib/RootCollection.php
index 359037587a5..29ab65d46a9 100644
--- a/apps/dav/lib/RootCollection.php
+++ b/apps/dav/lib/RootCollection.php
@@ -7,6 +7,7 @@
* @author Georg Ehrke <oc.list@georgehrke.com>
* @author Joas Schilling <coding@schilljs.com>
* @author Roeland Jago Douma <roeland@famdouma.nl>
+ * @author Thomas Citharel <nextcloud@tcit.fr>
* @author Thomas Müller <thomas.mueller@tmit.eu>
* @author Vincent Petry <vincent@nextcloud.com>
*
@@ -62,7 +63,6 @@ class RootCollection extends SimpleCollection {
$shareManager = \OC::$server->getShareManager();
$db = \OC::$server->getDatabaseConnection();
$dispatcher = \OC::$server->get(IEventDispatcher::class);
- $legacyDispatcher = \OC::$server->getEventDispatcher();
$config = \OC::$server->get(IConfig::class);
$proxyMapper = \OC::$server->query(ProxyMapper::class);
@@ -107,7 +107,6 @@ class RootCollection extends SimpleCollection {
$random,
$logger,
$dispatcher,
- $legacyDispatcher,
$config
);
$userCalendarRoot = new CalendarRoot($userPrincipalBackend, $caldavBackend, 'principals/users', $logger);
@@ -142,11 +141,11 @@ class RootCollection extends SimpleCollection {
);
$pluginManager = new PluginManager(\OC::$server, \OC::$server->query(IAppManager::class));
- $usersCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, $userManager, $groupManager, $dispatcher, $legacyDispatcher);
+ $usersCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, $userManager, $groupManager, $dispatcher);
$usersAddressBookRoot = new AddressBookRoot($userPrincipalBackend, $usersCardDavBackend, $pluginManager, 'principals/users');
$usersAddressBookRoot->disableListing = $disableListing;
- $systemCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, $userManager, $groupManager, $dispatcher, $legacyDispatcher);
+ $systemCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, $userManager, $groupManager, $dispatcher);
$systemAddressBookRoot = new AddressBookRoot(new SystemPrincipalBackend(), $systemCardDavBackend, $pluginManager, 'principals/system');
$systemAddressBookRoot->disableListing = $disableListing;
diff --git a/apps/dav/lib/UserMigration/CalendarMigrator.php b/apps/dav/lib/UserMigration/CalendarMigrator.php
index 015ce6faa86..057f7dce77d 100644
--- a/apps/dav/lib/UserMigration/CalendarMigrator.php
+++ b/apps/dav/lib/UserMigration/CalendarMigrator.php
@@ -42,6 +42,7 @@ use OCP\IUser;
use OCP\UserMigration\IExportDestination;
use OCP\UserMigration\IImportSource;
use OCP\UserMigration\IMigrator;
+use OCP\UserMigration\ISizeEstimationMigrator;
use OCP\UserMigration\TMigratorBasicVersionHandling;
use Sabre\VObject\Component as VObjectComponent;
use Sabre\VObject\Component\VCalendar;
@@ -50,10 +51,11 @@ use Sabre\VObject\Property\ICalendar\DateTime;
use Sabre\VObject\Reader as VObjectReader;
use Sabre\VObject\UUIDUtil;
use Safe\Exceptions\StringsException;
+use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Throwable;
-class CalendarMigrator implements IMigrator {
+class CalendarMigrator implements IMigrator, ISizeEstimationMigrator {
use TMigratorBasicVersionHandling;
@@ -209,6 +211,31 @@ class CalendarMigrator implements IMigrator {
/**
* {@inheritDoc}
*/
+ public function getEstimatedExportSize(IUser $user): int {
+ $calendarExports = $this->getCalendarExports($user, new NullOutput());
+ $calendarCount = count($calendarExports);
+
+ // 150B for top-level properties
+ $size = ($calendarCount * 150) / 1024;
+
+ $componentCount = array_sum(array_map(
+ function (array $data): int {
+ /** @var VCalendar $vCalendar */
+ $vCalendar = $data['vCalendar'];
+ return count($vCalendar->getComponents());
+ },
+ $calendarExports,
+ ));
+
+ // 450B for each component (events, todos, alarms, etc.)
+ $size += ($componentCount * 450) / 1024;
+
+ return (int)ceil($size);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public function export(IUser $user, IExportDestination $exportDestination, OutputInterface $output): void {
$output->writeln('Exporting calendars into ' . CalendarMigrator::EXPORT_ROOT . '…');
diff --git a/apps/dav/lib/UserMigration/ContactsMigrator.php b/apps/dav/lib/UserMigration/ContactsMigrator.php
index aed41e5c82f..ae1a61ce4f4 100644
--- a/apps/dav/lib/UserMigration/ContactsMigrator.php
+++ b/apps/dav/lib/UserMigration/ContactsMigrator.php
@@ -39,6 +39,7 @@ use OCP\IUser;
use OCP\UserMigration\IExportDestination;
use OCP\UserMigration\IImportSource;
use OCP\UserMigration\IMigrator;
+use OCP\UserMigration\ISizeEstimationMigrator;
use OCP\UserMigration\TMigratorBasicVersionHandling;
use Sabre\VObject\Component\VCard;
use Sabre\VObject\Parser\Parser as VObjectParser;
@@ -47,10 +48,11 @@ use Sabre\VObject\Splitter\VCard as VCardSplitter;
use Sabre\VObject\UUIDUtil;
use Safe\Exceptions\ArrayException;
use Safe\Exceptions\StringsException;
+use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Throwable;
-class ContactsMigrator implements IMigrator {
+class ContactsMigrator implements IMigrator, ISizeEstimationMigrator {
use TMigratorBasicVersionHandling;
@@ -196,6 +198,27 @@ class ContactsMigrator implements IMigrator {
/**
* {@inheritDoc}
*/
+ public function getEstimatedExportSize(IUser $user): int {
+ $addressBookExports = $this->getAddressBookExports($user, new NullOutput());
+ $addressBookCount = count($addressBookExports);
+
+ // 50B for each metadata JSON
+ $size = ($addressBookCount * 50) / 1024;
+
+ $contactsCount = array_sum(array_map(
+ fn (array $data): int => count($data['vCards']),
+ $addressBookExports,
+ ));
+
+ // 350B for each contact
+ $size += ($contactsCount * 350) / 1024;
+
+ return (int)ceil($size);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public function export(IUser $user, IExportDestination $exportDestination, OutputInterface $output): void {
$output->writeln('Exporting contacts into ' . ContactsMigrator::PATH_ROOT . '…');
diff --git a/apps/dav/src/views/Availability.vue b/apps/dav/src/views/Availability.vue
index 928db771458..f3b3ec34bd2 100644
--- a/apps/dav/src/views/Availability.vue
+++ b/apps/dav/src/views/Availability.vue
@@ -1,9 +1,6 @@
<template>
- <div class="section">
- <h2>{{ $t('dav', 'Availability') }}</h2>
- <p>
- {{ $t('dav', 'If you configure your working hours, other users will see when you are out of office when they book a meeting.') }}
- </p>
+ <SettingsSection :title="$t('dav', 'Availability')"
+ :description="$t('dav', 'If you configure your working hours, other users will see when you are out of office when they book a meeting.')">
<div class="time-zone">
<strong>
{{ $t('dav', 'Time zone:') }}
@@ -12,6 +9,7 @@
<TimezonePicker v-model="timezone" />
</span>
</div>
+
<CalendarAvailability :slots.sync="slots"
:loading="loading"
:l10n-to="$t('dav', 'to')"
@@ -25,31 +23,38 @@
:l10n-friday="$t('dav', 'Friday')"
:l10n-saturday="$t('dav', 'Saturday')"
:l10n-sunday="$t('dav', 'Sunday')" />
+
<Button :disabled="loading || saving"
type="primary"
@click="save">
{{ $t('dav', 'Save') }}
</Button>
- </div>
+ </SettingsSection>
</template>
<script>
import { CalendarAvailability } from '@nextcloud/calendar-availability-vue'
import {
+ showError,
+ showSuccess,
+} from '@nextcloud/dialogs'
+import {
findScheduleInboxAvailability,
getEmptySlots,
saveScheduleInboxAvailability,
} from '../service/CalendarService'
import jstz from 'jstimezonedetect'
-import TimezonePicker from '@nextcloud/vue/dist/Components/TimezonePicker'
import Button from '@nextcloud/vue/dist/Components/Button'
+import SettingsSection from '@nextcloud/vue/dist/Components/SettingsSection'
+import TimezonePicker from '@nextcloud/vue/dist/Components/TimezonePicker'
export default {
name: 'Availability',
components: {
+ Button,
CalendarAvailability,
+ SettingsSection,
TimezonePicker,
- Button,
},
data() {
// Try to determine the current timezone, and fall back to UTC otherwise
@@ -80,7 +85,7 @@ export default {
} catch (e) {
console.error('could not load existing availability', e)
- // TODO: show a nice toast
+ showError(t('dav', 'Failed to load availability'))
} finally {
this.loading = false
}
@@ -92,11 +97,11 @@ export default {
await saveScheduleInboxAvailability(this.slots, this.timezone)
- // TODO: show a nice toast
+ showSuccess(t('dav', 'Saved availability'))
} catch (e) {
console.error('could not save availability', e)
- // TODO: show a nice toast
+ showError(t('dav', 'Failed to save availability'))
} finally {
this.saving = false
}
diff --git a/apps/dav/src/views/CalDavSettings.spec.js b/apps/dav/src/views/CalDavSettings.spec.js
index 13abca03d5b..5c81c6259a1 100644
--- a/apps/dav/src/views/CalDavSettings.spec.js
+++ b/apps/dav/src/views/CalDavSettings.spec.js
@@ -1,6 +1,4 @@
-import axios from '@nextcloud/axios'
import { render } from '@testing-library/vue'
-import userEvent from '@testing-library/user-event'
import CalDavSettings from './CalDavSettings'
// eslint-disable-next-line no-unused-vars
import { generateUrl } from '@nextcloud/router'
@@ -76,6 +74,9 @@ describe('CalDavSettings', () => {
)
expect(sendEventRemindersPush).toBeChecked()
+ /*
+ FIXME userEvent.click is broken with nextcloud-vue/Button
+
await userEvent.click(sendInvitations)
expect(sendInvitations).not.toBeChecked()
expect(OCP.AppConfig.setValue).toHaveBeenCalledWith(
@@ -127,5 +128,6 @@ describe('CalDavSettings', () => {
expect(sendEventRemindersToSharedGroupMembers).toBeEnabled()
expect(sendEventRemindersPush).toBeEnabled()
+ */
})
})
diff --git a/apps/dav/src/views/CalDavSettings.vue b/apps/dav/src/views/CalDavSettings.vue
index f1d39abee42..714fc9a4d32 100644
--- a/apps/dav/src/views/CalDavSettings.vue
+++ b/apps/dav/src/views/CalDavSettings.vue
@@ -1,20 +1,17 @@
<template>
- <div class="section">
- <h2>{{ $t('dav', 'Calendar server') }}</h2>
+ <SettingsSection :title="$t('dav', 'Calendar server')"
+ :doc-url="userSyncCalendarsDocUrl">
<!-- Can use v-html as:
- $t passes the translated string through DOMPurify.sanitize,
- replacement strings are not user-controlled. -->
<!-- eslint-disable-next-line vue/no-v-html -->
<p class="settings-hint" v-html="hint" />
<p>
- <input id="caldavSendInvitations"
- v-model="sendInvitations"
- type="checkbox"
- class="checkbox">
- <label for="caldavSendInvitations">
+ <CheckboxRadioSwitch id="caldavSendInvitations"
+ :checked.sync="sendInvitations"
+ type="switch">
{{ $t('dav', 'Send invitations to attendees') }}
- </label>
- <br>
+ </CheckboxRadioSwitch>
<!-- Can use v-html as:
- $t passes the translated string through DOMPurify.sanitize,
- replacement strings are not user-controlled. -->
@@ -22,14 +19,12 @@
<em v-html="sendInvitationsHelpText" />
</p>
<p>
- <input id="caldavGenerateBirthdayCalendar"
- v-model="generateBirthdayCalendar"
- type="checkbox"
+ <CheckboxRadioSwitch id="caldavGenerateBirthdayCalendar"
+ :checked.sync="generateBirthdayCalendar"
+ type="switch"
class="checkbox">
- <label for="caldavGenerateBirthdayCalendar">
{{ $t('dav', 'Automatically generate a birthday calendar') }}
- </label>
- <br>
+ </CheckboxRadioSwitch>
<em>
{{ $t('dav', 'Birthday calendars will be generated by a background job.') }}
</em>
@@ -39,14 +34,11 @@
</em>
</p>
<p>
- <input id="caldavSendEventReminders"
- v-model="sendEventReminders"
- type="checkbox"
- class="checkbox">
- <label for="caldavSendEventReminders">
+ <CheckboxRadioSwitch id="caldavSendEventReminders"
+ :checked.sync="sendEventReminders"
+ type="switch">
{{ $t('dav', 'Send notifications for events') }}
- </label>
- <br>
+ </CheckboxRadioSwitch>
<!-- Can use v-html as:
- $t passes the translated string through DOMPurify.sanitize,
- replacement strings are not user-controlled. -->
@@ -58,47 +50,47 @@
</em>
</p>
<p class="indented">
- <input id="caldavSendEventRemindersToSharedGroupMembers"
- v-model="sendEventRemindersToSharedGroupMembers"
- type="checkbox"
- class="checkbox"
+ <CheckboxRadioSwitch id="caldavSendEventRemindersToSharedGroupMembers"
+ :checked.sync="sendEventRemindersToSharedGroupMembers"
+ type="switch"
:disabled="!sendEventReminders">
- <label for="caldavSendEventRemindersToSharedGroupMembers">
{{ $t('dav', 'Send reminder notifications to calendar sharees as well' ) }}
- </label>
- <br>
+ </CheckboxRadioSwitch>
<em>
{{ $t('dav', 'Reminders are always sent to organizers and attendees.' ) }}
</em>
</p>
<p class="indented">
- <input id="caldavSendEventRemindersPush"
- v-model="sendEventRemindersPush"
- type="checkbox"
- class="checkbox"
+ <CheckboxRadioSwitch id="caldavSendEventRemindersPush"
+ :checked.sync="sendEventRemindersPush"
+ type="switch"
:disabled="!sendEventReminders">
- <label for="caldavSendEventRemindersPush">
{{ $t('dav', 'Enable notifications for events via push') }}
- </label>
+ </CheckboxRadioSwitch>
</p>
- </div>
+ </SettingsSection>
</template>
-<style lang="scss" scoped>
- .indented {
- padding-left: 28px;
- }
-</style>
-
<script>
import axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'
import { loadState } from '@nextcloud/initial-state'
+import SettingsSection from '@nextcloud/vue/dist/Components/SettingsSection'
+import CheckboxRadioSwitch from '@nextcloud/vue/dist/Components/CheckboxRadioSwitch'
const userSyncCalendarsDocUrl = loadState('dav', 'userSyncCalendarsDocUrl', '#')
export default {
name: 'CalDavSettings',
+ components: {
+ CheckboxRadioSwitch,
+ SettingsSection,
+ },
+ data() {
+ return {
+ userSyncCalendarsDocUrl,
+ }
+ },
computed: {
hint() {
const translated = this.$t(
@@ -151,3 +143,18 @@ export default {
},
}
</script>
+
+<style scoped>
+ .indented {
+ padding-left: 28px;
+ }
+ /** Use deep selector to affect v-html */
+ * >>> a {
+ text-decoration: underline;
+ }
+ .settings-hint {
+ margin-top: -.2em;
+ margin-bottom: 1em;
+ opacity: .7;
+ }
+</style>
diff --git a/apps/dav/src/views/__snapshots__/CalDavSettings.spec.js.snap b/apps/dav/src/views/__snapshots__/CalDavSettings.spec.js.snap
index 448361297fb..fa101948bd6 100644
--- a/apps/dav/src/views/__snapshots__/CalDavSettings.spec.js.snap
+++ b/apps/dav/src/views/__snapshots__/CalDavSettings.spec.js.snap
@@ -3,14 +3,53 @@
exports[`CalDavSettings interactions 1`] = `
<div>
<div
- class="section"
+ class="settings-section"
+ data-v-548823d7=""
>
- <h2>
- Calendar server
+ <h2
+ class="settings-section__title"
+ data-v-548823d7=""
+ >
+
+ Calendar server
+
+ <a
+ class="settings-section__info"
+ data-v-548823d7=""
+ href="https://docs.nextcloud.com/server/23/go.php?to=user-sync-calendars"
+ role="note"
+ title="External documentation for Calendar server"
+ >
+ <span
+ aria-hidden="true"
+ aria-label=""
+ class="material-design-icon help-circle-icon"
+ data-v-548823d7=""
+ decorative=""
+ role="img"
+ >
+ <svg
+ class="material-design-icon__svg"
+ fill="currentColor"
+ height="20"
+ viewBox="0 0 24 24"
+ width="20"
+ >
+ <path
+ d="M15.07,11.25L14.17,12.17C13.45,12.89 13,13.5 13,15H11V14.5C11,13.39 11.45,12.39 12.17,11.67L13.41,10.41C13.78,10.05 14,9.55 14,9C14,7.89 13.1,7 12,7A2,2 0 0,0 10,9H8A4,4 0 0,1 12,5A4,4 0 0,1 16,9C16,9.88 15.64,10.67 15.07,11.25M13,19H11V17H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z"
+ >
+ <!---->
+ </path>
+ </svg>
+ </span>
+ </a>
</h2>
+ <!---->
+
<p
class="settings-hint"
+ data-v-548823d7=""
>
Also install the
<a
@@ -30,24 +69,59 @@ exports[`CalDavSettings interactions 1`] = `
.
</p>
- <p>
- <input
- class="checkbox"
- id="caldavSendInvitations"
- type="checkbox"
- />
-
- <label
- for="caldavSendInvitations"
+ <p
+ data-v-548823d7=""
+ >
+ <span
+ class="checkbox-radio-switch checkbox-radio-switch-switch checkbox-radio-switch--checked"
+ data-v-036397c2=""
+ data-v-548823d7=""
+ style="--icon-size: 36px;"
>
-
+ <input
+ class="checkbox-radio-switch__input"
+ data-v-036397c2=""
+ id="caldavSendInvitations"
+ type="checkbox"
+ value=""
+ />
+
+ <label
+ class="checkbox-radio-switch__label"
+ data-v-036397c2=""
+ for="caldavSendInvitations"
+ >
+ <span
+ aria-hidden="true"
+ aria-label=""
+ class="material-design-icon toggle-switch-icon checkbox-radio-switch__icon"
+ data-v-036397c2=""
+ decorative=""
+ role="img"
+ >
+ <svg
+ class="material-design-icon__svg"
+ fill="currentColor"
+ height="36"
+ viewBox="0 0 24 24"
+ width="36"
+ >
+ <path
+ d="M17,7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7M17,15A3,3 0 0,1 14,12A3,3 0 0,1 17,9A3,3 0 0,1 20,12A3,3 0 0,1 17,15Z"
+ >
+ <!---->
+ </path>
+ </svg>
+ </span>
+
Send invitations to attendees
- </label>
-
- <br />
+ </label>
+ </span>
- <em>
+ <em
+ data-v-548823d7=""
+ >
Please make sure to properly set up
<a
href="../admin#mail_general_settings"
@@ -58,56 +132,130 @@ exports[`CalDavSettings interactions 1`] = `
</em>
</p>
- <p>
- <input
- class="checkbox"
- id="caldavGenerateBirthdayCalendar"
- type="checkbox"
- />
-
- <label
- for="caldavGenerateBirthdayCalendar"
+ <p
+ data-v-548823d7=""
+ >
+ <span
+ class="checkbox-radio-switch checkbox checkbox-radio-switch-switch checkbox-radio-switch--checked"
+ data-v-036397c2=""
+ data-v-548823d7=""
+ style="--icon-size: 36px;"
>
-
+ <input
+ class="checkbox-radio-switch__input"
+ data-v-036397c2=""
+ id="caldavGenerateBirthdayCalendar"
+ type="checkbox"
+ value=""
+ />
+
+ <label
+ class="checkbox-radio-switch__label"
+ data-v-036397c2=""
+ for="caldavGenerateBirthdayCalendar"
+ >
+ <span
+ aria-hidden="true"
+ aria-label=""
+ class="material-design-icon toggle-switch-icon checkbox-radio-switch__icon"
+ data-v-036397c2=""
+ decorative=""
+ role="img"
+ >
+ <svg
+ class="material-design-icon__svg"
+ fill="currentColor"
+ height="36"
+ viewBox="0 0 24 24"
+ width="36"
+ >
+ <path
+ d="M17,7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7M17,15A3,3 0 0,1 14,12A3,3 0 0,1 17,9A3,3 0 0,1 20,12A3,3 0 0,1 17,15Z"
+ >
+ <!---->
+ </path>
+ </svg>
+ </span>
+
Automatically generate a birthday calendar
- </label>
-
- <br />
+ </label>
+ </span>
- <em>
+ <em
+ data-v-548823d7=""
+ >
Birthday calendars will be generated by a background job.
</em>
- <br />
+ <br
+ data-v-548823d7=""
+ />
- <em>
+ <em
+ data-v-548823d7=""
+ >
Hence they will not be available immediately after enabling but will show up after some time.
</em>
</p>
- <p>
- <input
- class="checkbox"
- id="caldavSendEventReminders"
- type="checkbox"
- />
-
- <label
- for="caldavSendEventReminders"
+ <p
+ data-v-548823d7=""
+ >
+ <span
+ class="checkbox-radio-switch checkbox-radio-switch-switch checkbox-radio-switch--checked"
+ data-v-036397c2=""
+ data-v-548823d7=""
+ style="--icon-size: 36px;"
>
-
+ <input
+ class="checkbox-radio-switch__input"
+ data-v-036397c2=""
+ id="caldavSendEventReminders"
+ type="checkbox"
+ value=""
+ />
+
+ <label
+ class="checkbox-radio-switch__label"
+ data-v-036397c2=""
+ for="caldavSendEventReminders"
+ >
+ <span
+ aria-hidden="true"
+ aria-label=""
+ class="material-design-icon toggle-switch-icon checkbox-radio-switch__icon"
+ data-v-036397c2=""
+ decorative=""
+ role="img"
+ >
+ <svg
+ class="material-design-icon__svg"
+ fill="currentColor"
+ height="36"
+ viewBox="0 0 24 24"
+ width="36"
+ >
+ <path
+ d="M17,7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7M17,15A3,3 0 0,1 14,12A3,3 0 0,1 17,9A3,3 0 0,1 20,12A3,3 0 0,1 17,15Z"
+ >
+ <!---->
+ </path>
+ </svg>
+ </span>
+
Send notifications for events
- </label>
+ </label>
+ </span>
- <br />
-
- <em>
+ <em
+ data-v-548823d7=""
+ >
Please make sure to properly set up
<a
href="../admin#mail_general_settings"
@@ -117,9 +265,13 @@ exports[`CalDavSettings interactions 1`] = `
.
</em>
- <br />
+ <br
+ data-v-548823d7=""
+ />
- <em>
+ <em
+ data-v-548823d7=""
+ >
Notifications are sent via background jobs, so these must occur often enough.
@@ -128,24 +280,58 @@ exports[`CalDavSettings interactions 1`] = `
<p
class="indented"
+ data-v-548823d7=""
>
- <input
- class="checkbox"
- id="caldavSendEventRemindersToSharedGroupMembers"
- type="checkbox"
- />
-
- <label
- for="caldavSendEventRemindersToSharedGroupMembers"
+ <span
+ class="checkbox-radio-switch checkbox-radio-switch-switch checkbox-radio-switch--checked"
+ data-v-036397c2=""
+ data-v-548823d7=""
+ style="--icon-size: 36px;"
>
-
+ <input
+ class="checkbox-radio-switch__input"
+ data-v-036397c2=""
+ id="caldavSendEventRemindersToSharedGroupMembers"
+ type="checkbox"
+ value=""
+ />
+
+ <label
+ class="checkbox-radio-switch__label"
+ data-v-036397c2=""
+ for="caldavSendEventRemindersToSharedGroupMembers"
+ >
+ <span
+ aria-hidden="true"
+ aria-label=""
+ class="material-design-icon toggle-switch-icon checkbox-radio-switch__icon"
+ data-v-036397c2=""
+ decorative=""
+ role="img"
+ >
+ <svg
+ class="material-design-icon__svg"
+ fill="currentColor"
+ height="36"
+ viewBox="0 0 24 24"
+ width="36"
+ >
+ <path
+ d="M17,7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7M17,15A3,3 0 0,1 14,12A3,3 0 0,1 17,9A3,3 0 0,1 20,12A3,3 0 0,1 17,15Z"
+ >
+ <!---->
+ </path>
+ </svg>
+ </span>
+
Send reminder notifications to calendar sharees as well
- </label>
-
- <br />
+ </label>
+ </span>
- <em>
+ <em
+ data-v-548823d7=""
+ >
Reminders are always sent to organizers and attendees.
@@ -154,20 +340,54 @@ exports[`CalDavSettings interactions 1`] = `
<p
class="indented"
+ data-v-548823d7=""
>
- <input
- class="checkbox"
- id="caldavSendEventRemindersPush"
- type="checkbox"
- />
-
- <label
- for="caldavSendEventRemindersPush"
+ <span
+ class="checkbox-radio-switch checkbox-radio-switch-switch checkbox-radio-switch--checked"
+ data-v-036397c2=""
+ data-v-548823d7=""
+ style="--icon-size: 36px;"
>
-
+ <input
+ class="checkbox-radio-switch__input"
+ data-v-036397c2=""
+ id="caldavSendEventRemindersPush"
+ type="checkbox"
+ value=""
+ />
+
+ <label
+ class="checkbox-radio-switch__label"
+ data-v-036397c2=""
+ for="caldavSendEventRemindersPush"
+ >
+ <span
+ aria-hidden="true"
+ aria-label=""
+ class="material-design-icon toggle-switch-icon checkbox-radio-switch__icon"
+ data-v-036397c2=""
+ decorative=""
+ role="img"
+ >
+ <svg
+ class="material-design-icon__svg"
+ fill="currentColor"
+ height="36"
+ viewBox="0 0 24 24"
+ width="36"
+ >
+ <path
+ d="M17,7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7M17,15A3,3 0 0,1 14,12A3,3 0 0,1 17,9A3,3 0 0,1 20,12A3,3 0 0,1 17,15Z"
+ >
+ <!---->
+ </path>
+ </svg>
+ </span>
+
Enable notifications for events via push
- </label>
+ </label>
+ </span>
</p>
</div>
</div>
diff --git a/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php
index 0a234fc5c8d..f2d2014d553 100644
--- a/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php
+++ b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php
@@ -7,6 +7,7 @@
* @author Joas Schilling <coding@schilljs.com>
* @author Morris Jobke <hey@morrisjobke.de>
* @author Roeland Jago Douma <roeland@famdouma.nl>
+ * @author Thomas Citharel <nextcloud@tcit.fr>
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @license AGPL-3.0
@@ -43,7 +44,6 @@ use OCP\Share\IManager as ShareManager;
use Psr\Log\LoggerInterface;
use Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet;
use Sabre\DAV\Xml\Property\Href;
-use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Test\TestCase;
/**
@@ -66,8 +66,6 @@ abstract class AbstractCalDavBackend extends TestCase {
protected $groupManager;
/** @var IEventDispatcher|\PHPUnit\Framework\MockObject\MockObject */
protected $dispatcher;
- /** @var EventDispatcherInterface|\PHPUnit\Framework\MockObject\MockObject */
- protected $legacyDispatcher;
/** @var ISecureRandom */
private $random;
@@ -85,7 +83,6 @@ abstract class AbstractCalDavBackend extends TestCase {
$this->userManager = $this->createMock(IUserManager::class);
$this->groupManager = $this->createMock(IGroupManager::class);
$this->dispatcher = $this->createMock(IEventDispatcher::class);
- $this->legacyDispatcher = $this->createMock(EventDispatcherInterface::class);
$this->principal = $this->getMockBuilder(Principal::class)
->setConstructorArgs([
$this->userManager,
@@ -122,7 +119,6 @@ abstract class AbstractCalDavBackend extends TestCase {
$this->random,
$this->logger,
$this->dispatcher,
- $this->legacyDispatcher,
$this->config
);
@@ -149,8 +145,6 @@ abstract class AbstractCalDavBackend extends TestCase {
$calendars = $this->backend->getCalendarsForUser($principal);
$this->dispatcher->expects(self::any())
->method('dispatchTyped');
- $this->legacyDispatcher->expects(self::any())
- ->method('dispatch');
foreach ($calendars as $calendar) {
$this->backend->deleteCalendar($calendar['id'], true);
}
diff --git a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
index 3a5cf56409c..13025415f2a 100644
--- a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
@@ -35,6 +35,7 @@ use DateTime;
use DateTimeZone;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\Calendar;
+use OCA\DAV\DAV\Sharing\Plugin as SharingPlugin;
use OCA\DAV\Events\CalendarDeletedEvent;
use OCP\IConfig;
use OCP\IL10N;
@@ -150,9 +151,6 @@ class CalDavBackendTest extends AbstractCalDavBackend {
$calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER);
$this->assertCount(1, $calendars);
$calendar = new Calendar($this->backend, $calendars[0], $l10n, $config, $logger);
- $this->legacyDispatcher->expects($this->at(0))
- ->method('dispatch')
- ->with('\OCA\DAV\CalDAV\CalDavBackend::updateShares');
$this->backend->updateShares($calendar, $add, []);
$calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER1);
$this->assertCount(1, $calendars);
@@ -232,13 +230,13 @@ EOD;
->method('dispatchTyped');
$this->backend->createCalendarObject($calendarId, $uri, $calData);
- // get all the cards
+ // get all the calendar objects
$calendarObjects = $this->backend->getCalendarObjects($calendarId);
$this->assertCount(1, $calendarObjects);
$this->assertEquals($calendarId, $calendarObjects[0]['calendarid']);
$this->assertArrayHasKey('classification', $calendarObjects[0]);
- // get the cards
+ // get the calendar objects
$calendarObject = $this->backend->getCalendarObject($calendarId, $uri);
$this->assertNotNull($calendarObject);
$this->assertArrayHasKey('id', $calendarObject);
@@ -247,6 +245,7 @@ EOD;
$this->assertArrayHasKey('etag', $calendarObject);
$this->assertArrayHasKey('size', $calendarObject);
$this->assertArrayHasKey('classification', $calendarObject);
+ $this->assertArrayHasKey('{' . SharingPlugin::NS_NEXTCLOUD . '}deleted-at', $calendarObject);
$this->assertEquals($calData, $calendarObject['calendardata']);
// update the card
diff --git a/apps/dav/tests/unit/CalDAV/Listener/CalendarPublicationListenerTest.php b/apps/dav/tests/unit/CalDAV/Listener/CalendarPublicationListenerTest.php
new file mode 100644
index 00000000000..c42fca1a1cf
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/Listener/CalendarPublicationListenerTest.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * @copyright 2022 Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @author Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @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\DAV\Tests\unit\CalDAV\Listeners;
+
+use OCA\DAV\CalDAV\Activity\Backend;
+use OCA\DAV\Events\CalendarPublishedEvent;
+use OCA\DAV\Events\CalendarUnpublishedEvent;
+use OCA\DAV\Listener\CalendarPublicationListener;
+use OCP\EventDispatcher\Event;
+use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
+use Test\TestCase;
+
+class CalendarPublicationListenerTest extends TestCase {
+
+ /** @var Backend|MockObject */
+ private $activityBackend;
+
+ /** @var LoggerInterface|MockObject */
+ private $logger;
+
+ private CalendarPublicationListener $calendarPublicationListener;
+
+ /** @var CalendarPublishedEvent|MockObject */
+ private $publicationEvent;
+
+ /** @var CalendarUnpublishedEvent|MockObject */
+ private $unpublicationEvent;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->activityBackend = $this->createMock(Backend::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
+ $this->publicationEvent = $this->createMock(CalendarPublishedEvent::class);
+ $this->unpublicationEvent = $this->createMock(CalendarUnpublishedEvent::class);
+ $this->calendarPublicationListener = new CalendarPublicationListener($this->activityBackend, $this->logger);
+ }
+
+ public function testInvalidEvent(): void {
+ $this->activityBackend->expects($this->never())->method('onCalendarPublication');
+ $this->logger->expects($this->never())->method('debug');
+ $this->calendarPublicationListener->handle(new Event());
+ }
+
+ public function testPublicationEvent(): void {
+ $this->publicationEvent->expects($this->once())->method('getCalendarData')->with()->willReturn([]);
+ $this->activityBackend->expects($this->once())->method('onCalendarPublication')->with([], true);
+ $this->logger->expects($this->once())->method('debug');
+ $this->calendarPublicationListener->handle($this->publicationEvent);
+ }
+
+ public function testUnPublicationEvent(): void {
+ $this->unpublicationEvent->expects($this->once())->method('getCalendarData')->with()->willReturn([]);
+ $this->activityBackend->expects($this->once())->method('onCalendarPublication')->with([], false);
+ $this->logger->expects($this->once())->method('debug');
+ $this->calendarPublicationListener->handle($this->unpublicationEvent);
+ }
+}
diff --git a/apps/dav/tests/unit/CalDAV/Listener/CalendarShareUpdateListenerTest.php b/apps/dav/tests/unit/CalDAV/Listener/CalendarShareUpdateListenerTest.php
new file mode 100644
index 00000000000..0252cffd5a0
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/Listener/CalendarShareUpdateListenerTest.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * @copyright 2022 Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @author Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @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\DAV\Tests\unit\CalDAV\Listeners;
+
+use OCA\DAV\CalDAV\Activity\Backend;
+use OCA\DAV\Events\CalendarShareUpdatedEvent;
+use OCA\DAV\Listener\CalendarShareUpdateListener;
+use OCP\EventDispatcher\Event;
+use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
+use Test\TestCase;
+
+class CalendarShareUpdateListenerTest extends TestCase {
+
+ /** @var Backend|MockObject */
+ private $activityBackend;
+
+ /** @var LoggerInterface|MockObject */
+ private $logger;
+
+ private CalendarShareUpdateListener $calendarPublicationListener;
+
+ /** @var CalendarShareUpdatedEvent|MockObject */
+ private $event;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->activityBackend = $this->createMock(Backend::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
+ $this->event = $this->createMock(CalendarShareUpdatedEvent::class);
+ $this->calendarPublicationListener = new CalendarShareUpdateListener($this->activityBackend, $this->logger);
+ }
+
+ public function testInvalidEvent(): void {
+ $this->activityBackend->expects($this->never())->method('onCalendarUpdateShares');
+ $this->logger->expects($this->never())->method('debug');
+ $this->calendarPublicationListener->handle(new Event());
+ }
+
+ public function testEvent(): void {
+ $this->event->expects($this->once())->method('getCalendarData')->with()->willReturn([]);
+ $this->event->expects($this->once())->method('getOldShares')->with()->willReturn([]);
+ $this->event->expects($this->once())->method('getAdded')->with()->willReturn([]);
+ $this->event->expects($this->once())->method('getRemoved')->with()->willReturn([]);
+ $this->activityBackend->expects($this->once())->method('onCalendarUpdateShares')->with([], [], [], []);
+ $this->logger->expects($this->once())->method('debug');
+ $this->calendarPublicationListener->handle($this->event);
+ }
+}
diff --git a/apps/dav/tests/unit/CalDAV/Listener/SubscriptionListenerTest.php b/apps/dav/tests/unit/CalDAV/Listener/SubscriptionListenerTest.php
new file mode 100644
index 00000000000..709ebdac7af
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/Listener/SubscriptionListenerTest.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * @copyright 2022 Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @author Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @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\DAV\Tests\unit\CalDAV\Listeners;
+
+use OCA\DAV\BackgroundJob\RefreshWebcalJob;
+use OCA\DAV\CalDAV\Reminder\Backend;
+use OCA\DAV\CalDAV\WebcalCaching\RefreshWebcalService;
+use OCA\DAV\Events\SubscriptionCreatedEvent;
+use OCA\DAV\Events\SubscriptionDeletedEvent;
+use OCA\DAV\Listener\SubscriptionListener;
+use OCP\BackgroundJob\IJobList;
+use OCP\EventDispatcher\Event;
+use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
+use Test\TestCase;
+
+class SubscriptionListenerTest extends TestCase {
+
+ /** @var RefreshWebcalService|MockObject */
+ private $refreshWebcalService;
+
+ /** @var Backend|MockObject */
+ private $reminderBackend;
+
+ /** @var IJobList|MockObject */
+ private $jobList;
+
+ /** @var LoggerInterface|MockObject */
+ private $logger;
+
+ private SubscriptionListener $calendarPublicationListener;
+
+ /** @var SubscriptionCreatedEvent|MockObject */
+ private $subscriptionCreatedEvent;
+
+ /** @var SubscriptionDeletedEvent|MockObject */
+ private $subscriptionDeletedEvent;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->refreshWebcalService = $this->createMock(RefreshWebcalService::class);
+ $this->reminderBackend = $this->createMock(Backend::class);
+ $this->jobList = $this->createMock(IJobList::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
+ $this->subscriptionCreatedEvent = $this->createMock(SubscriptionCreatedEvent::class);
+ $this->subscriptionDeletedEvent = $this->createMock(SubscriptionDeletedEvent::class);
+ $this->calendarPublicationListener = new SubscriptionListener($this->jobList, $this->refreshWebcalService, $this->reminderBackend, $this->logger);
+ }
+
+ public function testInvalidEvent(): void {
+ $this->refreshWebcalService->expects($this->never())->method('refreshSubscription');
+ $this->jobList->expects($this->never())->method('add');
+ $this->logger->expects($this->never())->method('debug');
+ $this->calendarPublicationListener->handle(new Event());
+ }
+
+ public function testCreateSubscriptionEvent(): void {
+ $this->subscriptionCreatedEvent->expects($this->once())->method('getSubscriptionId')->with()->willReturn(5);
+ $this->subscriptionCreatedEvent->expects($this->once())->method('getSubscriptionData')->with()->willReturn(['principaluri' => 'principaluri', 'uri' => 'uri']);
+ $this->refreshWebcalService->expects($this->once())->method('refreshSubscription')->with('principaluri', 'uri');
+ $this->jobList->expects($this->once())->method('add')->with(RefreshWebcalJob::class, ['principaluri' => 'principaluri', 'uri' => 'uri']);
+ $this->logger->expects($this->exactly(2))->method('debug');
+ $this->calendarPublicationListener->handle($this->subscriptionCreatedEvent);
+ }
+
+ public function testDeleteSubscriptionEvent(): void {
+ $this->subscriptionDeletedEvent->expects($this->once())->method('getSubscriptionId')->with()->willReturn(5);
+ $this->subscriptionDeletedEvent->expects($this->once())->method('getSubscriptionData')->with()->willReturn(['principaluri' => 'principaluri', 'uri' => 'uri']);
+ $this->jobList->expects($this->once())->method('remove')->with(RefreshWebcalJob::class, ['principaluri' => 'principaluri', 'uri' => 'uri']);
+ $this->reminderBackend->expects($this->once())->method('cleanRemindersForCalendar')->with(5);
+ $this->logger->expects($this->exactly(2))->method('debug');
+ $this->calendarPublicationListener->handle($this->subscriptionDeletedEvent);
+ }
+}
diff --git a/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php b/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php
index 80e43d279dc..23c1c2ae896 100644
--- a/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php
+++ b/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php
@@ -42,7 +42,6 @@ use OCP\IL10N;
use OCP\IUserManager;
use OCP\Security\ISecureRandom;
use Psr\Log\LoggerInterface;
-use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Test\TestCase;
/**
@@ -84,7 +83,6 @@ class PublicCalendarRootTest extends TestCase {
$this->random = \OC::$server->getSecureRandom();
$this->logger = $this->createMock(LoggerInterface::class);
$dispatcher = $this->createMock(IEventDispatcher::class);
- $legacyDispatcher = $this->createMock(EventDispatcherInterface::class);
$config = $this->createMock(IConfig::class);
$this->principal->expects($this->any())->method('getGroupMembership')
@@ -103,7 +101,6 @@ class PublicCalendarRootTest extends TestCase {
$this->random,
$this->logger,
$dispatcher,
- $legacyDispatcher,
$config
);
$this->l10n = $this->getMockBuilder(IL10N::class)
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php
index 6428652ccab..273ad939144 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php
@@ -224,99 +224,45 @@ class EmailProviderTest extends AbstractNotificationProviderTest {
$message22 = $this->getMessageMock('foo4@example.org', $template2);
$message23 = $this->getMessageMock('uid1@example.com', $template2);
- $this->mailer->expects($this->at(0))
+ $this->mailer->expects(self::exactly(2))
->method('createEMailTemplate')
->with('dav.calendarReminder')
- ->willReturn($template1);
-
- $this->mailer->expects($this->at(1))
- ->method('validateMailAddress')
- ->with('foo1@example.org')
- ->willReturn(true);
-
- $this->mailer->expects($this->at(2))
- ->method('createMessage')
- ->with()
- ->willReturn($message11);
- $this->mailer->expects($this->at(3))
- ->method('send')
- ->with($message11)
- ->willReturn([]);
- $this->mailer->expects($this->at(4))
- ->method('validateMailAddress')
- ->with('uid2@example.com')
- ->willReturn(true);
- $this->mailer->expects($this->at(5))
- ->method('createMessage')
- ->with()
- ->willReturn($message12);
- $this->mailer->expects($this->at(6))
- ->method('send')
- ->with($message12)
- ->willReturn([]);
-
- $this->mailer->expects($this->at(7))
+ ->willReturnOnConsecutiveCalls(
+ $template1,
+ $template2,
+ );
+ $this->mailer->expects($this->atLeastOnce())
->method('validateMailAddress')
- ->with('uid3@example.com')
- ->willReturn(true);
-
- $this->mailer->expects($this->at(8))
- ->method('createMessage')
- ->with()
- ->willReturn($message13);
- $this->mailer->expects($this->at(9))
- ->method('send')
- ->with($message13)
- ->willReturn([]);
-
- $this->mailer->expects($this->at(10))
- ->method('validateMailAddress')
- ->with('invalid')
- ->willReturn(false);
-
- $this->mailer->expects($this->at(11))
- ->method('createEMailTemplate')
- ->with('dav.calendarReminder')
- ->willReturn($template2);
-
- $this->mailer->expects($this->at(12))
- ->method('validateMailAddress')
- ->with('foo3@example.org')
- ->willReturn(true);
-
- $this->mailer->expects($this->at(13))
- ->method('createMessage')
- ->with()
- ->willReturn($message21);
- $this->mailer->expects($this->at(14))
- ->method('send')
- ->with($message21)
- ->willReturn([]);
- $this->mailer->expects($this->at(15))
- ->method('validateMailAddress')
- ->with('foo4@example.org')
- ->willReturn(true);
- $this->mailer->expects($this->at(16))
- ->method('createMessage')
- ->with()
- ->willReturn($message22);
- $this->mailer->expects($this->at(17))
- ->method('send')
- ->with($message22)
- ->willReturn([]);
- $this->mailer->expects($this->at(18))
- ->method('validateMailAddress')
- ->with('uid1@example.com')
- ->willReturn(true);
- $this->mailer->expects($this->at(19))
+ ->willReturnMap([
+ ['foo1@example.org', true],
+ ['foo3@example.org', true],
+ ['foo4@example.org', true],
+ ['uid1@example.com', true],
+ ['uid2@example.com', true],
+ ['uid3@example.com', true],
+ ['invalid', false],
+ ]);
+ $this->mailer->expects($this->exactly(6))
->method('createMessage')
->with()
- ->willReturn($message23);
- $this->mailer->expects($this->at(20))
+ ->willReturnOnConsecutiveCalls(
+ $message11,
+ $message12,
+ $message13,
+ $message21,
+ $message22,
+ $message23,
+ );
+ $this->mailer->expects($this->exactly(6))
->method('send')
- ->with($message23)
- ->willReturn([]);
-
+ ->withConsecutive(
+ [$message11],
+ [$message12],
+ [$message13],
+ [$message21],
+ [$message22],
+ [$message23],
+ )->willReturn([]);
$this->setupURLGeneratorMock(2);
$vcalendar = $this->getAttendeeVCalendar();
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php b/apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php
index 39fbf1c79ff..6242e8d0355 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php
@@ -39,37 +39,39 @@ use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
use Test\TestCase;
class ReminderServiceTest extends TestCase {
- /** @var Backend|\PHPUnit\Framework\MockObject\MockObject */
+ /** @var Backend|MockObject */
private $backend;
- /** @var NotificationProviderManager|\PHPUnit\Framework\MockObject\MockObject */
+ /** @var NotificationProviderManager|MockObject */
private $notificationProviderManager;
- /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
+ /** @var IUserManager|MockObject */
private $userManager;
- /** @var IGroupManager|\PHPUnit\Framework\MockObject\MockObject*/
+ /** @var IGroupManager|MockObject*/
private $groupManager;
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- private $userSession;
-
- /** @var CalDavBackend|\PHPUnit\Framework\MockObject\MockObject */
+ /** @var CalDavBackend|MockObject */
private $caldavBackend;
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
+ /** @var ITimeFactory|MockObject */
private $timeFactory;
- /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
+ /** @var IConfig|MockObject */
private $config;
/** @var ReminderService */
private $reminderService;
+ /** @var MockObject|LoggerInterface */
+ private $logger;
+
public const CALENDAR_DATA = <<<EOD
BEGIN:VCALENDAR
PRODID:-//Nextcloud calendar v1.6.4
@@ -199,16 +201,20 @@ EOD;
$this->caldavBackend = $this->createMock(CalDavBackend::class);
$this->timeFactory = $this->createMock(ITimeFactory::class);
$this->config = $this->createMock(IConfig::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
$this->caldavBackend->method('getShares')->willReturn([]);
- $this->reminderService = new ReminderService($this->backend,
+ $this->reminderService = new ReminderService(
+ $this->backend,
$this->notificationProviderManager,
$this->userManager,
$this->groupManager,
$this->caldavBackend,
$this->timeFactory,
- $this->config);
+ $this->config,
+ $this->logger,
+ );
}
public function testOnCalendarObjectDelete():void {
diff --git a/apps/dav/tests/unit/CalDAV/Schedule/PluginTest.php b/apps/dav/tests/unit/CalDAV/Schedule/PluginTest.php
index 2518cc3d91a..b651379c2bd 100644
--- a/apps/dav/tests/unit/CalDAV/Schedule/PluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/Schedule/PluginTest.php
@@ -27,11 +27,15 @@
namespace OCA\DAV\Tests\unit\CalDAV\Schedule;
use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\CalDAV\Calendar;
use OCA\DAV\CalDAV\CalendarHome;
use OCA\DAV\CalDAV\Plugin as CalDAVPlugin;
use OCA\DAV\CalDAV\Schedule\Plugin;
+use OCA\DAV\CalDAV\Trashbin\Plugin as TrashbinPlugin;
use OCP\IConfig;
+use OCP\IL10N;
use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
use Sabre\DAV\PropFind;
use Sabre\DAV\Server;
use Sabre\DAV\Tree;
@@ -73,17 +77,22 @@ class PluginTest extends TestCase {
public function testInitialize() {
$plugin = new Plugin($this->config);
- $this->server->expects($this->at(7))
+ $this->server->expects($this->exactly(10))
->method('on')
- ->with('propFind', [$plugin, 'propFindDefaultCalendarUrl'], 90);
-
- $this->server->expects($this->at(8))
- ->method('on')
- ->with('afterWriteContent', [$plugin, 'dispatchSchedulingResponses']);
-
- $this->server->expects($this->at(9))
- ->method('on')
- ->with('afterCreateFile', [$plugin, 'dispatchSchedulingResponses']);
+ ->withConsecutive(
+ // Sabre\CalDAV\Schedule\Plugin events
+ ['method:POST', [$plugin, 'httpPost']],
+ ['propFind', [$plugin, 'propFind']],
+ ['propPatch', [$plugin, 'propPatch']],
+ ['calendarObjectChange', [$plugin, 'calendarObjectChange']],
+ ['beforeUnbind', [$plugin, 'beforeUnbind']],
+ ['schedule', [$plugin, 'scheduleLocalDelivery']],
+ ['getSupportedPrivilegeSet', [$plugin, 'getSupportedPrivilegeSet']],
+ // OCA\DAV\CalDAV\Schedule\Plugin events
+ ['propFind', [$plugin, 'propFindDefaultCalendarUrl'], 90],
+ ['afterWriteContent', [$plugin, 'dispatchSchedulingResponses']],
+ ['afterCreateFile', [$plugin, 'dispatchSchedulingResponses']]
+ );
$plugin->initialize($this->server);
}
@@ -183,6 +192,15 @@ class PluginTest extends TestCase {
false,
CalDavBackend::PERSONAL_CALENDAR_URI,
CalDavBackend::PERSONAL_CALENDAR_NAME,
+ false,
+ true
+ ],
+ [
+ 'principals/users/myuser',
+ 'calendars/myuser',
+ false,
+ CalDavBackend::PERSONAL_CALENDAR_URI,
+ CalDavBackend::PERSONAL_CALENDAR_NAME,
false
],
[
@@ -201,6 +219,7 @@ class PluginTest extends TestCase {
CalDavBackend::PERSONAL_CALENDAR_NAME,
true,
false,
+ false,
],
[
'principals/users/myuser',
@@ -240,14 +259,14 @@ class PluginTest extends TestCase {
/**
* @dataProvider propFindDefaultCalendarUrlProvider
* @param string $principalUri
- * @param string $calendarHome
+ * @param string|null $calendarHome
* @param bool $isResource
* @param string $calendarUri
* @param string $displayName
* @param bool $exists
* @param bool $propertiesForPath
*/
- public function testPropFindDefaultCalendarUrl(string $principalUri, ?string $calendarHome, bool $isResource, string $calendarUri, string $displayName, bool $exists, bool $propertiesForPath = true) {
+ public function testPropFindDefaultCalendarUrl(string $principalUri, ?string $calendarHome, bool $isResource, string $calendarUri, string $displayName, bool $exists, bool $hasExistingCalendars = false, bool $propertiesForPath = true) {
/** @var PropFind $propFind */
$propFind = new PropFind(
$principalUri,
@@ -290,6 +309,7 @@ class PluginTest extends TestCase {
$this->assertNull($propFind->get(Plugin::SCHEDULE_DEFAULT_CALENDAR_URL));
return;
}
+
if (!$isResource) {
$this->config->expects($this->once())
->method('getUserValue')
@@ -303,18 +323,47 @@ class PluginTest extends TestCase {
->with($calendarUri)
->willReturn($exists);
+ $calendarBackend = $this->createMock(CalDavBackend::class);
+ $calendarUri = $hasExistingCalendars ? 'custom' : $calendarUri;
+ $displayName = $hasExistingCalendars ? 'Custom Calendar' : $displayName;
+
+ $existingCalendars = $hasExistingCalendars ? [
+ new Calendar(
+ $calendarBackend,
+ ['uri' => 'deleted', '{DAV:}displayname' => 'A deleted calendar', TrashbinPlugin::PROPERTY_DELETED_AT => 42],
+ $this->createMock(IL10N::class),
+ $this->config,
+ $this->createMock(LoggerInterface::class)
+ ),
+ new Calendar(
+ $calendarBackend,
+ ['uri' => $calendarUri, '{DAV:}displayname' => $displayName],
+ $this->createMock(IL10N::class),
+ $this->config,
+ $this->createMock(LoggerInterface::class)
+ )
+ ] : [];
+
if (!$exists) {
- $calendarBackend = $this->createMock(CalDavBackend::class);
- $calendarBackend->expects($this->once())
+ if (!$hasExistingCalendars) {
+ $calendarBackend->expects($this->once())
->method('createCalendar')
->with($principalUri, $calendarUri, [
'{DAV:}displayname' => $displayName,
]);
- $calendarHomeObject->expects($this->once())
- ->method('getCalDAVBackend')
- ->with()
- ->willReturn($calendarBackend);
+ $calendarHomeObject->expects($this->once())
+ ->method('getCalDAVBackend')
+ ->with()
+ ->willReturn($calendarBackend);
+ }
+
+ if (!$isResource) {
+ $calendarHomeObject->expects($this->once())
+ ->method('getChildren')
+ ->with()
+ ->willReturn($existingCalendars);
+ }
}
/** @var Tree|MockObject $tree */
diff --git a/apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php b/apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php
index 6bd1f6b3206..71d93bf851e 100644
--- a/apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php
+++ b/apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php
@@ -74,7 +74,7 @@ class RefreshWebcalServiceTest extends TestCase {
*/
public function testRun(string $body, string $contentType, string $result) {
$refreshWebcalService = $this->getMockBuilder(RefreshWebcalService::class)
- ->setMethods(['getRandomCalendarObjectUri'])
+ ->onlyMethods(['getRandomCalendarObjectUri'])
->setConstructorArgs([$this->caldavBackend, $this->clientService, $this->config, $this->logger])
->getMock();
@@ -156,7 +156,7 @@ class RefreshWebcalServiceTest extends TestCase {
$client = $this->createMock(IClient::class);
$response = $this->createMock(IResponse::class);
$refreshWebcalService = $this->getMockBuilder(RefreshWebcalService::class)
- ->setMethods(['getRandomCalendarObjectUri', 'getSubscription', 'queryWebcalFeed'])
+ ->onlyMethods(['getRandomCalendarObjectUri', 'getSubscription', 'queryWebcalFeed'])
->setConstructorArgs([$this->caldavBackend, $this->clientService, $this->config, $this->logger])
->getMock();
@@ -217,7 +217,7 @@ class RefreshWebcalServiceTest extends TestCase {
$this->logger->expects($this->once())
->method('error')
- ->with($noInstanceException->getMessage(), ['exception' => $noInstanceException]);
+ ->with('Unable to create calendar object from subscription {subscriptionId}', ['exception' => $noInstanceException, 'subscriptionId' => '42', 'source' => 'webcal://foo.bar/bla2']);
$refreshWebcalService->refreshSubscription('principals/users/testuser', 'sub123');
}
@@ -233,7 +233,7 @@ class RefreshWebcalServiceTest extends TestCase {
$client = $this->createMock(IClient::class);
$response = $this->createMock(IResponse::class);
$refreshWebcalService = $this->getMockBuilder(RefreshWebcalService::class)
- ->setMethods(['getRandomCalendarObjectUri', 'getSubscription', 'queryWebcalFeed'])
+ ->onlyMethods(['getRandomCalendarObjectUri', 'getSubscription', 'queryWebcalFeed'])
->setConstructorArgs([$this->caldavBackend, $this->clientService, $this->config, $this->logger])
->getMock();
@@ -294,7 +294,7 @@ class RefreshWebcalServiceTest extends TestCase {
$this->logger->expects($this->once())
->method('error')
- ->with($badRequestException->getMessage(), ['exception' => $badRequestException]);
+ ->with('Unable to create calendar object from subscription {subscriptionId}', ['exception' => $badRequestException, 'subscriptionId' => '42', 'source' => 'webcal://foo.bar/bla2']);
$refreshWebcalService->refreshSubscription('principals/users/testuser', 'sub123');
}
@@ -324,10 +324,8 @@ class RefreshWebcalServiceTest extends TestCase {
/**
* @dataProvider runLocalURLDataProvider
- *
- * @param string $source
*/
- public function testRunLocalURL($source) {
+ public function testRunLocalURL(string $source) {
$refreshWebcalService = new RefreshWebcalService(
$this->caldavBackend,
$this->clientService,
@@ -361,14 +359,15 @@ class RefreshWebcalServiceTest extends TestCase {
->with('dav', 'webcalAllowLocalAccess', 'no')
->willReturn('no');
- $exception = new LocalServerException();
+ $localServerException = new LocalServerException();
+
$client->expects($this->once())
->method('get')
- ->willThrowException($exception);
+ ->willThrowException($localServerException);
$this->logger->expects($this->once())
->method('warning')
- ->with($this->anything(), ['exception' => $exception]);
+ ->with("Subscription 42 was not refreshed because it violates local access rules", ['exception' => $localServerException]);
$refreshWebcalService->refreshSubscription('principals/users/testuser', 'sub123');
}
diff --git a/apps/dav/tests/unit/CardDAV/Activity/BackendTest.php b/apps/dav/tests/unit/CardDAV/Activity/BackendTest.php
new file mode 100644
index 00000000000..bd88294ce81
--- /dev/null
+++ b/apps/dav/tests/unit/CardDAV/Activity/BackendTest.php
@@ -0,0 +1,503 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
+ *
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ * @author Joas Schilling <coding@schilljs.com>
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ * @author Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @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\DAV\Tests\unit\CardDAV\Activity;
+
+use OCA\DAV\CardDAV\Activity\Backend;
+use OCA\DAV\CardDAV\Activity\Provider\Addressbook;
+use OCA\DAV\CardDAV\Activity\Provider\Card;
+use OCP\Activity\IEvent;
+use OCP\Activity\IManager;
+use OCP\App\IAppManager;
+use OCP\IGroup;
+use OCP\IGroupManager;
+use OCP\IUser;
+use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
+use Test\TestCase;
+
+class BackendTest extends TestCase {
+
+ /** @var IManager|MockObject */
+ protected $activityManager;
+
+ /** @var IGroupManager|MockObject */
+ protected $groupManager;
+
+ /** @var IUserSession|MockObject */
+ protected $userSession;
+
+ /** @var IAppManager|MockObject */
+ protected $appManager;
+
+ protected function setUp(): void {
+ parent::setUp();
+ $this->activityManager = $this->createMock(IManager::class);
+ $this->groupManager = $this->createMock(IGroupManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->appManager = $this->createMock(IAppManager::class);
+ }
+
+ /**
+ * @param array $methods
+ * @return Backend|MockObject
+ */
+ protected function getBackend(array $methods = []) {
+ if (empty($methods)) {
+ return new Backend(
+ $this->activityManager,
+ $this->groupManager,
+ $this->userSession,
+ $this->appManager
+ );
+ } else {
+ return $this->getMockBuilder(Backend::class)
+ ->setConstructorArgs([
+ $this->activityManager,
+ $this->groupManager,
+ $this->userSession,
+ $this->appManager,
+ ])
+ ->onlyMethods($methods)
+ ->getMock();
+ }
+ }
+
+ public function dataCallTriggerAddressBookActivity(): array {
+ return [
+ ['onAddressbookCreate', [['data']], Addressbook::SUBJECT_ADD, [['data'], [], []]],
+ ['onAddressbookUpdate', [['data'], ['shares'], ['changed-properties']], Addressbook::SUBJECT_UPDATE, [['data'], ['shares'], ['changed-properties']]],
+ ['onAddressbookDelete', [['data'], ['shares']], Addressbook::SUBJECT_DELETE, [['data'], ['shares'], []]],
+ ];
+ }
+
+ /**
+ * @dataProvider dataCallTriggerAddressBookActivity
+ */
+ public function testCallTriggerAddressBookActivity(string $method, array $payload, string $expectedSubject, array $expectedPayload) {
+ $backend = $this->getBackend(['triggerAddressbookActivity']);
+ $backend->expects($this->once())
+ ->method('triggerAddressbookActivity')
+ ->willReturnCallback(function () use ($expectedPayload, $expectedSubject) {
+ $arguments = func_get_args();
+ $this->assertSame($expectedSubject, array_shift($arguments));
+ $this->assertEquals($expectedPayload, $arguments);
+ });
+
+ call_user_func_array([$backend, $method], $payload);
+ }
+
+ public function dataTriggerAddressBookActivity(): array {
+ return [
+ // Add addressbook
+ [Addressbook::SUBJECT_ADD, [], [], [], '', '', null, []],
+ [Addressbook::SUBJECT_ADD, [
+ 'principaluri' => 'principal/user/admin',
+ 'id' => 42,
+ 'uri' => 'this-uri',
+ '{DAV:}displayname' => 'Name of addressbook',
+ ], [], [], '', 'admin', null, ['admin']],
+ [Addressbook::SUBJECT_ADD, [
+ 'principaluri' => 'principal/user/admin',
+ 'id' => 42,
+ 'uri' => 'this-uri',
+ '{DAV:}displayname' => 'Name of addressbook',
+ ], [], [], 'test2', 'test2', null, ['admin']],
+
+ // Update addressbook
+ [Addressbook::SUBJECT_UPDATE, [], [], [], '', '', null, []],
+ // No visible change - owner only
+ [Addressbook::SUBJECT_UPDATE, [
+ 'principaluri' => 'principal/user/admin',
+ 'id' => 42,
+ 'uri' => 'this-uri',
+ '{DAV:}displayname' => 'Name of addressbook',
+ ], ['shares'], [], '', 'admin', null, ['admin']],
+ // Visible change
+ [Addressbook::SUBJECT_UPDATE, [
+ 'principaluri' => 'principal/user/admin',
+ 'id' => 42,
+ 'uri' => 'this-uri',
+ '{DAV:}displayname' => 'Name of addressbook',
+ ], ['shares'], ['{DAV:}displayname' => 'Name'], '', 'admin', ['user1'], ['user1', 'admin']],
+ [Addressbook::SUBJECT_UPDATE, [
+ 'principaluri' => 'principal/user/admin',
+ 'id' => 42,
+ 'uri' => 'this-uri',
+ '{DAV:}displayname' => 'Name of addressbook',
+ ], ['shares'], ['{DAV:}displayname' => 'Name'], 'test2', 'test2', ['user1'], ['user1', 'admin']],
+
+ // Delete addressbook
+ [Addressbook::SUBJECT_DELETE, [], [], [], '', '', null, []],
+ [Addressbook::SUBJECT_DELETE, [
+ 'principaluri' => 'principal/user/admin',
+ 'id' => 42,
+ 'uri' => 'this-uri',
+ '{DAV:}displayname' => 'Name of addressbook',
+ ], ['shares'], [], '', 'admin', [], ['admin']],
+ [Addressbook::SUBJECT_DELETE, [
+ 'principaluri' => 'principal/user/admin',
+ 'id' => 42,
+ 'uri' => 'this-uri',
+ '{DAV:}displayname' => 'Name of addressbook',
+ ], ['shares'], [], '', 'admin', ['user1'], ['user1', 'admin']],
+ [Addressbook::SUBJECT_DELETE, [
+ 'principaluri' => 'principal/user/admin',
+ 'id' => 42,
+ 'uri' => 'this-uri',
+ '{DAV:}displayname' => 'Name of addressbook',
+ ], ['shares'], [], 'test2', 'test2', ['user1'], ['user1', 'admin']],
+ ];
+ }
+
+ /**
+ * @dataProvider dataTriggerAddressBookActivity
+ * @param string $action
+ * @param array $data
+ * @param array $shares
+ * @param array $changedProperties
+ * @param string $currentUser
+ * @param string $author
+ * @param string[]|null $shareUsers
+ * @param string[] $users
+ */
+ public function testTriggerAddressBookActivity(string $action, array $data, array $shares, array $changedProperties, string $currentUser, string $author, ?array $shareUsers, array $users) {
+ $backend = $this->getBackend(['getUsersForShares']);
+
+ if ($shareUsers === null) {
+ $backend->expects($this->never())
+ ->method('getUsersForShares');
+ } else {
+ $backend->expects($this->once())
+ ->method('getUsersForShares')
+ ->with($shares)
+ ->willReturn($shareUsers);
+ }
+
+ if ($author !== '') {
+ if ($currentUser !== '') {
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->willReturn($this->getUserMock($currentUser));
+ } else {
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->willReturn(null);
+ }
+
+ $event = $this->createMock(IEvent::class);
+ $this->activityManager->expects($this->once())
+ ->method('generateEvent')
+ ->willReturn($event);
+
+ $event->expects($this->once())
+ ->method('setApp')
+ ->with('dav')
+ ->willReturnSelf();
+ $event->expects($this->once())
+ ->method('setObject')
+ ->with('addressbook', $data['id'])
+ ->willReturnSelf();
+ $event->expects($this->once())
+ ->method('setType')
+ ->with('addressbook')
+ ->willReturnSelf();
+ $event->expects($this->once())
+ ->method('setAuthor')
+ ->with($author)
+ ->willReturnSelf();
+
+ $event->expects($this->exactly(sizeof($users)))
+ ->method('setAffectedUser')
+ ->willReturnSelf();
+ $event->expects($this->exactly(sizeof($users)))
+ ->method('setSubject')
+ ->willReturnSelf();
+ $this->activityManager->expects($this->exactly(sizeof($users)))
+ ->method('publish')
+ ->with($event);
+ } else {
+ $this->activityManager->expects($this->never())
+ ->method('generateEvent');
+ }
+
+ $this->invokePrivate($backend, 'triggerAddressbookActivity', [$action, $data, $shares, $changedProperties]);
+ }
+
+ public function testNoAddressbookActivityCreatedForSystemAddressbook(): void {
+ $backend = $this->getBackend();
+ $this->activityManager->expects($this->never())
+ ->method('generateEvent');
+ $this->assertEmpty($this->invokePrivate($backend, 'triggerAddressbookActivity', [Addressbook::SUBJECT_ADD, ['principaluri' => 'principals/system/system'], [], [], '', '', null, []]));
+ }
+
+ public function dataTriggerCardActivity(): array {
+ $cardData = "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 3.4.8//EN\r\nUID:test-user\r\nFN:test-user\r\nN:test-user;;;;\r\nEND:VCARD\r\n\r\n";
+
+ return [
+ // Add card
+ [Card::SUBJECT_ADD, [], [], [], '', '', null, []],
+ [Card::SUBJECT_ADD, [
+ 'principaluri' => 'principal/user/admin',
+ 'id' => 42,
+ 'uri' => 'this-uri',
+ '{DAV:}displayname' => 'Name of addressbook',
+ ], [], [
+ 'carddata' => $cardData
+ ], '', 'admin', [], ['admin']],
+ [Card::SUBJECT_ADD, [
+ 'principaluri' => 'principal/user/admin',
+ 'id' => 42,
+ 'uri' => 'this-uri',
+ '{DAV:}displayname' => 'Name of addressbook',
+ ], [], ['carddata' => $cardData], 'test2', 'test2', [], ['admin']],
+
+ // Update card
+ [Card::SUBJECT_UPDATE, [], [], [], '', '', null, []],
+ // No visible change - owner only
+ [Card::SUBJECT_UPDATE, [
+ 'principaluri' => 'principal/user/admin',
+ 'id' => 42,
+ 'uri' => 'this-uri',
+ '{DAV:}displayname' => 'Name of addressbook',
+ ], ['shares'], ['carddata' => $cardData], '', 'admin', [], ['admin']],
+ // Visible change
+ [Card::SUBJECT_UPDATE, [
+ 'principaluri' => 'principal/user/admin',
+ 'id' => 42,
+ 'uri' => 'this-uri',
+ '{DAV:}displayname' => 'Name of addressbook',
+ ], ['shares'], ['carddata' => $cardData], '', 'admin', ['user1'], ['user1', 'admin']],
+ [Card::SUBJECT_UPDATE, [
+ 'principaluri' => 'principal/user/admin',
+ 'id' => 42,
+ 'uri' => 'this-uri',
+ '{DAV:}displayname' => 'Name of addressbook',
+ ], ['shares'], ['carddata' => $cardData], 'test2', 'test2', ['user1'], ['user1', 'admin']],
+
+ // Delete card
+ [Card::SUBJECT_DELETE, [], [], ['carddata' => $cardData], '', '', null, []],
+ [Card::SUBJECT_DELETE, [
+ 'principaluri' => 'principal/user/admin',
+ 'id' => 42,
+ 'uri' => 'this-uri',
+ '{DAV:}displayname' => 'Name of addressbook',
+ ], ['shares'], ['carddata' => $cardData], '', 'admin', [], ['admin']],
+ [Card::SUBJECT_DELETE, [
+ 'principaluri' => 'principal/user/admin',
+ 'id' => 42,
+ 'uri' => 'this-uri',
+ '{DAV:}displayname' => 'Name of addressbook',
+ ], ['shares'], ['carddata' => $cardData], '', 'admin', ['user1'], ['user1', 'admin']],
+ [Card::SUBJECT_DELETE, [
+ 'principaluri' => 'principal/user/admin',
+ 'id' => 42,
+ 'uri' => 'this-uri',
+ '{DAV:}displayname' => 'Name of addressbook',
+ ], ['shares'], ['carddata' => $cardData], 'test2', 'test2', ['user1'], ['user1', 'admin']],
+ ];
+ }
+
+ /**
+ * @dataProvider dataTriggerCardActivity
+ * @param string $action
+ * @param array $addressBookData
+ * @param array $shares
+ * @param array $cardData
+ * @param string $currentUser
+ * @param string $author
+ * @param string[]|null $shareUsers
+ * @param string[] $users
+ */
+ public function testTriggerCardActivity(string $action, array $addressBookData, array $shares, array $cardData, string $currentUser, string $author, ?array $shareUsers, array $users) {
+ $backend = $this->getBackend(['getUsersForShares']);
+
+ if ($shareUsers === null) {
+ $backend->expects($this->never())
+ ->method('getUsersForShares');
+ } else {
+ $backend->expects($this->once())
+ ->method('getUsersForShares')
+ ->with($shares)
+ ->willReturn($shareUsers);
+ }
+
+ if ($author !== '') {
+ if ($currentUser !== '') {
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->willReturn($this->getUserMock($currentUser));
+ } else {
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->willReturn(null);
+ }
+
+ $event = $this->createMock(IEvent::class);
+ $this->activityManager->expects($this->once())
+ ->method('generateEvent')
+ ->willReturn($event);
+
+ $event->expects($this->once())
+ ->method('setApp')
+ ->with('dav')
+ ->willReturnSelf();
+ $event->expects($this->once())
+ ->method('setObject')
+ ->with('addressbook', $addressBookData['id'])
+ ->willReturnSelf();
+ $event->expects($this->once())
+ ->method('setType')
+ ->with('card')
+ ->willReturnSelf();
+ $event->expects($this->once())
+ ->method('setAuthor')
+ ->with($author)
+ ->willReturnSelf();
+
+ $event->expects($this->exactly(sizeof($users)))
+ ->method('setAffectedUser')
+ ->willReturnSelf();
+ $event->expects($this->exactly(sizeof($users)))
+ ->method('setSubject')
+ ->willReturnSelf();
+ $this->activityManager->expects($this->exactly(sizeof($users)))
+ ->method('publish')
+ ->with($event);
+ } else {
+ $this->activityManager->expects($this->never())
+ ->method('generateEvent');
+ }
+
+ $this->invokePrivate($backend, 'triggerCardActivity', [$action, $addressBookData, $shares, $cardData]);
+ }
+
+ public function testNoCardActivityCreatedForSystemAddressbook(): void {
+ $backend = $this->getBackend();
+ $this->activityManager->expects($this->never())
+ ->method('generateEvent');
+ $this->assertEmpty($this->invokePrivate($backend, 'triggerCardActivity', [Card::SUBJECT_UPDATE, ['principaluri' => 'principals/system/system'], [], []]));
+ }
+
+ public function dataGetUsersForShares(): array {
+ return [
+ [
+ [],
+ [],
+ [],
+ ],
+ [
+ [
+ ['{http://owncloud.org/ns}principal' => 'principal/users/user1'],
+ ['{http://owncloud.org/ns}principal' => 'principal/users/user2'],
+ ['{http://owncloud.org/ns}principal' => 'principal/users/user2'],
+ ['{http://owncloud.org/ns}principal' => 'principal/users/user2'],
+ ['{http://owncloud.org/ns}principal' => 'principal/users/user3'],
+ ],
+ [],
+ ['user1', 'user2', 'user3'],
+ ],
+ [
+ [
+ ['{http://owncloud.org/ns}principal' => 'principal/users/user1'],
+ ['{http://owncloud.org/ns}principal' => 'principal/users/user2'],
+ ['{http://owncloud.org/ns}principal' => 'principal/users/user2'],
+ ['{http://owncloud.org/ns}principal' => 'principal/groups/group2'],
+ ['{http://owncloud.org/ns}principal' => 'principal/groups/group3'],
+ ],
+ ['group2' => null, 'group3' => null],
+ ['user1', 'user2'],
+ ],
+ [
+ [
+ ['{http://owncloud.org/ns}principal' => 'principal/users/user1'],
+ ['{http://owncloud.org/ns}principal' => 'principal/users/user2'],
+ ['{http://owncloud.org/ns}principal' => 'principal/users/user2'],
+ ['{http://owncloud.org/ns}principal' => 'principal/groups/group2'],
+ ['{http://owncloud.org/ns}principal' => 'principal/groups/group3'],
+ ],
+ ['group2' => ['user1', 'user2', 'user3'], 'group3' => ['user2', 'user3', 'user4']],
+ ['user1', 'user2', 'user3', 'user4'],
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataGetUsersForShares
+ * @param array $shares
+ * @param array $groups
+ * @param array $expected
+ */
+ public function testGetUsersForShares(array $shares, array $groups, array $expected) {
+ $backend = $this->getBackend();
+
+ $getGroups = [];
+ foreach ($groups as $gid => $members) {
+ if ($members === null) {
+ $getGroups[] = [$gid, null];
+ continue;
+ }
+
+ $group = $this->createMock(IGroup::class);
+ $group->expects($this->once())
+ ->method('getUsers')
+ ->willReturn($this->getUsers($members));
+
+ $getGroups[] = [$gid, $group];
+ }
+
+ $this->groupManager->expects($this->exactly(sizeof($getGroups)))
+ ->method('get')
+ ->willReturnMap($getGroups);
+
+ $users = $this->invokePrivate($backend, 'getUsersForShares', [$shares]);
+ sort($users);
+ $this->assertEquals($expected, $users);
+ }
+
+ /**
+ * @param string[] $users
+ * @return IUser[]|MockObject[]
+ */
+ protected function getUsers(array $users): array {
+ $list = [];
+ foreach ($users as $user) {
+ $list[] = $this->getUserMock($user);
+ }
+ return $list;
+ }
+
+ /**
+ * @param string $uid
+ * @return IUser|MockObject
+ */
+ protected function getUserMock(string $uid) {
+ $user = $this->createMock(IUser::class);
+ $user->expects($this->once())
+ ->method('getUID')
+ ->willReturn($uid);
+ return $user;
+ }
+}
diff --git a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
index 136751628d0..b468a2a65ae 100644
--- a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
+++ b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
@@ -13,6 +13,7 @@
* @author Morris Jobke <hey@morrisjobke.de>
* @author Robin Appelman <robin@icewind.nl>
* @author Roeland Jago Douma <roeland@famdouma.nl>
+ * @author Thomas Citharel <nextcloud@tcit.fr>
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @license AGPL-3.0
@@ -53,8 +54,6 @@ use Sabre\DAV\Exception\BadRequest;
use Sabre\DAV\PropPatch;
use Sabre\VObject\Component\VCard;
use Sabre\VObject\Property\Text;
-use Symfony\Component\EventDispatcher\EventDispatcherInterface;
-use Symfony\Component\EventDispatcher\GenericEvent;
use Test\TestCase;
/**
@@ -78,10 +77,7 @@ class CardDavBackendTest extends TestCase {
/** @var IGroupManager|\PHPUnit\Framework\MockObject\MockObject */
private $groupManager;
- /** @var EventDispatcherInterface|\PHPUnit\Framework\MockObject\MockObject */
- private $legacyDispatcher;
-
- /** @var IEventDispatcher|\PHPUnit\Framework\MockObject\MockObject */
+ /** @var IEventDispatcher|MockObject */
private $dispatcher;
/** @var IDBConnection */
@@ -157,11 +153,10 @@ class CardDavBackendTest extends TestCase {
->withAnyParameters()
->willReturn([self::UNIT_TEST_GROUP]);
$this->dispatcher = $this->createMock(IEventDispatcher::class);
- $this->legacyDispatcher = $this->createMock(EventDispatcherInterface::class);
$this->db = \OC::$server->getDatabaseConnection();
- $this->backend = new CardDavBackend($this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher);
+ $this->backend = new CardDavBackend($this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher);
// start every test with a empty cards_properties and cards table
$query = $this->db->getQueryBuilder();
$query->delete('cards_properties')->execute();
@@ -251,8 +246,8 @@ class CardDavBackendTest extends TestCase {
/** @var CardDavBackend | \PHPUnit\Framework\MockObject\MockObject $backend */
$backend = $this->getMockBuilder(CardDavBackend::class)
- ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher])
- ->setMethods(['updateProperties', 'purgeProperties'])->getMock();
+ ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher])
+ ->onlyMethods(['updateProperties', 'purgeProperties'])->getMock();
// create a new address book
$backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []);
@@ -266,13 +261,9 @@ class CardDavBackendTest extends TestCase {
$backend->expects($this->at(1))->method('updateProperties')->with($bookId, $uri, $this->vcardTest1);
// Expect event
- $this->legacyDispatcher->expects($this->at(0))
- ->method('dispatch')
- ->with('\OCA\DAV\CardDAV\CardDavBackend::createCard', $this->callback(function (GenericEvent $e) use ($bookId, $uri) {
- return $e->getArgument('addressBookId') === $bookId &&
- $e->getArgument('cardUri') === $uri &&
- $e->getArgument('cardData') === $this->vcardTest0;
- }));
+ $this->dispatcher
+ ->expects($this->exactly(3))
+ ->method('dispatchTyped');
// create a card
$backend->createCard($bookId, $uri, $this->vcardTest0);
@@ -292,28 +283,11 @@ class CardDavBackendTest extends TestCase {
$this->assertArrayHasKey('size', $card);
$this->assertEquals($this->vcardTest0, $card['carddata']);
- // Expect event
- $this->legacyDispatcher->expects($this->at(0))
- ->method('dispatch')
- ->with('\OCA\DAV\CardDAV\CardDavBackend::updateCard', $this->callback(function (GenericEvent $e) use ($bookId, $uri) {
- return $e->getArgument('addressBookId') === $bookId &&
- $e->getArgument('cardUri') === $uri &&
- $e->getArgument('cardData') === $this->vcardTest1;
- }));
-
// update the card
$backend->updateCard($bookId, $uri, $this->vcardTest1);
$card = $backend->getCard($bookId, $uri);
$this->assertEquals($this->vcardTest1, $card['carddata']);
- // Expect event
- $this->legacyDispatcher->expects($this->at(0))
- ->method('dispatch')
- ->with('\OCA\DAV\CardDAV\CardDavBackend::deleteCard', $this->callback(function (GenericEvent $e) use ($bookId, $uri) {
- return $e->getArgument('addressBookId') === $bookId &&
- $e->getArgument('cardUri') === $uri;
- }));
-
// delete the card
$backend->expects($this->once())->method('purgeProperties')->with($bookId, $card['id']);
$backend->deleteCard($bookId, $uri);
@@ -323,7 +297,7 @@ class CardDavBackendTest extends TestCase {
public function testMultiCard() {
$this->backend = $this->getMockBuilder(CardDavBackend::class)
- ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher])
+ ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher])
->setMethods(['updateProperties'])->getMock();
// create a new address book
@@ -376,8 +350,8 @@ class CardDavBackendTest extends TestCase {
public function testMultipleUIDOnDifferentAddressbooks() {
$this->backend = $this->getMockBuilder(CardDavBackend::class)
- ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher])
- ->setMethods(['updateProperties'])->getMock();
+ ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher])
+ ->onlyMethods(['updateProperties'])->getMock();
// create 2 new address books
$this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []);
@@ -398,7 +372,7 @@ class CardDavBackendTest extends TestCase {
public function testMultipleUIDDenied() {
$this->backend = $this->getMockBuilder(CardDavBackend::class)
- ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher])
+ ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher])
->setMethods(['updateProperties'])->getMock();
// create a new address book
@@ -419,7 +393,7 @@ class CardDavBackendTest extends TestCase {
public function testNoValidUID() {
$this->backend = $this->getMockBuilder(CardDavBackend::class)
- ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher])
+ ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher])
->setMethods(['updateProperties'])->getMock();
// create a new address book
@@ -436,8 +410,8 @@ class CardDavBackendTest extends TestCase {
public function testDeleteWithoutCard() {
$this->backend = $this->getMockBuilder(CardDavBackend::class)
- ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher])
- ->setMethods([
+ ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher])
+ ->onlyMethods([
'getCardId',
'addChange',
'purgeProperties',
@@ -476,7 +450,7 @@ class CardDavBackendTest extends TestCase {
public function testSyncSupport() {
$this->backend = $this->getMockBuilder(CardDavBackend::class)
- ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher])
+ ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher])
->setMethods(['updateProperties'])->getMock();
// create a new address book
@@ -542,8 +516,8 @@ class CardDavBackendTest extends TestCase {
$cardId = 2;
$backend = $this->getMockBuilder(CardDavBackend::class)
- ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher, $this->legacyDispatcher])
- ->setMethods(['getCardId'])->getMock();
+ ->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->groupManager, $this->dispatcher])
+ ->onlyMethods(['getCardId'])->getMock();
$backend->expects($this->any())->method('getCardId')->willReturn($cardId);
@@ -632,8 +606,8 @@ class CardDavBackendTest extends TestCase {
$qResult->closeCursor();
$this->assertSame(1, count($result));
- $this->assertSame(1 ,(int)$result[0]['addressbookid']);
- $this->assertSame(2 ,(int)$result[0]['cardid']);
+ $this->assertSame(1, (int)$result[0]['addressbookid']);
+ $this->assertSame(2, (int)$result[0]['cardid']);
}
public function testGetCardId() {
diff --git a/apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php
index 3627a177969..a553c0687e0 100644
--- a/apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php
@@ -32,6 +32,7 @@ use OC\Log;
use OC\SystemConfig;
use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
use OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin;
+use OCA\DAV\Exception\ServerMaintenanceMode;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\Exception\ServiceUnavailable;
@@ -84,8 +85,10 @@ class ExceptionLoggerPluginTest extends TestCase {
public function providesExceptions() {
return [
['debug', new NotFound()],
- ['debug', new ServiceUnavailable('System in maintenance mode.')],
- ['critical', new ServiceUnavailable('Upgrade needed')],
+ ['debug', new ServerMaintenanceMode('System is in maintenance mode.')],
+ // Faking a translation
+ ['debug', new ServerMaintenanceMode('Syst3m 1s 1n m41nt3n4nc3 m0d3.')],
+ ['debug', new ServerMaintenanceMode('Upgrade needed')],
['critical', new InvalidPath('This path leads to nowhere')]
];
}
diff --git a/apps/dav/tests/unit/Listener/ActivityUpdaterListenerTest.php b/apps/dav/tests/unit/Listener/ActivityUpdaterListenerTest.php
new file mode 100644
index 00000000000..03c4046991c
--- /dev/null
+++ b/apps/dav/tests/unit/Listener/ActivityUpdaterListenerTest.php
@@ -0,0 +1,104 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2022 Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @author Thomas Citharel <nextcloud@tcit.fr>
+ *
+ * @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\DAV\Tests\Unit\Listener;
+
+use OCA\DAV\CalDAV\Activity\Backend as ActivityBackend;
+use OCA\DAV\CalDAV\Activity\Provider\Event;
+use OCA\DAV\DAV\Sharing\Plugin as SharingPlugin;
+use OCA\DAV\Events\CalendarDeletedEvent;
+use OCA\DAV\Events\CalendarObjectDeletedEvent;
+use OCA\DAV\Listener\ActivityUpdaterListener;
+use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
+use Test\TestCase;
+
+class ActivityUpdaterListenerTest extends TestCase {
+
+ /** @var ActivityBackend|MockObject */
+ private $activityBackend;
+ /** @var LoggerInterface|MockObject */
+ private $logger;
+ /** @var ActivityUpdaterListener */
+ private ActivityUpdaterListener $listener;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->activityBackend = $this->createMock(ActivityBackend::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
+
+ $this->listener = new ActivityUpdaterListener(
+ $this->activityBackend,
+ $this->logger
+ );
+ }
+
+ /**
+ * @dataProvider dataForTestHandleCalendarObjectDeletedEvent
+ */
+ public function testHandleCalendarObjectDeletedEvent(int $calendarId, array $calendarData, array $shares, array $objectData, bool $createsActivity): void {
+ $event = new CalendarObjectDeletedEvent($calendarId, $calendarData, $shares, $objectData);
+ $this->logger->expects($this->once())->method('debug')->with(
+ $createsActivity ? "Activity generated for deleted calendar object in calendar $calendarId" : "Calendar object in calendar $calendarId was already in trashbin, skipping deletion activity"
+ );
+ $this->activityBackend->expects($createsActivity ? $this->once() : $this->never())->method('onTouchCalendarObject')->with(
+ Event::SUBJECT_OBJECT_DELETE,
+ $calendarData,
+ $shares,
+ $objectData
+ );
+ $this->listener->handle($event);
+ }
+
+ public function dataForTestHandleCalendarObjectDeletedEvent(): array {
+ return [
+ [1, [], [], [], true],
+ [1, [], [], ['{' . SharingPlugin::NS_NEXTCLOUD . '}deleted-at' => 120], false],
+ ];
+ }
+
+ /**
+ * @dataProvider dataForTestHandleCalendarDeletedEvent
+ */
+ public function testHandleCalendarDeletedEvent(int $calendarId, array $calendarData, array $shares, bool $createsActivity): void {
+ $event = new CalendarDeletedEvent($calendarId, $calendarData, $shares);
+ $this->logger->expects($this->once())->method('debug')->with(
+ $createsActivity ? "Activity generated for deleted calendar $calendarId" : "Calendar $calendarId was already in trashbin, skipping deletion activity"
+ );
+ $this->activityBackend->expects($createsActivity ? $this->once() : $this->never())->method('onCalendarDelete')->with(
+ $calendarData,
+ $shares
+ );
+ $this->listener->handle($event);
+ }
+
+ public function dataForTestHandleCalendarDeletedEvent(): array {
+ return [
+ [1, [], [], true],
+ [1, ['{' . SharingPlugin::NS_NEXTCLOUD . '}deleted-at' => 120], [], false],
+ ];
+ }
+}