aboutsummaryrefslogtreecommitdiffstats
path: root/apps/dav
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dav')
-rw-r--r--apps/dav/appinfo/routes.php3
-rw-r--r--apps/dav/composer/composer/autoload_classmap.php2
-rw-r--r--apps/dav/composer/composer/autoload_static.php2
-rw-r--r--apps/dav/l10n/en_GB.js10
-rw-r--r--apps/dav/l10n/en_GB.json10
-rw-r--r--apps/dav/l10n/fr.js36
-rw-r--r--apps/dav/l10n/fr.json36
-rw-r--r--apps/dav/l10n/ga.js10
-rw-r--r--apps/dav/l10n/ga.json10
-rw-r--r--apps/dav/l10n/pl.js20
-rw-r--r--apps/dav/l10n/pl.json20
-rw-r--r--apps/dav/l10n/zh_CN.js18
-rw-r--r--apps/dav/l10n/zh_CN.json18
-rw-r--r--apps/dav/l10n/zh_HK.js10
-rw-r--r--apps/dav/l10n/zh_HK.json10
-rw-r--r--apps/dav/lib/CalDAV/CalDavBackend.php2
-rw-r--r--apps/dav/lib/Controller/ExampleContentController.php80
-rw-r--r--apps/dav/lib/Listener/UserEventsListener.php6
-rw-r--r--apps/dav/lib/Service/DefaultContactService.php77
-rw-r--r--apps/dav/lib/Service/ExampleContactService.php132
-rw-r--r--apps/dav/lib/Settings/ExampleContentSettings.php14
-rw-r--r--apps/dav/src/components/ExampleContactSettings.vue4
-rw-r--r--apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php8
-rw-r--r--apps/dav/tests/unit/Service/ExampleContactServiceTest.php (renamed from apps/dav/tests/unit/Service/DefaultContactServiceTest.php)85
24 files changed, 423 insertions, 200 deletions
diff --git a/apps/dav/appinfo/routes.php b/apps/dav/appinfo/routes.php
index d0953add93f..91c1ba58ea2 100644
--- a/apps/dav/appinfo/routes.php
+++ b/apps/dav/appinfo/routes.php
@@ -11,9 +11,6 @@ return [
['name' => 'invitation_response#decline', 'url' => '/invitation/decline/{token}', 'verb' => 'GET'],
['name' => 'invitation_response#options', 'url' => '/invitation/moreOptions/{token}', 'verb' => 'GET'],
['name' => 'invitation_response#processMoreOptionsResult', 'url' => '/invitation/moreOptions/{token}', 'verb' => 'POST'],
- ['name' => 'example_content#getDefaultContact', 'url' => '/api/defaultcontact/contact', 'verb' => 'GET'],
- ['name' => 'example_content#setDefaultContact', 'url' => '/api/defaultcontact/contact', 'verb' => 'PUT'],
- ['name' => 'example_content#setEnableDefaultContact', 'url' => '/api/defaultcontact/config', 'verb' => 'PUT'],
],
'ocs' => [
['name' => 'direct#getUrl', 'url' => '/api/v1/direct', 'verb' => 'POST'],
diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php
index 312f30ca8c5..4c48f343c4c 100644
--- a/apps/dav/composer/composer/autoload_classmap.php
+++ b/apps/dav/composer/composer/autoload_classmap.php
@@ -366,7 +366,7 @@ return array(
'OCA\\DAV\\Server' => $baseDir . '/../lib/Server.php',
'OCA\\DAV\\ServerFactory' => $baseDir . '/../lib/ServerFactory.php',
'OCA\\DAV\\Service\\AbsenceService' => $baseDir . '/../lib/Service/AbsenceService.php',
- 'OCA\\DAV\\Service\\DefaultContactService' => $baseDir . '/../lib/Service/DefaultContactService.php',
+ 'OCA\\DAV\\Service\\ExampleContactService' => $baseDir . '/../lib/Service/ExampleContactService.php',
'OCA\\DAV\\Service\\ExampleEventService' => $baseDir . '/../lib/Service/ExampleEventService.php',
'OCA\\DAV\\Settings\\Admin\\SystemAddressBookSettings' => $baseDir . '/../lib/Settings/Admin/SystemAddressBookSettings.php',
'OCA\\DAV\\Settings\\AvailabilitySettings' => $baseDir . '/../lib/Settings/AvailabilitySettings.php',
diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php
index aeb354685bf..4d9166a2d5a 100644
--- a/apps/dav/composer/composer/autoload_static.php
+++ b/apps/dav/composer/composer/autoload_static.php
@@ -381,7 +381,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Server' => __DIR__ . '/..' . '/../lib/Server.php',
'OCA\\DAV\\ServerFactory' => __DIR__ . '/..' . '/../lib/ServerFactory.php',
'OCA\\DAV\\Service\\AbsenceService' => __DIR__ . '/..' . '/../lib/Service/AbsenceService.php',
- 'OCA\\DAV\\Service\\DefaultContactService' => __DIR__ . '/..' . '/../lib/Service/DefaultContactService.php',
+ 'OCA\\DAV\\Service\\ExampleContactService' => __DIR__ . '/..' . '/../lib/Service/ExampleContactService.php',
'OCA\\DAV\\Service\\ExampleEventService' => __DIR__ . '/..' . '/../lib/Service/ExampleEventService.php',
'OCA\\DAV\\Settings\\Admin\\SystemAddressBookSettings' => __DIR__ . '/..' . '/../lib/Settings/Admin/SystemAddressBookSettings.php',
'OCA\\DAV\\Settings\\AvailabilitySettings' => __DIR__ . '/..' . '/../lib/Settings/AvailabilitySettings.php',
diff --git a/apps/dav/l10n/en_GB.js b/apps/dav/l10n/en_GB.js
index d8b77218a68..75233b334ed 100644
--- a/apps/dav/l10n/en_GB.js
+++ b/apps/dav/l10n/en_GB.js
@@ -301,6 +301,14 @@ OC.L10N.register(
"Reset to default" : "Reset to default",
"Import contacts" : "Import contacts",
"Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?",
+ "Failed to save example event creation setting" : "Failed to save example event creation setting",
+ "Failed to upload the example event" : "Failed to upload the example event",
+ "Custom example event was saved successfully" : "Custom example event was saved successfully",
+ "Failed to delete the custom example event" : "Failed to delete the custom example event",
+ "Custom example event was deleted successfully" : "Custom example event was deleted successfully",
+ "Import calendar event" : "Import calendar event",
+ "Uploading a new event will overwrite the existing one." : "Uploading a new event will overwrite the existing one.",
+ "Upload event" : "Upload event",
"Availability" : "Availability",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "If you configure your working hours, other people will see when you are out of office when they book a meeting.",
"Absence" : "Absence",
@@ -317,6 +325,8 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Send reminder notifications to calendar sharees as well",
"Reminders are always sent to organizers and attendees." : "Reminders are always sent to organisers and attendees.",
"Enable notifications for events via push" : "Enable notifications for events via push",
+ "Example content" : "Example content",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content.",
"There was an error updating your attendance status." : "There was an error updating your attendance status.",
"Please contact the organizer directly." : "Please contact the organiser directly.",
"Are you accepting the invitation?" : "Are you accepting the invitation?",
diff --git a/apps/dav/l10n/en_GB.json b/apps/dav/l10n/en_GB.json
index 10e37cc1bf9..0fbdf464438 100644
--- a/apps/dav/l10n/en_GB.json
+++ b/apps/dav/l10n/en_GB.json
@@ -299,6 +299,14 @@
"Reset to default" : "Reset to default",
"Import contacts" : "Import contacts",
"Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?",
+ "Failed to save example event creation setting" : "Failed to save example event creation setting",
+ "Failed to upload the example event" : "Failed to upload the example event",
+ "Custom example event was saved successfully" : "Custom example event was saved successfully",
+ "Failed to delete the custom example event" : "Failed to delete the custom example event",
+ "Custom example event was deleted successfully" : "Custom example event was deleted successfully",
+ "Import calendar event" : "Import calendar event",
+ "Uploading a new event will overwrite the existing one." : "Uploading a new event will overwrite the existing one.",
+ "Upload event" : "Upload event",
"Availability" : "Availability",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "If you configure your working hours, other people will see when you are out of office when they book a meeting.",
"Absence" : "Absence",
@@ -315,6 +323,8 @@
"Send reminder notifications to calendar sharees as well" : "Send reminder notifications to calendar sharees as well",
"Reminders are always sent to organizers and attendees." : "Reminders are always sent to organisers and attendees.",
"Enable notifications for events via push" : "Enable notifications for events via push",
+ "Example content" : "Example content",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content.",
"There was an error updating your attendance status." : "There was an error updating your attendance status.",
"Please contact the organizer directly." : "Please contact the organiser directly.",
"Are you accepting the invitation?" : "Are you accepting the invitation?",
diff --git a/apps/dav/l10n/fr.js b/apps/dav/l10n/fr.js
index 94949657119..667666b94dc 100644
--- a/apps/dav/l10n/fr.js
+++ b/apps/dav/l10n/fr.js
@@ -81,6 +81,11 @@ OC.L10N.register(
"_In a year on %1$s for the entire day_::_In %n years on %1$s for the entire day_" : ["Dans un an toute la journée du %1$s","Dans %n années toute la journée du %1$s","Dans %n années toute la journée du %1$s"],
"In the past on %1$s between %2$s - %3$s" : "Dans le passé le %1$s entre %2$s - %3$s",
"_In a minute on %1$s between %2$s - %3$s_::_In %n minutes on %1$s between %2$s - %3$s_" : ["Dans une minute le %1$s entre %2$s - %3$s","Dans %n minutes le %1$s entre %2$s - %3$s","Dans %n minutes le %1$s entre %2$s - %3$s"],
+ "_In a hour on %1$s between %2$s - %3$s_::_In %n hours on %1$s between %2$s - %3$s_" : ["Dans une heure le %1$s entre %2$s et %3$s","Dans %n heures le %1$s entre %2$s et %3$s","Dans %n heures le %1$s entre %2$s et %3$s"],
+ "_In a day on %1$s between %2$s - %3$s_::_In %n days on %1$s between %2$s - %3$s_" : ["Demain le %1$s entre %2$s et %3$s","Dans %n jours le %1$s entre %2$s et %3$s","Dans %n jours le %1$s entre %2$s et %3$s"],
+ "_In a week on %1$s between %2$s - %3$s_::_In %n weeks on %1$s between %2$s - %3$s_" : ["La semaine prochaine le %1$s entre %2$s et %3$s","Dans %n semaines le %1$s entre %2$s et %3$s","Dans %n semaines le %1$s entre %2$s et %3$s"],
+ "_In a month on %1$s between %2$s - %3$s_::_In %n months on %1$s between %2$s - %3$s_" : ["Dans un mois le %1$s entre %2$s et %3$s","Dans %n mois le %1$s entre %2$s et %3$s","Dans %n mois le %1$s entre %2$s et %3$s"],
+ "_In a year on %1$s between %2$s - %3$s_::_In %n years on %1$s between %2$s - %3$s_" : ["L'an prochain le %1$s entre %2$s et %3$s","Dans %n ans le %1$s entre %2$s et %3$s","Dans %n ans le %1$s entre %2$s et %3$s"],
"Could not generate when statement" : "Impossible de déterminer quand",
"Every Day for the entire day" : "Chaque jour pour toute la journée",
"Every Day for the entire day until %1$s" : "Chaque jour pour toute la journée jusqu'au %1$s",
@@ -117,6 +122,27 @@ OC.L10N.register(
"Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Tous les %1$d ans en %2$s le %3$s entre %4$s - %5$s jusqu'au %6$s",
"On specific dates for the entire day until %1$s" : "À une date spécifique pour la journée entière jusqu'au %1$s",
"On specific dates between %1$s - %2$s until %3$s" : "À des dates spécifiques entre %1$s et %2$s jusqu'au %3$s",
+ "In the past on %1$s" : "Dans le passé sur %1$s",
+ "_In a minute on %1$s_::_In %n minutes on %1$s_" : ["Dans une minute sur %1$s","Dans %n minutes sur %1$s","Dans %n minutes sur %1$s"],
+ "_In a hour on %1$s_::_In %n hours on %1$s_" : ["Dans une heure sur %1$s","Dans %n heures sur %1$s","Dans %n sur %1$s"],
+ "_In a day on %1$s_::_In %n days on %1$s_" : ["Demain le %1$s","Dans %n jours le %1$s","Dans %n jours le %1$s"],
+ "_In a week on %1$s_::_In %n weeks on %1$s_" : ["La semaine prochaine le %1$s","Dans %n semaines le %1$s","Dans %n semaines le %1$s"],
+ "_In a month on %1$s_::_In %n months on %1$s_" : ["Le mois prochain le %1$s","Dans %n mois le %1$s","Dans %n mois le %1$s"],
+ "_In a year on %1$s_::_In %n years on %1$s_" : ["L'an prochain le %1$s","Dans %n ans le %1$s","Dans %n ans le %1$s"],
+ "In the past on %1$s then on %2$s" : "Dans le passé le %1$s puis le %2$s",
+ "_In a minute on %1$s then on %2$s_::_In %n minutes on %1$s then on %2$s_" : ["Dans une minute le %1$s puis le %2$s","Dans %n minutes le %1$s puis le %2$s","Dans %n minutes le %1$s puis le %2$s"],
+ "_In a hour on %1$s then on %2$s_::_In %n hours on %1$s then on %2$s_" : ["Dans une heure le %1$s puis le %2$s","Dans %n heures le %1$s puis le %2$s","Dans %n heures le %1$s puis le %2$s"],
+ "_In a day on %1$s then on %2$s_::_In %n days on %1$s then on %2$s_" : ["Demain le %1$s puis le %2$s","Dans %n jours le %1$s puis le %2$s","Dans %n jours le %1$s puis le %2$s"],
+ "_In a week on %1$s then on %2$s_::_In %n weeks on %1$s then on %2$s_" : ["La semaine prochaine le %1$s puis le %2$s","Dans %n semaines le %1$s puis le %2$s","Dans %n semaines le %1$s puis le %2$s"],
+ "_In a month on %1$s then on %2$s_::_In %n months on %1$s then on %2$s_" : ["Le mois prochain le %1$s puis le %2$s","Dans %n mois le %1$s puis le %2$s","Dans %n mois le %1$s puis le %2$s"],
+ "_In a year on %1$s then on %2$s_::_In %n years on %1$s then on %2$s_" : ["L'an prochain le %1$s puis le %2$s","Dans %n ans le %1$s puis le %2$s","Dans %n ans le %1$s puis le %2$s"],
+ "In the past on %1$s then on %2$s and %3$s" : "Dans le passé le %1$s puis le %2$s et %3$s",
+ "_In a minute on %1$s then on %2$s and %3$s_::_In %n minutes on %1$s then on %2$s and %3$s_" : ["Dans une minute le %1$s puis le %2$s et %3$s","Dans %n minutes le %1$s puis le %2$s et %3$s","Dans %n minutes le %1$s puis le %2$s et %3$s"],
+ "_In a hour on %1$s then on %2$s and %3$s_::_In %n hours on %1$s then on %2$s and %3$s_" : ["Dans une heure le %1$s puis le %2$s et %3$s","Dans %n heures le %1$s puis le %2$s et %3$s","Dans %n heures le %1$s puis le %2$s et %3$s"],
+ "_In a day on %1$s then on %2$s and %3$s_::_In %n days on %1$s then on %2$s and %3$s_" : ["Demain le %1$s puis le %2$s et %3$s","Dans %n jours le %1$s puis le %2$s et %3$s","Dans %n jours le %1$s puis le %2$s et %3$s"],
+ "_In a week on %1$s then on %2$s and %3$s_::_In %n weeks on %1$s then on %2$s and %3$s_" : ["La semaine prochaine le %1$s puis le %2$s et %3$s","Dans %n semaines le %1$s puis le %2$s et %3$s","Dans %n semaines le %1$s puis le %2$s et %3$s"],
+ "_In a month on %1$s then on %2$s and %3$s_::_In %n months on %1$s then on %2$s and %3$s_" : ["Dans un mois le %1$s puis le %2$s et %3$s","Dans %n mois le %1$s puis le %2$s et %3$s","Dans %n mois le %1$s puis le %2$s et %3$s"],
+ "_In a year on %1$s then on %2$s and %3$s_::_In %n years on %1$s then on %2$s and %3$s_" : ["Dans un an sur %1$spuis sur %2$s et %3$s","Dans %n années sur %1$s puis sur %2$s et %3$s","Dans %n années sur %1$s puis sur %2$s et %3$s"],
"Could not generate next recurrence statement" : "Impossible de déterminer la prochaine récurrence",
"Cancelled: %1$s" : "Annulé : %1$s",
"\"%1$s\" has been canceled" : "\"%1$s\" a été annulé(e)",
@@ -275,6 +301,14 @@ OC.L10N.register(
"Reset to default" : "Restaurer les valeurs par défaut",
"Import contacts" : "Importer des contacts",
"Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Importer un nouveau fichier .vcf supprimera le contact par défaut existant et le remplacera. Voulez-vous continuer ?",
+ "Failed to save example event creation setting" : "Échec de la sauvegarde du paramètre de l'exemple de création d'événement",
+ "Failed to upload the example event" : "Échec du téléversement de l'exemple d'événement",
+ "Custom example event was saved successfully" : "L'exemple d'événement personnalisé a bien été enregistré",
+ "Failed to delete the custom example event" : "Échec de la suppression de l'exemple d'événement personnalisé ",
+ "Custom example event was deleted successfully" : "L'exemple de contenu personnalisé a bien été supprimé",
+ "Import calendar event" : "Importer l'événement du calendrier",
+ "Uploading a new event will overwrite the existing one." : "Charger un nouvel événement qui va remplacer l'actuel.",
+ "Upload event" : "Téléverser un événement",
"Availability" : "Disponibilités",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Si vous configurez vos heures de travail, les autres personnes verront si vous êtes disponible quand ils planifient une réunion.",
"Absence" : "Absence",
@@ -291,6 +325,8 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Envoyez également des notifications de rappel aux personnes partageant le calendrier",
"Reminders are always sent to organizers and attendees." : "Des rappels sont toujours envoyés aux organisateurs et aux participants.",
"Enable notifications for events via push" : "Activer les notifications push pour les évènements",
+ "Example content" : "Exemple de contenu",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Les exemples de contenu servent à présenter les fonctionnalités de Nextcloud. Le contenu par défaut est fourni avec Nextcloud et peut être remplacé par du contenu personnalisé.",
"There was an error updating your attendance status." : "Une erreur s'est produite lors de la mise à jour de votre statut de présence.",
"Please contact the organizer directly." : "Merci de contacter l'organisateur directement.",
"Are you accepting the invitation?" : "Acceptez-vous l'invitation ?",
diff --git a/apps/dav/l10n/fr.json b/apps/dav/l10n/fr.json
index f64d65ed786..b9a5a65e888 100644
--- a/apps/dav/l10n/fr.json
+++ b/apps/dav/l10n/fr.json
@@ -79,6 +79,11 @@
"_In a year on %1$s for the entire day_::_In %n years on %1$s for the entire day_" : ["Dans un an toute la journée du %1$s","Dans %n années toute la journée du %1$s","Dans %n années toute la journée du %1$s"],
"In the past on %1$s between %2$s - %3$s" : "Dans le passé le %1$s entre %2$s - %3$s",
"_In a minute on %1$s between %2$s - %3$s_::_In %n minutes on %1$s between %2$s - %3$s_" : ["Dans une minute le %1$s entre %2$s - %3$s","Dans %n minutes le %1$s entre %2$s - %3$s","Dans %n minutes le %1$s entre %2$s - %3$s"],
+ "_In a hour on %1$s between %2$s - %3$s_::_In %n hours on %1$s between %2$s - %3$s_" : ["Dans une heure le %1$s entre %2$s et %3$s","Dans %n heures le %1$s entre %2$s et %3$s","Dans %n heures le %1$s entre %2$s et %3$s"],
+ "_In a day on %1$s between %2$s - %3$s_::_In %n days on %1$s between %2$s - %3$s_" : ["Demain le %1$s entre %2$s et %3$s","Dans %n jours le %1$s entre %2$s et %3$s","Dans %n jours le %1$s entre %2$s et %3$s"],
+ "_In a week on %1$s between %2$s - %3$s_::_In %n weeks on %1$s between %2$s - %3$s_" : ["La semaine prochaine le %1$s entre %2$s et %3$s","Dans %n semaines le %1$s entre %2$s et %3$s","Dans %n semaines le %1$s entre %2$s et %3$s"],
+ "_In a month on %1$s between %2$s - %3$s_::_In %n months on %1$s between %2$s - %3$s_" : ["Dans un mois le %1$s entre %2$s et %3$s","Dans %n mois le %1$s entre %2$s et %3$s","Dans %n mois le %1$s entre %2$s et %3$s"],
+ "_In a year on %1$s between %2$s - %3$s_::_In %n years on %1$s between %2$s - %3$s_" : ["L'an prochain le %1$s entre %2$s et %3$s","Dans %n ans le %1$s entre %2$s et %3$s","Dans %n ans le %1$s entre %2$s et %3$s"],
"Could not generate when statement" : "Impossible de déterminer quand",
"Every Day for the entire day" : "Chaque jour pour toute la journée",
"Every Day for the entire day until %1$s" : "Chaque jour pour toute la journée jusqu'au %1$s",
@@ -115,6 +120,27 @@
"Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Tous les %1$d ans en %2$s le %3$s entre %4$s - %5$s jusqu'au %6$s",
"On specific dates for the entire day until %1$s" : "À une date spécifique pour la journée entière jusqu'au %1$s",
"On specific dates between %1$s - %2$s until %3$s" : "À des dates spécifiques entre %1$s et %2$s jusqu'au %3$s",
+ "In the past on %1$s" : "Dans le passé sur %1$s",
+ "_In a minute on %1$s_::_In %n minutes on %1$s_" : ["Dans une minute sur %1$s","Dans %n minutes sur %1$s","Dans %n minutes sur %1$s"],
+ "_In a hour on %1$s_::_In %n hours on %1$s_" : ["Dans une heure sur %1$s","Dans %n heures sur %1$s","Dans %n sur %1$s"],
+ "_In a day on %1$s_::_In %n days on %1$s_" : ["Demain le %1$s","Dans %n jours le %1$s","Dans %n jours le %1$s"],
+ "_In a week on %1$s_::_In %n weeks on %1$s_" : ["La semaine prochaine le %1$s","Dans %n semaines le %1$s","Dans %n semaines le %1$s"],
+ "_In a month on %1$s_::_In %n months on %1$s_" : ["Le mois prochain le %1$s","Dans %n mois le %1$s","Dans %n mois le %1$s"],
+ "_In a year on %1$s_::_In %n years on %1$s_" : ["L'an prochain le %1$s","Dans %n ans le %1$s","Dans %n ans le %1$s"],
+ "In the past on %1$s then on %2$s" : "Dans le passé le %1$s puis le %2$s",
+ "_In a minute on %1$s then on %2$s_::_In %n minutes on %1$s then on %2$s_" : ["Dans une minute le %1$s puis le %2$s","Dans %n minutes le %1$s puis le %2$s","Dans %n minutes le %1$s puis le %2$s"],
+ "_In a hour on %1$s then on %2$s_::_In %n hours on %1$s then on %2$s_" : ["Dans une heure le %1$s puis le %2$s","Dans %n heures le %1$s puis le %2$s","Dans %n heures le %1$s puis le %2$s"],
+ "_In a day on %1$s then on %2$s_::_In %n days on %1$s then on %2$s_" : ["Demain le %1$s puis le %2$s","Dans %n jours le %1$s puis le %2$s","Dans %n jours le %1$s puis le %2$s"],
+ "_In a week on %1$s then on %2$s_::_In %n weeks on %1$s then on %2$s_" : ["La semaine prochaine le %1$s puis le %2$s","Dans %n semaines le %1$s puis le %2$s","Dans %n semaines le %1$s puis le %2$s"],
+ "_In a month on %1$s then on %2$s_::_In %n months on %1$s then on %2$s_" : ["Le mois prochain le %1$s puis le %2$s","Dans %n mois le %1$s puis le %2$s","Dans %n mois le %1$s puis le %2$s"],
+ "_In a year on %1$s then on %2$s_::_In %n years on %1$s then on %2$s_" : ["L'an prochain le %1$s puis le %2$s","Dans %n ans le %1$s puis le %2$s","Dans %n ans le %1$s puis le %2$s"],
+ "In the past on %1$s then on %2$s and %3$s" : "Dans le passé le %1$s puis le %2$s et %3$s",
+ "_In a minute on %1$s then on %2$s and %3$s_::_In %n minutes on %1$s then on %2$s and %3$s_" : ["Dans une minute le %1$s puis le %2$s et %3$s","Dans %n minutes le %1$s puis le %2$s et %3$s","Dans %n minutes le %1$s puis le %2$s et %3$s"],
+ "_In a hour on %1$s then on %2$s and %3$s_::_In %n hours on %1$s then on %2$s and %3$s_" : ["Dans une heure le %1$s puis le %2$s et %3$s","Dans %n heures le %1$s puis le %2$s et %3$s","Dans %n heures le %1$s puis le %2$s et %3$s"],
+ "_In a day on %1$s then on %2$s and %3$s_::_In %n days on %1$s then on %2$s and %3$s_" : ["Demain le %1$s puis le %2$s et %3$s","Dans %n jours le %1$s puis le %2$s et %3$s","Dans %n jours le %1$s puis le %2$s et %3$s"],
+ "_In a week on %1$s then on %2$s and %3$s_::_In %n weeks on %1$s then on %2$s and %3$s_" : ["La semaine prochaine le %1$s puis le %2$s et %3$s","Dans %n semaines le %1$s puis le %2$s et %3$s","Dans %n semaines le %1$s puis le %2$s et %3$s"],
+ "_In a month on %1$s then on %2$s and %3$s_::_In %n months on %1$s then on %2$s and %3$s_" : ["Dans un mois le %1$s puis le %2$s et %3$s","Dans %n mois le %1$s puis le %2$s et %3$s","Dans %n mois le %1$s puis le %2$s et %3$s"],
+ "_In a year on %1$s then on %2$s and %3$s_::_In %n years on %1$s then on %2$s and %3$s_" : ["Dans un an sur %1$spuis sur %2$s et %3$s","Dans %n années sur %1$s puis sur %2$s et %3$s","Dans %n années sur %1$s puis sur %2$s et %3$s"],
"Could not generate next recurrence statement" : "Impossible de déterminer la prochaine récurrence",
"Cancelled: %1$s" : "Annulé : %1$s",
"\"%1$s\" has been canceled" : "\"%1$s\" a été annulé(e)",
@@ -273,6 +299,14 @@
"Reset to default" : "Restaurer les valeurs par défaut",
"Import contacts" : "Importer des contacts",
"Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Importer un nouveau fichier .vcf supprimera le contact par défaut existant et le remplacera. Voulez-vous continuer ?",
+ "Failed to save example event creation setting" : "Échec de la sauvegarde du paramètre de l'exemple de création d'événement",
+ "Failed to upload the example event" : "Échec du téléversement de l'exemple d'événement",
+ "Custom example event was saved successfully" : "L'exemple d'événement personnalisé a bien été enregistré",
+ "Failed to delete the custom example event" : "Échec de la suppression de l'exemple d'événement personnalisé ",
+ "Custom example event was deleted successfully" : "L'exemple de contenu personnalisé a bien été supprimé",
+ "Import calendar event" : "Importer l'événement du calendrier",
+ "Uploading a new event will overwrite the existing one." : "Charger un nouvel événement qui va remplacer l'actuel.",
+ "Upload event" : "Téléverser un événement",
"Availability" : "Disponibilités",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Si vous configurez vos heures de travail, les autres personnes verront si vous êtes disponible quand ils planifient une réunion.",
"Absence" : "Absence",
@@ -289,6 +323,8 @@
"Send reminder notifications to calendar sharees as well" : "Envoyez également des notifications de rappel aux personnes partageant le calendrier",
"Reminders are always sent to organizers and attendees." : "Des rappels sont toujours envoyés aux organisateurs et aux participants.",
"Enable notifications for events via push" : "Activer les notifications push pour les évènements",
+ "Example content" : "Exemple de contenu",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Les exemples de contenu servent à présenter les fonctionnalités de Nextcloud. Le contenu par défaut est fourni avec Nextcloud et peut être remplacé par du contenu personnalisé.",
"There was an error updating your attendance status." : "Une erreur s'est produite lors de la mise à jour de votre statut de présence.",
"Please contact the organizer directly." : "Merci de contacter l'organisateur directement.",
"Are you accepting the invitation?" : "Acceptez-vous l'invitation ?",
diff --git a/apps/dav/l10n/ga.js b/apps/dav/l10n/ga.js
index f32f66ac342..fe197df1bd8 100644
--- a/apps/dav/l10n/ga.js
+++ b/apps/dav/l10n/ga.js
@@ -301,6 +301,14 @@ OC.L10N.register(
"Reset to default" : "Athshocraigh go réamhshocrú",
"Import contacts" : "Teagmhálaithe a allmhairiú",
"Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Má dhéantar comhad .vcf nua a iompórtáil, scriosfar an teagmhálaí réamhshocraithe atá ann cheana féin agus cuirfear an ceann nua ina ionad. Ar mhaith leat leanúint ar aghaidh?",
+ "Failed to save example event creation setting" : "Theip ar shocrú cruthaithe imeachta samplach a shábháil",
+ "Failed to upload the example event" : "Theip ar an imeacht samplach a uaslódáil",
+ "Custom example event was saved successfully" : "Sábháladh imeacht samplach saincheaptha go rathúil",
+ "Failed to delete the custom example event" : "Theip ar an imeacht samplach saincheaptha a scriosadh",
+ "Custom example event was deleted successfully" : "Scriosadh imeacht samplach saincheaptha go rathúil",
+ "Import calendar event" : "Imeacht féilire a allmhairiú",
+ "Uploading a new event will overwrite the existing one." : "Scríobhfar an ceann atá ann cheana má uaslódálann tú imeacht nua.",
+ "Upload event" : "Uaslódáil imeacht",
"Availability" : "Infhaighteacht",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Má dhéanann tú do chuid uaireanta oibre a chumrú, feicfidh daoine eile nuair a bhíonn tú as oifig nuair a chuireann siad cruinniú in áirithe.",
"Absence" : "Neamhláithreacht",
@@ -317,6 +325,8 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Seol fógraí meabhrúcháin chuig scaireanna féilire freisin",
"Reminders are always sent to organizers and attendees." : "Seoltar meabhrúcháin chuig na heagraithe agus an lucht freastail i gcónaí.",
"Enable notifications for events via push" : "Cumasaigh fógraí le haghaidh imeachtaí trí bhrú",
+ "Example content" : "Ábhar samplach",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Feidhmíonn ábhar samplach chun gnéithe Nextcloud a thaispeáint. Seoltar ábhar réamhshocraithe le Nextcloud, agus is féidir ábhar saincheaptha a chur ina áit.",
"There was an error updating your attendance status." : "Tharla earráid agus do stádas freastail á nuashonrú.",
"Please contact the organizer directly." : "Téigh i dteagmháil leis an eagraí go díreach le do thoil.",
"Are you accepting the invitation?" : "An bhfuil tú ag glacadh leis an gcuireadh?",
diff --git a/apps/dav/l10n/ga.json b/apps/dav/l10n/ga.json
index 29e76c0052f..cde6b45cf5f 100644
--- a/apps/dav/l10n/ga.json
+++ b/apps/dav/l10n/ga.json
@@ -299,6 +299,14 @@
"Reset to default" : "Athshocraigh go réamhshocrú",
"Import contacts" : "Teagmhálaithe a allmhairiú",
"Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Má dhéantar comhad .vcf nua a iompórtáil, scriosfar an teagmhálaí réamhshocraithe atá ann cheana féin agus cuirfear an ceann nua ina ionad. Ar mhaith leat leanúint ar aghaidh?",
+ "Failed to save example event creation setting" : "Theip ar shocrú cruthaithe imeachta samplach a shábháil",
+ "Failed to upload the example event" : "Theip ar an imeacht samplach a uaslódáil",
+ "Custom example event was saved successfully" : "Sábháladh imeacht samplach saincheaptha go rathúil",
+ "Failed to delete the custom example event" : "Theip ar an imeacht samplach saincheaptha a scriosadh",
+ "Custom example event was deleted successfully" : "Scriosadh imeacht samplach saincheaptha go rathúil",
+ "Import calendar event" : "Imeacht féilire a allmhairiú",
+ "Uploading a new event will overwrite the existing one." : "Scríobhfar an ceann atá ann cheana má uaslódálann tú imeacht nua.",
+ "Upload event" : "Uaslódáil imeacht",
"Availability" : "Infhaighteacht",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Má dhéanann tú do chuid uaireanta oibre a chumrú, feicfidh daoine eile nuair a bhíonn tú as oifig nuair a chuireann siad cruinniú in áirithe.",
"Absence" : "Neamhláithreacht",
@@ -315,6 +323,8 @@
"Send reminder notifications to calendar sharees as well" : "Seol fógraí meabhrúcháin chuig scaireanna féilire freisin",
"Reminders are always sent to organizers and attendees." : "Seoltar meabhrúcháin chuig na heagraithe agus an lucht freastail i gcónaí.",
"Enable notifications for events via push" : "Cumasaigh fógraí le haghaidh imeachtaí trí bhrú",
+ "Example content" : "Ábhar samplach",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Feidhmíonn ábhar samplach chun gnéithe Nextcloud a thaispeáint. Seoltar ábhar réamhshocraithe le Nextcloud, agus is féidir ábhar saincheaptha a chur ina áit.",
"There was an error updating your attendance status." : "Tharla earráid agus do stádas freastail á nuashonrú.",
"Please contact the organizer directly." : "Téigh i dteagmháil leis an eagraí go díreach le do thoil.",
"Are you accepting the invitation?" : "An bhfuil tú ag glacadh leis an gcuireadh?",
diff --git a/apps/dav/l10n/pl.js b/apps/dav/l10n/pl.js
index 48b5b484903..01688c638bd 100644
--- a/apps/dav/l10n/pl.js
+++ b/apps/dav/l10n/pl.js
@@ -178,6 +178,9 @@ OC.L10N.register(
"Completed on %s" : "Ukończono %s",
"Due on %s by %s" : "Na dzień %s w %s",
"Due on %s" : "Na dzień %s",
+ "System Address Book" : "Systemowa książka adresowa",
+ "The system address book contains contact information for all users in your instance." : "Systemowa książka adresowa zawiera informacje kontaktowe wszystkich użytkowników w Twojej instancji",
+ "Enable System Address Book" : "Włącz systemową książkę adresową",
"DAV system address book" : "Książka adresowa systemu DAV",
"No outstanding DAV system address book sync." : "Brak zaległej synchronizacji książki adresowej systemu DAV.",
"The DAV system address book sync has not run yet as your instance has more than 1000 users or because an error occurred. Please run it manually by calling \"occ dav:sync-system-addressbook\"." : "Synchronizacja książki adresowej systemu DAV nie została jeszcze uruchomiona, ponieważ Twoja instancja ma ponad 1000 użytkowników lub wystąpił błąd. Uruchom go ręcznie, wywołując \"occ dav:sync-system-addressbook\".",
@@ -218,7 +221,22 @@ OC.L10N.register(
"Cancel" : "Anuluj",
"Import" : "Importuj",
"Error while saving settings" : "Błąd podczas zapisywania ustawień",
+ "Contact reset successfully" : "Kontakt został pomyślnie zresetowany",
+ "Error while resetting contact" : "Błąd podczas resetowania kontaktu",
+ "Contact imported successfully" : "Kontakt został pomyślnie zaimportowany",
+ "Error while importing contact" : "Błąd podczas importowania kontaktu",
+ "Import contact" : "Importuj kontakt",
"Reset to default" : "Przywróć domyślne",
+ "Import contacts" : "Importuj kontakty",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Importowanie nowego pliku .vcf usunie domyślny kontakt i zastąpi go nowym. Czy chcesz kontynuować?",
+ "Failed to save example event creation setting" : "Nie udało się zapisać ustawień tworzenia przykładowego wydarzenia",
+ "Failed to upload the example event" : "Nie udało się przesłać przykładowego wydarzenia",
+ "Custom example event was saved successfully" : "Niestandardowe przykładowe wydarzenie zostało pomyślnie zapisane",
+ "Failed to delete the custom example event" : "Nie udało się usunąć niestandardowego przykładowego wydarzenia",
+ "Custom example event was deleted successfully" : "Niestandardowe przykładowe wydarzenie zostało pomyślnie usunięte",
+ "Import calendar event" : "Importuj wydarzenie z kalendarza",
+ "Uploading a new event will overwrite the existing one." : "Przesłanie nowego wydarzenia zastąpi istniejące",
+ "Upload event" : "Prześlij wydarzenie",
"Availability" : "Dostępność",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Jeśli skonfigurujesz godziny pracy, inne osoby będą widzieć, kiedy jesteś poza biurem, rezerwując spotkanie.",
"Absence" : "Nieobecność",
@@ -235,6 +253,8 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Wysyłaj przypomnienia również do udostępnionych kalendarzy",
"Reminders are always sent to organizers and attendees." : "Przypomnienia są zawsze wysyłane do organizatorów i uczestników.",
"Enable notifications for events via push" : "Włącz powiadomienia o zdarzeniach poprzez Push",
+ "Example content" : "Przykładowa zawartość",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Przykładowa zawartość służy do prezentacji funkcji Nextcloud. Domyślna zawartość jest dostarczana z Nextcloud i może zostać zastąpiona zawartością niestandardową",
"There was an error updating your attendance status." : "Wystąpił błąd zmiany stanu uczestnictwa",
"Please contact the organizer directly." : "Skontaktuj się bezpośrednio z orgnizatorem.",
"Are you accepting the invitation?" : "Czy akceptujesz zaproszenie?",
diff --git a/apps/dav/l10n/pl.json b/apps/dav/l10n/pl.json
index 0404cf1538c..448986178a8 100644
--- a/apps/dav/l10n/pl.json
+++ b/apps/dav/l10n/pl.json
@@ -176,6 +176,9 @@
"Completed on %s" : "Ukończono %s",
"Due on %s by %s" : "Na dzień %s w %s",
"Due on %s" : "Na dzień %s",
+ "System Address Book" : "Systemowa książka adresowa",
+ "The system address book contains contact information for all users in your instance." : "Systemowa książka adresowa zawiera informacje kontaktowe wszystkich użytkowników w Twojej instancji",
+ "Enable System Address Book" : "Włącz systemową książkę adresową",
"DAV system address book" : "Książka adresowa systemu DAV",
"No outstanding DAV system address book sync." : "Brak zaległej synchronizacji książki adresowej systemu DAV.",
"The DAV system address book sync has not run yet as your instance has more than 1000 users or because an error occurred. Please run it manually by calling \"occ dav:sync-system-addressbook\"." : "Synchronizacja książki adresowej systemu DAV nie została jeszcze uruchomiona, ponieważ Twoja instancja ma ponad 1000 użytkowników lub wystąpił błąd. Uruchom go ręcznie, wywołując \"occ dav:sync-system-addressbook\".",
@@ -216,7 +219,22 @@
"Cancel" : "Anuluj",
"Import" : "Importuj",
"Error while saving settings" : "Błąd podczas zapisywania ustawień",
+ "Contact reset successfully" : "Kontakt został pomyślnie zresetowany",
+ "Error while resetting contact" : "Błąd podczas resetowania kontaktu",
+ "Contact imported successfully" : "Kontakt został pomyślnie zaimportowany",
+ "Error while importing contact" : "Błąd podczas importowania kontaktu",
+ "Import contact" : "Importuj kontakt",
"Reset to default" : "Przywróć domyślne",
+ "Import contacts" : "Importuj kontakty",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Importowanie nowego pliku .vcf usunie domyślny kontakt i zastąpi go nowym. Czy chcesz kontynuować?",
+ "Failed to save example event creation setting" : "Nie udało się zapisać ustawień tworzenia przykładowego wydarzenia",
+ "Failed to upload the example event" : "Nie udało się przesłać przykładowego wydarzenia",
+ "Custom example event was saved successfully" : "Niestandardowe przykładowe wydarzenie zostało pomyślnie zapisane",
+ "Failed to delete the custom example event" : "Nie udało się usunąć niestandardowego przykładowego wydarzenia",
+ "Custom example event was deleted successfully" : "Niestandardowe przykładowe wydarzenie zostało pomyślnie usunięte",
+ "Import calendar event" : "Importuj wydarzenie z kalendarza",
+ "Uploading a new event will overwrite the existing one." : "Przesłanie nowego wydarzenia zastąpi istniejące",
+ "Upload event" : "Prześlij wydarzenie",
"Availability" : "Dostępność",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Jeśli skonfigurujesz godziny pracy, inne osoby będą widzieć, kiedy jesteś poza biurem, rezerwując spotkanie.",
"Absence" : "Nieobecność",
@@ -233,6 +251,8 @@
"Send reminder notifications to calendar sharees as well" : "Wysyłaj przypomnienia również do udostępnionych kalendarzy",
"Reminders are always sent to organizers and attendees." : "Przypomnienia są zawsze wysyłane do organizatorów i uczestników.",
"Enable notifications for events via push" : "Włącz powiadomienia o zdarzeniach poprzez Push",
+ "Example content" : "Przykładowa zawartość",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Przykładowa zawartość służy do prezentacji funkcji Nextcloud. Domyślna zawartość jest dostarczana z Nextcloud i może zostać zastąpiona zawartością niestandardową",
"There was an error updating your attendance status." : "Wystąpił błąd zmiany stanu uczestnictwa",
"Please contact the organizer directly." : "Skontaktuj się bezpośrednio z orgnizatorem.",
"Are you accepting the invitation?" : "Czy akceptujesz zaproszenie?",
diff --git a/apps/dav/l10n/zh_CN.js b/apps/dav/l10n/zh_CN.js
index 2a3470f738a..e181553ce39 100644
--- a/apps/dav/l10n/zh_CN.js
+++ b/apps/dav/l10n/zh_CN.js
@@ -156,7 +156,7 @@ OC.L10N.register(
"Invitation: %1$s" : "邀请:%1$s",
"%1$s would like to invite you to \"%2$s\"" : "%1$s 想邀请您加入“%2$s”",
"Organizer:" : "组织者:",
- "Attendees:" : "与会者:",
+ "Attendees:" : "参加者:",
"Title:" : "标题:",
"When:" : "时间:",
"Location:" : "地区:",
@@ -261,7 +261,7 @@ OC.L10N.register(
"Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "您的网页服务器没有正确设置允许文件同步,因为 WebDAV 接口看起来无法正常工作。",
"Your web server is properly set up to allow file synchronization over WebDAV." : "您的 Web 服务器已正确设置为允许通过 WebDAV 进行文件同步。",
"Migrated calendar (%1$s)" : "迁移的日历(%1$s)",
- "Calendars including events, details and attendees" : "日历包含活动、参与人和事件详情",
+ "Calendars including events, details and attendees" : "日历,包括事件、详情和参加者",
"Contacts and groups" : "联系人和群组",
"WebDAV" : "WebDAV",
"Absence saved" : "缺席已保存",
@@ -301,6 +301,14 @@ OC.L10N.register(
"Reset to default" : "重置为默认设置",
"Import contacts" : "导入联系人",
"Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "导入新的 .vcf 文件将删除现有的默认联系人,并用新联系人替换。是否要继续?",
+ "Failed to save example event creation setting" : "无法保存示例事件创建设置",
+ "Failed to upload the example event" : "无法上传示例事件",
+ "Custom example event was saved successfully" : "已成功保存自定义示例事件",
+ "Failed to delete the custom example event" : "无法删除自定义示例事件",
+ "Custom example event was deleted successfully" : "已成功删除自定义示例事件",
+ "Import calendar event" : "导入日历事件",
+ "Uploading a new event will overwrite the existing one." : "上传新事件将覆盖现有事件。",
+ "Upload event" : "上传事件",
"Availability" : "工作时间",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "如果你配置了工作时间,其他人在预订会议时会看到你何时不在办公室。",
"Absence" : "离开",
@@ -308,15 +316,17 @@ OC.L10N.register(
"Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "也安装{calendarappstoreopen}日历应用{linkclose},或者{calendardocopen}连接您的桌面和移动端同步日历 ↗{linkclose}。",
"Please make sure to properly set up {emailopen}the email server{linkclose}." : "请确保正确设置{emailopen}邮件服务器{linkclose}。",
"Calendar server" : "日历服务器",
- "Send invitations to attendees" : "向与会者发送邀请",
+ "Send invitations to attendees" : "向参加者发送邀请",
"Automatically generate a birthday calendar" : "自动生成生日日历",
"Birthday calendars will be generated by a background job." : "生日日历将由后台作业生成。",
"Hence they will not be available immediately after enabling but will show up after some time." : "因此,它们在启用后不会立即可用,但会在一段时间后显示出来。",
"Send notifications for events" : "发送事件通知",
"Notifications are sent via background jobs, so these must occur often enough." : "通知将通过后台任务发送,所以任务的频率要足够高。",
"Send reminder notifications to calendar sharees as well" : "同时向日历共享者发送提醒通知",
- "Reminders are always sent to organizers and attendees." : "始终向组织者和与会者发出提醒。",
+ "Reminders are always sent to organizers and attendees." : "始终向组织者和参加者发送提醒。",
"Enable notifications for events via push" : "启用推送事件通知",
+ "Example content" : "示例内容",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "示例内容用于展示 Nextcloud 的功能。默认内容随 Nextcloud 一起提供,可以用自定义内容替换。",
"There was an error updating your attendance status." : "更新您的出席状态时出错。",
"Please contact the organizer directly." : "请直接联系组织者。",
"Are you accepting the invitation?" : "您是否接受邀请?",
diff --git a/apps/dav/l10n/zh_CN.json b/apps/dav/l10n/zh_CN.json
index 1c240fa7585..8e3986f615c 100644
--- a/apps/dav/l10n/zh_CN.json
+++ b/apps/dav/l10n/zh_CN.json
@@ -154,7 +154,7 @@
"Invitation: %1$s" : "邀请:%1$s",
"%1$s would like to invite you to \"%2$s\"" : "%1$s 想邀请您加入“%2$s”",
"Organizer:" : "组织者:",
- "Attendees:" : "与会者:",
+ "Attendees:" : "参加者:",
"Title:" : "标题:",
"When:" : "时间:",
"Location:" : "地区:",
@@ -259,7 +259,7 @@
"Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "您的网页服务器没有正确设置允许文件同步,因为 WebDAV 接口看起来无法正常工作。",
"Your web server is properly set up to allow file synchronization over WebDAV." : "您的 Web 服务器已正确设置为允许通过 WebDAV 进行文件同步。",
"Migrated calendar (%1$s)" : "迁移的日历(%1$s)",
- "Calendars including events, details and attendees" : "日历包含活动、参与人和事件详情",
+ "Calendars including events, details and attendees" : "日历,包括事件、详情和参加者",
"Contacts and groups" : "联系人和群组",
"WebDAV" : "WebDAV",
"Absence saved" : "缺席已保存",
@@ -299,6 +299,14 @@
"Reset to default" : "重置为默认设置",
"Import contacts" : "导入联系人",
"Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "导入新的 .vcf 文件将删除现有的默认联系人,并用新联系人替换。是否要继续?",
+ "Failed to save example event creation setting" : "无法保存示例事件创建设置",
+ "Failed to upload the example event" : "无法上传示例事件",
+ "Custom example event was saved successfully" : "已成功保存自定义示例事件",
+ "Failed to delete the custom example event" : "无法删除自定义示例事件",
+ "Custom example event was deleted successfully" : "已成功删除自定义示例事件",
+ "Import calendar event" : "导入日历事件",
+ "Uploading a new event will overwrite the existing one." : "上传新事件将覆盖现有事件。",
+ "Upload event" : "上传事件",
"Availability" : "工作时间",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "如果你配置了工作时间,其他人在预订会议时会看到你何时不在办公室。",
"Absence" : "离开",
@@ -306,15 +314,17 @@
"Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "也安装{calendarappstoreopen}日历应用{linkclose},或者{calendardocopen}连接您的桌面和移动端同步日历 ↗{linkclose}。",
"Please make sure to properly set up {emailopen}the email server{linkclose}." : "请确保正确设置{emailopen}邮件服务器{linkclose}。",
"Calendar server" : "日历服务器",
- "Send invitations to attendees" : "向与会者发送邀请",
+ "Send invitations to attendees" : "向参加者发送邀请",
"Automatically generate a birthday calendar" : "自动生成生日日历",
"Birthday calendars will be generated by a background job." : "生日日历将由后台作业生成。",
"Hence they will not be available immediately after enabling but will show up after some time." : "因此,它们在启用后不会立即可用,但会在一段时间后显示出来。",
"Send notifications for events" : "发送事件通知",
"Notifications are sent via background jobs, so these must occur often enough." : "通知将通过后台任务发送,所以任务的频率要足够高。",
"Send reminder notifications to calendar sharees as well" : "同时向日历共享者发送提醒通知",
- "Reminders are always sent to organizers and attendees." : "始终向组织者和与会者发出提醒。",
+ "Reminders are always sent to organizers and attendees." : "始终向组织者和参加者发送提醒。",
"Enable notifications for events via push" : "启用推送事件通知",
+ "Example content" : "示例内容",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "示例内容用于展示 Nextcloud 的功能。默认内容随 Nextcloud 一起提供,可以用自定义内容替换。",
"There was an error updating your attendance status." : "更新您的出席状态时出错。",
"Please contact the organizer directly." : "请直接联系组织者。",
"Are you accepting the invitation?" : "您是否接受邀请?",
diff --git a/apps/dav/l10n/zh_HK.js b/apps/dav/l10n/zh_HK.js
index a90bea5c954..df201c06f90 100644
--- a/apps/dav/l10n/zh_HK.js
+++ b/apps/dav/l10n/zh_HK.js
@@ -301,6 +301,14 @@ OC.L10N.register(
"Reset to default" : "恢復預設值",
"Import contacts" : "導入聯絡人",
"Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "導入新的 .vcf 檔案將刪除現有的默認聯絡人並將其替換為新的聯絡人。您想繼續嗎?",
+ "Failed to save example event creation setting" : "儲存範例事件建立設定失敗",
+ "Failed to upload the example event" : "上傳範例事件失敗",
+ "Custom example event was saved successfully" : "已成功儲存自訂範例事件",
+ "Failed to delete the custom example event" : "刪除自訂範例事件失敗",
+ "Custom example event was deleted successfully" : "已成功刪除自訂範例事件",
+ "Import calendar event" : "導入日曆活動",
+ "Uploading a new event will overwrite the existing one." : "上傳新活動將會覆寫原有的",
+ "Upload event" : "上傳活動",
"Availability" : "空閒時間",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "若您設定了您的工作時間,其他人仕在預約會議時就會知道您何時不在辦公室。",
"Absence" : "缺席",
@@ -317,6 +325,8 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "也向共享日曆者傳送提醒通告",
"Reminders are always sent to organizers and attendees." : "一律傳送提醒通知給舉辦者與參與者。",
"Enable notifications for events via push" : "啟用推送活動通知",
+ "Example content" : "範例內容",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "範例內容用來展示 Nextcloud 的功能。Nextcloud 隨附預設內容,可由自訂內容取代。",
"There was an error updating your attendance status." : "更新您的參與狀況時發生錯誤",
"Please contact the organizer directly." : "請直接聯繫絡主辦人",
"Are you accepting the invitation?" : "接受邀請嗎?",
diff --git a/apps/dav/l10n/zh_HK.json b/apps/dav/l10n/zh_HK.json
index 13f69901a7a..0cafd6ec077 100644
--- a/apps/dav/l10n/zh_HK.json
+++ b/apps/dav/l10n/zh_HK.json
@@ -299,6 +299,14 @@
"Reset to default" : "恢復預設值",
"Import contacts" : "導入聯絡人",
"Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "導入新的 .vcf 檔案將刪除現有的默認聯絡人並將其替換為新的聯絡人。您想繼續嗎?",
+ "Failed to save example event creation setting" : "儲存範例事件建立設定失敗",
+ "Failed to upload the example event" : "上傳範例事件失敗",
+ "Custom example event was saved successfully" : "已成功儲存自訂範例事件",
+ "Failed to delete the custom example event" : "刪除自訂範例事件失敗",
+ "Custom example event was deleted successfully" : "已成功刪除自訂範例事件",
+ "Import calendar event" : "導入日曆活動",
+ "Uploading a new event will overwrite the existing one." : "上傳新活動將會覆寫原有的",
+ "Upload event" : "上傳活動",
"Availability" : "空閒時間",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "若您設定了您的工作時間,其他人仕在預約會議時就會知道您何時不在辦公室。",
"Absence" : "缺席",
@@ -315,6 +323,8 @@
"Send reminder notifications to calendar sharees as well" : "也向共享日曆者傳送提醒通告",
"Reminders are always sent to organizers and attendees." : "一律傳送提醒通知給舉辦者與參與者。",
"Enable notifications for events via push" : "啟用推送活動通知",
+ "Example content" : "範例內容",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "範例內容用來展示 Nextcloud 的功能。Nextcloud 隨附預設內容,可由自訂內容取代。",
"There was an error updating your attendance status." : "更新您的參與狀況時發生錯誤",
"Please contact the organizer directly." : "請直接聯繫絡主辦人",
"Are you accepting the invitation?" : "接受邀請嗎?",
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php
index c49e843d2b9..1cbf2a1e4eb 100644
--- a/apps/dav/lib/CalDAV/CalDavBackend.php
+++ b/apps/dav/lib/CalDAV/CalDavBackend.php
@@ -2986,7 +2986,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'calendarid' => $query->createNamedParameter($calendarId),
'operation' => $query->createNamedParameter($operation),
'calendartype' => $query->createNamedParameter($calendarType),
- 'created_at' => time(),
+ 'created_at' => $query->createNamedParameter(time()),
]);
foreach ($objectUris as $uri) {
$query->setParameter('uri', $uri);
diff --git a/apps/dav/lib/Controller/ExampleContentController.php b/apps/dav/lib/Controller/ExampleContentController.php
index 905fd392e6c..e20ee4b7f49 100644
--- a/apps/dav/lib/Controller/ExampleContentController.php
+++ b/apps/dav/lib/Controller/ExampleContentController.php
@@ -10,6 +10,7 @@ declare(strict_types=1);
namespace OCA\DAV\Controller;
use OCA\DAV\AppInfo\Application;
+use OCA\DAV\Service\ExampleContactService;
use OCA\DAV\Service\ExampleEventService;
use OCP\AppFramework\ApiController;
use OCP\AppFramework\Http;
@@ -17,103 +18,50 @@ use OCP\AppFramework\Http\Attribute\FrontpageRoute;
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
use OCP\AppFramework\Http\DataDownloadResponse;
use OCP\AppFramework\Http\JSONResponse;
-use OCP\Files\AppData\IAppDataFactory;
-use OCP\Files\IAppData;
-use OCP\Files\NotFoundException;
-use OCP\IAppConfig;
-use OCP\IConfig;
use OCP\IRequest;
use Psr\Log\LoggerInterface;
class ExampleContentController extends ApiController {
- private IAppData $appData;
-
public function __construct(
IRequest $request,
- private IConfig $config,
- private IAppConfig $appConfig,
- private IAppDataFactory $appDataFactory,
- private LoggerInterface $logger,
- private ExampleEventService $exampleEventService,
+ private readonly LoggerInterface $logger,
+ private readonly ExampleEventService $exampleEventService,
+ private readonly ExampleContactService $exampleContactService,
) {
parent::__construct(Application::APP_ID, $request);
- $this->appData = $this->appDataFactory->get('dav');
}
- public function setEnableDefaultContact($allow) {
- if ($allow === 'yes' && !$this->defaultContactExists()) {
+ #[FrontpageRoute(verb: 'PUT', url: '/api/defaultcontact/config')]
+ public function setEnableDefaultContact(bool $allow): JSONResponse {
+ if ($allow && !$this->exampleContactService->defaultContactExists()) {
try {
- $this->setCard();
+ $this->exampleContactService->setCard();
} catch (\Exception $e) {
$this->logger->error('Could not create default contact', ['exception' => $e]);
return new JSONResponse([], Http::STATUS_INTERNAL_SERVER_ERROR);
}
}
- $this->config->setAppValue(Application::APP_ID, 'enableDefaultContact', $allow);
+ $this->exampleContactService->setDefaultContactEnabled($allow);
return new JSONResponse([], Http::STATUS_OK);
}
#[NoCSRFRequired]
+ #[FrontpageRoute(verb: 'GET', url: '/api/defaultcontact/contact')]
public function getDefaultContact(): DataDownloadResponse {
- $cardData = $this->getCard()
+ $cardData = $this->exampleContactService->getCard()
?? file_get_contents(__DIR__ . '/../ExampleContentFiles/exampleContact.vcf');
return new DataDownloadResponse($cardData, 'example_contact.vcf', 'text/vcard');
}
+ #[FrontpageRoute(verb: 'PUT', url: '/api/defaultcontact/contact')]
public function setDefaultContact(?string $contactData = null) {
- if (!$this->config->getAppValue(Application::APP_ID, 'enableDefaultContact', 'yes')) {
+ if (!$this->exampleContactService->isDefaultContactEnabled()) {
return new JSONResponse([], Http::STATUS_FORBIDDEN);
}
- $this->setCard($contactData);
+ $this->exampleContactService->setCard($contactData);
return new JSONResponse([], Http::STATUS_OK);
}
- private function getCard(): ?string {
- try {
- $folder = $this->appData->getFolder('defaultContact');
- } catch (NotFoundException $e) {
- return null;
- }
-
- if (!$folder->fileExists('defaultContact.vcf')) {
- return null;
- }
-
- return $folder->getFile('defaultContact.vcf')->getContent();
- }
-
- private function setCard(?string $cardData = null) {
- try {
- $folder = $this->appData->getFolder('defaultContact');
- } catch (NotFoundException $e) {
- $folder = $this->appData->newFolder('defaultContact');
- }
-
- $isCustom = true;
- if (is_null($cardData)) {
- $cardData = file_get_contents(__DIR__ . '/../ExampleContentFiles/exampleContact.vcf');
- $isCustom = false;
- }
-
- if (!$cardData) {
- throw new \Exception('Could not read exampleContact.vcf');
- }
-
- $file = (!$folder->fileExists('defaultContact.vcf')) ? $folder->newFile('defaultContact.vcf') : $folder->getFile('defaultContact.vcf');
- $file->putContent($cardData);
-
- $this->appConfig->setValueBool(Application::APP_ID, 'hasCustomDefaultContact', $isCustom);
- }
-
- private function defaultContactExists(): bool {
- try {
- $folder = $this->appData->getFolder('defaultContact');
- } catch (NotFoundException $e) {
- return false;
- }
- return $folder->fileExists('defaultContact.vcf');
- }
-
#[FrontpageRoute(verb: 'POST', url: '/api/exampleEvent/enable')]
public function setCreateExampleEvent(bool $enable): JSONResponse {
$this->exampleEventService->setCreateExampleEvent($enable);
diff --git a/apps/dav/lib/Listener/UserEventsListener.php b/apps/dav/lib/Listener/UserEventsListener.php
index 67cf228515a..c876192d67f 100644
--- a/apps/dav/lib/Listener/UserEventsListener.php
+++ b/apps/dav/lib/Listener/UserEventsListener.php
@@ -12,7 +12,7 @@ namespace OCA\DAV\Listener;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CardDAV\CardDavBackend;
use OCA\DAV\CardDAV\SyncService;
-use OCA\DAV\Service\DefaultContactService;
+use OCA\DAV\Service\ExampleContactService;
use OCA\DAV\Service\ExampleEventService;
use OCP\Accounts\UserUpdatedEvent;
use OCP\Defaults;
@@ -46,7 +46,7 @@ class UserEventsListener implements IEventListener {
private CalDavBackend $calDav,
private CardDavBackend $cardDav,
private Defaults $themingDefaults,
- private DefaultContactService $defaultContactService,
+ private ExampleContactService $exampleContactService,
private ExampleEventService $exampleEventService,
private LoggerInterface $logger,
) {
@@ -175,7 +175,7 @@ class UserEventsListener implements IEventListener {
}
}
if ($addressBookId) {
- $this->defaultContactService->createDefaultContact($addressBookId);
+ $this->exampleContactService->createDefaultContact($addressBookId);
}
}
}
diff --git a/apps/dav/lib/Service/DefaultContactService.php b/apps/dav/lib/Service/DefaultContactService.php
deleted file mode 100644
index 24e55ef7b69..00000000000
--- a/apps/dav/lib/Service/DefaultContactService.php
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-namespace OCA\DAV\Service;
-
-use OCA\DAV\AppInfo\Application;
-use OCA\DAV\CardDAV\CardDavBackend;
-use OCP\App\IAppManager;
-use OCP\Files\AppData\IAppDataFactory;
-use OCP\IAppConfig;
-use Psr\Log\LoggerInterface;
-use Symfony\Component\Uid\Uuid;
-
-class DefaultContactService {
- public function __construct(
- private CardDavBackend $cardDav,
- private IAppManager $appManager,
- private IAppDataFactory $appDataFactory,
- private IAppConfig $config,
- private LoggerInterface $logger,
- ) {
- }
-
- public function createDefaultContact(int $addressBookId): void {
- $enableDefaultContact = $this->config->getValueString(Application::APP_ID, 'enableDefaultContact', 'yes');
- if ($enableDefaultContact !== 'yes') {
- return;
- }
- $appData = $this->appDataFactory->get('dav');
- try {
- $folder = $appData->getFolder('defaultContact');
- $defaultContactFile = $folder->getFile('defaultContact.vcf');
- $data = $defaultContactFile->getContent();
- } catch (\Exception $e) {
- $this->logger->error('Couldn\'t get default contact file', ['exception' => $e]);
- return;
- }
-
- // Make sure the UID is unique
- $newUid = Uuid::v4()->toRfc4122();
- $newRev = date('Ymd\THis\Z');
- $vcard = \Sabre\VObject\Reader::read($data, \Sabre\VObject\Reader::OPTION_FORGIVING);
- if ($vcard->UID) {
- $vcard->UID->setValue($newUid);
- } else {
- $vcard->add('UID', $newUid);
- }
- if ($vcard->REV) {
- $vcard->REV->setValue($newRev);
- } else {
- $vcard->add('REV', $newRev);
- }
-
- // Level 3 means that the document is invalid
- // https://sabre.io/vobject/vcard/#validating-vcard
- $level3Warnings = array_filter($vcard->validate(), function ($warning) {
- return $warning['level'] === 3;
- });
-
- if (!empty($level3Warnings)) {
- $this->logger->error('Default contact is invalid', ['warnings' => $level3Warnings]);
- return;
- }
- try {
- $this->cardDav->createCard($addressBookId, 'default', $vcard->serialize(), false);
- } catch (\Exception $e) {
- $this->logger->error($e->getMessage(), ['exception' => $e]);
- }
-
- }
-}
diff --git a/apps/dav/lib/Service/ExampleContactService.php b/apps/dav/lib/Service/ExampleContactService.php
new file mode 100644
index 00000000000..6ed6c66cbb3
--- /dev/null
+++ b/apps/dav/lib/Service/ExampleContactService.php
@@ -0,0 +1,132 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Service;
+
+use OCA\DAV\AppInfo\Application;
+use OCA\DAV\CardDAV\CardDavBackend;
+use OCP\AppFramework\Services\IAppConfig;
+use OCP\Files\AppData\IAppDataFactory;
+use OCP\Files\IAppData;
+use OCP\Files\NotFoundException;
+use Psr\Log\LoggerInterface;
+use Symfony\Component\Uid\Uuid;
+
+class ExampleContactService {
+ private readonly IAppData $appData;
+
+ public function __construct(
+ IAppDataFactory $appDataFactory,
+ private readonly IAppConfig $appConfig,
+ private readonly LoggerInterface $logger,
+ private readonly CardDavBackend $cardDav,
+ ) {
+ $this->appData = $appDataFactory->get(Application::APP_ID);
+ }
+
+ public function isDefaultContactEnabled(): bool {
+ return $this->appConfig->getAppValueBool('enableDefaultContact', true);
+ }
+
+ public function setDefaultContactEnabled(bool $value): void {
+ $this->appConfig->setAppValueBool('enableDefaultContact', $value);
+ }
+
+ public function getCard(): ?string {
+ try {
+ $folder = $this->appData->getFolder('defaultContact');
+ } catch (NotFoundException $e) {
+ return null;
+ }
+
+ if (!$folder->fileExists('defaultContact.vcf')) {
+ return null;
+ }
+
+ return $folder->getFile('defaultContact.vcf')->getContent();
+ }
+
+ public function setCard(?string $cardData = null) {
+ try {
+ $folder = $this->appData->getFolder('defaultContact');
+ } catch (NotFoundException $e) {
+ $folder = $this->appData->newFolder('defaultContact');
+ }
+
+ $isCustom = true;
+ if (is_null($cardData)) {
+ $cardData = file_get_contents(__DIR__ . '/../ExampleContentFiles/exampleContact.vcf');
+ $isCustom = false;
+ }
+
+ if (!$cardData) {
+ throw new \Exception('Could not read exampleContact.vcf');
+ }
+
+ $file = (!$folder->fileExists('defaultContact.vcf')) ? $folder->newFile('defaultContact.vcf') : $folder->getFile('defaultContact.vcf');
+ $file->putContent($cardData);
+
+ $this->appConfig->setAppValueBool('hasCustomDefaultContact', $isCustom);
+ }
+
+ public function defaultContactExists(): bool {
+ try {
+ $folder = $this->appData->getFolder('defaultContact');
+ } catch (NotFoundException $e) {
+ return false;
+ }
+ return $folder->fileExists('defaultContact.vcf');
+ }
+
+ public function createDefaultContact(int $addressBookId): void {
+ if (!$this->isDefaultContactEnabled()) {
+ return;
+ }
+
+ try {
+ $folder = $this->appData->getFolder('defaultContact');
+ $defaultContactFile = $folder->getFile('defaultContact.vcf');
+ $data = $defaultContactFile->getContent();
+ } catch (\Exception $e) {
+ $this->logger->error('Couldn\'t get default contact file', ['exception' => $e]);
+ return;
+ }
+
+ // Make sure the UID is unique
+ $newUid = Uuid::v4()->toRfc4122();
+ $newRev = date('Ymd\THis\Z');
+ $vcard = \Sabre\VObject\Reader::read($data, \Sabre\VObject\Reader::OPTION_FORGIVING);
+ if ($vcard->UID) {
+ $vcard->UID->setValue($newUid);
+ } else {
+ $vcard->add('UID', $newUid);
+ }
+ if ($vcard->REV) {
+ $vcard->REV->setValue($newRev);
+ } else {
+ $vcard->add('REV', $newRev);
+ }
+
+ // Level 3 means that the document is invalid
+ // https://sabre.io/vobject/vcard/#validating-vcard
+ $level3Warnings = array_filter($vcard->validate(), static function ($warning) {
+ return $warning['level'] === 3;
+ });
+
+ if (!empty($level3Warnings)) {
+ $this->logger->error('Default contact is invalid', ['warnings' => $level3Warnings]);
+ return;
+ }
+ try {
+ $this->cardDav->createCard($addressBookId, 'default', $vcard->serialize(), false);
+ } catch (\Exception $e) {
+ $this->logger->error($e->getMessage(), ['exception' => $e]);
+ }
+ }
+}
diff --git a/apps/dav/lib/Settings/ExampleContentSettings.php b/apps/dav/lib/Settings/ExampleContentSettings.php
index fef2d25b8d2..7b6f9b03a3a 100644
--- a/apps/dav/lib/Settings/ExampleContentSettings.php
+++ b/apps/dav/lib/Settings/ExampleContentSettings.php
@@ -9,21 +9,21 @@ declare(strict_types=1);
namespace OCA\DAV\Settings;
use OCA\DAV\AppInfo\Application;
+use OCA\DAV\Service\ExampleContactService;
use OCA\DAV\Service\ExampleEventService;
use OCP\App\IAppManager;
use OCP\AppFramework\Http\TemplateResponse;
+use OCP\AppFramework\Services\IAppConfig;
use OCP\AppFramework\Services\IInitialState;
-use OCP\IAppConfig;
-use OCP\IConfig;
use OCP\Settings\ISettings;
class ExampleContentSettings implements ISettings {
public function __construct(
- private readonly IConfig $config,
private readonly IAppConfig $appConfig,
private readonly IInitialState $initialState,
private readonly IAppManager $appManager,
private readonly ExampleEventService $exampleEventService,
+ private readonly ExampleContactService $exampleContactService,
) {
}
@@ -43,11 +43,13 @@ class ExampleContentSettings implements ISettings {
}
if ($contactsEnabled) {
- $enableDefaultContact = $this->config->getAppValue(Application::APP_ID, 'enableDefaultContact', 'yes');
- $this->initialState->provideInitialState('enableDefaultContact', $enableDefaultContact);
+ $this->initialState->provideInitialState(
+ 'enableDefaultContact',
+ $this->exampleContactService->isDefaultContactEnabled(),
+ );
$this->initialState->provideInitialState(
'hasCustomDefaultContact',
- $this->appConfig->getValueBool(Application::APP_ID, 'hasCustomDefaultContact'),
+ $this->appConfig->getAppValueBool('hasCustomDefaultContact'),
);
}
diff --git a/apps/dav/src/components/ExampleContactSettings.vue b/apps/dav/src/components/ExampleContactSettings.vue
index 0e34c7a12da..cdfdc130189 100644
--- a/apps/dav/src/components/ExampleContactSettings.vue
+++ b/apps/dav/src/components/ExampleContactSettings.vue
@@ -63,7 +63,7 @@ import IconCheck from '@mdi/svg/svg/check.svg?raw'
import logger from '../service/logger.js'
import ExampleContentDownloadButton from './ExampleContentDownloadButton.vue'
-const enableDefaultContact = loadState('dav', 'enableDefaultContact') === 'yes'
+const enableDefaultContact = loadState('dav', 'enableDefaultContact')
const hasCustomDefaultContact = loadState('dav', 'hasCustomDefaultContact')
export default {
@@ -106,7 +106,7 @@ export default {
methods: {
updateEnableDefaultContact() {
axios.put(generateUrl('apps/dav/api/defaultcontact/config'), {
- allow: this.enableDefaultContact ? 'no' : 'yes',
+ allow: !this.enableDefaultContact,
}).then(() => {
this.enableDefaultContact = !this.enableDefaultContact
}).catch(() => {
diff --git a/apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php b/apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php
index f03343af008..40d2fb62431 100644
--- a/apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php
+++ b/apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php
@@ -14,7 +14,7 @@ use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CardDAV\CardDavBackend;
use OCA\DAV\CardDAV\SyncService;
use OCA\DAV\Listener\UserEventsListener;
-use OCA\DAV\Service\DefaultContactService;
+use OCA\DAV\Service\ExampleContactService;
use OCA\DAV\Service\ExampleEventService;
use OCP\Defaults;
use OCP\IUser;
@@ -29,7 +29,7 @@ class UserEventsListenerTest extends TestCase {
private CalDavBackend&MockObject $calDavBackend;
private CardDavBackend&MockObject $cardDavBackend;
private Defaults&MockObject $defaults;
- private DefaultContactService&MockObject $defaultContactService;
+ private ExampleContactService&MockObject $exampleContactService;
private ExampleEventService&MockObject $exampleEventService;
private LoggerInterface&MockObject $logger;
@@ -43,7 +43,7 @@ class UserEventsListenerTest extends TestCase {
$this->calDavBackend = $this->createMock(CalDavBackend::class);
$this->cardDavBackend = $this->createMock(CardDavBackend::class);
$this->defaults = $this->createMock(Defaults::class);
- $this->defaultContactService = $this->createMock(DefaultContactService::class);
+ $this->exampleContactService = $this->createMock(ExampleContactService::class);
$this->exampleEventService = $this->createMock(ExampleEventService::class);
$this->logger = $this->createMock(LoggerInterface::class);
@@ -53,7 +53,7 @@ class UserEventsListenerTest extends TestCase {
$this->calDavBackend,
$this->cardDavBackend,
$this->defaults,
- $this->defaultContactService,
+ $this->exampleContactService,
$this->exampleEventService,
$this->logger,
);
diff --git a/apps/dav/tests/unit/Service/DefaultContactServiceTest.php b/apps/dav/tests/unit/Service/ExampleContactServiceTest.php
index 3bd8c9cb6f6..4c8d900ae86 100644
--- a/apps/dav/tests/unit/Service/DefaultContactServiceTest.php
+++ b/apps/dav/tests/unit/Service/ExampleContactServiceTest.php
@@ -10,56 +10,60 @@ declare(strict_types=1);
namespace OCA\DAV\Tests\unit\Service;
use OCA\DAV\CardDAV\CardDavBackend;
-use OCA\DAV\Service\DefaultContactService;
+use OCA\DAV\Service\ExampleContactService;
use OCP\App\IAppManager;
+use OCP\AppFramework\Services\IAppConfig;
use OCP\Files\AppData\IAppDataFactory;
use OCP\Files\IAppData;
use OCP\Files\NotFoundException;
use OCP\Files\SimpleFS\ISimpleFile;
use OCP\Files\SimpleFS\ISimpleFolder;
-use OCP\IAppConfig;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Symfony\Component\Uid\Uuid;
use Test\TestCase;
-class DefaultContactServiceTest extends TestCase {
- protected DefaultContactService $service;
+class ExampleContactServiceTest extends TestCase {
+ protected ExampleContactService $service;
protected CardDavBackend&MockObject $cardDav;
protected IAppManager&MockObject $appManager;
protected IAppDataFactory&MockObject $appDataFactory;
protected LoggerInterface&MockObject $logger;
- protected IAppConfig&MockObject $config;
+ protected IAppConfig&MockObject $appConfig;
+ protected IAppData&MockObject $appData;
protected function setUp(): void {
parent::setUp();
$this->cardDav = $this->createMock(CardDavBackend::class);
- $this->appManager = $this->createMock(IAppManager::class);
$this->appDataFactory = $this->createMock(IAppDataFactory::class);
$this->logger = $this->createMock(LoggerInterface::class);
- $this->config = $this->createMock(IAppConfig::class);
+ $this->appConfig = $this->createMock(IAppConfig::class);
- $this->service = new DefaultContactService(
- $this->cardDav,
- $this->appManager,
+ $this->appData = $this->createMock(IAppData::class);
+ $this->appDataFactory->method('get')
+ ->with('dav')
+ ->willReturn($this->appData);
+
+ $this->service = new ExampleContactService(
$this->appDataFactory,
- $this->config,
+ $this->appConfig,
$this->logger,
+ $this->cardDav,
);
}
public function testCreateDefaultContactWithInvalidCard(): void {
// Invalid vCard missing required FN property
$vcardContent = "BEGIN:VCARD\nVERSION:3.0\nEND:VCARD";
- $this->config->method('getValueString')->willReturn('yes');
- $appData = $this->createMock(IAppData::class);
+ $this->appConfig->method('getAppValueBool')
+ ->with('enableDefaultContact', true)
+ ->willReturn(true);
$folder = $this->createMock(ISimpleFolder::class);
$file = $this->createMock(ISimpleFile::class);
$file->method('getContent')->willReturn($vcardContent);
$folder->method('getFile')->willReturn($file);
- $appData->method('getFolder')->willReturn($folder);
- $this->appDataFactory->method('get')->willReturn($appData);
+ $this->appData->method('getFolder')->willReturn($folder);
$this->logger->expects($this->once())
->method('error')
@@ -76,14 +80,14 @@ class DefaultContactServiceTest extends TestCase {
$originalRev = '20200101T000000Z';
$vcardContent = "BEGIN:VCARD\nVERSION:3.0\nFN:Test User\nUID:$originalUid\nREV:$originalRev\nEND:VCARD";
- $this->config->method('getValueString')->willReturn('yes');
- $appData = $this->createMock(IAppData::class);
+ $this->appConfig->method('getAppValueBool')
+ ->with('enableDefaultContact', true)
+ ->willReturn(true);
$folder = $this->createMock(ISimpleFolder::class);
$file = $this->createMock(ISimpleFile::class);
$file->method('getContent')->willReturn($vcardContent);
$folder->method('getFile')->willReturn($file);
- $appData->method('getFolder')->willReturn($folder);
- $this->appDataFactory->method('get')->willReturn($appData);
+ $this->appData->method('getFolder')->willReturn($folder);
$capturedCardData = null;
$this->cardDav->expects($this->once())
@@ -107,10 +111,10 @@ class DefaultContactServiceTest extends TestCase {
}
public function testDefaultContactFileDoesNotExist(): void {
- $appData = $this->createMock(IAppData::class);
- $this->config->method('getValueString')->willReturn('yes');
- $appData->method('getFolder')->willThrowException(new NotFoundException());
- $this->appDataFactory->method('get')->willReturn($appData);
+ $this->appConfig->method('getAppValueBool')
+ ->with('enableDefaultContact', true)
+ ->willReturn(true);
+ $this->appData->method('getFolder')->willThrowException(new NotFoundException());
$this->cardDav->expects($this->never())
->method('createCard');
@@ -121,14 +125,14 @@ class DefaultContactServiceTest extends TestCase {
public function testUidAndRevAreAddedIfMissing(): void {
$vcardContent = "BEGIN:VCARD\nVERSION:3.0\nFN:Test User\nEND:VCARD";
- $this->config->method('getValueString')->willReturn('yes');
- $appData = $this->createMock(IAppData::class);
+ $this->appConfig->method('getAppValueBool')
+ ->with('enableDefaultContact', true)
+ ->willReturn(true);
$folder = $this->createMock(ISimpleFolder::class);
$file = $this->createMock(ISimpleFile::class);
$file->method('getContent')->willReturn($vcardContent);
$folder->method('getFile')->willReturn($file);
- $appData->method('getFolder')->willReturn($folder);
- $this->appDataFactory->method('get')->willReturn($appData);
+ $this->appData->method('getFolder')->willReturn($folder);
$capturedCardData = 'new-card-data';
@@ -154,7 +158,9 @@ class DefaultContactServiceTest extends TestCase {
}
public function testDefaultContactIsNotCreatedIfEnabled(): void {
- $this->config->method('getValueString')->willReturn('no');
+ $this->appConfig->method('getAppValueBool')
+ ->with('enableDefaultContact', true)
+ ->willReturn(false);
$this->logger->expects($this->never())
->method('error');
$this->cardDav->expects($this->never())
@@ -162,4 +168,27 @@ class DefaultContactServiceTest extends TestCase {
$this->service->createDefaultContact(123);
}
+
+ public static function provideDefaultContactEnableData(): array {
+ return [[true], [false]];
+ }
+
+ /** @dataProvider provideDefaultContactEnableData */
+ public function testIsDefaultContactEnabled(bool $enabled): void {
+ $this->appConfig->expects(self::once())
+ ->method('getAppValueBool')
+ ->with('enableDefaultContact', true)
+ ->willReturn($enabled);
+
+ $this->assertEquals($enabled, $this->service->isDefaultContactEnabled());
+ }
+
+ /** @dataProvider provideDefaultContactEnableData */
+ public function testSetDefaultContactEnabled(bool $enabled): void {
+ $this->appConfig->expects(self::once())
+ ->method('setAppValueBool')
+ ->with('enableDefaultContact', $enabled);
+
+ $this->service->setDefaultContactEnabled($enabled);
+ }
}