aboutsummaryrefslogtreecommitdiffstats
path: root/apps/dav
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dav')
-rw-r--r--apps/dav/appinfo/info.xml5
-rw-r--r--apps/dav/appinfo/routes.php3
-rw-r--r--apps/dav/appinfo/v1/carddav.php6
-rw-r--r--apps/dav/appinfo/v1/publicwebdav.php6
-rw-r--r--apps/dav/appinfo/v1/webdav.php2
-rw-r--r--apps/dav/appinfo/v2/publicremote.php19
-rw-r--r--apps/dav/composer/composer/autoload_classmap.php14
-rw-r--r--apps/dav/composer/composer/autoload_static.php14
-rw-r--r--apps/dav/css/schedule-response.css1
-rw-r--r--apps/dav/l10n/ar.js30
-rw-r--r--apps/dav/l10n/ar.json30
-rw-r--r--apps/dav/l10n/ast.js13
-rw-r--r--apps/dav/l10n/ast.json13
-rw-r--r--apps/dav/l10n/bg.js26
-rw-r--r--apps/dav/l10n/bg.json26
-rw-r--r--apps/dav/l10n/ca.js13
-rw-r--r--apps/dav/l10n/ca.json13
-rw-r--r--apps/dav/l10n/cs.js40
-rw-r--r--apps/dav/l10n/cs.json40
-rw-r--r--apps/dav/l10n/da.js30
-rw-r--r--apps/dav/l10n/da.json30
-rw-r--r--apps/dav/l10n/de.js58
-rw-r--r--apps/dav/l10n/de.json58
-rw-r--r--apps/dav/l10n/de_DE.js56
-rw-r--r--apps/dav/l10n/de_DE.json56
-rw-r--r--apps/dav/l10n/el.js120
-rw-r--r--apps/dav/l10n/el.json118
-rw-r--r--apps/dav/l10n/en_GB.js40
-rw-r--r--apps/dav/l10n/en_GB.json40
-rw-r--r--apps/dav/l10n/eo.js104
-rw-r--r--apps/dav/l10n/eo.json102
-rw-r--r--apps/dav/l10n/es.js13
-rw-r--r--apps/dav/l10n/es.json13
-rw-r--r--apps/dav/l10n/es_419.js66
-rw-r--r--apps/dav/l10n/es_419.json64
-rw-r--r--apps/dav/l10n/es_AR.js56
-rw-r--r--apps/dav/l10n/es_AR.json54
-rw-r--r--apps/dav/l10n/es_CL.js66
-rw-r--r--apps/dav/l10n/es_CL.json64
-rw-r--r--apps/dav/l10n/es_CO.js66
-rw-r--r--apps/dav/l10n/es_CO.json64
-rw-r--r--apps/dav/l10n/es_CR.js66
-rw-r--r--apps/dav/l10n/es_CR.json64
-rw-r--r--apps/dav/l10n/es_DO.js66
-rw-r--r--apps/dav/l10n/es_DO.json64
-rw-r--r--apps/dav/l10n/es_EC.js13
-rw-r--r--apps/dav/l10n/es_EC.json13
-rw-r--r--apps/dav/l10n/es_GT.js66
-rw-r--r--apps/dav/l10n/es_GT.json64
-rw-r--r--apps/dav/l10n/es_HN.js66
-rw-r--r--apps/dav/l10n/es_HN.json64
-rw-r--r--apps/dav/l10n/es_MX.js13
-rw-r--r--apps/dav/l10n/es_MX.json13
-rw-r--r--apps/dav/l10n/es_NI.js66
-rw-r--r--apps/dav/l10n/es_NI.json64
-rw-r--r--apps/dav/l10n/es_PA.js66
-rw-r--r--apps/dav/l10n/es_PA.json64
-rw-r--r--apps/dav/l10n/es_PE.js66
-rw-r--r--apps/dav/l10n/es_PE.json64
-rw-r--r--apps/dav/l10n/es_PR.js66
-rw-r--r--apps/dav/l10n/es_PR.json64
-rw-r--r--apps/dav/l10n/es_PY.js66
-rw-r--r--apps/dav/l10n/es_PY.json64
-rw-r--r--apps/dav/l10n/es_SV.js66
-rw-r--r--apps/dav/l10n/es_SV.json64
-rw-r--r--apps/dav/l10n/es_UY.js66
-rw-r--r--apps/dav/l10n/es_UY.json64
-rw-r--r--apps/dav/l10n/et_EE.js185
-rw-r--r--apps/dav/l10n/et_EE.json185
-rw-r--r--apps/dav/l10n/eu.js13
-rw-r--r--apps/dav/l10n/eu.json13
-rw-r--r--apps/dav/l10n/fa.js451
-rw-r--r--apps/dav/l10n/fa.json451
-rw-r--r--apps/dav/l10n/fi.js165
-rw-r--r--apps/dav/l10n/fi.json163
-rw-r--r--apps/dav/l10n/fr.js82
-rw-r--r--apps/dav/l10n/fr.json82
-rw-r--r--apps/dav/l10n/ga.js40
-rw-r--r--apps/dav/l10n/ga.json40
-rw-r--r--apps/dav/l10n/gl.js13
-rw-r--r--apps/dav/l10n/gl.json13
-rw-r--r--apps/dav/l10n/he.js101
-rw-r--r--apps/dav/l10n/he.json99
-rw-r--r--apps/dav/l10n/hr.js157
-rw-r--r--apps/dav/l10n/hr.json155
-rw-r--r--apps/dav/l10n/hu.js17
-rw-r--r--apps/dav/l10n/hu.json17
-rw-r--r--apps/dav/l10n/id.js11
-rw-r--r--apps/dav/l10n/id.json9
-rw-r--r--apps/dav/l10n/is.js13
-rw-r--r--apps/dav/l10n/is.json13
-rw-r--r--apps/dav/l10n/it.js13
-rw-r--r--apps/dav/l10n/it.json13
-rw-r--r--apps/dav/l10n/ja.js30
-rw-r--r--apps/dav/l10n/ja.json30
-rw-r--r--apps/dav/l10n/ka.js13
-rw-r--r--apps/dav/l10n/ka.json13
-rw-r--r--apps/dav/l10n/ka_GE.js66
-rw-r--r--apps/dav/l10n/ka_GE.json64
-rw-r--r--apps/dav/l10n/ko.js13
-rw-r--r--apps/dav/l10n/ko.json13
-rw-r--r--apps/dav/l10n/lt_LT.js111
-rw-r--r--apps/dav/l10n/lt_LT.json109
-rw-r--r--apps/dav/l10n/lv.js11
-rw-r--r--apps/dav/l10n/lv.json9
-rw-r--r--apps/dav/l10n/mk.js9
-rw-r--r--apps/dav/l10n/mk.json9
-rw-r--r--apps/dav/l10n/nb.js13
-rw-r--r--apps/dav/l10n/nb.json13
-rw-r--r--apps/dav/l10n/nl.js13
-rw-r--r--apps/dav/l10n/nl.json13
-rw-r--r--apps/dav/l10n/nn_NO.js43
-rw-r--r--apps/dav/l10n/nn_NO.json41
-rw-r--r--apps/dav/l10n/pl.js41
-rw-r--r--apps/dav/l10n/pl.json41
-rw-r--r--apps/dav/l10n/pt_BR.js90
-rw-r--r--apps/dav/l10n/pt_BR.json90
-rw-r--r--apps/dav/l10n/pt_PT.js336
-rw-r--r--apps/dav/l10n/pt_PT.json334
-rw-r--r--apps/dav/l10n/ro.js60
-rw-r--r--apps/dav/l10n/ro.json58
-rw-r--r--apps/dav/l10n/ru.js109
-rw-r--r--apps/dav/l10n/ru.json109
-rw-r--r--apps/dav/l10n/sc.js151
-rw-r--r--apps/dav/l10n/sc.json149
-rw-r--r--apps/dav/l10n/sk.js30
-rw-r--r--apps/dav/l10n/sk.json30
-rw-r--r--apps/dav/l10n/sl.js13
-rw-r--r--apps/dav/l10n/sl.json13
-rw-r--r--apps/dav/l10n/sq.js63
-rw-r--r--apps/dav/l10n/sq.json61
-rw-r--r--apps/dav/l10n/sr.js40
-rw-r--r--apps/dav/l10n/sr.json40
-rw-r--r--apps/dav/l10n/sv.js40
-rw-r--r--apps/dav/l10n/sv.json40
-rw-r--r--apps/dav/l10n/tr.js48
-rw-r--r--apps/dav/l10n/tr.json48
-rw-r--r--apps/dav/l10n/ug.js13
-rw-r--r--apps/dav/l10n/ug.json13
-rw-r--r--apps/dav/l10n/uk.js18
-rw-r--r--apps/dav/l10n/uk.json18
-rw-r--r--apps/dav/l10n/zh_CN.js48
-rw-r--r--apps/dav/l10n/zh_CN.json48
-rw-r--r--apps/dav/l10n/zh_HK.js40
-rw-r--r--apps/dav/l10n/zh_HK.json40
-rw-r--r--apps/dav/l10n/zh_TW.js40
-rw-r--r--apps/dav/l10n/zh_TW.json40
-rw-r--r--apps/dav/lib/AppInfo/Application.php8
-rw-r--r--apps/dav/lib/Avatars/RootCollection.php1
-rw-r--r--apps/dav/lib/BackgroundJob/CleanupOrphanedChildrenJob.php89
-rw-r--r--apps/dav/lib/BulkUpload/BulkUploadPlugin.php1
-rw-r--r--apps/dav/lib/BulkUpload/MultipartRequestParser.php7
-rw-r--r--apps/dav/lib/CalDAV/Activity/Backend.php1
-rw-r--r--apps/dav/lib/CalDAV/Activity/Filter/Calendar.php1
-rw-r--r--apps/dav/lib/CalDAV/Activity/Filter/Todo.php1
-rw-r--r--apps/dav/lib/CalDAV/Activity/Provider/Base.php5
-rw-r--r--apps/dav/lib/CalDAV/Activity/Provider/Calendar.php1
-rw-r--r--apps/dav/lib/CalDAV/Activity/Provider/Event.php10
-rw-r--r--apps/dav/lib/CalDAV/Activity/Provider/Todo.php1
-rw-r--r--apps/dav/lib/CalDAV/Activity/Setting/Calendar.php1
-rw-r--r--apps/dav/lib/CalDAV/Activity/Setting/Event.php1
-rw-r--r--apps/dav/lib/CalDAV/Activity/Setting/Todo.php1
-rw-r--r--apps/dav/lib/CalDAV/BirthdayCalendar/EnablePlugin.php1
-rw-r--r--apps/dav/lib/CalDAV/BirthdayService.php4
-rw-r--r--apps/dav/lib/CalDAV/CachedSubscriptionImpl.php20
-rw-r--r--apps/dav/lib/CalDAV/CalDavBackend.php151
-rw-r--r--apps/dav/lib/CalDAV/Calendar.php21
-rw-r--r--apps/dav/lib/CalDAV/CalendarImpl.php48
-rw-r--r--apps/dav/lib/CalDAV/CalendarManager.php1
-rw-r--r--apps/dav/lib/CalDAV/CalendarObject.php1
-rw-r--r--apps/dav/lib/CalDAV/CalendarProvider.php23
-rw-r--r--apps/dav/lib/CalDAV/CalendarRoot.php4
-rw-r--r--apps/dav/lib/CalDAV/EventReader.php10
-rw-r--r--apps/dav/lib/CalDAV/Export/ExportService.php107
-rw-r--r--apps/dav/lib/CalDAV/ICSExportPlugin/ICSExportPlugin.php1
-rw-r--r--apps/dav/lib/CalDAV/Integration/ExternalCalendar.php1
-rw-r--r--apps/dav/lib/CalDAV/Integration/ICalendarProvider.php1
-rw-r--r--apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php1
-rw-r--r--apps/dav/lib/CalDAV/Outbox.php1
-rw-r--r--apps/dav/lib/CalDAV/Principal/Collection.php1
-rw-r--r--apps/dav/lib/CalDAV/Principal/User.php1
-rw-r--r--apps/dav/lib/CalDAV/PublicCalendar.php1
-rw-r--r--apps/dav/lib/CalDAV/PublicCalendarObject.php1
-rw-r--r--apps/dav/lib/CalDAV/Publishing/PublishPlugin.php1
-rw-r--r--apps/dav/lib/CalDAV/Publishing/Xml/Publisher.php1
-rw-r--r--apps/dav/lib/CalDAV/Reminder/ReminderService.php8
-rw-r--r--apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php23
-rw-r--r--apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php1
-rw-r--r--apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php1
-rw-r--r--apps/dav/lib/CalDAV/Schedule/IMipPlugin.php11
-rw-r--r--apps/dav/lib/CalDAV/Schedule/IMipService.php67
-rw-r--r--apps/dav/lib/CalDAV/Schedule/Plugin.php4
-rw-r--r--apps/dav/lib/CalDAV/Search/SearchPlugin.php5
-rw-r--r--apps/dav/lib/CalDAV/Search/Xml/Filter/CompFilter.php1
-rw-r--r--apps/dav/lib/CalDAV/Search/Xml/Filter/LimitFilter.php1
-rw-r--r--apps/dav/lib/CalDAV/Search/Xml/Filter/OffsetFilter.php1
-rw-r--r--apps/dav/lib/CalDAV/Search/Xml/Filter/ParamFilter.php1
-rw-r--r--apps/dav/lib/CalDAV/Search/Xml/Filter/PropFilter.php1
-rw-r--r--apps/dav/lib/CalDAV/Search/Xml/Filter/SearchTermFilter.php1
-rw-r--r--apps/dav/lib/CalDAV/Search/Xml/Request/CalendarSearchReport.php1
-rw-r--r--apps/dav/lib/CalDAV/TipBroker.php14
-rw-r--r--apps/dav/lib/CalDAV/UpcomingEventsService.php44
-rw-r--r--apps/dav/lib/Capabilities.php4
-rw-r--r--apps/dav/lib/CardDAV/Activity/Filter.php1
-rw-r--r--apps/dav/lib/CardDAV/Activity/Provider/Base.php4
-rw-r--r--apps/dav/lib/CardDAV/AddressBook.php4
-rw-r--r--apps/dav/lib/CardDAV/AddressBookImpl.php6
-rw-r--r--apps/dav/lib/CardDAV/CardDavBackend.php7
-rw-r--r--apps/dav/lib/CardDAV/PhotoCache.php25
-rw-r--r--apps/dav/lib/Command/ClearCalendarUnshares.php114
-rw-r--r--apps/dav/lib/Command/ClearContactsPhotoCache.php75
-rw-r--r--apps/dav/lib/Command/ExportCalendar.php95
-rw-r--r--apps/dav/lib/Command/ListCalendarShares.php131
-rw-r--r--apps/dav/lib/Command/ListCalendars.php1
-rw-r--r--apps/dav/lib/Command/MoveCalendar.php1
-rw-r--r--apps/dav/lib/Command/SendEventReminders.php1
-rw-r--r--apps/dav/lib/Connector/Sabre/AnonymousOptionsPlugin.php1
-rw-r--r--apps/dav/lib/Connector/Sabre/AppleQuirksPlugin.php1
-rw-r--r--apps/dav/lib/Connector/Sabre/Auth.php24
-rw-r--r--apps/dav/lib/Connector/Sabre/BearerAuth.php1
-rw-r--r--apps/dav/lib/Connector/Sabre/CachingTree.php1
-rw-r--r--apps/dav/lib/Connector/Sabre/ChecksumUpdatePlugin.php14
-rw-r--r--apps/dav/lib/Connector/Sabre/DavAclPlugin.php2
-rw-r--r--apps/dav/lib/Connector/Sabre/Directory.php22
-rw-r--r--apps/dav/lib/Connector/Sabre/DummyGetResponsePlugin.php4
-rw-r--r--apps/dav/lib/Connector/Sabre/Exception/BadGateway.php1
-rw-r--r--apps/dav/lib/Connector/Sabre/FakeLockerPlugin.php4
-rw-r--r--apps/dav/lib/Connector/Sabre/File.php7
-rw-r--r--apps/dav/lib/Connector/Sabre/FilesPlugin.php52
-rw-r--r--apps/dav/lib/Connector/Sabre/MtimeSanitizer.php1
-rw-r--r--apps/dav/lib/Connector/Sabre/Principal.php12
-rw-r--r--apps/dav/lib/Connector/Sabre/PublicAuth.php44
-rw-r--r--apps/dav/lib/Connector/Sabre/ServerFactory.php78
-rw-r--r--apps/dav/lib/Connector/Sabre/SharesPlugin.php4
-rw-r--r--apps/dav/lib/Connector/Sabre/TagsPlugin.php44
-rw-r--r--apps/dav/lib/Controller/BirthdayCalendarController.php1
-rw-r--r--apps/dav/lib/Controller/ExampleContentController.php86
-rw-r--r--apps/dav/lib/DAV/CustomPropertiesBackend.php10
-rw-r--r--apps/dav/lib/DAV/GroupPrincipalBackend.php13
-rw-r--r--apps/dav/lib/DAV/Sharing/Backend.php53
-rw-r--r--apps/dav/lib/DAV/Sharing/SharingMapper.php24
-rw-r--r--apps/dav/lib/DAV/Sharing/SharingService.php10
-rw-r--r--apps/dav/lib/DAV/ViewOnlyPlugin.php13
-rw-r--r--apps/dav/lib/Db/PropertyMapper.php14
-rw-r--r--apps/dav/lib/Direct/DirectHome.php2
-rw-r--r--apps/dav/lib/Events/CalendarShareUpdatedEvent.php11
-rw-r--r--apps/dav/lib/Exception/ExampleEventException.php13
-rw-r--r--apps/dav/lib/Exception/UnsupportedLimitOnInitialSyncException.php1
-rw-r--r--apps/dav/lib/Files/BrowserErrorPagePlugin.php6
-rw-r--r--apps/dav/lib/Files/FileSearchBackend.php4
-rw-r--r--apps/dav/lib/Files/LazySearchBackend.php1
-rw-r--r--apps/dav/lib/Files/Sharing/FilesDropPlugin.php173
-rw-r--r--apps/dav/lib/Files/Sharing/RootCollection.php32
-rw-r--r--apps/dav/lib/Listener/AddMissingIndicesListener.php5
-rw-r--r--apps/dav/lib/Listener/DavAdminSettingsListener.php4
-rw-r--r--apps/dav/lib/Listener/UserEventsListener.php30
-rw-r--r--apps/dav/lib/Migration/BuildCalendarSearchIndex.php1
-rw-r--r--apps/dav/lib/Migration/BuildSocialSearchIndex.php1
-rw-r--r--apps/dav/lib/Migration/CalDAVRemoveEmptyValue.php1
-rw-r--r--apps/dav/lib/Migration/RegenerateBirthdayCalendars.php1
-rw-r--r--apps/dav/lib/Migration/RegisterUpdateCalendarResourcesRoomBackgroundJob.php30
-rw-r--r--apps/dav/lib/Migration/RemoveObjectProperties.php1
-rw-r--r--apps/dav/lib/Migration/RemoveOrphanEventsAndContacts.php87
-rw-r--r--apps/dav/lib/Migration/Version1004Date20170825134824.php1
-rw-r--r--apps/dav/lib/Migration/Version1004Date20170919104507.php1
-rw-r--r--apps/dav/lib/Migration/Version1004Date20170924124212.php1
-rw-r--r--apps/dav/lib/Migration/Version1004Date20170926103422.php1
-rw-r--r--apps/dav/lib/Migration/Version1005Date20180530124431.php1
-rw-r--r--apps/dav/lib/Migration/Version1006Date20180619154313.php1
-rw-r--r--apps/dav/lib/Migration/Version1006Date20180628111625.php1
-rw-r--r--apps/dav/lib/Model/ExampleEvent.php31
-rw-r--r--apps/dav/lib/Paginate/PaginatePlugin.php10
-rw-r--r--apps/dav/lib/Provisioning/Apple/AppleProvisioningNode.php3
-rw-r--r--apps/dav/lib/Provisioning/Apple/AppleProvisioningPlugin.php1
-rw-r--r--apps/dav/lib/RootCollection.php1
-rw-r--r--apps/dav/lib/Server.php12
-rw-r--r--apps/dav/lib/Service/DefaultContactService.php77
-rw-r--r--apps/dav/lib/Service/ExampleContactService.php132
-rw-r--r--apps/dav/lib/Service/ExampleEventService.php205
-rw-r--r--apps/dav/lib/Settings/CalDAVSettings.php1
-rw-r--r--apps/dav/lib/Settings/ExampleContentSettings.php45
-rw-r--r--apps/dav/lib/SystemTag/SystemTagList.php1
-rw-r--r--apps/dav/lib/SystemTag/SystemTagNode.php10
-rw-r--r--apps/dav/lib/SystemTag/SystemTagObjectType.php1
-rw-r--r--apps/dav/lib/SystemTag/SystemTagsObjectList.php2
-rw-r--r--apps/dav/lib/Traits/PrincipalProxyTrait.php1
-rw-r--r--apps/dav/lib/Upload/CleanupService.php10
-rw-r--r--apps/dav/lib/Upload/RootCollection.php10
-rw-r--r--apps/dav/lib/Upload/UploadAutoMkcolPlugin.php68
-rw-r--r--apps/dav/lib/Upload/UploadFolder.php3
-rw-r--r--apps/dav/lib/Upload/UploadHome.php35
-rw-r--r--apps/dav/openapi.json9
-rw-r--r--apps/dav/src/components/ExampleContactSettings.vue (renamed from apps/dav/src/views/ExampleContactSettings.vue)104
-rw-r--r--apps/dav/src/components/ExampleContentDownloadButton.vue57
-rw-r--r--apps/dav/src/components/ExampleEventSettings.vue217
-rw-r--r--apps/dav/src/service/ExampleEventService.js43
-rw-r--r--apps/dav/src/settings-example-content.js11
-rw-r--r--apps/dav/src/views/ExampleContentSettingsSection.vue38
-rw-r--r--apps/dav/templates/settings-example-content.php2
-rw-r--r--apps/dav/tests/integration/DAV/Sharing/CalDavSharingBackendTest.php251
-rw-r--r--apps/dav/tests/integration/DAV/Sharing/SharingMapperTest.php2
-rw-r--r--apps/dav/tests/unit/AppInfo/ApplicationTest.php1
-rw-r--r--apps/dav/tests/unit/AppInfo/PluginManagerTest.php2
-rw-r--r--apps/dav/tests/unit/Avatars/AvatarHomeTest.php20
-rw-r--r--apps/dav/tests/unit/Avatars/AvatarNodeTest.php8
-rw-r--r--apps/dav/tests/unit/BackgroundJob/CleanupInvitationTokenJobTest.php12
-rw-r--r--apps/dav/tests/unit/BackgroundJob/CleanupOrphanedChildrenJobTest.php170
-rw-r--r--apps/dav/tests/unit/BackgroundJob/EventReminderJobTest.php29
-rw-r--r--apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php16
-rw-r--r--apps/dav/tests/unit/BackgroundJob/OutOfOfficeEventDispatcherJobTest.php20
-rw-r--r--apps/dav/tests/unit/BackgroundJob/PruneOutdatedSyncTokensJobTest.php22
-rw-r--r--apps/dav/tests/unit/BackgroundJob/RefreshWebcalJobTest.php22
-rw-r--r--apps/dav/tests/unit/BackgroundJob/RegisterRegenerateBirthdayCalendarsTest.php48
-rw-r--r--apps/dav/tests/unit/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJobTest.php12
-rw-r--r--apps/dav/tests/unit/BackgroundJob/UserStatusAutomationTest.php19
-rw-r--r--apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php20
-rw-r--r--apps/dav/tests/unit/CalDAV/Activity/BackendTest.php57
-rw-r--r--apps/dav/tests/unit/CalDAV/Activity/Filter/CalendarTest.php15
-rw-r--r--apps/dav/tests/unit/CalDAV/Activity/Filter/GenericTest.php25
-rw-r--r--apps/dav/tests/unit/CalDAV/Activity/Filter/TodoTest.php15
-rw-r--r--apps/dav/tests/unit/CalDAV/Activity/Provider/BaseTest.php42
-rw-r--r--apps/dav/tests/unit/CalDAV/Activity/Provider/EventTest.php66
-rw-r--r--apps/dav/tests/unit/CalDAV/Activity/Setting/GenericTest.php28
-rw-r--r--apps/dav/tests/unit/CalDAV/AppCalendar/AppCalendarTest.php17
-rw-r--r--apps/dav/tests/unit/CalDAV/AppCalendar/CalendarObjectTest.php7
-rw-r--r--apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php23
-rw-r--r--apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php5
-rw-r--r--apps/dav/tests/unit/CalDAV/CachedSubscriptionObjectTest.php6
-rw-r--r--apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php3
-rw-r--r--apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php49
-rw-r--r--apps/dav/tests/unit/CalDAV/CalDavBackendTest.php59
-rw-r--r--apps/dav/tests/unit/CalDAV/CalendarHomeTest.php28
-rw-r--r--apps/dav/tests/unit/CalDAV/CalendarImplTest.php78
-rw-r--r--apps/dav/tests/unit/CalDAV/CalendarManagerTest.php23
-rw-r--r--apps/dav/tests/unit/CalDAV/CalendarTest.php83
-rw-r--r--apps/dav/tests/unit/CalDAV/EventComparisonServiceTest.php3
-rw-r--r--apps/dav/tests/unit/CalDAV/EventReaderTest.php32
-rw-r--r--apps/dav/tests/unit/CalDAV/Export/ExportServiceTest.php81
-rw-r--r--apps/dav/tests/unit/CalDAV/Integration/ExternalCalendarTest.php13
-rw-r--r--apps/dav/tests/unit/CalDAV/Listener/CalendarPublicationListenerTest.php19
-rw-r--r--apps/dav/tests/unit/CalDAV/Listener/CalendarShareUpdateListenerTest.php15
-rw-r--r--apps/dav/tests/unit/CalDAV/Listener/SubscriptionListenerTest.php27
-rw-r--r--apps/dav/tests/unit/CalDAV/OutboxTest.php11
-rw-r--r--apps/dav/tests/unit/CalDAV/PluginTest.php12
-rw-r--r--apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php39
-rw-r--r--apps/dav/tests/unit/CalDAV/PublicCalendarTest.php22
-rw-r--r--apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php8
-rw-r--r--apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php33
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/BackendTest.php49
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/AbstractNotificationProviderTestCase.php (renamed from apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/AbstractNotificationProviderTest.php)45
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php82
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/PushProviderTest.php25
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/NotificationProviderManagerTest.php4
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/NotifierTest.php36
-rw-r--r--apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php202
-rw-r--r--apps/dav/tests/unit/CalDAV/ResourceBooking/AbstractPrincipalBackendTestCase.php (renamed from apps/dav/tests/unit/CalDAV/ResourceBooking/AbstractPrincipalBackendTest.php)119
-rw-r--r--apps/dav/tests/unit/CalDAV/ResourceBooking/ResourcePrincipalBackendTest.php4
-rw-r--r--apps/dav/tests/unit/CalDAV/ResourceBooking/RoomPrincipalBackendTest.php4
-rw-r--r--apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php176
-rw-r--r--apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php86
-rw-r--r--apps/dav/tests/unit/CalDAV/Schedule/PluginTest.php66
-rw-r--r--apps/dav/tests/unit/CalDAV/Search/Request/CalendarSearchReportTest.php18
-rw-r--r--apps/dav/tests/unit/CalDAV/Search/SearchPluginTest.php2
-rw-r--r--apps/dav/tests/unit/CalDAV/Security/RateLimitingPluginTest.php10
-rw-r--r--apps/dav/tests/unit/CalDAV/Status/StatusServiceTest.php18
-rw-r--r--apps/dav/tests/unit/CalDAV/TimeZoneFactoryTest.php1
-rw-r--r--apps/dav/tests/unit/CalDAV/TimezoneServiceTest.php12
-rw-r--r--apps/dav/tests/unit/CalDAV/TipBrokerTest.php14
-rw-r--r--apps/dav/tests/unit/CalDAV/Validation/CalDavValidatePluginTest.php14
-rw-r--r--apps/dav/tests/unit/CalDAV/WebcalCaching/ConnectionTest.php7
-rw-r--r--apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php2
-rw-r--r--apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php34
-rw-r--r--apps/dav/tests/unit/CapabilitiesTest.php5
-rw-r--r--apps/dav/tests/unit/CardDAV/Activity/BackendTest.php62
-rw-r--r--apps/dav/tests/unit/CardDAV/AddressBookImplTest.php75
-rw-r--r--apps/dav/tests/unit/CardDAV/AddressBookTest.php32
-rw-r--r--apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php130
-rw-r--r--apps/dav/tests/unit/CardDAV/CardDavBackendTest.php167
-rw-r--r--apps/dav/tests/unit/CardDAV/ContactsManagerTest.php12
-rw-r--r--apps/dav/tests/unit/CardDAV/ConverterTest.php43
-rw-r--r--apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php69
-rw-r--r--apps/dav/tests/unit/CardDAV/Security/CardDavRateLimitingPluginTest.php10
-rw-r--r--apps/dav/tests/unit/CardDAV/Sharing/PluginTest.php28
-rw-r--r--apps/dav/tests/unit/CardDAV/SyncServiceTest.php46
-rw-r--r--apps/dav/tests/unit/CardDAV/SystemAddressBookTest.php12
-rw-r--r--apps/dav/tests/unit/CardDAV/Validation/CardDavValidatePluginTest.php14
-rw-r--r--apps/dav/tests/unit/Command/DeleteCalendarTest.php25
-rw-r--r--apps/dav/tests/unit/Command/ListAddressbooksTest.php9
-rw-r--r--apps/dav/tests/unit/Command/ListCalendarSharesTest.php172
-rw-r--r--apps/dav/tests/unit/Command/ListCalendarsTest.php19
-rw-r--r--apps/dav/tests/unit/Command/MoveCalendarTest.php204
-rw-r--r--apps/dav/tests/unit/Command/RemoveInvalidSharesTest.php14
-rw-r--r--apps/dav/tests/unit/Comments/CommentsNodeTest.php91
-rw-r--r--apps/dav/tests/unit/Comments/CommentsPluginTest.php50
-rw-r--r--apps/dav/tests/unit/Comments/EntityCollectionTest.php44
-rw-r--r--apps/dav/tests/unit/Comments/EntityTypeCollectionTest.php42
-rw-r--r--apps/dav/tests/unit/Comments/RootCollectionTest.php52
-rw-r--r--apps/dav/tests/unit/Connector/LegacyPublicAuthTest.php74
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/AuthTest.php221
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/BearerAuthTest.php18
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/BlockLegacyClientPluginTest.php2
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/CommentsPropertiesPluginTest.php80
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/CopyEtagHeaderPluginTest.php17
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/CustomPropertiesBackendTest.php52
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php66
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/DummyGetResponsePluginTest.php17
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/Exception/ForbiddenTest.php6
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/Exception/InvalidPathTest.php6
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php16
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/FakeLockerPluginTest.php69
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/FileTest.php106
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php216
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php224
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/MaintenancePluginTest.php15
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/NodeTest.php70
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php51
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php98
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/PropfindCompressionPluginTest.php3
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/PublicAuthTest.php119
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/QuotaPluginTest.php51
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/Auth.php1
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/DeleteTest.php5
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/DownloadTest.php7
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionMasterKeyUploadTest.php3
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionUploadTest.php3
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/ExceptionPlugin.php1
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/PartFileInRootUploadTest.php4
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/RequestTestCase.php20
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/Sapi.php1
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/RequestTest/UploadTest.php9
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php51
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/TagsPluginTest.php143
-rw-r--r--apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php52
-rw-r--r--apps/dav/tests/unit/Controller/DirectControllerTest.php31
-rw-r--r--apps/dav/tests/unit/Controller/InvitationResponseControllerTest.php30
-rw-r--r--apps/dav/tests/unit/Controller/UpcomingEventsControllerTest.php7
-rw-r--r--apps/dav/tests/unit/DAV/AnonymousOptionsTest.php6
-rw-r--r--apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php18
-rw-r--r--apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php42
-rw-r--r--apps/dav/tests/unit/DAV/GroupPrincipalTest.php40
-rw-r--r--apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php47
-rw-r--r--apps/dav/tests/unit/DAV/Sharing/BackendTest.php38
-rw-r--r--apps/dav/tests/unit/DAV/Sharing/PluginTest.php22
-rw-r--r--apps/dav/tests/unit/DAV/Sharing/SharingServiceTest.php58
-rw-r--r--apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php38
-rw-r--r--apps/dav/tests/unit/DAV/ViewOnlyPluginTest.php52
-rw-r--r--apps/dav/tests/unit/Direct/DirectFileTest.php27
-rw-r--r--apps/dav/tests/unit/Direct/DirectHomeTest.php33
-rw-r--r--apps/dav/tests/unit/Files/FileSearchBackendTest.php94
-rw-r--r--apps/dav/tests/unit/Files/MultipartRequestParserTest.php37
-rw-r--r--apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php219
-rw-r--r--apps/dav/tests/unit/Listener/ActivityUpdaterListenerTest.php12
-rw-r--r--apps/dav/tests/unit/Listener/CalendarContactInteractionListenerTest.php26
-rw-r--r--apps/dav/tests/unit/Listener/OutOfOfficeListenerTest.php22
-rw-r--r--apps/dav/tests/unit/Migration/CalDAVRemoveEmptyValueTest.php40
-rw-r--r--apps/dav/tests/unit/Migration/CreateSystemAddressBookStepTest.php4
-rw-r--r--apps/dav/tests/unit/Migration/RefreshWebcalJobRegistrarTest.php52
-rw-r--r--apps/dav/tests/unit/Migration/RegenerateBirthdayCalendarsTest.php15
-rw-r--r--apps/dav/tests/unit/Migration/RemoveDeletedUsersCalendarSubscriptionsTest.php54
-rw-r--r--apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningNodeTest.php13
-rw-r--r--apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningPluginTest.php74
-rw-r--r--apps/dav/tests/unit/Search/ContactsSearchProviderTest.php68
-rw-r--r--apps/dav/tests/unit/Search/EventsSearchProviderTest.php386
-rw-r--r--apps/dav/tests/unit/Search/TasksSearchProviderTest.php165
-rw-r--r--apps/dav/tests/unit/ServerTest.php5
-rw-r--r--apps/dav/tests/unit/Service/AbsenceServiceTest.php23
-rw-r--r--apps/dav/tests/unit/Service/ExampleContactServiceTest.php (renamed from apps/dav/tests/unit/Service/DefaultContactServiceTest.php)101
-rw-r--r--apps/dav/tests/unit/Service/ExampleEventServiceTest.php196
-rw-r--r--apps/dav/tests/unit/Service/UpcomingEventsServiceTest.php12
-rw-r--r--apps/dav/tests/unit/Settings/CalDAVSettingsTest.php58
-rw-r--r--apps/dav/tests/unit/SystemTag/SystemTagMappingNodeTest.php31
-rw-r--r--apps/dav/tests/unit/SystemTag/SystemTagNodeTest.php79
-rw-r--r--apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php185
-rw-r--r--apps/dav/tests/unit/SystemTag/SystemTagsByIdCollectionTest.php69
-rw-r--r--apps/dav/tests/unit/SystemTag/SystemTagsObjectMappingCollectionTest.php40
-rw-r--r--apps/dav/tests/unit/SystemTag/SystemTagsObjectTypeCollectionTest.php46
-rw-r--r--apps/dav/tests/unit/Upload/AssemblyStreamTest.php73
-rw-r--r--apps/dav/tests/unit/Upload/ChunkingPluginTest.php109
-rw-r--r--apps/dav/tests/unit/Upload/FutureFileTest.php14
-rw-r--r--apps/dav/tests/unit/Upload/UploadAutoMkcolPluginTest.php135
-rw-r--r--apps/dav/tests/unit/test_fixtures/example-event-default-expected.ics20
-rw-r--r--apps/dav/tests/unit/test_fixtures/example-event-default-expected.ics.license2
-rw-r--r--apps/dav/tests/unit/test_fixtures/example-event-expected.ics18
-rw-r--r--apps/dav/tests/unit/test_fixtures/example-event-expected.ics.license2
-rw-r--r--apps/dav/tests/unit/test_fixtures/example-event-with-attendees.ics21
-rw-r--r--apps/dav/tests/unit/test_fixtures/example-event-with-attendees.ics.license2
-rw-r--r--apps/dav/tests/unit/test_fixtures/example-event.ics18
-rw-r--r--apps/dav/tests/unit/test_fixtures/example-event.ics.license2
488 files changed, 10204 insertions, 10712 deletions
diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml
index a99bea224b6..a4ce51fd89c 100644
--- a/apps/dav/appinfo/info.xml
+++ b/apps/dav/appinfo/info.xml
@@ -41,6 +41,7 @@
<step>OCA\DAV\Migration\BuildSocialSearchIndex</step>
<step>OCA\DAV\Migration\RefreshWebcalJobRegistrar</step>
<step>OCA\DAV\Migration\RegisterBuildReminderIndexBackgroundJob</step>
+ <step>OCA\DAV\Migration\RegisterUpdateCalendarResourcesRoomBackgroundJob</step>
<step>OCA\DAV\Migration\RemoveOrphanEventsAndContacts</step>
<step>OCA\DAV\Migration\RemoveClassifiedEventActivity</step>
<step>OCA\DAV\Migration\RemoveDeletedUsersCalendarSubscriptions</step>
@@ -55,13 +56,17 @@
</repair-steps>
<commands>
+ <command>OCA\DAV\Command\ClearCalendarUnshares</command>
+ <command>OCA\DAV\Command\ClearContactsPhotoCache</command>
<command>OCA\DAV\Command\CreateAddressBook</command>
<command>OCA\DAV\Command\CreateCalendar</command>
<command>OCA\DAV\Command\CreateSubscription</command>
<command>OCA\DAV\Command\DeleteCalendar</command>
<command>OCA\DAV\Command\DeleteSubscription</command>
+ <command>OCA\DAV\Command\ExportCalendar</command>
<command>OCA\DAV\Command\FixCalendarSyncCommand</command>
<command>OCA\DAV\Command\ListAddressbooks</command>
+ <command>OCA\DAV\Command\ListCalendarShares</command>
<command>OCA\DAV\Command\ListCalendars</command>
<command>OCA\DAV\Command\ListSubscriptions</command>
<command>OCA\DAV\Command\MoveCalendar</command>
diff --git a/apps/dav/appinfo/routes.php b/apps/dav/appinfo/routes.php
index 67bfa44e995..dba7bcbbdf0 100644
--- a/apps/dav/appinfo/routes.php
+++ b/apps/dav/appinfo/routes.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -11,8 +12,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#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/appinfo/v1/carddav.php b/apps/dav/appinfo/v1/carddav.php
index 0220332297e..bcd66e47090 100644
--- a/apps/dav/appinfo/v1/carddav.php
+++ b/apps/dav/appinfo/v1/carddav.php
@@ -23,7 +23,6 @@ use OCA\DAV\Connector\Sabre\Principal;
use OCP\Accounts\IAccountManager;
use OCP\App\IAppManager;
use OCP\EventDispatcher\IEventDispatcher;
-use OCP\Files\AppData\IAppDataFactory;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IGroupManager;
@@ -98,10 +97,7 @@ if ($debugging) {
$server->addPlugin(new \Sabre\DAV\Sync\Plugin());
$server->addPlugin(new \Sabre\CardDAV\VCFExportPlugin());
-$server->addPlugin(new ImageExportPlugin(new PhotoCache(
- Server::get(IAppDataFactory::class)->get('dav-photocache'),
- Server::get(LoggerInterface::class)
-)));
+$server->addPlugin(new ImageExportPlugin(Server::get(PhotoCache::class)));
$server->addPlugin(new ExceptionLoggerPlugin('carddav', Server::get(LoggerInterface::class)));
$server->addPlugin(Server::get(CardDavRateLimitingPlugin::class));
$server->addPlugin(Server::get(CardDavValidatePlugin::class));
diff --git a/apps/dav/appinfo/v1/publicwebdav.php b/apps/dav/appinfo/v1/publicwebdav.php
index 85dbb19d290..af49ca5462c 100644
--- a/apps/dav/appinfo/v1/publicwebdav.php
+++ b/apps/dav/appinfo/v1/publicwebdav.php
@@ -68,7 +68,7 @@ $requestUri = Server::get(IRequest::class)->getRequestUri();
$linkCheckPlugin = new PublicLinkCheckPlugin();
$filesDropPlugin = new FilesDropPlugin();
-$server = $serverFactory->createServer($baseuri, $requestUri, $authPlugin, function (\Sabre\DAV\Server $server) use ($authBackend, $linkCheckPlugin, $filesDropPlugin) {
+$server = $serverFactory->createServer(false, $baseuri, $requestUri, $authPlugin, function (\Sabre\DAV\Server $server) use ($authBackend, $linkCheckPlugin, $filesDropPlugin) {
$isAjax = in_array('XMLHttpRequest', explode(',', $_SERVER['HTTP_X_REQUESTED_WITH'] ?? ''));
/** @var FederatedShareProvider $shareProvider */
$federatedShareProvider = Server::get(FederatedShareProvider::class);
@@ -104,11 +104,9 @@ $server = $serverFactory->createServer($baseuri, $requestUri, $authPlugin, funct
if (!$isReadable) {
$filesDropPlugin->enable();
}
-
- $view = new View($node->getPath());
- $filesDropPlugin->setView($view);
$filesDropPlugin->setShare($share);
+ $view = new View($node->getPath());
return $view;
});
diff --git a/apps/dav/appinfo/v1/webdav.php b/apps/dav/appinfo/v1/webdav.php
index baeae66bb20..92ff55c850e 100644
--- a/apps/dav/appinfo/v1/webdav.php
+++ b/apps/dav/appinfo/v1/webdav.php
@@ -68,7 +68,7 @@ $authPlugin->addBackend($bearerAuthPlugin);
$requestUri = Server::get(IRequest::class)->getRequestUri();
-$server = $serverFactory->createServer($baseuri, $requestUri, $authPlugin, function () {
+$server = $serverFactory->createServer(false, $baseuri, $requestUri, $authPlugin, function () {
// use the view for the logged in user
return Filesystem::getView();
});
diff --git a/apps/dav/appinfo/v2/publicremote.php b/apps/dav/appinfo/v2/publicremote.php
index 27b8716f6ae..e089fa7bb62 100644
--- a/apps/dav/appinfo/v2/publicremote.php
+++ b/apps/dav/appinfo/v2/publicremote.php
@@ -14,18 +14,22 @@ use OCA\DAV\Files\Sharing\FilesDropPlugin;
use OCA\DAV\Files\Sharing\PublicLinkCheckPlugin;
use OCA\DAV\Storage\PublicOwnerWrapper;
use OCA\DAV\Storage\PublicShareWrapper;
+use OCA\DAV\Upload\ChunkingPlugin;
+use OCA\DAV\Upload\ChunkingV2Plugin;
use OCA\FederatedFileSharing\FederatedShareProvider;
use OCP\BeforeSabrePubliclyLoadedEvent;
use OCP\Constants;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\IRootFolder;
use OCP\Files\Mount\IMountManager;
+use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IPreview;
use OCP\IRequest;
use OCP\ISession;
use OCP\ITagManager;
+use OCP\IURLGenerator;
use OCP\IUserSession;
use OCP\L10N\IFactory;
use OCP\Security\Bruteforce\IThrottler;
@@ -53,7 +57,8 @@ $authBackend = new PublicAuth(
Server::get(IManager::class),
$session,
Server::get(IThrottler::class),
- Server::get(LoggerInterface::class)
+ Server::get(LoggerInterface::class),
+ Server::get(IURLGenerator::class),
);
$authPlugin = new \Sabre\DAV\Auth\Plugin($authBackend);
@@ -75,12 +80,8 @@ $serverFactory = new ServerFactory(
$linkCheckPlugin = new PublicLinkCheckPlugin();
$filesDropPlugin = new FilesDropPlugin();
-// Define root url with /public.php/dav/files/TOKEN
/** @var string $baseuri defined in public.php */
-preg_match('/(^files\/[a-z0-9-_]+)/i', substr($requestUri, strlen($baseuri)), $match);
-$baseuri = $baseuri . $match[0];
-
-$server = $serverFactory->createServer($baseuri, $requestUri, $authPlugin, function (\Sabre\DAV\Server $server) use ($authBackend, $linkCheckPlugin, $filesDropPlugin) {
+$server = $serverFactory->createServer(true, $baseuri, $requestUri, $authPlugin, function (\Sabre\DAV\Server $server) use ($authBackend, $linkCheckPlugin, $filesDropPlugin) {
// GET must be allowed for e.g. showing images and allowing Zip downloads
if ($server->httpRequest->getMethod() !== 'GET') {
// If this is *not* a GET request we only allow access to public DAV from AJAX or when Server2Server is allowed
@@ -132,16 +133,16 @@ $server = $serverFactory->createServer($baseuri, $requestUri, $authPlugin, funct
if (!$isReadable) {
$filesDropPlugin->enable();
}
-
- $view = new View($node->getPath());
- $filesDropPlugin->setView($view);
$filesDropPlugin->setShare($share);
+ $view = new View($node->getPath());
return $view;
});
$server->addPlugin($linkCheckPlugin);
$server->addPlugin($filesDropPlugin);
+$server->addPlugin(new ChunkingV2Plugin(Server::get(ICacheFactory::class)));
+$server->addPlugin(new ChunkingPlugin());
// allow setup of additional plugins
$event = new BeforeSabrePubliclyLoadedEvent($server);
diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php
index 71d590f85a9..28dfeaed498 100644
--- a/apps/dav/composer/composer/autoload_classmap.php
+++ b/apps/dav/composer/composer/autoload_classmap.php
@@ -16,6 +16,7 @@ return array(
'OCA\\DAV\\BackgroundJob\\CalendarRetentionJob' => $baseDir . '/../lib/BackgroundJob/CalendarRetentionJob.php',
'OCA\\DAV\\BackgroundJob\\CleanupDirectLinksJob' => $baseDir . '/../lib/BackgroundJob/CleanupDirectLinksJob.php',
'OCA\\DAV\\BackgroundJob\\CleanupInvitationTokenJob' => $baseDir . '/../lib/BackgroundJob/CleanupInvitationTokenJob.php',
+ 'OCA\\DAV\\BackgroundJob\\CleanupOrphanedChildrenJob' => $baseDir . '/../lib/BackgroundJob/CleanupOrphanedChildrenJob.php',
'OCA\\DAV\\BackgroundJob\\DeleteOutdatedSchedulingObjects' => $baseDir . '/../lib/BackgroundJob/DeleteOutdatedSchedulingObjects.php',
'OCA\\DAV\\BackgroundJob\\EventReminderJob' => $baseDir . '/../lib/BackgroundJob/EventReminderJob.php',
'OCA\\DAV\\BackgroundJob\\GenerateBirthdayCalendarBackgroundJob' => $baseDir . '/../lib/BackgroundJob/GenerateBirthdayCalendarBackgroundJob.php',
@@ -63,6 +64,7 @@ return array(
'OCA\\DAV\\CalDAV\\EventReader' => $baseDir . '/../lib/CalDAV/EventReader.php',
'OCA\\DAV\\CalDAV\\EventReaderRDate' => $baseDir . '/../lib/CalDAV/EventReaderRDate.php',
'OCA\\DAV\\CalDAV\\EventReaderRRule' => $baseDir . '/../lib/CalDAV/EventReaderRRule.php',
+ 'OCA\\DAV\\CalDAV\\Export\\ExportService' => $baseDir . '/../lib/CalDAV/Export/ExportService.php',
'OCA\\DAV\\CalDAV\\FreeBusy\\FreeBusyGenerator' => $baseDir . '/../lib/CalDAV/FreeBusy/FreeBusyGenerator.php',
'OCA\\DAV\\CalDAV\\ICSExportPlugin\\ICSExportPlugin' => $baseDir . '/../lib/CalDAV/ICSExportPlugin/ICSExportPlugin.php',
'OCA\\DAV\\CalDAV\\IRestorable' => $baseDir . '/../lib/CalDAV/IRestorable.php',
@@ -153,13 +155,17 @@ return array(
'OCA\\DAV\\CardDAV\\UserAddressBooks' => $baseDir . '/../lib/CardDAV/UserAddressBooks.php',
'OCA\\DAV\\CardDAV\\Validation\\CardDavValidatePlugin' => $baseDir . '/../lib/CardDAV/Validation/CardDavValidatePlugin.php',
'OCA\\DAV\\CardDAV\\Xml\\Groups' => $baseDir . '/../lib/CardDAV/Xml/Groups.php',
+ 'OCA\\DAV\\Command\\ClearCalendarUnshares' => $baseDir . '/../lib/Command/ClearCalendarUnshares.php',
+ 'OCA\\DAV\\Command\\ClearContactsPhotoCache' => $baseDir . '/../lib/Command/ClearContactsPhotoCache.php',
'OCA\\DAV\\Command\\CreateAddressBook' => $baseDir . '/../lib/Command/CreateAddressBook.php',
'OCA\\DAV\\Command\\CreateCalendar' => $baseDir . '/../lib/Command/CreateCalendar.php',
'OCA\\DAV\\Command\\CreateSubscription' => $baseDir . '/../lib/Command/CreateSubscription.php',
'OCA\\DAV\\Command\\DeleteCalendar' => $baseDir . '/../lib/Command/DeleteCalendar.php',
'OCA\\DAV\\Command\\DeleteSubscription' => $baseDir . '/../lib/Command/DeleteSubscription.php',
+ 'OCA\\DAV\\Command\\ExportCalendar' => $baseDir . '/../lib/Command/ExportCalendar.php',
'OCA\\DAV\\Command\\FixCalendarSyncCommand' => $baseDir . '/../lib/Command/FixCalendarSyncCommand.php',
'OCA\\DAV\\Command\\ListAddressbooks' => $baseDir . '/../lib/Command/ListAddressbooks.php',
+ 'OCA\\DAV\\Command\\ListCalendarShares' => $baseDir . '/../lib/Command/ListCalendarShares.php',
'OCA\\DAV\\Command\\ListCalendars' => $baseDir . '/../lib/Command/ListCalendars.php',
'OCA\\DAV\\Command\\ListSubscriptions' => $baseDir . '/../lib/Command/ListSubscriptions.php',
'OCA\\DAV\\Command\\MoveCalendar' => $baseDir . '/../lib/Command/MoveCalendar.php',
@@ -272,6 +278,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\\ExampleEventException' => $baseDir . '/../lib/Exception/ExampleEventException.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',
@@ -281,6 +288,7 @@ return array(
'OCA\\DAV\\Files\\RootCollection' => $baseDir . '/../lib/Files/RootCollection.php',
'OCA\\DAV\\Files\\Sharing\\FilesDropPlugin' => $baseDir . '/../lib/Files/Sharing/FilesDropPlugin.php',
'OCA\\DAV\\Files\\Sharing\\PublicLinkCheckPlugin' => $baseDir . '/../lib/Files/Sharing/PublicLinkCheckPlugin.php',
+ 'OCA\\DAV\\Files\\Sharing\\RootCollection' => $baseDir . '/../lib/Files/Sharing/RootCollection.php',
'OCA\\DAV\\Listener\\ActivityUpdaterListener' => $baseDir . '/../lib/Listener/ActivityUpdaterListener.php',
'OCA\\DAV\\Listener\\AddMissingIndicesListener' => $baseDir . '/../lib/Listener/AddMissingIndicesListener.php',
'OCA\\DAV\\Listener\\AddressbookListener' => $baseDir . '/../lib/Listener/AddressbookListener.php',
@@ -310,6 +318,7 @@ return array(
'OCA\\DAV\\Migration\\RefreshWebcalJobRegistrar' => $baseDir . '/../lib/Migration/RefreshWebcalJobRegistrar.php',
'OCA\\DAV\\Migration\\RegenerateBirthdayCalendars' => $baseDir . '/../lib/Migration/RegenerateBirthdayCalendars.php',
'OCA\\DAV\\Migration\\RegisterBuildReminderIndexBackgroundJob' => $baseDir . '/../lib/Migration/RegisterBuildReminderIndexBackgroundJob.php',
+ 'OCA\\DAV\\Migration\\RegisterUpdateCalendarResourcesRoomBackgroundJob' => $baseDir . '/../lib/Migration/RegisterUpdateCalendarResourcesRoomBackgroundJob.php',
'OCA\\DAV\\Migration\\RemoveClassifiedEventActivity' => $baseDir . '/../lib/Migration/RemoveClassifiedEventActivity.php',
'OCA\\DAV\\Migration\\RemoveDeletedUsersCalendarSubscriptions' => $baseDir . '/../lib/Migration/RemoveDeletedUsersCalendarSubscriptions.php',
'OCA\\DAV\\Migration\\RemoveObjectProperties' => $baseDir . '/../lib/Migration/RemoveObjectProperties.php',
@@ -341,6 +350,7 @@ return array(
'OCA\\DAV\\Migration\\Version1029Date20231004091403' => $baseDir . '/../lib/Migration/Version1029Date20231004091403.php',
'OCA\\DAV\\Migration\\Version1030Date20240205103243' => $baseDir . '/../lib/Migration/Version1030Date20240205103243.php',
'OCA\\DAV\\Migration\\Version1031Date20240610134258' => $baseDir . '/../lib/Migration/Version1031Date20240610134258.php',
+ 'OCA\\DAV\\Model\\ExampleEvent' => $baseDir . '/../lib/Model/ExampleEvent.php',
'OCA\\DAV\\Paginate\\LimitedCopyIterator' => $baseDir . '/../lib/Paginate/LimitedCopyIterator.php',
'OCA\\DAV\\Paginate\\PaginateCache' => $baseDir . '/../lib/Paginate/PaginateCache.php',
'OCA\\DAV\\Paginate\\PaginatePlugin' => $baseDir . '/../lib/Paginate/PaginatePlugin.php',
@@ -356,7 +366,8 @@ 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',
'OCA\\DAV\\Settings\\CalDAVSettings' => $baseDir . '/../lib/Settings/CalDAVSettings.php',
@@ -384,6 +395,7 @@ return array(
'OCA\\DAV\\Upload\\FutureFile' => $baseDir . '/../lib/Upload/FutureFile.php',
'OCA\\DAV\\Upload\\PartFile' => $baseDir . '/../lib/Upload/PartFile.php',
'OCA\\DAV\\Upload\\RootCollection' => $baseDir . '/../lib/Upload/RootCollection.php',
+ 'OCA\\DAV\\Upload\\UploadAutoMkcolPlugin' => $baseDir . '/../lib/Upload/UploadAutoMkcolPlugin.php',
'OCA\\DAV\\Upload\\UploadFile' => $baseDir . '/../lib/Upload/UploadFile.php',
'OCA\\DAV\\Upload\\UploadFolder' => $baseDir . '/../lib/Upload/UploadFolder.php',
'OCA\\DAV\\Upload\\UploadHome' => $baseDir . '/../lib/Upload/UploadHome.php',
diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php
index 9e652acc01e..83661b73a30 100644
--- a/apps/dav/composer/composer/autoload_static.php
+++ b/apps/dav/composer/composer/autoload_static.php
@@ -31,6 +31,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\BackgroundJob\\CalendarRetentionJob' => __DIR__ . '/..' . '/../lib/BackgroundJob/CalendarRetentionJob.php',
'OCA\\DAV\\BackgroundJob\\CleanupDirectLinksJob' => __DIR__ . '/..' . '/../lib/BackgroundJob/CleanupDirectLinksJob.php',
'OCA\\DAV\\BackgroundJob\\CleanupInvitationTokenJob' => __DIR__ . '/..' . '/../lib/BackgroundJob/CleanupInvitationTokenJob.php',
+ 'OCA\\DAV\\BackgroundJob\\CleanupOrphanedChildrenJob' => __DIR__ . '/..' . '/../lib/BackgroundJob/CleanupOrphanedChildrenJob.php',
'OCA\\DAV\\BackgroundJob\\DeleteOutdatedSchedulingObjects' => __DIR__ . '/..' . '/../lib/BackgroundJob/DeleteOutdatedSchedulingObjects.php',
'OCA\\DAV\\BackgroundJob\\EventReminderJob' => __DIR__ . '/..' . '/../lib/BackgroundJob/EventReminderJob.php',
'OCA\\DAV\\BackgroundJob\\GenerateBirthdayCalendarBackgroundJob' => __DIR__ . '/..' . '/../lib/BackgroundJob/GenerateBirthdayCalendarBackgroundJob.php',
@@ -78,6 +79,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\CalDAV\\EventReader' => __DIR__ . '/..' . '/../lib/CalDAV/EventReader.php',
'OCA\\DAV\\CalDAV\\EventReaderRDate' => __DIR__ . '/..' . '/../lib/CalDAV/EventReaderRDate.php',
'OCA\\DAV\\CalDAV\\EventReaderRRule' => __DIR__ . '/..' . '/../lib/CalDAV/EventReaderRRule.php',
+ 'OCA\\DAV\\CalDAV\\Export\\ExportService' => __DIR__ . '/..' . '/../lib/CalDAV/Export/ExportService.php',
'OCA\\DAV\\CalDAV\\FreeBusy\\FreeBusyGenerator' => __DIR__ . '/..' . '/../lib/CalDAV/FreeBusy/FreeBusyGenerator.php',
'OCA\\DAV\\CalDAV\\ICSExportPlugin\\ICSExportPlugin' => __DIR__ . '/..' . '/../lib/CalDAV/ICSExportPlugin/ICSExportPlugin.php',
'OCA\\DAV\\CalDAV\\IRestorable' => __DIR__ . '/..' . '/../lib/CalDAV/IRestorable.php',
@@ -168,13 +170,17 @@ class ComposerStaticInitDAV
'OCA\\DAV\\CardDAV\\UserAddressBooks' => __DIR__ . '/..' . '/../lib/CardDAV/UserAddressBooks.php',
'OCA\\DAV\\CardDAV\\Validation\\CardDavValidatePlugin' => __DIR__ . '/..' . '/../lib/CardDAV/Validation/CardDavValidatePlugin.php',
'OCA\\DAV\\CardDAV\\Xml\\Groups' => __DIR__ . '/..' . '/../lib/CardDAV/Xml/Groups.php',
+ 'OCA\\DAV\\Command\\ClearCalendarUnshares' => __DIR__ . '/..' . '/../lib/Command/ClearCalendarUnshares.php',
+ 'OCA\\DAV\\Command\\ClearContactsPhotoCache' => __DIR__ . '/..' . '/../lib/Command/ClearContactsPhotoCache.php',
'OCA\\DAV\\Command\\CreateAddressBook' => __DIR__ . '/..' . '/../lib/Command/CreateAddressBook.php',
'OCA\\DAV\\Command\\CreateCalendar' => __DIR__ . '/..' . '/../lib/Command/CreateCalendar.php',
'OCA\\DAV\\Command\\CreateSubscription' => __DIR__ . '/..' . '/../lib/Command/CreateSubscription.php',
'OCA\\DAV\\Command\\DeleteCalendar' => __DIR__ . '/..' . '/../lib/Command/DeleteCalendar.php',
'OCA\\DAV\\Command\\DeleteSubscription' => __DIR__ . '/..' . '/../lib/Command/DeleteSubscription.php',
+ 'OCA\\DAV\\Command\\ExportCalendar' => __DIR__ . '/..' . '/../lib/Command/ExportCalendar.php',
'OCA\\DAV\\Command\\FixCalendarSyncCommand' => __DIR__ . '/..' . '/../lib/Command/FixCalendarSyncCommand.php',
'OCA\\DAV\\Command\\ListAddressbooks' => __DIR__ . '/..' . '/../lib/Command/ListAddressbooks.php',
+ 'OCA\\DAV\\Command\\ListCalendarShares' => __DIR__ . '/..' . '/../lib/Command/ListCalendarShares.php',
'OCA\\DAV\\Command\\ListCalendars' => __DIR__ . '/..' . '/../lib/Command/ListCalendars.php',
'OCA\\DAV\\Command\\ListSubscriptions' => __DIR__ . '/..' . '/../lib/Command/ListSubscriptions.php',
'OCA\\DAV\\Command\\MoveCalendar' => __DIR__ . '/..' . '/../lib/Command/MoveCalendar.php',
@@ -287,6 +293,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\\ExampleEventException' => __DIR__ . '/..' . '/../lib/Exception/ExampleEventException.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',
@@ -296,6 +303,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Files\\RootCollection' => __DIR__ . '/..' . '/../lib/Files/RootCollection.php',
'OCA\\DAV\\Files\\Sharing\\FilesDropPlugin' => __DIR__ . '/..' . '/../lib/Files/Sharing/FilesDropPlugin.php',
'OCA\\DAV\\Files\\Sharing\\PublicLinkCheckPlugin' => __DIR__ . '/..' . '/../lib/Files/Sharing/PublicLinkCheckPlugin.php',
+ 'OCA\\DAV\\Files\\Sharing\\RootCollection' => __DIR__ . '/..' . '/../lib/Files/Sharing/RootCollection.php',
'OCA\\DAV\\Listener\\ActivityUpdaterListener' => __DIR__ . '/..' . '/../lib/Listener/ActivityUpdaterListener.php',
'OCA\\DAV\\Listener\\AddMissingIndicesListener' => __DIR__ . '/..' . '/../lib/Listener/AddMissingIndicesListener.php',
'OCA\\DAV\\Listener\\AddressbookListener' => __DIR__ . '/..' . '/../lib/Listener/AddressbookListener.php',
@@ -325,6 +333,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Migration\\RefreshWebcalJobRegistrar' => __DIR__ . '/..' . '/../lib/Migration/RefreshWebcalJobRegistrar.php',
'OCA\\DAV\\Migration\\RegenerateBirthdayCalendars' => __DIR__ . '/..' . '/../lib/Migration/RegenerateBirthdayCalendars.php',
'OCA\\DAV\\Migration\\RegisterBuildReminderIndexBackgroundJob' => __DIR__ . '/..' . '/../lib/Migration/RegisterBuildReminderIndexBackgroundJob.php',
+ 'OCA\\DAV\\Migration\\RegisterUpdateCalendarResourcesRoomBackgroundJob' => __DIR__ . '/..' . '/../lib/Migration/RegisterUpdateCalendarResourcesRoomBackgroundJob.php',
'OCA\\DAV\\Migration\\RemoveClassifiedEventActivity' => __DIR__ . '/..' . '/../lib/Migration/RemoveClassifiedEventActivity.php',
'OCA\\DAV\\Migration\\RemoveDeletedUsersCalendarSubscriptions' => __DIR__ . '/..' . '/../lib/Migration/RemoveDeletedUsersCalendarSubscriptions.php',
'OCA\\DAV\\Migration\\RemoveObjectProperties' => __DIR__ . '/..' . '/../lib/Migration/RemoveObjectProperties.php',
@@ -356,6 +365,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Migration\\Version1029Date20231004091403' => __DIR__ . '/..' . '/../lib/Migration/Version1029Date20231004091403.php',
'OCA\\DAV\\Migration\\Version1030Date20240205103243' => __DIR__ . '/..' . '/../lib/Migration/Version1030Date20240205103243.php',
'OCA\\DAV\\Migration\\Version1031Date20240610134258' => __DIR__ . '/..' . '/../lib/Migration/Version1031Date20240610134258.php',
+ 'OCA\\DAV\\Model\\ExampleEvent' => __DIR__ . '/..' . '/../lib/Model/ExampleEvent.php',
'OCA\\DAV\\Paginate\\LimitedCopyIterator' => __DIR__ . '/..' . '/../lib/Paginate/LimitedCopyIterator.php',
'OCA\\DAV\\Paginate\\PaginateCache' => __DIR__ . '/..' . '/../lib/Paginate/PaginateCache.php',
'OCA\\DAV\\Paginate\\PaginatePlugin' => __DIR__ . '/..' . '/../lib/Paginate/PaginatePlugin.php',
@@ -371,7 +381,8 @@ 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',
'OCA\\DAV\\Settings\\CalDAVSettings' => __DIR__ . '/..' . '/../lib/Settings/CalDAVSettings.php',
@@ -399,6 +410,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Upload\\FutureFile' => __DIR__ . '/..' . '/../lib/Upload/FutureFile.php',
'OCA\\DAV\\Upload\\PartFile' => __DIR__ . '/..' . '/../lib/Upload/PartFile.php',
'OCA\\DAV\\Upload\\RootCollection' => __DIR__ . '/..' . '/../lib/Upload/RootCollection.php',
+ 'OCA\\DAV\\Upload\\UploadAutoMkcolPlugin' => __DIR__ . '/..' . '/../lib/Upload/UploadAutoMkcolPlugin.php',
'OCA\\DAV\\Upload\\UploadFile' => __DIR__ . '/..' . '/../lib/Upload/UploadFile.php',
'OCA\\DAV\\Upload\\UploadFolder' => __DIR__ . '/..' . '/../lib/Upload/UploadFolder.php',
'OCA\\DAV\\Upload\\UploadHome' => __DIR__ . '/..' . '/../lib/Upload/UploadHome.php',
diff --git a/apps/dav/css/schedule-response.css b/apps/dav/css/schedule-response.css
index eef571027c5..85a03cb63e1 100644
--- a/apps/dav/css/schedule-response.css
+++ b/apps/dav/css/schedule-response.css
@@ -56,6 +56,7 @@ form #selectPartStatForm label span {
display: block;
line-height: normal;
}
+
form #selectPartStatForm label.ui-state-hover,
form #selectPartStatForm label.ui-state-active {
color:#000;
diff --git a/apps/dav/l10n/ar.js b/apps/dav/l10n/ar.js
index 53dc3590cde..a058786dd54 100644
--- a/apps/dav/l10n/ar.js
+++ b/apps/dav/l10n/ar.js
@@ -290,6 +290,17 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "إختَر وقت البدء ليوم {dayName}",
"Pick a end time for {dayName}" : "إختَر وقت الانتهاء ليوم {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "قم بتعيين حالة المستخدم تلقائيًا على \"عدم الإزعاج\" خارج نطاق أوقات التواجد لكتم جميع الإشعارات",
+ "Cancel" : "إلغاء",
+ "Import" : "إستيراد",
+ "Error while saving settings" : "خطأ أثناء حفظ الإعدادات",
+ "Contact reset successfully" : "تمّت إعادة تعيين جهة الاتصال بنجاحٍ",
+ "Error while resetting contact" : "خطأ أثناء إعادة تعيين جهة الاتصال",
+ "Contact imported successfully" : "تمّ استيراد جهة الاتصال بنجاحٍ",
+ "Error while importing contact" : "خطأ أثناء استيراد جهة الاتصال",
+ "Import contact" : "استيراد جهة اتصال",
+ "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?" : "استيراد ملف .cvf جديد سوف يؤدي إلى حذف جهات الاتصال التلقائية الحالية واستبدالها بالجديدة. هل ترغب في الاستمرار؟",
"Availability" : "أوقات التواجد ",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "إذا قمت بضبط ساعات عملك، سيرى الآخرون متى تكون خارج المكتب عندما يقومون بحجز اجتماع معك.",
"Absence" : "غياب",
@@ -306,27 +317,10 @@ 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" : "تمكين الإشعارات حول الأحداث عن طريق أسلوب دفع الإشعارات Push",
- "Cancel" : "إلغاء",
- "Import" : "إستيراد",
- "Error while saving settings" : "خطأ أثناء حفظ الإعدادات",
- "Contact reset successfully" : "تمّت إعادة تعيين جهة الاتصال بنجاحٍ",
- "Error while resetting contact" : "خطأ أثناء إعادة تعيين جهة الاتصال",
- "Contact imported successfully" : "تمّ استيراد جهة الاتصال بنجاحٍ",
- "Error while importing contact" : "خطأ أثناء استيراد جهة الاتصال",
- "Example Content" : "نموذج للمحتوى",
- "Set example content to be created on new user first login." : "عيِّن نموذجاً للمحتوى ليتم إنشاؤه عند تسجيل المستخدِم دخوله لأول مرةٍ.",
- "Import contact" : "استيراد جهة اتصال",
- "Reset to default contact" : "إعادة التعيين لجهة اتصال تلقائية ",
- "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?" : "استيراد ملف .cvf جديد سوف يؤدي إلى حذف جهات الاتصال التلقائية الحالية واستبدالها بالجديدة. هل ترغب في الاستمرار؟",
"There was an error updating your attendance status." : "حدث خطأ في تحديث حالة حضورك.",
"Please contact the organizer directly." : "يرجى الاتصال بالمنظم مباشرةً",
"Are you accepting the invitation?" : "هل تقبل الدعوة؟",
"Tentative" : "مبدئي",
- "Your attendance was updated successfully." : "حضورك تم تحديثه بنجاحٍ",
- "Time:" : "الوقت:",
- "Could not open file" : "تعذّر فتح الملف",
- "Invalid chunk name" : "اسم كتلة chunk غير صحيح",
- "Could not rename part file assembled from chunks" : "تعذّرت إعادة تسمية ملف جزئي مُجمّعٍ من كُتلٍ chunks"
+ "Your attendance was updated successfully." : "حضورك تم تحديثه بنجاحٍ"
},
"nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;");
diff --git a/apps/dav/l10n/ar.json b/apps/dav/l10n/ar.json
index 34884cde46a..212dc54ee03 100644
--- a/apps/dav/l10n/ar.json
+++ b/apps/dav/l10n/ar.json
@@ -288,6 +288,17 @@
"Pick a start time for {dayName}" : "إختَر وقت البدء ليوم {dayName}",
"Pick a end time for {dayName}" : "إختَر وقت الانتهاء ليوم {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "قم بتعيين حالة المستخدم تلقائيًا على \"عدم الإزعاج\" خارج نطاق أوقات التواجد لكتم جميع الإشعارات",
+ "Cancel" : "إلغاء",
+ "Import" : "إستيراد",
+ "Error while saving settings" : "خطأ أثناء حفظ الإعدادات",
+ "Contact reset successfully" : "تمّت إعادة تعيين جهة الاتصال بنجاحٍ",
+ "Error while resetting contact" : "خطأ أثناء إعادة تعيين جهة الاتصال",
+ "Contact imported successfully" : "تمّ استيراد جهة الاتصال بنجاحٍ",
+ "Error while importing contact" : "خطأ أثناء استيراد جهة الاتصال",
+ "Import contact" : "استيراد جهة اتصال",
+ "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?" : "استيراد ملف .cvf جديد سوف يؤدي إلى حذف جهات الاتصال التلقائية الحالية واستبدالها بالجديدة. هل ترغب في الاستمرار؟",
"Availability" : "أوقات التواجد ",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "إذا قمت بضبط ساعات عملك، سيرى الآخرون متى تكون خارج المكتب عندما يقومون بحجز اجتماع معك.",
"Absence" : "غياب",
@@ -304,27 +315,10 @@
"Send reminder notifications to calendar sharees as well" : "أرسل إشعارات للتذكير إلى المشتركين بالتقويم كذلك",
"Reminders are always sent to organizers and attendees." : "إشعارات التذكير يتم إرسالها دائماً إلى مُنظّم أو مُنظّمي الحدث و المستهدفين بحضوره.",
"Enable notifications for events via push" : "تمكين الإشعارات حول الأحداث عن طريق أسلوب دفع الإشعارات Push",
- "Cancel" : "إلغاء",
- "Import" : "إستيراد",
- "Error while saving settings" : "خطأ أثناء حفظ الإعدادات",
- "Contact reset successfully" : "تمّت إعادة تعيين جهة الاتصال بنجاحٍ",
- "Error while resetting contact" : "خطأ أثناء إعادة تعيين جهة الاتصال",
- "Contact imported successfully" : "تمّ استيراد جهة الاتصال بنجاحٍ",
- "Error while importing contact" : "خطأ أثناء استيراد جهة الاتصال",
- "Example Content" : "نموذج للمحتوى",
- "Set example content to be created on new user first login." : "عيِّن نموذجاً للمحتوى ليتم إنشاؤه عند تسجيل المستخدِم دخوله لأول مرةٍ.",
- "Import contact" : "استيراد جهة اتصال",
- "Reset to default contact" : "إعادة التعيين لجهة اتصال تلقائية ",
- "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?" : "استيراد ملف .cvf جديد سوف يؤدي إلى حذف جهات الاتصال التلقائية الحالية واستبدالها بالجديدة. هل ترغب في الاستمرار؟",
"There was an error updating your attendance status." : "حدث خطأ في تحديث حالة حضورك.",
"Please contact the organizer directly." : "يرجى الاتصال بالمنظم مباشرةً",
"Are you accepting the invitation?" : "هل تقبل الدعوة؟",
"Tentative" : "مبدئي",
- "Your attendance was updated successfully." : "حضورك تم تحديثه بنجاحٍ",
- "Time:" : "الوقت:",
- "Could not open file" : "تعذّر فتح الملف",
- "Invalid chunk name" : "اسم كتلة chunk غير صحيح",
- "Could not rename part file assembled from chunks" : "تعذّرت إعادة تسمية ملف جزئي مُجمّعٍ من كُتلٍ chunks"
+ "Your attendance was updated successfully." : "حضورك تم تحديثه بنجاحٍ"
},"pluralForm" :"nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;"
} \ No newline at end of file
diff --git a/apps/dav/l10n/ast.js b/apps/dav/l10n/ast.js
index a75c384f6b5..b0cba5d934f 100644
--- a/apps/dav/l10n/ast.js
+++ b/apps/dav/l10n/ast.js
@@ -195,6 +195,10 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Escueyi una hora de comienzu pal {dayName}",
"Pick a end time for {dayName}" : "Escueyi una hora de fin pal {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Afitar automáticamente l'estáu a «Nun molestar» fuera de la disponibilidá pa desactivar tolos avisos.",
+ "Cancel" : "Encaboxar",
+ "Import" : "Importa",
+ "Error while saving settings" : "Hebo un error mentanto se guardaba la configuración",
+ "Reset to default" : "Reafitar los valores",
"Availability" : "Disponibilidá",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Si configures les hores llaborales, les demás persones van ver cuando coles de la oficina al acutar una reunión.",
"Absence" : "Ausencia",
@@ -211,17 +215,10 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Unvia tamién avisos de recordatoriu pa les persones coles que se compartiere'l calendariu",
"Reminders are always sent to organizers and attendees." : "Los recordatorios únviense siempres a organizadores y asistentes",
"Enable notifications for events via push" : "Acriva los avisos automáticos pa los eventos",
- "Cancel" : "Encaboxar",
- "Import" : "Importa",
- "Error while saving settings" : "Hebo un error mentanto se guardaba la configuración",
"There was an error updating your attendance status." : "Hebo un error al anovar l'estáu de l'asistencia.",
"Please contact the organizer directly." : "Ponte en contautu direutamente cola organización.",
"Are you accepting the invitation?" : "¿Aceptes la invitación?",
"Tentative" : "Provisional",
- "Your attendance was updated successfully." : "La to asistencia anovóse correutamente.",
- "Time:" : "Hora:",
- "Could not open file" : "Nun se pudo abrir el ficheru",
- "Invalid chunk name" : "El nome del cachu ye inválidu",
- "Could not rename part file assembled from chunks" : "Nun se pudo renomar el ficheru parcial ensambláu de los cachos"
+ "Your attendance was updated successfully." : "La to asistencia anovóse correutamente."
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/ast.json b/apps/dav/l10n/ast.json
index 584b58f5b1a..519aa700951 100644
--- a/apps/dav/l10n/ast.json
+++ b/apps/dav/l10n/ast.json
@@ -193,6 +193,10 @@
"Pick a start time for {dayName}" : "Escueyi una hora de comienzu pal {dayName}",
"Pick a end time for {dayName}" : "Escueyi una hora de fin pal {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Afitar automáticamente l'estáu a «Nun molestar» fuera de la disponibilidá pa desactivar tolos avisos.",
+ "Cancel" : "Encaboxar",
+ "Import" : "Importa",
+ "Error while saving settings" : "Hebo un error mentanto se guardaba la configuración",
+ "Reset to default" : "Reafitar los valores",
"Availability" : "Disponibilidá",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Si configures les hores llaborales, les demás persones van ver cuando coles de la oficina al acutar una reunión.",
"Absence" : "Ausencia",
@@ -209,17 +213,10 @@
"Send reminder notifications to calendar sharees as well" : "Unvia tamién avisos de recordatoriu pa les persones coles que se compartiere'l calendariu",
"Reminders are always sent to organizers and attendees." : "Los recordatorios únviense siempres a organizadores y asistentes",
"Enable notifications for events via push" : "Acriva los avisos automáticos pa los eventos",
- "Cancel" : "Encaboxar",
- "Import" : "Importa",
- "Error while saving settings" : "Hebo un error mentanto se guardaba la configuración",
"There was an error updating your attendance status." : "Hebo un error al anovar l'estáu de l'asistencia.",
"Please contact the organizer directly." : "Ponte en contautu direutamente cola organización.",
"Are you accepting the invitation?" : "¿Aceptes la invitación?",
"Tentative" : "Provisional",
- "Your attendance was updated successfully." : "La to asistencia anovóse correutamente.",
- "Time:" : "Hora:",
- "Could not open file" : "Nun se pudo abrir el ficheru",
- "Invalid chunk name" : "El nome del cachu ye inválidu",
- "Could not rename part file assembled from chunks" : "Nun se pudo renomar el ficheru parcial ensambláu de los cachos"
+ "Your attendance was updated successfully." : "La to asistencia anovóse correutamente."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/bg.js b/apps/dav/l10n/bg.js
index ad4ae1539aa..d8d27bc7d4b 100644
--- a/apps/dav/l10n/bg.js
+++ b/apps/dav/l10n/bg.js
@@ -138,6 +138,7 @@ 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>contact</strong> или <strong>address book</strong> са променени",
+ "Accounts" : "Профили",
"File is not updatable: %1$s" : "Файлът не подлежи на актуализиране: %1$s",
"Could not write to final file, canceled by hook" : "Не можа да се запише в крайния файл, анулирано от кука",
"Could not write file contents" : "Съдържанието на файла не можа да се запише",
@@ -168,8 +169,16 @@ OC.L10N.register(
"Calendars including events, details and attendees" : "Календари, включително събития, подробности и участници",
"Contacts and groups" : "Контакти и групи",
"WebDAV" : "WebDAV",
+ "Absence saved" : "Отсъствието е запаметено",
+ "Failed to save your absence settings" : "Неуспешно запаметяване на настройките за отсъствие",
+ "Absence cleared" : "Отсъствието е изчистено",
+ "Failed to clear your absence settings" : "Неуспешно изчистване на настройките за отсъствие",
"First day" : "Първи ден",
+ "Last day (inclusive)" : "До (включително)",
+ "Short absence status" : "Кратко описание за периода на отсъствие",
+ "Long absence Message" : "Съобщение, използвано за периода на отсъствие.",
"Save" : "Запазване",
+ "Disable absence" : "Изключи известието за отсъствие",
"Failed to load availability" : "Неуспешно зареждане на наличност",
"Saved availability" : "Запазена наличност",
"Failed to save availability" : "Неуспешно записване на наличност",
@@ -179,7 +188,13 @@ OC.L10N.register(
"No working hours set" : "Няма зададено работно време",
"Add slot" : "Добавяне на слот",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Автоматично задаване на потребителският статус на „Не безпокойте“ извън достъпността, за заглушаване на всички известия.",
- "Availability" : "Наличност",
+ "Cancel" : "Отказ",
+ "Import" : "Импортиране /внасяне/",
+ "Error while saving settings" : "Грешка при запазване на настройките",
+ "Reset to default" : "Настройки по подразбиране",
+ "Availability" : "Работно време",
+ "Absence" : "Отсъствия",
+ "Configure your next absence period." : "Задай своето съобщение за отсъствие.",
"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" : "Сървър на календар",
@@ -192,17 +207,10 @@ 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" : "Активиране на известията за събития чрез push",
- "Cancel" : "Отказ",
- "Import" : "Импортиране /внасяне/",
- "Error while saving settings" : "Грешка при запазване на настройките",
"There was an error updating your attendance status." : "Възникна грешка при актуализиране на състоянието на присъствието Ви.",
"Please contact the organizer directly." : "Моля, свържете се директно с организатора.",
"Are you accepting the invitation?" : "Приемате ли поканата?",
"Tentative" : "Несигурно",
- "Your attendance was updated successfully." : "Вашето присъствие е актуализирано успешно.",
- "Time:" : "Час:",
- "Could not open file" : "Файлът не можа да се отвори",
- "Invalid chunk name" : "Невалидно име на блок",
- "Could not rename part file assembled from chunks" : "Не можа да се преименува частичен файл, сглобен от блок"
+ "Your attendance was updated successfully." : "Вашето присъствие е актуализирано успешно."
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/bg.json b/apps/dav/l10n/bg.json
index 075e9d18d7a..6ebc3b0f6ab 100644
--- a/apps/dav/l10n/bg.json
+++ b/apps/dav/l10n/bg.json
@@ -136,6 +136,7 @@
"{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>contact</strong> или <strong>address book</strong> са променени",
+ "Accounts" : "Профили",
"File is not updatable: %1$s" : "Файлът не подлежи на актуализиране: %1$s",
"Could not write to final file, canceled by hook" : "Не можа да се запише в крайния файл, анулирано от кука",
"Could not write file contents" : "Съдържанието на файла не можа да се запише",
@@ -166,8 +167,16 @@
"Calendars including events, details and attendees" : "Календари, включително събития, подробности и участници",
"Contacts and groups" : "Контакти и групи",
"WebDAV" : "WebDAV",
+ "Absence saved" : "Отсъствието е запаметено",
+ "Failed to save your absence settings" : "Неуспешно запаметяване на настройките за отсъствие",
+ "Absence cleared" : "Отсъствието е изчистено",
+ "Failed to clear your absence settings" : "Неуспешно изчистване на настройките за отсъствие",
"First day" : "Първи ден",
+ "Last day (inclusive)" : "До (включително)",
+ "Short absence status" : "Кратко описание за периода на отсъствие",
+ "Long absence Message" : "Съобщение, използвано за периода на отсъствие.",
"Save" : "Запазване",
+ "Disable absence" : "Изключи известието за отсъствие",
"Failed to load availability" : "Неуспешно зареждане на наличност",
"Saved availability" : "Запазена наличност",
"Failed to save availability" : "Неуспешно записване на наличност",
@@ -177,7 +186,13 @@
"No working hours set" : "Няма зададено работно време",
"Add slot" : "Добавяне на слот",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Автоматично задаване на потребителският статус на „Не безпокойте“ извън достъпността, за заглушаване на всички известия.",
- "Availability" : "Наличност",
+ "Cancel" : "Отказ",
+ "Import" : "Импортиране /внасяне/",
+ "Error while saving settings" : "Грешка при запазване на настройките",
+ "Reset to default" : "Настройки по подразбиране",
+ "Availability" : "Работно време",
+ "Absence" : "Отсъствия",
+ "Configure your next absence period." : "Задай своето съобщение за отсъствие.",
"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" : "Сървър на календар",
@@ -190,17 +205,10 @@
"Send reminder notifications to calendar sharees as well" : "Изпращане на известия за напомняния и до споделящите календар",
"Reminders are always sent to organizers and attendees." : "Напомнянията винаги се изпращат до организаторите и присъстващите.",
"Enable notifications for events via push" : "Активиране на известията за събития чрез push",
- "Cancel" : "Отказ",
- "Import" : "Импортиране /внасяне/",
- "Error while saving settings" : "Грешка при запазване на настройките",
"There was an error updating your attendance status." : "Възникна грешка при актуализиране на състоянието на присъствието Ви.",
"Please contact the organizer directly." : "Моля, свържете се директно с организатора.",
"Are you accepting the invitation?" : "Приемате ли поканата?",
"Tentative" : "Несигурно",
- "Your attendance was updated successfully." : "Вашето присъствие е актуализирано успешно.",
- "Time:" : "Час:",
- "Could not open file" : "Файлът не можа да се отвори",
- "Invalid chunk name" : "Невалидно име на блок",
- "Could not rename part file assembled from chunks" : "Не можа да се преименува частичен файл, сглобен от блок"
+ "Your attendance was updated successfully." : "Вашето присъствие е актуализирано успешно."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/ca.js b/apps/dav/l10n/ca.js
index 047c3e0c6c2..6ed5523a0e5 100644
--- a/apps/dav/l10n/ca.js
+++ b/apps/dav/l10n/ca.js
@@ -290,6 +290,10 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Trieu una hora d'inici per a {dayName}",
"Pick a end time for {dayName}" : "Trieu una hora de finalització per a {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Estableix automàticament l'estat de l'usuari com a \"No molesteu” fora de la disponibilitat per a silenciar totes les notificacions.",
+ "Cancel" : "Cancel·la",
+ "Import" : "Importa",
+ "Error while saving settings" : "S'ha produït un error en desar els paràmetres",
+ "Reset to default" : "Reinicialitza els valors per defecte",
"Availability" : "Disponibilitat",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Si configureu el vostre horari laboral, la resta de persones veuran quan sou fora de l'oficina quan planifiquin una reunió.",
"Absence" : "Absència",
@@ -306,17 +310,10 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Envia també notificacions de recordatori als usuaris amb qui s'ha compartit el calendari",
"Reminders are always sent to organizers and attendees." : "Sempre s'envien recordatoris als organitzadors i als assistents.",
"Enable notifications for events via push" : "Habilita les notificacions automàtiques per als esdeveniments",
- "Cancel" : "Cancel·la",
- "Import" : "Importa",
- "Error while saving settings" : "S'ha produït un error en desar els paràmetres",
"There was an error updating your attendance status." : "S'ha produït un error en actualitzar l'estat d'assistència.",
"Please contact the organizer directly." : "Contacteu amb l'organització directament.",
"Are you accepting the invitation?" : "Accepteu la invitació?",
"Tentative" : "Provisional",
- "Your attendance was updated successfully." : "S'ha actualitzat correctament l'assistència.",
- "Time:" : "Hora:",
- "Could not open file" : "No s'ha pogut obrir el fitxer",
- "Invalid chunk name" : "El nom del fragment no és vàlid",
- "Could not rename part file assembled from chunks" : "No s'ha pogut canviar el nom del fitxer de part muntat a partir de fragments"
+ "Your attendance was updated successfully." : "S'ha actualitzat correctament l'assistència."
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/ca.json b/apps/dav/l10n/ca.json
index 94d94ed7523..88cb071325a 100644
--- a/apps/dav/l10n/ca.json
+++ b/apps/dav/l10n/ca.json
@@ -288,6 +288,10 @@
"Pick a start time for {dayName}" : "Trieu una hora d'inici per a {dayName}",
"Pick a end time for {dayName}" : "Trieu una hora de finalització per a {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Estableix automàticament l'estat de l'usuari com a \"No molesteu” fora de la disponibilitat per a silenciar totes les notificacions.",
+ "Cancel" : "Cancel·la",
+ "Import" : "Importa",
+ "Error while saving settings" : "S'ha produït un error en desar els paràmetres",
+ "Reset to default" : "Reinicialitza els valors per defecte",
"Availability" : "Disponibilitat",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Si configureu el vostre horari laboral, la resta de persones veuran quan sou fora de l'oficina quan planifiquin una reunió.",
"Absence" : "Absència",
@@ -304,17 +308,10 @@
"Send reminder notifications to calendar sharees as well" : "Envia també notificacions de recordatori als usuaris amb qui s'ha compartit el calendari",
"Reminders are always sent to organizers and attendees." : "Sempre s'envien recordatoris als organitzadors i als assistents.",
"Enable notifications for events via push" : "Habilita les notificacions automàtiques per als esdeveniments",
- "Cancel" : "Cancel·la",
- "Import" : "Importa",
- "Error while saving settings" : "S'ha produït un error en desar els paràmetres",
"There was an error updating your attendance status." : "S'ha produït un error en actualitzar l'estat d'assistència.",
"Please contact the organizer directly." : "Contacteu amb l'organització directament.",
"Are you accepting the invitation?" : "Accepteu la invitació?",
"Tentative" : "Provisional",
- "Your attendance was updated successfully." : "S'ha actualitzat correctament l'assistència.",
- "Time:" : "Hora:",
- "Could not open file" : "No s'ha pogut obrir el fitxer",
- "Invalid chunk name" : "El nom del fragment no és vàlid",
- "Could not rename part file assembled from chunks" : "No s'ha pogut canviar el nom del fitxer de part muntat a partir de fragments"
+ "Your attendance was updated successfully." : "S'ha actualitzat correctament l'assistència."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/cs.js b/apps/dav/l10n/cs.js
index ce5b1b83203..c2d10ac429d 100644
--- a/apps/dav/l10n/cs.js
+++ b/apps/dav/l10n/cs.js
@@ -290,6 +290,25 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Vyberte začátek pro {dayName}",
"Pick a end time for {dayName}" : "Vyberte konec pro {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "V době, kdy není k dispozici, automaticky nastavit stav uživatele na „Nerušit“ a ztlumit tak veškerá upozornění.",
+ "Cancel" : "Storno",
+ "Import" : "Naimportovat",
+ "Error while saving settings" : "Chyba při ukládání nastavení",
+ "Contact reset successfully" : "Kontakt úspěšně resetován",
+ "Error while resetting contact" : "Chyba při resetování kontaktu",
+ "Contact imported successfully" : "Kontakt úspěšně naimportován",
+ "Error while importing contact" : "Chyba při importování kontaktu",
+ "Import contact" : "Importovat kontakt",
+ "Reset to default" : "Vrátit zpět na výchozí hodnoty",
+ "Import contacts" : "Importovat kontakty",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Naimportování nového .vcf souboru smaže stávající výchozí kontakt a nahradí ho novým. Chcete pokračovat?",
+ "Failed to save example event creation setting" : "Nepodařilo se uložit nastavení vytváření události pro ukázku",
+ "Failed to upload the example event" : "Nepodařilo se nahrát událost pro ukázku",
+ "Custom example event was saved successfully" : "Uživatelsky určená událost pro ukázku byla úspěšně uložena",
+ "Failed to delete the custom example event" : "Nepodařilo se smazat uživatelsky určenou událost pro ukázku",
+ "Custom example event was deleted successfully" : "Uživatelsky určená událost pro ukázku byla úspěšně smazána",
+ "Import calendar event" : "Naimportovat událost kalendáře",
+ "Uploading a new event will overwrite the existing one." : "Nahrání nové události přepíše tu existující.",
+ "Upload event" : "Nahrát událost",
"Availability" : "Dostupnost",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Když sem zadáte svou pracovní dobu, ostatní lidé při rezervování schůzky uvidí, kdy jste mimo kancelář.",
"Absence" : "Nepřítomnost",
@@ -306,27 +325,12 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Poslat připomínky také těm, kteří mají tento sdílený kalendář připojený",
"Reminders are always sent to organizers and attendees." : "Připomínky jsou vždy poslány organizátorům a účastníkům.",
"Enable notifications for events via push" : "Upozorňovat na události prostřednictvím služby push",
- "Cancel" : "Storno",
- "Import" : "Naimportovat",
- "Error while saving settings" : "Chyba při ukládání nastavení",
- "Contact reset successfully" : "Kontakt úspěšně resetován",
- "Error while resetting contact" : "Chyba při resetování kontaktu",
- "Contact imported successfully" : "Kontakt úspěšně naimportován",
- "Error while importing contact" : "Chyba při importování kontaktu",
- "Example Content" : "Obsah pro ukázku",
- "Set example content to be created on new user first login." : "Nastavit obsah pro ukázku, který vytvořit při prvním přihlášení nového uživatele.",
- "Import contact" : "Importovat kontakt",
- "Reset to default contact" : "Vrátit na výchozí kontakt",
- "Import contacts" : "Importovat kontakty",
- "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Naimportování nového .vcf souboru smaže stávající výchozí kontakt a nahradí ho novým. Chcete pokračovat?",
+ "Example content" : "Obsah pro ukázku",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Obsah pro ukázku slouží pro předvedení funkcí Nextcloud. Výchozí obsah je dodáván s Nextcloud a je možné ho nahradit uživatelsky určeným.",
"There was an error updating your attendance status." : "Vyskytla se chyba při aktualizaci vašeho stavu účasti.",
"Please contact the organizer directly." : "Kontaktujte organizátora přímo.",
"Are you accepting the invitation?" : "Přijímáte pozvání?",
"Tentative" : "Nezávazně",
- "Your attendance was updated successfully." : "Vaše účast byla úspěšně aktualizována.",
- "Time:" : "Čas:",
- "Could not open file" : "Nedaří se otevřít soubor",
- "Invalid chunk name" : "Neplatný název pro shluk (chunk)",
- "Could not rename part file assembled from chunks" : "Nedaří se přejmenovat částečný soubor složený ze shluků"
+ "Your attendance was updated successfully." : "Vaše účast byla úspěšně aktualizována."
},
"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;");
diff --git a/apps/dav/l10n/cs.json b/apps/dav/l10n/cs.json
index 0355b986132..69be44bbd4e 100644
--- a/apps/dav/l10n/cs.json
+++ b/apps/dav/l10n/cs.json
@@ -288,6 +288,25 @@
"Pick a start time for {dayName}" : "Vyberte začátek pro {dayName}",
"Pick a end time for {dayName}" : "Vyberte konec pro {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "V době, kdy není k dispozici, automaticky nastavit stav uživatele na „Nerušit“ a ztlumit tak veškerá upozornění.",
+ "Cancel" : "Storno",
+ "Import" : "Naimportovat",
+ "Error while saving settings" : "Chyba při ukládání nastavení",
+ "Contact reset successfully" : "Kontakt úspěšně resetován",
+ "Error while resetting contact" : "Chyba při resetování kontaktu",
+ "Contact imported successfully" : "Kontakt úspěšně naimportován",
+ "Error while importing contact" : "Chyba při importování kontaktu",
+ "Import contact" : "Importovat kontakt",
+ "Reset to default" : "Vrátit zpět na výchozí hodnoty",
+ "Import contacts" : "Importovat kontakty",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Naimportování nového .vcf souboru smaže stávající výchozí kontakt a nahradí ho novým. Chcete pokračovat?",
+ "Failed to save example event creation setting" : "Nepodařilo se uložit nastavení vytváření události pro ukázku",
+ "Failed to upload the example event" : "Nepodařilo se nahrát událost pro ukázku",
+ "Custom example event was saved successfully" : "Uživatelsky určená událost pro ukázku byla úspěšně uložena",
+ "Failed to delete the custom example event" : "Nepodařilo se smazat uživatelsky určenou událost pro ukázku",
+ "Custom example event was deleted successfully" : "Uživatelsky určená událost pro ukázku byla úspěšně smazána",
+ "Import calendar event" : "Naimportovat událost kalendáře",
+ "Uploading a new event will overwrite the existing one." : "Nahrání nové události přepíše tu existující.",
+ "Upload event" : "Nahrát událost",
"Availability" : "Dostupnost",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Když sem zadáte svou pracovní dobu, ostatní lidé při rezervování schůzky uvidí, kdy jste mimo kancelář.",
"Absence" : "Nepřítomnost",
@@ -304,27 +323,12 @@
"Send reminder notifications to calendar sharees as well" : "Poslat připomínky také těm, kteří mají tento sdílený kalendář připojený",
"Reminders are always sent to organizers and attendees." : "Připomínky jsou vždy poslány organizátorům a účastníkům.",
"Enable notifications for events via push" : "Upozorňovat na události prostřednictvím služby push",
- "Cancel" : "Storno",
- "Import" : "Naimportovat",
- "Error while saving settings" : "Chyba při ukládání nastavení",
- "Contact reset successfully" : "Kontakt úspěšně resetován",
- "Error while resetting contact" : "Chyba při resetování kontaktu",
- "Contact imported successfully" : "Kontakt úspěšně naimportován",
- "Error while importing contact" : "Chyba při importování kontaktu",
- "Example Content" : "Obsah pro ukázku",
- "Set example content to be created on new user first login." : "Nastavit obsah pro ukázku, který vytvořit při prvním přihlášení nového uživatele.",
- "Import contact" : "Importovat kontakt",
- "Reset to default contact" : "Vrátit na výchozí kontakt",
- "Import contacts" : "Importovat kontakty",
- "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Naimportování nového .vcf souboru smaže stávající výchozí kontakt a nahradí ho novým. Chcete pokračovat?",
+ "Example content" : "Obsah pro ukázku",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Obsah pro ukázku slouží pro předvedení funkcí Nextcloud. Výchozí obsah je dodáván s Nextcloud a je možné ho nahradit uživatelsky určeným.",
"There was an error updating your attendance status." : "Vyskytla se chyba při aktualizaci vašeho stavu účasti.",
"Please contact the organizer directly." : "Kontaktujte organizátora přímo.",
"Are you accepting the invitation?" : "Přijímáte pozvání?",
"Tentative" : "Nezávazně",
- "Your attendance was updated successfully." : "Vaše účast byla úspěšně aktualizována.",
- "Time:" : "Čas:",
- "Could not open file" : "Nedaří se otevřít soubor",
- "Invalid chunk name" : "Neplatný název pro shluk (chunk)",
- "Could not rename part file assembled from chunks" : "Nedaří se přejmenovat částečný soubor složený ze shluků"
+ "Your attendance was updated successfully." : "Vaše účast byla úspěšně aktualizována."
},"pluralForm" :"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;"
} \ No newline at end of file
diff --git a/apps/dav/l10n/da.js b/apps/dav/l10n/da.js
index a6a2bdbe29b..782f0a3b21b 100644
--- a/apps/dav/l10n/da.js
+++ b/apps/dav/l10n/da.js
@@ -290,6 +290,17 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Vælg et starttidspunkt for {dayName}",
"Pick a end time for {dayName}" : "Vælg et sluttidspunkt for {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Indstil automatisk brugerstatus til \"Forstyr ikke\" uden for tilgængelighed for at slå alle notifikationer fra.",
+ "Cancel" : "Annuller",
+ "Import" : "Importér",
+ "Error while saving settings" : "Der opstod en fejl under lagring af indstillinger",
+ "Contact reset successfully" : "Kontakten blev nulstillet",
+ "Error while resetting contact" : "Fejl under nulstilling af kontakt",
+ "Contact imported successfully" : "Kontakten blev importeret",
+ "Error while importing contact" : "Fejl under import af kontakt",
+ "Import contact" : "Importér kontakt",
+ "Reset to default" : "Nulstil",
+ "Import contacts" : "Importér kontakter",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Import af en ny .vcf-fil vil slette den eksisterende standardkontakt og erstatte den med den nye. Vil du fortsætte?",
"Availability" : "tilgængelighed",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Hvis du konfigurerer dine arbejdstider, vil andre se, når du er fraværende, når de booker et møde.",
"Absence" : "Fravær",
@@ -306,27 +317,10 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Send også påmindelsesmeddelelser til kalenderdelinger",
"Reminders are always sent to organizers and attendees." : "Påmindelser sendes altid til arrangører og deltagere.",
"Enable notifications for events via push" : "Aktiver notifikationer for begivenheder via push",
- "Cancel" : "Annuller",
- "Import" : "Importer",
- "Error while saving settings" : "Der opstod en fejl under lagring af indstillinger",
- "Contact reset successfully" : "Kontakten blev nulstillet",
- "Error while resetting contact" : "Fejl under nulstilling af kontakt",
- "Contact imported successfully" : "Kontakten blev importeret",
- "Error while importing contact" : "Fejl under import af kontakt",
- "Example Content" : "Eksempelindhold",
- "Set example content to be created on new user first login." : "Indstil eksempel på indhold, der skal oprettes ved ny brugers første login.",
- "Import contact" : "Importér kontakt",
- "Reset to default contact" : "Nulstil til standardkontakt",
- "Import contacts" : "Importér kontakter",
- "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Import af en ny .vcf-fil vil slette den eksisterende standardkontakt og erstatte den med den nye. Vil du fortsætte?",
"There was an error updating your attendance status." : "Der opstod en fejl under opdatering af din fremmødestatus.",
"Please contact the organizer directly." : "Kontakt venligst arrangøren direkte.",
"Are you accepting the invitation?" : "Accepter du invitationen?",
"Tentative" : "Foreløbig",
- "Your attendance was updated successfully." : "Dit tilstedeværelse blev opdateret.",
- "Time:" : "Tid:",
- "Could not open file" : "Kunne ikke åbne fil",
- "Invalid chunk name" : "Ugyldigt stykke navn",
- "Could not rename part file assembled from chunks" : "Kunne ikke omdøbe delfilen samlet fra stykker"
+ "Your attendance was updated successfully." : "Dit tilstedeværelse blev opdateret."
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/da.json b/apps/dav/l10n/da.json
index 0fc9cb3690d..1007a84bb10 100644
--- a/apps/dav/l10n/da.json
+++ b/apps/dav/l10n/da.json
@@ -288,6 +288,17 @@
"Pick a start time for {dayName}" : "Vælg et starttidspunkt for {dayName}",
"Pick a end time for {dayName}" : "Vælg et sluttidspunkt for {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Indstil automatisk brugerstatus til \"Forstyr ikke\" uden for tilgængelighed for at slå alle notifikationer fra.",
+ "Cancel" : "Annuller",
+ "Import" : "Importér",
+ "Error while saving settings" : "Der opstod en fejl under lagring af indstillinger",
+ "Contact reset successfully" : "Kontakten blev nulstillet",
+ "Error while resetting contact" : "Fejl under nulstilling af kontakt",
+ "Contact imported successfully" : "Kontakten blev importeret",
+ "Error while importing contact" : "Fejl under import af kontakt",
+ "Import contact" : "Importér kontakt",
+ "Reset to default" : "Nulstil",
+ "Import contacts" : "Importér kontakter",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Import af en ny .vcf-fil vil slette den eksisterende standardkontakt og erstatte den med den nye. Vil du fortsætte?",
"Availability" : "tilgængelighed",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Hvis du konfigurerer dine arbejdstider, vil andre se, når du er fraværende, når de booker et møde.",
"Absence" : "Fravær",
@@ -304,27 +315,10 @@
"Send reminder notifications to calendar sharees as well" : "Send også påmindelsesmeddelelser til kalenderdelinger",
"Reminders are always sent to organizers and attendees." : "Påmindelser sendes altid til arrangører og deltagere.",
"Enable notifications for events via push" : "Aktiver notifikationer for begivenheder via push",
- "Cancel" : "Annuller",
- "Import" : "Importer",
- "Error while saving settings" : "Der opstod en fejl under lagring af indstillinger",
- "Contact reset successfully" : "Kontakten blev nulstillet",
- "Error while resetting contact" : "Fejl under nulstilling af kontakt",
- "Contact imported successfully" : "Kontakten blev importeret",
- "Error while importing contact" : "Fejl under import af kontakt",
- "Example Content" : "Eksempelindhold",
- "Set example content to be created on new user first login." : "Indstil eksempel på indhold, der skal oprettes ved ny brugers første login.",
- "Import contact" : "Importér kontakt",
- "Reset to default contact" : "Nulstil til standardkontakt",
- "Import contacts" : "Importér kontakter",
- "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Import af en ny .vcf-fil vil slette den eksisterende standardkontakt og erstatte den med den nye. Vil du fortsætte?",
"There was an error updating your attendance status." : "Der opstod en fejl under opdatering af din fremmødestatus.",
"Please contact the organizer directly." : "Kontakt venligst arrangøren direkte.",
"Are you accepting the invitation?" : "Accepter du invitationen?",
"Tentative" : "Foreløbig",
- "Your attendance was updated successfully." : "Dit tilstedeværelse blev opdateret.",
- "Time:" : "Tid:",
- "Could not open file" : "Kunne ikke åbne fil",
- "Invalid chunk name" : "Ugyldigt stykke navn",
- "Could not rename part file assembled from chunks" : "Kunne ikke omdøbe delfilen samlet fra stykker"
+ "Your attendance was updated successfully." : "Dit tilstedeværelse blev opdateret."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/de.js b/apps/dav/l10n/de.js
index e22163e7731..6cc5380d058 100644
--- a/apps/dav/l10n/de.js
+++ b/apps/dav/l10n/de.js
@@ -161,7 +161,7 @@ OC.L10N.register(
"When:" : "Wann:",
"Location:" : "Ort:",
"Link:" : "Link:",
- "Occurring:" : "Vorkommend:",
+ "Occurring:" : "Findet statt:",
"Accept" : "Akzeptieren",
"Decline" : "Ablehnen",
"More options …" : "Weitere Optionen …",
@@ -250,6 +250,8 @@ OC.L10N.register(
"Completed on %s" : "Erledigt am %s",
"Due on %s by %s" : "Fällig am %s von %s",
"Due on %s" : "Fällig am %s",
+ "Welcome to Nextcloud Calendar!\n\nThis is a sample event - explore the flexibility of planning with Nextcloud Calendar by making any edits you want!\n\nWith Nextcloud Calendar, you can:\n- Create, edit, and manage events effortlessly.\n- Create multiple calendars and share them with teammates, friends, or family.\n- Check availability and display your busy times to others.\n- Seamlessly integrate with apps and devices via CalDAV.\n- Customize your experience: schedule recurring events, adjust notifications and other settings." : "Willkommen bei Nextcloud Calendar!\n\nDies ist ein Beispielereignis – entdecke die Flexibilität der Planung mit Nextcloud Calendar und nimm beliebige Änderungen vor!\n\nMit Nextcloud Calendar kannst du:\n– Ereignisse mühelos erstellen, bearbeiten und verwalten.\n– Mehrere Kalender erstellen und mit Teamkollegen, Freunden oder der Familie teilen.\n– Verfügbarkeit prüfen und Ihre Termine anderen anzeigen.\n– Nahtlose Integration mit Apps und Geräten über CalDAV.\n– Individuelle Gestaltung: Plane wiederkehrende Ereignisse, passe Benachrichtigungen und andere Einstellungen an.",
+ "Example event - open me!" : "Beispielereignis – öffne mich!",
"System Address Book" : "Systemadressbuch",
"The system address book contains contact information for all users in your instance." : "Das Systemadressbuch enthält Kontaktinformationen für alle Benutzer in dieser Instanz.",
"Enable System Address Book" : "Systemadressbuch aktivieren",
@@ -274,15 +276,15 @@ OC.L10N.register(
"Name of the replacement" : "Name der Vertretung",
"No results." : "Keine Ergebnisse",
"Start typing." : "Mit dem Schreiben beginnen.",
- "Short absence status" : "Kurze Abwesenheits Meldung",
- "Long absence Message" : "Lange Abwesenheits Meldung",
+ "Short absence status" : "Kurzer Abwesenheitsstatus",
+ "Long absence Message" : "Lange Abwesenheitsnachricht",
"Save" : "Speichern",
- "Disable absence" : "Abwesenheitmeldungen deaktivieren",
+ "Disable absence" : "Abwesenheit deaktivieren",
"Failed to load availability" : "Verfügbarkeit konnte nicht geladen werden",
"Saved availability" : "Verfügbarkeit gespeichert",
"Failed to save availability" : "Verfügbarkeit konnte nicht gespeichert werden",
"Time zone:" : "Zeitzone:",
- "to" : "an",
+ "to" : "bis",
"Delete slot" : "Slot löschen",
"No working hours set" : "Keine Arbeitszeiten konfiguriert",
"Add slot" : "Slot hinzufügen",
@@ -290,8 +292,27 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Eine Startzeit für {dayName} wählen",
"Pick a end time for {dayName}" : "Eine Endezeit für {dayName} wählen",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Setze den Benutzerstatus außerhalb deiner Verfügbarkeit automatisch auf \"Nicht stören\", um alle Benachrichtigungen stumm zu schalten.",
+ "Cancel" : "Abbrechen",
+ "Import" : "Importieren",
+ "Error while saving settings" : "Fehler beim Speichern der Einstellungen",
+ "Contact reset successfully" : "Kontakt zurückgesetzt",
+ "Error while resetting contact" : "Fehler beim Zurücksetzen des Kontakts",
+ "Contact imported successfully" : "Kontakt importiert",
+ "Error while importing contact" : "Fehler beim Import des Kontakts",
+ "Import contact" : "Kontakt importieren",
+ "Reset to default" : "Auf Standard zurücksetzen ",
+ "Import contacts" : "Kontakte importieren",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Durch das Importieren einer neuen VCF-Datei wird der vorhandene Standardkontakt gelöscht und durch den neuen ersetzt. Fortsetzen?",
+ "Failed to save example event creation setting" : "Einstellung für die Beispiels-Ereigniserstellung konnte nicht gespeichert werden",
+ "Failed to upload the example event" : "Das Beispielsereignis konnte nicht hochgeladen werden",
+ "Custom example event was saved successfully" : "Benutzerdefiniertes Beispielereignis gespeichert",
+ "Failed to delete the custom example event" : "Benutzerdefiniertes Beispielsereignis konnte nicht gelöscht werden",
+ "Custom example event was deleted successfully" : "Benutzerdefiniertes Beispielsereignis wurde gelöscht",
+ "Import calendar event" : "Kalenderereignis importieren",
+ "Uploading a new event will overwrite the existing one." : "Das Hochladen eines neuen Ereignisses wird das bestehende Ereignis überschreiben.",
+ "Upload event" : "Ereignis hochladen",
"Availability" : "Verfügbarkeit",
- "If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Wenn du deine Arbeitszeiten konfigurierst, können andere Benutzer sehen, wann du nicht im Büro bist, wenn sie eine Besprechung buchen.",
+ "If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Wenn du deine Arbeitszeiten angibst, können andere beim Buchen einer Besprechung sehen, wann du nicht im Büro bist.",
"Absence" : "Abwesenheit",
"Configure your next absence period." : "Richte deinen nächsten Abwesenheitszeitraum ein.",
"Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Installiere außerdem die {calendarappstoreopen}Kalender-App{linkclose} oder {calendardocopen}verbinde deinen Desktop & Mobilgerät zur Synchronisierung ↗{linkclose}.",
@@ -299,34 +320,19 @@ OC.L10N.register(
"Calendar server" : "Kalender-Server",
"Send invitations to attendees" : "Einladungen an die Teilnehmer senden",
"Automatically generate a birthday calendar" : "Automatisch einen Kalender für Geburtstage erstellen",
- "Birthday calendars will be generated by a background job." : "Kalender für Geburtstage werden von einem Hintergrund-Auftrag erstellt",
+ "Birthday calendars will be generated by a background job." : "Kalender für Geburtstage werden von einer Hintergrundaufgabe erstellt",
"Hence they will not be available immediately after enabling but will show up after some time." : "Die Einträge werden nicht sofort angezeigt. Nach der Aktivierung wird es bis zur Anzeige ein wenig dauern.",
"Send notifications for events" : "Sende Benachrichtigungen für Termine",
- "Notifications are sent via background jobs, so these must occur often enough." : "Benachrichtigungen werden von Hintergrundjobs gesendet, so dass diese häufig genug ausgeführt werden.",
+ "Notifications are sent via background jobs, so these must occur often enough." : "Benachrichtigungen werden von Hintergrundaufgaben gesendet, so dass diese häufig genug ausgeführt werden.",
"Send reminder notifications to calendar sharees as well" : "Erinnerungsbenachrichtigungen auch an die freigegebenen Kalender senden",
"Reminders are always sent to organizers and attendees." : "Erinnerungen werden immer an Organisatoren und Teilnehmer gesendet.",
"Enable notifications for events via push" : "Benachrichtigungen für Termine per Push aktivieren",
- "Cancel" : "Abbrechen",
- "Import" : "Importieren",
- "Error while saving settings" : "Fehler beim Speichern der Einstellungen",
- "Contact reset successfully" : "Kontakt erfolgreich zurückgesetzt",
- "Error while resetting contact" : "Fehler beim Zurücksetzen des Kontakts",
- "Contact imported successfully" : "Kontakt erfolgreich importiert",
- "Error while importing contact" : "Fehler beim Import des Kontakts",
- "Example Content" : "Beispielinhalt",
- "Set example content to be created on new user first login." : "Beispielinhalte festlegen, die bei der ersten Anmeldung eines neuen Benutzers erstellt werden sollen.",
- "Import contact" : "Kontakt importieren",
- "Reset to default contact" : "Standardkontakt zurücksetzen",
- "Import contacts" : "Kontakte importieren",
- "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Durch das Importieren einer neuen VCF-Datei wird der vorhandene Standardkontakt gelöscht und durch den neuen ersetzt. Fortsetzen?",
+ "Example content" : "Beispielsinhalt",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Beispielinhalte dienen dazu, die Funktionen von Nextcloud vorzustellen. Standardinhalte werden mit Nextcloud ausgeliefert und können durch benutzerdefinierte Inhalte ersetzt werden.",
"There was an error updating your attendance status." : "Es ist ein Fehler beim Aktualisieren deines Teilnehmerstatus aufgetreten.",
"Please contact the organizer directly." : "Bitte den Organisator direkt kontaktieren.",
"Are you accepting the invitation?" : "Die Einladung annehmen?",
"Tentative" : "Vorläufig",
- "Your attendance was updated successfully." : "Dein Teilnehmerstatus wurde aktualisiert.",
- "Time:" : "Zeit:",
- "Could not open file" : "Datei konnte nicht geöffnet werden",
- "Invalid chunk name" : "Ungültiger Chunk-Name",
- "Could not rename part file assembled from chunks" : "Aus Chunks zusammengesetzte temporäre Datei konnte nicht umbenannt werden"
+ "Your attendance was updated successfully." : "Dein Teilnehmerstatus wurde aktualisiert."
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/de.json b/apps/dav/l10n/de.json
index 02a0a5707ab..5f48c4898a3 100644
--- a/apps/dav/l10n/de.json
+++ b/apps/dav/l10n/de.json
@@ -159,7 +159,7 @@
"When:" : "Wann:",
"Location:" : "Ort:",
"Link:" : "Link:",
- "Occurring:" : "Vorkommend:",
+ "Occurring:" : "Findet statt:",
"Accept" : "Akzeptieren",
"Decline" : "Ablehnen",
"More options …" : "Weitere Optionen …",
@@ -248,6 +248,8 @@
"Completed on %s" : "Erledigt am %s",
"Due on %s by %s" : "Fällig am %s von %s",
"Due on %s" : "Fällig am %s",
+ "Welcome to Nextcloud Calendar!\n\nThis is a sample event - explore the flexibility of planning with Nextcloud Calendar by making any edits you want!\n\nWith Nextcloud Calendar, you can:\n- Create, edit, and manage events effortlessly.\n- Create multiple calendars and share them with teammates, friends, or family.\n- Check availability and display your busy times to others.\n- Seamlessly integrate with apps and devices via CalDAV.\n- Customize your experience: schedule recurring events, adjust notifications and other settings." : "Willkommen bei Nextcloud Calendar!\n\nDies ist ein Beispielereignis – entdecke die Flexibilität der Planung mit Nextcloud Calendar und nimm beliebige Änderungen vor!\n\nMit Nextcloud Calendar kannst du:\n– Ereignisse mühelos erstellen, bearbeiten und verwalten.\n– Mehrere Kalender erstellen und mit Teamkollegen, Freunden oder der Familie teilen.\n– Verfügbarkeit prüfen und Ihre Termine anderen anzeigen.\n– Nahtlose Integration mit Apps und Geräten über CalDAV.\n– Individuelle Gestaltung: Plane wiederkehrende Ereignisse, passe Benachrichtigungen und andere Einstellungen an.",
+ "Example event - open me!" : "Beispielereignis – öffne mich!",
"System Address Book" : "Systemadressbuch",
"The system address book contains contact information for all users in your instance." : "Das Systemadressbuch enthält Kontaktinformationen für alle Benutzer in dieser Instanz.",
"Enable System Address Book" : "Systemadressbuch aktivieren",
@@ -272,15 +274,15 @@
"Name of the replacement" : "Name der Vertretung",
"No results." : "Keine Ergebnisse",
"Start typing." : "Mit dem Schreiben beginnen.",
- "Short absence status" : "Kurze Abwesenheits Meldung",
- "Long absence Message" : "Lange Abwesenheits Meldung",
+ "Short absence status" : "Kurzer Abwesenheitsstatus",
+ "Long absence Message" : "Lange Abwesenheitsnachricht",
"Save" : "Speichern",
- "Disable absence" : "Abwesenheitmeldungen deaktivieren",
+ "Disable absence" : "Abwesenheit deaktivieren",
"Failed to load availability" : "Verfügbarkeit konnte nicht geladen werden",
"Saved availability" : "Verfügbarkeit gespeichert",
"Failed to save availability" : "Verfügbarkeit konnte nicht gespeichert werden",
"Time zone:" : "Zeitzone:",
- "to" : "an",
+ "to" : "bis",
"Delete slot" : "Slot löschen",
"No working hours set" : "Keine Arbeitszeiten konfiguriert",
"Add slot" : "Slot hinzufügen",
@@ -288,8 +290,27 @@
"Pick a start time for {dayName}" : "Eine Startzeit für {dayName} wählen",
"Pick a end time for {dayName}" : "Eine Endezeit für {dayName} wählen",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Setze den Benutzerstatus außerhalb deiner Verfügbarkeit automatisch auf \"Nicht stören\", um alle Benachrichtigungen stumm zu schalten.",
+ "Cancel" : "Abbrechen",
+ "Import" : "Importieren",
+ "Error while saving settings" : "Fehler beim Speichern der Einstellungen",
+ "Contact reset successfully" : "Kontakt zurückgesetzt",
+ "Error while resetting contact" : "Fehler beim Zurücksetzen des Kontakts",
+ "Contact imported successfully" : "Kontakt importiert",
+ "Error while importing contact" : "Fehler beim Import des Kontakts",
+ "Import contact" : "Kontakt importieren",
+ "Reset to default" : "Auf Standard zurücksetzen ",
+ "Import contacts" : "Kontakte importieren",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Durch das Importieren einer neuen VCF-Datei wird der vorhandene Standardkontakt gelöscht und durch den neuen ersetzt. Fortsetzen?",
+ "Failed to save example event creation setting" : "Einstellung für die Beispiels-Ereigniserstellung konnte nicht gespeichert werden",
+ "Failed to upload the example event" : "Das Beispielsereignis konnte nicht hochgeladen werden",
+ "Custom example event was saved successfully" : "Benutzerdefiniertes Beispielereignis gespeichert",
+ "Failed to delete the custom example event" : "Benutzerdefiniertes Beispielsereignis konnte nicht gelöscht werden",
+ "Custom example event was deleted successfully" : "Benutzerdefiniertes Beispielsereignis wurde gelöscht",
+ "Import calendar event" : "Kalenderereignis importieren",
+ "Uploading a new event will overwrite the existing one." : "Das Hochladen eines neuen Ereignisses wird das bestehende Ereignis überschreiben.",
+ "Upload event" : "Ereignis hochladen",
"Availability" : "Verfügbarkeit",
- "If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Wenn du deine Arbeitszeiten konfigurierst, können andere Benutzer sehen, wann du nicht im Büro bist, wenn sie eine Besprechung buchen.",
+ "If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Wenn du deine Arbeitszeiten angibst, können andere beim Buchen einer Besprechung sehen, wann du nicht im Büro bist.",
"Absence" : "Abwesenheit",
"Configure your next absence period." : "Richte deinen nächsten Abwesenheitszeitraum ein.",
"Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Installiere außerdem die {calendarappstoreopen}Kalender-App{linkclose} oder {calendardocopen}verbinde deinen Desktop & Mobilgerät zur Synchronisierung ↗{linkclose}.",
@@ -297,34 +318,19 @@
"Calendar server" : "Kalender-Server",
"Send invitations to attendees" : "Einladungen an die Teilnehmer senden",
"Automatically generate a birthday calendar" : "Automatisch einen Kalender für Geburtstage erstellen",
- "Birthday calendars will be generated by a background job." : "Kalender für Geburtstage werden von einem Hintergrund-Auftrag erstellt",
+ "Birthday calendars will be generated by a background job." : "Kalender für Geburtstage werden von einer Hintergrundaufgabe erstellt",
"Hence they will not be available immediately after enabling but will show up after some time." : "Die Einträge werden nicht sofort angezeigt. Nach der Aktivierung wird es bis zur Anzeige ein wenig dauern.",
"Send notifications for events" : "Sende Benachrichtigungen für Termine",
- "Notifications are sent via background jobs, so these must occur often enough." : "Benachrichtigungen werden von Hintergrundjobs gesendet, so dass diese häufig genug ausgeführt werden.",
+ "Notifications are sent via background jobs, so these must occur often enough." : "Benachrichtigungen werden von Hintergrundaufgaben gesendet, so dass diese häufig genug ausgeführt werden.",
"Send reminder notifications to calendar sharees as well" : "Erinnerungsbenachrichtigungen auch an die freigegebenen Kalender senden",
"Reminders are always sent to organizers and attendees." : "Erinnerungen werden immer an Organisatoren und Teilnehmer gesendet.",
"Enable notifications for events via push" : "Benachrichtigungen für Termine per Push aktivieren",
- "Cancel" : "Abbrechen",
- "Import" : "Importieren",
- "Error while saving settings" : "Fehler beim Speichern der Einstellungen",
- "Contact reset successfully" : "Kontakt erfolgreich zurückgesetzt",
- "Error while resetting contact" : "Fehler beim Zurücksetzen des Kontakts",
- "Contact imported successfully" : "Kontakt erfolgreich importiert",
- "Error while importing contact" : "Fehler beim Import des Kontakts",
- "Example Content" : "Beispielinhalt",
- "Set example content to be created on new user first login." : "Beispielinhalte festlegen, die bei der ersten Anmeldung eines neuen Benutzers erstellt werden sollen.",
- "Import contact" : "Kontakt importieren",
- "Reset to default contact" : "Standardkontakt zurücksetzen",
- "Import contacts" : "Kontakte importieren",
- "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Durch das Importieren einer neuen VCF-Datei wird der vorhandene Standardkontakt gelöscht und durch den neuen ersetzt. Fortsetzen?",
+ "Example content" : "Beispielsinhalt",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Beispielinhalte dienen dazu, die Funktionen von Nextcloud vorzustellen. Standardinhalte werden mit Nextcloud ausgeliefert und können durch benutzerdefinierte Inhalte ersetzt werden.",
"There was an error updating your attendance status." : "Es ist ein Fehler beim Aktualisieren deines Teilnehmerstatus aufgetreten.",
"Please contact the organizer directly." : "Bitte den Organisator direkt kontaktieren.",
"Are you accepting the invitation?" : "Die Einladung annehmen?",
"Tentative" : "Vorläufig",
- "Your attendance was updated successfully." : "Dein Teilnehmerstatus wurde aktualisiert.",
- "Time:" : "Zeit:",
- "Could not open file" : "Datei konnte nicht geöffnet werden",
- "Invalid chunk name" : "Ungültiger Chunk-Name",
- "Could not rename part file assembled from chunks" : "Aus Chunks zusammengesetzte temporäre Datei konnte nicht umbenannt werden"
+ "Your attendance was updated successfully." : "Dein Teilnehmerstatus wurde aktualisiert."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/de_DE.js b/apps/dav/l10n/de_DE.js
index f513d35cdc9..40030b8de84 100644
--- a/apps/dav/l10n/de_DE.js
+++ b/apps/dav/l10n/de_DE.js
@@ -161,7 +161,7 @@ OC.L10N.register(
"When:" : "Wann:",
"Location:" : "Ort:",
"Link:" : "Link:",
- "Occurring:" : "Vorkommend:",
+ "Occurring:" : "Findet statt:",
"Accept" : "Akzeptieren",
"Decline" : "Ablehnen",
"More options …" : "Weitere Optionen …",
@@ -250,6 +250,8 @@ OC.L10N.register(
"Completed on %s" : "Erledigt am %s",
"Due on %s by %s" : "Fällig am %s von %s",
"Due on %s" : "Fällig am %s",
+ "Welcome to Nextcloud Calendar!\n\nThis is a sample event - explore the flexibility of planning with Nextcloud Calendar by making any edits you want!\n\nWith Nextcloud Calendar, you can:\n- Create, edit, and manage events effortlessly.\n- Create multiple calendars and share them with teammates, friends, or family.\n- Check availability and display your busy times to others.\n- Seamlessly integrate with apps and devices via CalDAV.\n- Customize your experience: schedule recurring events, adjust notifications and other settings." : "Willkommen bei Nextcloud Calendar!\n\nDies ist ein Beispielereignis – entdecken Sie die Flexibilität der Planung mit Nextcloud Calendar und nehmen Sie beliebige Änderungen vor!\n\nMit Nextcloud Calendar können Sie:\n– Ereignisse mühelos erstellen, bearbeiten und verwalten.\n– Mehrere Kalender erstellen und mit Teamkollegen, Freunden oder der Familie teilen.\n– Verfügbarkeit prüfen und Ihre Termine anderen anzeigen.\n– Nahtlose Integration mit Apps und Geräten über CalDAV.\n– Individuelle Gestaltung: Planen Sie wiederkehrende Ereignisse, passen Sie Benachrichtigungen und andere Einstellungen an.",
+ "Example event - open me!" : "Beispielereignis – öffne mich!",
"System Address Book" : "Systemadressbuch",
"The system address book contains contact information for all users in your instance." : "Das Systemadressbuch enthält Kontaktinformationen für alle Benutzer in dieser Instanz.",
"Enable System Address Book" : "Systemadressbuch aktivieren",
@@ -274,7 +276,7 @@ OC.L10N.register(
"Name of the replacement" : "Name der Vertretung",
"No results." : "Keine Ergebnisse.",
"Start typing." : "Anfangen zu tippen.",
- "Short absence status" : "Kurzer Abwesenheitsstaus",
+ "Short absence status" : "Kurzer Abwesenheitsstatus",
"Long absence Message" : "Lange Abwesenheitsnachricht",
"Save" : "Speichern",
"Disable absence" : "Abwesenheit deaktivieren",
@@ -282,18 +284,37 @@ OC.L10N.register(
"Saved availability" : "Verfügbarkeit gespeichert",
"Failed to save availability" : "Verfügbarkeit konnte nicht gespeichert werden",
"Time zone:" : "Zeitzone:",
- "to" : "an",
+ "to" : "bis",
"Delete slot" : "Zeitfenster löschen",
- "No working hours set" : "Arbeitsfreie Stunden gesetzt",
+ "No working hours set" : "Keine Arbeitszeiten konfiguriert",
"Add slot" : "Zeitfenster hinzufügen",
"Weekdays" : "Wochentage",
"Pick a start time for {dayName}" : "Eine Startzeit für {dayName} wählen",
"Pick a end time for {dayName}" : "Eine Endezeit für {dayName} wählen",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Setzen Sie den Benutzerstatus außerhalb Ihrer Verfügbarkeit automatisch auf \"Nicht stören\", um alle Benachrichtigungen stumm zu schalten.",
+ "Cancel" : "Abbrechen",
+ "Import" : "Importieren",
+ "Error while saving settings" : "Fehler beim Speichern der Einstellungen",
+ "Contact reset successfully" : "Kontakt zurückgesetzt",
+ "Error while resetting contact" : "Fehler beim Zurücksetzen des Kontakts",
+ "Contact imported successfully" : "Kontakt importiert",
+ "Error while importing contact" : "Fehler beim Import des Kontakts",
+ "Import contact" : "Kontakt importieren",
+ "Reset to default" : "Auf Standard zurücksetzen ",
+ "Import contacts" : "Kontakte importieren",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Durch das Importieren einer neuen VCF-Datei wird der vorhandene Standardkontakt gelöscht und durch den neuen ersetzt. Fortsetzen?",
+ "Failed to save example event creation setting" : "Einstellung für die Beispiels-Terminerstellung konnte nicht gespeichert werden",
+ "Failed to upload the example event" : "Der Beispieltermin konnte nicht hochgeladen werden",
+ "Custom example event was saved successfully" : "Benutzerdefinierter Beispieltermin gespeichert",
+ "Failed to delete the custom example event" : "Benutzerdefinierter Beispieltermin konnte nicht gelöscht werden",
+ "Custom example event was deleted successfully" : "Benutzerdefinierter Beispieltermin wurde gelöscht",
+ "Import calendar event" : "Kalendertermin importieren",
+ "Uploading a new event will overwrite the existing one." : "Das Hochladen eines neuen Termins wird den bestehenden Termin überschreiben.",
+ "Upload event" : "Termin hochladen",
"Availability" : "Verfügbarkeit",
- "If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Wenn Sie Ihre Arbeitszeiten angeben, können Andere beim Buchen einer Besprechung sehen, wann Sie nicht im Büro sind.",
+ "If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Wenn Sie Ihre Arbeitszeiten angeben, können andere beim Buchen einer Besprechung sehen, wann Sie nicht im Büro sind.",
"Absence" : "Abwesenheit",
- "Configure your next absence period." : "Richten Sie ihren nächsten Abwesenheitszeitraum ein",
+ "Configure your next absence period." : "Richten Sie ihren nächsten Abwesenheitszeitraum ein.",
"Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Installieren Sie außerdem die {calendarappstoreopen}Kalender-App{linkclose} oder {calendardocopen}verbinden Sie Ihren Desktop & Mobilgerät zur Synchronisierung ↗{linkclose}.",
"Please make sure to properly set up {emailopen}the email server{linkclose}." : "Bitte stellen Sie sicher, dass Sie {emailopen}den E-Mail Server{linkclose} ordnungsgemäß eingerichtet haben.",
"Calendar server" : "Kalender-Server",
@@ -302,31 +323,16 @@ OC.L10N.register(
"Birthday calendars will be generated by a background job." : "Kalender für Geburtstage werden von einem Hintergrund-Auftrag erstellt",
"Hence they will not be available immediately after enabling but will show up after some time." : "Die Einträge werden nicht sofort angezeigt. Nach der Aktivierung wird es ein wenig dauern bis zur Anzeige.",
"Send notifications for events" : "Sende Benachrichtigungen für Termine",
- "Notifications are sent via background jobs, so these must occur often enough." : "Benachrichtigungen werden von Hintergrundjobs versendet, so dass diese häufig genug ausgeführt werden müssen.",
+ "Notifications are sent via background jobs, so these must occur often enough." : "Benachrichtigungen werden von Hintergrundaufgaben versendet, so dass diese häufig genug ausgeführt werden müssen.",
"Send reminder notifications to calendar sharees as well" : "Erinnerungsbenachrichtigungen auch an die Kalenderfreigaben senden",
"Reminders are always sent to organizers and attendees." : "Erinnerungen werden immer an Organisatoren und Teilnehmer gesendet.",
"Enable notifications for events via push" : "Benachrichtigungen für Termine per Push aktivieren",
- "Cancel" : "Abbrechen",
- "Import" : "Importieren",
- "Error while saving settings" : "Fehler beim Speichern der Einstellungen",
- "Contact reset successfully" : "Kontakt zurückgesetzt",
- "Error while resetting contact" : "Fehler beim Zurücksetzen des Kontakts",
- "Contact imported successfully" : "Kontakt importiert",
- "Error while importing contact" : "Fehler beim Import des Kontakts",
- "Example Content" : "Beispielinhalt",
- "Set example content to be created on new user first login." : "Beispielinhalte festlegen, die bei der ersten Anmeldung eines neuen Benutzers erstellt werden sollen.",
- "Import contact" : "Kontakt importieren",
- "Reset to default contact" : "Standardkontakt zurücksetzen",
- "Import contacts" : "Kontakte importieren",
- "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Durch das Importieren einer neuen VCF-Datei wird der vorhandene Standardkontakt gelöscht und durch den neuen ersetzt. Fortsetzen?",
+ "Example content" : "Beispielsinhalt",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Beispielinhalte dienen dazu, die Funktionen von Nextcloud vorzustellen. Standardinhalte werden mit Nextcloud ausgeliefert und können durch benutzerdefinierte Inhalte ersetzt werden.",
"There was an error updating your attendance status." : "Es ist ein Fehler beim Aktualisieren Ihres Teilnehmerstatus aufgetreten.",
"Please contact the organizer directly." : "Bitte den Organisator direkt kontaktieren.",
"Are you accepting the invitation?" : "Die Einladung annehmen?",
"Tentative" : "Vorläufig",
- "Your attendance was updated successfully." : "Ihr Teilnehmerstatus wurde aktualisiert.",
- "Time:" : "Zeit:",
- "Could not open file" : "Datei konnte nicht geöffnet werden",
- "Invalid chunk name" : "Ungültiger Chunk-Name",
- "Could not rename part file assembled from chunks" : "Aus Chunks zusammengesetzte Teildatei konnte nicht umbenannt werden"
+ "Your attendance was updated successfully." : "Ihr Teilnehmerstatus wurde aktualisiert."
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/de_DE.json b/apps/dav/l10n/de_DE.json
index e27822fbaa6..3857d9be185 100644
--- a/apps/dav/l10n/de_DE.json
+++ b/apps/dav/l10n/de_DE.json
@@ -159,7 +159,7 @@
"When:" : "Wann:",
"Location:" : "Ort:",
"Link:" : "Link:",
- "Occurring:" : "Vorkommend:",
+ "Occurring:" : "Findet statt:",
"Accept" : "Akzeptieren",
"Decline" : "Ablehnen",
"More options …" : "Weitere Optionen …",
@@ -248,6 +248,8 @@
"Completed on %s" : "Erledigt am %s",
"Due on %s by %s" : "Fällig am %s von %s",
"Due on %s" : "Fällig am %s",
+ "Welcome to Nextcloud Calendar!\n\nThis is a sample event - explore the flexibility of planning with Nextcloud Calendar by making any edits you want!\n\nWith Nextcloud Calendar, you can:\n- Create, edit, and manage events effortlessly.\n- Create multiple calendars and share them with teammates, friends, or family.\n- Check availability and display your busy times to others.\n- Seamlessly integrate with apps and devices via CalDAV.\n- Customize your experience: schedule recurring events, adjust notifications and other settings." : "Willkommen bei Nextcloud Calendar!\n\nDies ist ein Beispielereignis – entdecken Sie die Flexibilität der Planung mit Nextcloud Calendar und nehmen Sie beliebige Änderungen vor!\n\nMit Nextcloud Calendar können Sie:\n– Ereignisse mühelos erstellen, bearbeiten und verwalten.\n– Mehrere Kalender erstellen und mit Teamkollegen, Freunden oder der Familie teilen.\n– Verfügbarkeit prüfen und Ihre Termine anderen anzeigen.\n– Nahtlose Integration mit Apps und Geräten über CalDAV.\n– Individuelle Gestaltung: Planen Sie wiederkehrende Ereignisse, passen Sie Benachrichtigungen und andere Einstellungen an.",
+ "Example event - open me!" : "Beispielereignis – öffne mich!",
"System Address Book" : "Systemadressbuch",
"The system address book contains contact information for all users in your instance." : "Das Systemadressbuch enthält Kontaktinformationen für alle Benutzer in dieser Instanz.",
"Enable System Address Book" : "Systemadressbuch aktivieren",
@@ -272,7 +274,7 @@
"Name of the replacement" : "Name der Vertretung",
"No results." : "Keine Ergebnisse.",
"Start typing." : "Anfangen zu tippen.",
- "Short absence status" : "Kurzer Abwesenheitsstaus",
+ "Short absence status" : "Kurzer Abwesenheitsstatus",
"Long absence Message" : "Lange Abwesenheitsnachricht",
"Save" : "Speichern",
"Disable absence" : "Abwesenheit deaktivieren",
@@ -280,18 +282,37 @@
"Saved availability" : "Verfügbarkeit gespeichert",
"Failed to save availability" : "Verfügbarkeit konnte nicht gespeichert werden",
"Time zone:" : "Zeitzone:",
- "to" : "an",
+ "to" : "bis",
"Delete slot" : "Zeitfenster löschen",
- "No working hours set" : "Arbeitsfreie Stunden gesetzt",
+ "No working hours set" : "Keine Arbeitszeiten konfiguriert",
"Add slot" : "Zeitfenster hinzufügen",
"Weekdays" : "Wochentage",
"Pick a start time for {dayName}" : "Eine Startzeit für {dayName} wählen",
"Pick a end time for {dayName}" : "Eine Endezeit für {dayName} wählen",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Setzen Sie den Benutzerstatus außerhalb Ihrer Verfügbarkeit automatisch auf \"Nicht stören\", um alle Benachrichtigungen stumm zu schalten.",
+ "Cancel" : "Abbrechen",
+ "Import" : "Importieren",
+ "Error while saving settings" : "Fehler beim Speichern der Einstellungen",
+ "Contact reset successfully" : "Kontakt zurückgesetzt",
+ "Error while resetting contact" : "Fehler beim Zurücksetzen des Kontakts",
+ "Contact imported successfully" : "Kontakt importiert",
+ "Error while importing contact" : "Fehler beim Import des Kontakts",
+ "Import contact" : "Kontakt importieren",
+ "Reset to default" : "Auf Standard zurücksetzen ",
+ "Import contacts" : "Kontakte importieren",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Durch das Importieren einer neuen VCF-Datei wird der vorhandene Standardkontakt gelöscht und durch den neuen ersetzt. Fortsetzen?",
+ "Failed to save example event creation setting" : "Einstellung für die Beispiels-Terminerstellung konnte nicht gespeichert werden",
+ "Failed to upload the example event" : "Der Beispieltermin konnte nicht hochgeladen werden",
+ "Custom example event was saved successfully" : "Benutzerdefinierter Beispieltermin gespeichert",
+ "Failed to delete the custom example event" : "Benutzerdefinierter Beispieltermin konnte nicht gelöscht werden",
+ "Custom example event was deleted successfully" : "Benutzerdefinierter Beispieltermin wurde gelöscht",
+ "Import calendar event" : "Kalendertermin importieren",
+ "Uploading a new event will overwrite the existing one." : "Das Hochladen eines neuen Termins wird den bestehenden Termin überschreiben.",
+ "Upload event" : "Termin hochladen",
"Availability" : "Verfügbarkeit",
- "If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Wenn Sie Ihre Arbeitszeiten angeben, können Andere beim Buchen einer Besprechung sehen, wann Sie nicht im Büro sind.",
+ "If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Wenn Sie Ihre Arbeitszeiten angeben, können andere beim Buchen einer Besprechung sehen, wann Sie nicht im Büro sind.",
"Absence" : "Abwesenheit",
- "Configure your next absence period." : "Richten Sie ihren nächsten Abwesenheitszeitraum ein",
+ "Configure your next absence period." : "Richten Sie ihren nächsten Abwesenheitszeitraum ein.",
"Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Installieren Sie außerdem die {calendarappstoreopen}Kalender-App{linkclose} oder {calendardocopen}verbinden Sie Ihren Desktop & Mobilgerät zur Synchronisierung ↗{linkclose}.",
"Please make sure to properly set up {emailopen}the email server{linkclose}." : "Bitte stellen Sie sicher, dass Sie {emailopen}den E-Mail Server{linkclose} ordnungsgemäß eingerichtet haben.",
"Calendar server" : "Kalender-Server",
@@ -300,31 +321,16 @@
"Birthday calendars will be generated by a background job." : "Kalender für Geburtstage werden von einem Hintergrund-Auftrag erstellt",
"Hence they will not be available immediately after enabling but will show up after some time." : "Die Einträge werden nicht sofort angezeigt. Nach der Aktivierung wird es ein wenig dauern bis zur Anzeige.",
"Send notifications for events" : "Sende Benachrichtigungen für Termine",
- "Notifications are sent via background jobs, so these must occur often enough." : "Benachrichtigungen werden von Hintergrundjobs versendet, so dass diese häufig genug ausgeführt werden müssen.",
+ "Notifications are sent via background jobs, so these must occur often enough." : "Benachrichtigungen werden von Hintergrundaufgaben versendet, so dass diese häufig genug ausgeführt werden müssen.",
"Send reminder notifications to calendar sharees as well" : "Erinnerungsbenachrichtigungen auch an die Kalenderfreigaben senden",
"Reminders are always sent to organizers and attendees." : "Erinnerungen werden immer an Organisatoren und Teilnehmer gesendet.",
"Enable notifications for events via push" : "Benachrichtigungen für Termine per Push aktivieren",
- "Cancel" : "Abbrechen",
- "Import" : "Importieren",
- "Error while saving settings" : "Fehler beim Speichern der Einstellungen",
- "Contact reset successfully" : "Kontakt zurückgesetzt",
- "Error while resetting contact" : "Fehler beim Zurücksetzen des Kontakts",
- "Contact imported successfully" : "Kontakt importiert",
- "Error while importing contact" : "Fehler beim Import des Kontakts",
- "Example Content" : "Beispielinhalt",
- "Set example content to be created on new user first login." : "Beispielinhalte festlegen, die bei der ersten Anmeldung eines neuen Benutzers erstellt werden sollen.",
- "Import contact" : "Kontakt importieren",
- "Reset to default contact" : "Standardkontakt zurücksetzen",
- "Import contacts" : "Kontakte importieren",
- "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Durch das Importieren einer neuen VCF-Datei wird der vorhandene Standardkontakt gelöscht und durch den neuen ersetzt. Fortsetzen?",
+ "Example content" : "Beispielsinhalt",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Beispielinhalte dienen dazu, die Funktionen von Nextcloud vorzustellen. Standardinhalte werden mit Nextcloud ausgeliefert und können durch benutzerdefinierte Inhalte ersetzt werden.",
"There was an error updating your attendance status." : "Es ist ein Fehler beim Aktualisieren Ihres Teilnehmerstatus aufgetreten.",
"Please contact the organizer directly." : "Bitte den Organisator direkt kontaktieren.",
"Are you accepting the invitation?" : "Die Einladung annehmen?",
"Tentative" : "Vorläufig",
- "Your attendance was updated successfully." : "Ihr Teilnehmerstatus wurde aktualisiert.",
- "Time:" : "Zeit:",
- "Could not open file" : "Datei konnte nicht geöffnet werden",
- "Invalid chunk name" : "Ungültiger Chunk-Name",
- "Could not rename part file assembled from chunks" : "Aus Chunks zusammengesetzte Teildatei konnte nicht umbenannt werden"
+ "Your attendance was updated successfully." : "Ihr Teilnehmerstatus wurde aktualisiert."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/el.js b/apps/dav/l10n/el.js
deleted file mode 100644
index 640819dd14c..00000000000
--- a/apps/dav/l10n/el.js
+++ /dev/null
@@ -1,120 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Ημερολόγιο",
- "Tasks" : "Εργασίες",
- "Personal" : "Προσωπικά",
- "{actor} created calendar {calendar}" : "{actor} δημιουργήθηκε το ημερολόγιο {calendar}",
- "You created calendar {calendar}" : "Δημιουργήσατε ημερολόγιο {ημερολόγιο}",
- "{actor} deleted calendar {calendar}" : "{actor} διέγραψε το ημερολόγιο {calendar}",
- "You deleted calendar {calendar}" : "Διαγράψατε το ημερολόγιο {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} ενημέρωσε το ημερολόγιο {calendar}",
- "You updated calendar {calendar}" : "Έχετε ενημερώσει το ημερολόγιο {calendar}",
- "You restored calendar {calendar}" : "Επαναφέρατε το ημερολόγιο {calendar}",
- "You shared calendar {calendar} as public link" : "Μοιραστήκατε το ημερολόγιο {calendar} με δημόσιο σύνδεσμο.",
- "You removed public link for calendar {calendar}" : "Αφαιρέσατε τον δημόσιο σύνδεσμο για το ημερολόγιο {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} διαμοιράστηκε το ημερολόγιο {calendar} με εσάς",
- "You shared calendar {calendar} with {user}" : "Διαμοιραστήκατε το ημερολογίου {calendar} με {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} διαμοίρασε το ημερολόγιο {calendar} με {user}",
- "{actor} unshared calendar {calendar} from you" : "Ο {actor} σταμάτησε τον διαμοιρασμό του ημερολογίου {calendar} από εσάς",
- "You unshared calendar {calendar} from {user}" : "Σταματήσατε τον διαμοιρασμό ημερολογίου {calendar} από {user}",
- "{actor} unshared calendar {calendar} from {user}" : "Ο {actor} σταμάτησε τον διαμοιρασμό του ημερολογίου {calendar} από τον χρήστη {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} σταμάτησε το διαμοιρασμένο ημερολόγιο {calendar} από τον εαυτό τους",
- "You shared calendar {calendar} with group {group}" : "Διαμοιραστείκατε ένα ημερολόγιο {calendar} με την ομάδα {group}",
- "{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}",
- "You deleted event {event} from calendar {calendar}" : "Διαγράψατε το συμβάν {event} από το ημερολόγιο {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "Ο {actor} ενημέρωσε το γεγονός {event} στο ημερολόγιο {calendar}",
- "You updated event {event} in calendar {calendar}" : "Ενημερώσατε το συμβάν {event} στο ημερολόγιο {calendar}",
- "Busy" : "Απασχολημένος",
- "Calendar, contacts and tasks" : "Ημερολόγιο, επαφές και εργασίες",
- "A <strong>calendar</strong> was modified" : "Τροποποιήθηκε ένα <strong>ημερολόγιο</strong> ",
- "A calendar <strong>event</strong> was modified" : "Τροποποιήθηκε ένα <strong>γεγονός</strong> του ημερολογίου",
- "A calendar <strong>to-do</strong> was modified" : "Τροποποιήθηκε μια <strong>εκκρεμότητα</strong> ημερολογίου",
- "Contact birthdays" : "Γενέθλια επαφών",
- "Death of %s" : "Θάνατος του %s",
- "Untitled calendar" : "Ημερολόγιο χωρίς τίτλο",
- "Calendar:" : "Ημερολόγιο:",
- "Date:" : "Ημερομηνία:",
- "Where:" : "Που:",
- "Description:" : "Περιγραφή:",
- "_%n year_::_%n years_" : ["%n χρόνος/χρονιά","%n χρόνια"],
- "_%n month_::_%n months_" : ["%n μήνας","%d μήνες"],
- "_%n day_::_%n days_" : ["%n ημέρα","%n ημέρες"],
- "_%n hour_::_%n hours_" : ["%nώρα","%nώρες"],
- "_%n minute_::_%n minutes_" : ["%n λεπτό","%n λεπτά"],
- "%s (in %s)" : "%s (σε %s)",
- "%s (%s ago)" : "%s (%s πριν)",
- "Calendar: %s" : "Ημερολόγιο:%s",
- "Date: %s" : "Ημερομηνία:%s",
- "Description: %s" : "Περιγραφή:%s",
- "Where: %s" : "Που:%s",
- "%1$s via %2$s" : "%1$s μέσω %2$s",
- "Organizer:" : "Διοργανωτής:",
- "Attendees:" : "Συμμετέχοντες:",
- "Title:" : "Τίτλος:",
- "Location:" : "Τοποθεσία:",
- "Link:" : "Σύνδεσμος:",
- "Accept" : "Αποδοχή",
- "Decline" : "Απόρριψη",
- "More options …" : "Περισσότερες επιλογές...",
- "More options at %s" : "Περισσότερες επιλογές στο %s",
- "Contacts" : "Επαφές",
- "You created contact {card} in address book {addressbook}" : "Δημιουργήσατε την επαφή {card} στο βιβλίο διευθύνσεων {addressbook}",
- "You deleted contact {card} from address book {addressbook}" : "Διαγράψατε την επαφή {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>",
- "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.",
- "Configures a CalDAV account" : "Ρυθμίσεις λογαριασμού CalDAV",
- "Configures a CardDAV account" : "Ρυθμίσεις λογαριασμού CardDAV",
- "Events" : "Συμβάντα",
- "Untitled task" : "Εργασία χωρίς όνομα",
- "Completed on %s" : "Ολοκληρώθηκε %s",
- "WebDAV endpoint" : "Τερματικό WebDAV",
- "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Ο διακομιστής σας δεν έχει ρυθμιστεί ακόμη κατάλληλα ώστε να επιτρέπει τον συγχρονισμό αρχείων, διότι η διεπαφή WebDAV φαίνεται να μη λειτουργεί.",
- "Contacts and groups" : "Επαφές και ομάδες",
- "WebDAV" : "WebDAV",
- "Save" : "Αποθήκευση",
- "Time zone:" : "Ζώνη ώρας:",
- "to" : "προς",
- "Delete slot" : "Διαγραφή θέσης",
- "No working hours set" : "Δεν έχει οριστεί ωράριο εργασίας",
- "Monday" : "Δευτέρα",
- "Tuesday" : "Τρίτη",
- "Wednesday" : "Τετάρτη",
- "Thursday" : "Πέμπτη",
- "Friday" : "Παρασκευή",
- "Saturday" : "Σάββατο",
- "Sunday" : "Κυριακή",
- "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Ορισμός αυτόματα της κατάστασης χρήστη σε \"Μην ενοχλείτε\" εκτός διαθεσιμότητας για σίγαση όλων των ειδοποιήσεων.",
- "Failed to load availability" : "Αποτυχία φόρτωσης της διαθεσιμότητας",
- "Failed to save availability" : "Αποτυχία αποθήκευσης της διαθεσιμότητας",
- "Availability" : "Διαθεσιμότητα",
- "Calendar server" : "Διακομιστής ημερολογίου",
- "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." : "Οι υπενθυμίσεις αποστέλλονται πάντα στους διοργανωτές και στους συμμετέχοντες.",
- "Enable notifications for events via push" : "Ενεργοποίηση ειδοποιήσεων μέσω push",
- "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}.",
- "There was an error updating your attendance status." : "Σφάλμα ενημέρωσης κατάστασής σας.",
- "Please contact the organizer directly." : "Παρακαλώ επικοινωνήστε απ' ευθείας με τον διοργανωτή.",
- "Are you accepting the invitation?" : "Αποδέχεστε την πρόσκληση;",
- "Tentative" : "Δοκιμαστικό",
- "Your attendance was updated successfully." : "Η παρουσία σας ενημερώθηκε με επιτυχία.",
- "Time:" : "Ώρα:",
- "If you configure your working hours, other users will see when you are out of office when they book a meeting." : "Εάν διαμορφώσετε τις ώρες εργασίας σας, οι άλλοι χρήστες θα βλέπουν πότε είστε εκτός γραφείου όταν κάνουν κράτηση για μια συνάντηση."
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/el.json b/apps/dav/l10n/el.json
deleted file mode 100644
index 35dc70af33f..00000000000
--- a/apps/dav/l10n/el.json
+++ /dev/null
@@ -1,118 +0,0 @@
-{ "translations": {
- "Calendar" : "Ημερολόγιο",
- "Tasks" : "Εργασίες",
- "Personal" : "Προσωπικά",
- "{actor} created calendar {calendar}" : "{actor} δημιουργήθηκε το ημερολόγιο {calendar}",
- "You created calendar {calendar}" : "Δημιουργήσατε ημερολόγιο {ημερολόγιο}",
- "{actor} deleted calendar {calendar}" : "{actor} διέγραψε το ημερολόγιο {calendar}",
- "You deleted calendar {calendar}" : "Διαγράψατε το ημερολόγιο {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} ενημέρωσε το ημερολόγιο {calendar}",
- "You updated calendar {calendar}" : "Έχετε ενημερώσει το ημερολόγιο {calendar}",
- "You restored calendar {calendar}" : "Επαναφέρατε το ημερολόγιο {calendar}",
- "You shared calendar {calendar} as public link" : "Μοιραστήκατε το ημερολόγιο {calendar} με δημόσιο σύνδεσμο.",
- "You removed public link for calendar {calendar}" : "Αφαιρέσατε τον δημόσιο σύνδεσμο για το ημερολόγιο {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} διαμοιράστηκε το ημερολόγιο {calendar} με εσάς",
- "You shared calendar {calendar} with {user}" : "Διαμοιραστήκατε το ημερολογίου {calendar} με {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} διαμοίρασε το ημερολόγιο {calendar} με {user}",
- "{actor} unshared calendar {calendar} from you" : "Ο {actor} σταμάτησε τον διαμοιρασμό του ημερολογίου {calendar} από εσάς",
- "You unshared calendar {calendar} from {user}" : "Σταματήσατε τον διαμοιρασμό ημερολογίου {calendar} από {user}",
- "{actor} unshared calendar {calendar} from {user}" : "Ο {actor} σταμάτησε τον διαμοιρασμό του ημερολογίου {calendar} από τον χρήστη {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} σταμάτησε το διαμοιρασμένο ημερολόγιο {calendar} από τον εαυτό τους",
- "You shared calendar {calendar} with group {group}" : "Διαμοιραστείκατε ένα ημερολόγιο {calendar} με την ομάδα {group}",
- "{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}",
- "You deleted event {event} from calendar {calendar}" : "Διαγράψατε το συμβάν {event} από το ημερολόγιο {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "Ο {actor} ενημέρωσε το γεγονός {event} στο ημερολόγιο {calendar}",
- "You updated event {event} in calendar {calendar}" : "Ενημερώσατε το συμβάν {event} στο ημερολόγιο {calendar}",
- "Busy" : "Απασχολημένος",
- "Calendar, contacts and tasks" : "Ημερολόγιο, επαφές και εργασίες",
- "A <strong>calendar</strong> was modified" : "Τροποποιήθηκε ένα <strong>ημερολόγιο</strong> ",
- "A calendar <strong>event</strong> was modified" : "Τροποποιήθηκε ένα <strong>γεγονός</strong> του ημερολογίου",
- "A calendar <strong>to-do</strong> was modified" : "Τροποποιήθηκε μια <strong>εκκρεμότητα</strong> ημερολογίου",
- "Contact birthdays" : "Γενέθλια επαφών",
- "Death of %s" : "Θάνατος του %s",
- "Untitled calendar" : "Ημερολόγιο χωρίς τίτλο",
- "Calendar:" : "Ημερολόγιο:",
- "Date:" : "Ημερομηνία:",
- "Where:" : "Που:",
- "Description:" : "Περιγραφή:",
- "_%n year_::_%n years_" : ["%n χρόνος/χρονιά","%n χρόνια"],
- "_%n month_::_%n months_" : ["%n μήνας","%d μήνες"],
- "_%n day_::_%n days_" : ["%n ημέρα","%n ημέρες"],
- "_%n hour_::_%n hours_" : ["%nώρα","%nώρες"],
- "_%n minute_::_%n minutes_" : ["%n λεπτό","%n λεπτά"],
- "%s (in %s)" : "%s (σε %s)",
- "%s (%s ago)" : "%s (%s πριν)",
- "Calendar: %s" : "Ημερολόγιο:%s",
- "Date: %s" : "Ημερομηνία:%s",
- "Description: %s" : "Περιγραφή:%s",
- "Where: %s" : "Που:%s",
- "%1$s via %2$s" : "%1$s μέσω %2$s",
- "Organizer:" : "Διοργανωτής:",
- "Attendees:" : "Συμμετέχοντες:",
- "Title:" : "Τίτλος:",
- "Location:" : "Τοποθεσία:",
- "Link:" : "Σύνδεσμος:",
- "Accept" : "Αποδοχή",
- "Decline" : "Απόρριψη",
- "More options …" : "Περισσότερες επιλογές...",
- "More options at %s" : "Περισσότερες επιλογές στο %s",
- "Contacts" : "Επαφές",
- "You created contact {card} in address book {addressbook}" : "Δημιουργήσατε την επαφή {card} στο βιβλίο διευθύνσεων {addressbook}",
- "You deleted contact {card} from address book {addressbook}" : "Διαγράψατε την επαφή {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>",
- "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.",
- "Configures a CalDAV account" : "Ρυθμίσεις λογαριασμού CalDAV",
- "Configures a CardDAV account" : "Ρυθμίσεις λογαριασμού CardDAV",
- "Events" : "Συμβάντα",
- "Untitled task" : "Εργασία χωρίς όνομα",
- "Completed on %s" : "Ολοκληρώθηκε %s",
- "WebDAV endpoint" : "Τερματικό WebDAV",
- "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Ο διακομιστής σας δεν έχει ρυθμιστεί ακόμη κατάλληλα ώστε να επιτρέπει τον συγχρονισμό αρχείων, διότι η διεπαφή WebDAV φαίνεται να μη λειτουργεί.",
- "Contacts and groups" : "Επαφές και ομάδες",
- "WebDAV" : "WebDAV",
- "Save" : "Αποθήκευση",
- "Time zone:" : "Ζώνη ώρας:",
- "to" : "προς",
- "Delete slot" : "Διαγραφή θέσης",
- "No working hours set" : "Δεν έχει οριστεί ωράριο εργασίας",
- "Monday" : "Δευτέρα",
- "Tuesday" : "Τρίτη",
- "Wednesday" : "Τετάρτη",
- "Thursday" : "Πέμπτη",
- "Friday" : "Παρασκευή",
- "Saturday" : "Σάββατο",
- "Sunday" : "Κυριακή",
- "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Ορισμός αυτόματα της κατάστασης χρήστη σε \"Μην ενοχλείτε\" εκτός διαθεσιμότητας για σίγαση όλων των ειδοποιήσεων.",
- "Failed to load availability" : "Αποτυχία φόρτωσης της διαθεσιμότητας",
- "Failed to save availability" : "Αποτυχία αποθήκευσης της διαθεσιμότητας",
- "Availability" : "Διαθεσιμότητα",
- "Calendar server" : "Διακομιστής ημερολογίου",
- "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." : "Οι υπενθυμίσεις αποστέλλονται πάντα στους διοργανωτές και στους συμμετέχοντες.",
- "Enable notifications for events via push" : "Ενεργοποίηση ειδοποιήσεων μέσω push",
- "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}.",
- "There was an error updating your attendance status." : "Σφάλμα ενημέρωσης κατάστασής σας.",
- "Please contact the organizer directly." : "Παρακαλώ επικοινωνήστε απ' ευθείας με τον διοργανωτή.",
- "Are you accepting the invitation?" : "Αποδέχεστε την πρόσκληση;",
- "Tentative" : "Δοκιμαστικό",
- "Your attendance was updated successfully." : "Η παρουσία σας ενημερώθηκε με επιτυχία.",
- "Time:" : "Ώρα:",
- "If you configure your working hours, other users will see when you are out of office when they book a meeting." : "Εάν διαμορφώσετε τις ώρες εργασίας σας, οι άλλοι χρήστες θα βλέπουν πότε είστε εκτός γραφείου όταν κάνουν κράτηση για μια συνάντηση."
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/en_GB.js b/apps/dav/l10n/en_GB.js
index 8303faf330b..75233b334ed 100644
--- a/apps/dav/l10n/en_GB.js
+++ b/apps/dav/l10n/en_GB.js
@@ -290,6 +290,25 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Pick a start time for {dayName}",
"Pick a end time for {dayName}" : "Pick a end time for {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications.",
+ "Cancel" : "Cancel",
+ "Import" : "Import",
+ "Error while saving settings" : "Error while saving settings",
+ "Contact reset successfully" : "Contact reset successfully",
+ "Error while resetting contact" : "Error while resetting contact",
+ "Contact imported successfully" : "Contact imported successfully",
+ "Error while importing contact" : "Error while importing contact",
+ "Import contact" : "Import contact",
+ "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",
@@ -306,27 +325,12 @@ 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",
- "Cancel" : "Cancel",
- "Import" : "Import",
- "Error while saving settings" : "Error while saving settings",
- "Contact reset successfully" : "Contact reset successfully",
- "Error while resetting contact" : "Error while resetting contact",
- "Contact imported successfully" : "Contact imported successfully",
- "Error while importing contact" : "Error while importing contact",
- "Example Content" : "Example Content",
- "Set example content to be created on new user first login." : "Set example content to be created on new user first login.",
- "Import contact" : "Import contact",
- "Reset to default contact" : "Reset to default contact",
- "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?",
+ "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?",
"Tentative" : "Tentative",
- "Your attendance was updated successfully." : "Your attendance was updated successfully.",
- "Time:" : "Time:",
- "Could not open file" : "Could not open file",
- "Invalid chunk name" : "Invalid chunk name",
- "Could not rename part file assembled from chunks" : "Could not rename part file assembled from chunks"
+ "Your attendance was updated successfully." : "Your attendance was updated successfully."
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/en_GB.json b/apps/dav/l10n/en_GB.json
index 5c826dc4d7f..0fbdf464438 100644
--- a/apps/dav/l10n/en_GB.json
+++ b/apps/dav/l10n/en_GB.json
@@ -288,6 +288,25 @@
"Pick a start time for {dayName}" : "Pick a start time for {dayName}",
"Pick a end time for {dayName}" : "Pick a end time for {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications.",
+ "Cancel" : "Cancel",
+ "Import" : "Import",
+ "Error while saving settings" : "Error while saving settings",
+ "Contact reset successfully" : "Contact reset successfully",
+ "Error while resetting contact" : "Error while resetting contact",
+ "Contact imported successfully" : "Contact imported successfully",
+ "Error while importing contact" : "Error while importing contact",
+ "Import contact" : "Import contact",
+ "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",
@@ -304,27 +323,12 @@
"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",
- "Cancel" : "Cancel",
- "Import" : "Import",
- "Error while saving settings" : "Error while saving settings",
- "Contact reset successfully" : "Contact reset successfully",
- "Error while resetting contact" : "Error while resetting contact",
- "Contact imported successfully" : "Contact imported successfully",
- "Error while importing contact" : "Error while importing contact",
- "Example Content" : "Example Content",
- "Set example content to be created on new user first login." : "Set example content to be created on new user first login.",
- "Import contact" : "Import contact",
- "Reset to default contact" : "Reset to default contact",
- "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?",
+ "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?",
"Tentative" : "Tentative",
- "Your attendance was updated successfully." : "Your attendance was updated successfully.",
- "Time:" : "Time:",
- "Could not open file" : "Could not open file",
- "Invalid chunk name" : "Invalid chunk name",
- "Could not rename part file assembled from chunks" : "Could not rename part file assembled from chunks"
+ "Your attendance was updated successfully." : "Your attendance was updated successfully."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/eo.js b/apps/dav/l10n/eo.js
deleted file mode 100644
index e87ec548476..00000000000
--- a/apps/dav/l10n/eo.js
+++ /dev/null
@@ -1,104 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Kalendaro",
- "Personal" : "Persona",
- "{actor} created calendar {calendar}" : "{actor} kreis kalendaron {calendar}",
- "You created calendar {calendar}" : "Vi kreis kalendaron {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} forigis kalendaron {calendar}",
- "You deleted calendar {calendar}" : "Vi forigis kalendaron {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} ĝisdatigis kalendaron {calendar}",
- "You updated calendar {calendar}" : "Vi ĝisdatigis kalendaron {calendar}",
- "You shared calendar {calendar} as public link" : "Vi kunhavigis kalendaron {calendar} per publika ligilo",
- "You removed public link for calendar {calendar}" : "Vi forigis publikan ligilon por kalendaro {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} kunhavigis kalendaron {calendar} kun vi",
- "You shared calendar {calendar} with {user}" : "Vi kunhavigis kalendaron {calendar} kun {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} kunhavigis kalendaron {calendar} kun {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} malkunhavigis kalendaron {calendar} kun vi",
- "You unshared calendar {calendar} from {user}" : "Vi malkunhavigis kalendaron {calendar} kun {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} malkunhavigis kalendaron {calendar} kun {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} malkunhavigis kalendaron {calendar} kun si mem",
- "You shared calendar {calendar} with group {group}" : "Vi kunhavigis kalendaron {calendar} kun grupo {group}",
- "{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}",
- "You deleted event {event} from calendar {calendar}" : "Vi forigis okazaĵon {event} en kalendaro {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} ĝisdatigis okazaĵon {event} en kalendaro {calendar}",
- "You updated event {event} in calendar {calendar}" : "Vi ĝisdatigis okazaĵon {event} en kalendaro {calendar}",
- "Busy" : "Okupita",
- "A <strong>calendar</strong> was modified" : "<strong>Kalendaro</strong> estis modifita",
- "A calendar <strong>event</strong> was modified" : "Kalendara <strong>okazaĵo</strong> estis modifita",
- "Contact birthdays" : "Kontaktaj datrevenoj",
- "Death of %s" : "Morto de %s",
- "Calendar:" : "Kalendaro:",
- "Date:" : "Dato:",
- "Where:" : "Kie:",
- "Description:" : "Priskribo:",
- "_%n year_::_%n years_" : ["%n jaro","%n jaroj"],
- "_%n month_::_%n months_" : ["%n monato","%n monatoj"],
- "_%n day_::_%n days_" : ["%n tago","%n tagoj"],
- "_%n hour_::_%n hours_" : ["%n horo","%n horoj"],
- "_%n minute_::_%n minutes_" : ["%n minuto","%n minutoj"],
- "%s (in %s)" : "%s (en %s)",
- "%s (%s ago)" : "%s (antaŭ %s)",
- "Calendar: %s" : "Kalendaro: %s",
- "Date: %s" : "Dato: %s",
- "Description: %s" : "Priskribo: %s",
- "Where: %s" : "Kie: %s",
- "%1$s via %2$s" : "%1$s pere de %2$s",
- "Location:" : "Loko:",
- "Link:" : "Ligilo:",
- "Accept" : "Akcepti",
- "Decline" : "Malakcepti",
- "More options …" : "Pli da opcioj...",
- "More options at %s" : "Pli da opcioj je %s",
- "Contacts" : "Kontaktoj",
- "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Via %s uzu HTTPS, por ke vi povu uzi CalDAV kaj CardDAV kun iOS aŭ macOS.",
- "Configures a CalDAV account" : "Agordas CalDAV-konton.",
- "Configures a CardDAV account" : "Agordas CardlDAV-konton.",
- "Tasks" : "Taskoj",
- "WebDAV" : "WebDAV",
- "WebDAV endpoint" : "WebDAV-finpunkto",
- "to" : "al",
- "Monday" : "lundo",
- "Tuesday" : "mardo",
- "Wednesday" : "merkredo",
- "Thursday" : "ĵaŭdo",
- "Friday" : "vendredo",
- "Saturday" : "sabato",
- "Sunday" : "dimanĉo",
- "Save" : "Konservi",
- "Calendar server" : "Kalendara servilo",
- "Send invitations to attendees" : "Sendi invitojn al ĉeestantoj",
- "Automatically generate a birthday calendar" : "Aŭtomate estigi datrevenan kalendaron",
- "Birthday calendars will be generated by a background job." : "Datrevenaj kalendaroj estos kreitaj de fona tasko.",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Tial, ili disponeblos nur post kelke da tempo.",
- "Send notifications for events" : "Sendi sciigojn pri okazaĵoj",
- "Enable notifications for events via push" : "Ebligi sciigojn pri okazaĵoj per puŝteĥniko",
- "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Ankaŭ instalu la aplikaĵon {calendarappstoreopen}Kalendaro{linkclose} aŭ {calendardocopen}konektu vian surtablan kaj porteblan aparaton por eksinkronigi ↗{linkclose}.",
- "Please make sure to properly set up {emailopen}the email server{linkclose}." : "Bv. certigi, ke via {emailopen}retpoŝtserva servilo{linkclose} estas bone agordita.",
- "There was an error updating your attendance status." : "Estis eraro dum ĝisdatigo de via ĉeesta stato.",
- "Please contact the organizer directly." : "Bv. senpere kontakti la organizanton.",
- "Are you accepting the invitation?" : "Ĉu vi akceptas la inviton?",
- "Tentative" : "Nekonfirmita",
- "Your attendance was updated successfully." : "Via ĉeesto sukcese ĝisdatiĝis.",
- "Todos" : "Taskoj",
- "{actor} created todo {todo} in list {calendar}" : "{actor} kreis farendaĵon {todo} en listo {calendar}",
- "You created todo {todo} in list {calendar}" : "Vi kreis farendaĵon {todo} en listo {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} forigis farendaĵon {todo} en listo {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Vi forigis farendaĵon {todo} en listo {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} ĝisdatigis farendaĵon {todo} en listo {calendar}",
- "You updated todo {todo} in list {calendar}" : "Vi ĝisdatigis farendaĵon {todo} en listo {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} plenumis farendaĵon {todo} en listo {calendar}",
- "You solved todo {todo} in list {calendar}" : "Vi plenumis farendaĵon {todo} en listo {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} remalfermis farendaĵon {todo} en listo {calendar}",
- "You reopened todo {todo} in list {calendar}" : "Vi remalfermis farendaĵon {todo} en listo {calendar}",
- "A calendar <strong>todo</strong> was modified" : "Kalendara <strong>farendaĵo</strong> estis modifita",
- "Invitation canceled" : "Invito nuligita",
- "Invitation updated" : "Invito ĝisdatigita"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/eo.json b/apps/dav/l10n/eo.json
deleted file mode 100644
index 67fd37faca9..00000000000
--- a/apps/dav/l10n/eo.json
+++ /dev/null
@@ -1,102 +0,0 @@
-{ "translations": {
- "Calendar" : "Kalendaro",
- "Personal" : "Persona",
- "{actor} created calendar {calendar}" : "{actor} kreis kalendaron {calendar}",
- "You created calendar {calendar}" : "Vi kreis kalendaron {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} forigis kalendaron {calendar}",
- "You deleted calendar {calendar}" : "Vi forigis kalendaron {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} ĝisdatigis kalendaron {calendar}",
- "You updated calendar {calendar}" : "Vi ĝisdatigis kalendaron {calendar}",
- "You shared calendar {calendar} as public link" : "Vi kunhavigis kalendaron {calendar} per publika ligilo",
- "You removed public link for calendar {calendar}" : "Vi forigis publikan ligilon por kalendaro {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} kunhavigis kalendaron {calendar} kun vi",
- "You shared calendar {calendar} with {user}" : "Vi kunhavigis kalendaron {calendar} kun {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} kunhavigis kalendaron {calendar} kun {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} malkunhavigis kalendaron {calendar} kun vi",
- "You unshared calendar {calendar} from {user}" : "Vi malkunhavigis kalendaron {calendar} kun {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} malkunhavigis kalendaron {calendar} kun {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} malkunhavigis kalendaron {calendar} kun si mem",
- "You shared calendar {calendar} with group {group}" : "Vi kunhavigis kalendaron {calendar} kun grupo {group}",
- "{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}",
- "You deleted event {event} from calendar {calendar}" : "Vi forigis okazaĵon {event} en kalendaro {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} ĝisdatigis okazaĵon {event} en kalendaro {calendar}",
- "You updated event {event} in calendar {calendar}" : "Vi ĝisdatigis okazaĵon {event} en kalendaro {calendar}",
- "Busy" : "Okupita",
- "A <strong>calendar</strong> was modified" : "<strong>Kalendaro</strong> estis modifita",
- "A calendar <strong>event</strong> was modified" : "Kalendara <strong>okazaĵo</strong> estis modifita",
- "Contact birthdays" : "Kontaktaj datrevenoj",
- "Death of %s" : "Morto de %s",
- "Calendar:" : "Kalendaro:",
- "Date:" : "Dato:",
- "Where:" : "Kie:",
- "Description:" : "Priskribo:",
- "_%n year_::_%n years_" : ["%n jaro","%n jaroj"],
- "_%n month_::_%n months_" : ["%n monato","%n monatoj"],
- "_%n day_::_%n days_" : ["%n tago","%n tagoj"],
- "_%n hour_::_%n hours_" : ["%n horo","%n horoj"],
- "_%n minute_::_%n minutes_" : ["%n minuto","%n minutoj"],
- "%s (in %s)" : "%s (en %s)",
- "%s (%s ago)" : "%s (antaŭ %s)",
- "Calendar: %s" : "Kalendaro: %s",
- "Date: %s" : "Dato: %s",
- "Description: %s" : "Priskribo: %s",
- "Where: %s" : "Kie: %s",
- "%1$s via %2$s" : "%1$s pere de %2$s",
- "Location:" : "Loko:",
- "Link:" : "Ligilo:",
- "Accept" : "Akcepti",
- "Decline" : "Malakcepti",
- "More options …" : "Pli da opcioj...",
- "More options at %s" : "Pli da opcioj je %s",
- "Contacts" : "Kontaktoj",
- "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Via %s uzu HTTPS, por ke vi povu uzi CalDAV kaj CardDAV kun iOS aŭ macOS.",
- "Configures a CalDAV account" : "Agordas CalDAV-konton.",
- "Configures a CardDAV account" : "Agordas CardlDAV-konton.",
- "Tasks" : "Taskoj",
- "WebDAV" : "WebDAV",
- "WebDAV endpoint" : "WebDAV-finpunkto",
- "to" : "al",
- "Monday" : "lundo",
- "Tuesday" : "mardo",
- "Wednesday" : "merkredo",
- "Thursday" : "ĵaŭdo",
- "Friday" : "vendredo",
- "Saturday" : "sabato",
- "Sunday" : "dimanĉo",
- "Save" : "Konservi",
- "Calendar server" : "Kalendara servilo",
- "Send invitations to attendees" : "Sendi invitojn al ĉeestantoj",
- "Automatically generate a birthday calendar" : "Aŭtomate estigi datrevenan kalendaron",
- "Birthday calendars will be generated by a background job." : "Datrevenaj kalendaroj estos kreitaj de fona tasko.",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Tial, ili disponeblos nur post kelke da tempo.",
- "Send notifications for events" : "Sendi sciigojn pri okazaĵoj",
- "Enable notifications for events via push" : "Ebligi sciigojn pri okazaĵoj per puŝteĥniko",
- "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Ankaŭ instalu la aplikaĵon {calendarappstoreopen}Kalendaro{linkclose} aŭ {calendardocopen}konektu vian surtablan kaj porteblan aparaton por eksinkronigi ↗{linkclose}.",
- "Please make sure to properly set up {emailopen}the email server{linkclose}." : "Bv. certigi, ke via {emailopen}retpoŝtserva servilo{linkclose} estas bone agordita.",
- "There was an error updating your attendance status." : "Estis eraro dum ĝisdatigo de via ĉeesta stato.",
- "Please contact the organizer directly." : "Bv. senpere kontakti la organizanton.",
- "Are you accepting the invitation?" : "Ĉu vi akceptas la inviton?",
- "Tentative" : "Nekonfirmita",
- "Your attendance was updated successfully." : "Via ĉeesto sukcese ĝisdatiĝis.",
- "Todos" : "Taskoj",
- "{actor} created todo {todo} in list {calendar}" : "{actor} kreis farendaĵon {todo} en listo {calendar}",
- "You created todo {todo} in list {calendar}" : "Vi kreis farendaĵon {todo} en listo {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} forigis farendaĵon {todo} en listo {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Vi forigis farendaĵon {todo} en listo {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} ĝisdatigis farendaĵon {todo} en listo {calendar}",
- "You updated todo {todo} in list {calendar}" : "Vi ĝisdatigis farendaĵon {todo} en listo {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} plenumis farendaĵon {todo} en listo {calendar}",
- "You solved todo {todo} in list {calendar}" : "Vi plenumis farendaĵon {todo} en listo {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} remalfermis farendaĵon {todo} en listo {calendar}",
- "You reopened todo {todo} in list {calendar}" : "Vi remalfermis farendaĵon {todo} en listo {calendar}",
- "A calendar <strong>todo</strong> was modified" : "Kalendara <strong>farendaĵo</strong> estis modifita",
- "Invitation canceled" : "Invito nuligita",
- "Invitation updated" : "Invito ĝisdatigita"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/es.js b/apps/dav/l10n/es.js
index 39dc736727d..22365efe29b 100644
--- a/apps/dav/l10n/es.js
+++ b/apps/dav/l10n/es.js
@@ -285,6 +285,10 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Elija una hora de inicio para {dayName}",
"Pick a end time for {dayName}" : "Elija una hora fin para {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Cambiar automáticamente el estado del usuario a \"No molestar\" cuando no esté disponible para silenciar todas las notificaciones.",
+ "Cancel" : "Cancelar",
+ "Import" : "Importar",
+ "Error while saving settings" : "Error al guardar los ajustes",
+ "Reset to default" : "Reestablecer a predeterminado",
"Availability" : "Disponibilidad",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Si configura sus horas laborales, otras personas verán cuando está fuera de la oficina cuando agenden una reunión.",
"Absence" : "Ausencia",
@@ -301,17 +305,10 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Enviar recordatorio también a los usuarios con los que se comparte el calendario",
"Reminders are always sent to organizers and attendees." : "Los recordatorios siempre se envían a los organizadores y asistentes.",
"Enable notifications for events via push" : "Activar notificaciones push para eventos",
- "Cancel" : "Cancelar",
- "Import" : "Importar",
- "Error while saving settings" : "Error al guardar los ajustes",
"There was an error updating your attendance status." : "Ha habido un error al actualizar tu estado de asistencia.",
"Please contact the organizer directly." : "Por favor, contacta directamente con el organizador.",
"Are you accepting the invitation?" : "¿Aceptas la invitación?",
"Tentative" : "Provisional",
- "Your attendance was updated successfully." : "Tu asistencia se ha actualizado con éxito.",
- "Time:" : "Hora:",
- "Could not open file" : "No se ha podido abrir el archivo",
- "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"
+ "Your attendance was updated successfully." : "Tu asistencia se ha actualizado con éxito."
},
"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 9a717e4eaca..bed92b5fd76 100644
--- a/apps/dav/l10n/es.json
+++ b/apps/dav/l10n/es.json
@@ -283,6 +283,10 @@
"Pick a start time for {dayName}" : "Elija una hora de inicio para {dayName}",
"Pick a end time for {dayName}" : "Elija una hora fin para {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Cambiar automáticamente el estado del usuario a \"No molestar\" cuando no esté disponible para silenciar todas las notificaciones.",
+ "Cancel" : "Cancelar",
+ "Import" : "Importar",
+ "Error while saving settings" : "Error al guardar los ajustes",
+ "Reset to default" : "Reestablecer a predeterminado",
"Availability" : "Disponibilidad",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Si configura sus horas laborales, otras personas verán cuando está fuera de la oficina cuando agenden una reunión.",
"Absence" : "Ausencia",
@@ -299,17 +303,10 @@
"Send reminder notifications to calendar sharees as well" : "Enviar recordatorio también a los usuarios con los que se comparte el calendario",
"Reminders are always sent to organizers and attendees." : "Los recordatorios siempre se envían a los organizadores y asistentes.",
"Enable notifications for events via push" : "Activar notificaciones push para eventos",
- "Cancel" : "Cancelar",
- "Import" : "Importar",
- "Error while saving settings" : "Error al guardar los ajustes",
"There was an error updating your attendance status." : "Ha habido un error al actualizar tu estado de asistencia.",
"Please contact the organizer directly." : "Por favor, contacta directamente con el organizador.",
"Are you accepting the invitation?" : "¿Aceptas la invitación?",
"Tentative" : "Provisional",
- "Your attendance was updated successfully." : "Tu asistencia se ha actualizado con éxito.",
- "Time:" : "Hora:",
- "Could not open file" : "No se ha podido abrir el archivo",
- "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"
+ "Your attendance was updated successfully." : "Tu asistencia se ha actualizado con éxito."
},"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/es_419.js b/apps/dav/l10n/es_419.js
deleted file mode 100644
index ba78d8940a8..00000000000
--- a/apps/dav/l10n/es_419.js
+++ /dev/null
@@ -1,66 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/es_419.json b/apps/dav/l10n/es_419.json
deleted file mode 100644
index ec79fad2802..00000000000
--- a/apps/dav/l10n/es_419.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{ "translations": {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/es_AR.js b/apps/dav/l10n/es_AR.js
deleted file mode 100644
index b15ab1b367e..00000000000
--- a/apps/dav/l10n/es_AR.js
+++ /dev/null
@@ -1,56 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Usted creó el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Usted borró el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Usted actualizó el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} con usted",
- "You shared calendar {calendar} with {user}" : "Usted ha compartido el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} con usted",
- "You unshared calendar {calendar} from {user}" : "Usted ha dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Usted ha compartido el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Usted ha dejado de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{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} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Usted borró el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Usted actualizó el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Usted creo el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Usted borró el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Usted actualizó el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Usted resolvió el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Usted reabrió el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Hello %s," : "Hola %s:",
- "Link:" : "Link:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Technical details" : "Detalles técnicos",
- "Remote Address: %s" : "Dirección remota: %s",
- "Request ID: %s" : "ID de solicitud: %s"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/es_AR.json b/apps/dav/l10n/es_AR.json
deleted file mode 100644
index 40f99876c49..00000000000
--- a/apps/dav/l10n/es_AR.json
+++ /dev/null
@@ -1,54 +0,0 @@
-{ "translations": {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Usted creó el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Usted borró el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Usted actualizó el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} con usted",
- "You shared calendar {calendar} with {user}" : "Usted ha compartido el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} con usted",
- "You unshared calendar {calendar} from {user}" : "Usted ha dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Usted ha compartido el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Usted ha dejado de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{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} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Usted borró el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Usted actualizó el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Usted creo el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Usted borró el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Usted actualizó el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Usted resolvió el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Usted reabrió el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Hello %s," : "Hola %s:",
- "Link:" : "Link:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Technical details" : "Detalles técnicos",
- "Remote Address: %s" : "Dirección remota: %s",
- "Request ID: %s" : "ID de solicitud: %s"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/es_CL.js b/apps/dav/l10n/es_CL.js
deleted file mode 100644
index ba78d8940a8..00000000000
--- a/apps/dav/l10n/es_CL.js
+++ /dev/null
@@ -1,66 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/es_CL.json b/apps/dav/l10n/es_CL.json
deleted file mode 100644
index ec79fad2802..00000000000
--- a/apps/dav/l10n/es_CL.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{ "translations": {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/es_CO.js b/apps/dav/l10n/es_CO.js
deleted file mode 100644
index ba78d8940a8..00000000000
--- a/apps/dav/l10n/es_CO.js
+++ /dev/null
@@ -1,66 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/es_CO.json b/apps/dav/l10n/es_CO.json
deleted file mode 100644
index ec79fad2802..00000000000
--- a/apps/dav/l10n/es_CO.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{ "translations": {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/es_CR.js b/apps/dav/l10n/es_CR.js
deleted file mode 100644
index ba78d8940a8..00000000000
--- a/apps/dav/l10n/es_CR.js
+++ /dev/null
@@ -1,66 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/es_CR.json b/apps/dav/l10n/es_CR.json
deleted file mode 100644
index ec79fad2802..00000000000
--- a/apps/dav/l10n/es_CR.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{ "translations": {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/es_DO.js b/apps/dav/l10n/es_DO.js
deleted file mode 100644
index ba78d8940a8..00000000000
--- a/apps/dav/l10n/es_DO.js
+++ /dev/null
@@ -1,66 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/es_DO.json b/apps/dav/l10n/es_DO.json
deleted file mode 100644
index ec79fad2802..00000000000
--- a/apps/dav/l10n/es_DO.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{ "translations": {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/es_EC.js b/apps/dav/l10n/es_EC.js
index bf69429e716..bc36002e1e8 100644
--- a/apps/dav/l10n/es_EC.js
+++ b/apps/dav/l10n/es_EC.js
@@ -182,6 +182,10 @@ OC.L10N.register(
"No working hours set" : "No se han establecido horas de trabajo",
"Add slot" : "Agregar ranura",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Configurar automáticamente el estado del usuario como \"No molestar\" fuera de la disponibilidad para silenciar todas las notificaciones.",
+ "Cancel" : "Cancelar",
+ "Import" : "Importar",
+ "Error while saving settings" : "Error al guardar la configuración.",
+ "Reset to default" : "Restablecer al predeterminado",
"Availability" : "Disponibilidad",
"Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "También instala la {calendarappstoreopen}aplicación Calendario{linkclose}, o {calendardocopen}conecta tu escritorio y móvil para sincronizar ↗{linkclose}.",
"Please make sure to properly set up {emailopen}the email server{linkclose}." : "Asegúrate de configurar correctamente {emailopen}el servidor de correo electrónico{linkclose}.",
@@ -195,17 +199,10 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Enviar recordatorios a los asistentes del calendario también",
"Reminders are always sent to organizers and attendees." : "Los recordatorios siempre se envían a los organizadores y asistentes.",
"Enable notifications for events via push" : "Habilitar notificaciones para eventos mediante push",
- "Cancel" : "Cancelar",
- "Import" : "Importar",
- "Error while saving settings" : "Error al guardar la configuración.",
"There was an error updating your attendance status." : "Hubo un error al actualizar tu estado de asistencia.",
"Please contact the organizer directly." : "Por favor, contacta directamente al organizador.",
"Are you accepting the invitation?" : "¿Aceptas la invitación?",
"Tentative" : "Tentativo",
- "Your attendance was updated successfully." : "Tu asistencia se actualizó correctamente.",
- "Time:" : "Hora:",
- "Could not open file" : "No se pudo abrir el archivo",
- "Invalid chunk name" : "Nombre de fragmento no válido",
- "Could not rename part file assembled from chunks" : "No se pudo renombrar el archivo parcial ensamblado a archivo final"
+ "Your attendance was updated successfully." : "Tu asistencia se actualizó correctamente."
},
"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/dav/l10n/es_EC.json b/apps/dav/l10n/es_EC.json
index 2a496cbc268..5e04a22c11b 100644
--- a/apps/dav/l10n/es_EC.json
+++ b/apps/dav/l10n/es_EC.json
@@ -180,6 +180,10 @@
"No working hours set" : "No se han establecido horas de trabajo",
"Add slot" : "Agregar ranura",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Configurar automáticamente el estado del usuario como \"No molestar\" fuera de la disponibilidad para silenciar todas las notificaciones.",
+ "Cancel" : "Cancelar",
+ "Import" : "Importar",
+ "Error while saving settings" : "Error al guardar la configuración.",
+ "Reset to default" : "Restablecer al predeterminado",
"Availability" : "Disponibilidad",
"Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "También instala la {calendarappstoreopen}aplicación Calendario{linkclose}, o {calendardocopen}conecta tu escritorio y móvil para sincronizar ↗{linkclose}.",
"Please make sure to properly set up {emailopen}the email server{linkclose}." : "Asegúrate de configurar correctamente {emailopen}el servidor de correo electrónico{linkclose}.",
@@ -193,17 +197,10 @@
"Send reminder notifications to calendar sharees as well" : "Enviar recordatorios a los asistentes del calendario también",
"Reminders are always sent to organizers and attendees." : "Los recordatorios siempre se envían a los organizadores y asistentes.",
"Enable notifications for events via push" : "Habilitar notificaciones para eventos mediante push",
- "Cancel" : "Cancelar",
- "Import" : "Importar",
- "Error while saving settings" : "Error al guardar la configuración.",
"There was an error updating your attendance status." : "Hubo un error al actualizar tu estado de asistencia.",
"Please contact the organizer directly." : "Por favor, contacta directamente al organizador.",
"Are you accepting the invitation?" : "¿Aceptas la invitación?",
"Tentative" : "Tentativo",
- "Your attendance was updated successfully." : "Tu asistencia se actualizó correctamente.",
- "Time:" : "Hora:",
- "Could not open file" : "No se pudo abrir el archivo",
- "Invalid chunk name" : "Nombre de fragmento no válido",
- "Could not rename part file assembled from chunks" : "No se pudo renombrar el archivo parcial ensamblado a archivo final"
+ "Your attendance was updated successfully." : "Tu asistencia se actualizó correctamente."
},"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/es_GT.js b/apps/dav/l10n/es_GT.js
deleted file mode 100644
index ba78d8940a8..00000000000
--- a/apps/dav/l10n/es_GT.js
+++ /dev/null
@@ -1,66 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/es_GT.json b/apps/dav/l10n/es_GT.json
deleted file mode 100644
index ec79fad2802..00000000000
--- a/apps/dav/l10n/es_GT.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{ "translations": {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/es_HN.js b/apps/dav/l10n/es_HN.js
deleted file mode 100644
index ba78d8940a8..00000000000
--- a/apps/dav/l10n/es_HN.js
+++ /dev/null
@@ -1,66 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/es_HN.json b/apps/dav/l10n/es_HN.json
deleted file mode 100644
index ec79fad2802..00000000000
--- a/apps/dav/l10n/es_HN.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{ "translations": {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/es_MX.js b/apps/dav/l10n/es_MX.js
index 3815d91f708..4c58640df1a 100644
--- a/apps/dav/l10n/es_MX.js
+++ b/apps/dav/l10n/es_MX.js
@@ -220,6 +220,10 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Elija una hora de inicio para {dayName}",
"Pick a end time for {dayName}" : "Elija una hora fin para {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Establecer automáticamente el estado de usuario como \"No molestar\" fuera de la disponibilidad para silenciar todas las notificaciones.",
+ "Cancel" : "Cancelar",
+ "Import" : "Importar",
+ "Error while saving settings" : "Error al guardar la configuración",
+ "Reset to default" : "Restablecer al predeterminado",
"Availability" : "Disponibilidad",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Si configura sus horas laborales, otras personas verán cuándo está fuera de la oficina cuando agenden una reunión.",
"Absence" : "Ausencia",
@@ -236,17 +240,10 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Enviar recordatorio también a los usuarios con los que se comparte el calendario",
"Reminders are always sent to organizers and attendees." : "Los recordatorios se envían siempre a los organizadores y asistentes.",
"Enable notifications for events via push" : "Habilitar notificaciones para eventos mediante push",
- "Cancel" : "Cancelar",
- "Import" : "Importar",
- "Error while saving settings" : "Error al guardar la configuración",
"There was an error updating your attendance status." : "Ocurrió un error al actualizar su estado de asistencia.",
"Please contact the organizer directly." : "Por favor, contacte al organizador directamente.",
"Are you accepting the invitation?" : "¿Acepta la invitación?",
"Tentative" : "Tentativo",
- "Your attendance was updated successfully." : "Su asistencia se actualizó correctamente.",
- "Time:" : "Hora:",
- "Could not open file" : "No se pudo abrir el archivo",
- "Invalid chunk name" : "Nombre de fragmento inválido",
- "Could not rename part file assembled from chunks" : "No se pudo renombrar el archivo parcial ensamblado por fragmentos"
+ "Your attendance was updated successfully." : "Su asistencia se actualizó correctamente."
},
"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/dav/l10n/es_MX.json b/apps/dav/l10n/es_MX.json
index ce57525938b..646747cfc68 100644
--- a/apps/dav/l10n/es_MX.json
+++ b/apps/dav/l10n/es_MX.json
@@ -218,6 +218,10 @@
"Pick a start time for {dayName}" : "Elija una hora de inicio para {dayName}",
"Pick a end time for {dayName}" : "Elija una hora fin para {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Establecer automáticamente el estado de usuario como \"No molestar\" fuera de la disponibilidad para silenciar todas las notificaciones.",
+ "Cancel" : "Cancelar",
+ "Import" : "Importar",
+ "Error while saving settings" : "Error al guardar la configuración",
+ "Reset to default" : "Restablecer al predeterminado",
"Availability" : "Disponibilidad",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Si configura sus horas laborales, otras personas verán cuándo está fuera de la oficina cuando agenden una reunión.",
"Absence" : "Ausencia",
@@ -234,17 +238,10 @@
"Send reminder notifications to calendar sharees as well" : "Enviar recordatorio también a los usuarios con los que se comparte el calendario",
"Reminders are always sent to organizers and attendees." : "Los recordatorios se envían siempre a los organizadores y asistentes.",
"Enable notifications for events via push" : "Habilitar notificaciones para eventos mediante push",
- "Cancel" : "Cancelar",
- "Import" : "Importar",
- "Error while saving settings" : "Error al guardar la configuración",
"There was an error updating your attendance status." : "Ocurrió un error al actualizar su estado de asistencia.",
"Please contact the organizer directly." : "Por favor, contacte al organizador directamente.",
"Are you accepting the invitation?" : "¿Acepta la invitación?",
"Tentative" : "Tentativo",
- "Your attendance was updated successfully." : "Su asistencia se actualizó correctamente.",
- "Time:" : "Hora:",
- "Could not open file" : "No se pudo abrir el archivo",
- "Invalid chunk name" : "Nombre de fragmento inválido",
- "Could not rename part file assembled from chunks" : "No se pudo renombrar el archivo parcial ensamblado por fragmentos"
+ "Your attendance was updated successfully." : "Su asistencia se actualizó correctamente."
},"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/es_NI.js b/apps/dav/l10n/es_NI.js
deleted file mode 100644
index ba78d8940a8..00000000000
--- a/apps/dav/l10n/es_NI.js
+++ /dev/null
@@ -1,66 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/es_NI.json b/apps/dav/l10n/es_NI.json
deleted file mode 100644
index ec79fad2802..00000000000
--- a/apps/dav/l10n/es_NI.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{ "translations": {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/es_PA.js b/apps/dav/l10n/es_PA.js
deleted file mode 100644
index ba78d8940a8..00000000000
--- a/apps/dav/l10n/es_PA.js
+++ /dev/null
@@ -1,66 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/es_PA.json b/apps/dav/l10n/es_PA.json
deleted file mode 100644
index ec79fad2802..00000000000
--- a/apps/dav/l10n/es_PA.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{ "translations": {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/es_PE.js b/apps/dav/l10n/es_PE.js
deleted file mode 100644
index ba78d8940a8..00000000000
--- a/apps/dav/l10n/es_PE.js
+++ /dev/null
@@ -1,66 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/es_PE.json b/apps/dav/l10n/es_PE.json
deleted file mode 100644
index ec79fad2802..00000000000
--- a/apps/dav/l10n/es_PE.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{ "translations": {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/es_PR.js b/apps/dav/l10n/es_PR.js
deleted file mode 100644
index ba78d8940a8..00000000000
--- a/apps/dav/l10n/es_PR.js
+++ /dev/null
@@ -1,66 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/es_PR.json b/apps/dav/l10n/es_PR.json
deleted file mode 100644
index ec79fad2802..00000000000
--- a/apps/dav/l10n/es_PR.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{ "translations": {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/es_PY.js b/apps/dav/l10n/es_PY.js
deleted file mode 100644
index ba78d8940a8..00000000000
--- a/apps/dav/l10n/es_PY.js
+++ /dev/null
@@ -1,66 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/es_PY.json b/apps/dav/l10n/es_PY.json
deleted file mode 100644
index ec79fad2802..00000000000
--- a/apps/dav/l10n/es_PY.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{ "translations": {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/es_SV.js b/apps/dav/l10n/es_SV.js
deleted file mode 100644
index ba78d8940a8..00000000000
--- a/apps/dav/l10n/es_SV.js
+++ /dev/null
@@ -1,66 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/es_SV.json b/apps/dav/l10n/es_SV.json
deleted file mode 100644
index ec79fad2802..00000000000
--- a/apps/dav/l10n/es_SV.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{ "translations": {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/es_UY.js b/apps/dav/l10n/es_UY.js
deleted file mode 100644
index ba78d8940a8..00000000000
--- a/apps/dav/l10n/es_UY.js
+++ /dev/null
@@ -1,66 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/es_UY.json b/apps/dav/l10n/es_UY.json
deleted file mode 100644
index ec79fad2802..00000000000
--- a/apps/dav/l10n/es_UY.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{ "translations": {
- "Calendar" : "Calendario",
- "Todos" : "Pendientes",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} creó el calendario {calendar}",
- "You created calendar {calendar}" : "Creaste el calendario {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} borró el calendario {calendar}",
- "You deleted calendar {calendar}" : "Borraste el calendario {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} actualizó el calendario {calendar}",
- "You updated calendar {calendar}" : "Actualizaste el calendario {calendar}",
- "You shared calendar {calendar} as public link" : "Compartiste el calendario {calendar} como una liga pública",
- "You removed public link for calendar {calendar}" : "Eliminaste la liga pública para el calendario {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} ha compartido el calendario {calendar} contigo",
- "You shared calendar {calendar} with {user}" : "Compartiste el calendario {calendar} con {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} compartió el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ha dejado de compartir el calendario {calendar} contigo",
- "You unshared calendar {calendar} from {user}" : "Has dejado de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} dejó de compartir el calendario {calendar} con {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} dejó de compartir {el calendario calendar} con él mismo",
- "You shared calendar {calendar} with group {group}" : "Compartiste el calendario {calendar} con el grupo {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} compartió el calendario {calendar} con el grupo {group}",
- "You unshared calendar {calendar} from group {group}" : "Dejaste de compartir el calendario {calendar} con el grupo {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} dejó de compartir el calendrio {calendar} con el grupo {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} creó el evento {event} en el calendario {calendar}",
- "You created event {event} in calendar {calendar}" : "Creaste el evento {event} en el calendario {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} borró el eventó {event} del calendario {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Borraste el evento {event} del calendario {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} actualizó el evento {event} en el calendario {calendar}",
- "You updated event {event} in calendar {calendar}" : "Actualizaste el evento {event} en el calendario {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} creó el pendiente {todo} en la lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Creaste el pendiente {todo} en la lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} borró el pendiente {todo} de la lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Borraste el pendiente {todo} de la lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} actualizó el pendiente {todo} de la lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Actualizaste el pendiente {todo} de la lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} resolvió el pendiente {todo} de la lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Resolviste el pendiente {todo} de la lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} reabrió el pendiente {todo} de la lista{calendar}",
- "You reopened todo {todo} in list {calendar}" : "Reabriste el pendiente {todo} de la lista {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendario</strong> fue modificado",
- "A calendar <strong>event</strong> was modified" : "Un <strong>evento</strong> de un calendario fue modificado",
- "A calendar <strong>todo</strong> was modified" : "Un <strong>pendiente</strong> de un calendario fue modificado",
- "Contact birthdays" : "Cumpleaños del contacto",
- "Where:" : "Dónde:",
- "Description:" : "Descripción:",
- "Invitation canceled" : "Invitación cancelada",
- "Invitation updated" : "Invitación actualizada",
- "Location:" : "Ubicación:",
- "Link:" : "Enlace:",
- "Accept" : "Aceptar",
- "Decline" : "Declinar",
- "Contacts" : "Contactos",
- "Tasks" : "Tareas",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativo",
- "Save" : "Guardar",
- "Send invitations to attendees" : "Enviar invitaciones a los asistentes",
- "Automatically generate a birthday calendar" : "Generar automaticamente un calendario para cumpleaños",
- "Birthday calendars will be generated by a background job." : "Los calendarios de cumpleaños serán generados por un trabajo de segundo plano",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Por lo tanto no estarán disponbiles inmediatamente después de habilitarlos pero se mostrarán después de un tiempo.",
- "Hello %s," : "Hola %s,",
- "When:" : "Cuándo:"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/et_EE.js b/apps/dav/l10n/et_EE.js
index d32f6895bc3..9935e3357df 100644
--- a/apps/dav/l10n/et_EE.js
+++ b/apps/dav/l10n/et_EE.js
@@ -31,7 +31,11 @@ OC.L10N.register(
"{actor} deleted event {event} from calendar {calendar}" : "{actor} kustutas sündmuse {event} kalendrist {calendar}",
"You deleted event {event} from calendar {calendar}" : "Sa kustutasid sündmuse {event} kalendrist {calendar}",
"{actor} updated event {event} in calendar {calendar}" : "{actor} uuendas sündmust {event} kalendris {calendar}",
- "You updated event {event} in calendar {calendar}" : "Sa uuendasid sündmust {event} kalendris {calendar}",
+ "You updated event {event} in calendar {calendar}" : "Sa uuendasid „{event}“ sündmust „{calendar}“ kalendris",
+ "{actor} moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "{actor} teisaldas „{event}“ sündmuse „{sourceCalendar}“ kalendrist „{targetCalendar}“ kalendrisse",
+ "You moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "Sina teisaldasid „{event}“ sündmuse „{sourceCalendar}“ kalendrist „{targetCalendar}“ kalendrisse",
+ "{actor} restored event {event} of calendar {calendar}" : "{actor} taastas „{event}“ sündmuse „{calendar}“ kalendris",
+ "You restored event {event} of calendar {calendar}" : "Sina taastasid „{event}“ sündmuse „{calendar}“ kalendris",
"Busy" : "Hõivatud",
"{actor} created to-do {todo} in list {calendar}" : "{actor} lisas {todo} ülesande {calendar} loendissse",
"You created to-do {todo} in list {calendar}" : "Sina lisasid {todo} ülesande {calendar} loendisse",
@@ -68,11 +72,100 @@ OC.L10N.register(
"Description: %s" : "Kirjeldus: %s",
"Where: %s" : "Kus: %s",
"%1$s via %2$s" : "%1$s %2$s kaudu",
+ "In the past on %1$s for the entire day" : "Minevikus kogu päeva: %1$s",
+ "_In a minute on %1$s for the entire day_::_In %n minutes on %1$s for the entire day_" : ["%n minuti pärast kogu päeva: %1$s","%n minuti pärast kogu päeva: %1$s"],
+ "_In a hour on %1$s for the entire day_::_In %n hours on %1$s for the entire day_" : ["%n tunni pärast kogu päeva: %1$s","%n tunni pärast kogu päeva: %1$s"],
+ "_In a day on %1$s for the entire day_::_In %n days on %1$s for the entire day_" : ["%n päeva pärast kogu päeva: %1$s","%n päeva pärast kogu päeva: %1$s"],
+ "_In a week on %1$s for the entire day_::_In %n weeks on %1$s for the entire day_" : ["%n nädala pärast kogu päeva: %1$s","%n nädala pärast kogu päeva: %1$s"],
+ "_In a month on %1$s for the entire day_::_In %n months on %1$s for the entire day_" : ["%n kuu pärast kogu päeva: %1$s","%n kuu pärast kogu päeva: %1$s"],
+ "_In a year on %1$s for the entire day_::_In %n years on %1$s for the entire day_" : ["%n aasta pärast kogu päeva: %1$s","%n aasta pärast kogu päeva: %1$s"],
+ "In the past on %1$s between %2$s - %3$s" : "Minevikus: %1$s ajavahemikus %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_" : ["%n minuti pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s","%n minuti pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s"],
+ "_In a hour on %1$s between %2$s - %3$s_::_In %n hours on %1$s between %2$s - %3$s_" : ["%n tunni pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s","%n tunni pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s"],
+ "_In a day on %1$s between %2$s - %3$s_::_In %n days on %1$s between %2$s - %3$s_" : ["%n päeva pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s","%n päeva pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s"],
+ "_In a week on %1$s between %2$s - %3$s_::_In %n weeks on %1$s between %2$s - %3$s_" : ["%n nädala pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s","%n nädala pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s"],
+ "_In a month on %1$s between %2$s - %3$s_::_In %n months on %1$s between %2$s - %3$s_" : ["%n kuu pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s","%n kuu pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s"],
+ "_In a year on %1$s between %2$s - %3$s_::_In %n years on %1$s between %2$s - %3$s_" : ["%n aasta pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s","%n aasta pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s"],
+ "Could not generate when statement" : "Ei õnnestunud koostada tingimuslikku „when“ lausendit",
+ "Every Day for the entire day" : "Iga päev kogu päeva jooksul",
+ "Every Day for the entire day until %1$s" : "Iga päev kogu päeva jooksul kuni %1$s",
+ "Every Day between %1$s - %2$s" : "Iga päev ajavahemikus %1$s - %2$s",
+ "Every Day between %1$s - %2$s until %3$s" : "Iga päev ajavahemikus %1$s - %2$s kuni %3$s",
+ "Every %1$d Days for the entire day" : "Iga %1$d. päev kogu päeva jooksul",
+ "Every %1$d Days for the entire day until %2$s" : "Iga %1$d. päev kogu päeva jooksul kuni %2$s",
+ "Every %1$d Days between %2$s - %3$s" : "Iga %1$d. päev kogu päeva jooksul ajavahemikus %2$s - %3$s",
+ "Every %1$d Days between %2$s - %3$s until %4$s" : "Iga %1$d. päev kogu päeva jooksul ajavahemikus %2$s - %3$s, kuni %4$s",
+ "Could not generate event recurrence statement" : "Ei õnnestunud koostada ürituse kordumise lausendit",
+ "Every Week on %1$s for the entire day" : "Kogu päeva kestel igal nädalal: %1$s",
+ "Every Week on %1$s for the entire day until %2$s" : "Kogu päeva kestel igal nädalal kuni %2$s: %1$s",
+ "Every Week on %1$s between %2$s - %3$s" : "Igal nädalal: %1$s ajavahemikus %2$s - %3$s",
+ "Every Week on %1$s between %2$s - %3$s until %4$s" : "Igal nädalal kuni %2$s: %1$s ajavahemikus %3$s - %4$s",
+ "Every %1$d Weeks on %2$s for the entire day" : "Igal %1$d-l nädalal kogu päeva kestel: %2$s",
+ "Every %1$d Weeks on %2$s for the entire day until %3$s" : "Igal %1$d-l nädalal kuni %3$s kogu päeva kestel: %2$s",
+ "Every %1$d Weeks on %2$s between %3$s - %4$s" : "Igal %1$d-l nädalal ajavahemikus %3$s - %4$s: %2$s",
+ "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Igal %1$d-l nädalal kuni %5$s ajavahemikus %3$s - %4$s: %2$s",
+ "Every Month on the %1$s for the entire day" : "Kogu päeva kestel igal kuul: %1$s",
+ "Every Month on the %1$s for the entire day until %2$s" : "Kogu päeva kestel igal kuul kuni %2$s: %1$s",
+ "Every Month on the %1$s between %2$s - %3$s" : "Igal kuul: %1$s ajavahemikus %2$s - %3$s",
+ "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Igal kuul kuni %2$s: %1$s ajavahemikus %3$s - %4$s",
+ "Every %1$d Months on the %2$s for the entire day" : "Igal %1$d-l kuul kogu päeva kestel: %2$s",
+ "Every %1$d Months on the %2$s for the entire day until %3$s" : "Igal %1$d-l kuul kuni %3$s kogu päeva kestel: %2$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s" : "Igal %1$d-l kuul ajavahemikus %3$s - %4$s: %2$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "Igal %1$d-l kuul kuni %5$s ajavahemikus %3$s - %4$s: %2$s",
+ "Every Year in %1$s on the %2$s for the entire day" : "Kogu päeva kestel igal aastal: %1$s, %2$s",
+ "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Kogu päeva kestel igal aastal kuni %3$s: %1$s, %2$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Igal aastal ajavahemikus %3$s - %4$s: %1$s, %2$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Igal aastal kuni %5$sajavahemikus %3$s - %4$s: %1$s, %2$s",
+ "Every %1$d Years in %2$s on the %3$s for the entire day" : "Igal %1$d-l aastal kogu päeva kestel: %2$s, %3$s",
+ "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "Kogu päeva kestel igal %1$d-l aastal kuni %4$s: %2$s, %3$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "Igal %1$d-l aastal ajavahemikus %4$s - %5$s: %2$s, %3$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Igal %1$d-l aastal kuni %6$s ajavahemikus %4$s - %5$s: %2$s, %3$s",
+ "On specific dates for the entire day until %1$s" : "Kindlatel päevadel kogu päeva jooksul kuni %1$s",
+ "On specific dates between %1$s - %2$s until %3$s" : "Kindlatel päevadel ajavahemikus %1$s - %2$s kuni %3$s",
+ "In the past on %1$s" : "Minevikus %1$s",
+ "_In a minute on %1$s_::_In %n minutes on %1$s_" : ["Ühe minuti pärast: %1$s","%n minuti pärast: %1$s"],
+ "_In a hour on %1$s_::_In %n hours on %1$s_" : ["Tunni pärast: %1$s","%n tunni pärast: %1$s"],
+ "_In a day on %1$s_::_In %n days on %1$s_" : ["Päeva möödudes: %1$s","%n päeva möödudes: %1$s"],
+ "_In a week on %1$s_::_In %n weeks on %1$s_" : ["Nädala möödudes: %1$s","%n nädala möödudes: %1$s"],
+ "_In a month on %1$s_::_In %n months on %1$s_" : ["Kuu möödudes: %1$s","%n kuu möödudes: %1$s"],
+ "_In a year on %1$s_::_In %n years on %1$s_" : ["Aasta möödudes: %1$s","%n aasta möödudes: %1$s"],
+ "In the past on %1$s then on %2$s" : "Minevikus: %1$s ja siis %2$s",
+ "_In a minute on %1$s then on %2$s_::_In %n minutes on %1$s then on %2$s_" : ["Minuti pärast: %1$s ja siis %2$s","%n minuti pärast: %1$s ja siis %2$s"],
+ "_In a hour on %1$s then on %2$s_::_In %n hours on %1$s then on %2$s_" : ["Tunni pärast: %1$s ja siis %2$s","%n tunni pärast: %1$s ja siis %2$s"],
+ "_In a day on %1$s then on %2$s_::_In %n days on %1$s then on %2$s_" : ["Päeva möödudes: %1$s ja siis %2$s","%n päeva möödudes: %1$s ja siis %2$s"],
+ "_In a week on %1$s then on %2$s_::_In %n weeks on %1$s then on %2$s_" : ["Nädala möödudes: %1$s ja siis %2$s","%n nädala möödudes: %1$s ja siis %2$s"],
+ "_In a month on %1$s then on %2$s_::_In %n months on %1$s then on %2$s_" : ["Kuu möödudes: %1$s ja siis %2$s","%n kuu möödudes: %1$s ja siis %2$s"],
+ "_In a year on %1$s then on %2$s_::_In %n years on %1$s then on %2$s_" : ["Aasta möödudes: %1$s ja siis %2$s","%n aasta möödudes: %1$s ja siis %2$s"],
+ "In the past on %1$s then on %2$s and %3$s" : "Minevikus: %1$s ja siis %2$s ning %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_" : ["Minuti pärast: %1$s ja siis %2$s ning %3$s","%n minuti pärast: %1$s ja siis %2$s ning %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_" : ["Tunni pärast: %1$s ja siis %2$s ning %3$s","%n tunni pärast: %1$s ja siis %2$s ning %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_" : ["Päeva möödudes: %1$s ja siis %2$s ning %3$s","%n päeva möödudes: %1$s ja siis %2$s ning %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_" : ["Nädala möödudes: %1$s ja siis %2$s ning %3$s","%n nädala möödudes: %1$s ja siis %2$s ning %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_" : ["Kuu möödudes: %1$s ja siis %2$s ning %3$s","%n kuu möödudes: %1$s ja siis %2$s ning %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_" : ["Aasta möödudes: %1$s ja siis %2$s ning %3$s","%n aasta möödudes: %1$s ja siis %2$s ning %3$s"],
+ "Could not generate next recurrence statement" : "Ei õnnestunud koostada korduva ürituse järgmise toimumise lausendit",
+ "Cancelled: %1$s" : "Tühistatud: %1$s",
+ "\"%1$s\" has been canceled" : "„%1$s“ on tühistatud",
+ "Re: %1$s" : "Re: %1$s",
+ "%1$s has accepted your invitation" : "„%1$s“ on nõustunud sinu kutsega",
+ "%1$s has tentatively accepted your invitation" : "„%1$s“ on esialgselt nõustunud sinu kutsega",
+ "%1$s has declined your invitation" : "„%1$s“ on sinu kutsest keeldunud",
+ "%1$s has responded to your invitation" : "„%1$s“ on vastanud sinu kutsele",
+ "Invitation updated: %1$s" : "Kutse on uuendatud: %1$s",
+ "%1$s updated the event \"%2$s\"" : "„%1$s“ uuendas sündmust „%2$s“",
+ "Invitation: %1$s" : "Kutse: %1$s",
+ "%1$s would like to invite you to \"%2$s\"" : "„%1$s“ soovib saata sulle „%2$s“ kutset",
+ "Organizer:" : "Korraldaja:",
+ "Attendees:" : "Osalejad:",
+ "Title:" : "Pealkiri:",
"When:" : "Millal:",
"Location:" : "Asukoht:",
"Link:" : "Link:",
+ "Occurring:" : "Toimub:",
"Accept" : "Nõustu",
"Decline" : "Keeldu",
+ "More options …" : "Täiendavad valikud…",
+ "More options at %s" : "Lisavalikud: %s",
"Monday" : "Esmaspäev",
"Tuesday" : "Teisipäev",
"Wednesday" : "Kolmapäev",
@@ -98,13 +191,46 @@ OC.L10N.register(
"Fourth" : "Neljas",
"Fifth" : "Viies",
"Last" : "Viimane",
+ "Second Last" : "Teiseks viimane",
+ "Third Last" : "Kolmandks viimane",
+ "Fourth Last" : "Neljandaks viimane",
+ "Fifth Last" : "Viiendaks viimane",
"Contacts" : "Kontaktid",
+ "{actor} created address book {addressbook}" : "{actor} lõi aadressiraamatu „{addressbook}“",
+ "You created address book {addressbook}" : "Sa lõid aadressiraamatu „{addressbook}“",
+ "{actor} deleted address book {addressbook}" : "„{actor}“ kustutas „{addressbook}“ aadressiraamatu",
+ "You deleted address book {addressbook}" : "Sa kustutasid aadressiraamatu „{addressbook}“",
+ "{actor} updated address book {addressbook}" : "{actor} uuendasaadressiraamatut „{addressbook}“",
+ "You updated address book {addressbook}" : "Sa uuendasid aadressiraamatut „{addressbook}“",
+ "{actor} shared address book {addressbook} with you" : "{actor} jagas „{addressbook}“ aadressiraamatut sinuga",
+ "You shared address book {addressbook} with {user}" : "Sa jagasid „{addressbook}“ aadressiraamatut kasutajaga „{user}“",
+ "{actor} shared address book {addressbook} with {user}" : "{actor} jagas „{addressbook}“ aadressiraamatut kasutajaga „{user}“",
+ "{actor} unshared address book {addressbook} from you" : "{actor} lõpetas „{addressbook}“ aadressiraamatu jagamise sinult",
+ "You unshared address book {addressbook} from {user}" : "Sina lõpetasid „{addressbook}“ aadressiraamatu jagamise kasutajalt {user}",
+ "{actor} unshared address book {addressbook} from {user}" : "{actor} lõpetas „{addressbook}“ aadressiraamatu kasutajalt {user}",
+ "{actor} unshared address book {addressbook} from themselves" : "{actor} lõpetas „{addressbook}“ aadressiraamatu jagamise iseendalt",
+ "You shared address book {addressbook} with group {group}" : "Sina jagasid „{addressbook}“ aadressiraamatut grupiga {group}",
+ "{actor} shared address book {addressbook} with group {group}" : "{actor} jagas „{addressbook}“ aadressiraamatut grupiga {group}",
+ "You unshared address book {addressbook} from group {group}" : "Sina lõpetasid „{addressbook}“ aadressiraamatu jagamise grupiga {group}",
+ "{actor} unshared address book {addressbook} from group {group}" : "{actor} lõpetas „{addressbook}“ aadressiraamatu jagamise grupiga {group}",
+ "{actor} created contact {card} in address book {addressbook}" : "{actor} lisas „{card}“ kontakti „{addressbook}“ aadressiraamatusse",
+ "You created contact {card} in address book {addressbook}" : "Sina lisasid „{card}“ kontakti „{addressbook}“ aadressiraamatusse",
+ "{actor} deleted contact {card} from address book {addressbook}" : "{actor} kustutas „{card}“ kontakti „{addressbook}“ aadressiraamatus",
+ "You deleted contact {card} from address book {addressbook}" : "Sa kustutasid „{card}“ kontakti „{addressbook}“ aadressiraamatus",
+ "{actor} updated contact {card} in address book {addressbook}" : "{actor} uuendas „{card}“ kontakti „{addressbook}“ aadressiraamatus",
+ "You updated contact {card} in address book {addressbook}" : "Sa uuendasid „{card}“ kontakti „{addressbook}“ aadressiraamatus",
+ "A <strong>contact</strong> or <strong>address book</strong> was modified" : "<strong>Kontakti</strong> või <strong>aadressiraamatut</strong> muudeti",
"Accounts" : "Kasutajakontod",
"System address book which holds all accounts" : "Süsteemne aadressiraamat, kus leiduvad kõik kasutajakontod",
"File is not updatable: %1$s" : "Fail pole uuendatav: %1$s",
"Failed to get storage for file" : "Failile ei õnnestunud eraldada andmeruumi",
+ "Could not write to final file, canceled by hook" : "Lõppfaili kirjutamine ei õnnestunud, selle katkestas programmi haak",
"Could not write file contents" : "Ei õnnestunud kirjutada faili sisu",
"_%n byte_::_%n bytes_" : ["%n bait","%n baiti"],
+ "Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Viga faili kopeerimisel sihtkausta (kopeerisin %1$s, aga suuruseks eeldasin %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." : "Eeldasin faili suuruseks %1$s, aga lugesin (Nextcloudi kliendilt) ja kirjutasin (Nextcloudi andmeruumi) %2$s. Tegemist võib olla võrguühenduse veaga saatja poolel või andmeruumi kirjutamise veaga serveri poolel.",
+ "Could not rename part file to final file, canceled by hook" : "Osalise faili nime muutmine lõplikuks nimeks ei õnnestunud, selle katkestas programmi haak",
+ "Could not rename part file to final file" : "Osalise faili nime muutmine lõplikuks nimeks ei õnnestunud",
"Failed to check file size: %1$s" : "Faili suuruse kontrollimine ei õnnestunud: %1$s",
"Could not open file: %1$s, file does seem to exist" : "„%1$s“ faili avamine ei õnnestunud - aga tundub, et ta on olemas",
"Could not open file: %1$s, file doesn't seem to exist" : "„%1$s“ faili avamine ei õnnestunud - tundub, et teda pole olemas",
@@ -113,21 +239,30 @@ OC.L10N.register(
"Failed to unlink: %1$s" : "Lingi eemaldamine ei õnnestunud: %1$s",
"Failed to write file contents: %1$s" : "Faili sisu salvestamine ei õnnestunud: %1$s",
"File not found: %1$s" : "Faili ei leidu: %1$s",
+ "Invalid target path" : "Vigane sihtasukoht",
"System is in maintenance mode." : "Server on hooldusrežiimis.",
"Upgrade needed" : "Uuendus on vajalik",
+ "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Selleks, et sinu %s toimiks iOS-is/macOS-is CalDAV-i ja CardDAV-iga peab https olema seadistatud.",
"Configures a CalDAV account" : "Seadistab CalDAV-i kasutajakonto",
"Configures a CardDAV account" : "Seadistab CardDAV-i kasutajakonto",
"Events" : "Sündmused",
"Untitled task" : "Ilma nimeta pealkiri",
+ "Completed on %s" : "Lõpetatud %s",
+ "Due on %s by %s" : "Tähtaeg: %s, täitjaks %s",
"Due on %s" : "Tähtaeg: %s",
+ "Welcome to Nextcloud Calendar!\n\nThis is a sample event - explore the flexibility of planning with Nextcloud Calendar by making any edits you want!\n\nWith Nextcloud Calendar, you can:\n- Create, edit, and manage events effortlessly.\n- Create multiple calendars and share them with teammates, friends, or family.\n- Check availability and display your busy times to others.\n- Seamlessly integrate with apps and devices via CalDAV.\n- Customize your experience: schedule recurring events, adjust notifications and other settings." : "Tere tulemast Nextcloudi Kalendrisse!\n\nSee näidissündmus võimaldab sul tutvuda Nextcloudi Kalendri paindlikkusega oma aja plaanimisel - proovi teha igasuguseid muudatusi!\n\nNextcloudi Kalendriga saad sa:\n- vaevata luua, muuta ja hallata sündmusi,\n- koostada mitmeid kalendreid ning neid jagada tiimikaaslaste, sõprade ja perega,\n- kontrollida teiste vabu aega ja enda omi näidata teistele,\n- kasutada sujuvat CalDAV-i põhist lõimingut teiste rakenduste ja seadmetega,\n- kohendada kõike oma vajadustele: ajastades korduvaid sündmusi ning sättida teavitusi ja muid seadistusi.",
+ "Example event - open me!" : "Näidissündmus - klõpsi mind!",
"System Address Book" : "Süsteemne aadressiraamat",
"The system address book contains contact information for all users in your instance." : "Süsteemses aadressiraamatus leiduvad kõikde selle serveri kasutajate kontaktteave.",
"Enable System Address Book" : "Kasuta süsteemset aadressiraamatut",
"DAV system address book" : "DAV-i süsteemne aadressiraamat",
+ "No outstanding DAV system address book sync." : "Pole DAV-i süsteemse aadressiraamatu sünkroniseerimist.",
+ "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\"." : "Kuna selles serveris on üle 1000 kasutaja, siis DAV-i süsteemse aadressiraamatu sünkroonomist poel veel toimunud. Aga võis ka juhtuda viga. Palun käivita ta käsurealt ise käsuga „occ dav:sync-system-addressbook“.",
"WebDAV endpoint" : "WebDAV-i teenuse otspunkt",
"Could not check that your web server is properly set up to allow file synchronization over WebDAV. Please check manually." : "Ei õnnestunud kontrollida, kas sinu veebiserver on korrektselt seadistatud ja võimaldab kasutada failide sünkroniseerimist WebDAV-i vahendusel. Palun kontrolli seda käsitsi.",
"Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Sinu veebiserver pole veel failide sünkroniseerimiseks vajalikult seadistatud, kuna WebDAV liides paistab olevat katki.",
"Your web server is properly set up to allow file synchronization over WebDAV." : "Sinu veebiserver on korrektselt seadistatud ja võimaldab kasutada failide sünkroniseerimist WebDAV-i vahendusel.",
+ "Migrated calendar (%1$s)" : "Ümberkolitud kalender (%1$s)",
"Calendars including events, details and attendees" : "Kalendrid, sealhulgas sündmused, üksikasjad ja osalejad",
"Contacts and groups" : "Kontaktid ja grupid",
"WebDAV" : "WebDAV",
@@ -137,6 +272,8 @@ OC.L10N.register(
"Failed to clear your absence settings" : "Sinu äraoleku seadistuste eemaldamine ei õnnestunud",
"First day" : "Esimene päev",
"Last day (inclusive)" : "Viimane päev (kaasaarvatud)",
+ "Out of office replacement (optional)" : "Asendaja äraoleku ajaks (valikuline)",
+ "Name of the replacement" : "Asendaja nimi",
"No results." : "Vasteid ei leitud.",
"Start typing." : "Alusta kirjutamist.",
"Short absence status" : "Äraoleku lühinimi",
@@ -148,11 +285,13 @@ OC.L10N.register(
"Failed to save availability" : "Saadavuse salvestamine ei õnnestunud",
"Time zone:" : "Ajavöönd:",
"to" : "saaja",
- "Availability" : "Saadavus",
- "Absence" : "Äraolek",
- "Configure your next absence period." : "Seadista järgmise äraoleku ajavahemik.",
- "Send invitations to attendees" : "Saada osalejatele kutsed",
- "Enable notifications for events via push" : "Võta kasutusele tõuketeenustepõhised teavitused",
+ "Delete slot" : "Kustuta ajavahemik",
+ "No working hours set" : "Tööajad on sisestamata",
+ "Add slot" : "Lisa ajavahemik",
+ "Weekdays" : "Nädalapäevad",
+ "Pick a start time for {dayName}" : "Vali algusaeg: {dayName}",
+ "Pick a end time for {dayName}" : "Vali lõpuaeg: {dayName}",
+ "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Kõikide teavituste summutamiseks määra automaatselt kasutajale olek „Ära sega“ nendele aegadele, kus ta vaba ei ole.",
"Cancel" : "Tühista",
"Import" : "Impordi",
"Error while saving settings" : "Viga seadistuste salvestamisel",
@@ -160,18 +299,40 @@ OC.L10N.register(
"Error while resetting contact" : "Viga kontakti lähtestamisel",
"Contact imported successfully" : "Kontakti importimine õnnestus",
"Error while importing contact" : "Viga kontakti importimisel",
- "Example Content" : "Sisunäidis",
- "Set example content to be created on new user first login." : "Kirjelda näidissisu, mis uue kasutaja esimesel sisselogimisel luuakse.",
"Import contact" : "Impordi kontakt",
- "Reset to default contact" : "Lähtesta vaikimisi kontakstiks",
+ "Reset to default" : "Taasta vaikeseadistused",
"Import contacts" : "Impordi kontaktid",
"Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Uue .vcf faili importimisel olemasolev vaikimisi kontakt kustutatakse ja asendatakse uuega. Kas sa soovid jätkata?",
+ "Failed to save example event creation setting" : "Näidissündmuse loomise seadistuste salvestamine ei õnnestunud",
+ "Failed to upload the example event" : "Näidissündmuse üleslaadimine ei õnnestunud",
+ "Custom example event was saved successfully" : "Kohandatud näidissündmuse salvestamine õnnestus",
+ "Failed to delete the custom example event" : "Kohandatud näidissündmuse kustutamine ei õnnestunud",
+ "Custom example event was deleted successfully" : "Kohandatud näidissündmuse kustutamine õnnestus",
+ "Import calendar event" : "Impordi kalendrisündmus",
+ "Uploading a new event will overwrite the existing one." : "Uue sündmuse üleslaadimisel asendatakse olemasolevad.",
+ "Upload event" : "Laadi sündmus üles",
+ "Availability" : "Saadavus",
+ "If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Kui seadistad oma tööajad, siis teised saavad kohtumise broneerimisel arvestada sellega, millal sind kohal pole.",
+ "Absence" : "Äraolek",
+ "Configure your next absence period." : "Seadista järgmise äraoleku ajavahemik.",
+ "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Palun paigalda ka {calendarappstoreopen}Kalendrirakendus{linkclose} või {calendardocopen}lisa sünkroniseerimine oma töölaule ja nutiseadmesse ↗{linkclose}.",
+ "Please make sure to properly set up {emailopen}the email server{linkclose}." : "Palun kontrolli, et {emailopen}e-posti server{linkclose} on seadistatud korrektselt.",
+ "Calendar server" : "Kalendriserver",
+ "Send invitations to attendees" : "Saada osalejatele kutsed",
+ "Automatically generate a birthday calendar" : "Koosta sünnipäevade kalender automaatselt",
+ "Birthday calendars will be generated by a background job." : "Sünnipäevade kalender luuakse automaatselt taustateenuse poolt.",
+ "Hence they will not be available immediately after enabling but will show up after some time." : "Seega pole need andmed kohe saadaval, vaid ilmuvad mingi aja pärast.",
+ "Send notifications for events" : "Saada sündmuste teavitusi",
+ "Notifications are sent via background jobs, so these must occur often enough." : "Teavitused saadetakse taustateenuste poolt. See eeldab, et vastavaid skripte käivitatakse piisavalt tihti.",
+ "Send reminder notifications to calendar sharees as well" : "Saada meeldetuletused ka neile, kes ürituse on lisanud oma kalendrisse",
+ "Reminders are always sent to organizers and attendees." : "Meeldetuletused on alati saadetud korraldajatele ja osalejatele.",
+ "Enable notifications for events via push" : "Võta kasutusele tõuketeenustepõhised teavitused",
+ "Example content" : "Sisunäidis",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Sisunäidis annab ülevaate Nexctcloudi võimalustest. Vaikimisi sisu tuleb Nexctcloudi paigaldusega kaasa ja seda saab alati oma sisuga asendada.",
"There was an error updating your attendance status." : "Sinu osalemise oleku muutmisel tekkis viga.",
"Please contact the organizer directly." : "Palun võta ühendust korraldajaga otse.",
"Are you accepting the invitation?" : "Kas sa nõustud kutsega?",
"Tentative" : "Esialgne",
- "Your attendance was updated successfully." : "Sinu osalemise oleku muutmine õnnestus.",
- "Time:" : "Aeg:",
- "Could not open file" : "Ei õnnestunud avada faili"
+ "Your attendance was updated successfully." : "Sinu osalemise oleku muutmine õnnestus."
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/et_EE.json b/apps/dav/l10n/et_EE.json
index 06543cb78bc..3da2c28f3d9 100644
--- a/apps/dav/l10n/et_EE.json
+++ b/apps/dav/l10n/et_EE.json
@@ -29,7 +29,11 @@
"{actor} deleted event {event} from calendar {calendar}" : "{actor} kustutas sündmuse {event} kalendrist {calendar}",
"You deleted event {event} from calendar {calendar}" : "Sa kustutasid sündmuse {event} kalendrist {calendar}",
"{actor} updated event {event} in calendar {calendar}" : "{actor} uuendas sündmust {event} kalendris {calendar}",
- "You updated event {event} in calendar {calendar}" : "Sa uuendasid sündmust {event} kalendris {calendar}",
+ "You updated event {event} in calendar {calendar}" : "Sa uuendasid „{event}“ sündmust „{calendar}“ kalendris",
+ "{actor} moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "{actor} teisaldas „{event}“ sündmuse „{sourceCalendar}“ kalendrist „{targetCalendar}“ kalendrisse",
+ "You moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "Sina teisaldasid „{event}“ sündmuse „{sourceCalendar}“ kalendrist „{targetCalendar}“ kalendrisse",
+ "{actor} restored event {event} of calendar {calendar}" : "{actor} taastas „{event}“ sündmuse „{calendar}“ kalendris",
+ "You restored event {event} of calendar {calendar}" : "Sina taastasid „{event}“ sündmuse „{calendar}“ kalendris",
"Busy" : "Hõivatud",
"{actor} created to-do {todo} in list {calendar}" : "{actor} lisas {todo} ülesande {calendar} loendissse",
"You created to-do {todo} in list {calendar}" : "Sina lisasid {todo} ülesande {calendar} loendisse",
@@ -66,11 +70,100 @@
"Description: %s" : "Kirjeldus: %s",
"Where: %s" : "Kus: %s",
"%1$s via %2$s" : "%1$s %2$s kaudu",
+ "In the past on %1$s for the entire day" : "Minevikus kogu päeva: %1$s",
+ "_In a minute on %1$s for the entire day_::_In %n minutes on %1$s for the entire day_" : ["%n minuti pärast kogu päeva: %1$s","%n minuti pärast kogu päeva: %1$s"],
+ "_In a hour on %1$s for the entire day_::_In %n hours on %1$s for the entire day_" : ["%n tunni pärast kogu päeva: %1$s","%n tunni pärast kogu päeva: %1$s"],
+ "_In a day on %1$s for the entire day_::_In %n days on %1$s for the entire day_" : ["%n päeva pärast kogu päeva: %1$s","%n päeva pärast kogu päeva: %1$s"],
+ "_In a week on %1$s for the entire day_::_In %n weeks on %1$s for the entire day_" : ["%n nädala pärast kogu päeva: %1$s","%n nädala pärast kogu päeva: %1$s"],
+ "_In a month on %1$s for the entire day_::_In %n months on %1$s for the entire day_" : ["%n kuu pärast kogu päeva: %1$s","%n kuu pärast kogu päeva: %1$s"],
+ "_In a year on %1$s for the entire day_::_In %n years on %1$s for the entire day_" : ["%n aasta pärast kogu päeva: %1$s","%n aasta pärast kogu päeva: %1$s"],
+ "In the past on %1$s between %2$s - %3$s" : "Minevikus: %1$s ajavahemikus %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_" : ["%n minuti pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s","%n minuti pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s"],
+ "_In a hour on %1$s between %2$s - %3$s_::_In %n hours on %1$s between %2$s - %3$s_" : ["%n tunni pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s","%n tunni pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s"],
+ "_In a day on %1$s between %2$s - %3$s_::_In %n days on %1$s between %2$s - %3$s_" : ["%n päeva pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s","%n päeva pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s"],
+ "_In a week on %1$s between %2$s - %3$s_::_In %n weeks on %1$s between %2$s - %3$s_" : ["%n nädala pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s","%n nädala pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s"],
+ "_In a month on %1$s between %2$s - %3$s_::_In %n months on %1$s between %2$s - %3$s_" : ["%n kuu pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s","%n kuu pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s"],
+ "_In a year on %1$s between %2$s - %3$s_::_In %n years on %1$s between %2$s - %3$s_" : ["%n aasta pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s","%n aasta pärast ajavahemikus %2$s -%3$s kogu päeva: %1$s"],
+ "Could not generate when statement" : "Ei õnnestunud koostada tingimuslikku „when“ lausendit",
+ "Every Day for the entire day" : "Iga päev kogu päeva jooksul",
+ "Every Day for the entire day until %1$s" : "Iga päev kogu päeva jooksul kuni %1$s",
+ "Every Day between %1$s - %2$s" : "Iga päev ajavahemikus %1$s - %2$s",
+ "Every Day between %1$s - %2$s until %3$s" : "Iga päev ajavahemikus %1$s - %2$s kuni %3$s",
+ "Every %1$d Days for the entire day" : "Iga %1$d. päev kogu päeva jooksul",
+ "Every %1$d Days for the entire day until %2$s" : "Iga %1$d. päev kogu päeva jooksul kuni %2$s",
+ "Every %1$d Days between %2$s - %3$s" : "Iga %1$d. päev kogu päeva jooksul ajavahemikus %2$s - %3$s",
+ "Every %1$d Days between %2$s - %3$s until %4$s" : "Iga %1$d. päev kogu päeva jooksul ajavahemikus %2$s - %3$s, kuni %4$s",
+ "Could not generate event recurrence statement" : "Ei õnnestunud koostada ürituse kordumise lausendit",
+ "Every Week on %1$s for the entire day" : "Kogu päeva kestel igal nädalal: %1$s",
+ "Every Week on %1$s for the entire day until %2$s" : "Kogu päeva kestel igal nädalal kuni %2$s: %1$s",
+ "Every Week on %1$s between %2$s - %3$s" : "Igal nädalal: %1$s ajavahemikus %2$s - %3$s",
+ "Every Week on %1$s between %2$s - %3$s until %4$s" : "Igal nädalal kuni %2$s: %1$s ajavahemikus %3$s - %4$s",
+ "Every %1$d Weeks on %2$s for the entire day" : "Igal %1$d-l nädalal kogu päeva kestel: %2$s",
+ "Every %1$d Weeks on %2$s for the entire day until %3$s" : "Igal %1$d-l nädalal kuni %3$s kogu päeva kestel: %2$s",
+ "Every %1$d Weeks on %2$s between %3$s - %4$s" : "Igal %1$d-l nädalal ajavahemikus %3$s - %4$s: %2$s",
+ "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Igal %1$d-l nädalal kuni %5$s ajavahemikus %3$s - %4$s: %2$s",
+ "Every Month on the %1$s for the entire day" : "Kogu päeva kestel igal kuul: %1$s",
+ "Every Month on the %1$s for the entire day until %2$s" : "Kogu päeva kestel igal kuul kuni %2$s: %1$s",
+ "Every Month on the %1$s between %2$s - %3$s" : "Igal kuul: %1$s ajavahemikus %2$s - %3$s",
+ "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Igal kuul kuni %2$s: %1$s ajavahemikus %3$s - %4$s",
+ "Every %1$d Months on the %2$s for the entire day" : "Igal %1$d-l kuul kogu päeva kestel: %2$s",
+ "Every %1$d Months on the %2$s for the entire day until %3$s" : "Igal %1$d-l kuul kuni %3$s kogu päeva kestel: %2$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s" : "Igal %1$d-l kuul ajavahemikus %3$s - %4$s: %2$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "Igal %1$d-l kuul kuni %5$s ajavahemikus %3$s - %4$s: %2$s",
+ "Every Year in %1$s on the %2$s for the entire day" : "Kogu päeva kestel igal aastal: %1$s, %2$s",
+ "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Kogu päeva kestel igal aastal kuni %3$s: %1$s, %2$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Igal aastal ajavahemikus %3$s - %4$s: %1$s, %2$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Igal aastal kuni %5$sajavahemikus %3$s - %4$s: %1$s, %2$s",
+ "Every %1$d Years in %2$s on the %3$s for the entire day" : "Igal %1$d-l aastal kogu päeva kestel: %2$s, %3$s",
+ "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "Kogu päeva kestel igal %1$d-l aastal kuni %4$s: %2$s, %3$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "Igal %1$d-l aastal ajavahemikus %4$s - %5$s: %2$s, %3$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Igal %1$d-l aastal kuni %6$s ajavahemikus %4$s - %5$s: %2$s, %3$s",
+ "On specific dates for the entire day until %1$s" : "Kindlatel päevadel kogu päeva jooksul kuni %1$s",
+ "On specific dates between %1$s - %2$s until %3$s" : "Kindlatel päevadel ajavahemikus %1$s - %2$s kuni %3$s",
+ "In the past on %1$s" : "Minevikus %1$s",
+ "_In a minute on %1$s_::_In %n minutes on %1$s_" : ["Ühe minuti pärast: %1$s","%n minuti pärast: %1$s"],
+ "_In a hour on %1$s_::_In %n hours on %1$s_" : ["Tunni pärast: %1$s","%n tunni pärast: %1$s"],
+ "_In a day on %1$s_::_In %n days on %1$s_" : ["Päeva möödudes: %1$s","%n päeva möödudes: %1$s"],
+ "_In a week on %1$s_::_In %n weeks on %1$s_" : ["Nädala möödudes: %1$s","%n nädala möödudes: %1$s"],
+ "_In a month on %1$s_::_In %n months on %1$s_" : ["Kuu möödudes: %1$s","%n kuu möödudes: %1$s"],
+ "_In a year on %1$s_::_In %n years on %1$s_" : ["Aasta möödudes: %1$s","%n aasta möödudes: %1$s"],
+ "In the past on %1$s then on %2$s" : "Minevikus: %1$s ja siis %2$s",
+ "_In a minute on %1$s then on %2$s_::_In %n minutes on %1$s then on %2$s_" : ["Minuti pärast: %1$s ja siis %2$s","%n minuti pärast: %1$s ja siis %2$s"],
+ "_In a hour on %1$s then on %2$s_::_In %n hours on %1$s then on %2$s_" : ["Tunni pärast: %1$s ja siis %2$s","%n tunni pärast: %1$s ja siis %2$s"],
+ "_In a day on %1$s then on %2$s_::_In %n days on %1$s then on %2$s_" : ["Päeva möödudes: %1$s ja siis %2$s","%n päeva möödudes: %1$s ja siis %2$s"],
+ "_In a week on %1$s then on %2$s_::_In %n weeks on %1$s then on %2$s_" : ["Nädala möödudes: %1$s ja siis %2$s","%n nädala möödudes: %1$s ja siis %2$s"],
+ "_In a month on %1$s then on %2$s_::_In %n months on %1$s then on %2$s_" : ["Kuu möödudes: %1$s ja siis %2$s","%n kuu möödudes: %1$s ja siis %2$s"],
+ "_In a year on %1$s then on %2$s_::_In %n years on %1$s then on %2$s_" : ["Aasta möödudes: %1$s ja siis %2$s","%n aasta möödudes: %1$s ja siis %2$s"],
+ "In the past on %1$s then on %2$s and %3$s" : "Minevikus: %1$s ja siis %2$s ning %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_" : ["Minuti pärast: %1$s ja siis %2$s ning %3$s","%n minuti pärast: %1$s ja siis %2$s ning %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_" : ["Tunni pärast: %1$s ja siis %2$s ning %3$s","%n tunni pärast: %1$s ja siis %2$s ning %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_" : ["Päeva möödudes: %1$s ja siis %2$s ning %3$s","%n päeva möödudes: %1$s ja siis %2$s ning %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_" : ["Nädala möödudes: %1$s ja siis %2$s ning %3$s","%n nädala möödudes: %1$s ja siis %2$s ning %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_" : ["Kuu möödudes: %1$s ja siis %2$s ning %3$s","%n kuu möödudes: %1$s ja siis %2$s ning %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_" : ["Aasta möödudes: %1$s ja siis %2$s ning %3$s","%n aasta möödudes: %1$s ja siis %2$s ning %3$s"],
+ "Could not generate next recurrence statement" : "Ei õnnestunud koostada korduva ürituse järgmise toimumise lausendit",
+ "Cancelled: %1$s" : "Tühistatud: %1$s",
+ "\"%1$s\" has been canceled" : "„%1$s“ on tühistatud",
+ "Re: %1$s" : "Re: %1$s",
+ "%1$s has accepted your invitation" : "„%1$s“ on nõustunud sinu kutsega",
+ "%1$s has tentatively accepted your invitation" : "„%1$s“ on esialgselt nõustunud sinu kutsega",
+ "%1$s has declined your invitation" : "„%1$s“ on sinu kutsest keeldunud",
+ "%1$s has responded to your invitation" : "„%1$s“ on vastanud sinu kutsele",
+ "Invitation updated: %1$s" : "Kutse on uuendatud: %1$s",
+ "%1$s updated the event \"%2$s\"" : "„%1$s“ uuendas sündmust „%2$s“",
+ "Invitation: %1$s" : "Kutse: %1$s",
+ "%1$s would like to invite you to \"%2$s\"" : "„%1$s“ soovib saata sulle „%2$s“ kutset",
+ "Organizer:" : "Korraldaja:",
+ "Attendees:" : "Osalejad:",
+ "Title:" : "Pealkiri:",
"When:" : "Millal:",
"Location:" : "Asukoht:",
"Link:" : "Link:",
+ "Occurring:" : "Toimub:",
"Accept" : "Nõustu",
"Decline" : "Keeldu",
+ "More options …" : "Täiendavad valikud…",
+ "More options at %s" : "Lisavalikud: %s",
"Monday" : "Esmaspäev",
"Tuesday" : "Teisipäev",
"Wednesday" : "Kolmapäev",
@@ -96,13 +189,46 @@
"Fourth" : "Neljas",
"Fifth" : "Viies",
"Last" : "Viimane",
+ "Second Last" : "Teiseks viimane",
+ "Third Last" : "Kolmandks viimane",
+ "Fourth Last" : "Neljandaks viimane",
+ "Fifth Last" : "Viiendaks viimane",
"Contacts" : "Kontaktid",
+ "{actor} created address book {addressbook}" : "{actor} lõi aadressiraamatu „{addressbook}“",
+ "You created address book {addressbook}" : "Sa lõid aadressiraamatu „{addressbook}“",
+ "{actor} deleted address book {addressbook}" : "„{actor}“ kustutas „{addressbook}“ aadressiraamatu",
+ "You deleted address book {addressbook}" : "Sa kustutasid aadressiraamatu „{addressbook}“",
+ "{actor} updated address book {addressbook}" : "{actor} uuendasaadressiraamatut „{addressbook}“",
+ "You updated address book {addressbook}" : "Sa uuendasid aadressiraamatut „{addressbook}“",
+ "{actor} shared address book {addressbook} with you" : "{actor} jagas „{addressbook}“ aadressiraamatut sinuga",
+ "You shared address book {addressbook} with {user}" : "Sa jagasid „{addressbook}“ aadressiraamatut kasutajaga „{user}“",
+ "{actor} shared address book {addressbook} with {user}" : "{actor} jagas „{addressbook}“ aadressiraamatut kasutajaga „{user}“",
+ "{actor} unshared address book {addressbook} from you" : "{actor} lõpetas „{addressbook}“ aadressiraamatu jagamise sinult",
+ "You unshared address book {addressbook} from {user}" : "Sina lõpetasid „{addressbook}“ aadressiraamatu jagamise kasutajalt {user}",
+ "{actor} unshared address book {addressbook} from {user}" : "{actor} lõpetas „{addressbook}“ aadressiraamatu kasutajalt {user}",
+ "{actor} unshared address book {addressbook} from themselves" : "{actor} lõpetas „{addressbook}“ aadressiraamatu jagamise iseendalt",
+ "You shared address book {addressbook} with group {group}" : "Sina jagasid „{addressbook}“ aadressiraamatut grupiga {group}",
+ "{actor} shared address book {addressbook} with group {group}" : "{actor} jagas „{addressbook}“ aadressiraamatut grupiga {group}",
+ "You unshared address book {addressbook} from group {group}" : "Sina lõpetasid „{addressbook}“ aadressiraamatu jagamise grupiga {group}",
+ "{actor} unshared address book {addressbook} from group {group}" : "{actor} lõpetas „{addressbook}“ aadressiraamatu jagamise grupiga {group}",
+ "{actor} created contact {card} in address book {addressbook}" : "{actor} lisas „{card}“ kontakti „{addressbook}“ aadressiraamatusse",
+ "You created contact {card} in address book {addressbook}" : "Sina lisasid „{card}“ kontakti „{addressbook}“ aadressiraamatusse",
+ "{actor} deleted contact {card} from address book {addressbook}" : "{actor} kustutas „{card}“ kontakti „{addressbook}“ aadressiraamatus",
+ "You deleted contact {card} from address book {addressbook}" : "Sa kustutasid „{card}“ kontakti „{addressbook}“ aadressiraamatus",
+ "{actor} updated contact {card} in address book {addressbook}" : "{actor} uuendas „{card}“ kontakti „{addressbook}“ aadressiraamatus",
+ "You updated contact {card} in address book {addressbook}" : "Sa uuendasid „{card}“ kontakti „{addressbook}“ aadressiraamatus",
+ "A <strong>contact</strong> or <strong>address book</strong> was modified" : "<strong>Kontakti</strong> või <strong>aadressiraamatut</strong> muudeti",
"Accounts" : "Kasutajakontod",
"System address book which holds all accounts" : "Süsteemne aadressiraamat, kus leiduvad kõik kasutajakontod",
"File is not updatable: %1$s" : "Fail pole uuendatav: %1$s",
"Failed to get storage for file" : "Failile ei õnnestunud eraldada andmeruumi",
+ "Could not write to final file, canceled by hook" : "Lõppfaili kirjutamine ei õnnestunud, selle katkestas programmi haak",
"Could not write file contents" : "Ei õnnestunud kirjutada faili sisu",
"_%n byte_::_%n bytes_" : ["%n bait","%n baiti"],
+ "Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Viga faili kopeerimisel sihtkausta (kopeerisin %1$s, aga suuruseks eeldasin %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." : "Eeldasin faili suuruseks %1$s, aga lugesin (Nextcloudi kliendilt) ja kirjutasin (Nextcloudi andmeruumi) %2$s. Tegemist võib olla võrguühenduse veaga saatja poolel või andmeruumi kirjutamise veaga serveri poolel.",
+ "Could not rename part file to final file, canceled by hook" : "Osalise faili nime muutmine lõplikuks nimeks ei õnnestunud, selle katkestas programmi haak",
+ "Could not rename part file to final file" : "Osalise faili nime muutmine lõplikuks nimeks ei õnnestunud",
"Failed to check file size: %1$s" : "Faili suuruse kontrollimine ei õnnestunud: %1$s",
"Could not open file: %1$s, file does seem to exist" : "„%1$s“ faili avamine ei õnnestunud - aga tundub, et ta on olemas",
"Could not open file: %1$s, file doesn't seem to exist" : "„%1$s“ faili avamine ei õnnestunud - tundub, et teda pole olemas",
@@ -111,21 +237,30 @@
"Failed to unlink: %1$s" : "Lingi eemaldamine ei õnnestunud: %1$s",
"Failed to write file contents: %1$s" : "Faili sisu salvestamine ei õnnestunud: %1$s",
"File not found: %1$s" : "Faili ei leidu: %1$s",
+ "Invalid target path" : "Vigane sihtasukoht",
"System is in maintenance mode." : "Server on hooldusrežiimis.",
"Upgrade needed" : "Uuendus on vajalik",
+ "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Selleks, et sinu %s toimiks iOS-is/macOS-is CalDAV-i ja CardDAV-iga peab https olema seadistatud.",
"Configures a CalDAV account" : "Seadistab CalDAV-i kasutajakonto",
"Configures a CardDAV account" : "Seadistab CardDAV-i kasutajakonto",
"Events" : "Sündmused",
"Untitled task" : "Ilma nimeta pealkiri",
+ "Completed on %s" : "Lõpetatud %s",
+ "Due on %s by %s" : "Tähtaeg: %s, täitjaks %s",
"Due on %s" : "Tähtaeg: %s",
+ "Welcome to Nextcloud Calendar!\n\nThis is a sample event - explore the flexibility of planning with Nextcloud Calendar by making any edits you want!\n\nWith Nextcloud Calendar, you can:\n- Create, edit, and manage events effortlessly.\n- Create multiple calendars and share them with teammates, friends, or family.\n- Check availability and display your busy times to others.\n- Seamlessly integrate with apps and devices via CalDAV.\n- Customize your experience: schedule recurring events, adjust notifications and other settings." : "Tere tulemast Nextcloudi Kalendrisse!\n\nSee näidissündmus võimaldab sul tutvuda Nextcloudi Kalendri paindlikkusega oma aja plaanimisel - proovi teha igasuguseid muudatusi!\n\nNextcloudi Kalendriga saad sa:\n- vaevata luua, muuta ja hallata sündmusi,\n- koostada mitmeid kalendreid ning neid jagada tiimikaaslaste, sõprade ja perega,\n- kontrollida teiste vabu aega ja enda omi näidata teistele,\n- kasutada sujuvat CalDAV-i põhist lõimingut teiste rakenduste ja seadmetega,\n- kohendada kõike oma vajadustele: ajastades korduvaid sündmusi ning sättida teavitusi ja muid seadistusi.",
+ "Example event - open me!" : "Näidissündmus - klõpsi mind!",
"System Address Book" : "Süsteemne aadressiraamat",
"The system address book contains contact information for all users in your instance." : "Süsteemses aadressiraamatus leiduvad kõikde selle serveri kasutajate kontaktteave.",
"Enable System Address Book" : "Kasuta süsteemset aadressiraamatut",
"DAV system address book" : "DAV-i süsteemne aadressiraamat",
+ "No outstanding DAV system address book sync." : "Pole DAV-i süsteemse aadressiraamatu sünkroniseerimist.",
+ "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\"." : "Kuna selles serveris on üle 1000 kasutaja, siis DAV-i süsteemse aadressiraamatu sünkroonomist poel veel toimunud. Aga võis ka juhtuda viga. Palun käivita ta käsurealt ise käsuga „occ dav:sync-system-addressbook“.",
"WebDAV endpoint" : "WebDAV-i teenuse otspunkt",
"Could not check that your web server is properly set up to allow file synchronization over WebDAV. Please check manually." : "Ei õnnestunud kontrollida, kas sinu veebiserver on korrektselt seadistatud ja võimaldab kasutada failide sünkroniseerimist WebDAV-i vahendusel. Palun kontrolli seda käsitsi.",
"Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Sinu veebiserver pole veel failide sünkroniseerimiseks vajalikult seadistatud, kuna WebDAV liides paistab olevat katki.",
"Your web server is properly set up to allow file synchronization over WebDAV." : "Sinu veebiserver on korrektselt seadistatud ja võimaldab kasutada failide sünkroniseerimist WebDAV-i vahendusel.",
+ "Migrated calendar (%1$s)" : "Ümberkolitud kalender (%1$s)",
"Calendars including events, details and attendees" : "Kalendrid, sealhulgas sündmused, üksikasjad ja osalejad",
"Contacts and groups" : "Kontaktid ja grupid",
"WebDAV" : "WebDAV",
@@ -135,6 +270,8 @@
"Failed to clear your absence settings" : "Sinu äraoleku seadistuste eemaldamine ei õnnestunud",
"First day" : "Esimene päev",
"Last day (inclusive)" : "Viimane päev (kaasaarvatud)",
+ "Out of office replacement (optional)" : "Asendaja äraoleku ajaks (valikuline)",
+ "Name of the replacement" : "Asendaja nimi",
"No results." : "Vasteid ei leitud.",
"Start typing." : "Alusta kirjutamist.",
"Short absence status" : "Äraoleku lühinimi",
@@ -146,11 +283,13 @@
"Failed to save availability" : "Saadavuse salvestamine ei õnnestunud",
"Time zone:" : "Ajavöönd:",
"to" : "saaja",
- "Availability" : "Saadavus",
- "Absence" : "Äraolek",
- "Configure your next absence period." : "Seadista järgmise äraoleku ajavahemik.",
- "Send invitations to attendees" : "Saada osalejatele kutsed",
- "Enable notifications for events via push" : "Võta kasutusele tõuketeenustepõhised teavitused",
+ "Delete slot" : "Kustuta ajavahemik",
+ "No working hours set" : "Tööajad on sisestamata",
+ "Add slot" : "Lisa ajavahemik",
+ "Weekdays" : "Nädalapäevad",
+ "Pick a start time for {dayName}" : "Vali algusaeg: {dayName}",
+ "Pick a end time for {dayName}" : "Vali lõpuaeg: {dayName}",
+ "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Kõikide teavituste summutamiseks määra automaatselt kasutajale olek „Ära sega“ nendele aegadele, kus ta vaba ei ole.",
"Cancel" : "Tühista",
"Import" : "Impordi",
"Error while saving settings" : "Viga seadistuste salvestamisel",
@@ -158,18 +297,40 @@
"Error while resetting contact" : "Viga kontakti lähtestamisel",
"Contact imported successfully" : "Kontakti importimine õnnestus",
"Error while importing contact" : "Viga kontakti importimisel",
- "Example Content" : "Sisunäidis",
- "Set example content to be created on new user first login." : "Kirjelda näidissisu, mis uue kasutaja esimesel sisselogimisel luuakse.",
"Import contact" : "Impordi kontakt",
- "Reset to default contact" : "Lähtesta vaikimisi kontakstiks",
+ "Reset to default" : "Taasta vaikeseadistused",
"Import contacts" : "Impordi kontaktid",
"Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Uue .vcf faili importimisel olemasolev vaikimisi kontakt kustutatakse ja asendatakse uuega. Kas sa soovid jätkata?",
+ "Failed to save example event creation setting" : "Näidissündmuse loomise seadistuste salvestamine ei õnnestunud",
+ "Failed to upload the example event" : "Näidissündmuse üleslaadimine ei õnnestunud",
+ "Custom example event was saved successfully" : "Kohandatud näidissündmuse salvestamine õnnestus",
+ "Failed to delete the custom example event" : "Kohandatud näidissündmuse kustutamine ei õnnestunud",
+ "Custom example event was deleted successfully" : "Kohandatud näidissündmuse kustutamine õnnestus",
+ "Import calendar event" : "Impordi kalendrisündmus",
+ "Uploading a new event will overwrite the existing one." : "Uue sündmuse üleslaadimisel asendatakse olemasolevad.",
+ "Upload event" : "Laadi sündmus üles",
+ "Availability" : "Saadavus",
+ "If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Kui seadistad oma tööajad, siis teised saavad kohtumise broneerimisel arvestada sellega, millal sind kohal pole.",
+ "Absence" : "Äraolek",
+ "Configure your next absence period." : "Seadista järgmise äraoleku ajavahemik.",
+ "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Palun paigalda ka {calendarappstoreopen}Kalendrirakendus{linkclose} või {calendardocopen}lisa sünkroniseerimine oma töölaule ja nutiseadmesse ↗{linkclose}.",
+ "Please make sure to properly set up {emailopen}the email server{linkclose}." : "Palun kontrolli, et {emailopen}e-posti server{linkclose} on seadistatud korrektselt.",
+ "Calendar server" : "Kalendriserver",
+ "Send invitations to attendees" : "Saada osalejatele kutsed",
+ "Automatically generate a birthday calendar" : "Koosta sünnipäevade kalender automaatselt",
+ "Birthday calendars will be generated by a background job." : "Sünnipäevade kalender luuakse automaatselt taustateenuse poolt.",
+ "Hence they will not be available immediately after enabling but will show up after some time." : "Seega pole need andmed kohe saadaval, vaid ilmuvad mingi aja pärast.",
+ "Send notifications for events" : "Saada sündmuste teavitusi",
+ "Notifications are sent via background jobs, so these must occur often enough." : "Teavitused saadetakse taustateenuste poolt. See eeldab, et vastavaid skripte käivitatakse piisavalt tihti.",
+ "Send reminder notifications to calendar sharees as well" : "Saada meeldetuletused ka neile, kes ürituse on lisanud oma kalendrisse",
+ "Reminders are always sent to organizers and attendees." : "Meeldetuletused on alati saadetud korraldajatele ja osalejatele.",
+ "Enable notifications for events via push" : "Võta kasutusele tõuketeenustepõhised teavitused",
+ "Example content" : "Sisunäidis",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Sisunäidis annab ülevaate Nexctcloudi võimalustest. Vaikimisi sisu tuleb Nexctcloudi paigaldusega kaasa ja seda saab alati oma sisuga asendada.",
"There was an error updating your attendance status." : "Sinu osalemise oleku muutmisel tekkis viga.",
"Please contact the organizer directly." : "Palun võta ühendust korraldajaga otse.",
"Are you accepting the invitation?" : "Kas sa nõustud kutsega?",
"Tentative" : "Esialgne",
- "Your attendance was updated successfully." : "Sinu osalemise oleku muutmine õnnestus.",
- "Time:" : "Aeg:",
- "Could not open file" : "Ei õnnestunud avada faili"
+ "Your attendance was updated successfully." : "Sinu osalemise oleku muutmine õnnestus."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/eu.js b/apps/dav/l10n/eu.js
index 2a897a6ae73..4deb8172bed 100644
--- a/apps/dav/l10n/eu.js
+++ b/apps/dav/l10n/eu.js
@@ -285,6 +285,10 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Hautatu hasiera ordu bat {dayName}(e)rako",
"Pick a end time for {dayName}" : "Hautatu bukaera ordu bat {dayName}(e)rako",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Eskuragarri ez egotean, ezarri automatikoki erabiltzailearen egoera \"Ez molestatu\" moduan jakinarazpen guztiak isilarazteko.",
+ "Cancel" : "Utzi",
+ "Import" : "Inportatu",
+ "Error while saving settings" : "Errorea ezarpenak gordetzean",
+ "Reset to default" : "Berezarri balio lehenetsira",
"Availability" : "Eskuragarritasuna",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Zure lan orduak konfiguratzen badituzu, beste pertsonek bulegotik kanpo zaudela ikusiko dute bilera bat erreserbatzen dutenean.",
"Absence" : "Absentzia",
@@ -301,17 +305,10 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Bidali gogorarazpen jakinarazpenak egutegi partekatzea dutenei ere",
"Reminders are always sent to organizers and attendees." : "Gogorarazpenak beti bidaltzen zaizkie antolatzaileei eta parte-hartzaileei.",
"Enable notifications for events via push" : "Gaitu push bidezko jakinarazpenak gertaerentzat",
- "Cancel" : "Utzi",
- "Import" : "Inportatu",
- "Error while saving settings" : "Errorea ezarpenak gordetzean",
"There was an error updating your attendance status." : "Errore bat gertatu da zure parte-hartze egoera eguneratzerakoan.",
"Please contact the organizer directly." : "Mesedez jarri harremanetan antolatzailearekin zuzenean.",
"Are you accepting the invitation?" : "Gonbidapena onartzen duzu?",
"Tentative" : "Behin behinekoa",
- "Your attendance was updated successfully." : "Zure parte-hartzea ondo eguneratu da.",
- "Time:" : "Noiz:",
- "Could not open file" : "Ezin izan da fitxategia ireki",
- "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"
+ "Your attendance was updated successfully." : "Zure parte-hartzea ondo eguneratu da."
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/eu.json b/apps/dav/l10n/eu.json
index ab0924414c4..ac11ede49c3 100644
--- a/apps/dav/l10n/eu.json
+++ b/apps/dav/l10n/eu.json
@@ -283,6 +283,10 @@
"Pick a start time for {dayName}" : "Hautatu hasiera ordu bat {dayName}(e)rako",
"Pick a end time for {dayName}" : "Hautatu bukaera ordu bat {dayName}(e)rako",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Eskuragarri ez egotean, ezarri automatikoki erabiltzailearen egoera \"Ez molestatu\" moduan jakinarazpen guztiak isilarazteko.",
+ "Cancel" : "Utzi",
+ "Import" : "Inportatu",
+ "Error while saving settings" : "Errorea ezarpenak gordetzean",
+ "Reset to default" : "Berezarri balio lehenetsira",
"Availability" : "Eskuragarritasuna",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Zure lan orduak konfiguratzen badituzu, beste pertsonek bulegotik kanpo zaudela ikusiko dute bilera bat erreserbatzen dutenean.",
"Absence" : "Absentzia",
@@ -299,17 +303,10 @@
"Send reminder notifications to calendar sharees as well" : "Bidali gogorarazpen jakinarazpenak egutegi partekatzea dutenei ere",
"Reminders are always sent to organizers and attendees." : "Gogorarazpenak beti bidaltzen zaizkie antolatzaileei eta parte-hartzaileei.",
"Enable notifications for events via push" : "Gaitu push bidezko jakinarazpenak gertaerentzat",
- "Cancel" : "Utzi",
- "Import" : "Inportatu",
- "Error while saving settings" : "Errorea ezarpenak gordetzean",
"There was an error updating your attendance status." : "Errore bat gertatu da zure parte-hartze egoera eguneratzerakoan.",
"Please contact the organizer directly." : "Mesedez jarri harremanetan antolatzailearekin zuzenean.",
"Are you accepting the invitation?" : "Gonbidapena onartzen duzu?",
"Tentative" : "Behin behinekoa",
- "Your attendance was updated successfully." : "Zure parte-hartzea ondo eguneratu da.",
- "Time:" : "Noiz:",
- "Could not open file" : "Ezin izan da fitxategia ireki",
- "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"
+ "Your attendance was updated successfully." : "Zure parte-hartzea ondo eguneratu da."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/fa.js b/apps/dav/l10n/fa.js
index 03bc4a221ba..4ce74a149f2 100644
--- a/apps/dav/l10n/fa.js
+++ b/apps/dav/l10n/fa.js
@@ -4,96 +4,170 @@ OC.L10N.register(
"Calendar" : "تقویم",
"Tasks" : "وظایف",
"Personal" : "شخصی",
- "{actor} created calendar {calendar}" : "{actor} created calendar {calendar}",
- "You created calendar {calendar}" : "تقویم ساخته شد",
- "{actor} deleted calendar {calendar}" : "{actor} deleted calendar {calendar}",
- "You deleted calendar {calendar}" : "You deleted calendar {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} updated calendar {calendar}",
- "You updated calendar {calendar}" : "You updated calendar {calendar}",
- "{actor} restored calendar {calendar}" : "{actor} restored calendar {calendar}",
- "You restored calendar {calendar}" : "You restored calendar {calendar}",
- "You shared calendar {calendar} as public link" : "You shared calendar {calendar} as public link",
- "You removed public link for calendar {calendar}" : "You removed public link for calendar {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} shared calendar {calendar} with you",
- "You shared calendar {calendar} with {user}" : "You shared calendar {calendar} with {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} shared calendar {calendar} with {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} unshared calendar {calendar} from you",
- "You unshared calendar {calendar} from {user}" : "You unshared calendar {calendar} from {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} unshared calendar {calendar} from {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} unshared calendar {calendar} from themselves",
- "You shared calendar {calendar} with group {group}" : "You shared calendar {calendar} with group {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} shared calendar {calendar} with group {group}",
- "You unshared calendar {calendar} from group {group}" : "You unshared calendar {calendar} from group {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} unshared calendar {calendar} from group {group}",
+ "{actor} created calendar {calendar}" : "{actor} تقویم {calendar} را ایجاد کرد",
+ "You created calendar {calendar}" : "شما تقویم {calendar} را ایجاد کردید",
+ "{actor} deleted calendar {calendar}" : "{actor} تقویم {calendar} را حذف کرد",
+ "You deleted calendar {calendar}" : "شما تقویم {calendar} را حذف کردید",
+ "{actor} updated calendar {calendar}" : "{actor} تقویم {calendar} را به‌روزرسانی کرد",
+ "You updated calendar {calendar}" : "شما تقویم {calendar} را به‌روزرسانی کردید",
+ "{actor} restored calendar {calendar}" : "{actor} تقویم {calendar} را بازیابی کرد",
+ "You restored calendar {calendar}" : "شما تقویم {calendar} را بازیابی کردید",
+ "You shared calendar {calendar} as public link" : "شما تقویم {calendar} را به‌عنوان پیوند عمومی به اشتراک گذاشتید",
+ "You removed public link for calendar {calendar}" : "شما پیوند عمومی تقویم {calendar} را حذف کردید",
+ "{actor} shared calendar {calendar} with you" : "{actor} تقویم {calendar} را با شما به اشتراک گذاشت",
+ "You shared calendar {calendar} with {user}" : "شما تقویم {calendar} را با {user} به اشتراک گذاشتید",
+ "{actor} shared calendar {calendar} with {user}" : "{actor} تقویم {calendar} را با {user} به اشتراک گذاشت",
+ "{actor} unshared calendar {calendar} from you" : "{actor} اشتراک‌گذاری تقویم {calendar} را از شما لغو کرد",
+ "You unshared calendar {calendar} from {user}" : "شما اشتراک‌گذاری تقویم {calendar} را از {user} لغو کردید",
+ "{actor} unshared calendar {calendar} from {user}" : "{actor} اشتراک‌گذاری تقویم {calendar} را از {user} لغو کرد",
+ "{actor} unshared calendar {calendar} from themselves" : "{actor} اشتراک‌گذاری تقویم {calendar} را از خود لغو کرد",
+ "You shared calendar {calendar} with group {group}" : "شما تقویم {calendar} را با گروه {group} به اشتراک گذاشتید",
+ "{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} created event {event} in calendar {calendar}",
- "You created event {event} in calendar {calendar}" : "You created event {event} in calendar {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} deleted event {event} from calendar {calendar}",
- "You deleted event {event} from calendar {calendar}" : "You deleted event {event} from calendar {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} updated event {event} in calendar {calendar}",
- "You updated event {event} in calendar {calendar}" : "You updated event {event} in calendar {calendar}",
- "{actor} moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "{actor} moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}",
- "You moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "You moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}",
- "{actor} restored event {event} of calendar {calendar}" : "{actor} restored event {event} of calendar {calendar}",
- "You restored event {event} of calendar {calendar}" : "You restored event {event} of calendar {calendar}",
+ "{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} حذف کرد",
+ "You deleted event {event} from calendar {calendar}" : "شما رویداد {event} را از تقویم {calendar} حذف کردید",
+ "{actor} updated event {event} in calendar {calendar}" : "{actor} رویداد {event} را در تقویم {calendar} به‌روزرسانی کرد",
+ "You updated event {event} in calendar {calendar}" : "شما رویداد {event} را در تقویم {calendar} به‌روزرسانی کردید",
+ "{actor} moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "{actor} رویداد {event} را از تقویم {sourceCalendar} به تقویم {targetCalendar} منتقل کرد",
+ "You moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "شما رویداد {event} را از تقویم {sourceCalendar} به تقویم {targetCalendar} منتقل کردید",
+ "{actor} restored event {event} of calendar {calendar}" : "{actor} رویداد {event} را از تقویم {calendar} بازیابی کرد",
+ "You restored event {event} of calendar {calendar}" : "شما رویداد {event} را از تقویم {calendar} بازیابی کردید",
"Busy" : "مشغول",
- "{actor} created to-do {todo} in list {calendar}" : "{actor} created to-do {todo} in list {calendar}",
- "You created to-do {todo} in list {calendar}" : "You created to-do {todo} in list {calendar}",
- "{actor} deleted to-do {todo} from list {calendar}" : "{actor} deleted to-do {todo} from list {calendar}",
- "You deleted to-do {todo} from list {calendar}" : "You deleted to-do {todo} from list {calendar}",
- "{actor} updated to-do {todo} in list {calendar}" : "{actor} updated to-do {todo} in list {calendar}",
- "You updated to-do {todo} in list {calendar}" : "You updated to-do {todo} in list {calendar}",
- "{actor} solved to-do {todo} in list {calendar}" : "{actor} solved to-do {todo} in list {calendar}",
- "You solved to-do {todo} in list {calendar}" : "You solved to-do {todo} in list {calendar}",
- "{actor} reopened to-do {todo} in list {calendar}" : "{actor} reopened to-do {todo} in list {calendar}",
- "You reopened to-do {todo} in list {calendar}" : "You reopened to-do {todo} in list {calendar}",
- "{actor} moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}" : "{actor} moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}",
- "You moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}" : "You moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}",
- "Calendar, contacts and tasks" : "Calendar, contacts and tasks",
- "A <strong>calendar</strong> was modified" : "یک تقویم تغییر کرد",
- "A calendar <strong>event</strong> was modified" : "یک رویداد ثبت شده در تقویم تغییر کرد",
- "A calendar <strong>to-do</strong> was modified" : "یک کار ثبت شده در تقویم تغییر کرد",
- "Contact birthdays" : "Contact birthdays",
- "Death of %s" : "Death of %s",
+ "{actor} created to-do {todo} in list {calendar}" : "{actor} کار {todo} را در لیست {calendar} ایجاد کرد",
+ "You created to-do {todo} in list {calendar}" : "شما کار {todo} را در لیست {calendar} ایجاد کردید",
+ "{actor} deleted to-do {todo} from list {calendar}" : "{actor} کار {todo} را از لیست {calendar} حذف کرد",
+ "You deleted to-do {todo} from list {calendar}" : "شما کار {todo} را از لیست {calendar} حذف کردید",
+ "{actor} updated to-do {todo} in list {calendar}" : "{actor} کار {todo} را در لیست {calendar} به‌روزرسانی کرد",
+ "You updated to-do {todo} in list {calendar}" : "شما کار {todo} را در لیست {calendar} به‌روزرسانی کردید",
+ "{actor} solved to-do {todo} in list {calendar}" : "{actor} کار {todo} را در لیست {calendar} حل کرد",
+ "You solved to-do {todo} in list {calendar}" : "شما کار {todo} را در لیست {calendar} حل کردید",
+ "{actor} reopened to-do {todo} in list {calendar}" : "{actor} کار {todo} را در لیست {calendar} بازگشایی کرد",
+ "You reopened to-do {todo} in list {calendar}" : "شما کار {todo} را در لیست {calendar} بازگشایی کردید",
+ "{actor} moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}" : "{actor} کار {todo} را از لیست {sourceCalendar} به لیست {targetCalendar} منتقل کرد",
+ "You moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}" : "شما کار {todo} را از لیست {sourceCalendar} به لیست {targetCalendar} منتقل کردید",
+ "Calendar, contacts and tasks" : "تقویم، مخاطبین و وظایف",
+ "A <strong>calendar</strong> was modified" : "یک <strong>تقویم</strong> تغییر کرد",
+ "A calendar <strong>event</strong> was modified" : "یک <strong>رویداد</strong> تقویم تغییر کرد",
+ "A calendar <strong>to-do</strong> was modified" : "یک <strong>کار</strong> تقویم تغییر کرد",
+ "Contact birthdays" : "تولد مخاطبین",
+ "Death of %s" : "فوت %s",
"Untitled calendar" : "تقویم بدون عنوان",
- "Calendar:" : "Calendar:",
+ "Calendar:" : "تقویم:",
"Date:" : "تاریخ:",
"Where:" : "مکان:",
"Description:" : "توضیحات:",
- "_%n year_::_%n years_" : ["%n year","%n years"],
- "_%n month_::_%n months_" : ["%n month","%n months"],
- "_%n day_::_%n days_" : ["%n day","%n days"],
- "_%n hour_::_%n hours_" : ["%n hour","%n hours"],
- "_%n minute_::_%n minutes_" : ["%n minute","%n minutes"],
- "%s (in %s)" : "%s (in %s)",
- "%s (%s ago)" : "%s (%s ago)",
- "Calendar: %s" : "Calendar: %s",
- "Date: %s" : "Date: %s",
- "Description: %s" : "Description: %s",
- "Where: %s" : "Where: %s",
+ "_%n year_::_%n years_" : ["%n سال","%n سال"],
+ "_%n month_::_%n months_" : ["%n ماه","%n ماه"],
+ "_%n day_::_%n days_" : ["%n روز","%n روز"],
+ "_%n hour_::_%n hours_" : ["%n ساعت","%n ساعت"],
+ "_%n minute_::_%n minutes_" : ["%n دقیقه","%n دقیقه"],
+ "%s (in %s)" : "%s (در %s)",
+ "%s (%s ago)" : "%s (%s پیش)",
+ "Calendar: %s" : "تقویم: %s",
+ "Date: %s" : "تاریخ: %s",
+ "Description: %s" : "توضیحات: %s",
+ "Where: %s" : "مکان: %s",
"%1$s via %2$s" : "%1$s از طریق %2$s",
- "Cancelled: %1$s" : "Cancelled: %1$s",
- "\"%1$s\" has been canceled" : "\"%1$s\" has been canceled",
- "Re: %1$s" : "Re: %1$s",
- "%1$s has accepted your invitation" : "%1$s has accepted your invitation",
- "%1$s has tentatively accepted your invitation" : "%1$s has tentatively accepted your invitation",
- "%1$s has declined your invitation" : "%1$s has declined your invitation",
- "%1$s has responded to your invitation" : "%1$s has responded to your invitation",
- "Invitation updated: %1$s" : "Invitation updated: %1$s",
- "%1$s updated the event \"%2$s\"" : "%1$s updated the event \"%2$s\"",
- "Invitation: %1$s" : "Invitation: %1$s",
- "%1$s would like to invite you to \"%2$s\"" : "%1$s would like to invite you to \"%2$s\"",
- "Organizer:" : "Organizer:",
- "Attendees:" : "Attendees:",
+ "In the past on %1$s for the entire day" : "در گذشته در %1$s برای کل روز",
+ "_In a minute on %1$s for the entire day_::_In %n minutes on %1$s for the entire day_" : ["در یک دقیقه در %1$s برای کل روز","در %n دقیقه در %1$s برای کل روز"],
+ "_In a hour on %1$s for the entire day_::_In %n hours on %1$s for the entire day_" : ["در یک ساعت در %1$s برای کل روز","در %n ساعت در %1$s برای کل روز"],
+ "_In a day on %1$s for the entire day_::_In %n days on %1$s for the entire day_" : ["در یک روز در %1$s برای کل روز","در %n روز در %1$s برای کل روز"],
+ "_In a week on %1$s for the entire day_::_In %n weeks on %1$s for the entire day_" : ["در یک هفته در %1$s برای کل روز","در %n هفته در %1$s برای کل روز"],
+ "_In a month on %1$s for the entire day_::_In %n months on %1$s for the entire day_" : ["در یک ماه در %1$s برای کل روز","در %n ماه در %1$s برای کل روز"],
+ "_In a year on %1$s for the entire day_::_In %n years on %1$s for the entire day_" : ["در یک سال در %1$s برای کل روز","در %n سال در %1$s برای کل روز"],
+ "In the past on %1$s between %2$s - %3$s" : "در گذشته در %1$s بین %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_" : ["در یک دقیقه در %1$s بین %2$s - %3$s","در %n دقیقه در %1$s بین %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_" : ["در یک ساعت در %1$s بین %2$s - %3$s","در %n ساعت در %1$s بین %2$s - %3$s"],
+ "_In a day on %1$s between %2$s - %3$s_::_In %n days on %1$s between %2$s - %3$s_" : ["در یک روز در %1$s بین %2$s - %3$s","در %n روز در %1$s بین %2$s - %3$s"],
+ "_In a week on %1$s between %2$s - %3$s_::_In %n weeks on %1$s between %2$s - %3$s_" : ["در یک هفته در %1$s بین %2$s - %3$s","در %n هفته در %1$s بین %2$s - %3$s"],
+ "_In a month on %1$s between %2$s - %3$s_::_In %n months on %1$s between %2$s - %3$s_" : ["در یک ماه در %1$s بین %2$s - %3$s","در %n ماه در %1$s بین %2$s - %3$s"],
+ "_In a year on %1$s between %2$s - %3$s_::_In %n years on %1$s between %2$s - %3$s_" : ["در یک سال در %1$s بین %2$s - %3$s","در %n سال در %1$s بین %2$s - %3$s"],
+ "Could not generate when statement" : "امکان ایجاد عبارت زمان وجود ندارد",
+ "Every Day for the entire day" : "هر روز برای کل روز",
+ "Every Day for the entire day until %1$s" : "هر روز برای کل روز تا %1$s",
+ "Every Day between %1$s - %2$s" : "هر روز بین %1$s - %2$s",
+ "Every Day between %1$s - %2$s until %3$s" : "هر روز بین %1$s - %2$s تا %3$s",
+ "Every %1$d Days for the entire day" : "هر %1$d روز برای کل روز",
+ "Every %1$d Days for the entire day until %2$s" : "هر %1$d روز برای کل روز تا %2$s",
+ "Every %1$d Days between %2$s - %3$s" : "هر %1$d روز بین %2$s - %3$s",
+ "Every %1$d Days between %2$s - %3$s until %4$s" : "هر %1$d روز بین %2$s - %3$s تا %4$s",
+ "Could not generate event recurrence statement" : "امکان ایجاد عبارت تکرار رویداد وجود ندارد",
+ "Every Week on %1$s for the entire day" : "هر هفته در %1$s برای کل روز",
+ "Every Week on %1$s for the entire day until %2$s" : "هر هفته در %1$s برای کل روز تا %2$s",
+ "Every Week on %1$s between %2$s - %3$s" : "هر هفته در %1$s بین %2$s - %3$s",
+ "Every Week on %1$s between %2$s - %3$s until %4$s" : "هر هفته در %1$s بین %2$s - %3$s تا %4$s",
+ "Every %1$d Weeks on %2$s for the entire day" : "هر %1$d هفته در %2$s برای کل روز",
+ "Every %1$d Weeks on %2$s for the entire day until %3$s" : "هر %1$d هفته در %2$s برای کل روز تا %3$s",
+ "Every %1$d Weeks on %2$s between %3$s - %4$s" : "هر %1$d هفته در %2$s بین %3$s - %4$s",
+ "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "هر %1$d هفته در %2$s بین %3$s - %4$s تا %5$s",
+ "Every Month on the %1$s for the entire day" : "هر ماه در %1$s برای کل روز",
+ "Every Month on the %1$s for the entire day until %2$s" : "هر ماه در %1$s برای کل روز تا %2$s",
+ "Every Month on the %1$s between %2$s - %3$s" : "هر ماه در %1$s بین %2$s - %3$s",
+ "Every Month on the %1$s between %2$s - %3$s until %4$s" : "هر ماه در %1$s بین %2$s - %3$s تا %4$s",
+ "Every %1$d Months on the %2$s for the entire day" : "هر %1$d ماه در %2$s برای کل روز",
+ "Every %1$d Months on the %2$s for the entire day until %3$s" : "هر %1$d ماه در %2$s برای کل روز تا %3$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s" : "هر %1$d ماه در %2$s بین %3$s - %4$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "هر %1$d ماه در %2$s بین %3$s - %4$s تا %5$s",
+ "Every Year in %1$s on the %2$s for the entire day" : "هر سال در %1$s در %2$s برای کل روز",
+ "Every Year in %1$s on the %2$s for the entire day until %3$s" : "هر سال در %1$s در %2$s برای کل روز تا %3$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s" : "هر سال در %1$s در %2$s بین %3$s - %4$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "هر سال در %1$s در %2$s بین %3$s - %4$s تا %5$s",
+ "Every %1$d Years in %2$s on the %3$s for the entire day" : "هر %1$d سال در %2$s در %3$s برای کل روز",
+ "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "هر %1$d سال در %2$s در %3$s برای کل روز تا %4$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "هر %1$d سال در %2$s در %3$s بین %4$s - %5$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "هر %1$d سال در %2$s در %3$s بین %4$s - %5$s تا %6$s",
+ "On specific dates for the entire day until %1$s" : "در تاریخ‌های مشخص برای کل روز تا %1$s",
+ "On specific dates between %1$s - %2$s until %3$s" : "در تاریخ‌های مشخص بین %1$s - %2$s تا %3$s",
+ "In the past on %1$s" : "در گذشته در %1$s",
+ "_In a minute on %1$s_::_In %n minutes on %1$s_" : ["در یک دقیقه در %1$s","در %n دقیقه در %1$s"],
+ "_In a hour on %1$s_::_In %n hours on %1$s_" : ["در یک ساعت در %1$s","در %n ساعت در %1$s"],
+ "_In a day on %1$s_::_In %n days on %1$s_" : ["در یک روز در %1$s","در %n روز در %1$s"],
+ "_In a week on %1$s_::_In %n weeks on %1$s_" : ["در یک هفته در %1$s","در %n هفته در %1$s"],
+ "_In a month on %1$s_::_In %n months on %1$s_" : ["در یک ماه در %1$s","در %n ماه در %1$s"],
+ "_In a year on %1$s_::_In %n years on %1$s_" : ["در یک سال در %1$s","در %n سال در %1$s"],
+ "In the past on %1$s then on %2$s" : "در گذشته در %1$s سپس در %2$s",
+ "_In a minute on %1$s then on %2$s_::_In %n minutes on %1$s then on %2$s_" : ["در یک دقیقه در %1$s سپس در %2$s","در %n دقیقه در %1$s سپس در %2$s"],
+ "_In a hour on %1$s then on %2$s_::_In %n hours on %1$s then on %2$s_" : ["در یک ساعت در %1$s سپس در %2$s","در %n ساعت در %1$s سپس در %2$s"],
+ "_In a day on %1$s then on %2$s_::_In %n days on %1$s then on %2$s_" : ["در یک روز در %1$s سپس در %2$s","در %n روز در %1$s سپس در %2$s"],
+ "_In a week on %1$s then on %2$s_::_In %n weeks on %1$s then on %2$s_" : ["در یک هفته در %1$s سپس در %2$s","در %n هفته در %1$s سپس در %2$s"],
+ "_In a month on %1$s then on %2$s_::_In %n months on %1$s then on %2$s_" : ["در یک ماه در %1$s سپس در %2$s","در %n ماه در %1$s سپس در %2$s"],
+ "_In a year on %1$s then on %2$s_::_In %n years on %1$s then on %2$s_" : ["در یک سال در %1$s سپس در %2$s","در %n سال در %1$s سپس در %2$s"],
+ "In the past on %1$s then on %2$s and %3$s" : "در گذشته در %1$s سپس در %2$s و %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_" : ["در یک دقیقه در %1$s سپس در %2$s و %3$s","در %n دقیقه در %1$s سپس در %2$s و %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_" : ["در یک ساعت در %1$s سپس در %2$s و %3$s","در %n ساعت در %1$s سپس در %2$s و %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_" : ["در یک روز در %1$s سپس در %2$s و %3$s","در %n روز در %1$s سپس در %2$s و %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_" : ["در یک هفته در %1$s سپس در %2$s و %3$s","در %n هفته در %1$s سپس در %2$s و %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_" : ["در یک ماه در %1$s سپس در %2$s و %3$s","در %n ماه در %1$s سپس در %2$s و %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_" : ["در یک سال در %1$s سپس در %2$s و %3$s","در %n سال در %1$s سپس در %2$s و %3$s"],
+ "Could not generate next recurrence statement" : "امکان ایجاد عبارت تکرار بعدی وجود ندارد",
+ "Cancelled: %1$s" : "لغو شد: %1$s",
+ "\"%1$s\" has been canceled" : "\"%1$s\" لغو شده است",
+ "Re: %1$s" : "پاسخ: %1$s",
+ "%1$s has accepted your invitation" : "%1$s دعوت شما را پذیرفته است",
+ "%1$s has tentatively accepted your invitation" : "%1$s دعوت شما را به‌طور آزمایشی پذیرفته است",
+ "%1$s has declined your invitation" : "%1$s دعوت شما را رد کرده است",
+ "%1$s has responded to your invitation" : "%1$s به دعوت شما پاسخ داده است",
+ "Invitation updated: %1$s" : "دعوت به‌روزرسانی شد: %1$s",
+ "%1$s updated the event \"%2$s\"" : "%1$s رویداد \"%2$s\" را به‌روزرسانی کرد",
+ "Invitation: %1$s" : "دعوت: %1$s",
+ "%1$s would like to invite you to \"%2$s\"" : "%1$s مایل است شما را به \"%2$s\" دعوت کند",
+ "Organizer:" : "برگزارکننده:",
+ "Attendees:" : "شرکت‌کنندگان:",
"Title:" : "عنوان:",
+ "When:" : "چه زمانی:",
"Location:" : "مکان:",
- "Link:" : "Link:",
- "Accept" : "قبول",
- "Decline" : "کاهش می یابد",
- "More options …" : "More options …",
- "More options at %s" : "More options at %s",
+ "Link:" : "پیوند:",
+ "Occurring:" : "در حال وقوع:",
+ "Accept" : "پذیرفتن",
+ "Decline" : "رد کردن",
+ "More options …" : "گزینه‌های بیشتر…",
+ "More options at %s" : "گزینه‌های بیشتر در %s",
"Monday" : "دوشنبه",
- "Tuesday" : "سه شنبه",
+ "Tuesday" : "سه‌شنبه",
"Wednesday" : "چهارشنبه",
"Thursday" : "پنجشنبه",
"Friday" : "جمعه",
@@ -105,105 +179,148 @@ OC.L10N.register(
"April" : "آوریل",
"May" : "مه",
"June" : "ژوئن",
- "July" : "جولای",
+ "July" : "ژوئیه",
"August" : "اوت",
"September" : "سپتامبر",
"October" : "اکتبر",
"November" : "نوامبر",
"December" : "دسامبر",
- "First" : "First",
- "Last" : "Last",
+ "First" : "اول",
+ "Second" : "دوم",
+ "Third" : "سوم",
+ "Fourth" : "چهارم",
+ "Fifth" : "پنجم",
+ "Last" : "آخر",
+ "Second Last" : "دومی از آخر",
+ "Third Last" : "سومی از آخر",
+ "Fourth Last" : "چهارمی از آخر",
+ "Fifth Last" : "پنجمی از آخر",
"Contacts" : "مخاطبین",
- "{actor} created address book {addressbook}" : "{actor} created address book {addressbook}",
- "You created address book {addressbook}" : "دفترچه آدرس ساخته شد",
- "{actor} deleted address book {addressbook}" : "{actor} deleted address book {addressbook}",
- "You deleted address book {addressbook}" : "You deleted address book {addressbook}",
- "{actor} updated address book {addressbook}" : "{actor} updated address book {addressbook}",
- "You updated address book {addressbook}" : "You updated address book {addressbook}",
- "{actor} shared address book {addressbook} with you" : "{actor} shared address book {addressbook} with you",
- "You shared address book {addressbook} with {user}" : "You shared address book {addressbook} with {user}",
- "{actor} shared address book {addressbook} with {user}" : "{actor} shared address book {addressbook} with {user}",
- "{actor} unshared address book {addressbook} from you" : "{actor} unshared address book {addressbook} from you",
- "You unshared address book {addressbook} from {user}" : "You unshared address book {addressbook} from {user}",
- "{actor} unshared address book {addressbook} from {user}" : "{actor} unshared address book {addressbook} from {user}",
- "{actor} unshared address book {addressbook} from themselves" : "{actor} unshared address book {addressbook} from themselves",
- "You shared address book {addressbook} with group {group}" : "You shared address book {addressbook} with group {group}",
- "{actor} shared address book {addressbook} with group {group}" : "{actor} shared address book {addressbook} with group {group}",
- "You unshared address book {addressbook} from group {group}" : "You unshared address book {addressbook} from group {group}",
- "{actor} unshared address book {addressbook} from group {group}" : "{actor} unshared address book {addressbook} from group {group}",
- "{actor} created contact {card} in address book {addressbook}" : "{actor} created contact {card} in address book {addressbook}",
- "You created contact {card} in address book {addressbook}" : "You created contact {card} in address book {addressbook}",
- "{actor} deleted contact {card} from address book {addressbook}" : "{actor} deleted contact {card} from address book {addressbook}",
- "You deleted contact {card} from address book {addressbook}" : "You deleted contact {card} from address book {addressbook}",
- "{actor} updated contact {card} in address book {addressbook}" : "{actor} updated contact {card} in address book {addressbook}",
- "You updated contact {card} in address book {addressbook}" : "You updated contact {card} in address book {addressbook}",
- "A <strong>contact</strong> or <strong>address book</strong> was modified" : "یک مخاطب یا دفترچه آدرس تغییر کرد",
+ "{actor} created address book {addressbook}" : "{actor} دفترچه آدرس {addressbook} را ایجاد کرد",
+ "You created address book {addressbook}" : "شما دفترچه آدرس {addressbook} را ایجاد کردید",
+ "{actor} deleted address book {addressbook}" : "{actor} دفترچه آدرس {addressbook} را حذف کرد",
+ "You deleted address book {addressbook}" : "شما دفترچه آدرس {addressbook} را حذف کردید",
+ "{actor} updated address book {addressbook}" : "{actor} دفترچه آدرس {addressbook} را به‌روزرسانی کرد",
+ "You updated address book {addressbook}" : "شما دفترچه آدرس {addressbook} را به‌روزرسانی کردید",
+ "{actor} shared address book {addressbook} with you" : "{actor} دفترچه آدرس {addressbook} را با شما به اشتراک گذاشت",
+ "You shared address book {addressbook} with {user}" : "شما دفترچه آدرس {addressbook} را با {user} به اشتراک گذاشتید",
+ "{actor} shared address book {addressbook} with {user}" : "{actor} دفترچه آدرس {addressbook} را با {user} به اشتراک گذاشت",
+ "{actor} unshared address book {addressbook} from you" : "{actor} اشتراک‌گذاری دفترچه آدرس {addressbook} را از شما لغو کرد",
+ "You unshared address book {addressbook} from {user}" : "شما اشتراک‌گذاری دفترچه آدرس {addressbook} را از {user} لغو کردید",
+ "{actor} unshared address book {addressbook} from {user}" : "{actor} اشتراک‌گذاری دفترچه آدرس {addressbook} را از {user} لغو کرد",
+ "{actor} unshared address book {addressbook} from themselves" : "{actor} اشتراک‌گذاری دفترچه آدرس {addressbook} را از خود لغو کرد",
+ "You shared address book {addressbook} with group {group}" : "شما دفترچه آدرس {addressbook} را با گروه {group} به اشتراک گذاشتید",
+ "{actor} shared address book {addressbook} with group {group}" : "{actor} دفترچه آدرس {addressbook} را با گروه {group} به اشتراک گذاشت",
+ "You unshared address book {addressbook} from group {group}" : "شما اشتراک‌گذاری دفترچه آدرس {addressbook} را از گروه {group} لغو کردید",
+ "{actor} unshared address book {addressbook} from group {group}" : "{actor} اشتراک‌گذاری دفترچه آدرس {addressbook} را از گروه {group} لغو کرد",
+ "{actor} created contact {card} in address book {addressbook}" : "{actor} مخاطب {card} را در دفترچه آدرس {addressbook} ایجاد کرد",
+ "You created contact {card} in address book {addressbook}" : "شما مخاطب {card} را در دفترچه آدرس {addressbook} ایجاد کردید",
+ "{actor} deleted contact {card} from address book {addressbook}" : "{actor} مخاطب {card} را از دفترچه آدرس {addressbook} حذف کرد",
+ "You deleted contact {card} from address book {addressbook}" : "شما مخاطب {card} را از دفترچه آدرس {addressbook} حذف کردید",
+ "{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> تغییر کرد",
"Accounts" : "حساب‌ها",
- "File is not updatable: %1$s" : "File is not updatable: %1$s",
- "Could not write to final file, canceled by hook" : "Could not write to final file, canceled by hook",
- "Could not write file contents" : "Could not write file contents",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Error while copying file to target location (copied: %1$s, expected filesize: %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." : "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.",
- "Could not rename part file to final file, canceled by hook" : "Could not rename part file to final file, canceled by hook",
- "Could not rename part file to final file" : "Could not rename part file to final file",
- "Failed to check file size: %1$s" : "Failed to check file size: %1$s",
- "Encryption not ready: %1$s" : "Encryption not ready: %1$s",
- "Failed to open file: %1$s" : "Failed to open file: %1$s",
- "Failed to unlink: %1$s" : "Failed to unlink: %1$s",
- "Failed to write file contents: %1$s" : "Failed to write file contents: %1$s",
- "File not found: %1$s" : "File not found: %1$s",
- "System is in maintenance mode." : "System is in maintenance mode.",
- "Upgrade needed" : "Upgrade needed",
- "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS.",
- "Configures a CalDAV account" : "Configures a CalDAV account",
- "Configures a CardDAV account" : "Configures a CardDAV account",
- "Events" : "Events",
+ "System address book which holds all accounts" : "دفترچه آدرس سیستمی که شامل تمام حساب‌ها است",
+ "File is not updatable: %1$s" : "فایل قابل به‌روزرسانی نیست: %1$s",
+ "Failed to get storage for file" : "دریافت فضای ذخیره‌سازی برای فایل با شکست مواجه شد",
+ "Could not write to final file, canceled by hook" : "نوشتن در فایل نهایی امکان‌پذیر نبود، توسط هوک لغو شد",
+ "Could not write file contents" : "امکان نوشتن محتویات فایل وجود ندارد",
+ "_%n byte_::_%n bytes_" : ["%n بایت","%n بایت"],
+ "Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "خطا هنگام کپی فایل به مکان مقصد (کپی شده: %1$s، حجم فایل مورد انتظار: %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$s بود اما %2$s خوانده (از کلاینت Nextcloud) و نوشته (در فضای ذخیره‌سازی Nextcloud) شد. این می‌تواند ناشی از مشکل شبکه در سمت ارسال یا مشکل نوشتن در فضای ذخیره‌سازی در سمت سرور باشد.",
+ "Could not rename part file to final file, canceled by hook" : "امکان تغییر نام فایل جزئی به فایل نهایی وجود نداشت، توسط هوک لغو شد",
+ "Could not rename part file to final file" : "امکان تغییر نام فایل جزئی به فایل نهایی وجود ندارد",
+ "Failed to check file size: %1$s" : "بررسی حجم فایل با شکست مواجه شد: %1$s",
+ "Could not open file: %1$s, file does seem to exist" : "امکان باز کردن فایل وجود ندارد: %1$s، به نظر می‌رسد فایل وجود دارد",
+ "Could not open file: %1$s, file doesn't seem to exist" : "امکان باز کردن فایل وجود ندارد: %1$s، به نظر می‌رسد فایل وجود ندارد",
+ "Encryption not ready: %1$s" : "رمزگذاری آماده نیست: %1$s",
+ "Failed to open file: %1$s" : "باز کردن فایل با شکست مواجه شد: %1$s",
+ "Failed to unlink: %1$s" : "حذف پیوند با شکست مواجه شد: %1$s",
+ "Failed to write file contents: %1$s" : "نوشتن محتویات فایل با شکست مواجه شد: %1$s",
+ "File not found: %1$s" : "فایل یافت نشد: %1$s",
+ "Invalid target path" : "مسیر مقصد نامعتبر است",
+ "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." : "برای استفاده از CalDAV و CardDAV با iOS/macOS، %s شما باید برای استفاده از HTTPS پیکربندی شود.",
+ "Configures a CalDAV account" : "یک حساب CalDAV را پیکربندی می‌کند",
+ "Configures a CardDAV account" : "یک حساب CardDAV را پیکربندی می‌کند",
+ "Events" : "رویدادها",
"Untitled task" : "کار بدون عنوان",
- "Completed on %s" : "Completed on %s",
- "Due on %s by %s" : "Due on %s by %s",
- "Due on %s" : "Due on %s",
- "WebDAV endpoint" : "WebDAV endpoint",
- "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken.",
- "Migrated calendar (%1$s)" : "Migrated calendar (%1$s)",
- "Calendars including events, details and attendees" : "Calendars including events, details and attendees",
- "Contacts and groups" : "Contacts and groups",
- "WebDAV" : "WebDAV",
- "First day" : "First day",
+ "Completed on %s" : "تکمیل شده در %s",
+ "Due on %s by %s" : "موعد در %s توسط %s",
+ "Due on %s" : "موعد در %s",
+ "System Address Book" : "دفترچه آدرس سیستم",
+ "The system address book contains contact information for all users in your instance." : "دفترچه آدرس سیستم شامل اطلاعات تماس برای همه کاربران در نمونه شما است.",
+ "Enable System Address Book" : "فعال کردن دفترچه آدرس سیستم",
+ "DAV system address book" : "دفترچه آدرس سیستم DAV",
+ "No outstanding DAV system address book sync." : "هیچ همگام‌سازی دفترچه آدرس سیستم 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\"." : "همگام‌سازی دفترچه آدرس سیستم DAV هنوز اجرا نشده است زیرا نمونه شما بیش از ۱۰۰۰ کاربر دارد یا خطایی رخ داده است. لطفاً آن را به‌صورت دستی با فراخوانی \"occ dav:sync-system-addressbook\" اجرا کنید.",
+ "WebDAV endpoint" : "نقطه پایانی WebDAV",
+ "Could not check that your web server is properly set up to allow file synchronization over WebDAV. Please check manually." : "امکان بررسی اینکه سرور وب شما به درستی برای همگام‌سازی فایل از طریق WebDAV تنظیم شده است، وجود ندارد. لطفاً به صورت دستی بررسی کنید.",
+ "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." : "سرور وب شما به درستی برای همگام‌سازی فایل از طریق WebDAV تنظیم شده است.",
+ "Migrated calendar (%1$s)" : "تقویم منتقل شده (%1$s)",
+ "Calendars including events, details and attendees" : "تقویم‌ها شامل رویدادها، جزئیات و شرکت‌کنندگان",
+ "Contacts and groups" : "مخاطبین و گروه‌ها",
+ "WebDAV" : "وب‌دَو",
+ "Absence saved" : "غیبت ذخیره شد",
+ "Failed to save your absence settings" : "ذخیره تنظیمات غیبت شما با شکست مواجه شد",
+ "Absence cleared" : "غیبت پاک شد",
+ "Failed to clear your absence settings" : "پاک کردن تنظیمات غیبت شما با شکست مواجه شد",
+ "First day" : "روز اول",
+ "Last day (inclusive)" : "روز آخر (شامل)",
+ "Out of office replacement (optional)" : "جایگزین خارج از دفتر (اختیاری)",
+ "Name of the replacement" : "نام جایگزین",
+ "No results." : "نتیجه‌ای یافت نشد.",
+ "Start typing." : "شروع به تایپ کنید.",
+ "Short absence status" : "وضعیت کوتاه غیبت",
+ "Long absence Message" : "پیام طولانی غیبت",
"Save" : "ذخیره",
- "Failed to load availability" : "Failed to load availability",
- "Saved availability" : "Saved availability",
- "Failed to save availability" : "Failed to save availability",
+ "Disable absence" : "غیرفعال کردن غیبت",
+ "Failed to load availability" : "بارگذاری در دسترس بودن با شکست مواجه شد",
+ "Saved availability" : "در دسترس بودن ذخیره شد",
+ "Failed to save availability" : "ذخیره در دسترس بودن با شکست مواجه شد",
"Time zone:" : "منطقه زمانی:",
- "to" : "به",
- "Delete slot" : "Delete slot",
+ "to" : "تا",
+ "Delete slot" : "حذف بازه زمانی",
"No working hours set" : "ساعات کاری تعیین نشده است",
- "Add slot" : "Add slot",
- "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "وضعیت کاربر بصورت خودکار به \"مزاحم نشوید\" تغییر داده شود تا همه ی اعلان ها خاموش شوند",
- "Availability" : "موجود بودن",
- "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}.",
- "Please make sure to properly set up {emailopen}the email server{linkclose}." : "Please make sure to properly set up {emailopen}the email server{linkclose}.",
- "Calendar server" : "Calendar server",
- "Send invitations to attendees" : "Send invitations to attendees",
- "Automatically generate a birthday calendar" : "Automatically generate a birthday calendar",
- "Birthday calendars will be generated by a background job." : "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." : "Hence they will not be available immediately after enabling but will show up after some time.",
- "Send notifications for events" : "Send notifications for events",
- "Notifications are sent via background jobs, so these must occur often enough." : "Notifications are sent via background jobs, so these must occur often enough.",
- "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 organizers and attendees.",
- "Enable notifications for events via push" : "Enable notifications for events via push",
- "Cancel" : "ردکردن",
+ "Add slot" : "افزودن بازه زمانی",
+ "Weekdays" : "روزهای هفته",
+ "Pick a start time for {dayName}" : "زمان شروع برای {dayName} را انتخاب کنید",
+ "Pick a end time for {dayName}" : "زمان پایان برای {dayName} را انتخاب کنید",
+ "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "وضعیت کاربر بصورت خودکار به \"مزاحم نشوید\" تغییر داده شود تا همه ی اعلان ها خاموش شوند.",
+ "Cancel" : "لغو",
"Import" : "وارد کردن",
- "Error while saving settings" : "Error while saving settings",
- "There was an error updating your attendance status." : "There was an error updating your attendance status.",
- "Please contact the organizer directly." : "Please contact the organizer directly.",
- "Are you accepting the invitation?" : "Are you accepting the invitation?",
+ "Error while saving settings" : "خطا هنگام ذخیره تنظیمات",
+ "Contact reset successfully" : "مخاطب با موفقیت بازنشانی شد",
+ "Error while resetting contact" : "خطا هنگام بازنشانی مخاطب",
+ "Contact imported successfully" : "مخاطب با موفقیت وارد شد",
+ "Error while importing contact" : "خطا هنگام وارد کردن مخاطب",
+ "Import contact" : "وارد کردن مخاطب",
+ "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 جدید، مخاطب پیش‌فرض موجود را حذف کرده و آن را با مخاطب جدید جایگزین می‌کند. آیا می‌خواهید ادامه دهید؟",
+ "Availability" : "در دسترس بودن",
+ "If you configure your working hours, other people will see when you are out of office when they book a meeting." : "اگر ساعات کاری خود را پیکربندی کنید، دیگران هنگام رزرو جلسه متوجه خواهند شد که شما در دفتر نیستید.",
+ "Absence" : "غیبت",
+ "Configure your next absence period." : "دوره غیبت بعدی خود را پیکربندی کنید.",
+ "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" : "ارسال دعوت‌نامه‌ها به شرکت‌کنندگان",
+ "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." : "یادآوری‌ها همیشه برای برگزارکنندگان و شرکت‌کنندگان ارسال می‌شوند.",
+ "Enable notifications for events via push" : "فعال کردن اعلان‌ها برای رویدادها از طریق پوش",
+ "There was an error updating your attendance status." : "خطایی در به‌روزرسانی وضعیت حضور شما رخ داد.",
+ "Please contact the organizer directly." : "لطفاً مستقیماً با برگزارکننده تماس بگیرید.",
+ "Are you accepting the invitation?" : "آیا دعوت را می‌پذیرید؟",
"Tentative" : "آزمایشی",
- "Your attendance was updated successfully." : "Your attendance was updated successfully.",
- "Time:" : "Time:",
- "Could not open file" : "Could not open file",
- "Invalid chunk name" : "Invalid chunk name",
- "Could not rename part file assembled from chunks" : "Could not rename part file assembled from chunks"
+ "Your attendance was updated successfully." : "وضعیت حضور شما با موفقیت به‌روزرسانی شد."
},
"nplurals=2; plural=(n > 1);");
diff --git a/apps/dav/l10n/fa.json b/apps/dav/l10n/fa.json
index 97e7a950714..ca3b31c1f55 100644
--- a/apps/dav/l10n/fa.json
+++ b/apps/dav/l10n/fa.json
@@ -2,96 +2,170 @@
"Calendar" : "تقویم",
"Tasks" : "وظایف",
"Personal" : "شخصی",
- "{actor} created calendar {calendar}" : "{actor} created calendar {calendar}",
- "You created calendar {calendar}" : "تقویم ساخته شد",
- "{actor} deleted calendar {calendar}" : "{actor} deleted calendar {calendar}",
- "You deleted calendar {calendar}" : "You deleted calendar {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} updated calendar {calendar}",
- "You updated calendar {calendar}" : "You updated calendar {calendar}",
- "{actor} restored calendar {calendar}" : "{actor} restored calendar {calendar}",
- "You restored calendar {calendar}" : "You restored calendar {calendar}",
- "You shared calendar {calendar} as public link" : "You shared calendar {calendar} as public link",
- "You removed public link for calendar {calendar}" : "You removed public link for calendar {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} shared calendar {calendar} with you",
- "You shared calendar {calendar} with {user}" : "You shared calendar {calendar} with {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} shared calendar {calendar} with {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} unshared calendar {calendar} from you",
- "You unshared calendar {calendar} from {user}" : "You unshared calendar {calendar} from {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} unshared calendar {calendar} from {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} unshared calendar {calendar} from themselves",
- "You shared calendar {calendar} with group {group}" : "You shared calendar {calendar} with group {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} shared calendar {calendar} with group {group}",
- "You unshared calendar {calendar} from group {group}" : "You unshared calendar {calendar} from group {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} unshared calendar {calendar} from group {group}",
+ "{actor} created calendar {calendar}" : "{actor} تقویم {calendar} را ایجاد کرد",
+ "You created calendar {calendar}" : "شما تقویم {calendar} را ایجاد کردید",
+ "{actor} deleted calendar {calendar}" : "{actor} تقویم {calendar} را حذف کرد",
+ "You deleted calendar {calendar}" : "شما تقویم {calendar} را حذف کردید",
+ "{actor} updated calendar {calendar}" : "{actor} تقویم {calendar} را به‌روزرسانی کرد",
+ "You updated calendar {calendar}" : "شما تقویم {calendar} را به‌روزرسانی کردید",
+ "{actor} restored calendar {calendar}" : "{actor} تقویم {calendar} را بازیابی کرد",
+ "You restored calendar {calendar}" : "شما تقویم {calendar} را بازیابی کردید",
+ "You shared calendar {calendar} as public link" : "شما تقویم {calendar} را به‌عنوان پیوند عمومی به اشتراک گذاشتید",
+ "You removed public link for calendar {calendar}" : "شما پیوند عمومی تقویم {calendar} را حذف کردید",
+ "{actor} shared calendar {calendar} with you" : "{actor} تقویم {calendar} را با شما به اشتراک گذاشت",
+ "You shared calendar {calendar} with {user}" : "شما تقویم {calendar} را با {user} به اشتراک گذاشتید",
+ "{actor} shared calendar {calendar} with {user}" : "{actor} تقویم {calendar} را با {user} به اشتراک گذاشت",
+ "{actor} unshared calendar {calendar} from you" : "{actor} اشتراک‌گذاری تقویم {calendar} را از شما لغو کرد",
+ "You unshared calendar {calendar} from {user}" : "شما اشتراک‌گذاری تقویم {calendar} را از {user} لغو کردید",
+ "{actor} unshared calendar {calendar} from {user}" : "{actor} اشتراک‌گذاری تقویم {calendar} را از {user} لغو کرد",
+ "{actor} unshared calendar {calendar} from themselves" : "{actor} اشتراک‌گذاری تقویم {calendar} را از خود لغو کرد",
+ "You shared calendar {calendar} with group {group}" : "شما تقویم {calendar} را با گروه {group} به اشتراک گذاشتید",
+ "{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} created event {event} in calendar {calendar}",
- "You created event {event} in calendar {calendar}" : "You created event {event} in calendar {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} deleted event {event} from calendar {calendar}",
- "You deleted event {event} from calendar {calendar}" : "You deleted event {event} from calendar {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} updated event {event} in calendar {calendar}",
- "You updated event {event} in calendar {calendar}" : "You updated event {event} in calendar {calendar}",
- "{actor} moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "{actor} moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}",
- "You moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "You moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}",
- "{actor} restored event {event} of calendar {calendar}" : "{actor} restored event {event} of calendar {calendar}",
- "You restored event {event} of calendar {calendar}" : "You restored event {event} of calendar {calendar}",
+ "{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} حذف کرد",
+ "You deleted event {event} from calendar {calendar}" : "شما رویداد {event} را از تقویم {calendar} حذف کردید",
+ "{actor} updated event {event} in calendar {calendar}" : "{actor} رویداد {event} را در تقویم {calendar} به‌روزرسانی کرد",
+ "You updated event {event} in calendar {calendar}" : "شما رویداد {event} را در تقویم {calendar} به‌روزرسانی کردید",
+ "{actor} moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "{actor} رویداد {event} را از تقویم {sourceCalendar} به تقویم {targetCalendar} منتقل کرد",
+ "You moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "شما رویداد {event} را از تقویم {sourceCalendar} به تقویم {targetCalendar} منتقل کردید",
+ "{actor} restored event {event} of calendar {calendar}" : "{actor} رویداد {event} را از تقویم {calendar} بازیابی کرد",
+ "You restored event {event} of calendar {calendar}" : "شما رویداد {event} را از تقویم {calendar} بازیابی کردید",
"Busy" : "مشغول",
- "{actor} created to-do {todo} in list {calendar}" : "{actor} created to-do {todo} in list {calendar}",
- "You created to-do {todo} in list {calendar}" : "You created to-do {todo} in list {calendar}",
- "{actor} deleted to-do {todo} from list {calendar}" : "{actor} deleted to-do {todo} from list {calendar}",
- "You deleted to-do {todo} from list {calendar}" : "You deleted to-do {todo} from list {calendar}",
- "{actor} updated to-do {todo} in list {calendar}" : "{actor} updated to-do {todo} in list {calendar}",
- "You updated to-do {todo} in list {calendar}" : "You updated to-do {todo} in list {calendar}",
- "{actor} solved to-do {todo} in list {calendar}" : "{actor} solved to-do {todo} in list {calendar}",
- "You solved to-do {todo} in list {calendar}" : "You solved to-do {todo} in list {calendar}",
- "{actor} reopened to-do {todo} in list {calendar}" : "{actor} reopened to-do {todo} in list {calendar}",
- "You reopened to-do {todo} in list {calendar}" : "You reopened to-do {todo} in list {calendar}",
- "{actor} moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}" : "{actor} moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}",
- "You moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}" : "You moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}",
- "Calendar, contacts and tasks" : "Calendar, contacts and tasks",
- "A <strong>calendar</strong> was modified" : "یک تقویم تغییر کرد",
- "A calendar <strong>event</strong> was modified" : "یک رویداد ثبت شده در تقویم تغییر کرد",
- "A calendar <strong>to-do</strong> was modified" : "یک کار ثبت شده در تقویم تغییر کرد",
- "Contact birthdays" : "Contact birthdays",
- "Death of %s" : "Death of %s",
+ "{actor} created to-do {todo} in list {calendar}" : "{actor} کار {todo} را در لیست {calendar} ایجاد کرد",
+ "You created to-do {todo} in list {calendar}" : "شما کار {todo} را در لیست {calendar} ایجاد کردید",
+ "{actor} deleted to-do {todo} from list {calendar}" : "{actor} کار {todo} را از لیست {calendar} حذف کرد",
+ "You deleted to-do {todo} from list {calendar}" : "شما کار {todo} را از لیست {calendar} حذف کردید",
+ "{actor} updated to-do {todo} in list {calendar}" : "{actor} کار {todo} را در لیست {calendar} به‌روزرسانی کرد",
+ "You updated to-do {todo} in list {calendar}" : "شما کار {todo} را در لیست {calendar} به‌روزرسانی کردید",
+ "{actor} solved to-do {todo} in list {calendar}" : "{actor} کار {todo} را در لیست {calendar} حل کرد",
+ "You solved to-do {todo} in list {calendar}" : "شما کار {todo} را در لیست {calendar} حل کردید",
+ "{actor} reopened to-do {todo} in list {calendar}" : "{actor} کار {todo} را در لیست {calendar} بازگشایی کرد",
+ "You reopened to-do {todo} in list {calendar}" : "شما کار {todo} را در لیست {calendar} بازگشایی کردید",
+ "{actor} moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}" : "{actor} کار {todo} را از لیست {sourceCalendar} به لیست {targetCalendar} منتقل کرد",
+ "You moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}" : "شما کار {todo} را از لیست {sourceCalendar} به لیست {targetCalendar} منتقل کردید",
+ "Calendar, contacts and tasks" : "تقویم، مخاطبین و وظایف",
+ "A <strong>calendar</strong> was modified" : "یک <strong>تقویم</strong> تغییر کرد",
+ "A calendar <strong>event</strong> was modified" : "یک <strong>رویداد</strong> تقویم تغییر کرد",
+ "A calendar <strong>to-do</strong> was modified" : "یک <strong>کار</strong> تقویم تغییر کرد",
+ "Contact birthdays" : "تولد مخاطبین",
+ "Death of %s" : "فوت %s",
"Untitled calendar" : "تقویم بدون عنوان",
- "Calendar:" : "Calendar:",
+ "Calendar:" : "تقویم:",
"Date:" : "تاریخ:",
"Where:" : "مکان:",
"Description:" : "توضیحات:",
- "_%n year_::_%n years_" : ["%n year","%n years"],
- "_%n month_::_%n months_" : ["%n month","%n months"],
- "_%n day_::_%n days_" : ["%n day","%n days"],
- "_%n hour_::_%n hours_" : ["%n hour","%n hours"],
- "_%n minute_::_%n minutes_" : ["%n minute","%n minutes"],
- "%s (in %s)" : "%s (in %s)",
- "%s (%s ago)" : "%s (%s ago)",
- "Calendar: %s" : "Calendar: %s",
- "Date: %s" : "Date: %s",
- "Description: %s" : "Description: %s",
- "Where: %s" : "Where: %s",
+ "_%n year_::_%n years_" : ["%n سال","%n سال"],
+ "_%n month_::_%n months_" : ["%n ماه","%n ماه"],
+ "_%n day_::_%n days_" : ["%n روز","%n روز"],
+ "_%n hour_::_%n hours_" : ["%n ساعت","%n ساعت"],
+ "_%n minute_::_%n minutes_" : ["%n دقیقه","%n دقیقه"],
+ "%s (in %s)" : "%s (در %s)",
+ "%s (%s ago)" : "%s (%s پیش)",
+ "Calendar: %s" : "تقویم: %s",
+ "Date: %s" : "تاریخ: %s",
+ "Description: %s" : "توضیحات: %s",
+ "Where: %s" : "مکان: %s",
"%1$s via %2$s" : "%1$s از طریق %2$s",
- "Cancelled: %1$s" : "Cancelled: %1$s",
- "\"%1$s\" has been canceled" : "\"%1$s\" has been canceled",
- "Re: %1$s" : "Re: %1$s",
- "%1$s has accepted your invitation" : "%1$s has accepted your invitation",
- "%1$s has tentatively accepted your invitation" : "%1$s has tentatively accepted your invitation",
- "%1$s has declined your invitation" : "%1$s has declined your invitation",
- "%1$s has responded to your invitation" : "%1$s has responded to your invitation",
- "Invitation updated: %1$s" : "Invitation updated: %1$s",
- "%1$s updated the event \"%2$s\"" : "%1$s updated the event \"%2$s\"",
- "Invitation: %1$s" : "Invitation: %1$s",
- "%1$s would like to invite you to \"%2$s\"" : "%1$s would like to invite you to \"%2$s\"",
- "Organizer:" : "Organizer:",
- "Attendees:" : "Attendees:",
+ "In the past on %1$s for the entire day" : "در گذشته در %1$s برای کل روز",
+ "_In a minute on %1$s for the entire day_::_In %n minutes on %1$s for the entire day_" : ["در یک دقیقه در %1$s برای کل روز","در %n دقیقه در %1$s برای کل روز"],
+ "_In a hour on %1$s for the entire day_::_In %n hours on %1$s for the entire day_" : ["در یک ساعت در %1$s برای کل روز","در %n ساعت در %1$s برای کل روز"],
+ "_In a day on %1$s for the entire day_::_In %n days on %1$s for the entire day_" : ["در یک روز در %1$s برای کل روز","در %n روز در %1$s برای کل روز"],
+ "_In a week on %1$s for the entire day_::_In %n weeks on %1$s for the entire day_" : ["در یک هفته در %1$s برای کل روز","در %n هفته در %1$s برای کل روز"],
+ "_In a month on %1$s for the entire day_::_In %n months on %1$s for the entire day_" : ["در یک ماه در %1$s برای کل روز","در %n ماه در %1$s برای کل روز"],
+ "_In a year on %1$s for the entire day_::_In %n years on %1$s for the entire day_" : ["در یک سال در %1$s برای کل روز","در %n سال در %1$s برای کل روز"],
+ "In the past on %1$s between %2$s - %3$s" : "در گذشته در %1$s بین %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_" : ["در یک دقیقه در %1$s بین %2$s - %3$s","در %n دقیقه در %1$s بین %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_" : ["در یک ساعت در %1$s بین %2$s - %3$s","در %n ساعت در %1$s بین %2$s - %3$s"],
+ "_In a day on %1$s between %2$s - %3$s_::_In %n days on %1$s between %2$s - %3$s_" : ["در یک روز در %1$s بین %2$s - %3$s","در %n روز در %1$s بین %2$s - %3$s"],
+ "_In a week on %1$s between %2$s - %3$s_::_In %n weeks on %1$s between %2$s - %3$s_" : ["در یک هفته در %1$s بین %2$s - %3$s","در %n هفته در %1$s بین %2$s - %3$s"],
+ "_In a month on %1$s between %2$s - %3$s_::_In %n months on %1$s between %2$s - %3$s_" : ["در یک ماه در %1$s بین %2$s - %3$s","در %n ماه در %1$s بین %2$s - %3$s"],
+ "_In a year on %1$s between %2$s - %3$s_::_In %n years on %1$s between %2$s - %3$s_" : ["در یک سال در %1$s بین %2$s - %3$s","در %n سال در %1$s بین %2$s - %3$s"],
+ "Could not generate when statement" : "امکان ایجاد عبارت زمان وجود ندارد",
+ "Every Day for the entire day" : "هر روز برای کل روز",
+ "Every Day for the entire day until %1$s" : "هر روز برای کل روز تا %1$s",
+ "Every Day between %1$s - %2$s" : "هر روز بین %1$s - %2$s",
+ "Every Day between %1$s - %2$s until %3$s" : "هر روز بین %1$s - %2$s تا %3$s",
+ "Every %1$d Days for the entire day" : "هر %1$d روز برای کل روز",
+ "Every %1$d Days for the entire day until %2$s" : "هر %1$d روز برای کل روز تا %2$s",
+ "Every %1$d Days between %2$s - %3$s" : "هر %1$d روز بین %2$s - %3$s",
+ "Every %1$d Days between %2$s - %3$s until %4$s" : "هر %1$d روز بین %2$s - %3$s تا %4$s",
+ "Could not generate event recurrence statement" : "امکان ایجاد عبارت تکرار رویداد وجود ندارد",
+ "Every Week on %1$s for the entire day" : "هر هفته در %1$s برای کل روز",
+ "Every Week on %1$s for the entire day until %2$s" : "هر هفته در %1$s برای کل روز تا %2$s",
+ "Every Week on %1$s between %2$s - %3$s" : "هر هفته در %1$s بین %2$s - %3$s",
+ "Every Week on %1$s between %2$s - %3$s until %4$s" : "هر هفته در %1$s بین %2$s - %3$s تا %4$s",
+ "Every %1$d Weeks on %2$s for the entire day" : "هر %1$d هفته در %2$s برای کل روز",
+ "Every %1$d Weeks on %2$s for the entire day until %3$s" : "هر %1$d هفته در %2$s برای کل روز تا %3$s",
+ "Every %1$d Weeks on %2$s between %3$s - %4$s" : "هر %1$d هفته در %2$s بین %3$s - %4$s",
+ "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "هر %1$d هفته در %2$s بین %3$s - %4$s تا %5$s",
+ "Every Month on the %1$s for the entire day" : "هر ماه در %1$s برای کل روز",
+ "Every Month on the %1$s for the entire day until %2$s" : "هر ماه در %1$s برای کل روز تا %2$s",
+ "Every Month on the %1$s between %2$s - %3$s" : "هر ماه در %1$s بین %2$s - %3$s",
+ "Every Month on the %1$s between %2$s - %3$s until %4$s" : "هر ماه در %1$s بین %2$s - %3$s تا %4$s",
+ "Every %1$d Months on the %2$s for the entire day" : "هر %1$d ماه در %2$s برای کل روز",
+ "Every %1$d Months on the %2$s for the entire day until %3$s" : "هر %1$d ماه در %2$s برای کل روز تا %3$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s" : "هر %1$d ماه در %2$s بین %3$s - %4$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "هر %1$d ماه در %2$s بین %3$s - %4$s تا %5$s",
+ "Every Year in %1$s on the %2$s for the entire day" : "هر سال در %1$s در %2$s برای کل روز",
+ "Every Year in %1$s on the %2$s for the entire day until %3$s" : "هر سال در %1$s در %2$s برای کل روز تا %3$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s" : "هر سال در %1$s در %2$s بین %3$s - %4$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "هر سال در %1$s در %2$s بین %3$s - %4$s تا %5$s",
+ "Every %1$d Years in %2$s on the %3$s for the entire day" : "هر %1$d سال در %2$s در %3$s برای کل روز",
+ "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "هر %1$d سال در %2$s در %3$s برای کل روز تا %4$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "هر %1$d سال در %2$s در %3$s بین %4$s - %5$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "هر %1$d سال در %2$s در %3$s بین %4$s - %5$s تا %6$s",
+ "On specific dates for the entire day until %1$s" : "در تاریخ‌های مشخص برای کل روز تا %1$s",
+ "On specific dates between %1$s - %2$s until %3$s" : "در تاریخ‌های مشخص بین %1$s - %2$s تا %3$s",
+ "In the past on %1$s" : "در گذشته در %1$s",
+ "_In a minute on %1$s_::_In %n minutes on %1$s_" : ["در یک دقیقه در %1$s","در %n دقیقه در %1$s"],
+ "_In a hour on %1$s_::_In %n hours on %1$s_" : ["در یک ساعت در %1$s","در %n ساعت در %1$s"],
+ "_In a day on %1$s_::_In %n days on %1$s_" : ["در یک روز در %1$s","در %n روز در %1$s"],
+ "_In a week on %1$s_::_In %n weeks on %1$s_" : ["در یک هفته در %1$s","در %n هفته در %1$s"],
+ "_In a month on %1$s_::_In %n months on %1$s_" : ["در یک ماه در %1$s","در %n ماه در %1$s"],
+ "_In a year on %1$s_::_In %n years on %1$s_" : ["در یک سال در %1$s","در %n سال در %1$s"],
+ "In the past on %1$s then on %2$s" : "در گذشته در %1$s سپس در %2$s",
+ "_In a minute on %1$s then on %2$s_::_In %n minutes on %1$s then on %2$s_" : ["در یک دقیقه در %1$s سپس در %2$s","در %n دقیقه در %1$s سپس در %2$s"],
+ "_In a hour on %1$s then on %2$s_::_In %n hours on %1$s then on %2$s_" : ["در یک ساعت در %1$s سپس در %2$s","در %n ساعت در %1$s سپس در %2$s"],
+ "_In a day on %1$s then on %2$s_::_In %n days on %1$s then on %2$s_" : ["در یک روز در %1$s سپس در %2$s","در %n روز در %1$s سپس در %2$s"],
+ "_In a week on %1$s then on %2$s_::_In %n weeks on %1$s then on %2$s_" : ["در یک هفته در %1$s سپس در %2$s","در %n هفته در %1$s سپس در %2$s"],
+ "_In a month on %1$s then on %2$s_::_In %n months on %1$s then on %2$s_" : ["در یک ماه در %1$s سپس در %2$s","در %n ماه در %1$s سپس در %2$s"],
+ "_In a year on %1$s then on %2$s_::_In %n years on %1$s then on %2$s_" : ["در یک سال در %1$s سپس در %2$s","در %n سال در %1$s سپس در %2$s"],
+ "In the past on %1$s then on %2$s and %3$s" : "در گذشته در %1$s سپس در %2$s و %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_" : ["در یک دقیقه در %1$s سپس در %2$s و %3$s","در %n دقیقه در %1$s سپس در %2$s و %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_" : ["در یک ساعت در %1$s سپس در %2$s و %3$s","در %n ساعت در %1$s سپس در %2$s و %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_" : ["در یک روز در %1$s سپس در %2$s و %3$s","در %n روز در %1$s سپس در %2$s و %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_" : ["در یک هفته در %1$s سپس در %2$s و %3$s","در %n هفته در %1$s سپس در %2$s و %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_" : ["در یک ماه در %1$s سپس در %2$s و %3$s","در %n ماه در %1$s سپس در %2$s و %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_" : ["در یک سال در %1$s سپس در %2$s و %3$s","در %n سال در %1$s سپس در %2$s و %3$s"],
+ "Could not generate next recurrence statement" : "امکان ایجاد عبارت تکرار بعدی وجود ندارد",
+ "Cancelled: %1$s" : "لغو شد: %1$s",
+ "\"%1$s\" has been canceled" : "\"%1$s\" لغو شده است",
+ "Re: %1$s" : "پاسخ: %1$s",
+ "%1$s has accepted your invitation" : "%1$s دعوت شما را پذیرفته است",
+ "%1$s has tentatively accepted your invitation" : "%1$s دعوت شما را به‌طور آزمایشی پذیرفته است",
+ "%1$s has declined your invitation" : "%1$s دعوت شما را رد کرده است",
+ "%1$s has responded to your invitation" : "%1$s به دعوت شما پاسخ داده است",
+ "Invitation updated: %1$s" : "دعوت به‌روزرسانی شد: %1$s",
+ "%1$s updated the event \"%2$s\"" : "%1$s رویداد \"%2$s\" را به‌روزرسانی کرد",
+ "Invitation: %1$s" : "دعوت: %1$s",
+ "%1$s would like to invite you to \"%2$s\"" : "%1$s مایل است شما را به \"%2$s\" دعوت کند",
+ "Organizer:" : "برگزارکننده:",
+ "Attendees:" : "شرکت‌کنندگان:",
"Title:" : "عنوان:",
+ "When:" : "چه زمانی:",
"Location:" : "مکان:",
- "Link:" : "Link:",
- "Accept" : "قبول",
- "Decline" : "کاهش می یابد",
- "More options …" : "More options …",
- "More options at %s" : "More options at %s",
+ "Link:" : "پیوند:",
+ "Occurring:" : "در حال وقوع:",
+ "Accept" : "پذیرفتن",
+ "Decline" : "رد کردن",
+ "More options …" : "گزینه‌های بیشتر…",
+ "More options at %s" : "گزینه‌های بیشتر در %s",
"Monday" : "دوشنبه",
- "Tuesday" : "سه شنبه",
+ "Tuesday" : "سه‌شنبه",
"Wednesday" : "چهارشنبه",
"Thursday" : "پنجشنبه",
"Friday" : "جمعه",
@@ -103,105 +177,148 @@
"April" : "آوریل",
"May" : "مه",
"June" : "ژوئن",
- "July" : "جولای",
+ "July" : "ژوئیه",
"August" : "اوت",
"September" : "سپتامبر",
"October" : "اکتبر",
"November" : "نوامبر",
"December" : "دسامبر",
- "First" : "First",
- "Last" : "Last",
+ "First" : "اول",
+ "Second" : "دوم",
+ "Third" : "سوم",
+ "Fourth" : "چهارم",
+ "Fifth" : "پنجم",
+ "Last" : "آخر",
+ "Second Last" : "دومی از آخر",
+ "Third Last" : "سومی از آخر",
+ "Fourth Last" : "چهارمی از آخر",
+ "Fifth Last" : "پنجمی از آخر",
"Contacts" : "مخاطبین",
- "{actor} created address book {addressbook}" : "{actor} created address book {addressbook}",
- "You created address book {addressbook}" : "دفترچه آدرس ساخته شد",
- "{actor} deleted address book {addressbook}" : "{actor} deleted address book {addressbook}",
- "You deleted address book {addressbook}" : "You deleted address book {addressbook}",
- "{actor} updated address book {addressbook}" : "{actor} updated address book {addressbook}",
- "You updated address book {addressbook}" : "You updated address book {addressbook}",
- "{actor} shared address book {addressbook} with you" : "{actor} shared address book {addressbook} with you",
- "You shared address book {addressbook} with {user}" : "You shared address book {addressbook} with {user}",
- "{actor} shared address book {addressbook} with {user}" : "{actor} shared address book {addressbook} with {user}",
- "{actor} unshared address book {addressbook} from you" : "{actor} unshared address book {addressbook} from you",
- "You unshared address book {addressbook} from {user}" : "You unshared address book {addressbook} from {user}",
- "{actor} unshared address book {addressbook} from {user}" : "{actor} unshared address book {addressbook} from {user}",
- "{actor} unshared address book {addressbook} from themselves" : "{actor} unshared address book {addressbook} from themselves",
- "You shared address book {addressbook} with group {group}" : "You shared address book {addressbook} with group {group}",
- "{actor} shared address book {addressbook} with group {group}" : "{actor} shared address book {addressbook} with group {group}",
- "You unshared address book {addressbook} from group {group}" : "You unshared address book {addressbook} from group {group}",
- "{actor} unshared address book {addressbook} from group {group}" : "{actor} unshared address book {addressbook} from group {group}",
- "{actor} created contact {card} in address book {addressbook}" : "{actor} created contact {card} in address book {addressbook}",
- "You created contact {card} in address book {addressbook}" : "You created contact {card} in address book {addressbook}",
- "{actor} deleted contact {card} from address book {addressbook}" : "{actor} deleted contact {card} from address book {addressbook}",
- "You deleted contact {card} from address book {addressbook}" : "You deleted contact {card} from address book {addressbook}",
- "{actor} updated contact {card} in address book {addressbook}" : "{actor} updated contact {card} in address book {addressbook}",
- "You updated contact {card} in address book {addressbook}" : "You updated contact {card} in address book {addressbook}",
- "A <strong>contact</strong> or <strong>address book</strong> was modified" : "یک مخاطب یا دفترچه آدرس تغییر کرد",
+ "{actor} created address book {addressbook}" : "{actor} دفترچه آدرس {addressbook} را ایجاد کرد",
+ "You created address book {addressbook}" : "شما دفترچه آدرس {addressbook} را ایجاد کردید",
+ "{actor} deleted address book {addressbook}" : "{actor} دفترچه آدرس {addressbook} را حذف کرد",
+ "You deleted address book {addressbook}" : "شما دفترچه آدرس {addressbook} را حذف کردید",
+ "{actor} updated address book {addressbook}" : "{actor} دفترچه آدرس {addressbook} را به‌روزرسانی کرد",
+ "You updated address book {addressbook}" : "شما دفترچه آدرس {addressbook} را به‌روزرسانی کردید",
+ "{actor} shared address book {addressbook} with you" : "{actor} دفترچه آدرس {addressbook} را با شما به اشتراک گذاشت",
+ "You shared address book {addressbook} with {user}" : "شما دفترچه آدرس {addressbook} را با {user} به اشتراک گذاشتید",
+ "{actor} shared address book {addressbook} with {user}" : "{actor} دفترچه آدرس {addressbook} را با {user} به اشتراک گذاشت",
+ "{actor} unshared address book {addressbook} from you" : "{actor} اشتراک‌گذاری دفترچه آدرس {addressbook} را از شما لغو کرد",
+ "You unshared address book {addressbook} from {user}" : "شما اشتراک‌گذاری دفترچه آدرس {addressbook} را از {user} لغو کردید",
+ "{actor} unshared address book {addressbook} from {user}" : "{actor} اشتراک‌گذاری دفترچه آدرس {addressbook} را از {user} لغو کرد",
+ "{actor} unshared address book {addressbook} from themselves" : "{actor} اشتراک‌گذاری دفترچه آدرس {addressbook} را از خود لغو کرد",
+ "You shared address book {addressbook} with group {group}" : "شما دفترچه آدرس {addressbook} را با گروه {group} به اشتراک گذاشتید",
+ "{actor} shared address book {addressbook} with group {group}" : "{actor} دفترچه آدرس {addressbook} را با گروه {group} به اشتراک گذاشت",
+ "You unshared address book {addressbook} from group {group}" : "شما اشتراک‌گذاری دفترچه آدرس {addressbook} را از گروه {group} لغو کردید",
+ "{actor} unshared address book {addressbook} from group {group}" : "{actor} اشتراک‌گذاری دفترچه آدرس {addressbook} را از گروه {group} لغو کرد",
+ "{actor} created contact {card} in address book {addressbook}" : "{actor} مخاطب {card} را در دفترچه آدرس {addressbook} ایجاد کرد",
+ "You created contact {card} in address book {addressbook}" : "شما مخاطب {card} را در دفترچه آدرس {addressbook} ایجاد کردید",
+ "{actor} deleted contact {card} from address book {addressbook}" : "{actor} مخاطب {card} را از دفترچه آدرس {addressbook} حذف کرد",
+ "You deleted contact {card} from address book {addressbook}" : "شما مخاطب {card} را از دفترچه آدرس {addressbook} حذف کردید",
+ "{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> تغییر کرد",
"Accounts" : "حساب‌ها",
- "File is not updatable: %1$s" : "File is not updatable: %1$s",
- "Could not write to final file, canceled by hook" : "Could not write to final file, canceled by hook",
- "Could not write file contents" : "Could not write file contents",
- "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
- "Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Error while copying file to target location (copied: %1$s, expected filesize: %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." : "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.",
- "Could not rename part file to final file, canceled by hook" : "Could not rename part file to final file, canceled by hook",
- "Could not rename part file to final file" : "Could not rename part file to final file",
- "Failed to check file size: %1$s" : "Failed to check file size: %1$s",
- "Encryption not ready: %1$s" : "Encryption not ready: %1$s",
- "Failed to open file: %1$s" : "Failed to open file: %1$s",
- "Failed to unlink: %1$s" : "Failed to unlink: %1$s",
- "Failed to write file contents: %1$s" : "Failed to write file contents: %1$s",
- "File not found: %1$s" : "File not found: %1$s",
- "System is in maintenance mode." : "System is in maintenance mode.",
- "Upgrade needed" : "Upgrade needed",
- "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS.",
- "Configures a CalDAV account" : "Configures a CalDAV account",
- "Configures a CardDAV account" : "Configures a CardDAV account",
- "Events" : "Events",
+ "System address book which holds all accounts" : "دفترچه آدرس سیستمی که شامل تمام حساب‌ها است",
+ "File is not updatable: %1$s" : "فایل قابل به‌روزرسانی نیست: %1$s",
+ "Failed to get storage for file" : "دریافت فضای ذخیره‌سازی برای فایل با شکست مواجه شد",
+ "Could not write to final file, canceled by hook" : "نوشتن در فایل نهایی امکان‌پذیر نبود، توسط هوک لغو شد",
+ "Could not write file contents" : "امکان نوشتن محتویات فایل وجود ندارد",
+ "_%n byte_::_%n bytes_" : ["%n بایت","%n بایت"],
+ "Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "خطا هنگام کپی فایل به مکان مقصد (کپی شده: %1$s، حجم فایل مورد انتظار: %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$s بود اما %2$s خوانده (از کلاینت Nextcloud) و نوشته (در فضای ذخیره‌سازی Nextcloud) شد. این می‌تواند ناشی از مشکل شبکه در سمت ارسال یا مشکل نوشتن در فضای ذخیره‌سازی در سمت سرور باشد.",
+ "Could not rename part file to final file, canceled by hook" : "امکان تغییر نام فایل جزئی به فایل نهایی وجود نداشت، توسط هوک لغو شد",
+ "Could not rename part file to final file" : "امکان تغییر نام فایل جزئی به فایل نهایی وجود ندارد",
+ "Failed to check file size: %1$s" : "بررسی حجم فایل با شکست مواجه شد: %1$s",
+ "Could not open file: %1$s, file does seem to exist" : "امکان باز کردن فایل وجود ندارد: %1$s، به نظر می‌رسد فایل وجود دارد",
+ "Could not open file: %1$s, file doesn't seem to exist" : "امکان باز کردن فایل وجود ندارد: %1$s، به نظر می‌رسد فایل وجود ندارد",
+ "Encryption not ready: %1$s" : "رمزگذاری آماده نیست: %1$s",
+ "Failed to open file: %1$s" : "باز کردن فایل با شکست مواجه شد: %1$s",
+ "Failed to unlink: %1$s" : "حذف پیوند با شکست مواجه شد: %1$s",
+ "Failed to write file contents: %1$s" : "نوشتن محتویات فایل با شکست مواجه شد: %1$s",
+ "File not found: %1$s" : "فایل یافت نشد: %1$s",
+ "Invalid target path" : "مسیر مقصد نامعتبر است",
+ "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." : "برای استفاده از CalDAV و CardDAV با iOS/macOS، %s شما باید برای استفاده از HTTPS پیکربندی شود.",
+ "Configures a CalDAV account" : "یک حساب CalDAV را پیکربندی می‌کند",
+ "Configures a CardDAV account" : "یک حساب CardDAV را پیکربندی می‌کند",
+ "Events" : "رویدادها",
"Untitled task" : "کار بدون عنوان",
- "Completed on %s" : "Completed on %s",
- "Due on %s by %s" : "Due on %s by %s",
- "Due on %s" : "Due on %s",
- "WebDAV endpoint" : "WebDAV endpoint",
- "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken.",
- "Migrated calendar (%1$s)" : "Migrated calendar (%1$s)",
- "Calendars including events, details and attendees" : "Calendars including events, details and attendees",
- "Contacts and groups" : "Contacts and groups",
- "WebDAV" : "WebDAV",
- "First day" : "First day",
+ "Completed on %s" : "تکمیل شده در %s",
+ "Due on %s by %s" : "موعد در %s توسط %s",
+ "Due on %s" : "موعد در %s",
+ "System Address Book" : "دفترچه آدرس سیستم",
+ "The system address book contains contact information for all users in your instance." : "دفترچه آدرس سیستم شامل اطلاعات تماس برای همه کاربران در نمونه شما است.",
+ "Enable System Address Book" : "فعال کردن دفترچه آدرس سیستم",
+ "DAV system address book" : "دفترچه آدرس سیستم DAV",
+ "No outstanding DAV system address book sync." : "هیچ همگام‌سازی دفترچه آدرس سیستم 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\"." : "همگام‌سازی دفترچه آدرس سیستم DAV هنوز اجرا نشده است زیرا نمونه شما بیش از ۱۰۰۰ کاربر دارد یا خطایی رخ داده است. لطفاً آن را به‌صورت دستی با فراخوانی \"occ dav:sync-system-addressbook\" اجرا کنید.",
+ "WebDAV endpoint" : "نقطه پایانی WebDAV",
+ "Could not check that your web server is properly set up to allow file synchronization over WebDAV. Please check manually." : "امکان بررسی اینکه سرور وب شما به درستی برای همگام‌سازی فایل از طریق WebDAV تنظیم شده است، وجود ندارد. لطفاً به صورت دستی بررسی کنید.",
+ "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." : "سرور وب شما به درستی برای همگام‌سازی فایل از طریق WebDAV تنظیم شده است.",
+ "Migrated calendar (%1$s)" : "تقویم منتقل شده (%1$s)",
+ "Calendars including events, details and attendees" : "تقویم‌ها شامل رویدادها، جزئیات و شرکت‌کنندگان",
+ "Contacts and groups" : "مخاطبین و گروه‌ها",
+ "WebDAV" : "وب‌دَو",
+ "Absence saved" : "غیبت ذخیره شد",
+ "Failed to save your absence settings" : "ذخیره تنظیمات غیبت شما با شکست مواجه شد",
+ "Absence cleared" : "غیبت پاک شد",
+ "Failed to clear your absence settings" : "پاک کردن تنظیمات غیبت شما با شکست مواجه شد",
+ "First day" : "روز اول",
+ "Last day (inclusive)" : "روز آخر (شامل)",
+ "Out of office replacement (optional)" : "جایگزین خارج از دفتر (اختیاری)",
+ "Name of the replacement" : "نام جایگزین",
+ "No results." : "نتیجه‌ای یافت نشد.",
+ "Start typing." : "شروع به تایپ کنید.",
+ "Short absence status" : "وضعیت کوتاه غیبت",
+ "Long absence Message" : "پیام طولانی غیبت",
"Save" : "ذخیره",
- "Failed to load availability" : "Failed to load availability",
- "Saved availability" : "Saved availability",
- "Failed to save availability" : "Failed to save availability",
+ "Disable absence" : "غیرفعال کردن غیبت",
+ "Failed to load availability" : "بارگذاری در دسترس بودن با شکست مواجه شد",
+ "Saved availability" : "در دسترس بودن ذخیره شد",
+ "Failed to save availability" : "ذخیره در دسترس بودن با شکست مواجه شد",
"Time zone:" : "منطقه زمانی:",
- "to" : "به",
- "Delete slot" : "Delete slot",
+ "to" : "تا",
+ "Delete slot" : "حذف بازه زمانی",
"No working hours set" : "ساعات کاری تعیین نشده است",
- "Add slot" : "Add slot",
- "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "وضعیت کاربر بصورت خودکار به \"مزاحم نشوید\" تغییر داده شود تا همه ی اعلان ها خاموش شوند",
- "Availability" : "موجود بودن",
- "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}.",
- "Please make sure to properly set up {emailopen}the email server{linkclose}." : "Please make sure to properly set up {emailopen}the email server{linkclose}.",
- "Calendar server" : "Calendar server",
- "Send invitations to attendees" : "Send invitations to attendees",
- "Automatically generate a birthday calendar" : "Automatically generate a birthday calendar",
- "Birthday calendars will be generated by a background job." : "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." : "Hence they will not be available immediately after enabling but will show up after some time.",
- "Send notifications for events" : "Send notifications for events",
- "Notifications are sent via background jobs, so these must occur often enough." : "Notifications are sent via background jobs, so these must occur often enough.",
- "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 organizers and attendees.",
- "Enable notifications for events via push" : "Enable notifications for events via push",
- "Cancel" : "ردکردن",
+ "Add slot" : "افزودن بازه زمانی",
+ "Weekdays" : "روزهای هفته",
+ "Pick a start time for {dayName}" : "زمان شروع برای {dayName} را انتخاب کنید",
+ "Pick a end time for {dayName}" : "زمان پایان برای {dayName} را انتخاب کنید",
+ "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "وضعیت کاربر بصورت خودکار به \"مزاحم نشوید\" تغییر داده شود تا همه ی اعلان ها خاموش شوند.",
+ "Cancel" : "لغو",
"Import" : "وارد کردن",
- "Error while saving settings" : "Error while saving settings",
- "There was an error updating your attendance status." : "There was an error updating your attendance status.",
- "Please contact the organizer directly." : "Please contact the organizer directly.",
- "Are you accepting the invitation?" : "Are you accepting the invitation?",
+ "Error while saving settings" : "خطا هنگام ذخیره تنظیمات",
+ "Contact reset successfully" : "مخاطب با موفقیت بازنشانی شد",
+ "Error while resetting contact" : "خطا هنگام بازنشانی مخاطب",
+ "Contact imported successfully" : "مخاطب با موفقیت وارد شد",
+ "Error while importing contact" : "خطا هنگام وارد کردن مخاطب",
+ "Import contact" : "وارد کردن مخاطب",
+ "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 جدید، مخاطب پیش‌فرض موجود را حذف کرده و آن را با مخاطب جدید جایگزین می‌کند. آیا می‌خواهید ادامه دهید؟",
+ "Availability" : "در دسترس بودن",
+ "If you configure your working hours, other people will see when you are out of office when they book a meeting." : "اگر ساعات کاری خود را پیکربندی کنید، دیگران هنگام رزرو جلسه متوجه خواهند شد که شما در دفتر نیستید.",
+ "Absence" : "غیبت",
+ "Configure your next absence period." : "دوره غیبت بعدی خود را پیکربندی کنید.",
+ "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" : "ارسال دعوت‌نامه‌ها به شرکت‌کنندگان",
+ "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." : "یادآوری‌ها همیشه برای برگزارکنندگان و شرکت‌کنندگان ارسال می‌شوند.",
+ "Enable notifications for events via push" : "فعال کردن اعلان‌ها برای رویدادها از طریق پوش",
+ "There was an error updating your attendance status." : "خطایی در به‌روزرسانی وضعیت حضور شما رخ داد.",
+ "Please contact the organizer directly." : "لطفاً مستقیماً با برگزارکننده تماس بگیرید.",
+ "Are you accepting the invitation?" : "آیا دعوت را می‌پذیرید؟",
"Tentative" : "آزمایشی",
- "Your attendance was updated successfully." : "Your attendance was updated successfully.",
- "Time:" : "Time:",
- "Could not open file" : "Could not open file",
- "Invalid chunk name" : "Invalid chunk name",
- "Could not rename part file assembled from chunks" : "Could not rename part file assembled from chunks"
+ "Your attendance was updated successfully." : "وضعیت حضور شما با موفقیت به‌روزرسانی شد."
},"pluralForm" :"nplurals=2; plural=(n > 1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/fi.js b/apps/dav/l10n/fi.js
deleted file mode 100644
index b0f93e740c4..00000000000
--- a/apps/dav/l10n/fi.js
+++ /dev/null
@@ -1,165 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Kalenteri",
- "Tasks" : "Tehtävät",
- "Personal" : "Henkilökohtainen",
- "{actor} created calendar {calendar}" : "{actor} loi kalenterin {calendar}",
- "You created calendar {calendar}" : "Loit kalenterin {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} poisti kalenterin {calendar}",
- "You deleted calendar {calendar}" : "Poistit kalenterin {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} päivitti kalenterin {calendar}",
- "You updated calendar {calendar}" : "Päivitit kalenterin {calendar}",
- "{actor} restored calendar {calendar}" : "{actor} palautti kalenterin {calendar}",
- "You restored calendar {calendar}" : "Palautit kalenterin {calendar}",
- "You shared calendar {calendar} as public link" : "Jaoit kalenterin {calendar} julkisena linkkinä",
- "You removed public link for calendar {calendar}" : "Poistit julkisen linkin kalenterilta {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} jakoi kalenterin {calendar} kanssasi",
- "You shared calendar {calendar} with {user}" : "Jaoit kalenterin {calendar} käyttäjälle {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} jakoi kalenterin {calendar} käyttäjälle {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} lopetti kalenterin {calendar} jakamisen kanssasi",
- "You unshared calendar {calendar} from {user}" : "Lopetit kalenterin {calendar} jakamisen käyttäjälle {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} lopetti kalenterin {calendar} jakamisen käyttäjälle {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} lopetti kalenterin {calendar} jakamisen itselleen",
- "You shared calendar {calendar} with group {group}" : "Jaoit kalenterin {calendar} ryhmälle {group}",
- "{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}",
- "You deleted event {event} from calendar {calendar}" : "Poistit tapahtuman {event} kalenterista {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} päivitti tapahtuman {event} kalenteriin {calendar}",
- "You updated event {event} in calendar {calendar}" : "Päivitit tapahtuman {event} kalenteriin {calendar}",
- "You moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "Siirsit tapahtuman {event} kalenterista {sourceCalendar} kalenteriin {targetCalendar}",
- "Busy" : "Varattu",
- "Calendar, contacts and tasks" : "Kalenteri, yhteystiedot ja tehtävät",
- "A <strong>calendar</strong> was modified" : "<strong>Kalenteria</strong> on muokattu",
- "A calendar <strong>event</strong> was modified" : "Kalenterin <strong>tapahtumaa</strong> on muokattu",
- "Contact birthdays" : "Yhteystietojen syntymäpäivät",
- "Death of %s" : "%s kuolema",
- "Untitled calendar" : "Nimetön kalenteri",
- "Calendar:" : "Kalenteri:",
- "Date:" : "Päiväys:",
- "Where:" : "Missä:",
- "Description:" : "Kuvaus:",
- "_%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ää"],
- "_%n hour_::_%n hours_" : ["%n tunti","%n tuntia"],
- "_%n minute_::_%n minutes_" : ["%n minuutti","%n minuuttia"],
- "%s (%s ago)" : "%s (%s sitten)",
- "Calendar: %s" : "Kalenteri: %s",
- "Date: %s" : "Päiväys: %s",
- "Description: %s" : "Kuvaus: %s",
- "Where: %s" : "Missä: %s",
- "%1$s via %2$s" : "%1$s palvelun %2$s kautta",
- "Cancelled: %1$s" : "Peruutettu: %1$s",
- "\"%1$s\" has been canceled" : "\"%1$s\" on peruttu",
- "%1$s has accepted your invitation" : "%1$s on hyväksynyt kutsusi",
- "%1$s has declined your invitation" : "%1$s on kieltäytynyt kutsustasi",
- "%1$s has responded to your invitation" : "%1$s on vastannut kutsuusi",
- "Invitation updated: %1$s" : "Kutsu päivitetty: %1$s",
- "%1$s updated the event \"%2$s\"" : "%1$s päivitti tapahtuman \"%2$s\"",
- "Invitation: %1$s" : "Kutsu: %1$s",
- "Organizer:" : "Järjestäjä:",
- "Attendees:" : "Osallistujat:",
- "Title:" : "Otsikko:",
- "When:" : "Milloin:",
- "Location:" : "Sijainti:",
- "Link:" : "Linkki:",
- "Accept" : "Hyväksy",
- "Decline" : "Kieltäydy",
- "More options …" : "Lisää valintoja…",
- "More options at %s" : "Lisää valintoja kohteessa %s",
- "Monday" : "Maanantai",
- "Tuesday" : "Tiistai",
- "Wednesday" : "Keskiviikko",
- "Thursday" : "Torstai",
- "Friday" : "Perjantai",
- "Saturday" : "Lauantai",
- "Sunday" : "Sunnuntai",
- "January" : "tammikuu",
- "February" : "helmikuu",
- "March" : "maaliskuu",
- "April" : "huhtikuu",
- "May" : "toukokuu",
- "June" : "kesäkuu",
- "July" : "heinäkuu",
- "August" : "elokuu",
- "September" : "syyskuu",
- "October" : "lokakuu",
- "November" : "marraskuu",
- "December" : "joulukuu",
- "First" : "Ensimmäinen",
- "Last" : "Viimeinen",
- "Contacts" : "Yhteystiedot",
- "{actor} created address book {addressbook}" : "{actor} loi osoitekirjan {addressbook}",
- "You created address book {addressbook}" : "Loit osoitekirjan {addressbook}",
- "{actor} deleted address book {addressbook}" : "{actor} poisti osoitekirjan {addressbook}",
- "You deleted address book {addressbook}" : "Sinä poistit osoitekirjan {addressbook}",
- "{actor} updated address book {addressbook}" : "{actor} päivitti osoitekirjaa {addressbook}",
- "You updated address book {addressbook}" : "Sinä päivitit osoitekirjaa {addressbook}",
- "{actor} shared address book {addressbook} with you" : "{actor} jakoi osoitekirjan {addressbook} kanssasi",
- "You shared address book {addressbook} with {user}" : "Jaoit osoitekirjan {addressbook} käyttäjän {user} kanssa",
- "{actor} shared address book {addressbook} with {user}" : "{actor} jakoi osoitekirjan {addressbook} käyttäjän {user} kanssa",
- "{actor} unshared address book {addressbook} from you" : "{actor} lopetti osoitekirjan {addressbook} jakamisen kanssasi",
- "You unshared address book {addressbook} from {user}" : "Lopetit osoitekirjan {addressbook} jakamisen käyttäjän {user} kanssa",
- "{actor} unshared address book {addressbook} from {user}" : "{actor} lopetti osoitekirjan {addressbook} jakamisen käyttäjän {user} kanssa",
- "You shared address book {addressbook} with group {group}" : "Jaoit osoitekirjan {addressbook} ryhmän {group} kanssa",
- "{actor} shared address book {addressbook} with group {group}" : "{actor} jakoi osoitekirjan {addressbook} ryhmän {group} kanssa",
- "You unshared address book {addressbook} from group {group}" : "Lopetit osoitekirjan {addressbook} jakamisen ryhmän {group} kanssa",
- "{actor} unshared address book {addressbook} from group {group}" : "{actor} lopetti osoitekirjan {addressbook} jakamisen ryhmän {group} kanssa",
- "{actor} created contact {card} in address book {addressbook}" : "{actor} loi yhteystiedon {card} osoitekirjaan {addressbook}",
- "You created contact {card} in address book {addressbook}" : "Loit yhteystiedon {card} osoitekirjaan {addressbook}",
- "{actor} deleted contact {card} from address book {addressbook}" : "{actor} poisti yhteystiedon {card} osoitekirjasta {addressbook}",
- "You deleted contact {card} from address book {addressbook}" : "Poistit yhteystiedon {card} osoitekirjasta {addressbook}",
- "{actor} updated contact {card} in address book {addressbook}" : "{actor} päivitti yhteystietoa {card} osoitekirjassa {addressbook}",
- "You updated contact {card} in address book {addressbook}" : "Päivitit yhteystiedon {card} osoitekirjassa {addressbook}",
- "A <strong>contact</strong> or <strong>address book</strong> was modified" : "<strong>Yhteystietoa</strong> tai <strong>osoitekirjaa</strong> muokattiin",
- "Accounts" : "Tilit",
- "File is not updatable: %1$s" : "Tiedosto ei ole päivitettävissä: %1$s",
- "_%n byte_::_%n bytes_" : ["%n tavu","%n tavua"],
- "Failed to check file size: %1$s" : "Tiedoston koon tarkistaminen epäonnistui: %1$s",
- "Encryption not ready: %1$s" : "Salaus ei ole valmis: %1$s",
- "Failed to open file: %1$s" : "Tiedoston avaaminen epäonnistui: %1$s",
- "File not found: %1$s" : "Tiedostoa ei löydy: %1$s",
- "System is in maintenance mode." : "Järjestelmä on huoltotilassa",
- "Upgrade needed" : "Päivitys tarvitaan",
- "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "%s tulee asettaa käyttämään HTTPS-yhteyttä, jotta CalDAVia ja CardDAVia voi käyttää iOSilla tai macOS:llä.",
- "Configures a CalDAV account" : "Määrittää CalDAV-tilin",
- "Configures a CardDAV account" : "Määrittää CardDAV-tilin",
- "Events" : "Tapahtumat",
- "Untitled task" : "Nimetön tehtävä",
- "WebDAV endpoint" : "WebDAV-päätepiste",
- "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Palvelintasi ei ole määritetty oikein tiedostojen synkronointia varten, koska WebDAV-liitäntä vaikuttaa olevan rikki.",
- "Contacts and groups" : "Yhteystiedot ja ryhmät",
- "WebDAV" : "WebDAV",
- "First day" : "Ensimmäinen päivä",
- "Save" : "Tallenna",
- "Failed to load availability" : "Saatavuuden lataaminen epäonnistui",
- "Time zone:" : "Aikavyöhyke:",
- "to" : "Vastaanottaja",
- "Delete slot" : "Poista aikarako",
- "No working hours set" : "Työskentelytunteja ei ole asetettu",
- "Add slot" : "Lisää aikarako",
- "Weekdays" : "Viikonpäivät",
- "Availability" : "Saatavuus",
- "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Asenna myös {calendarappstoreopen}kalenterisovellus{linkclose}, tai {calendardocopen}yhdistä tietokoneesi ja mobiililaitteesi synkronointiyhteyteen ↗{linkclose}.",
- "Please make sure to properly set up {emailopen}the email server{linkclose}." : "Varmista että määrität {emailopen}sähköpostipalvelimen{linkclose} asetukset oikein.",
- "Calendar server" : "Kalenteripalvelin",
- "Send invitations to attendees" : "Lähetä kutsut osallistujille",
- "Automatically generate a birthday calendar" : "Luo syntymäpäiväkalenteri automaattisesti",
- "Birthday calendars will be generated by a background job." : "Syntymäpäiväkalenterit luodaan taustatyön toimesta.",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Sen vuoksi ne eivät ole välittömästi saatavilla käyttöönoton jälkeen, vaan ne tulevat näkyviin pienellä viiveellä.",
- "Send notifications for events" : "Lähetä ilmoitukset tapahtumista",
- "There was an error updating your attendance status." : "Osallistumisesi tilaa päivittäessä tapahtui virhe.",
- "Please contact the organizer directly." : "Ota yhteys suoraan järjestäjään.",
- "Are you accepting the invitation?" : "Hyväksytkö kutsun?",
- "Tentative" : "Alustava",
- "Your attendance was updated successfully." : "Osallistumisesi päivitettiin onnistuneesti.",
- "Time:" : "Aika:",
- "Could not open file" : "Tiedoston avaaminen ei onnistunut"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/fi.json b/apps/dav/l10n/fi.json
deleted file mode 100644
index cabd5d48efb..00000000000
--- a/apps/dav/l10n/fi.json
+++ /dev/null
@@ -1,163 +0,0 @@
-{ "translations": {
- "Calendar" : "Kalenteri",
- "Tasks" : "Tehtävät",
- "Personal" : "Henkilökohtainen",
- "{actor} created calendar {calendar}" : "{actor} loi kalenterin {calendar}",
- "You created calendar {calendar}" : "Loit kalenterin {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} poisti kalenterin {calendar}",
- "You deleted calendar {calendar}" : "Poistit kalenterin {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} päivitti kalenterin {calendar}",
- "You updated calendar {calendar}" : "Päivitit kalenterin {calendar}",
- "{actor} restored calendar {calendar}" : "{actor} palautti kalenterin {calendar}",
- "You restored calendar {calendar}" : "Palautit kalenterin {calendar}",
- "You shared calendar {calendar} as public link" : "Jaoit kalenterin {calendar} julkisena linkkinä",
- "You removed public link for calendar {calendar}" : "Poistit julkisen linkin kalenterilta {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} jakoi kalenterin {calendar} kanssasi",
- "You shared calendar {calendar} with {user}" : "Jaoit kalenterin {calendar} käyttäjälle {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} jakoi kalenterin {calendar} käyttäjälle {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} lopetti kalenterin {calendar} jakamisen kanssasi",
- "You unshared calendar {calendar} from {user}" : "Lopetit kalenterin {calendar} jakamisen käyttäjälle {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} lopetti kalenterin {calendar} jakamisen käyttäjälle {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} lopetti kalenterin {calendar} jakamisen itselleen",
- "You shared calendar {calendar} with group {group}" : "Jaoit kalenterin {calendar} ryhmälle {group}",
- "{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}",
- "You deleted event {event} from calendar {calendar}" : "Poistit tapahtuman {event} kalenterista {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} päivitti tapahtuman {event} kalenteriin {calendar}",
- "You updated event {event} in calendar {calendar}" : "Päivitit tapahtuman {event} kalenteriin {calendar}",
- "You moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "Siirsit tapahtuman {event} kalenterista {sourceCalendar} kalenteriin {targetCalendar}",
- "Busy" : "Varattu",
- "Calendar, contacts and tasks" : "Kalenteri, yhteystiedot ja tehtävät",
- "A <strong>calendar</strong> was modified" : "<strong>Kalenteria</strong> on muokattu",
- "A calendar <strong>event</strong> was modified" : "Kalenterin <strong>tapahtumaa</strong> on muokattu",
- "Contact birthdays" : "Yhteystietojen syntymäpäivät",
- "Death of %s" : "%s kuolema",
- "Untitled calendar" : "Nimetön kalenteri",
- "Calendar:" : "Kalenteri:",
- "Date:" : "Päiväys:",
- "Where:" : "Missä:",
- "Description:" : "Kuvaus:",
- "_%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ää"],
- "_%n hour_::_%n hours_" : ["%n tunti","%n tuntia"],
- "_%n minute_::_%n minutes_" : ["%n minuutti","%n minuuttia"],
- "%s (%s ago)" : "%s (%s sitten)",
- "Calendar: %s" : "Kalenteri: %s",
- "Date: %s" : "Päiväys: %s",
- "Description: %s" : "Kuvaus: %s",
- "Where: %s" : "Missä: %s",
- "%1$s via %2$s" : "%1$s palvelun %2$s kautta",
- "Cancelled: %1$s" : "Peruutettu: %1$s",
- "\"%1$s\" has been canceled" : "\"%1$s\" on peruttu",
- "%1$s has accepted your invitation" : "%1$s on hyväksynyt kutsusi",
- "%1$s has declined your invitation" : "%1$s on kieltäytynyt kutsustasi",
- "%1$s has responded to your invitation" : "%1$s on vastannut kutsuusi",
- "Invitation updated: %1$s" : "Kutsu päivitetty: %1$s",
- "%1$s updated the event \"%2$s\"" : "%1$s päivitti tapahtuman \"%2$s\"",
- "Invitation: %1$s" : "Kutsu: %1$s",
- "Organizer:" : "Järjestäjä:",
- "Attendees:" : "Osallistujat:",
- "Title:" : "Otsikko:",
- "When:" : "Milloin:",
- "Location:" : "Sijainti:",
- "Link:" : "Linkki:",
- "Accept" : "Hyväksy",
- "Decline" : "Kieltäydy",
- "More options …" : "Lisää valintoja…",
- "More options at %s" : "Lisää valintoja kohteessa %s",
- "Monday" : "Maanantai",
- "Tuesday" : "Tiistai",
- "Wednesday" : "Keskiviikko",
- "Thursday" : "Torstai",
- "Friday" : "Perjantai",
- "Saturday" : "Lauantai",
- "Sunday" : "Sunnuntai",
- "January" : "tammikuu",
- "February" : "helmikuu",
- "March" : "maaliskuu",
- "April" : "huhtikuu",
- "May" : "toukokuu",
- "June" : "kesäkuu",
- "July" : "heinäkuu",
- "August" : "elokuu",
- "September" : "syyskuu",
- "October" : "lokakuu",
- "November" : "marraskuu",
- "December" : "joulukuu",
- "First" : "Ensimmäinen",
- "Last" : "Viimeinen",
- "Contacts" : "Yhteystiedot",
- "{actor} created address book {addressbook}" : "{actor} loi osoitekirjan {addressbook}",
- "You created address book {addressbook}" : "Loit osoitekirjan {addressbook}",
- "{actor} deleted address book {addressbook}" : "{actor} poisti osoitekirjan {addressbook}",
- "You deleted address book {addressbook}" : "Sinä poistit osoitekirjan {addressbook}",
- "{actor} updated address book {addressbook}" : "{actor} päivitti osoitekirjaa {addressbook}",
- "You updated address book {addressbook}" : "Sinä päivitit osoitekirjaa {addressbook}",
- "{actor} shared address book {addressbook} with you" : "{actor} jakoi osoitekirjan {addressbook} kanssasi",
- "You shared address book {addressbook} with {user}" : "Jaoit osoitekirjan {addressbook} käyttäjän {user} kanssa",
- "{actor} shared address book {addressbook} with {user}" : "{actor} jakoi osoitekirjan {addressbook} käyttäjän {user} kanssa",
- "{actor} unshared address book {addressbook} from you" : "{actor} lopetti osoitekirjan {addressbook} jakamisen kanssasi",
- "You unshared address book {addressbook} from {user}" : "Lopetit osoitekirjan {addressbook} jakamisen käyttäjän {user} kanssa",
- "{actor} unshared address book {addressbook} from {user}" : "{actor} lopetti osoitekirjan {addressbook} jakamisen käyttäjän {user} kanssa",
- "You shared address book {addressbook} with group {group}" : "Jaoit osoitekirjan {addressbook} ryhmän {group} kanssa",
- "{actor} shared address book {addressbook} with group {group}" : "{actor} jakoi osoitekirjan {addressbook} ryhmän {group} kanssa",
- "You unshared address book {addressbook} from group {group}" : "Lopetit osoitekirjan {addressbook} jakamisen ryhmän {group} kanssa",
- "{actor} unshared address book {addressbook} from group {group}" : "{actor} lopetti osoitekirjan {addressbook} jakamisen ryhmän {group} kanssa",
- "{actor} created contact {card} in address book {addressbook}" : "{actor} loi yhteystiedon {card} osoitekirjaan {addressbook}",
- "You created contact {card} in address book {addressbook}" : "Loit yhteystiedon {card} osoitekirjaan {addressbook}",
- "{actor} deleted contact {card} from address book {addressbook}" : "{actor} poisti yhteystiedon {card} osoitekirjasta {addressbook}",
- "You deleted contact {card} from address book {addressbook}" : "Poistit yhteystiedon {card} osoitekirjasta {addressbook}",
- "{actor} updated contact {card} in address book {addressbook}" : "{actor} päivitti yhteystietoa {card} osoitekirjassa {addressbook}",
- "You updated contact {card} in address book {addressbook}" : "Päivitit yhteystiedon {card} osoitekirjassa {addressbook}",
- "A <strong>contact</strong> or <strong>address book</strong> was modified" : "<strong>Yhteystietoa</strong> tai <strong>osoitekirjaa</strong> muokattiin",
- "Accounts" : "Tilit",
- "File is not updatable: %1$s" : "Tiedosto ei ole päivitettävissä: %1$s",
- "_%n byte_::_%n bytes_" : ["%n tavu","%n tavua"],
- "Failed to check file size: %1$s" : "Tiedoston koon tarkistaminen epäonnistui: %1$s",
- "Encryption not ready: %1$s" : "Salaus ei ole valmis: %1$s",
- "Failed to open file: %1$s" : "Tiedoston avaaminen epäonnistui: %1$s",
- "File not found: %1$s" : "Tiedostoa ei löydy: %1$s",
- "System is in maintenance mode." : "Järjestelmä on huoltotilassa",
- "Upgrade needed" : "Päivitys tarvitaan",
- "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "%s tulee asettaa käyttämään HTTPS-yhteyttä, jotta CalDAVia ja CardDAVia voi käyttää iOSilla tai macOS:llä.",
- "Configures a CalDAV account" : "Määrittää CalDAV-tilin",
- "Configures a CardDAV account" : "Määrittää CardDAV-tilin",
- "Events" : "Tapahtumat",
- "Untitled task" : "Nimetön tehtävä",
- "WebDAV endpoint" : "WebDAV-päätepiste",
- "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Palvelintasi ei ole määritetty oikein tiedostojen synkronointia varten, koska WebDAV-liitäntä vaikuttaa olevan rikki.",
- "Contacts and groups" : "Yhteystiedot ja ryhmät",
- "WebDAV" : "WebDAV",
- "First day" : "Ensimmäinen päivä",
- "Save" : "Tallenna",
- "Failed to load availability" : "Saatavuuden lataaminen epäonnistui",
- "Time zone:" : "Aikavyöhyke:",
- "to" : "Vastaanottaja",
- "Delete slot" : "Poista aikarako",
- "No working hours set" : "Työskentelytunteja ei ole asetettu",
- "Add slot" : "Lisää aikarako",
- "Weekdays" : "Viikonpäivät",
- "Availability" : "Saatavuus",
- "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Asenna myös {calendarappstoreopen}kalenterisovellus{linkclose}, tai {calendardocopen}yhdistä tietokoneesi ja mobiililaitteesi synkronointiyhteyteen ↗{linkclose}.",
- "Please make sure to properly set up {emailopen}the email server{linkclose}." : "Varmista että määrität {emailopen}sähköpostipalvelimen{linkclose} asetukset oikein.",
- "Calendar server" : "Kalenteripalvelin",
- "Send invitations to attendees" : "Lähetä kutsut osallistujille",
- "Automatically generate a birthday calendar" : "Luo syntymäpäiväkalenteri automaattisesti",
- "Birthday calendars will be generated by a background job." : "Syntymäpäiväkalenterit luodaan taustatyön toimesta.",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Sen vuoksi ne eivät ole välittömästi saatavilla käyttöönoton jälkeen, vaan ne tulevat näkyviin pienellä viiveellä.",
- "Send notifications for events" : "Lähetä ilmoitukset tapahtumista",
- "There was an error updating your attendance status." : "Osallistumisesi tilaa päivittäessä tapahtui virhe.",
- "Please contact the organizer directly." : "Ota yhteys suoraan järjestäjään.",
- "Are you accepting the invitation?" : "Hyväksytkö kutsun?",
- "Tentative" : "Alustava",
- "Your attendance was updated successfully." : "Osallistumisesi päivitettiin onnistuneesti.",
- "Time:" : "Aika:",
- "Could not open file" : "Tiedoston avaaminen ei onnistunut"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/fr.js b/apps/dav/l10n/fr.js
index 736d0c450c2..9a2980ff4de 100644
--- a/apps/dav/l10n/fr.js
+++ b/apps/dav/l10n/fr.js
@@ -72,10 +72,20 @@ OC.L10N.register(
"Description: %s" : "Description : %s",
"Where: %s" : "Où : %s",
"%1$s via %2$s" : "%1$s via %2$s",
+ "In the past on %1$s for the entire day" : "Dans le passé toute la journée du %1$s ",
"_In a minute on %1$s for the entire day_::_In %n minutes on %1$s for the entire day_" : ["Dans une minute le %1$s pour la journée entière","Dans %n minutes le %1$s pour la journée entière","Dans %n minutes le %1$s pour la journée entière"],
"_In a hour on %1$s for the entire day_::_In %n hours on %1$s for the entire day_" : ["Dans une heure le %1$s pour la journée entière","Dans %n heures le %1$s pour la journée entière","Dans %n heures le %1$s pour la journée entière"],
"_In a day on %1$s for the entire day_::_In %n days on %1$s for the entire day_" : ["Dans un jour le %1$s pour la journée entière","Dans %n jours le %1$s pour la journée entière","Dans %n jours le %1$s pour la journée entière"],
"_In a week on %1$s for the entire day_::_In %n weeks on %1$s for the entire day_" : ["Dans une semaine le %1$s pour la journée entière","Dans %n semaines le %1$s pour la journée entière","Dans %n semaines le %1$s pour la journée entière"],
+ "_In a month on %1$s for the entire day_::_In %n months on %1$s for the entire day_" : ["Dans un mois toute la journée du %1$s","Dans %n mois toute la journée du %1$s","Dans %n mois toute la journée du %1$s"],
+ "_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",
@@ -112,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)",
@@ -159,11 +190,11 @@ OC.L10N.register(
"Third" : "Troisième",
"Fourth" : "Quatrième",
"Fifth" : "Cinquième",
- "Last" : "Dernière",
- "Second Last" : "Avant dernier",
- "Third Last" : "Antépénultième",
- "Fourth Last" : "Pré-antépénultième",
- "Fifth Last" : "Cinq Derniers",
+ "Last" : "Dernièr",
+ "Second Last" : "Avant-dernier",
+ "Third Last" : "Troisième dernier",
+ "Fourth Last" : "Quatrième dernier",
+ "Fifth Last" : "Cinquième dernier",
"Contacts" : "Contacts",
"{actor} created address book {addressbook}" : "{actor} a créé le carnet d'adresses {addressbook}",
"You created address book {addressbook}" : "Vous avez créé le carnet d'adresses {addressbook}",
@@ -219,6 +250,10 @@ OC.L10N.register(
"Completed on %s" : "Terminé le %s",
"Due on %s by %s" : "Echéance le %s pour %s",
"Due on %s" : "Echéance le %s",
+ "Example event - open me!" : "Exemple d'événement - ouvrez-moi !",
+ "System Address Book" : "Carnet d'adresses du système",
+ "The system address book contains contact information for all users in your instance." : "Le carnet d'adresses du système contient les informations de contact de tous les utilisateurs de votre instance.",
+ "Enable System Address Book" : "Activer le carnet d'adresses du système",
"DAV system address book" : "Carnet d'adresses système DAV",
"No outstanding DAV system address book sync." : "Pas de synchronisation DAV en cours du carnet d'adresses système.",
"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\"." : "La synchronisation du carnet d'adresses système DAV n'a pas encore été effectuée car votre instance a plus de 1 000 utilisateurs ou parce qu'une erreur est survenue. Merci de l'exécuter manuellement en tapant la commande \"occ dav:sync-system-addressbook\".",
@@ -256,6 +291,25 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Choisissez une heure de début pour {dayName}",
"Pick a end time for {dayName}" : "Choisissez une heure de fin pour {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Définir automatiquement le statut « Ne pas déranger » en dehors des heures de disponibilités pour désactiver toutes les notifications.",
+ "Cancel" : "Annuler",
+ "Import" : "Importation",
+ "Error while saving settings" : "Erreur lors de l'enregistrement des paramètres",
+ "Contact reset successfully" : "Contact réinitialisé avec succès",
+ "Error while resetting contact" : "Erreur lors de la remise à zéro du contact",
+ "Contact imported successfully" : "Contact importé avec succès",
+ "Error while importing contact" : "Erreur lors de l'importation du contact",
+ "Import contact" : "Importer un contact",
+ "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",
@@ -272,24 +326,12 @@ 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",
- "Cancel" : "Annuler",
- "Import" : "Importation",
- "Error while saving settings" : "Erreur lors de l'enregistrement des paramètres",
- "Contact reset successfully" : "Contact réinitialisé avec succès",
- "Error while resetting contact" : "Erreur lors de la remise à zéro du contact",
- "Contact imported successfully" : "Contact importé avec succès",
- "Error while importing contact" : "Erreur lors de l'importation du contact",
- "Import contact" : "Importer un contact",
- "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 ?",
+ "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 ?",
"Tentative" : "Tentative",
- "Your attendance was updated successfully." : "Votre présence a été mise à jour avec succès.",
- "Time:" : "Heure :",
- "Could not open file" : "Impossible d'ouvrir le fichier",
- "Invalid chunk name" : "Nom de morceau invalide",
- "Could not rename part file assembled from chunks" : "Impossible de renommer le fichier partiel à partir des morceaux"
+ "Your attendance was updated successfully." : "Votre présence a été mise à jour avec succès."
},
"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 8f64a867349..bdedf869268 100644
--- a/apps/dav/l10n/fr.json
+++ b/apps/dav/l10n/fr.json
@@ -70,10 +70,20 @@
"Description: %s" : "Description : %s",
"Where: %s" : "Où : %s",
"%1$s via %2$s" : "%1$s via %2$s",
+ "In the past on %1$s for the entire day" : "Dans le passé toute la journée du %1$s ",
"_In a minute on %1$s for the entire day_::_In %n minutes on %1$s for the entire day_" : ["Dans une minute le %1$s pour la journée entière","Dans %n minutes le %1$s pour la journée entière","Dans %n minutes le %1$s pour la journée entière"],
"_In a hour on %1$s for the entire day_::_In %n hours on %1$s for the entire day_" : ["Dans une heure le %1$s pour la journée entière","Dans %n heures le %1$s pour la journée entière","Dans %n heures le %1$s pour la journée entière"],
"_In a day on %1$s for the entire day_::_In %n days on %1$s for the entire day_" : ["Dans un jour le %1$s pour la journée entière","Dans %n jours le %1$s pour la journée entière","Dans %n jours le %1$s pour la journée entière"],
"_In a week on %1$s for the entire day_::_In %n weeks on %1$s for the entire day_" : ["Dans une semaine le %1$s pour la journée entière","Dans %n semaines le %1$s pour la journée entière","Dans %n semaines le %1$s pour la journée entière"],
+ "_In a month on %1$s for the entire day_::_In %n months on %1$s for the entire day_" : ["Dans un mois toute la journée du %1$s","Dans %n mois toute la journée du %1$s","Dans %n mois toute la journée du %1$s"],
+ "_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",
@@ -110,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)",
@@ -157,11 +188,11 @@
"Third" : "Troisième",
"Fourth" : "Quatrième",
"Fifth" : "Cinquième",
- "Last" : "Dernière",
- "Second Last" : "Avant dernier",
- "Third Last" : "Antépénultième",
- "Fourth Last" : "Pré-antépénultième",
- "Fifth Last" : "Cinq Derniers",
+ "Last" : "Dernièr",
+ "Second Last" : "Avant-dernier",
+ "Third Last" : "Troisième dernier",
+ "Fourth Last" : "Quatrième dernier",
+ "Fifth Last" : "Cinquième dernier",
"Contacts" : "Contacts",
"{actor} created address book {addressbook}" : "{actor} a créé le carnet d'adresses {addressbook}",
"You created address book {addressbook}" : "Vous avez créé le carnet d'adresses {addressbook}",
@@ -217,6 +248,10 @@
"Completed on %s" : "Terminé le %s",
"Due on %s by %s" : "Echéance le %s pour %s",
"Due on %s" : "Echéance le %s",
+ "Example event - open me!" : "Exemple d'événement - ouvrez-moi !",
+ "System Address Book" : "Carnet d'adresses du système",
+ "The system address book contains contact information for all users in your instance." : "Le carnet d'adresses du système contient les informations de contact de tous les utilisateurs de votre instance.",
+ "Enable System Address Book" : "Activer le carnet d'adresses du système",
"DAV system address book" : "Carnet d'adresses système DAV",
"No outstanding DAV system address book sync." : "Pas de synchronisation DAV en cours du carnet d'adresses système.",
"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\"." : "La synchronisation du carnet d'adresses système DAV n'a pas encore été effectuée car votre instance a plus de 1 000 utilisateurs ou parce qu'une erreur est survenue. Merci de l'exécuter manuellement en tapant la commande \"occ dav:sync-system-addressbook\".",
@@ -254,6 +289,25 @@
"Pick a start time for {dayName}" : "Choisissez une heure de début pour {dayName}",
"Pick a end time for {dayName}" : "Choisissez une heure de fin pour {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Définir automatiquement le statut « Ne pas déranger » en dehors des heures de disponibilités pour désactiver toutes les notifications.",
+ "Cancel" : "Annuler",
+ "Import" : "Importation",
+ "Error while saving settings" : "Erreur lors de l'enregistrement des paramètres",
+ "Contact reset successfully" : "Contact réinitialisé avec succès",
+ "Error while resetting contact" : "Erreur lors de la remise à zéro du contact",
+ "Contact imported successfully" : "Contact importé avec succès",
+ "Error while importing contact" : "Erreur lors de l'importation du contact",
+ "Import contact" : "Importer un contact",
+ "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",
@@ -270,24 +324,12 @@
"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",
- "Cancel" : "Annuler",
- "Import" : "Importation",
- "Error while saving settings" : "Erreur lors de l'enregistrement des paramètres",
- "Contact reset successfully" : "Contact réinitialisé avec succès",
- "Error while resetting contact" : "Erreur lors de la remise à zéro du contact",
- "Contact imported successfully" : "Contact importé avec succès",
- "Error while importing contact" : "Erreur lors de l'importation du contact",
- "Import contact" : "Importer un contact",
- "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 ?",
+ "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 ?",
"Tentative" : "Tentative",
- "Your attendance was updated successfully." : "Votre présence a été mise à jour avec succès.",
- "Time:" : "Heure :",
- "Could not open file" : "Impossible d'ouvrir le fichier",
- "Invalid chunk name" : "Nom de morceau invalide",
- "Could not rename part file assembled from chunks" : "Impossible de renommer le fichier partiel à partir des morceaux"
+ "Your attendance was updated successfully." : "Votre présence a été mise à jour avec succès."
},"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/ga.js b/apps/dav/l10n/ga.js
index 1d3d0d75c89..fe197df1bd8 100644
--- a/apps/dav/l10n/ga.js
+++ b/apps/dav/l10n/ga.js
@@ -290,6 +290,25 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Roghnaigh am tosaithe le haghaidh {dayName}",
"Pick a end time for {dayName}" : "Roghnaigh am críochnaithe le haghaidh {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Socraigh stádas úsáideora go huathoibríoch mar \"Ná cuir isteach\" taobh amuigh den infhaighteacht chun gach fógra a bhalbhú.",
+ "Cancel" : "Cealaigh",
+ "Import" : "Iompórtáil",
+ "Error while saving settings" : "Earráid agus na socruithe á sábháil",
+ "Contact reset successfully" : "D'éirigh le hathshocrú teagmhála",
+ "Error while resetting contact" : "Earráid agus an teagmhálaí á athshocrú",
+ "Contact imported successfully" : "D'éirigh le hiompórtáil an teagmhálaí",
+ "Error while importing contact" : "Earráid agus an teagmhálaí á iompórtáil",
+ "Import contact" : "Iompórtáil teagmhála",
+ "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",
@@ -306,27 +325,12 @@ 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ú",
- "Cancel" : "Cealaigh",
- "Import" : "Iompórtáil",
- "Error while saving settings" : "Earráid agus na socruithe á sábháil",
- "Contact reset successfully" : "D'éirigh le hathshocrú teagmhála",
- "Error while resetting contact" : "Earráid agus an teagmhálaí á athshocrú",
- "Contact imported successfully" : "D'éirigh le hiompórtáil an teagmhálaí",
- "Error while importing contact" : "Earráid agus an teagmhálaí á iompórtáil",
- "Example Content" : "Ábhar Samplach",
- "Set example content to be created on new user first login." : "Socraigh ábhar samplach le cruthú ar an gcéad logáil isteach úsáideora nua.",
- "Import contact" : "Iompórtáil teagmhála",
- "Reset to default contact" : "Athshocraigh go teagmhálaí réamhshocraithe",
- "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?",
+ "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?",
"Tentative" : "Sealadach",
- "Your attendance was updated successfully." : "D'éirigh le do thinreamh a nuashonrú.",
- "Time:" : "Am:",
- "Could not open file" : "Níorbh fhéidir an comhad a oscailt",
- "Invalid chunk name" : "Ainm smután neamhbhailí",
- "Could not rename part file assembled from chunks" : "Níorbh fhéidir páirtchomhad a athainmniú as smután"
+ "Your attendance was updated successfully." : "D'éirigh le do thinreamh a nuashonrú."
},
"nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4);");
diff --git a/apps/dav/l10n/ga.json b/apps/dav/l10n/ga.json
index 0012739b177..cde6b45cf5f 100644
--- a/apps/dav/l10n/ga.json
+++ b/apps/dav/l10n/ga.json
@@ -288,6 +288,25 @@
"Pick a start time for {dayName}" : "Roghnaigh am tosaithe le haghaidh {dayName}",
"Pick a end time for {dayName}" : "Roghnaigh am críochnaithe le haghaidh {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Socraigh stádas úsáideora go huathoibríoch mar \"Ná cuir isteach\" taobh amuigh den infhaighteacht chun gach fógra a bhalbhú.",
+ "Cancel" : "Cealaigh",
+ "Import" : "Iompórtáil",
+ "Error while saving settings" : "Earráid agus na socruithe á sábháil",
+ "Contact reset successfully" : "D'éirigh le hathshocrú teagmhála",
+ "Error while resetting contact" : "Earráid agus an teagmhálaí á athshocrú",
+ "Contact imported successfully" : "D'éirigh le hiompórtáil an teagmhálaí",
+ "Error while importing contact" : "Earráid agus an teagmhálaí á iompórtáil",
+ "Import contact" : "Iompórtáil teagmhála",
+ "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",
@@ -304,27 +323,12 @@
"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ú",
- "Cancel" : "Cealaigh",
- "Import" : "Iompórtáil",
- "Error while saving settings" : "Earráid agus na socruithe á sábháil",
- "Contact reset successfully" : "D'éirigh le hathshocrú teagmhála",
- "Error while resetting contact" : "Earráid agus an teagmhálaí á athshocrú",
- "Contact imported successfully" : "D'éirigh le hiompórtáil an teagmhálaí",
- "Error while importing contact" : "Earráid agus an teagmhálaí á iompórtáil",
- "Example Content" : "Ábhar Samplach",
- "Set example content to be created on new user first login." : "Socraigh ábhar samplach le cruthú ar an gcéad logáil isteach úsáideora nua.",
- "Import contact" : "Iompórtáil teagmhála",
- "Reset to default contact" : "Athshocraigh go teagmhálaí réamhshocraithe",
- "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?",
+ "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?",
"Tentative" : "Sealadach",
- "Your attendance was updated successfully." : "D'éirigh le do thinreamh a nuashonrú.",
- "Time:" : "Am:",
- "Could not open file" : "Níorbh fhéidir an comhad a oscailt",
- "Invalid chunk name" : "Ainm smután neamhbhailí",
- "Could not rename part file assembled from chunks" : "Níorbh fhéidir páirtchomhad a athainmniú as smután"
+ "Your attendance was updated successfully." : "D'éirigh le do thinreamh a nuashonrú."
},"pluralForm" :"nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/gl.js b/apps/dav/l10n/gl.js
index b1fa7954ad1..2dcf4a4d100 100644
--- a/apps/dav/l10n/gl.js
+++ b/apps/dav/l10n/gl.js
@@ -287,6 +287,10 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Escolla unha hora de inicio para {dayName}",
"Pick a end time for {dayName}" : "Escolla unha hora de finalización para {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Definir automaticamente o estado do usuario en «Non molestar» fóra de dispoñibilidade para enmudecer todas as notificacións.",
+ "Cancel" : "Cancelar",
+ "Import" : "Importar",
+ "Error while saving settings" : "Produciuse un erro ao gardar os axustes",
+ "Reset to default" : "Restabelecer os valores predeterminados",
"Availability" : "Dispoñibilidade",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Se configura o seu horario de traballo, outras persoas verán cando está fóra da oficina cando reserven unha xuntanza.",
"Absence" : "Ausencia",
@@ -303,17 +307,10 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Enviar notificacións de lembrete tamén aos que comparten calendario",
"Reminders are always sent to organizers and attendees." : "Os lembretes envíanselle sempre aos organizadores e aos asistentes.",
"Enable notifications for events via push" : "Activar o envío de notificacións emerxentes para eventos",
- "Cancel" : "Cancelar",
- "Import" : "Importar",
- "Error while saving settings" : "Produciuse un erro ao gardar os axustes",
"There was an error updating your attendance status." : "Produciuse un erro ao actualizar o seu estado de asistencia.",
"Please contact the organizer directly." : "Contacte directamente co organizador.",
"Are you accepting the invitation?" : "Acepta Vde. o convite?",
"Tentative" : "Provisional",
- "Your attendance was updated successfully." : "A súa asistencia foi actualizada satisfactoriamente.",
- "Time:" : "Hora:",
- "Could not open file" : "Non foi posíbel abrir o ficheiro",
- "Invalid chunk name" : "O nome do fragmento non é válido",
- "Could not rename part file assembled from chunks" : "Non foi posíbel cambiar o nome do ficheiro de pezas ensamblados a partir de fragmentos"
+ "Your attendance was updated successfully." : "A súa asistencia foi actualizada satisfactoriamente."
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/gl.json b/apps/dav/l10n/gl.json
index 75453854e87..777fd270c00 100644
--- a/apps/dav/l10n/gl.json
+++ b/apps/dav/l10n/gl.json
@@ -285,6 +285,10 @@
"Pick a start time for {dayName}" : "Escolla unha hora de inicio para {dayName}",
"Pick a end time for {dayName}" : "Escolla unha hora de finalización para {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Definir automaticamente o estado do usuario en «Non molestar» fóra de dispoñibilidade para enmudecer todas as notificacións.",
+ "Cancel" : "Cancelar",
+ "Import" : "Importar",
+ "Error while saving settings" : "Produciuse un erro ao gardar os axustes",
+ "Reset to default" : "Restabelecer os valores predeterminados",
"Availability" : "Dispoñibilidade",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Se configura o seu horario de traballo, outras persoas verán cando está fóra da oficina cando reserven unha xuntanza.",
"Absence" : "Ausencia",
@@ -301,17 +305,10 @@
"Send reminder notifications to calendar sharees as well" : "Enviar notificacións de lembrete tamén aos que comparten calendario",
"Reminders are always sent to organizers and attendees." : "Os lembretes envíanselle sempre aos organizadores e aos asistentes.",
"Enable notifications for events via push" : "Activar o envío de notificacións emerxentes para eventos",
- "Cancel" : "Cancelar",
- "Import" : "Importar",
- "Error while saving settings" : "Produciuse un erro ao gardar os axustes",
"There was an error updating your attendance status." : "Produciuse un erro ao actualizar o seu estado de asistencia.",
"Please contact the organizer directly." : "Contacte directamente co organizador.",
"Are you accepting the invitation?" : "Acepta Vde. o convite?",
"Tentative" : "Provisional",
- "Your attendance was updated successfully." : "A súa asistencia foi actualizada satisfactoriamente.",
- "Time:" : "Hora:",
- "Could not open file" : "Non foi posíbel abrir o ficheiro",
- "Invalid chunk name" : "O nome do fragmento non é válido",
- "Could not rename part file assembled from chunks" : "Non foi posíbel cambiar o nome do ficheiro de pezas ensamblados a partir de fragmentos"
+ "Your attendance was updated successfully." : "A súa asistencia foi actualizada satisfactoriamente."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/he.js b/apps/dav/l10n/he.js
deleted file mode 100644
index 20316f2dc51..00000000000
--- a/apps/dav/l10n/he.js
+++ /dev/null
@@ -1,101 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "יומן",
- "Personal" : "אישי",
- "{actor} created calendar {calendar}" : "היומן {calendar} נוצר על ידי {actor}",
- "You created calendar {calendar}" : "מחקת את היומן {calendar}",
- "{actor} deleted calendar {calendar}" : "היומן {calendar} נמחק על ידי {actor}",
- "You deleted calendar {calendar}" : "מחקת את היומן {calendar}",
- "{actor} updated calendar {calendar}" : "היומן {calendar} עודכן על ידי {actor}",
- "You updated calendar {calendar}" : "עדכנת את היומן {calendar}",
- "You shared calendar {calendar} as public link" : "שיתפת את היומן {calendar} כקישור ציבורי",
- "You removed public link for calendar {calendar}" : "הסרת את הקישור הציבורי ליומן {calendar}",
- "{actor} shared calendar {calendar} with you" : "שותף אתך לוח השנה {calendar} על ידי {actor}",
- "You shared calendar {calendar} with {user}" : "שיתפת לוח שנה {calendar} עם {user}",
- "{actor} shared calendar {calendar} with {user}" : "לוח השנה {calendar} שותף על ידי {actor} עם {user}",
- "{actor} unshared calendar {calendar} from you" : "השיתוף של לוח השנה {calendar} אתך הופסק על ידי {actor}",
- "You unshared calendar {calendar} from {user}" : "ביטלת את שיתוף לוח השנה {calendar} עם {user}",
- "{actor} unshared calendar {calendar} from {user}" : "השיתוף של לוח השנה {calendar} עם {user} הופסק על ידי {actor}",
- "{actor} unshared calendar {calendar} from themselves" : "השיתוף של לוח השנה {calendar} עם עצמם הופסק על ידי {actor}",
- "You shared calendar {calendar} with group {group}" : "שיתפת את לוח השנה {calendar} עם הקבוצה {group}",
- "{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}",
- "You deleted event {event} from calendar {calendar}" : "מחקת אירוע {event} מלוח השנה {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "האירוע {event} עודכן בלוח השנה {calendar} על ידי {actor}",
- "You updated event {event} in calendar {calendar}" : "עדכנת את האירוע {event} בלוח השנה {calendar}",
- "Busy" : "עסוק",
- "A <strong>calendar</strong> was modified" : " <strong>יומן</strong> נערך",
- "A calendar <strong>event</strong> was modified" : "<strong>אירוע</strong> ביומן נערך",
- "Contact birthdays" : "ימי הולדת של אנשי קשר",
- "Death of %s" : "הפטירה של %s",
- "Untitled calendar" : "לוח שנה ללא כותרת",
- "Calendar:" : "לוח שנה:",
- "Date:" : "תאריך:",
- "Where:" : "איפה:",
- "Description:" : "תיאור:",
- "_%n year_::_%n years_" : ["שנה","שנתיים","%n שנים","%n שנים"],
- "_%n month_::_%n months_" : ["חודש","חודשיים","%n חודשים","%n חודשים"],
- "_%n day_::_%n days_" : ["יום","יומיים","%n ימים","%n ימים"],
- "_%n hour_::_%n hours_" : ["שעה","שעתיים","%n שעות","%n שעות"],
- "_%n minute_::_%n minutes_" : ["דקה","%n דקות","%n דקות","%n דקות"],
- "%s (in %s)" : "%s (בתוך %s)",
- "%s (%s ago)" : "%s (לפני %s)",
- "Calendar: %s" : "לוח שנה: %s",
- "Date: %s" : "תאריך: %s",
- "Description: %s" : "תיאור: %s",
- "Where: %s" : "איפה: %s",
- "%1$s via %2$s" : "%1$s דרך %2$s",
- "Organizer:" : "ארגון:",
- "Attendees:" : "משתתפים:",
- "Title:" : "כותרת:",
- "Time:" : "שעה:",
- "Location:" : "מיקום:",
- "Link:" : "קישור:",
- "Accept" : "קבלה",
- "Decline" : "דחייה",
- "More options …" : "אפשרויות נוספות…",
- "More options at %s" : "אפשרויות נוספים ב־%s",
- "Contacts" : "אנשי קשר",
- "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.",
- "Configures a CalDAV account" : "מגדיר חשבון CalDAV",
- "Configures a CardDAV account" : "מגדיר חשבון CardDAV",
- "Events" : "אירועים",
- "Tasks" : "משימות",
- "Untitled task" : "משימה ללא כותרת",
- "Completed on %s" : "הושלמה ב־%s",
- "Contacts and groups" : "אנשי קשר וקבוצות",
- "WebDAV" : "WebDAV",
- "WebDAV endpoint" : "נקודת קצה WebDAV",
- "to" : "אל",
- "Monday" : "יום שני",
- "Tuesday" : "יום שלישי",
- "Wednesday" : "יום רביעי",
- "Thursday" : "יום חמישי",
- "Friday" : "יום שישי",
- "Saturday" : "יום שבת",
- "Sunday" : "יום ראשון",
- "Save" : "שמירה",
- "Calendar server" : "שרת לוח שנה",
- "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." : "התראות נשלחות באמצעות משימות רקע, לכן הבדיקה תתבצע יחסית לעתים קרובות.",
- "Enable notifications for events via push" : "הפעלת התראות לאירועים בדחיפה",
- "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} כראוי.",
- "There was an error updating your attendance status." : "אירעה שגיאה בעת עדכון מצב ההשתתפות שלך.",
- "Please contact the organizer directly." : "נא ליצור קשר עם הגוף מארגן ישירות.",
- "Are you accepting the invitation?" : "האם להיענות להזמנה?",
- "Tentative" : "טנטטיבית",
- "Your attendance was updated successfully." : "ההשתתפות שלך עודכנה בהצלחה."
-},
-"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;");
diff --git a/apps/dav/l10n/he.json b/apps/dav/l10n/he.json
deleted file mode 100644
index 2eebd45a9f5..00000000000
--- a/apps/dav/l10n/he.json
+++ /dev/null
@@ -1,99 +0,0 @@
-{ "translations": {
- "Calendar" : "יומן",
- "Personal" : "אישי",
- "{actor} created calendar {calendar}" : "היומן {calendar} נוצר על ידי {actor}",
- "You created calendar {calendar}" : "מחקת את היומן {calendar}",
- "{actor} deleted calendar {calendar}" : "היומן {calendar} נמחק על ידי {actor}",
- "You deleted calendar {calendar}" : "מחקת את היומן {calendar}",
- "{actor} updated calendar {calendar}" : "היומן {calendar} עודכן על ידי {actor}",
- "You updated calendar {calendar}" : "עדכנת את היומן {calendar}",
- "You shared calendar {calendar} as public link" : "שיתפת את היומן {calendar} כקישור ציבורי",
- "You removed public link for calendar {calendar}" : "הסרת את הקישור הציבורי ליומן {calendar}",
- "{actor} shared calendar {calendar} with you" : "שותף אתך לוח השנה {calendar} על ידי {actor}",
- "You shared calendar {calendar} with {user}" : "שיתפת לוח שנה {calendar} עם {user}",
- "{actor} shared calendar {calendar} with {user}" : "לוח השנה {calendar} שותף על ידי {actor} עם {user}",
- "{actor} unshared calendar {calendar} from you" : "השיתוף של לוח השנה {calendar} אתך הופסק על ידי {actor}",
- "You unshared calendar {calendar} from {user}" : "ביטלת את שיתוף לוח השנה {calendar} עם {user}",
- "{actor} unshared calendar {calendar} from {user}" : "השיתוף של לוח השנה {calendar} עם {user} הופסק על ידי {actor}",
- "{actor} unshared calendar {calendar} from themselves" : "השיתוף של לוח השנה {calendar} עם עצמם הופסק על ידי {actor}",
- "You shared calendar {calendar} with group {group}" : "שיתפת את לוח השנה {calendar} עם הקבוצה {group}",
- "{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}",
- "You deleted event {event} from calendar {calendar}" : "מחקת אירוע {event} מלוח השנה {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "האירוע {event} עודכן בלוח השנה {calendar} על ידי {actor}",
- "You updated event {event} in calendar {calendar}" : "עדכנת את האירוע {event} בלוח השנה {calendar}",
- "Busy" : "עסוק",
- "A <strong>calendar</strong> was modified" : " <strong>יומן</strong> נערך",
- "A calendar <strong>event</strong> was modified" : "<strong>אירוע</strong> ביומן נערך",
- "Contact birthdays" : "ימי הולדת של אנשי קשר",
- "Death of %s" : "הפטירה של %s",
- "Untitled calendar" : "לוח שנה ללא כותרת",
- "Calendar:" : "לוח שנה:",
- "Date:" : "תאריך:",
- "Where:" : "איפה:",
- "Description:" : "תיאור:",
- "_%n year_::_%n years_" : ["שנה","שנתיים","%n שנים","%n שנים"],
- "_%n month_::_%n months_" : ["חודש","חודשיים","%n חודשים","%n חודשים"],
- "_%n day_::_%n days_" : ["יום","יומיים","%n ימים","%n ימים"],
- "_%n hour_::_%n hours_" : ["שעה","שעתיים","%n שעות","%n שעות"],
- "_%n minute_::_%n minutes_" : ["דקה","%n דקות","%n דקות","%n דקות"],
- "%s (in %s)" : "%s (בתוך %s)",
- "%s (%s ago)" : "%s (לפני %s)",
- "Calendar: %s" : "לוח שנה: %s",
- "Date: %s" : "תאריך: %s",
- "Description: %s" : "תיאור: %s",
- "Where: %s" : "איפה: %s",
- "%1$s via %2$s" : "%1$s דרך %2$s",
- "Organizer:" : "ארגון:",
- "Attendees:" : "משתתפים:",
- "Title:" : "כותרת:",
- "Time:" : "שעה:",
- "Location:" : "מיקום:",
- "Link:" : "קישור:",
- "Accept" : "קבלה",
- "Decline" : "דחייה",
- "More options …" : "אפשרויות נוספות…",
- "More options at %s" : "אפשרויות נוספים ב־%s",
- "Contacts" : "אנשי קשר",
- "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.",
- "Configures a CalDAV account" : "מגדיר חשבון CalDAV",
- "Configures a CardDAV account" : "מגדיר חשבון CardDAV",
- "Events" : "אירועים",
- "Tasks" : "משימות",
- "Untitled task" : "משימה ללא כותרת",
- "Completed on %s" : "הושלמה ב־%s",
- "Contacts and groups" : "אנשי קשר וקבוצות",
- "WebDAV" : "WebDAV",
- "WebDAV endpoint" : "נקודת קצה WebDAV",
- "to" : "אל",
- "Monday" : "יום שני",
- "Tuesday" : "יום שלישי",
- "Wednesday" : "יום רביעי",
- "Thursday" : "יום חמישי",
- "Friday" : "יום שישי",
- "Saturday" : "יום שבת",
- "Sunday" : "יום ראשון",
- "Save" : "שמירה",
- "Calendar server" : "שרת לוח שנה",
- "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." : "התראות נשלחות באמצעות משימות רקע, לכן הבדיקה תתבצע יחסית לעתים קרובות.",
- "Enable notifications for events via push" : "הפעלת התראות לאירועים בדחיפה",
- "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} כראוי.",
- "There was an error updating your attendance status." : "אירעה שגיאה בעת עדכון מצב ההשתתפות שלך.",
- "Please contact the organizer directly." : "נא ליצור קשר עם הגוף מארגן ישירות.",
- "Are you accepting the invitation?" : "האם להיענות להזמנה?",
- "Tentative" : "טנטטיבית",
- "Your attendance was updated successfully." : "ההשתתפות שלך עודכנה בהצלחה."
-},"pluralForm" :"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/hr.js b/apps/dav/l10n/hr.js
deleted file mode 100644
index 0399a414f65..00000000000
--- a/apps/dav/l10n/hr.js
+++ /dev/null
@@ -1,157 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Kalendar",
- "Tasks" : "Zadaci",
- "Personal" : "Osobno",
- "{actor} created calendar {calendar}" : "{actor} je stvorio kalendar {calendar}",
- "You created calendar {calendar}" : "Stvorili ste kalendar {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} je izbrisao kalendar {calendar}",
- "You deleted calendar {calendar}" : "Izbrisali ste kalendar {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} je ažurirao kalendar {calendar}",
- "You updated calendar {calendar}" : "Ažurirali ste kalendar {calendar}",
- "{actor} restored calendar {calendar}" : "{actor} je vratio kalendar {calendar}",
- "You restored calendar {calendar}" : "Vratili ste kalendar {calendar}",
- "You shared calendar {calendar} as public link" : "Podijelili ste kalendar {calendar} putem javne poveznice",
- "You removed public link for calendar {calendar}" : "Uklonili ste javnu poveznicu na kalendar {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} dijeli kalendar {calendar} s vama",
- "You shared calendar {calendar} with {user}" : "Podijelili ste kalendar {calendar} s {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} dijeli kalendar {calendar} s {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} više ne dijeli kalendar {calendar} s vama",
- "You unshared calendar {calendar} from {user}" : "Više ne dijelite kalendar {calendar} s {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} više ne dijeli kalendar {calendar} s {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} više ne dijeli kalendar {calendar} sam sa sobom",
- "You shared calendar {calendar} with group {group}" : "Podijelili ste kalendar {calendar} s grupom {group}",
- "{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}",
- "You deleted event {event} from calendar {calendar}" : "Izbrisali ste događaj {event} iz kalendara {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} je ažurirao događaj {event} u kalendaru {calendar}",
- "You updated event {event} in calendar {calendar}" : "Ažurirali ste događaj {event} u kalendaru {calendar}",
- "{actor} restored event {event} of calendar {calendar}" : "{actor} je vratio događaj {event} kalendara {calendar}",
- "You restored event {event} of calendar {calendar}" : "Vratili ste događaj {event} kalendara {calendar}",
- "Busy" : "Zauzeto",
- "Calendar, contacts and tasks" : "Kalendar, kontakti i zadaci",
- "A <strong>calendar</strong> was modified" : "Izmijenjen je <strong>kalendar</strong>",
- "A calendar <strong>event</strong> was modified" : "Izmijenjen je <strong>događaj</strong> u kalendaru",
- "Contact birthdays" : "Rođendani kontakata",
- "Death of %s" : "Smrt %s",
- "Untitled calendar" : "Kalendar bez naslova",
- "Calendar:" : "Kalendar:",
- "Date:" : "Datum:",
- "Where:" : "Gdje:",
- "Description:" : "Opis:",
- "_%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"],
- "_%n hour_::_%n hours_" : ["%n sat","%n sati","%n sati"],
- "_%n minute_::_%n minutes_" : ["%n minute/minuta","%n minuta","%n minuta"],
- "%s (in %s)" : "%s (u %s)",
- "%s (%s ago)" : "%s (prije %s)",
- "Calendar: %s" : "Kalendar: %s",
- "Date: %s" : "Datum: %s",
- "Description: %s" : "Opis: %s",
- "Where: %s" : "Gdje: %s",
- "%1$s via %2$s" : "%1$s putem %2$s",
- "Cancelled: %1$s" : "Otkazano: %1$s",
- "Re: %1$s" : "Odgovor: %1 $ s",
- "Invitation: %1$s" : "Pozivnica: %1$s",
- "Organizer:" : "Organizator:",
- "Attendees:" : "Polaznici:",
- "Title:" : "Naslov:",
- "When:" : "Kada:",
- "Location:" : "Lokacija:",
- "Link:" : "Poveznica:",
- "Accept" : "Prihvati",
- "Decline" : "Odbij",
- "More options …" : "Više mogućnosti…",
- "More options at %s" : "Više mogućnosti na %s",
- "Monday" : "Ponedjeljak",
- "Tuesday" : "Utorak",
- "Wednesday" : "Srijeda",
- "Thursday" : "Četvrtak",
- "Friday" : "Petak",
- "Saturday" : "Subota",
- "Sunday" : "Nedjelja",
- "January" : "Siječanj",
- "February" : "Veljača",
- "March" : "Ožujak",
- "April" : "Travanj",
- "May" : "Svibanj",
- "June" : "Lipanj",
- "July" : "Srpanj",
- "August" : "Kolovoz",
- "September" : "Rujan",
- "October" : "Listopad",
- "November" : "Studeni",
- "December" : "Prosinac",
- "First" : "Prvi",
- "Last" : "Zadnji",
- "Contacts" : "Kontakti",
- "{actor} created address book {addressbook}" : "{actor} je stvorio adresar {addressbook}",
- "You created address book {addressbook}" : "Stvorili ste adresar {addressbook}",
- "{actor} deleted address book {addressbook}" : "{actor} je izbrisao adresar {addressbook}",
- "You deleted address book {addressbook}" : "Izbrisali ste adresar {addressbook}",
- "{actor} updated address book {addressbook}" : "{actor} je ažurirao adresar {addressbook}",
- "You updated address book {addressbook}" : "Ažurirali ste adresar {addressbook}",
- "{actor} shared address book {addressbook} with you" : "{actor} dijeli adresar {addressbook} s vama",
- "You shared address book {addressbook} with {user}" : "Dijelite adresar {addressbook} s {user}",
- "{actor} shared address book {addressbook} with {user}" : "{actor} dijeli adresar {addressbook} s {user}",
- "{actor} unshared address book {addressbook} from you" : "{actor} je prestao dijeliti adresar {addressbook} s vama",
- "You unshared address book {addressbook} from {user}" : "Prestali ste dijeliti adresar {addressbook} s {user}",
- "{actor} unshared address book {addressbook} from {user}" : "{actor} je prestao dijeliti adresar {addressbook} s {user}",
- "{actor} unshared address book {addressbook} from themselves" : "{actor} je prestao dijeliti adresar {addressbook} sa sobom",
- "You shared address book {addressbook} with group {group}" : "Dijelite adresar {addressbook} s grupom {group}",
- "{actor} shared address book {addressbook} with group {group}" : "{actor} dijeli adresar {addressbook} s grupom {group}",
- "You unshared address book {addressbook} from group {group}" : "Prestali ste dijeliti adresar {addressbook} s grupom {group}",
- "{actor} unshared address book {addressbook} from group {group}" : "{actor} je prestao dijeliti adresar {addressbook} s grupom {group}",
- "{actor} created contact {card} in address book {addressbook}" : "{actor} je stvorio kontakt {card} u adresaru {addressbook}",
- "You created contact {card} in address book {addressbook}" : "Stvorili ste kontakt {card} u adresaru {addressbook}",
- "{actor} deleted contact {card} from address book {addressbook}" : "{actor} je izbrisao kontakt {card} iz adresara {addressbook}",
- "You deleted contact {card} from address book {addressbook}" : "Izbrisali ste kontakt {card} iz adresara {addressbook}",
- "{actor} updated contact {card} in address book {addressbook}" : "{actor} je ažurirao kontakt {card} u adresaru {addressbook}",
- "You updated contact {card} in address book {addressbook}" : "Ažurirali ste kontakt {card} u adresaru {addressbook}",
- "A <strong>contact</strong> or <strong>address book</strong> was modified" : "Izmijenjen je <strong>kontakt</strong> ili <strong>adresar</strong>",
- "Accounts" : "Korisnićki računi",
- "System is in maintenance mode." : "Sustav je u načinu održavanja.",
- "Upgrade needed" : "Potrebno nadograditi",
- "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Vaš %s treba konfigurirati za korištenje HTTPS-a kako bi se mogli upotrebljavati CalDAV i CardDAV s operacijskim sustavom iOS/macOS.",
- "Configures a CalDAV account" : "Konfigurira CalDAV račun",
- "Configures a CardDAV account" : "Konfigurira CardDAV račun",
- "Events" : "Događaji",
- "Untitled task" : "Zadatak bez naslova",
- "Completed on %s" : "Završeno na %s",
- "Due on %s by %s" : "%s treba završiti do %s",
- "Due on %s" : "Treba završiti do %s",
- "WebDAV endpoint" : "WebDAV krajnja točka",
- "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Vaš mrežni poslužitelj nije pravilno podešen za sinkronizaciju podataka jer je sučelje protokola WebDAV neispravno.",
- "Contacts and groups" : "Kontakti i grupe",
- "WebDAV" : "WebDAV",
- "Save" : "Spremi",
- "to" : "do",
- "Delete slot" : "Izbriši mjesto",
- "Add slot" : "Dodaj mjesto",
- "Availability" : "Raspoloživost",
- "Calendar server" : "Poslužitelj kalendara",
- "Send invitations to attendees" : "Pošaljite pozive sudionicima",
- "Automatically generate a birthday calendar" : "Automatski generiraj kalendar rođendana",
- "Birthday calendars will be generated by a background job." : "Kalendari rođendana generirat će se u pozadini.",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Stoga neće biti dostupni odmah nakon omogućivanja, ali će se pojaviti nakon nekog vremena.",
- "Send notifications for events" : "Šalji obavijesti o događajima",
- "Notifications are sent via background jobs, so these must occur often enough." : "Obavijesti se šalju putem pozadinskih zadataka koji se moraju dovoljno često izvoditi.",
- "Enable notifications for events via push" : "Omogući slanje obavijesti o događajima putem push obavijesti",
- "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Također instalirajte {calendarappstoreopen}aplikaciju Kalendar{linkclose} ili {calendardocopen}povežite računalo i mobilni uređaj radi sinkroniziranja ↗{linkclose}.",
- "Please make sure to properly set up {emailopen}the email server{linkclose}." : "Provjerite jeste li ispravno postavili {emailopen}poslužitelj e-pošte{linkclose}.",
- "There was an error updating your attendance status." : "Došlo je do pogreške prilikom ažuriranja statusa prisutnosti.",
- "Please contact the organizer directly." : "Izravno se obratite organizatoru.",
- "Are you accepting the invitation?" : "Prihvaćate li poziv?",
- "Tentative" : "Uvjetno",
- "Your attendance was updated successfully." : "Vaša je prisutnost uspješno ažurirana.",
- "Time:" : "Vrijeme:",
- "If you configure your working hours, other users will see when you are out of office when they book a meeting." : "Ako konfigurirate svoje radno vrijeme, drugi korisnici moći će vidjeti jeste li izvan ureda kada rezerviraju sastanak."
-},
-"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;");
diff --git a/apps/dav/l10n/hr.json b/apps/dav/l10n/hr.json
deleted file mode 100644
index a3b41038c8c..00000000000
--- a/apps/dav/l10n/hr.json
+++ /dev/null
@@ -1,155 +0,0 @@
-{ "translations": {
- "Calendar" : "Kalendar",
- "Tasks" : "Zadaci",
- "Personal" : "Osobno",
- "{actor} created calendar {calendar}" : "{actor} je stvorio kalendar {calendar}",
- "You created calendar {calendar}" : "Stvorili ste kalendar {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} je izbrisao kalendar {calendar}",
- "You deleted calendar {calendar}" : "Izbrisali ste kalendar {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} je ažurirao kalendar {calendar}",
- "You updated calendar {calendar}" : "Ažurirali ste kalendar {calendar}",
- "{actor} restored calendar {calendar}" : "{actor} je vratio kalendar {calendar}",
- "You restored calendar {calendar}" : "Vratili ste kalendar {calendar}",
- "You shared calendar {calendar} as public link" : "Podijelili ste kalendar {calendar} putem javne poveznice",
- "You removed public link for calendar {calendar}" : "Uklonili ste javnu poveznicu na kalendar {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} dijeli kalendar {calendar} s vama",
- "You shared calendar {calendar} with {user}" : "Podijelili ste kalendar {calendar} s {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} dijeli kalendar {calendar} s {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} više ne dijeli kalendar {calendar} s vama",
- "You unshared calendar {calendar} from {user}" : "Više ne dijelite kalendar {calendar} s {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} više ne dijeli kalendar {calendar} s {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} više ne dijeli kalendar {calendar} sam sa sobom",
- "You shared calendar {calendar} with group {group}" : "Podijelili ste kalendar {calendar} s grupom {group}",
- "{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}",
- "You deleted event {event} from calendar {calendar}" : "Izbrisali ste događaj {event} iz kalendara {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} je ažurirao događaj {event} u kalendaru {calendar}",
- "You updated event {event} in calendar {calendar}" : "Ažurirali ste događaj {event} u kalendaru {calendar}",
- "{actor} restored event {event} of calendar {calendar}" : "{actor} je vratio događaj {event} kalendara {calendar}",
- "You restored event {event} of calendar {calendar}" : "Vratili ste događaj {event} kalendara {calendar}",
- "Busy" : "Zauzeto",
- "Calendar, contacts and tasks" : "Kalendar, kontakti i zadaci",
- "A <strong>calendar</strong> was modified" : "Izmijenjen je <strong>kalendar</strong>",
- "A calendar <strong>event</strong> was modified" : "Izmijenjen je <strong>događaj</strong> u kalendaru",
- "Contact birthdays" : "Rođendani kontakata",
- "Death of %s" : "Smrt %s",
- "Untitled calendar" : "Kalendar bez naslova",
- "Calendar:" : "Kalendar:",
- "Date:" : "Datum:",
- "Where:" : "Gdje:",
- "Description:" : "Opis:",
- "_%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"],
- "_%n hour_::_%n hours_" : ["%n sat","%n sati","%n sati"],
- "_%n minute_::_%n minutes_" : ["%n minute/minuta","%n minuta","%n minuta"],
- "%s (in %s)" : "%s (u %s)",
- "%s (%s ago)" : "%s (prije %s)",
- "Calendar: %s" : "Kalendar: %s",
- "Date: %s" : "Datum: %s",
- "Description: %s" : "Opis: %s",
- "Where: %s" : "Gdje: %s",
- "%1$s via %2$s" : "%1$s putem %2$s",
- "Cancelled: %1$s" : "Otkazano: %1$s",
- "Re: %1$s" : "Odgovor: %1 $ s",
- "Invitation: %1$s" : "Pozivnica: %1$s",
- "Organizer:" : "Organizator:",
- "Attendees:" : "Polaznici:",
- "Title:" : "Naslov:",
- "When:" : "Kada:",
- "Location:" : "Lokacija:",
- "Link:" : "Poveznica:",
- "Accept" : "Prihvati",
- "Decline" : "Odbij",
- "More options …" : "Više mogućnosti…",
- "More options at %s" : "Više mogućnosti na %s",
- "Monday" : "Ponedjeljak",
- "Tuesday" : "Utorak",
- "Wednesday" : "Srijeda",
- "Thursday" : "Četvrtak",
- "Friday" : "Petak",
- "Saturday" : "Subota",
- "Sunday" : "Nedjelja",
- "January" : "Siječanj",
- "February" : "Veljača",
- "March" : "Ožujak",
- "April" : "Travanj",
- "May" : "Svibanj",
- "June" : "Lipanj",
- "July" : "Srpanj",
- "August" : "Kolovoz",
- "September" : "Rujan",
- "October" : "Listopad",
- "November" : "Studeni",
- "December" : "Prosinac",
- "First" : "Prvi",
- "Last" : "Zadnji",
- "Contacts" : "Kontakti",
- "{actor} created address book {addressbook}" : "{actor} je stvorio adresar {addressbook}",
- "You created address book {addressbook}" : "Stvorili ste adresar {addressbook}",
- "{actor} deleted address book {addressbook}" : "{actor} je izbrisao adresar {addressbook}",
- "You deleted address book {addressbook}" : "Izbrisali ste adresar {addressbook}",
- "{actor} updated address book {addressbook}" : "{actor} je ažurirao adresar {addressbook}",
- "You updated address book {addressbook}" : "Ažurirali ste adresar {addressbook}",
- "{actor} shared address book {addressbook} with you" : "{actor} dijeli adresar {addressbook} s vama",
- "You shared address book {addressbook} with {user}" : "Dijelite adresar {addressbook} s {user}",
- "{actor} shared address book {addressbook} with {user}" : "{actor} dijeli adresar {addressbook} s {user}",
- "{actor} unshared address book {addressbook} from you" : "{actor} je prestao dijeliti adresar {addressbook} s vama",
- "You unshared address book {addressbook} from {user}" : "Prestali ste dijeliti adresar {addressbook} s {user}",
- "{actor} unshared address book {addressbook} from {user}" : "{actor} je prestao dijeliti adresar {addressbook} s {user}",
- "{actor} unshared address book {addressbook} from themselves" : "{actor} je prestao dijeliti adresar {addressbook} sa sobom",
- "You shared address book {addressbook} with group {group}" : "Dijelite adresar {addressbook} s grupom {group}",
- "{actor} shared address book {addressbook} with group {group}" : "{actor} dijeli adresar {addressbook} s grupom {group}",
- "You unshared address book {addressbook} from group {group}" : "Prestali ste dijeliti adresar {addressbook} s grupom {group}",
- "{actor} unshared address book {addressbook} from group {group}" : "{actor} je prestao dijeliti adresar {addressbook} s grupom {group}",
- "{actor} created contact {card} in address book {addressbook}" : "{actor} je stvorio kontakt {card} u adresaru {addressbook}",
- "You created contact {card} in address book {addressbook}" : "Stvorili ste kontakt {card} u adresaru {addressbook}",
- "{actor} deleted contact {card} from address book {addressbook}" : "{actor} je izbrisao kontakt {card} iz adresara {addressbook}",
- "You deleted contact {card} from address book {addressbook}" : "Izbrisali ste kontakt {card} iz adresara {addressbook}",
- "{actor} updated contact {card} in address book {addressbook}" : "{actor} je ažurirao kontakt {card} u adresaru {addressbook}",
- "You updated contact {card} in address book {addressbook}" : "Ažurirali ste kontakt {card} u adresaru {addressbook}",
- "A <strong>contact</strong> or <strong>address book</strong> was modified" : "Izmijenjen je <strong>kontakt</strong> ili <strong>adresar</strong>",
- "Accounts" : "Korisnićki računi",
- "System is in maintenance mode." : "Sustav je u načinu održavanja.",
- "Upgrade needed" : "Potrebno nadograditi",
- "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Vaš %s treba konfigurirati za korištenje HTTPS-a kako bi se mogli upotrebljavati CalDAV i CardDAV s operacijskim sustavom iOS/macOS.",
- "Configures a CalDAV account" : "Konfigurira CalDAV račun",
- "Configures a CardDAV account" : "Konfigurira CardDAV račun",
- "Events" : "Događaji",
- "Untitled task" : "Zadatak bez naslova",
- "Completed on %s" : "Završeno na %s",
- "Due on %s by %s" : "%s treba završiti do %s",
- "Due on %s" : "Treba završiti do %s",
- "WebDAV endpoint" : "WebDAV krajnja točka",
- "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Vaš mrežni poslužitelj nije pravilno podešen za sinkronizaciju podataka jer je sučelje protokola WebDAV neispravno.",
- "Contacts and groups" : "Kontakti i grupe",
- "WebDAV" : "WebDAV",
- "Save" : "Spremi",
- "to" : "do",
- "Delete slot" : "Izbriši mjesto",
- "Add slot" : "Dodaj mjesto",
- "Availability" : "Raspoloživost",
- "Calendar server" : "Poslužitelj kalendara",
- "Send invitations to attendees" : "Pošaljite pozive sudionicima",
- "Automatically generate a birthday calendar" : "Automatski generiraj kalendar rođendana",
- "Birthday calendars will be generated by a background job." : "Kalendari rođendana generirat će se u pozadini.",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Stoga neće biti dostupni odmah nakon omogućivanja, ali će se pojaviti nakon nekog vremena.",
- "Send notifications for events" : "Šalji obavijesti o događajima",
- "Notifications are sent via background jobs, so these must occur often enough." : "Obavijesti se šalju putem pozadinskih zadataka koji se moraju dovoljno često izvoditi.",
- "Enable notifications for events via push" : "Omogući slanje obavijesti o događajima putem push obavijesti",
- "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Također instalirajte {calendarappstoreopen}aplikaciju Kalendar{linkclose} ili {calendardocopen}povežite računalo i mobilni uređaj radi sinkroniziranja ↗{linkclose}.",
- "Please make sure to properly set up {emailopen}the email server{linkclose}." : "Provjerite jeste li ispravno postavili {emailopen}poslužitelj e-pošte{linkclose}.",
- "There was an error updating your attendance status." : "Došlo je do pogreške prilikom ažuriranja statusa prisutnosti.",
- "Please contact the organizer directly." : "Izravno se obratite organizatoru.",
- "Are you accepting the invitation?" : "Prihvaćate li poziv?",
- "Tentative" : "Uvjetno",
- "Your attendance was updated successfully." : "Vaša je prisutnost uspješno ažurirana.",
- "Time:" : "Vrijeme:",
- "If you configure your working hours, other users will see when you are out of office when they book a meeting." : "Ako konfigurirate svoje radno vrijeme, drugi korisnici moći će vidjeti jeste li izvan ureda kada rezerviraju sastanak."
-},"pluralForm" :"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/hu.js b/apps/dav/l10n/hu.js
index 94101573c66..d45c4d340dd 100644
--- a/apps/dav/l10n/hu.js
+++ b/apps/dav/l10n/hu.js
@@ -223,8 +223,8 @@ OC.L10N.register(
"Absence cleared" : "Távollét törölve",
"Failed to clear your absence settings" : "Nem sikerült a távolléti beállítások törlése",
"First day" : "Első nap",
- "Last day (inclusive)" : "Utols nap (beleértve)",
- "Out of office replacement (optional)" : "Távolléti helyettesítő (opcionális)",
+ "Last day (inclusive)" : "Utolsó nap (beleértve)",
+ "Out of office replacement (optional)" : "Távolléti helyettesítő (nem kötelező)",
"Name of the replacement" : "Helyettesítő neve",
"No results." : "Nincs eredmény.",
"Start typing." : "Kezdjen gépelni.",
@@ -244,6 +244,10 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Válassz kezdő dátumot a {dayName}-hoz",
"Pick a end time for {dayName}" : "Válassz vége dátumot a {dayName}-hoz",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Az elérhetőségi időn túl, a felhasználói állapot automatikus beállítása „Ne zavarjanak” módba az összes értesítés némításához.",
+ "Cancel" : "Mégse",
+ "Import" : "Importálás",
+ "Error while saving settings" : "Hiba a beállítások mentése során",
+ "Reset to default" : "Visszaállítás alapértelmezettre",
"Availability" : "Elérhetőség",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Ha beállítja a munkaidejét, akkor más emberek a megbeszélések létrehozásakor látni fogják, hogy Ön mikor nem érhető el.",
"Absence" : "Távollét",
@@ -260,17 +264,10 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Emlékeztető értesítések küldése azoknak is, akikkel a naptár meg van osztva",
"Reminders are always sent to organizers and attendees." : "Az értesítések mindig a szervezőknek és a résztvevőknek lesznek elküldve.",
"Enable notifications for events via push" : "Leküldéses értesítések engedélyezése az eseményekhez",
- "Cancel" : "Mégse",
- "Import" : "Importálás",
- "Error while saving settings" : "Hiba a beállítások mentése során",
"There was an error updating your attendance status." : "Hiba történt a részvételi állapotának frissítése során.",
"Please contact the organizer directly." : "Vegye fel a kapcsolatot közvetlenül a szervezővel.",
"Are you accepting the invitation?" : "Elfogadja az meghívást?",
"Tentative" : "Feltételes",
- "Your attendance was updated successfully." : "A részvétele frissítése sikeres.",
- "Time:" : "Idő:",
- "Could not open file" : "A fájl nem nyitható meg",
- "Invalid chunk name" : "Érvénytelen darabnév",
- "Could not rename part file assembled from chunks" : "Nem lehet átnevezni a darabokból összeállított részleges fájlt"
+ "Your attendance was updated successfully." : "A részvétele frissítése sikeres."
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/hu.json b/apps/dav/l10n/hu.json
index 9b396cb9271..2e623866c60 100644
--- a/apps/dav/l10n/hu.json
+++ b/apps/dav/l10n/hu.json
@@ -221,8 +221,8 @@
"Absence cleared" : "Távollét törölve",
"Failed to clear your absence settings" : "Nem sikerült a távolléti beállítások törlése",
"First day" : "Első nap",
- "Last day (inclusive)" : "Utols nap (beleértve)",
- "Out of office replacement (optional)" : "Távolléti helyettesítő (opcionális)",
+ "Last day (inclusive)" : "Utolsó nap (beleértve)",
+ "Out of office replacement (optional)" : "Távolléti helyettesítő (nem kötelező)",
"Name of the replacement" : "Helyettesítő neve",
"No results." : "Nincs eredmény.",
"Start typing." : "Kezdjen gépelni.",
@@ -242,6 +242,10 @@
"Pick a start time for {dayName}" : "Válassz kezdő dátumot a {dayName}-hoz",
"Pick a end time for {dayName}" : "Válassz vége dátumot a {dayName}-hoz",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Az elérhetőségi időn túl, a felhasználói állapot automatikus beállítása „Ne zavarjanak” módba az összes értesítés némításához.",
+ "Cancel" : "Mégse",
+ "Import" : "Importálás",
+ "Error while saving settings" : "Hiba a beállítások mentése során",
+ "Reset to default" : "Visszaállítás alapértelmezettre",
"Availability" : "Elérhetőség",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Ha beállítja a munkaidejét, akkor más emberek a megbeszélések létrehozásakor látni fogják, hogy Ön mikor nem érhető el.",
"Absence" : "Távollét",
@@ -258,17 +262,10 @@
"Send reminder notifications to calendar sharees as well" : "Emlékeztető értesítések küldése azoknak is, akikkel a naptár meg van osztva",
"Reminders are always sent to organizers and attendees." : "Az értesítések mindig a szervezőknek és a résztvevőknek lesznek elküldve.",
"Enable notifications for events via push" : "Leküldéses értesítések engedélyezése az eseményekhez",
- "Cancel" : "Mégse",
- "Import" : "Importálás",
- "Error while saving settings" : "Hiba a beállítások mentése során",
"There was an error updating your attendance status." : "Hiba történt a részvételi állapotának frissítése során.",
"Please contact the organizer directly." : "Vegye fel a kapcsolatot közvetlenül a szervezővel.",
"Are you accepting the invitation?" : "Elfogadja az meghívást?",
"Tentative" : "Feltételes",
- "Your attendance was updated successfully." : "A részvétele frissítése sikeres.",
- "Time:" : "Idő:",
- "Could not open file" : "A fájl nem nyitható meg",
- "Invalid chunk name" : "Érvénytelen darabnév",
- "Could not rename part file assembled from chunks" : "Nem lehet átnevezni a darabokból összeállított részleges fájlt"
+ "Your attendance was updated successfully." : "A részvétele frissítése sikeres."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/id.js b/apps/dav/l10n/id.js
deleted file mode 100644
index 0ab333b580f..00000000000
--- a/apps/dav/l10n/id.js
+++ /dev/null
@@ -1,11 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Contact birthdays" : "Ulang tahun kontak",
- "Personal" : "Pribadi",
- "Contacts" : "Kontak",
- "Technical details" : "Rincian teknis",
- "Remote Address: %s" : "Alamat remote: %s",
- "Request ID: %s" : "ID Permintaan: %s"
-},
-"nplurals=1; plural=0;");
diff --git a/apps/dav/l10n/id.json b/apps/dav/l10n/id.json
deleted file mode 100644
index 44280c8125b..00000000000
--- a/apps/dav/l10n/id.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{ "translations": {
- "Contact birthdays" : "Ulang tahun kontak",
- "Personal" : "Pribadi",
- "Contacts" : "Kontak",
- "Technical details" : "Rincian teknis",
- "Remote Address: %s" : "Alamat remote: %s",
- "Request ID: %s" : "ID Permintaan: %s"
-},"pluralForm" :"nplurals=1; plural=0;"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/is.js b/apps/dav/l10n/is.js
index 6a704e34114..80eb90d83db 100644
--- a/apps/dav/l10n/is.js
+++ b/apps/dav/l10n/is.js
@@ -287,6 +287,10 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Veldu upphafstíma fyrir {dayName}",
"Pick a end time for {dayName}" : "Veldu lokatíma fyrir {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Setja stöðu notenda sjálfkrafa á \"Ekki ónáða\" utan þess lausa tíma sem viðkomandi er tiltækur, til að þagga niður í öllum tilkynningum.",
+ "Cancel" : "Hætta við",
+ "Import" : "Flytja inn",
+ "Error while saving settings" : "Villa við að vista stillingar",
+ "Reset to default" : "Endurstilla á sjálfgefið",
"Availability" : "Aðgengileiki",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Ef þú stillir vinnutímana þína, geta aðrir séð hvenær þú sért fjarverandi þegar þeir bóka fundi með þér.",
"Absence" : "Fjarverandi",
@@ -303,17 +307,10 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Senda einnig tilkynningar til þeirra sem deila dagatalinu",
"Reminders are always sent to organizers and attendees." : "Áminningar eru alltaf sendar til skipuleggjenda og þátttakenda.",
"Enable notifications for events via push" : "Senda tilkynningar fyrir atburði sem ýtitilkynningar",
- "Cancel" : "Hætta við",
- "Import" : "Flytja inn",
- "Error while saving settings" : "Villa við að vista stillingar",
"There was an error updating your attendance status." : "Það kom upp villa við að uppfæra mætingarstöðu þína.",
"Please contact the organizer directly." : "Hafðu samband beint við skipuleggjendurna.",
"Are you accepting the invitation?" : "Ætlar þú að samþykkja boðið?",
"Tentative" : "Bráðabirgða",
- "Your attendance was updated successfully." : "Mætingarstaða þín var uppfærð.",
- "Time:" : "Tími:",
- "Could not open file" : "Gat ekki opnað skrá",
- "Invalid chunk name" : "Ógilt heiti á bút",
- "Could not rename part file assembled from chunks" : "Ekki var hægt að endurnefna hlutaskrá setta saman úr bútum"
+ "Your attendance was updated successfully." : "Mætingarstaða þín var uppfærð."
},
"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);");
diff --git a/apps/dav/l10n/is.json b/apps/dav/l10n/is.json
index 9fc9d6906d0..a89ef260f36 100644
--- a/apps/dav/l10n/is.json
+++ b/apps/dav/l10n/is.json
@@ -285,6 +285,10 @@
"Pick a start time for {dayName}" : "Veldu upphafstíma fyrir {dayName}",
"Pick a end time for {dayName}" : "Veldu lokatíma fyrir {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Setja stöðu notenda sjálfkrafa á \"Ekki ónáða\" utan þess lausa tíma sem viðkomandi er tiltækur, til að þagga niður í öllum tilkynningum.",
+ "Cancel" : "Hætta við",
+ "Import" : "Flytja inn",
+ "Error while saving settings" : "Villa við að vista stillingar",
+ "Reset to default" : "Endurstilla á sjálfgefið",
"Availability" : "Aðgengileiki",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Ef þú stillir vinnutímana þína, geta aðrir séð hvenær þú sért fjarverandi þegar þeir bóka fundi með þér.",
"Absence" : "Fjarverandi",
@@ -301,17 +305,10 @@
"Send reminder notifications to calendar sharees as well" : "Senda einnig tilkynningar til þeirra sem deila dagatalinu",
"Reminders are always sent to organizers and attendees." : "Áminningar eru alltaf sendar til skipuleggjenda og þátttakenda.",
"Enable notifications for events via push" : "Senda tilkynningar fyrir atburði sem ýtitilkynningar",
- "Cancel" : "Hætta við",
- "Import" : "Flytja inn",
- "Error while saving settings" : "Villa við að vista stillingar",
"There was an error updating your attendance status." : "Það kom upp villa við að uppfæra mætingarstöðu þína.",
"Please contact the organizer directly." : "Hafðu samband beint við skipuleggjendurna.",
"Are you accepting the invitation?" : "Ætlar þú að samþykkja boðið?",
"Tentative" : "Bráðabirgða",
- "Your attendance was updated successfully." : "Mætingarstaða þín var uppfærð.",
- "Time:" : "Tími:",
- "Could not open file" : "Gat ekki opnað skrá",
- "Invalid chunk name" : "Ógilt heiti á bút",
- "Could not rename part file assembled from chunks" : "Ekki var hægt að endurnefna hlutaskrá setta saman úr bútum"
+ "Your attendance was updated successfully." : "Mætingarstaða þín var uppfærð."
},"pluralForm" :"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/it.js b/apps/dav/l10n/it.js
index 644b25092fc..f441b42c3d8 100644
--- a/apps/dav/l10n/it.js
+++ b/apps/dav/l10n/it.js
@@ -207,6 +207,10 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Scegli un orario di inizio per {dayName}",
"Pick a end time for {dayName}" : "Scegli un orario di fine per {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Imposta automaticamente lo stato dell'utente su \"Non disturbare\" al di fuori della disponibilità per disattivare tutte le notifiche.",
+ "Cancel" : "Annulla",
+ "Import" : "Importa",
+ "Error while saving settings" : "Errore durante il salvataggio delle impostazioni",
+ "Reset to default" : "Ripristina valori predefiniti",
"Availability" : "Disponibilità",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Se imposti il tuo orario di lavoro, le altre persone potranno vedere quando non sei in ufficio per organizzare una riunione.",
"Absence" : "Assenza",
@@ -223,17 +227,10 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Invia notifiche di promemoria anche ai partecipanti al calendario",
"Reminders are always sent to organizers and attendees." : "I promemoria vengono sempre inviati agli organizzatori e ai partecipanti.",
"Enable notifications for events via push" : "Abilita notifiche per eventi tramite push",
- "Cancel" : "Annulla",
- "Import" : "Importa",
- "Error while saving settings" : "Errore durante il salvataggio delle impostazioni",
"There was an error updating your attendance status." : "Si è verificato un errore durante l'aggiornamento dello stato della tua partecipazione.",
"Please contact the organizer directly." : "Contatta direttamente l'amministratore.",
"Are you accepting the invitation?" : "Accetti l'invito?",
"Tentative" : "Provvisorio",
- "Your attendance was updated successfully." : "La tua partecipazione è stata aggiornata correttamente.",
- "Time:" : "Ora:",
- "Could not open file" : "Impossibile aprire il file",
- "Invalid chunk name" : "Nome non valido per lo spezzone",
- "Could not rename part file assembled from chunks" : "Non è possibile rinominare il file assemblato da più spezzoni"
+ "Your attendance was updated successfully." : "La tua partecipazione è stata aggiornata correttamente."
},
"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 7b41fafebbf..035866d3115 100644
--- a/apps/dav/l10n/it.json
+++ b/apps/dav/l10n/it.json
@@ -205,6 +205,10 @@
"Pick a start time for {dayName}" : "Scegli un orario di inizio per {dayName}",
"Pick a end time for {dayName}" : "Scegli un orario di fine per {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Imposta automaticamente lo stato dell'utente su \"Non disturbare\" al di fuori della disponibilità per disattivare tutte le notifiche.",
+ "Cancel" : "Annulla",
+ "Import" : "Importa",
+ "Error while saving settings" : "Errore durante il salvataggio delle impostazioni",
+ "Reset to default" : "Ripristina valori predefiniti",
"Availability" : "Disponibilità",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Se imposti il tuo orario di lavoro, le altre persone potranno vedere quando non sei in ufficio per organizzare una riunione.",
"Absence" : "Assenza",
@@ -221,17 +225,10 @@
"Send reminder notifications to calendar sharees as well" : "Invia notifiche di promemoria anche ai partecipanti al calendario",
"Reminders are always sent to organizers and attendees." : "I promemoria vengono sempre inviati agli organizzatori e ai partecipanti.",
"Enable notifications for events via push" : "Abilita notifiche per eventi tramite push",
- "Cancel" : "Annulla",
- "Import" : "Importa",
- "Error while saving settings" : "Errore durante il salvataggio delle impostazioni",
"There was an error updating your attendance status." : "Si è verificato un errore durante l'aggiornamento dello stato della tua partecipazione.",
"Please contact the organizer directly." : "Contatta direttamente l'amministratore.",
"Are you accepting the invitation?" : "Accetti l'invito?",
"Tentative" : "Provvisorio",
- "Your attendance was updated successfully." : "La tua partecipazione è stata aggiornata correttamente.",
- "Time:" : "Ora:",
- "Could not open file" : "Impossibile aprire il file",
- "Invalid chunk name" : "Nome non valido per lo spezzone",
- "Could not rename part file assembled from chunks" : "Non è possibile rinominare il file assemblato da più spezzoni"
+ "Your attendance was updated successfully." : "La tua partecipazione è stata aggiornata correttamente."
},"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 2aad56b6ee6..6a6753c1d35 100644
--- a/apps/dav/l10n/ja.js
+++ b/apps/dav/l10n/ja.js
@@ -290,6 +290,17 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "{dayName} 開始時間を指定してください",
"Pick a end time for {dayName}" : "{dayName} の終了時間を指定してください",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "利用時間外は自動的にユーザーステータスを\"非通知\" に設定し、すべての通知をミュートします。",
+ "Cancel" : "キャンセル",
+ "Import" : "インポート",
+ "Error while saving settings" : "設定の保存中にエラーが発生",
+ "Contact reset successfully" : "連絡先のリセットが正常に完了しました",
+ "Error while resetting contact" : "連絡先のリセット中にエラーが発生しました",
+ "Contact imported successfully" : "連絡先のインポートが正常に完了しました",
+ "Error while importing contact" : "連絡先のインポート中にエラーが発生しました",
+ "Import contact" : "連絡先のインポート",
+ "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 ファイルをインポートすると、既存のデフォルト連絡先が削除され、新しいものに置き換えられます。続行しますか?",
"Availability" : "応対可能日時",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "勤務時間を設定すると、他のユーザが会議を予約する際に、あなたがいつ不在であるかがわかります。",
"Absence" : "不在",
@@ -306,27 +317,10 @@ 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" : "イベントのプッシュ通知を有効にする",
- "Cancel" : "キャンセル",
- "Import" : "インポート",
- "Error while saving settings" : "設定の保存中にエラーが発生",
- "Contact reset successfully" : "連絡先のリセットが正常に完了しました",
- "Error while resetting contact" : "連絡先のリセット中にエラーが発生しました",
- "Contact imported successfully" : "連絡先のインポートが正常に完了しました",
- "Error while importing contact" : "連絡先のインポート中にエラーが発生しました",
- "Example Content" : "サンプルコンテンツ",
- "Set example content to be created on new user first login." : "新規ユーザの初回ログイン時に作成されるサンプルコンテンツを設定します。",
- "Import contact" : "連絡先のインポート",
- "Reset to default contact" : "デフォルトの連絡先にリセットする",
- "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 ファイルをインポートすると、既存のデフォルト連絡先が削除され、新しいものに置き換えられます。続行しますか?",
"There was an error updating your attendance status." : "出席状況の更新中にエラーが発生しました。",
"Please contact the organizer directly." : "主催者に直接お問い合わせください。",
"Are you accepting the invitation?" : "招待を受け入れていますか?",
"Tentative" : "暫定的",
- "Your attendance was updated successfully." : "出席は正常に更新されました。",
- "Time:" : "時刻:",
- "Could not open file" : "ファイルを開くことができませんでした",
- "Invalid chunk name" : "無効なチャンク名",
- "Could not rename part file assembled from chunks" : "チャンクから構成されている部分ファイルの名前の変更ができませんでした"
+ "Your attendance was updated successfully." : "出席は正常に更新されました。"
},
"nplurals=1; plural=0;");
diff --git a/apps/dav/l10n/ja.json b/apps/dav/l10n/ja.json
index 63d3df52c36..fdefc04c4c7 100644
--- a/apps/dav/l10n/ja.json
+++ b/apps/dav/l10n/ja.json
@@ -288,6 +288,17 @@
"Pick a start time for {dayName}" : "{dayName} 開始時間を指定してください",
"Pick a end time for {dayName}" : "{dayName} の終了時間を指定してください",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "利用時間外は自動的にユーザーステータスを\"非通知\" に設定し、すべての通知をミュートします。",
+ "Cancel" : "キャンセル",
+ "Import" : "インポート",
+ "Error while saving settings" : "設定の保存中にエラーが発生",
+ "Contact reset successfully" : "連絡先のリセットが正常に完了しました",
+ "Error while resetting contact" : "連絡先のリセット中にエラーが発生しました",
+ "Contact imported successfully" : "連絡先のインポートが正常に完了しました",
+ "Error while importing contact" : "連絡先のインポート中にエラーが発生しました",
+ "Import contact" : "連絡先のインポート",
+ "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 ファイルをインポートすると、既存のデフォルト連絡先が削除され、新しいものに置き換えられます。続行しますか?",
"Availability" : "応対可能日時",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "勤務時間を設定すると、他のユーザが会議を予約する際に、あなたがいつ不在であるかがわかります。",
"Absence" : "不在",
@@ -304,27 +315,10 @@
"Send reminder notifications to calendar sharees as well" : "カレンダー共有にもリマインダー通知を送信する",
"Reminders are always sent to organizers and attendees." : "リマインダーを常に作成者と出席者に送信します。",
"Enable notifications for events via push" : "イベントのプッシュ通知を有効にする",
- "Cancel" : "キャンセル",
- "Import" : "インポート",
- "Error while saving settings" : "設定の保存中にエラーが発生",
- "Contact reset successfully" : "連絡先のリセットが正常に完了しました",
- "Error while resetting contact" : "連絡先のリセット中にエラーが発生しました",
- "Contact imported successfully" : "連絡先のインポートが正常に完了しました",
- "Error while importing contact" : "連絡先のインポート中にエラーが発生しました",
- "Example Content" : "サンプルコンテンツ",
- "Set example content to be created on new user first login." : "新規ユーザの初回ログイン時に作成されるサンプルコンテンツを設定します。",
- "Import contact" : "連絡先のインポート",
- "Reset to default contact" : "デフォルトの連絡先にリセットする",
- "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 ファイルをインポートすると、既存のデフォルト連絡先が削除され、新しいものに置き換えられます。続行しますか?",
"There was an error updating your attendance status." : "出席状況の更新中にエラーが発生しました。",
"Please contact the organizer directly." : "主催者に直接お問い合わせください。",
"Are you accepting the invitation?" : "招待を受け入れていますか?",
"Tentative" : "暫定的",
- "Your attendance was updated successfully." : "出席は正常に更新されました。",
- "Time:" : "時刻:",
- "Could not open file" : "ファイルを開くことができませんでした",
- "Invalid chunk name" : "無効なチャンク名",
- "Could not rename part file assembled from chunks" : "チャンクから構成されている部分ファイルの名前の変更ができませんでした"
+ "Your attendance was updated successfully." : "出席は正常に更新されました。"
},"pluralForm" :"nplurals=1; plural=0;"
} \ No newline at end of file
diff --git a/apps/dav/l10n/ka.js b/apps/dav/l10n/ka.js
index a390102d876..682a8e1d254 100644
--- a/apps/dav/l10n/ka.js
+++ b/apps/dav/l10n/ka.js
@@ -192,6 +192,10 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Pick a start time for {dayName}",
"Pick a end time for {dayName}" : "Pick a end time for {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications.",
+ "Cancel" : "Cancel",
+ "Import" : "Import",
+ "Error while saving settings" : "Error while saving settings",
+ "Reset to default" : "Reset to default",
"Availability" : "Availability",
"Absence" : "Absence",
"Configure your next absence period." : "Configure your next absence period.",
@@ -207,17 +211,10 @@ 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 organizers and attendees.",
"Enable notifications for events via push" : "Enable notifications for events via push",
- "Cancel" : "Cancel",
- "Import" : "Import",
- "Error while saving settings" : "Error while saving settings",
"There was an error updating your attendance status." : "There was an error updating your attendance status.",
"Please contact the organizer directly." : "Please contact the organizer directly.",
"Are you accepting the invitation?" : "Are you accepting the invitation?",
"Tentative" : "Tentative",
- "Your attendance was updated successfully." : "Your attendance was updated successfully.",
- "Time:" : "Time:",
- "Could not open file" : "Could not open file",
- "Invalid chunk name" : "Invalid chunk name",
- "Could not rename part file assembled from chunks" : "Could not rename part file assembled from chunks"
+ "Your attendance was updated successfully." : "Your attendance was updated successfully."
},
"nplurals=2; plural=(n!=1);");
diff --git a/apps/dav/l10n/ka.json b/apps/dav/l10n/ka.json
index 5738b8b4fb8..3685b1a2173 100644
--- a/apps/dav/l10n/ka.json
+++ b/apps/dav/l10n/ka.json
@@ -190,6 +190,10 @@
"Pick a start time for {dayName}" : "Pick a start time for {dayName}",
"Pick a end time for {dayName}" : "Pick a end time for {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications.",
+ "Cancel" : "Cancel",
+ "Import" : "Import",
+ "Error while saving settings" : "Error while saving settings",
+ "Reset to default" : "Reset to default",
"Availability" : "Availability",
"Absence" : "Absence",
"Configure your next absence period." : "Configure your next absence period.",
@@ -205,17 +209,10 @@
"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 organizers and attendees.",
"Enable notifications for events via push" : "Enable notifications for events via push",
- "Cancel" : "Cancel",
- "Import" : "Import",
- "Error while saving settings" : "Error while saving settings",
"There was an error updating your attendance status." : "There was an error updating your attendance status.",
"Please contact the organizer directly." : "Please contact the organizer directly.",
"Are you accepting the invitation?" : "Are you accepting the invitation?",
"Tentative" : "Tentative",
- "Your attendance was updated successfully." : "Your attendance was updated successfully.",
- "Time:" : "Time:",
- "Could not open file" : "Could not open file",
- "Invalid chunk name" : "Invalid chunk name",
- "Could not rename part file assembled from chunks" : "Could not rename part file assembled from chunks"
+ "Your attendance was updated successfully." : "Your attendance was updated successfully."
},"pluralForm" :"nplurals=2; plural=(n!=1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/ka_GE.js b/apps/dav/l10n/ka_GE.js
deleted file mode 100644
index 05fa6351239..00000000000
--- a/apps/dav/l10n/ka_GE.js
+++ /dev/null
@@ -1,66 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "კალენდარი",
- "Todos" : "შესასრულებელი დავალებები",
- "Personal" : "პირადი",
- "{actor} created calendar {calendar}" : "{actor} მომხმარებელმა შექმნა კალენდარი {calendar}",
- "You created calendar {calendar}" : "თქვენ შექმენით {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} მომხმარებელმამა გააუქმა კალენდარი {calendar}",
- "You deleted calendar {calendar}" : "თქვენ გააუქმეთ კალენდარი {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} მომხმარებელმა განაახლა კალენდარი {calendar}",
- "You updated calendar {calendar}" : "თქვენ განაახლეთ კალენდარი {calendar}",
- "You shared calendar {calendar} as public link" : "თქვენ გააზიარეთ კალენდარი {calendar} საზოგადო ბმულის სახით",
- "You removed public link for calendar {calendar}" : "თქვენ გააუქმეთ საზოგადო ბმული კალენდარზე {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} მომხმარებელმა თქვენთან გააზიარა კალენდარი {calendar}",
- "You shared calendar {calendar} with {user}" : "თქვენ გააზიარეთ კალენდარი {calendar} მომხმარებელთან {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} მომხმარებელმა გააზიარა {calendar} მომხმარებელთან {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} მომხმარებელმა თქვენთან შეწყვიტა {calendar} კალენდრის გაზიარება",
- "You unshared calendar {calendar} from {user}" : "თქვენ შეწყვიტეთ {calendar} კალენდრის გაზიარება მომხმარებელთან {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} მომხმარებელმა შეწყვიტა {calendar} კალენდრის გაზიარება მომხმარებელთან {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} მომხმარებელმა შეწყვიტა {calendar} კალენდრის გაზიარება",
- "You shared calendar {calendar} with group {group}" : "თქვენ გააზიარეთ კალენდარი {calendar} ჯგუფთან {group}",
- "{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}",
- "{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}",
- "You deleted event {event} from calendar {calendar}" : "თქვენ გააუქმეთ მოვლენა {event} კალენდარში {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} მომხმარებელმა განაახლა მოვლენა {event} კალენდარში {calendar}",
- "You updated event {event} in calendar {calendar}" : "თქვენ განაახლეთ მოვლენა {event} კალენდარში {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} მომხმარებელმა შექმნა შესასრულებელი დავალება {todo} სიაში {calendar}",
- "You created todo {todo} in list {calendar}" : "თქვენ შექმენით შესასრულებელი დავალება {todo} სიაში {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} მომხმარებელმა გააუქმა შესასრულებელი დავალება {todo} სიიდან {calendar}",
- "You deleted todo {todo} from list {calendar}" : "თქვენ გააუქმეთ შესასრულებელი დავალება {todo} სიიდან {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} მომხმარებელმა განაახლა შესასრულებელი დავალება {todo} სიაში {calendar}",
- "You updated todo {todo} in list {calendar}" : "თქვენ განაახლეთ შესასრულებელი დავალება {todo} in list {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} მომხმარებელმა დაასრულა შესასრულებელი დავალება {todo} სიაში {calendar}",
- "You solved todo {todo} in list {calendar}" : "თქვენ დაასრულეთ შესასრულებელი დავალება {todo} სიაში {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} მომხმარებელმა ხელახლა გახსნა შესასრულებელი დავალება {todo} სიაში {calendar}",
- "You reopened todo {todo} in list {calendar}" : "თქვენ ხელახლა გახსენით შესასრულებელი დავალება {todo} სიაში {calendar}",
- "A <strong>calendar</strong> was modified" : "<strong>კალენდარი</strong> შეიცვალა",
- "A calendar <strong>event</strong> was modified" : "კალენდრის <strong>მოვლენა</strong> შეიცვალა",
- "A calendar <strong>todo</strong> was modified" : "კალენდრის <strong>შესასრულებელი დავალება</strong> შეიცვალა",
- "Contact birthdays" : "კონტაქტების დაბადების დღეები",
- "Where:" : "სად:",
- "Description:" : "აღწერა:",
- "Invitation canceled" : "მოწვევა გაუქმდა",
- "Invitation updated" : "მოწვევა განახლდა",
- "Location:" : "ადგილმდებარეობა:",
- "Link:" : "ბმული:",
- "Accept" : "მიღება",
- "Decline" : "ურაყოფა",
- "Contacts" : "კონტაქტები",
- "Tasks" : "დავალებები",
- "WebDAV" : "WebDAV",
- "Tentative" : "საცდელი",
- "Save" : "შენახვა",
- "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." : "ისინი არ იქნებიან ხელმიწავდომნი უცბად, მაგრამ გამოჩნდებიან გარკვეული პერიოდის შემდეგ.",
- "Hello %s," : "გამარჯობა %s,",
- "When:" : "როდის:"
-},
-"nplurals=2; plural=(n!=1);");
diff --git a/apps/dav/l10n/ka_GE.json b/apps/dav/l10n/ka_GE.json
deleted file mode 100644
index 7597200d061..00000000000
--- a/apps/dav/l10n/ka_GE.json
+++ /dev/null
@@ -1,64 +0,0 @@
-{ "translations": {
- "Calendar" : "კალენდარი",
- "Todos" : "შესასრულებელი დავალებები",
- "Personal" : "პირადი",
- "{actor} created calendar {calendar}" : "{actor} მომხმარებელმა შექმნა კალენდარი {calendar}",
- "You created calendar {calendar}" : "თქვენ შექმენით {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} მომხმარებელმამა გააუქმა კალენდარი {calendar}",
- "You deleted calendar {calendar}" : "თქვენ გააუქმეთ კალენდარი {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} მომხმარებელმა განაახლა კალენდარი {calendar}",
- "You updated calendar {calendar}" : "თქვენ განაახლეთ კალენდარი {calendar}",
- "You shared calendar {calendar} as public link" : "თქვენ გააზიარეთ კალენდარი {calendar} საზოგადო ბმულის სახით",
- "You removed public link for calendar {calendar}" : "თქვენ გააუქმეთ საზოგადო ბმული კალენდარზე {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} მომხმარებელმა თქვენთან გააზიარა კალენდარი {calendar}",
- "You shared calendar {calendar} with {user}" : "თქვენ გააზიარეთ კალენდარი {calendar} მომხმარებელთან {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} მომხმარებელმა გააზიარა {calendar} მომხმარებელთან {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} მომხმარებელმა თქვენთან შეწყვიტა {calendar} კალენდრის გაზიარება",
- "You unshared calendar {calendar} from {user}" : "თქვენ შეწყვიტეთ {calendar} კალენდრის გაზიარება მომხმარებელთან {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} მომხმარებელმა შეწყვიტა {calendar} კალენდრის გაზიარება მომხმარებელთან {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} მომხმარებელმა შეწყვიტა {calendar} კალენდრის გაზიარება",
- "You shared calendar {calendar} with group {group}" : "თქვენ გააზიარეთ კალენდარი {calendar} ჯგუფთან {group}",
- "{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}",
- "{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}",
- "You deleted event {event} from calendar {calendar}" : "თქვენ გააუქმეთ მოვლენა {event} კალენდარში {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} მომხმარებელმა განაახლა მოვლენა {event} კალენდარში {calendar}",
- "You updated event {event} in calendar {calendar}" : "თქვენ განაახლეთ მოვლენა {event} კალენდარში {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} მომხმარებელმა შექმნა შესასრულებელი დავალება {todo} სიაში {calendar}",
- "You created todo {todo} in list {calendar}" : "თქვენ შექმენით შესასრულებელი დავალება {todo} სიაში {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} მომხმარებელმა გააუქმა შესასრულებელი დავალება {todo} სიიდან {calendar}",
- "You deleted todo {todo} from list {calendar}" : "თქვენ გააუქმეთ შესასრულებელი დავალება {todo} სიიდან {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} მომხმარებელმა განაახლა შესასრულებელი დავალება {todo} სიაში {calendar}",
- "You updated todo {todo} in list {calendar}" : "თქვენ განაახლეთ შესასრულებელი დავალება {todo} in list {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} მომხმარებელმა დაასრულა შესასრულებელი დავალება {todo} სიაში {calendar}",
- "You solved todo {todo} in list {calendar}" : "თქვენ დაასრულეთ შესასრულებელი დავალება {todo} სიაში {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} მომხმარებელმა ხელახლა გახსნა შესასრულებელი დავალება {todo} სიაში {calendar}",
- "You reopened todo {todo} in list {calendar}" : "თქვენ ხელახლა გახსენით შესასრულებელი დავალება {todo} სიაში {calendar}",
- "A <strong>calendar</strong> was modified" : "<strong>კალენდარი</strong> შეიცვალა",
- "A calendar <strong>event</strong> was modified" : "კალენდრის <strong>მოვლენა</strong> შეიცვალა",
- "A calendar <strong>todo</strong> was modified" : "კალენდრის <strong>შესასრულებელი დავალება</strong> შეიცვალა",
- "Contact birthdays" : "კონტაქტების დაბადების დღეები",
- "Where:" : "სად:",
- "Description:" : "აღწერა:",
- "Invitation canceled" : "მოწვევა გაუქმდა",
- "Invitation updated" : "მოწვევა განახლდა",
- "Location:" : "ადგილმდებარეობა:",
- "Link:" : "ბმული:",
- "Accept" : "მიღება",
- "Decline" : "ურაყოფა",
- "Contacts" : "კონტაქტები",
- "Tasks" : "დავალებები",
- "WebDAV" : "WebDAV",
- "Tentative" : "საცდელი",
- "Save" : "შენახვა",
- "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." : "ისინი არ იქნებიან ხელმიწავდომნი უცბად, მაგრამ გამოჩნდებიან გარკვეული პერიოდის შემდეგ.",
- "Hello %s," : "გამარჯობა %s,",
- "When:" : "როდის:"
-},"pluralForm" :"nplurals=2; plural=(n!=1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/ko.js b/apps/dav/l10n/ko.js
index 91c84463670..ae3b8e5908c 100644
--- a/apps/dav/l10n/ko.js
+++ b/apps/dav/l10n/ko.js
@@ -192,6 +192,10 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "{dayName} 시작 시각을 지정하십시오",
"Pick a end time for {dayName}" : "{dayName} 종료 시각을 지정하십시오",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "다른 용무 중일 때 자동으로 사용자를 '방해 금지' 모드로 설정해 모든 알림을 음소거합니다.",
+ "Cancel" : "취소",
+ "Import" : "가져오기",
+ "Error while saving settings" : "설정 저장 중 오류 발생",
+ "Reset to default" : "기본값으로 초기화",
"Availability" : "시간 조율",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "업무 시간을 설정하면, 다른 사람이 회의를 예약할 때 내 부재 중 시간을 확인할 수 있습니다.",
"Absence" : "부재",
@@ -208,17 +212,10 @@ 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" : "일정에 대한 푸시 알림 활성화",
- "Cancel" : "취소",
- "Import" : "가져오기",
- "Error while saving settings" : "설정 저장 중 오류 발생",
"There was an error updating your attendance status." : "참석 상태를 업데이트하는 중 오류가 발생했습니다.",
"Please contact the organizer directly." : "주최자에게 직접 연락하십시오.",
"Are you accepting the invitation?" : "초대를 수락하시겠습니까?",
"Tentative" : "보류",
- "Your attendance was updated successfully." : "참석 정보를 업데이트했습니다.",
- "Time:" : "시간:",
- "Could not open file" : "파일을 열 수 없음",
- "Invalid chunk name" : "잘못된 청크 이름",
- "Could not rename part file assembled from chunks" : "청크에서 조합 된 부분 파일의 이름을 바꿀 수 없음"
+ "Your attendance was updated successfully." : "참석 정보를 업데이트했습니다."
},
"nplurals=1; plural=0;");
diff --git a/apps/dav/l10n/ko.json b/apps/dav/l10n/ko.json
index c45f8470385..50d8fee9c21 100644
--- a/apps/dav/l10n/ko.json
+++ b/apps/dav/l10n/ko.json
@@ -190,6 +190,10 @@
"Pick a start time for {dayName}" : "{dayName} 시작 시각을 지정하십시오",
"Pick a end time for {dayName}" : "{dayName} 종료 시각을 지정하십시오",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "다른 용무 중일 때 자동으로 사용자를 '방해 금지' 모드로 설정해 모든 알림을 음소거합니다.",
+ "Cancel" : "취소",
+ "Import" : "가져오기",
+ "Error while saving settings" : "설정 저장 중 오류 발생",
+ "Reset to default" : "기본값으로 초기화",
"Availability" : "시간 조율",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "업무 시간을 설정하면, 다른 사람이 회의를 예약할 때 내 부재 중 시간을 확인할 수 있습니다.",
"Absence" : "부재",
@@ -206,17 +210,10 @@
"Send reminder notifications to calendar sharees as well" : "캘린더 공유자에게도 미리 알림 보내기",
"Reminders are always sent to organizers and attendees." : "미리 알림은 주최자와 참석자에게 항상 전송됩니다.",
"Enable notifications for events via push" : "일정에 대한 푸시 알림 활성화",
- "Cancel" : "취소",
- "Import" : "가져오기",
- "Error while saving settings" : "설정 저장 중 오류 발생",
"There was an error updating your attendance status." : "참석 상태를 업데이트하는 중 오류가 발생했습니다.",
"Please contact the organizer directly." : "주최자에게 직접 연락하십시오.",
"Are you accepting the invitation?" : "초대를 수락하시겠습니까?",
"Tentative" : "보류",
- "Your attendance was updated successfully." : "참석 정보를 업데이트했습니다.",
- "Time:" : "시간:",
- "Could not open file" : "파일을 열 수 없음",
- "Invalid chunk name" : "잘못된 청크 이름",
- "Could not rename part file assembled from chunks" : "청크에서 조합 된 부분 파일의 이름을 바꿀 수 없음"
+ "Your attendance was updated successfully." : "참석 정보를 업데이트했습니다."
},"pluralForm" :"nplurals=1; plural=0;"
} \ No newline at end of file
diff --git a/apps/dav/l10n/lt_LT.js b/apps/dav/l10n/lt_LT.js
deleted file mode 100644
index b1ff0a2ee48..00000000000
--- a/apps/dav/l10n/lt_LT.js
+++ /dev/null
@@ -1,111 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Kalendorius",
- "Tasks" : "Užduotys",
- "Personal" : "Asmeniniai",
- "{actor} created calendar {calendar}" : "{actor} sukūrė kalendorių {calendar}",
- "You created calendar {calendar}" : "Jūs sukūrėte kalendorių {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} ištrynė kalendorių {calendar}",
- "You deleted calendar {calendar}" : "Jūs ištrynėte kalendorių {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} atnaujino kalendorių {calendar}",
- "You updated calendar {calendar}" : "Jūs atnaujinote kalendorių {calendar}",
- "{actor} restored calendar {calendar}" : "{actor} atkūrė kalendorių {calendar}",
- "You restored calendar {calendar}" : "Jūs atkūrėte kalendorių {calendar}",
- "You shared calendar {calendar} as public link" : "Jūs pradėjote bendrinti kalendorių {calendar} kaip viešąją nuorodą",
- "You removed public link for calendar {calendar}" : "Jūs pašalinote viešąją nuorodą kalendoriui {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} pradėjo bendrinti su jumis kalendorių {calendar}",
- "You shared calendar {calendar} with {user}" : "Jūs pradėjote bendrinti kalendorių {calendar} su {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} pradėjo bendrinti kalendorių {calendar} su {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} nustojo bendrinti su jumis kalendorių {calendar}",
- "You unshared calendar {calendar} from {user}" : "Jūs nustojote bendrinti kalendorių {calendar} su {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} nustojo bendrinti kalendorių {calendar} su {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} nustojo bendrinti su savimi kalendorių {calendar}",
- "You shared calendar {calendar} with group {group}" : "Jūs pradėjote bendrinti kalendorių {calendar} su grupe {group}",
- "{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}",
- "You deleted event {event} from calendar {calendar}" : "Jūs ištrynėte įvykį {event} iš kalendoriaus {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} kalendoriuje {calendar} atnaujino įvykį {event}",
- "You updated event {event} in calendar {calendar}" : "Jūs kalendoriuje {calendar} atnaujinote įvykį {event}",
- "{actor} restored event {event} of calendar {calendar}" : "{actor} kalendoriuje {calendar} atkūrė įvykį {event}",
- "You restored event {event} of calendar {calendar}" : "Jūs kalendoriuje {calendar} atkūrėte įvykį {event}",
- "Busy" : "Užimtas laikas",
- "Calendar, contacts and tasks" : "Kalendorius, adresatai ir užduotys",
- "A <strong>calendar</strong> was modified" : "<strong>Kalendorius</strong> buvo modifikuotas",
- "A calendar <strong>event</strong> was modified" : "Kalendoriaus <strong>įvykis</strong> buvo modifikuotas",
- "Contact birthdays" : "Adresatų gimtadieniai",
- "Untitled calendar" : "Kalendorius be pavadinimo",
- "Calendar:" : "Kalendorius:",
- "Date:" : "Data:",
- "Where:" : "Kur:",
- "Description:" : "Aprašas:",
- "_%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"],
- "_%n hour_::_%n hours_" : ["%n valanda","%n valandos","%n valandų","%n valanda"],
- "_%n minute_::_%n minutes_" : ["%n minutė","%n minutės","%n minučių","%n minutė"],
- "%s (in %s)" : "%s (po %s)",
- "%s (%s ago)" : "%s (prieš %s)",
- "Calendar: %s" : "Kalendorius: %s",
- "Date: %s" : "Data: %s",
- "Description: %s" : "Aprašas: %s",
- "Where: %s" : "Kur: %s",
- "%1$s via %2$s" : "%1$s per %2$s",
- "Invitation: %1$s" : "Pakvietimas: %1$s",
- "Organizer:" : "Organizatorius:",
- "Attendees:" : "Kviestiniai:",
- "Title:" : "Pavadinimas:",
- "Location:" : "Vieta:",
- "Link:" : "Nuoroda:",
- "Accept" : "Priimti",
- "Decline" : "Atmesti",
- "More options …" : "Daugiau parinkčių…",
- "Contacts" : "Adresatai",
- "{actor} created address book {addressbook}" : "{actor} sukūrė adresų knygą {addressbook}",
- "You created address book {addressbook}" : "Jūs sukūrėte adresų knygą {addressbook}",
- "{actor} deleted address book {addressbook}" : "{actor} ištrynė adresų knygą {addressbook}",
- "You deleted address book {addressbook}" : "Jūs ištrynėte adresų knygą {addressbook}",
- "{actor} updated address book {addressbook}" : "{actor} atnaujino adresų knygą {addressbook}",
- "You updated address book {addressbook}" : "Jūs atnaujinote adresų knygą {addressbook}",
- "System is in maintenance mode." : "Sistema yra techninės priežiūros veiksenoje.",
- "Upgrade needed" : "Reikalingas naujinimas",
- "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Norint naudoti CalDAV ir CardDAV su iOS/macOS, jūsų %s turi būti sukonfigūruota taip, kad naudotų HTTPS.",
- "Configures a CalDAV account" : "Konfigūruoja CalDAV paskyrą",
- "Configures a CardDAV account" : "Konfigūruoja CardDAV paskyrą",
- "Events" : "Įvykiai",
- "Untitled task" : "Užduotis be pavadinimo",
- "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Jūsų svetainės serveris nėra tinkamai sukonfiguruotas, Failų sinchronizavimas negalimas, nes neveikia WebDAV interfeisas.",
- "Contacts and groups" : "Adresatai ir grupės",
- "WebDAV" : "WebDAV",
- "Save" : "Įrašyti",
- "Time zone:" : "Laiko juosta:",
- "to" : "iki",
- "No working hours set" : "Nenustatyta jokių darbo valandų",
- "Monday" : "Pirmadienis",
- "Tuesday" : "Antradienis",
- "Wednesday" : "Trečiadienis",
- "Thursday" : "Ketvirtadienis",
- "Friday" : "Penktadienis",
- "Saturday" : "Šeštadienis",
- "Sunday" : "Sekmadienis",
- "Availability" : "Pasiekiamumas",
- "Calendar server" : "Kalendoriaus serveris",
- "Send invitations to attendees" : "Siųsti pakvietimus kviestiniams",
- "Automatically generate a birthday calendar" : "Automatiškai sukurti gimtadienių kalendorių",
- "Birthday calendars will be generated by a background job." : "Gimtadienių kalendoriai bus sukurti foninės užduoties.",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Tai reiškia, kad jie nebus matomi iš karto įjungus, o pasirodys tik po kurio laiko.",
- "Send notifications for events" : "Siųsti įvykių pranešimus",
- "Notifications are sent via background jobs, so these must occur often enough." : "Pranešimai yra siunčiami per fonines užduotis, todėl jos privalo būti vykdomos gana dažnai.",
- "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Taip pat įsidiekite {calendarappstoreopen}Kalendoriaus programėlę{linkclose} arba sinchronizavimui {calendardocopen}prijunkite savo darbalaukį ir mobilųjį ↗{linkclose}.",
- "Please make sure to properly set up {emailopen}the email server{linkclose}." : "Įsitikinkite, kad tinkamai nusistatėte {emailopen}el. pašto serverį{linkclose}.",
- "Please contact the organizer directly." : "Prašome susisiekti su organizatoriumi tiesiogiai.",
- "Are you accepting the invitation?" : "Ar priimate pakvietimą?",
- "Tentative" : "Preliminarus",
- "Time:" : "Laikas:"
-},
-"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);");
diff --git a/apps/dav/l10n/lt_LT.json b/apps/dav/l10n/lt_LT.json
deleted file mode 100644
index 7eab2a422ca..00000000000
--- a/apps/dav/l10n/lt_LT.json
+++ /dev/null
@@ -1,109 +0,0 @@
-{ "translations": {
- "Calendar" : "Kalendorius",
- "Tasks" : "Užduotys",
- "Personal" : "Asmeniniai",
- "{actor} created calendar {calendar}" : "{actor} sukūrė kalendorių {calendar}",
- "You created calendar {calendar}" : "Jūs sukūrėte kalendorių {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} ištrynė kalendorių {calendar}",
- "You deleted calendar {calendar}" : "Jūs ištrynėte kalendorių {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} atnaujino kalendorių {calendar}",
- "You updated calendar {calendar}" : "Jūs atnaujinote kalendorių {calendar}",
- "{actor} restored calendar {calendar}" : "{actor} atkūrė kalendorių {calendar}",
- "You restored calendar {calendar}" : "Jūs atkūrėte kalendorių {calendar}",
- "You shared calendar {calendar} as public link" : "Jūs pradėjote bendrinti kalendorių {calendar} kaip viešąją nuorodą",
- "You removed public link for calendar {calendar}" : "Jūs pašalinote viešąją nuorodą kalendoriui {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} pradėjo bendrinti su jumis kalendorių {calendar}",
- "You shared calendar {calendar} with {user}" : "Jūs pradėjote bendrinti kalendorių {calendar} su {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} pradėjo bendrinti kalendorių {calendar} su {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} nustojo bendrinti su jumis kalendorių {calendar}",
- "You unshared calendar {calendar} from {user}" : "Jūs nustojote bendrinti kalendorių {calendar} su {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} nustojo bendrinti kalendorių {calendar} su {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} nustojo bendrinti su savimi kalendorių {calendar}",
- "You shared calendar {calendar} with group {group}" : "Jūs pradėjote bendrinti kalendorių {calendar} su grupe {group}",
- "{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}",
- "You deleted event {event} from calendar {calendar}" : "Jūs ištrynėte įvykį {event} iš kalendoriaus {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} kalendoriuje {calendar} atnaujino įvykį {event}",
- "You updated event {event} in calendar {calendar}" : "Jūs kalendoriuje {calendar} atnaujinote įvykį {event}",
- "{actor} restored event {event} of calendar {calendar}" : "{actor} kalendoriuje {calendar} atkūrė įvykį {event}",
- "You restored event {event} of calendar {calendar}" : "Jūs kalendoriuje {calendar} atkūrėte įvykį {event}",
- "Busy" : "Užimtas laikas",
- "Calendar, contacts and tasks" : "Kalendorius, adresatai ir užduotys",
- "A <strong>calendar</strong> was modified" : "<strong>Kalendorius</strong> buvo modifikuotas",
- "A calendar <strong>event</strong> was modified" : "Kalendoriaus <strong>įvykis</strong> buvo modifikuotas",
- "Contact birthdays" : "Adresatų gimtadieniai",
- "Untitled calendar" : "Kalendorius be pavadinimo",
- "Calendar:" : "Kalendorius:",
- "Date:" : "Data:",
- "Where:" : "Kur:",
- "Description:" : "Aprašas:",
- "_%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"],
- "_%n hour_::_%n hours_" : ["%n valanda","%n valandos","%n valandų","%n valanda"],
- "_%n minute_::_%n minutes_" : ["%n minutė","%n minutės","%n minučių","%n minutė"],
- "%s (in %s)" : "%s (po %s)",
- "%s (%s ago)" : "%s (prieš %s)",
- "Calendar: %s" : "Kalendorius: %s",
- "Date: %s" : "Data: %s",
- "Description: %s" : "Aprašas: %s",
- "Where: %s" : "Kur: %s",
- "%1$s via %2$s" : "%1$s per %2$s",
- "Invitation: %1$s" : "Pakvietimas: %1$s",
- "Organizer:" : "Organizatorius:",
- "Attendees:" : "Kviestiniai:",
- "Title:" : "Pavadinimas:",
- "Location:" : "Vieta:",
- "Link:" : "Nuoroda:",
- "Accept" : "Priimti",
- "Decline" : "Atmesti",
- "More options …" : "Daugiau parinkčių…",
- "Contacts" : "Adresatai",
- "{actor} created address book {addressbook}" : "{actor} sukūrė adresų knygą {addressbook}",
- "You created address book {addressbook}" : "Jūs sukūrėte adresų knygą {addressbook}",
- "{actor} deleted address book {addressbook}" : "{actor} ištrynė adresų knygą {addressbook}",
- "You deleted address book {addressbook}" : "Jūs ištrynėte adresų knygą {addressbook}",
- "{actor} updated address book {addressbook}" : "{actor} atnaujino adresų knygą {addressbook}",
- "You updated address book {addressbook}" : "Jūs atnaujinote adresų knygą {addressbook}",
- "System is in maintenance mode." : "Sistema yra techninės priežiūros veiksenoje.",
- "Upgrade needed" : "Reikalingas naujinimas",
- "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Norint naudoti CalDAV ir CardDAV su iOS/macOS, jūsų %s turi būti sukonfigūruota taip, kad naudotų HTTPS.",
- "Configures a CalDAV account" : "Konfigūruoja CalDAV paskyrą",
- "Configures a CardDAV account" : "Konfigūruoja CardDAV paskyrą",
- "Events" : "Įvykiai",
- "Untitled task" : "Užduotis be pavadinimo",
- "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Jūsų svetainės serveris nėra tinkamai sukonfiguruotas, Failų sinchronizavimas negalimas, nes neveikia WebDAV interfeisas.",
- "Contacts and groups" : "Adresatai ir grupės",
- "WebDAV" : "WebDAV",
- "Save" : "Įrašyti",
- "Time zone:" : "Laiko juosta:",
- "to" : "iki",
- "No working hours set" : "Nenustatyta jokių darbo valandų",
- "Monday" : "Pirmadienis",
- "Tuesday" : "Antradienis",
- "Wednesday" : "Trečiadienis",
- "Thursday" : "Ketvirtadienis",
- "Friday" : "Penktadienis",
- "Saturday" : "Šeštadienis",
- "Sunday" : "Sekmadienis",
- "Availability" : "Pasiekiamumas",
- "Calendar server" : "Kalendoriaus serveris",
- "Send invitations to attendees" : "Siųsti pakvietimus kviestiniams",
- "Automatically generate a birthday calendar" : "Automatiškai sukurti gimtadienių kalendorių",
- "Birthday calendars will be generated by a background job." : "Gimtadienių kalendoriai bus sukurti foninės užduoties.",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Tai reiškia, kad jie nebus matomi iš karto įjungus, o pasirodys tik po kurio laiko.",
- "Send notifications for events" : "Siųsti įvykių pranešimus",
- "Notifications are sent via background jobs, so these must occur often enough." : "Pranešimai yra siunčiami per fonines užduotis, todėl jos privalo būti vykdomos gana dažnai.",
- "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Taip pat įsidiekite {calendarappstoreopen}Kalendoriaus programėlę{linkclose} arba sinchronizavimui {calendardocopen}prijunkite savo darbalaukį ir mobilųjį ↗{linkclose}.",
- "Please make sure to properly set up {emailopen}the email server{linkclose}." : "Įsitikinkite, kad tinkamai nusistatėte {emailopen}el. pašto serverį{linkclose}.",
- "Please contact the organizer directly." : "Prašome susisiekti su organizatoriumi tiesiogiai.",
- "Are you accepting the invitation?" : "Ar priimate pakvietimą?",
- "Tentative" : "Preliminarus",
- "Time:" : "Laikas:"
-},"pluralForm" :"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/lv.js b/apps/dav/l10n/lv.js
deleted file mode 100644
index 0a8e585fbd1..00000000000
--- a/apps/dav/l10n/lv.js
+++ /dev/null
@@ -1,11 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Contact birthdays" : "Kontaktu dzimšanas dienas",
- "Personal" : "Personīgi",
- "Contacts" : "Kontakti",
- "Technical details" : "Tehniskās detaļas",
- "Remote Address: %s" : "Attālinātā adrese: %s",
- "Request ID: %s" : "Pieprasījuma ID: %s"
-},
-"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);");
diff --git a/apps/dav/l10n/lv.json b/apps/dav/l10n/lv.json
deleted file mode 100644
index c28aad665dd..00000000000
--- a/apps/dav/l10n/lv.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{ "translations": {
- "Contact birthdays" : "Kontaktu dzimšanas dienas",
- "Personal" : "Personīgi",
- "Contacts" : "Kontakti",
- "Technical details" : "Tehniskās detaļas",
- "Remote Address: %s" : "Attālinātā adrese: %s",
- "Request ID: %s" : "Pieprasījuma ID: %s"
-},"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/mk.js b/apps/dav/l10n/mk.js
index 46b51db6c3f..aee9a41896f 100644
--- a/apps/dav/l10n/mk.js
+++ b/apps/dav/l10n/mk.js
@@ -181,6 +181,9 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Избери почетно време за {dayName}",
"Pick a end time for {dayName}" : "Избери крајно време за {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Автоматско поставување на статус во \"Не вознемирувај\" недостапен за да ги занемите сите известувања.",
+ "Cancel" : "Откажи",
+ "Import" : "Увези",
+ "Reset to default" : "Ресетирај на стандардно",
"Availability" : "Достапност",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Ако ги поставите работните часови, другите корисници ќе можат да видат кога сте слободни за да можат да закажат состанок.",
"Absence" : "Отсуство",
@@ -197,14 +200,10 @@ 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" : "Овозможи известувања за настани преку push",
- "Cancel" : "Откажи",
- "Import" : "Увези",
"There was an error updating your attendance status." : "Настана грешка при ажурирање на вашето присуство.",
"Please contact the organizer directly." : "Контактирајте го организаторот директно.",
"Are you accepting the invitation?" : "Дали ја прифаќате поканата?",
"Tentative" : "Прелиминарно",
- "Your attendance was updated successfully." : "Вашето присуство е успешно ажурирано.",
- "Time:" : "Време:",
- "Could not open file" : "Неможе да се отвори датотеката"
+ "Your attendance was updated successfully." : "Вашето присуство е успешно ажурирано."
},
"nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;");
diff --git a/apps/dav/l10n/mk.json b/apps/dav/l10n/mk.json
index f7864e8bd64..50e9e168496 100644
--- a/apps/dav/l10n/mk.json
+++ b/apps/dav/l10n/mk.json
@@ -179,6 +179,9 @@
"Pick a start time for {dayName}" : "Избери почетно време за {dayName}",
"Pick a end time for {dayName}" : "Избери крајно време за {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Автоматско поставување на статус во \"Не вознемирувај\" недостапен за да ги занемите сите известувања.",
+ "Cancel" : "Откажи",
+ "Import" : "Увези",
+ "Reset to default" : "Ресетирај на стандардно",
"Availability" : "Достапност",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Ако ги поставите работните часови, другите корисници ќе можат да видат кога сте слободни за да можат да закажат состанок.",
"Absence" : "Отсуство",
@@ -195,14 +198,10 @@
"Send reminder notifications to calendar sharees as well" : "Испратете известувања за потсетници и до споделувањата на календарот",
"Reminders are always sent to organizers and attendees." : "Секогаш се испраќаат потсетници до организаторите и до присутните.",
"Enable notifications for events via push" : "Овозможи известувања за настани преку push",
- "Cancel" : "Откажи",
- "Import" : "Увези",
"There was an error updating your attendance status." : "Настана грешка при ажурирање на вашето присуство.",
"Please contact the organizer directly." : "Контактирајте го организаторот директно.",
"Are you accepting the invitation?" : "Дали ја прифаќате поканата?",
"Tentative" : "Прелиминарно",
- "Your attendance was updated successfully." : "Вашето присуство е успешно ажурирано.",
- "Time:" : "Време:",
- "Could not open file" : "Неможе да се отвори датотеката"
+ "Your attendance was updated successfully." : "Вашето присуство е успешно ажурирано."
},"pluralForm" :"nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;"
} \ No newline at end of file
diff --git a/apps/dav/l10n/nb.js b/apps/dav/l10n/nb.js
index bd6ae10ed39..d10ba88149b 100644
--- a/apps/dav/l10n/nb.js
+++ b/apps/dav/l10n/nb.js
@@ -247,6 +247,10 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Velg et starttidspunkt for {dayName}",
"Pick a end time for {dayName}" : "Velg et sluttidspunkt for {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Sett brukerstatus automatisk til «Ikke forstyrr» utenfor arbeidstid for å dempe alle varsler.",
+ "Cancel" : "Avbryt",
+ "Import" : "Importer",
+ "Error while saving settings" : "Feil ved lagring av innstillinger",
+ "Reset to default" : "Tilbakestill til standard",
"Availability" : "Arbeidstid",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Hvis du konfigurerer arbeidstiden din, vil andre personer se når du ikke er på kontoret når de bestiller et møte.",
"Absence" : "Fravær",
@@ -263,17 +267,10 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Send påminnelsesvarsler til kalenderdelinger også",
"Reminders are always sent to organizers and attendees." : "Reminders are always sent to organizers and attendees.",
"Enable notifications for events via push" : "Aktiver varsler for hendelser via push",
- "Cancel" : "Avbryt",
- "Import" : "Importer",
- "Error while saving settings" : "Feil ved lagring av innstillinger",
"There was an error updating your attendance status." : "Det oppsto en feil under oppdateringen av oppmøtestatusen din.",
"Please contact the organizer directly." : "Ta kontakt med arrangøren direkte.",
"Are you accepting the invitation?" : "Aksepterer du invitasjonen?",
"Tentative" : "Foreløpig",
- "Your attendance was updated successfully." : "Deltakelsen din ble oppdatert.",
- "Time:" : "Tid:",
- "Could not open file" : "Kunne ikke åpne fil",
- "Invalid chunk name" : "Ugyldig bitnavn",
- "Could not rename part file assembled from chunks" : "Kunne ikke gi nytt navn til delfil satt sammen fra biter"
+ "Your attendance was updated successfully." : "Deltakelsen din ble oppdatert."
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/nb.json b/apps/dav/l10n/nb.json
index e8aee0356f4..d33852e0013 100644
--- a/apps/dav/l10n/nb.json
+++ b/apps/dav/l10n/nb.json
@@ -245,6 +245,10 @@
"Pick a start time for {dayName}" : "Velg et starttidspunkt for {dayName}",
"Pick a end time for {dayName}" : "Velg et sluttidspunkt for {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Sett brukerstatus automatisk til «Ikke forstyrr» utenfor arbeidstid for å dempe alle varsler.",
+ "Cancel" : "Avbryt",
+ "Import" : "Importer",
+ "Error while saving settings" : "Feil ved lagring av innstillinger",
+ "Reset to default" : "Tilbakestill til standard",
"Availability" : "Arbeidstid",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Hvis du konfigurerer arbeidstiden din, vil andre personer se når du ikke er på kontoret når de bestiller et møte.",
"Absence" : "Fravær",
@@ -261,17 +265,10 @@
"Send reminder notifications to calendar sharees as well" : "Send påminnelsesvarsler til kalenderdelinger også",
"Reminders are always sent to organizers and attendees." : "Reminders are always sent to organizers and attendees.",
"Enable notifications for events via push" : "Aktiver varsler for hendelser via push",
- "Cancel" : "Avbryt",
- "Import" : "Importer",
- "Error while saving settings" : "Feil ved lagring av innstillinger",
"There was an error updating your attendance status." : "Det oppsto en feil under oppdateringen av oppmøtestatusen din.",
"Please contact the organizer directly." : "Ta kontakt med arrangøren direkte.",
"Are you accepting the invitation?" : "Aksepterer du invitasjonen?",
"Tentative" : "Foreløpig",
- "Your attendance was updated successfully." : "Deltakelsen din ble oppdatert.",
- "Time:" : "Tid:",
- "Could not open file" : "Kunne ikke åpne fil",
- "Invalid chunk name" : "Ugyldig bitnavn",
- "Could not rename part file assembled from chunks" : "Kunne ikke gi nytt navn til delfil satt sammen fra biter"
+ "Your attendance was updated successfully." : "Deltakelsen din ble oppdatert."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/nl.js b/apps/dav/l10n/nl.js
index 464dae7bf81..e07dc153418 100644
--- a/apps/dav/l10n/nl.js
+++ b/apps/dav/l10n/nl.js
@@ -166,6 +166,10 @@ OC.L10N.register(
"Add slot" : "Voeg slot toe",
"Weekdays" : "Weekdagen",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Stel de gebruikersstatus automatisch in op \"Niet storen\" buiten de beschikbaarheid om alle meldingen te dempen.",
+ "Cancel" : "Annuleren",
+ "Import" : "Import",
+ "Error while saving settings" : "Probleem tijdens het opslaan van instellingen",
+ "Reset to default" : "Herstellen naar standaard",
"Availability" : "Beschikbaarheid",
"Absence" : "Afwezigheid",
"Configure your next absence period." : "Configureer uw volgende afwezigheidsperiode.",
@@ -179,17 +183,10 @@ OC.L10N.register(
"Send notifications for events" : "Versturen meldingen voor afspraken",
"Notifications are sent via background jobs, so these must occur often enough." : "Meldingen worden via achtergrondtaken verstuurd, dus die moeten vaak genoeg plaatsvinden.",
"Enable notifications for events via push" : "Inschakelen push-melding voor afspraken",
- "Cancel" : "Annuleren",
- "Import" : "Import",
- "Error while saving settings" : "Probleem tijdens het opslaan van instellingen",
"There was an error updating your attendance status." : "Er trad een fout op bij het bijwerken van je deelnamestatus.",
"Please contact the organizer directly." : "Neem rechtstreeks contact op met de organisator.",
"Are you accepting the invitation?" : "Neem je de uitnodiging aan?",
"Tentative" : "Onder voorbehoud",
- "Your attendance was updated successfully." : "Je deelname is succesvol bijgewerkt.",
- "Time:" : "Tijd:",
- "Could not open file" : "Kan het bestand niet openen",
- "Invalid chunk name" : "Ongeldige chunknaam",
- "Could not rename part file assembled from chunks" : "Kon een bestandsdeel dat uit chunks is samengesteld niet hernoemen"
+ "Your attendance was updated successfully." : "Je deelname is succesvol bijgewerkt."
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/nl.json b/apps/dav/l10n/nl.json
index f5d509dfc4a..161b2287d8e 100644
--- a/apps/dav/l10n/nl.json
+++ b/apps/dav/l10n/nl.json
@@ -164,6 +164,10 @@
"Add slot" : "Voeg slot toe",
"Weekdays" : "Weekdagen",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Stel de gebruikersstatus automatisch in op \"Niet storen\" buiten de beschikbaarheid om alle meldingen te dempen.",
+ "Cancel" : "Annuleren",
+ "Import" : "Import",
+ "Error while saving settings" : "Probleem tijdens het opslaan van instellingen",
+ "Reset to default" : "Herstellen naar standaard",
"Availability" : "Beschikbaarheid",
"Absence" : "Afwezigheid",
"Configure your next absence period." : "Configureer uw volgende afwezigheidsperiode.",
@@ -177,17 +181,10 @@
"Send notifications for events" : "Versturen meldingen voor afspraken",
"Notifications are sent via background jobs, so these must occur often enough." : "Meldingen worden via achtergrondtaken verstuurd, dus die moeten vaak genoeg plaatsvinden.",
"Enable notifications for events via push" : "Inschakelen push-melding voor afspraken",
- "Cancel" : "Annuleren",
- "Import" : "Import",
- "Error while saving settings" : "Probleem tijdens het opslaan van instellingen",
"There was an error updating your attendance status." : "Er trad een fout op bij het bijwerken van je deelnamestatus.",
"Please contact the organizer directly." : "Neem rechtstreeks contact op met de organisator.",
"Are you accepting the invitation?" : "Neem je de uitnodiging aan?",
"Tentative" : "Onder voorbehoud",
- "Your attendance was updated successfully." : "Je deelname is succesvol bijgewerkt.",
- "Time:" : "Tijd:",
- "Could not open file" : "Kan het bestand niet openen",
- "Invalid chunk name" : "Ongeldige chunknaam",
- "Could not rename part file assembled from chunks" : "Kon een bestandsdeel dat uit chunks is samengesteld niet hernoemen"
+ "Your attendance was updated successfully." : "Je deelname is succesvol bijgewerkt."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/nn_NO.js b/apps/dav/l10n/nn_NO.js
deleted file mode 100644
index 5dee7e46749..00000000000
--- a/apps/dav/l10n/nn_NO.js
+++ /dev/null
@@ -1,43 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Kalendar",
- "Todos" : "Å gjere",
- "Personal" : "Personleg",
- "{actor} created calendar {calendar}" : "{actor} lagde kalendaren {calendar}",
- "You created calendar {calendar}" : "Du lagde kalendaren {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} sletta kalendaren {calendar}",
- "You deleted calendar {calendar}" : "Du sletta kalendaren {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} oppdaterte kalendaren {calendar}",
- "You updated calendar {calendar}" : "Du oppdaterte kalendaren {calendar}",
- "You shared calendar {calendar} as public link" : "Du delte kalendaren {calendar} som en offentleg lenke",
- "You removed public link for calendar {calendar}" : "Du fjerna den offentlege lenka for kalendaren {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} delte kalendaren {calendar} med deg",
- "You shared calendar {calendar} with {user}" : "Du delte kalendaren {calendar} med {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} delte kalendaren {calendar} med {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} stoppa å dele kalendaren {calendar} med deg",
- "You unshared calendar {calendar} from {user}" : "Du stoppa å dele kalendaren {calendar} med {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} stoppa å dele kalendaren {calendar} med {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} stoppa å dele kalendaren {calendar} med segsjølv",
- "You shared calendar {calendar} with group {group}" : "Du delte kalendaren {calendar} med gruppa {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} delte kalendaren {calendar} med gruppa {group}",
- "You unshared calendar {calendar} from group {group}" : "Du stoppa å dele {calendar} med gruppa {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} stoppa å dele kalendaren {calendar} med gruppa {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} oppretta ein hending {event} i kalendaren {calendar}",
- "You created event {event} in calendar {calendar}" : "Du oppretta ei hending {event} i kalendaren {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} seltta ei hending {event} frå kalendaren {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Du sletta ei hending {event} frå kalendaren {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} oppdaterte hendinga {event} i kalendaren {calendar}",
- "You updated event {event} in calendar {calendar}" : "Du oppdaterte hendinga {event} i kalendaren {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} oppretta å gjere {todo} i lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Du oppretta å gjere {todo} i lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} sletta å gjere {todo} frå lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Du sletta å gjere {todo} frå lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} oppdaterte å gjere {todo} i lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Du oppdaterte å gjere {todo} i lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} løyste å gjere {todo} i lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Du løyste å gjere {todo} i lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} igjen-opna å gjere {todo} i lista {calendar}",
- "You reopened todo {todo} in list {calendar}" : "Du igjen-opna å gjere {todo} i lista {calendar}"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/nn_NO.json b/apps/dav/l10n/nn_NO.json
deleted file mode 100644
index 3323f9f7088..00000000000
--- a/apps/dav/l10n/nn_NO.json
+++ /dev/null
@@ -1,41 +0,0 @@
-{ "translations": {
- "Calendar" : "Kalendar",
- "Todos" : "Å gjere",
- "Personal" : "Personleg",
- "{actor} created calendar {calendar}" : "{actor} lagde kalendaren {calendar}",
- "You created calendar {calendar}" : "Du lagde kalendaren {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} sletta kalendaren {calendar}",
- "You deleted calendar {calendar}" : "Du sletta kalendaren {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} oppdaterte kalendaren {calendar}",
- "You updated calendar {calendar}" : "Du oppdaterte kalendaren {calendar}",
- "You shared calendar {calendar} as public link" : "Du delte kalendaren {calendar} som en offentleg lenke",
- "You removed public link for calendar {calendar}" : "Du fjerna den offentlege lenka for kalendaren {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} delte kalendaren {calendar} med deg",
- "You shared calendar {calendar} with {user}" : "Du delte kalendaren {calendar} med {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} delte kalendaren {calendar} med {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} stoppa å dele kalendaren {calendar} med deg",
- "You unshared calendar {calendar} from {user}" : "Du stoppa å dele kalendaren {calendar} med {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} stoppa å dele kalendaren {calendar} med {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} stoppa å dele kalendaren {calendar} med segsjølv",
- "You shared calendar {calendar} with group {group}" : "Du delte kalendaren {calendar} med gruppa {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} delte kalendaren {calendar} med gruppa {group}",
- "You unshared calendar {calendar} from group {group}" : "Du stoppa å dele {calendar} med gruppa {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} stoppa å dele kalendaren {calendar} med gruppa {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} oppretta ein hending {event} i kalendaren {calendar}",
- "You created event {event} in calendar {calendar}" : "Du oppretta ei hending {event} i kalendaren {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} seltta ei hending {event} frå kalendaren {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Du sletta ei hending {event} frå kalendaren {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} oppdaterte hendinga {event} i kalendaren {calendar}",
- "You updated event {event} in calendar {calendar}" : "Du oppdaterte hendinga {event} i kalendaren {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} oppretta å gjere {todo} i lista {calendar}",
- "You created todo {todo} in list {calendar}" : "Du oppretta å gjere {todo} i lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} sletta å gjere {todo} frå lista {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Du sletta å gjere {todo} frå lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} oppdaterte å gjere {todo} i lista {calendar}",
- "You updated todo {todo} in list {calendar}" : "Du oppdaterte å gjere {todo} i lista {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} løyste å gjere {todo} i lista {calendar}",
- "You solved todo {todo} in list {calendar}" : "Du løyste å gjere {todo} i lista {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} igjen-opna å gjere {todo} i lista {calendar}",
- "You reopened todo {todo} in list {calendar}" : "Du igjen-opna å gjere {todo} i lista {calendar}"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/pl.js b/apps/dav/l10n/pl.js
index 45c51f70f42..f495d241d6f 100644
--- a/apps/dav/l10n/pl.js
+++ b/apps/dav/l10n/pl.js
@@ -72,8 +72,14 @@ OC.L10N.register(
"Description: %s" : "Opis: %s",
"Where: %s" : "Gdzie: %s",
"%1$s via %2$s" : "%1$s przez %2$s",
+ "In the past on %1$s for the entire day" : "W przeszłości w %1$s na cały dzień",
+ "_In a hour on %1$s for the entire day_::_In %n hours on %1$s for the entire day_" : ["Za godzinę, dnia %1$s, przez cały dzień","Za %n godziny, dnia %1$s, przez cały dzień","Za %n godzin, dnia %1$s, przez cały dzień","Za %n godzin, dnia %1$s, przez cały dzień"],
+ "_In a day on %1$s for the entire day_::_In %n days on %1$s for the entire day_" : ["Za jeden dzień, dnia %1$s, przez cały dzień","Za %n dni, dnia %1$s, przez cały dzień","Za %n dni, dnia %1$s, przez cały dzień","Za %n dni, dnia %1$s, przez cały dzień"],
+ "_In a week on %1$s for the entire day_::_In %n weeks on %1$s for the entire day_" : ["Za tydzień, dnia %1$s, przez cały dzień","Za %n tygodnie, dnia %1$s, przez cały dzień","Za %n tygodni, dnia %1$s, przez cały dzień","Za %n tygodni, dnia %1$s, przez cały dzień"],
"Could not generate when statement" : "Nie można wygenerować instrukcji when",
"Every Day for the entire day" : "Codziennie przez cały dzień",
+ "Every Day for the entire day until %1$s" : "Codziennie przez cały dzień do %1$s",
+ "Every Day between %1$s - %2$s" : "Codziennie między %1$s – %2$s",
"Could not generate event recurrence statement" : "Nie można wygenerować zestawienia powtórzeń zdarzenia",
"Could not generate next recurrence statement" : "Nie można wygenerować następnej instrukcji powtarzania",
"Cancelled: %1$s" : "Anulowane: %1$s",
@@ -121,10 +127,12 @@ OC.L10N.register(
"Second" : "Druga",
"Third" : "Trzecia",
"Fourth" : "Czwarta",
+ "Fifth" : "Piąty",
"Last" : "Ostatnia",
"Second Last" : "Druga ostatnia",
"Third Last" : "Trzecia ostatnia",
"Fourth Last" : "Czwarty ostatni",
+ "Fifth Last" : "Piąty od końca",
"Contacts" : "Kontakty",
"{actor} created address book {addressbook}" : "{actor} utworzył książkę adresową {addressbook}",
"You created address book {addressbook}" : "Utworzyłeś książkę adresową {addressbook}",
@@ -178,6 +186,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\".",
@@ -215,6 +226,25 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Wybierz dzień rozpoczęcia {dayName}",
"Pick a end time for {dayName}" : "Wybierz dzień zakończenia {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automatycznie ustaw status użytkownika na \"Nie przeszkadzać\" poza dostępnością, aby wyciszyć wszystkie powiadomienia.",
+ "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ść",
@@ -231,17 +261,12 @@ 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",
- "Cancel" : "Anuluj",
- "Import" : "Importuj",
- "Error while saving settings" : "Błąd podczas zapisywania ustawień",
+ "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?",
"Tentative" : "Niepewne",
- "Your attendance was updated successfully." : "Twoja obecność została pomyślnie zaktualizowana.",
- "Time:" : "Czas:",
- "Could not open file" : "Nie można otworzyć pliku",
- "Invalid chunk name" : "Nieprawidłowa nazwa fragmentu",
- "Could not rename part file assembled from chunks" : "Nie można zmienić nazwy pliku podzielonego złożonego z kawałków"
+ "Your attendance was updated successfully." : "Twoja obecność została pomyślnie zaktualizowana."
},
"nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);");
diff --git a/apps/dav/l10n/pl.json b/apps/dav/l10n/pl.json
index f8a2313f7ea..4f8bd86cc4c 100644
--- a/apps/dav/l10n/pl.json
+++ b/apps/dav/l10n/pl.json
@@ -70,8 +70,14 @@
"Description: %s" : "Opis: %s",
"Where: %s" : "Gdzie: %s",
"%1$s via %2$s" : "%1$s przez %2$s",
+ "In the past on %1$s for the entire day" : "W przeszłości w %1$s na cały dzień",
+ "_In a hour on %1$s for the entire day_::_In %n hours on %1$s for the entire day_" : ["Za godzinę, dnia %1$s, przez cały dzień","Za %n godziny, dnia %1$s, przez cały dzień","Za %n godzin, dnia %1$s, przez cały dzień","Za %n godzin, dnia %1$s, przez cały dzień"],
+ "_In a day on %1$s for the entire day_::_In %n days on %1$s for the entire day_" : ["Za jeden dzień, dnia %1$s, przez cały dzień","Za %n dni, dnia %1$s, przez cały dzień","Za %n dni, dnia %1$s, przez cały dzień","Za %n dni, dnia %1$s, przez cały dzień"],
+ "_In a week on %1$s for the entire day_::_In %n weeks on %1$s for the entire day_" : ["Za tydzień, dnia %1$s, przez cały dzień","Za %n tygodnie, dnia %1$s, przez cały dzień","Za %n tygodni, dnia %1$s, przez cały dzień","Za %n tygodni, dnia %1$s, przez cały dzień"],
"Could not generate when statement" : "Nie można wygenerować instrukcji when",
"Every Day for the entire day" : "Codziennie przez cały dzień",
+ "Every Day for the entire day until %1$s" : "Codziennie przez cały dzień do %1$s",
+ "Every Day between %1$s - %2$s" : "Codziennie między %1$s – %2$s",
"Could not generate event recurrence statement" : "Nie można wygenerować zestawienia powtórzeń zdarzenia",
"Could not generate next recurrence statement" : "Nie można wygenerować następnej instrukcji powtarzania",
"Cancelled: %1$s" : "Anulowane: %1$s",
@@ -119,10 +125,12 @@
"Second" : "Druga",
"Third" : "Trzecia",
"Fourth" : "Czwarta",
+ "Fifth" : "Piąty",
"Last" : "Ostatnia",
"Second Last" : "Druga ostatnia",
"Third Last" : "Trzecia ostatnia",
"Fourth Last" : "Czwarty ostatni",
+ "Fifth Last" : "Piąty od końca",
"Contacts" : "Kontakty",
"{actor} created address book {addressbook}" : "{actor} utworzył książkę adresową {addressbook}",
"You created address book {addressbook}" : "Utworzyłeś książkę adresową {addressbook}",
@@ -176,6 +184,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\".",
@@ -213,6 +224,25 @@
"Pick a start time for {dayName}" : "Wybierz dzień rozpoczęcia {dayName}",
"Pick a end time for {dayName}" : "Wybierz dzień zakończenia {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automatycznie ustaw status użytkownika na \"Nie przeszkadzać\" poza dostępnością, aby wyciszyć wszystkie powiadomienia.",
+ "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ść",
@@ -229,17 +259,12 @@
"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",
- "Cancel" : "Anuluj",
- "Import" : "Importuj",
- "Error while saving settings" : "Błąd podczas zapisywania ustawień",
+ "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?",
"Tentative" : "Niepewne",
- "Your attendance was updated successfully." : "Twoja obecność została pomyślnie zaktualizowana.",
- "Time:" : "Czas:",
- "Could not open file" : "Nie można otworzyć pliku",
- "Invalid chunk name" : "Nieprawidłowa nazwa fragmentu",
- "Could not rename part file assembled from chunks" : "Nie można zmienić nazwy pliku podzielonego złożonego z kawałków"
+ "Your attendance was updated successfully." : "Twoja obecność została pomyślnie zaktualizowana."
},"pluralForm" :"nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/pt_BR.js b/apps/dav/l10n/pt_BR.js
index df87e8e0a32..df50b516e36 100644
--- a/apps/dav/l10n/pt_BR.js
+++ b/apps/dav/l10n/pt_BR.js
@@ -104,22 +104,22 @@ OC.L10N.register(
"Every %1$d Weeks on %2$s for the entire day until %3$s" : "A Cada %1$d Semanas, %2$s para o dia inteiro até %3$s",
"Every %1$d Weeks on %2$s between %3$s - %4$s" : "A Cada %1$d Semanas, %2$s entre %3$s - %4$s",
"Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "A Cada %1$d Semanas, %2$s entre %3$s - %4$s até %5$s",
- "Every Month on the %1$s for the entire day" : "Todo Mês no dia %1$s para o dia inteiro",
- "Every Month on the %1$s for the entire day until %2$s" : "Todo Mês no dia %1$s para o dia inteiro até %2$s",
- "Every Month on the %1$s between %2$s - %3$s" : "Todo Mês no dia %1$s entre %2$s - %3$s",
- "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Todo Mês no dia %1$s entre %2$s - %3$s até %4$s",
- "Every %1$d Months on the %2$s for the entire day" : "A Cada %1$d Meses no dia %2$s para o dia inteiro",
- "Every %1$d Months on the %2$s for the entire day until %3$s" : "A Cada %1$d Meses no dia %2$s para o dia inteiro até %3$s",
- "Every %1$d Months on the %2$s between %3$s - %4$s" : "A Cada %1$d Meses no dia %2$s entre %3$s - %4$s",
- "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "A Cada %1$d Meses no dia %2$s entre %3$s - %4$s até %5$s",
- "Every Year in %1$s on the %2$s for the entire day" : "Todo Ano em %1$s no dia %2$s para o dia inteiro",
- "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Todo Ano em %1$s no dia %2$s para o dia inteiro até %3$s",
- "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Todo Ano em %1$s no dia %2$s entre %3$s - %4$s",
- "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Todo Ano em %1$s no dia %2$s entre %3$s - %4$s até %5$s",
- "Every %1$d Years in %2$s on the %3$s for the entire day" : "A Cada %1$d Anos em %2$s no dia %3$s para o dia inteiro",
- "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "A Cada %1$d Anos em %2$s no dia %3$s para o dia inteiro até %4$s",
- "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "A Cada %1$d Anos em %2$s no dia %3$s entre %4$s - %5$s ",
- "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "A Cada %1$d Anos em %2$s no dia %3$s entre %4$s - %5$s até %6$s",
+ "Every Month on the %1$s for the entire day" : "Todo Mês, dia: %1$s, para o dia inteiro",
+ "Every Month on the %1$s for the entire day until %2$s" : "Todo Mês, dia: %1$s, para o dia inteiro até %2$s",
+ "Every Month on the %1$s between %2$s - %3$s" : "Todo Mês, dia: %1$s, entre %2$s - %3$s",
+ "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Todo Mês, dia: %1$s, entre %2$s - %3$s até %4$s",
+ "Every %1$d Months on the %2$s for the entire day" : "A Cada %1$d Meses, dia: %2$s, para o dia inteiro",
+ "Every %1$d Months on the %2$s for the entire day until %3$s" : "A Cada %1$d Meses, dia: %2$s, para o dia inteiro até %3$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s" : "A Cada %1$d Meses, dia: %2$s, entre %3$s - %4$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "A Cada %1$d Meses, dia: %2$s, entre %3$s - %4$s até %5$s",
+ "Every Year in %1$s on the %2$s for the entire day" : "Todo Ano em %1$s, dia: %2$s, para o dia inteiro",
+ "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Todo Ano em %1$s, dia: %2$s, para o dia inteiro até %3$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Todo Ano em %1$s, dia: %2$s, entre %3$s - %4$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Todo Ano em %1$s, dia: %2$s, entre %3$s - %4$s até %5$s",
+ "Every %1$d Years in %2$s on the %3$s for the entire day" : "A Cada %1$d Anos em %2$s, dia: %3$s, para o dia inteiro",
+ "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "A Cada %1$d Anos em %2$s, dia: %3$s, para o dia inteiro até %4$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "A Cada %1$d Anos em %2$s, dia: %3$s, entre %4$s - %5$s ",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "A Cada %1$d Anos em %2$s, dia: %3$s, entre %4$s - %5$s até %6$s",
"On specific dates for the entire day until %1$s" : "Em datas específicas para o dia inteiro até %1$s",
"On specific dates between %1$s - %2$s until %3$s" : "Em datas específicas entre %1$s - %2$s até %3$s",
"In the past on %1$s" : "No passado em %1$s",
@@ -185,16 +185,16 @@ OC.L10N.register(
"October" : "Outubro",
"November" : "Novembro",
"December" : "Dezembro",
- "First" : "Primeiro/a",
- "Second" : "Segundo/a",
- "Third" : "Terço/a",
- "Fourth" : "Quarto/a",
- "Fifth" : "Quinto/a",
+ "First" : "1.º/ª",
+ "Second" : "2.º/ª",
+ "Third" : "3.º/ª",
+ "Fourth" : "4.º/ª",
+ "Fifth" : "5.º/ª",
"Last" : "Último/a",
"Second Last" : "Penúltimo/a",
- "Third Last" : "Terceiro/a Último/a",
- "Fourth Last" : "Quarto/a Último/a",
- "Fifth Last" : "Quinto/a Último/a",
+ "Third Last" : "3.º/ª Último/a",
+ "Fourth Last" : "4.º/ª Último/a",
+ "Fifth Last" : "5.º/ª Último/a",
"Contacts" : "Contatos",
"{actor} created address book {addressbook}" : "{actor} criou o catálogo de endereços {addressbook}",
"You created address book {addressbook}" : "Você criou o catálogo de endereços {addressbook}",
@@ -250,6 +250,8 @@ OC.L10N.register(
"Completed on %s" : "Concluída em %s",
"Due on %s by %s" : "Vence em %s até %s",
"Due on %s" : "Vence em %s",
+ "Welcome to Nextcloud Calendar!\n\nThis is a sample event - explore the flexibility of planning with Nextcloud Calendar by making any edits you want!\n\nWith Nextcloud Calendar, you can:\n- Create, edit, and manage events effortlessly.\n- Create multiple calendars and share them with teammates, friends, or family.\n- Check availability and display your busy times to others.\n- Seamlessly integrate with apps and devices via CalDAV.\n- Customize your experience: schedule recurring events, adjust notifications and other settings." : "Bem-vindo ao Nextcloud Calendário!\n\nEste é um exemplo de evento - explore a flexibilidade do planejamento com o Nextcloud Calendário fazendo as edições que desejar!\n\nCom o Nextcloud Calendário, você pode:\n- Criar, editar e gerenciar eventos sem esforço.\n- Criar vários calendários e compartilhá-los com colegas de equipe, amigos ou familiares.\n- Verificar a disponibilidade e exibir seus horários de trabalho para outras pessoas.\n- Integrar-se perfeitamente com aplicativos e dispositivos via CalDAV.\n- Personalize sua experiência: agende eventos recorrentes, ajuste as notificações e outras configurações.",
+ "Example event - open me!" : "Exemplo de evento - abra-me!",
"System Address Book" : "Catálogo de Endereços do Sistema",
"The system address book contains contact information for all users in your instance." : "O catálogo de endereços do sistema contém informações de contato de todos os usuários da sua instância.",
"Enable System Address Book" : "Ativar Catálogo de Endereços do Sistema",
@@ -290,6 +292,25 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Selecione um horário de início para {dayName}",
"Pick a end time for {dayName}" : "Selecione um horário de fim para {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Defina automaticamente o status do usuário como \"Não perturbe\" fora de disponibilidade para silenciar todas as notificações.",
+ "Cancel" : "Cancelar",
+ "Import" : "Importar",
+ "Error while saving settings" : "Erro ao salvar as configurações",
+ "Contact reset successfully" : "O contato foi reiniciado com sucesso",
+ "Error while resetting contact" : "Erro ao reiniciar o contato",
+ "Contact imported successfully" : "O contato foi importado com sucesso",
+ "Error while importing contact" : "Erro ao importar o contato",
+ "Import contact" : "Importar contato",
+ "Reset to default" : "Redefinir para o padrão",
+ "Import contacts" : "Importar contatos",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "A importação de um novo arquivo .vcf excluirá o contato padrão existente e o substituirá pelo novo. Deseja continuar?",
+ "Failed to save example event creation setting" : "Falha ao salvar a configuração de criação de evento de exemplo",
+ "Failed to upload the example event" : "Falha ao fazer upload do evento de exemplo",
+ "Custom example event was saved successfully" : "O evento de exemplo personalizado foi salvo com êxito",
+ "Failed to delete the custom example event" : "Falha ao excluir o evento de exemplo personalizado",
+ "Custom example event was deleted successfully" : "O evento de exemplo personalizado foi excluído com êxito",
+ "Import calendar event" : "Importar evento de calendário",
+ "Uploading a new event will overwrite the existing one." : "O upload de um novo evento substituirá o existente.",
+ "Upload event" : "Fazer upload do evento",
"Availability" : "Disponibilidade",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Se você configurar seu horário de trabalho, outras pessoas verão quando você estiver ausente quando agendarem uma reunião.",
"Absence" : "Ausência",
@@ -306,27 +327,12 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Enviar notificações de lembrete também para os compartilhadores de calendário",
"Reminders are always sent to organizers and attendees." : "Lembretes são sempre enviados aos organizadores e participantes.",
"Enable notifications for events via push" : "Ativar notificações para eventos via push",
- "Cancel" : "Cancelar",
- "Import" : "Importar",
- "Error while saving settings" : "Erro ao salvar as configurações",
- "Contact reset successfully" : "O contato foi reiniciado com sucesso",
- "Error while resetting contact" : "Erro ao reiniciar o contato",
- "Contact imported successfully" : "O contato foi importado com sucesso",
- "Error while importing contact" : "Erro ao importar o contato",
- "Example Content" : "Exemplo de Conteúdo",
- "Set example content to be created on new user first login." : "Defina o exemplo de conteúdo a ser criado no primeiro login do novo usuário.",
- "Import contact" : "Importar contato",
- "Reset to default contact" : "Redefinir para o contato padrão",
- "Import contacts" : "Importar contatos",
- "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "A importação de um novo arquivo .vcf excluirá o contato padrão existente e o substituirá pelo novo. Deseja continuar?",
+ "Example content" : "Exemplo de conteúdo",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "O conteúdo de exemplo serve para mostrar os recursos do Nextcloud. O conteúdo padrão é fornecido com o Nextcloud e pode ser substituído por conteúdo personalizado.",
"There was an error updating your attendance status." : "Houve um erro ao atualizar seu status de participação.",
"Please contact the organizer directly." : "Por favor, contate o organizador diretamente.",
"Are you accepting the invitation?" : "Você está aceitando o convite?",
"Tentative" : "Tentativa",
- "Your attendance was updated successfully." : "Sua presença foi atualizada com sucesso.",
- "Time:" : "Horário:",
- "Could not open file" : "Não foi possível abrir o arquivo",
- "Invalid chunk name" : "Nome de pedaço inválido",
- "Could not rename part file assembled from chunks" : "Não foi possível renomear o arquivo de peça montado a partir de pedaços"
+ "Your attendance was updated successfully." : "Sua presença foi atualizada com sucesso."
},
"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 971fd07089f..340a9fcf50e 100644
--- a/apps/dav/l10n/pt_BR.json
+++ b/apps/dav/l10n/pt_BR.json
@@ -102,22 +102,22 @@
"Every %1$d Weeks on %2$s for the entire day until %3$s" : "A Cada %1$d Semanas, %2$s para o dia inteiro até %3$s",
"Every %1$d Weeks on %2$s between %3$s - %4$s" : "A Cada %1$d Semanas, %2$s entre %3$s - %4$s",
"Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "A Cada %1$d Semanas, %2$s entre %3$s - %4$s até %5$s",
- "Every Month on the %1$s for the entire day" : "Todo Mês no dia %1$s para o dia inteiro",
- "Every Month on the %1$s for the entire day until %2$s" : "Todo Mês no dia %1$s para o dia inteiro até %2$s",
- "Every Month on the %1$s between %2$s - %3$s" : "Todo Mês no dia %1$s entre %2$s - %3$s",
- "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Todo Mês no dia %1$s entre %2$s - %3$s até %4$s",
- "Every %1$d Months on the %2$s for the entire day" : "A Cada %1$d Meses no dia %2$s para o dia inteiro",
- "Every %1$d Months on the %2$s for the entire day until %3$s" : "A Cada %1$d Meses no dia %2$s para o dia inteiro até %3$s",
- "Every %1$d Months on the %2$s between %3$s - %4$s" : "A Cada %1$d Meses no dia %2$s entre %3$s - %4$s",
- "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "A Cada %1$d Meses no dia %2$s entre %3$s - %4$s até %5$s",
- "Every Year in %1$s on the %2$s for the entire day" : "Todo Ano em %1$s no dia %2$s para o dia inteiro",
- "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Todo Ano em %1$s no dia %2$s para o dia inteiro até %3$s",
- "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Todo Ano em %1$s no dia %2$s entre %3$s - %4$s",
- "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Todo Ano em %1$s no dia %2$s entre %3$s - %4$s até %5$s",
- "Every %1$d Years in %2$s on the %3$s for the entire day" : "A Cada %1$d Anos em %2$s no dia %3$s para o dia inteiro",
- "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "A Cada %1$d Anos em %2$s no dia %3$s para o dia inteiro até %4$s",
- "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "A Cada %1$d Anos em %2$s no dia %3$s entre %4$s - %5$s ",
- "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "A Cada %1$d Anos em %2$s no dia %3$s entre %4$s - %5$s até %6$s",
+ "Every Month on the %1$s for the entire day" : "Todo Mês, dia: %1$s, para o dia inteiro",
+ "Every Month on the %1$s for the entire day until %2$s" : "Todo Mês, dia: %1$s, para o dia inteiro até %2$s",
+ "Every Month on the %1$s between %2$s - %3$s" : "Todo Mês, dia: %1$s, entre %2$s - %3$s",
+ "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Todo Mês, dia: %1$s, entre %2$s - %3$s até %4$s",
+ "Every %1$d Months on the %2$s for the entire day" : "A Cada %1$d Meses, dia: %2$s, para o dia inteiro",
+ "Every %1$d Months on the %2$s for the entire day until %3$s" : "A Cada %1$d Meses, dia: %2$s, para o dia inteiro até %3$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s" : "A Cada %1$d Meses, dia: %2$s, entre %3$s - %4$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "A Cada %1$d Meses, dia: %2$s, entre %3$s - %4$s até %5$s",
+ "Every Year in %1$s on the %2$s for the entire day" : "Todo Ano em %1$s, dia: %2$s, para o dia inteiro",
+ "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Todo Ano em %1$s, dia: %2$s, para o dia inteiro até %3$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Todo Ano em %1$s, dia: %2$s, entre %3$s - %4$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Todo Ano em %1$s, dia: %2$s, entre %3$s - %4$s até %5$s",
+ "Every %1$d Years in %2$s on the %3$s for the entire day" : "A Cada %1$d Anos em %2$s, dia: %3$s, para o dia inteiro",
+ "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "A Cada %1$d Anos em %2$s, dia: %3$s, para o dia inteiro até %4$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "A Cada %1$d Anos em %2$s, dia: %3$s, entre %4$s - %5$s ",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "A Cada %1$d Anos em %2$s, dia: %3$s, entre %4$s - %5$s até %6$s",
"On specific dates for the entire day until %1$s" : "Em datas específicas para o dia inteiro até %1$s",
"On specific dates between %1$s - %2$s until %3$s" : "Em datas específicas entre %1$s - %2$s até %3$s",
"In the past on %1$s" : "No passado em %1$s",
@@ -183,16 +183,16 @@
"October" : "Outubro",
"November" : "Novembro",
"December" : "Dezembro",
- "First" : "Primeiro/a",
- "Second" : "Segundo/a",
- "Third" : "Terço/a",
- "Fourth" : "Quarto/a",
- "Fifth" : "Quinto/a",
+ "First" : "1.º/ª",
+ "Second" : "2.º/ª",
+ "Third" : "3.º/ª",
+ "Fourth" : "4.º/ª",
+ "Fifth" : "5.º/ª",
"Last" : "Último/a",
"Second Last" : "Penúltimo/a",
- "Third Last" : "Terceiro/a Último/a",
- "Fourth Last" : "Quarto/a Último/a",
- "Fifth Last" : "Quinto/a Último/a",
+ "Third Last" : "3.º/ª Último/a",
+ "Fourth Last" : "4.º/ª Último/a",
+ "Fifth Last" : "5.º/ª Último/a",
"Contacts" : "Contatos",
"{actor} created address book {addressbook}" : "{actor} criou o catálogo de endereços {addressbook}",
"You created address book {addressbook}" : "Você criou o catálogo de endereços {addressbook}",
@@ -248,6 +248,8 @@
"Completed on %s" : "Concluída em %s",
"Due on %s by %s" : "Vence em %s até %s",
"Due on %s" : "Vence em %s",
+ "Welcome to Nextcloud Calendar!\n\nThis is a sample event - explore the flexibility of planning with Nextcloud Calendar by making any edits you want!\n\nWith Nextcloud Calendar, you can:\n- Create, edit, and manage events effortlessly.\n- Create multiple calendars and share them with teammates, friends, or family.\n- Check availability and display your busy times to others.\n- Seamlessly integrate with apps and devices via CalDAV.\n- Customize your experience: schedule recurring events, adjust notifications and other settings." : "Bem-vindo ao Nextcloud Calendário!\n\nEste é um exemplo de evento - explore a flexibilidade do planejamento com o Nextcloud Calendário fazendo as edições que desejar!\n\nCom o Nextcloud Calendário, você pode:\n- Criar, editar e gerenciar eventos sem esforço.\n- Criar vários calendários e compartilhá-los com colegas de equipe, amigos ou familiares.\n- Verificar a disponibilidade e exibir seus horários de trabalho para outras pessoas.\n- Integrar-se perfeitamente com aplicativos e dispositivos via CalDAV.\n- Personalize sua experiência: agende eventos recorrentes, ajuste as notificações e outras configurações.",
+ "Example event - open me!" : "Exemplo de evento - abra-me!",
"System Address Book" : "Catálogo de Endereços do Sistema",
"The system address book contains contact information for all users in your instance." : "O catálogo de endereços do sistema contém informações de contato de todos os usuários da sua instância.",
"Enable System Address Book" : "Ativar Catálogo de Endereços do Sistema",
@@ -288,6 +290,25 @@
"Pick a start time for {dayName}" : "Selecione um horário de início para {dayName}",
"Pick a end time for {dayName}" : "Selecione um horário de fim para {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Defina automaticamente o status do usuário como \"Não perturbe\" fora de disponibilidade para silenciar todas as notificações.",
+ "Cancel" : "Cancelar",
+ "Import" : "Importar",
+ "Error while saving settings" : "Erro ao salvar as configurações",
+ "Contact reset successfully" : "O contato foi reiniciado com sucesso",
+ "Error while resetting contact" : "Erro ao reiniciar o contato",
+ "Contact imported successfully" : "O contato foi importado com sucesso",
+ "Error while importing contact" : "Erro ao importar o contato",
+ "Import contact" : "Importar contato",
+ "Reset to default" : "Redefinir para o padrão",
+ "Import contacts" : "Importar contatos",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "A importação de um novo arquivo .vcf excluirá o contato padrão existente e o substituirá pelo novo. Deseja continuar?",
+ "Failed to save example event creation setting" : "Falha ao salvar a configuração de criação de evento de exemplo",
+ "Failed to upload the example event" : "Falha ao fazer upload do evento de exemplo",
+ "Custom example event was saved successfully" : "O evento de exemplo personalizado foi salvo com êxito",
+ "Failed to delete the custom example event" : "Falha ao excluir o evento de exemplo personalizado",
+ "Custom example event was deleted successfully" : "O evento de exemplo personalizado foi excluído com êxito",
+ "Import calendar event" : "Importar evento de calendário",
+ "Uploading a new event will overwrite the existing one." : "O upload de um novo evento substituirá o existente.",
+ "Upload event" : "Fazer upload do evento",
"Availability" : "Disponibilidade",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Se você configurar seu horário de trabalho, outras pessoas verão quando você estiver ausente quando agendarem uma reunião.",
"Absence" : "Ausência",
@@ -304,27 +325,12 @@
"Send reminder notifications to calendar sharees as well" : "Enviar notificações de lembrete também para os compartilhadores de calendário",
"Reminders are always sent to organizers and attendees." : "Lembretes são sempre enviados aos organizadores e participantes.",
"Enable notifications for events via push" : "Ativar notificações para eventos via push",
- "Cancel" : "Cancelar",
- "Import" : "Importar",
- "Error while saving settings" : "Erro ao salvar as configurações",
- "Contact reset successfully" : "O contato foi reiniciado com sucesso",
- "Error while resetting contact" : "Erro ao reiniciar o contato",
- "Contact imported successfully" : "O contato foi importado com sucesso",
- "Error while importing contact" : "Erro ao importar o contato",
- "Example Content" : "Exemplo de Conteúdo",
- "Set example content to be created on new user first login." : "Defina o exemplo de conteúdo a ser criado no primeiro login do novo usuário.",
- "Import contact" : "Importar contato",
- "Reset to default contact" : "Redefinir para o contato padrão",
- "Import contacts" : "Importar contatos",
- "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "A importação de um novo arquivo .vcf excluirá o contato padrão existente e o substituirá pelo novo. Deseja continuar?",
+ "Example content" : "Exemplo de conteúdo",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "O conteúdo de exemplo serve para mostrar os recursos do Nextcloud. O conteúdo padrão é fornecido com o Nextcloud e pode ser substituído por conteúdo personalizado.",
"There was an error updating your attendance status." : "Houve um erro ao atualizar seu status de participação.",
"Please contact the organizer directly." : "Por favor, contate o organizador diretamente.",
"Are you accepting the invitation?" : "Você está aceitando o convite?",
"Tentative" : "Tentativa",
- "Your attendance was updated successfully." : "Sua presença foi atualizada com sucesso.",
- "Time:" : "Horário:",
- "Could not open file" : "Não foi possível abrir o arquivo",
- "Invalid chunk name" : "Nome de pedaço inválido",
- "Could not rename part file assembled from chunks" : "Não foi possível renomear o arquivo de peça montado a partir de pedaços"
+ "Your attendance was updated successfully." : "Sua presença foi atualizada com sucesso."
},"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/pt_PT.js b/apps/dav/l10n/pt_PT.js
new file mode 100644
index 00000000000..17246a2a574
--- /dev/null
+++ b/apps/dav/l10n/pt_PT.js
@@ -0,0 +1,336 @@
+OC.L10N.register(
+ "dav",
+ {
+ "Calendar" : "Calendário",
+ "Tasks" : "Tarefas",
+ "Personal" : "Pessoal",
+ "{actor} created calendar {calendar}" : "{actor} criou o calendário {calendar}",
+ "You created calendar {calendar}" : "Criou o calendario {calendar}",
+ "{actor} deleted calendar {calendar}" : "{actor} apagou o calendário {calendar}",
+ "You deleted calendar {calendar}" : "Apagou o calendário {calendar}",
+ "{actor} updated calendar {calendar}" : "{actor} atualizou o calendário {calendar}",
+ "You updated calendar {calendar}" : "Atualizou o calendário {calendar}",
+ "{actor} restored calendar {calendar}" : "{actor} restaurou o calendário {calendar}",
+ "You restored calendar {calendar}" : "restaurou o calendário {calendar}",
+ "You shared calendar {calendar} as public link" : "Partilhou o calendário {calendar} como uma hiperligação pública",
+ "You removed public link for calendar {calendar}" : "Removeu uma hiperligação pública para o calendário {calendar}",
+ "{actor} shared calendar {calendar} with you" : "{actor} partilhou o calendário {calendar} consigo",
+ "You shared calendar {calendar} with {user}" : "Partilhou o calendário {calendar} com {user}",
+ "{actor} shared calendar {calendar} with {user}" : "{actor} partilhou o calendário {calendar} com {user}",
+ "{actor} unshared calendar {calendar} from you" : "{actor} retirou-lhe a partilha do calendário {calendar}",
+ "You unshared calendar {calendar} from {user}" : "Retirou a partilha do calendário {calendar} com {user}",
+ "{actor} unshared calendar {calendar} from {user}" : "{actor} retirou a partilha do calendário {calendar} com {user}",
+ "{actor} unshared calendar {calendar} from themselves" : "{actor} deixou de partilhar o calendário {calendar} de próprio",
+ "You shared calendar {calendar} with group {group}" : "partilhou o calendário {calendar} com o grupo {group}",
+ "{actor} shared calendar {calendar} with group {group}" : "{actor} partilhou o calendário {calendar} com o grupo {group}",
+ "You unshared calendar {calendar} from group {group}" : "deixou de partilhar o calendário {calendar} do grupo {group}",
+ "{actor} unshared calendar {calendar} from group {group}" : "{actor} deixou de partilhar 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} in o calendário {calendar}",
+ "You created event {event} in calendar {calendar}" : "criou o evento {event} in o calendário {calendar}",
+ "{actor} deleted event {event} from calendar {calendar}" : "{actor} eliminou o evento {event} de o calendário {calendar}",
+ "You deleted event {event} from calendar {calendar}" : "eliminou o evento {event} de o calendário {calendar}",
+ "{actor} updated event {event} in calendar {calendar}" : "{actor} atualizou o evento {event} in o calendário {calendar}",
+ "You updated event {event} in calendar {calendar}" : "atualizou o evento {event} in o calendário {calendar}",
+ "{actor} moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "{actor} moveu o evento {event} de o calendário {sourceCalendar} para o calendário {targetCalendar}",
+ "You moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "moveu o evento {event} de o calendário {sourceCalendar} para o calendário {targetCalendar}",
+ "{actor} restored event {event} of calendar {calendar}" : "{actor} restaurou o evento {event} of o calendário {calendar}",
+ "You restored event {event} of calendar {calendar}" : "restaurou o evento {event} of o calendário {calendar}",
+ "Busy" : "Ocupado",
+ "{actor} created to-do {todo} in list {calendar}" : "{actor} criou to-do {todo} in list {calendar}",
+ "You created to-do {todo} in list {calendar}" : "criou to-do {todo} in list {calendar}",
+ "{actor} deleted to-do {todo} from list {calendar}" : "{actor} eliminou to-do {todo} de list {calendar}",
+ "You deleted to-do {todo} from list {calendar}" : "eliminou to-do {todo} de list {calendar}",
+ "{actor} updated to-do {todo} in list {calendar}" : "{actor} atualizou to-do {todo} in list {calendar}",
+ "You updated to-do {todo} in list {calendar}" : "atualizou to-do {todo} in list {calendar}",
+ "{actor} solved to-do {todo} in list {calendar}" : "{actor} concluiu a tarefa {todo} na lista {calendar}",
+ "You solved to-do {todo} in list {calendar}" : "solved to-do {todo} in list {calendar}",
+ "{actor} reopened to-do {todo} in list {calendar}" : "{actor} reabriu a tarefa {todo} na lista {calendar}",
+ "You reopened to-do {todo} in list {calendar}" : "reopened to-do {todo} in list {calendar}",
+ "{actor} moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}" : "{actor} moveu to-do {todo} de list {sourceCalendar} para list {targetCalendar}",
+ "You moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}" : "moveu to-do {todo} de list {sourceCalendar} para list {targetCalendar}",
+ "Calendar, contacts and tasks" : "Calendário, contactos e tarefas",
+ "A <strong>calendar</strong> was modified" : "O <strong>calendário</strong> foi modificado.",
+ "A calendar <strong>event</strong> was modified" : "Um <strong>event</strong> do calendário foi modificado",
+ "A calendar <strong>to-do</strong> was modified" : "Foi modificada uma <strong>tarefa</strong> do calendário",
+ "Contact birthdays" : "Aniversário dos contactos",
+ "Death of %s" : "Falecimento de %s",
+ "Untitled calendar" : "Calendário sem titulo",
+ "Calendar:" : "Calendário:",
+ "Date:" : "Data:",
+ "Where:" : "Local:",
+ "Description:" : "Descrição:",
+ "_%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",
+ "Date: %s" : "Data: %s",
+ "Description: %s" : "Descrição: %s",
+ "Where: %s" : "Local: %s",
+ "%1$s via %2$s" : "%1$s via %2$s",
+ "In the past on %1$s for the entire day" : "No passado em %1$s durante todo o dia",
+ "_In a minute on %1$s for the entire day_::_In %n minutes on %1$s for the entire day_" : ["Daqui a um minuto em %1$s para todo o dia","Daqui a %n minutos em %1$s para todo o dia","Daqui a %n minutos em %1$s para todo o dia"],
+ "_In a hour on %1$s for the entire day_::_In %n hours on %1$s for the entire day_" : ["Daqui a um hora em %1$s para todo o dia","Daqui a %n horas em %1$s para todo o dia","Daqui a %n horas em %1$s para todo o dia"],
+ "_In a day on %1$s for the entire day_::_In %n days on %1$s for the entire day_" : ["Daqui a um dia em %1$s para todo o dia","Daqui a %n dias em %1$s para todo o dia","Daqui a %n dias em %1$s para todo o dia"],
+ "_In a week on %1$s for the entire day_::_In %n weeks on %1$s for the entire day_" : ["Daqui a um semana em %1$s para todo o dia","Daqui a %n semanas em %1$s para todo o dia","Daqui a %n semanas em %1$s para todo o dia"],
+ "_In a month on %1$s for the entire day_::_In %n months on %1$s for the entire day_" : ["Daqui a um mês em %1$s para todo o dia","Daqui a %n meses em %1$s para todo o dia","Daqui a %n meses em %1$s para todo o dia"],
+ "_In a year on %1$s for the entire day_::_In %n years on %1$s for the entire day_" : ["Daqui a um ano em %1$s para todo o dia","Daqui a %n anos em %1$s para todo o dia","Daqui a %n anos em %1$s para todo o dia"],
+ "In the past on %1$s between %2$s - %3$s" : "No passado em %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_" : ["Daqui a um minuto em %1$s entre %2$s - %3$s","Daqui a %n minutos em %1$s entre %2$s - %3$s","Daqui a %n minutos em %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_" : ["Daqui a um hora em %1$s entre %2$s - %3$s","Daqui a %n horas em %1$s entre %2$s - %3$s","Daqui a %n horas em %1$s entre %2$s - %3$s"],
+ "_In a day on %1$s between %2$s - %3$s_::_In %n days on %1$s between %2$s - %3$s_" : ["Daqui a um dia em %1$s entre %2$s - %3$s","Daqui a %n dias em %1$s entre %2$s - %3$s","Daqui a %n dias em %1$s entre %2$s - %3$s"],
+ "_In a week on %1$s between %2$s - %3$s_::_In %n weeks on %1$s between %2$s - %3$s_" : ["Daqui a um semana em %1$s entre %2$s - %3$s","Daqui a %n semanas em %1$s entre %2$s - %3$s","Daqui a %n semanas em %1$s entre %2$s - %3$s"],
+ "_In a month on %1$s between %2$s - %3$s_::_In %n months on %1$s between %2$s - %3$s_" : ["Daqui a um mês em %1$s entre %2$s - %3$s","Daqui a %n meses em %1$s entre %2$s - %3$s","Daqui a %n meses em %1$s entre %2$s - %3$s"],
+ "_In a year on %1$s between %2$s - %3$s_::_In %n years on %1$s between %2$s - %3$s_" : ["Daqui a um ano em %1$s entre %2$s - %3$s","Daqui a %n anos em %1$s entre %2$s - %3$s","Daqui a %n anos em %1$s entre %2$s - %3$s"],
+ "Could not generate when statement" : "Não foi possível gerar a expressão \"quando\"",
+ "Every Day for the entire day" : "Todos os dias, dia inteiro",
+ "Every Day for the entire day until %1$s" : "Todos os dias, dia inteiro até %1$s",
+ "Every Day between %1$s - %2$s" : "Todos os dias entre %1$s e %2$s",
+ "Every Day between %1$s - %2$s until %3$s" : "Todos os dias entre %1$s e %2$s até %3$s",
+ "Every %1$d Days for the entire day" : "A cada %1$d dias, dia inteiro",
+ "Every %1$d Days for the entire day until %2$s" : "A cada %1$d dias, dia inteiro até %2$s",
+ "Every %1$d Days between %2$s - %3$s" : "A cada %1$d dias entre %2$s e %3$s",
+ "Every %1$d Days between %2$s - %3$s until %4$s" : "A cada %1$d dias entre %2$s e %3$s até %4$s",
+ "Could not generate event recurrence statement" : "Não foi possível gerar a expressão de recorrência do evento",
+ "Every Week on %1$s for the entire day" : "Todas as semanas, em %1$s, dia inteiro",
+ "Every Week on %1$s for the entire day until %2$s" : "Todas as semanas, em %1$s, dia inteiro até %2$s",
+ "Every Week on %1$s between %2$s - %3$s" : "Todas as semanas, em %1$s entre %2$s e %3$s",
+ "Every Week on %1$s between %2$s - %3$s until %4$s" : "Todas as semanas, em %1$s entre %2$s e %3$s até %4$s",
+ "Every %1$d Weeks on %2$s for the entire day" : "A cada %1$d semanas, em %2$s, dia inteiro",
+ "Every %1$d Weeks on %2$s for the entire day until %3$s" : "A cada %1$d semanas, em %2$s, dia inteiro até %3$s",
+ "Every %1$d Weeks on %2$s between %3$s - %4$s" : "A cada %1$d semanas, em %2$s entre %3$s e %4$s",
+ "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "A cada %1$d semanas, em %2$s entre %3$s e %4$s até %5$s",
+ "Every Month on the %1$s for the entire day" : "Todos os meses, no dia %1$s, dia inteiro",
+ "Every Month on the %1$s for the entire day until %2$s" : "Todos os meses, no dia %1$s, dia inteiro até %2$s",
+ "Every Month on the %1$s between %2$s - %3$s" : "Todos os meses, no dia %1$s entre %2$s e %3$s",
+ "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Todos os meses, no dia %1$s entre %2$s e %3$s até %4$s",
+ "Every %1$d Months on the %2$s for the entire day" : "A cada %1$d meses, no dia %2$s, dia inteiro",
+ "Every %1$d Months on the %2$s for the entire day until %3$s" : "A cada %1$d meses, no dia %2$s, dia inteiro até %3$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s" : "A cada %1$d meses, no dia %2$s entre %3$s e %4$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "A cada %1$d meses, no dia %2$s entre %3$s e %4$s até %5$s",
+ "Every Year in %1$s on the %2$s for the entire day" : "Todos os anos em %1$s, no dia %2$s, dia inteiro",
+ "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Todos os anos em %1$s, no dia %2$s, dia inteiro até %3$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Todos os anos em %1$s, no dia %2$s entre %3$s e %4$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Todos os anos em %1$s, no dia %2$s entre %3$s e %4$s até %5$s",
+ "Every %1$d Years in %2$s on the %3$s for the entire day" : "A cada %1$d anos em %2$s, no dia %3$s, dia inteiro",
+ "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "A cada %1$d anos em %2$s, no dia %3$s, dia inteiro até %4$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "A cada %1$d anos em %2$s, no dia %3$s entre %4$s e %5$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "A cada %1$d anos em %2$s, no dia %3$s entre %4$s e %5$s até %6$s",
+ "On specific dates for the entire day until %1$s" : "Em datas específicas, dia inteiro até %1$s",
+ "On specific dates between %1$s - %2$s until %3$s" : "Em datas específicas entre %1$s e %2$s até %3$s",
+ "In the past on %1$s" : "No passado em %1$s",
+ "_In a minute on %1$s_::_In %n minutes on %1$s_" : ["Daqui a um minuto em %1$s","Daqui a %n minutos em %1$s","Daqui a %n minutos em %1$s"],
+ "_In a hour on %1$s_::_In %n hours on %1$s_" : ["Daqui a um hora em %1$s","Daqui a %n horas em %1$s","Daqui a %n horas em %1$s"],
+ "_In a day on %1$s_::_In %n days on %1$s_" : ["Daqui a um dia em %1$s","Daqui a %n dias em %1$s","Daqui a %n dias em %1$s"],
+ "_In a week on %1$s_::_In %n weeks on %1$s_" : ["Daqui a um semana em %1$s","Daqui a %n semanas em %1$s","Daqui a %n semanas em %1$s"],
+ "_In a month on %1$s_::_In %n months on %1$s_" : ["Daqui a um mês em %1$s","Daqui a %n meses em %1$s","Daqui a %n meses em %1$s"],
+ "_In a year on %1$s_::_In %n years on %1$s_" : ["Daqui a um ano em %1$s","Daqui a %n anos em %1$s","Daqui a %n anos em %1$s"],
+ "In the past on %1$s then on %2$s" : "No passado em %1$s e depois %2$s",
+ "_In a minute on %1$s then on %2$s_::_In %n minutes on %1$s then on %2$s_" : ["Daqui a um minuto em %1$s e depois em %2$s","Daqui a %n minutos em %1$s e depois em %2$s","Daqui a %n minutos em %1$s e depois em %2$s"],
+ "_In a hour on %1$s then on %2$s_::_In %n hours on %1$s then on %2$s_" : ["Daqui a um hora em %1$s e depois em %2$s","Daqui a %n horas em %1$s e depois em %2$s","Daqui a %n horas em %1$s e depois em %2$s"],
+ "_In a day on %1$s then on %2$s_::_In %n days on %1$s then on %2$s_" : ["Daqui a um dia em %1$s e depois em %2$s","Daqui a %n dias em %1$s e depois em %2$s","Daqui a %n dias em %1$s e depois em %2$s"],
+ "_In a week on %1$s then on %2$s_::_In %n weeks on %1$s then on %2$s_" : ["Daqui a um semana em %1$s e depois em %2$s","Daqui a %n semanas em %1$s e depois em %2$s","Daqui a %n semanas em %1$s e depois em %2$s"],
+ "_In a month on %1$s then on %2$s_::_In %n months on %1$s then on %2$s_" : ["Daqui a um mês em %1$s e depois em %2$s","Daqui a %n meses em %1$s e depois em %2$s","Daqui a %n meses em %1$s e depois em %2$s"],
+ "_In a year on %1$s then on %2$s_::_In %n years on %1$s then on %2$s_" : ["Daqui a um ano em %1$s e depois em %2$s","Daqui a %n anos em %1$s e depois em %2$s","Daqui a %n anos em %1$s e depois em %2$s"],
+ "In the past on %1$s then on %2$s and %3$s" : "No passado em %1$s e depois em %2$s e %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_" : ["Daqui a um minuto em %1$s e depois em %2$s e %3$s","Daqui a %n minutos em %1$s e depois em %2$s e %3$s","Daqui a %n minutos em %1$s e depois em %2$s e %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_" : ["Daqui a um hora em %1$s e depois em %2$s e %3$s","Daqui a %n horas em %1$s e depois em %2$s e %3$s","Daqui a %n horas em %1$s e depois em %2$s e %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_" : ["Daqui a um dia em %1$s e depois em %2$s e %3$s","Daqui a %n dias em %1$s e depois em %2$s e %3$s","Daqui a %n dias em %1$s e depois em %2$s e %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_" : ["Daqui a um semana em %1$s e depois em %2$s e %3$s","Daqui a %n semanas em %1$s e depois em %2$s e %3$s","Daqui a %n semanas em %1$s e depois em %2$s e %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_" : ["Daqui a um mês em %1$s e depois em %2$s e %3$s","Daqui a %n meses em %1$s e depois em %2$s e %3$s","Daqui a %n meses em %1$s e depois em %2$s e %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_" : ["Daqui a um ano em %1$s e depois em %2$s e %3$s","Daqui a %n anos em %1$s e depois em %2$s e %3$s","Daqui a %n anos em %1$s e depois em %2$s e %3$s"],
+ "Could not generate next recurrence statement" : "Não foi possível gerar a próxima expressão de recorrência",
+ "Cancelled: %1$s" : "Cancelado: %1$s",
+ "\"%1$s\" has been canceled" : "\"%1$s\" foi cancelado",
+ "Re: %1$s" : "Re: %1$s",
+ "%1$s has accepted your invitation" : "%1$s aceitou o seu convite",
+ "%1$s has tentatively accepted your invitation" : "%1$s aceitou provisoriamente o seu convite",
+ "%1$s has declined your invitation" : "%1$s recusou o seu convite",
+ "%1$s has responded to your invitation" : "%1$s respondeu ao seu convite",
+ "Invitation updated: %1$s" : "Convite atualizado: %1$s",
+ "%1$s updated the event \"%2$s\"" : "%1$s atualizou o evento \"%2$s\"",
+ "Invitation: %1$s" : "Convite: %1$s",
+ "%1$s would like to invite you to \"%2$s\"" : "%1$s gostaria de convidá‑lo para \"%2$s\"",
+ "Organizer:" : "Organizador:",
+ "Attendees:" : "Participantes:",
+ "Title:" : "Titulo: ",
+ "When:" : "Quando:",
+ "Location:" : "Localização:",
+ "Link:" : "Ligação:",
+ "Occurring:" : "Ocorrências:",
+ "Accept" : "Aceitar",
+ "Decline" : "Recusar",
+ "More options …" : "Mais opções…",
+ "More options at %s" : "Mais opções em %s",
+ "Monday" : "Segunda",
+ "Tuesday" : "Terça",
+ "Wednesday" : "Quarta",
+ "Thursday" : "Quinta",
+ "Friday" : "Sexta",
+ "Saturday" : "Sábado",
+ "Sunday" : "Domingo",
+ "January" : "Janeiro",
+ "February" : "Fevereiro",
+ "March" : "Março",
+ "April" : "Abril",
+ "May" : "Maio",
+ "June" : "Junho",
+ "July" : "Julho",
+ "August" : "Agosto",
+ "September" : "Setembro",
+ "October" : "Outubro",
+ "November" : "Novembro",
+ "December" : "Dezembro",
+ "First" : "Primeiro",
+ "Second" : "Segundo",
+ "Third" : "Terceiro",
+ "Fourth" : "Quarto",
+ "Fifth" : "Quinto",
+ "Last" : "Último",
+ "Second Last" : "Penúltimo",
+ "Third Last" : "Antepenúltimo",
+ "Fourth Last" : "Quarto do fim",
+ "Fifth Last" : "Quinto do fim",
+ "Contacts" : "Contactos",
+ "{actor} created address book {addressbook}" : "{actor} criou address book {addressbook}",
+ "You created address book {addressbook}" : "criou address book {addressbook}",
+ "{actor} deleted address book {addressbook}" : "{actor} eliminou address book {addressbook}",
+ "You deleted address book {addressbook}" : "eliminou address book {addressbook}",
+ "{actor} updated address book {addressbook}" : "{actor} atualizou address book {addressbook}",
+ "You updated address book {addressbook}" : "atualizou address book {addressbook}",
+ "{actor} shared address book {addressbook} with you" : "{actor} partilhou address book {addressbook} com you",
+ "You shared address book {addressbook} with {user}" : "partilhou address book {addressbook} com {user}",
+ "{actor} shared address book {addressbook} with {user}" : "{actor} partilhou address book {addressbook} com {user}",
+ "{actor} unshared address book {addressbook} from you" : "{actor} deixou de partilhar address book {addressbook} de you",
+ "You unshared address book {addressbook} from {user}" : "deixou de partilhar address book {addressbook} de {user}",
+ "{actor} unshared address book {addressbook} from {user}" : "{actor} deixou de partilhar address book {addressbook} de {user}",
+ "{actor} unshared address book {addressbook} from themselves" : "{actor} deixou de partilhar address book {addressbook} de próprio",
+ "You shared address book {addressbook} with group {group}" : "partilhou address book {addressbook} com o grupo {group}",
+ "{actor} shared address book {addressbook} with group {group}" : "{actor} partilhou address book {addressbook} com o grupo {group}",
+ "You unshared address book {addressbook} from group {group}" : "deixou de partilhar address book {addressbook} do grupo {group}",
+ "{actor} unshared address book {addressbook} from group {group}" : "{actor} deixou de partilhar address book {addressbook} do grupo {group}",
+ "{actor} created contact {card} in address book {addressbook}" : "{actor} criou contact {card} in address book {addressbook}",
+ "You created contact {card} in address book {addressbook}" : "criou contact {card} in address book {addressbook}",
+ "{actor} deleted contact {card} from address book {addressbook}" : "{actor} eliminou contact {card} de address book {addressbook}",
+ "You deleted contact {card} from address book {addressbook}" : "eliminou contact {card} de address book {addressbook}",
+ "{actor} updated contact {card} in address book {addressbook}" : "{actor} atualizou contact {card} in address book {addressbook}",
+ "You updated contact {card} in address book {addressbook}" : "atualizou contact {card} in address book {addressbook}",
+ "A <strong>contact</strong> or <strong>address book</strong> was modified" : "Foi modificado um <strong>contacto</strong> ou <strong>livro de endereços</strong>",
+ "Accounts" : "Contas",
+ "System address book which holds all accounts" : "Livro de endereços do sistema que contém todas as contas",
+ "File is not updatable: %1$s" : "O ficheiro não pode ser atualizado: %1$s",
+ "Failed to get storage for file" : "Falha ao obter armazenamento para o ficheiro",
+ "Could not write to final file, canceled by hook" : "Não foi possível escrever no ficheiro final, cancelado por hook",
+ "Could not write file contents" : "Não foi possível escrever o conteúdo do ficheiro",
+ "_%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 ficheiro para o destino (copiado: %1$s, tamanho 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 esperado de %1$s, mas leitura diferente (do cliente Nextcloud) e escreveu (para armazenamento Nextcloud) %2$s. Possível problema do lado do cliente ou ao escrever no armazenamento do servidor.",
+ "Could not rename part file to final file, canceled by hook" : "Não foi possível renomear o ficheiro parcial para ficheiro final, cancelado por hook",
+ "Could not rename part file to final file" : "Não foi possível renomear o ficheiro parcial para ficheiro final",
+ "Failed to check file size: %1$s" : "Falha ao verificar o tamanho do ficheiro: %1$s",
+ "Could not open file: %1$s, file does seem to exist" : "Não foi possível abrir o ficheiro: %1$s, o ficheiro parece existir",
+ "Could not open file: %1$s, file doesn't seem to exist" : "Não foi possível abrir o ficheiro: %1$s, o ficheiro não parece existir",
+ "Encryption not ready: %1$s" : "Encriptação não pronta: %1$s",
+ "Failed to open file: %1$s" : "Falha ao abrir o ficheiro: %1$s",
+ "Failed to unlink: %1$s" : "Falha ao eliminar: %1$s",
+ "Failed to write file contents: %1$s" : "Falha ao escrever o conteúdo do ficheiro: %1$s",
+ "File not found: %1$s" : "Ficheiro não encontrado: %1$s",
+ "Invalid target path" : "Caminho de destino inválido",
+ "System is in maintenance mode." : "O sistema está em modo de manutenção.",
+ "Upgrade needed" : "É necessária atualização",
+ "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "O seu %s precisa de estar configurado para usar HTTPS para que possa utilizar CalDAV e CardDAV com iOS/macOS.",
+ "Configures a CalDAV account" : "Configura uma conta CalDAV",
+ "Configures a CardDAV account" : "Configura uma conta CardDAV",
+ "Events" : "Eventos",
+ "Untitled task" : "Tarefa sem título",
+ "Completed on %s" : "Concluída em %s",
+ "Due on %s by %s" : "Vence em %s às %s",
+ "Due on %s" : "Vence em %s",
+ "System Address Book" : "Livro de endereços do sistema",
+ "The system address book contains contact information for all users in your instance." : "O livro de endereços do sistema contém informação de contacto de todos os utilizadores da sua instância.",
+ "Enable System Address Book" : "Ativar livro de endereços do sistema",
+ "DAV system address book" : "Livro de endereços DAV do sistema",
+ "No outstanding DAV system address book sync." : "Sem sincronizações pendentes do livro de endereços DAV do sistema.",
+ "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\"." : "A sincronização do livro de endereços DAV do sistema ainda não foi executada porque a sua instância não tem utilizadores; execute‑a manualmente com \"occ dav:sync-system-addressbook\".",
+ "WebDAV endpoint" : "Endpoint WebDAV",
+ "Could not check that your web server is properly set up to allow file synchronization over WebDAV. Please check manually." : "Não foi possível verificar se o seu servidor web está corretamente configurado para permitir a sincronização de ficheiros via WebDAV. Verifique manualmente.",
+ "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "O seu servidor da Web não está configurado corretamente para permitir a sincronização de ficheiros, porque a interface WebDAV parece estar com problemas.",
+ "Your web server is properly set up to allow file synchronization over WebDAV." : "O seu servidor web está corretamente configurado para permitir a sincronização de ficheiros via WebDAV.",
+ "Migrated calendar (%1$s)" : "Calendário migrado (%1$s)",
+ "Calendars including events, details and attendees" : "Calendários incluindo eventos, detalhes e participantes",
+ "Contacts and groups" : "Contactos e grupos",
+ "WebDAV" : "WebDAV",
+ "Absence saved" : "Ausência guardada",
+ "Failed to save your absence settings" : "Falha ao guardar as suas definições de ausência",
+ "Absence cleared" : "Ausência removida",
+ "Failed to clear your absence settings" : "Falha ao remover as suas definições de ausência",
+ "First day" : "Primeiro dia",
+ "Last day (inclusive)" : "Último dia (inclusive)",
+ "Out of office replacement (optional)" : "Substituto durante ausência (opcional)",
+ "Name of the replacement" : "Nome do substituto",
+ "No results." : "Sem resultados.",
+ "Start typing." : "Comece a escrever.",
+ "Short absence status" : "Estado de ausência curto",
+ "Long absence Message" : "Mensagem de ausência longa",
+ "Save" : "Guardar",
+ "Disable absence" : "Desativar ausência",
+ "Failed to load availability" : "Falha ao carregar disponibilidade",
+ "Saved availability" : "Disponibilidade guardada",
+ "Failed to save availability" : "Falha ao guardar disponibilidade",
+ "Time zone:" : "Fuso horário:",
+ "to" : "Para",
+ "Delete slot" : "Eliminar intervalo",
+ "No working hours set" : "Sem horário de trabalho definido",
+ "Add slot" : "Adicionar intervalo",
+ "Weekdays" : "Dias da semana",
+ "Pick a start time for {dayName}" : "Escolha uma hora de início para {dayName}",
+ "Pick a end time for {dayName}" : "Escolha uma hora de fim para {dayName}",
+ "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Definir automaticamente o estado para \"Não incomodar\" fora do horário de disponibilidade para silenciar todas as notificações.",
+ "Cancel" : "Cancelar",
+ "Import" : "Importar",
+ "Error while saving settings" : "Erro ao guardar definições",
+ "Contact reset successfully" : "Contacto reposto com sucesso",
+ "Error while resetting contact" : "Erro ao repor contacto",
+ "Contact imported successfully" : "Contacto importado com sucesso",
+ "Error while importing contact" : "Erro ao importar contacto",
+ "Import contact" : "Importar contacto",
+ "Reset to default" : "Repor original",
+ "Import contacts" : "Importar contactos",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "A importação de um novo ficheiro .vcf eliminará o contacto predefinido existente e substituí‑lo‑á pelo novo. Deseja continuar?",
+ "Failed to save example event creation setting" : "Falha ao guardar a definição de criação de evento de exemplo",
+ "Failed to upload the example event" : "Falha ao carregar o evento de exemplo",
+ "Custom example event was saved successfully" : "Evento de exemplo personalizado guardado com sucesso",
+ "Failed to delete the custom example event" : "Falha ao eliminar o evento de exemplo personalizado",
+ "Custom example event was deleted successfully" : "Evento de exemplo personalizado eliminado com sucesso",
+ "Import calendar event" : "Importar evento de calendário",
+ "Uploading a new event will overwrite the existing one." : "O carregamento de um novo evento substituirá o existente.",
+ "Upload event" : "Carregar evento",
+ "Availability" : "Disponibilidade",
+ "If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Se configurar o seu horário de trabalho, outras pessoas saberão quando está fora do escritório ao marcar uma reunião.",
+ "Absence" : "Ausência",
+ "Configure your next absence period." : "Configure o seu próximo período de ausência.",
+ "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Instale também a {calendarappstoreopen}aplicação Calendário {linkclose}, ou {calendardocopen} ligue o seu computador e telemóvel para sincronizar ↗{linkclose}.",
+ "Please make sure to properly set up {emailopen}the email server{linkclose}." : "Certifique‑se de configurar corretamente {emailopen}o servidor de email{linkclose}.",
+ "Calendar server" : "Servidor de calendário",
+ "Send invitations to attendees" : "Enviar convites aos participantes",
+ "Automatically generate a birthday calendar" : "Gerar automaticamente um calendário de aniversários",
+ "Birthday calendars will be generated by a background job." : "Os calendários de aniversário serão gerados por uma tarefa em segundo plano.",
+ "Hence they will not be available immediately after enabling but will show up after some time." : "Por isso, não estarão disponíveis imediatamente após a ativação, mas aparecerão após algum tempo.",
+ "Send notifications for events" : "Enviar notificações de eventos",
+ "Notifications are sent via background jobs, so these must occur often enough." : "As notificações são enviadas através de tarefas em segundo plano; estas devem ser executadas com frequência suficiente.",
+ "Send reminder notifications to calendar sharees as well" : "Enviar também notificações de lembrete aos partilhados do calendário",
+ "Reminders are always sent to organizers and attendees." : "Os lembretes são sempre enviados aos organizadores e participantes.",
+ "Enable notifications for events via push" : "Ativar notificações push para eventos",
+ "Example content" : "Conteúdo de exemplo",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "O conteúdo de exemplo serve para demonstrar as funcionalidades do Nextcloud. É fornecido com o Nextcloud e pode ser substituído por conteúdo personalizado.",
+ "There was an error updating your attendance status." : "Ocorreu um erro ao atualizar o seu estado de participação.",
+ "Please contact the organizer directly." : "Contacte diretamente o organizador.",
+ "Are you accepting the invitation?" : "Aceita o convite?",
+ "Tentative" : "Tentativa",
+ "Your attendance was updated successfully." : "O seu estado de participação foi atualizado com sucesso."
+},
+"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/dav/l10n/pt_PT.json b/apps/dav/l10n/pt_PT.json
new file mode 100644
index 00000000000..7120a7a8e96
--- /dev/null
+++ b/apps/dav/l10n/pt_PT.json
@@ -0,0 +1,334 @@
+{ "translations": {
+ "Calendar" : "Calendário",
+ "Tasks" : "Tarefas",
+ "Personal" : "Pessoal",
+ "{actor} created calendar {calendar}" : "{actor} criou o calendário {calendar}",
+ "You created calendar {calendar}" : "Criou o calendario {calendar}",
+ "{actor} deleted calendar {calendar}" : "{actor} apagou o calendário {calendar}",
+ "You deleted calendar {calendar}" : "Apagou o calendário {calendar}",
+ "{actor} updated calendar {calendar}" : "{actor} atualizou o calendário {calendar}",
+ "You updated calendar {calendar}" : "Atualizou o calendário {calendar}",
+ "{actor} restored calendar {calendar}" : "{actor} restaurou o calendário {calendar}",
+ "You restored calendar {calendar}" : "restaurou o calendário {calendar}",
+ "You shared calendar {calendar} as public link" : "Partilhou o calendário {calendar} como uma hiperligação pública",
+ "You removed public link for calendar {calendar}" : "Removeu uma hiperligação pública para o calendário {calendar}",
+ "{actor} shared calendar {calendar} with you" : "{actor} partilhou o calendário {calendar} consigo",
+ "You shared calendar {calendar} with {user}" : "Partilhou o calendário {calendar} com {user}",
+ "{actor} shared calendar {calendar} with {user}" : "{actor} partilhou o calendário {calendar} com {user}",
+ "{actor} unshared calendar {calendar} from you" : "{actor} retirou-lhe a partilha do calendário {calendar}",
+ "You unshared calendar {calendar} from {user}" : "Retirou a partilha do calendário {calendar} com {user}",
+ "{actor} unshared calendar {calendar} from {user}" : "{actor} retirou a partilha do calendário {calendar} com {user}",
+ "{actor} unshared calendar {calendar} from themselves" : "{actor} deixou de partilhar o calendário {calendar} de próprio",
+ "You shared calendar {calendar} with group {group}" : "partilhou o calendário {calendar} com o grupo {group}",
+ "{actor} shared calendar {calendar} with group {group}" : "{actor} partilhou o calendário {calendar} com o grupo {group}",
+ "You unshared calendar {calendar} from group {group}" : "deixou de partilhar o calendário {calendar} do grupo {group}",
+ "{actor} unshared calendar {calendar} from group {group}" : "{actor} deixou de partilhar 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} in o calendário {calendar}",
+ "You created event {event} in calendar {calendar}" : "criou o evento {event} in o calendário {calendar}",
+ "{actor} deleted event {event} from calendar {calendar}" : "{actor} eliminou o evento {event} de o calendário {calendar}",
+ "You deleted event {event} from calendar {calendar}" : "eliminou o evento {event} de o calendário {calendar}",
+ "{actor} updated event {event} in calendar {calendar}" : "{actor} atualizou o evento {event} in o calendário {calendar}",
+ "You updated event {event} in calendar {calendar}" : "atualizou o evento {event} in o calendário {calendar}",
+ "{actor} moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "{actor} moveu o evento {event} de o calendário {sourceCalendar} para o calendário {targetCalendar}",
+ "You moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "moveu o evento {event} de o calendário {sourceCalendar} para o calendário {targetCalendar}",
+ "{actor} restored event {event} of calendar {calendar}" : "{actor} restaurou o evento {event} of o calendário {calendar}",
+ "You restored event {event} of calendar {calendar}" : "restaurou o evento {event} of o calendário {calendar}",
+ "Busy" : "Ocupado",
+ "{actor} created to-do {todo} in list {calendar}" : "{actor} criou to-do {todo} in list {calendar}",
+ "You created to-do {todo} in list {calendar}" : "criou to-do {todo} in list {calendar}",
+ "{actor} deleted to-do {todo} from list {calendar}" : "{actor} eliminou to-do {todo} de list {calendar}",
+ "You deleted to-do {todo} from list {calendar}" : "eliminou to-do {todo} de list {calendar}",
+ "{actor} updated to-do {todo} in list {calendar}" : "{actor} atualizou to-do {todo} in list {calendar}",
+ "You updated to-do {todo} in list {calendar}" : "atualizou to-do {todo} in list {calendar}",
+ "{actor} solved to-do {todo} in list {calendar}" : "{actor} concluiu a tarefa {todo} na lista {calendar}",
+ "You solved to-do {todo} in list {calendar}" : "solved to-do {todo} in list {calendar}",
+ "{actor} reopened to-do {todo} in list {calendar}" : "{actor} reabriu a tarefa {todo} na lista {calendar}",
+ "You reopened to-do {todo} in list {calendar}" : "reopened to-do {todo} in list {calendar}",
+ "{actor} moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}" : "{actor} moveu to-do {todo} de list {sourceCalendar} para list {targetCalendar}",
+ "You moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}" : "moveu to-do {todo} de list {sourceCalendar} para list {targetCalendar}",
+ "Calendar, contacts and tasks" : "Calendário, contactos e tarefas",
+ "A <strong>calendar</strong> was modified" : "O <strong>calendário</strong> foi modificado.",
+ "A calendar <strong>event</strong> was modified" : "Um <strong>event</strong> do calendário foi modificado",
+ "A calendar <strong>to-do</strong> was modified" : "Foi modificada uma <strong>tarefa</strong> do calendário",
+ "Contact birthdays" : "Aniversário dos contactos",
+ "Death of %s" : "Falecimento de %s",
+ "Untitled calendar" : "Calendário sem titulo",
+ "Calendar:" : "Calendário:",
+ "Date:" : "Data:",
+ "Where:" : "Local:",
+ "Description:" : "Descrição:",
+ "_%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",
+ "Date: %s" : "Data: %s",
+ "Description: %s" : "Descrição: %s",
+ "Where: %s" : "Local: %s",
+ "%1$s via %2$s" : "%1$s via %2$s",
+ "In the past on %1$s for the entire day" : "No passado em %1$s durante todo o dia",
+ "_In a minute on %1$s for the entire day_::_In %n minutes on %1$s for the entire day_" : ["Daqui a um minuto em %1$s para todo o dia","Daqui a %n minutos em %1$s para todo o dia","Daqui a %n minutos em %1$s para todo o dia"],
+ "_In a hour on %1$s for the entire day_::_In %n hours on %1$s for the entire day_" : ["Daqui a um hora em %1$s para todo o dia","Daqui a %n horas em %1$s para todo o dia","Daqui a %n horas em %1$s para todo o dia"],
+ "_In a day on %1$s for the entire day_::_In %n days on %1$s for the entire day_" : ["Daqui a um dia em %1$s para todo o dia","Daqui a %n dias em %1$s para todo o dia","Daqui a %n dias em %1$s para todo o dia"],
+ "_In a week on %1$s for the entire day_::_In %n weeks on %1$s for the entire day_" : ["Daqui a um semana em %1$s para todo o dia","Daqui a %n semanas em %1$s para todo o dia","Daqui a %n semanas em %1$s para todo o dia"],
+ "_In a month on %1$s for the entire day_::_In %n months on %1$s for the entire day_" : ["Daqui a um mês em %1$s para todo o dia","Daqui a %n meses em %1$s para todo o dia","Daqui a %n meses em %1$s para todo o dia"],
+ "_In a year on %1$s for the entire day_::_In %n years on %1$s for the entire day_" : ["Daqui a um ano em %1$s para todo o dia","Daqui a %n anos em %1$s para todo o dia","Daqui a %n anos em %1$s para todo o dia"],
+ "In the past on %1$s between %2$s - %3$s" : "No passado em %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_" : ["Daqui a um minuto em %1$s entre %2$s - %3$s","Daqui a %n minutos em %1$s entre %2$s - %3$s","Daqui a %n minutos em %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_" : ["Daqui a um hora em %1$s entre %2$s - %3$s","Daqui a %n horas em %1$s entre %2$s - %3$s","Daqui a %n horas em %1$s entre %2$s - %3$s"],
+ "_In a day on %1$s between %2$s - %3$s_::_In %n days on %1$s between %2$s - %3$s_" : ["Daqui a um dia em %1$s entre %2$s - %3$s","Daqui a %n dias em %1$s entre %2$s - %3$s","Daqui a %n dias em %1$s entre %2$s - %3$s"],
+ "_In a week on %1$s between %2$s - %3$s_::_In %n weeks on %1$s between %2$s - %3$s_" : ["Daqui a um semana em %1$s entre %2$s - %3$s","Daqui a %n semanas em %1$s entre %2$s - %3$s","Daqui a %n semanas em %1$s entre %2$s - %3$s"],
+ "_In a month on %1$s between %2$s - %3$s_::_In %n months on %1$s between %2$s - %3$s_" : ["Daqui a um mês em %1$s entre %2$s - %3$s","Daqui a %n meses em %1$s entre %2$s - %3$s","Daqui a %n meses em %1$s entre %2$s - %3$s"],
+ "_In a year on %1$s between %2$s - %3$s_::_In %n years on %1$s between %2$s - %3$s_" : ["Daqui a um ano em %1$s entre %2$s - %3$s","Daqui a %n anos em %1$s entre %2$s - %3$s","Daqui a %n anos em %1$s entre %2$s - %3$s"],
+ "Could not generate when statement" : "Não foi possível gerar a expressão \"quando\"",
+ "Every Day for the entire day" : "Todos os dias, dia inteiro",
+ "Every Day for the entire day until %1$s" : "Todos os dias, dia inteiro até %1$s",
+ "Every Day between %1$s - %2$s" : "Todos os dias entre %1$s e %2$s",
+ "Every Day between %1$s - %2$s until %3$s" : "Todos os dias entre %1$s e %2$s até %3$s",
+ "Every %1$d Days for the entire day" : "A cada %1$d dias, dia inteiro",
+ "Every %1$d Days for the entire day until %2$s" : "A cada %1$d dias, dia inteiro até %2$s",
+ "Every %1$d Days between %2$s - %3$s" : "A cada %1$d dias entre %2$s e %3$s",
+ "Every %1$d Days between %2$s - %3$s until %4$s" : "A cada %1$d dias entre %2$s e %3$s até %4$s",
+ "Could not generate event recurrence statement" : "Não foi possível gerar a expressão de recorrência do evento",
+ "Every Week on %1$s for the entire day" : "Todas as semanas, em %1$s, dia inteiro",
+ "Every Week on %1$s for the entire day until %2$s" : "Todas as semanas, em %1$s, dia inteiro até %2$s",
+ "Every Week on %1$s between %2$s - %3$s" : "Todas as semanas, em %1$s entre %2$s e %3$s",
+ "Every Week on %1$s between %2$s - %3$s until %4$s" : "Todas as semanas, em %1$s entre %2$s e %3$s até %4$s",
+ "Every %1$d Weeks on %2$s for the entire day" : "A cada %1$d semanas, em %2$s, dia inteiro",
+ "Every %1$d Weeks on %2$s for the entire day until %3$s" : "A cada %1$d semanas, em %2$s, dia inteiro até %3$s",
+ "Every %1$d Weeks on %2$s between %3$s - %4$s" : "A cada %1$d semanas, em %2$s entre %3$s e %4$s",
+ "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "A cada %1$d semanas, em %2$s entre %3$s e %4$s até %5$s",
+ "Every Month on the %1$s for the entire day" : "Todos os meses, no dia %1$s, dia inteiro",
+ "Every Month on the %1$s for the entire day until %2$s" : "Todos os meses, no dia %1$s, dia inteiro até %2$s",
+ "Every Month on the %1$s between %2$s - %3$s" : "Todos os meses, no dia %1$s entre %2$s e %3$s",
+ "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Todos os meses, no dia %1$s entre %2$s e %3$s até %4$s",
+ "Every %1$d Months on the %2$s for the entire day" : "A cada %1$d meses, no dia %2$s, dia inteiro",
+ "Every %1$d Months on the %2$s for the entire day until %3$s" : "A cada %1$d meses, no dia %2$s, dia inteiro até %3$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s" : "A cada %1$d meses, no dia %2$s entre %3$s e %4$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "A cada %1$d meses, no dia %2$s entre %3$s e %4$s até %5$s",
+ "Every Year in %1$s on the %2$s for the entire day" : "Todos os anos em %1$s, no dia %2$s, dia inteiro",
+ "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Todos os anos em %1$s, no dia %2$s, dia inteiro até %3$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Todos os anos em %1$s, no dia %2$s entre %3$s e %4$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Todos os anos em %1$s, no dia %2$s entre %3$s e %4$s até %5$s",
+ "Every %1$d Years in %2$s on the %3$s for the entire day" : "A cada %1$d anos em %2$s, no dia %3$s, dia inteiro",
+ "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "A cada %1$d anos em %2$s, no dia %3$s, dia inteiro até %4$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "A cada %1$d anos em %2$s, no dia %3$s entre %4$s e %5$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "A cada %1$d anos em %2$s, no dia %3$s entre %4$s e %5$s até %6$s",
+ "On specific dates for the entire day until %1$s" : "Em datas específicas, dia inteiro até %1$s",
+ "On specific dates between %1$s - %2$s until %3$s" : "Em datas específicas entre %1$s e %2$s até %3$s",
+ "In the past on %1$s" : "No passado em %1$s",
+ "_In a minute on %1$s_::_In %n minutes on %1$s_" : ["Daqui a um minuto em %1$s","Daqui a %n minutos em %1$s","Daqui a %n minutos em %1$s"],
+ "_In a hour on %1$s_::_In %n hours on %1$s_" : ["Daqui a um hora em %1$s","Daqui a %n horas em %1$s","Daqui a %n horas em %1$s"],
+ "_In a day on %1$s_::_In %n days on %1$s_" : ["Daqui a um dia em %1$s","Daqui a %n dias em %1$s","Daqui a %n dias em %1$s"],
+ "_In a week on %1$s_::_In %n weeks on %1$s_" : ["Daqui a um semana em %1$s","Daqui a %n semanas em %1$s","Daqui a %n semanas em %1$s"],
+ "_In a month on %1$s_::_In %n months on %1$s_" : ["Daqui a um mês em %1$s","Daqui a %n meses em %1$s","Daqui a %n meses em %1$s"],
+ "_In a year on %1$s_::_In %n years on %1$s_" : ["Daqui a um ano em %1$s","Daqui a %n anos em %1$s","Daqui a %n anos em %1$s"],
+ "In the past on %1$s then on %2$s" : "No passado em %1$s e depois %2$s",
+ "_In a minute on %1$s then on %2$s_::_In %n minutes on %1$s then on %2$s_" : ["Daqui a um minuto em %1$s e depois em %2$s","Daqui a %n minutos em %1$s e depois em %2$s","Daqui a %n minutos em %1$s e depois em %2$s"],
+ "_In a hour on %1$s then on %2$s_::_In %n hours on %1$s then on %2$s_" : ["Daqui a um hora em %1$s e depois em %2$s","Daqui a %n horas em %1$s e depois em %2$s","Daqui a %n horas em %1$s e depois em %2$s"],
+ "_In a day on %1$s then on %2$s_::_In %n days on %1$s then on %2$s_" : ["Daqui a um dia em %1$s e depois em %2$s","Daqui a %n dias em %1$s e depois em %2$s","Daqui a %n dias em %1$s e depois em %2$s"],
+ "_In a week on %1$s then on %2$s_::_In %n weeks on %1$s then on %2$s_" : ["Daqui a um semana em %1$s e depois em %2$s","Daqui a %n semanas em %1$s e depois em %2$s","Daqui a %n semanas em %1$s e depois em %2$s"],
+ "_In a month on %1$s then on %2$s_::_In %n months on %1$s then on %2$s_" : ["Daqui a um mês em %1$s e depois em %2$s","Daqui a %n meses em %1$s e depois em %2$s","Daqui a %n meses em %1$s e depois em %2$s"],
+ "_In a year on %1$s then on %2$s_::_In %n years on %1$s then on %2$s_" : ["Daqui a um ano em %1$s e depois em %2$s","Daqui a %n anos em %1$s e depois em %2$s","Daqui a %n anos em %1$s e depois em %2$s"],
+ "In the past on %1$s then on %2$s and %3$s" : "No passado em %1$s e depois em %2$s e %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_" : ["Daqui a um minuto em %1$s e depois em %2$s e %3$s","Daqui a %n minutos em %1$s e depois em %2$s e %3$s","Daqui a %n minutos em %1$s e depois em %2$s e %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_" : ["Daqui a um hora em %1$s e depois em %2$s e %3$s","Daqui a %n horas em %1$s e depois em %2$s e %3$s","Daqui a %n horas em %1$s e depois em %2$s e %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_" : ["Daqui a um dia em %1$s e depois em %2$s e %3$s","Daqui a %n dias em %1$s e depois em %2$s e %3$s","Daqui a %n dias em %1$s e depois em %2$s e %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_" : ["Daqui a um semana em %1$s e depois em %2$s e %3$s","Daqui a %n semanas em %1$s e depois em %2$s e %3$s","Daqui a %n semanas em %1$s e depois em %2$s e %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_" : ["Daqui a um mês em %1$s e depois em %2$s e %3$s","Daqui a %n meses em %1$s e depois em %2$s e %3$s","Daqui a %n meses em %1$s e depois em %2$s e %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_" : ["Daqui a um ano em %1$s e depois em %2$s e %3$s","Daqui a %n anos em %1$s e depois em %2$s e %3$s","Daqui a %n anos em %1$s e depois em %2$s e %3$s"],
+ "Could not generate next recurrence statement" : "Não foi possível gerar a próxima expressão de recorrência",
+ "Cancelled: %1$s" : "Cancelado: %1$s",
+ "\"%1$s\" has been canceled" : "\"%1$s\" foi cancelado",
+ "Re: %1$s" : "Re: %1$s",
+ "%1$s has accepted your invitation" : "%1$s aceitou o seu convite",
+ "%1$s has tentatively accepted your invitation" : "%1$s aceitou provisoriamente o seu convite",
+ "%1$s has declined your invitation" : "%1$s recusou o seu convite",
+ "%1$s has responded to your invitation" : "%1$s respondeu ao seu convite",
+ "Invitation updated: %1$s" : "Convite atualizado: %1$s",
+ "%1$s updated the event \"%2$s\"" : "%1$s atualizou o evento \"%2$s\"",
+ "Invitation: %1$s" : "Convite: %1$s",
+ "%1$s would like to invite you to \"%2$s\"" : "%1$s gostaria de convidá‑lo para \"%2$s\"",
+ "Organizer:" : "Organizador:",
+ "Attendees:" : "Participantes:",
+ "Title:" : "Titulo: ",
+ "When:" : "Quando:",
+ "Location:" : "Localização:",
+ "Link:" : "Ligação:",
+ "Occurring:" : "Ocorrências:",
+ "Accept" : "Aceitar",
+ "Decline" : "Recusar",
+ "More options …" : "Mais opções…",
+ "More options at %s" : "Mais opções em %s",
+ "Monday" : "Segunda",
+ "Tuesday" : "Terça",
+ "Wednesday" : "Quarta",
+ "Thursday" : "Quinta",
+ "Friday" : "Sexta",
+ "Saturday" : "Sábado",
+ "Sunday" : "Domingo",
+ "January" : "Janeiro",
+ "February" : "Fevereiro",
+ "March" : "Março",
+ "April" : "Abril",
+ "May" : "Maio",
+ "June" : "Junho",
+ "July" : "Julho",
+ "August" : "Agosto",
+ "September" : "Setembro",
+ "October" : "Outubro",
+ "November" : "Novembro",
+ "December" : "Dezembro",
+ "First" : "Primeiro",
+ "Second" : "Segundo",
+ "Third" : "Terceiro",
+ "Fourth" : "Quarto",
+ "Fifth" : "Quinto",
+ "Last" : "Último",
+ "Second Last" : "Penúltimo",
+ "Third Last" : "Antepenúltimo",
+ "Fourth Last" : "Quarto do fim",
+ "Fifth Last" : "Quinto do fim",
+ "Contacts" : "Contactos",
+ "{actor} created address book {addressbook}" : "{actor} criou address book {addressbook}",
+ "You created address book {addressbook}" : "criou address book {addressbook}",
+ "{actor} deleted address book {addressbook}" : "{actor} eliminou address book {addressbook}",
+ "You deleted address book {addressbook}" : "eliminou address book {addressbook}",
+ "{actor} updated address book {addressbook}" : "{actor} atualizou address book {addressbook}",
+ "You updated address book {addressbook}" : "atualizou address book {addressbook}",
+ "{actor} shared address book {addressbook} with you" : "{actor} partilhou address book {addressbook} com you",
+ "You shared address book {addressbook} with {user}" : "partilhou address book {addressbook} com {user}",
+ "{actor} shared address book {addressbook} with {user}" : "{actor} partilhou address book {addressbook} com {user}",
+ "{actor} unshared address book {addressbook} from you" : "{actor} deixou de partilhar address book {addressbook} de you",
+ "You unshared address book {addressbook} from {user}" : "deixou de partilhar address book {addressbook} de {user}",
+ "{actor} unshared address book {addressbook} from {user}" : "{actor} deixou de partilhar address book {addressbook} de {user}",
+ "{actor} unshared address book {addressbook} from themselves" : "{actor} deixou de partilhar address book {addressbook} de próprio",
+ "You shared address book {addressbook} with group {group}" : "partilhou address book {addressbook} com o grupo {group}",
+ "{actor} shared address book {addressbook} with group {group}" : "{actor} partilhou address book {addressbook} com o grupo {group}",
+ "You unshared address book {addressbook} from group {group}" : "deixou de partilhar address book {addressbook} do grupo {group}",
+ "{actor} unshared address book {addressbook} from group {group}" : "{actor} deixou de partilhar address book {addressbook} do grupo {group}",
+ "{actor} created contact {card} in address book {addressbook}" : "{actor} criou contact {card} in address book {addressbook}",
+ "You created contact {card} in address book {addressbook}" : "criou contact {card} in address book {addressbook}",
+ "{actor} deleted contact {card} from address book {addressbook}" : "{actor} eliminou contact {card} de address book {addressbook}",
+ "You deleted contact {card} from address book {addressbook}" : "eliminou contact {card} de address book {addressbook}",
+ "{actor} updated contact {card} in address book {addressbook}" : "{actor} atualizou contact {card} in address book {addressbook}",
+ "You updated contact {card} in address book {addressbook}" : "atualizou contact {card} in address book {addressbook}",
+ "A <strong>contact</strong> or <strong>address book</strong> was modified" : "Foi modificado um <strong>contacto</strong> ou <strong>livro de endereços</strong>",
+ "Accounts" : "Contas",
+ "System address book which holds all accounts" : "Livro de endereços do sistema que contém todas as contas",
+ "File is not updatable: %1$s" : "O ficheiro não pode ser atualizado: %1$s",
+ "Failed to get storage for file" : "Falha ao obter armazenamento para o ficheiro",
+ "Could not write to final file, canceled by hook" : "Não foi possível escrever no ficheiro final, cancelado por hook",
+ "Could not write file contents" : "Não foi possível escrever o conteúdo do ficheiro",
+ "_%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 ficheiro para o destino (copiado: %1$s, tamanho 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 esperado de %1$s, mas leitura diferente (do cliente Nextcloud) e escreveu (para armazenamento Nextcloud) %2$s. Possível problema do lado do cliente ou ao escrever no armazenamento do servidor.",
+ "Could not rename part file to final file, canceled by hook" : "Não foi possível renomear o ficheiro parcial para ficheiro final, cancelado por hook",
+ "Could not rename part file to final file" : "Não foi possível renomear o ficheiro parcial para ficheiro final",
+ "Failed to check file size: %1$s" : "Falha ao verificar o tamanho do ficheiro: %1$s",
+ "Could not open file: %1$s, file does seem to exist" : "Não foi possível abrir o ficheiro: %1$s, o ficheiro parece existir",
+ "Could not open file: %1$s, file doesn't seem to exist" : "Não foi possível abrir o ficheiro: %1$s, o ficheiro não parece existir",
+ "Encryption not ready: %1$s" : "Encriptação não pronta: %1$s",
+ "Failed to open file: %1$s" : "Falha ao abrir o ficheiro: %1$s",
+ "Failed to unlink: %1$s" : "Falha ao eliminar: %1$s",
+ "Failed to write file contents: %1$s" : "Falha ao escrever o conteúdo do ficheiro: %1$s",
+ "File not found: %1$s" : "Ficheiro não encontrado: %1$s",
+ "Invalid target path" : "Caminho de destino inválido",
+ "System is in maintenance mode." : "O sistema está em modo de manutenção.",
+ "Upgrade needed" : "É necessária atualização",
+ "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "O seu %s precisa de estar configurado para usar HTTPS para que possa utilizar CalDAV e CardDAV com iOS/macOS.",
+ "Configures a CalDAV account" : "Configura uma conta CalDAV",
+ "Configures a CardDAV account" : "Configura uma conta CardDAV",
+ "Events" : "Eventos",
+ "Untitled task" : "Tarefa sem título",
+ "Completed on %s" : "Concluída em %s",
+ "Due on %s by %s" : "Vence em %s às %s",
+ "Due on %s" : "Vence em %s",
+ "System Address Book" : "Livro de endereços do sistema",
+ "The system address book contains contact information for all users in your instance." : "O livro de endereços do sistema contém informação de contacto de todos os utilizadores da sua instância.",
+ "Enable System Address Book" : "Ativar livro de endereços do sistema",
+ "DAV system address book" : "Livro de endereços DAV do sistema",
+ "No outstanding DAV system address book sync." : "Sem sincronizações pendentes do livro de endereços DAV do sistema.",
+ "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\"." : "A sincronização do livro de endereços DAV do sistema ainda não foi executada porque a sua instância não tem utilizadores; execute‑a manualmente com \"occ dav:sync-system-addressbook\".",
+ "WebDAV endpoint" : "Endpoint WebDAV",
+ "Could not check that your web server is properly set up to allow file synchronization over WebDAV. Please check manually." : "Não foi possível verificar se o seu servidor web está corretamente configurado para permitir a sincronização de ficheiros via WebDAV. Verifique manualmente.",
+ "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "O seu servidor da Web não está configurado corretamente para permitir a sincronização de ficheiros, porque a interface WebDAV parece estar com problemas.",
+ "Your web server is properly set up to allow file synchronization over WebDAV." : "O seu servidor web está corretamente configurado para permitir a sincronização de ficheiros via WebDAV.",
+ "Migrated calendar (%1$s)" : "Calendário migrado (%1$s)",
+ "Calendars including events, details and attendees" : "Calendários incluindo eventos, detalhes e participantes",
+ "Contacts and groups" : "Contactos e grupos",
+ "WebDAV" : "WebDAV",
+ "Absence saved" : "Ausência guardada",
+ "Failed to save your absence settings" : "Falha ao guardar as suas definições de ausência",
+ "Absence cleared" : "Ausência removida",
+ "Failed to clear your absence settings" : "Falha ao remover as suas definições de ausência",
+ "First day" : "Primeiro dia",
+ "Last day (inclusive)" : "Último dia (inclusive)",
+ "Out of office replacement (optional)" : "Substituto durante ausência (opcional)",
+ "Name of the replacement" : "Nome do substituto",
+ "No results." : "Sem resultados.",
+ "Start typing." : "Comece a escrever.",
+ "Short absence status" : "Estado de ausência curto",
+ "Long absence Message" : "Mensagem de ausência longa",
+ "Save" : "Guardar",
+ "Disable absence" : "Desativar ausência",
+ "Failed to load availability" : "Falha ao carregar disponibilidade",
+ "Saved availability" : "Disponibilidade guardada",
+ "Failed to save availability" : "Falha ao guardar disponibilidade",
+ "Time zone:" : "Fuso horário:",
+ "to" : "Para",
+ "Delete slot" : "Eliminar intervalo",
+ "No working hours set" : "Sem horário de trabalho definido",
+ "Add slot" : "Adicionar intervalo",
+ "Weekdays" : "Dias da semana",
+ "Pick a start time for {dayName}" : "Escolha uma hora de início para {dayName}",
+ "Pick a end time for {dayName}" : "Escolha uma hora de fim para {dayName}",
+ "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Definir automaticamente o estado para \"Não incomodar\" fora do horário de disponibilidade para silenciar todas as notificações.",
+ "Cancel" : "Cancelar",
+ "Import" : "Importar",
+ "Error while saving settings" : "Erro ao guardar definições",
+ "Contact reset successfully" : "Contacto reposto com sucesso",
+ "Error while resetting contact" : "Erro ao repor contacto",
+ "Contact imported successfully" : "Contacto importado com sucesso",
+ "Error while importing contact" : "Erro ao importar contacto",
+ "Import contact" : "Importar contacto",
+ "Reset to default" : "Repor original",
+ "Import contacts" : "Importar contactos",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "A importação de um novo ficheiro .vcf eliminará o contacto predefinido existente e substituí‑lo‑á pelo novo. Deseja continuar?",
+ "Failed to save example event creation setting" : "Falha ao guardar a definição de criação de evento de exemplo",
+ "Failed to upload the example event" : "Falha ao carregar o evento de exemplo",
+ "Custom example event was saved successfully" : "Evento de exemplo personalizado guardado com sucesso",
+ "Failed to delete the custom example event" : "Falha ao eliminar o evento de exemplo personalizado",
+ "Custom example event was deleted successfully" : "Evento de exemplo personalizado eliminado com sucesso",
+ "Import calendar event" : "Importar evento de calendário",
+ "Uploading a new event will overwrite the existing one." : "O carregamento de um novo evento substituirá o existente.",
+ "Upload event" : "Carregar evento",
+ "Availability" : "Disponibilidade",
+ "If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Se configurar o seu horário de trabalho, outras pessoas saberão quando está fora do escritório ao marcar uma reunião.",
+ "Absence" : "Ausência",
+ "Configure your next absence period." : "Configure o seu próximo período de ausência.",
+ "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Instale também a {calendarappstoreopen}aplicação Calendário {linkclose}, ou {calendardocopen} ligue o seu computador e telemóvel para sincronizar ↗{linkclose}.",
+ "Please make sure to properly set up {emailopen}the email server{linkclose}." : "Certifique‑se de configurar corretamente {emailopen}o servidor de email{linkclose}.",
+ "Calendar server" : "Servidor de calendário",
+ "Send invitations to attendees" : "Enviar convites aos participantes",
+ "Automatically generate a birthday calendar" : "Gerar automaticamente um calendário de aniversários",
+ "Birthday calendars will be generated by a background job." : "Os calendários de aniversário serão gerados por uma tarefa em segundo plano.",
+ "Hence they will not be available immediately after enabling but will show up after some time." : "Por isso, não estarão disponíveis imediatamente após a ativação, mas aparecerão após algum tempo.",
+ "Send notifications for events" : "Enviar notificações de eventos",
+ "Notifications are sent via background jobs, so these must occur often enough." : "As notificações são enviadas através de tarefas em segundo plano; estas devem ser executadas com frequência suficiente.",
+ "Send reminder notifications to calendar sharees as well" : "Enviar também notificações de lembrete aos partilhados do calendário",
+ "Reminders are always sent to organizers and attendees." : "Os lembretes são sempre enviados aos organizadores e participantes.",
+ "Enable notifications for events via push" : "Ativar notificações push para eventos",
+ "Example content" : "Conteúdo de exemplo",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "O conteúdo de exemplo serve para demonstrar as funcionalidades do Nextcloud. É fornecido com o Nextcloud e pode ser substituído por conteúdo personalizado.",
+ "There was an error updating your attendance status." : "Ocorreu um erro ao atualizar o seu estado de participação.",
+ "Please contact the organizer directly." : "Contacte diretamente o organizador.",
+ "Are you accepting the invitation?" : "Aceita o convite?",
+ "Tentative" : "Tentativa",
+ "Your attendance was updated successfully." : "O seu estado de participação foi atualizado com sucesso."
+},"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/ro.js b/apps/dav/l10n/ro.js
deleted file mode 100644
index d603496099d..00000000000
--- a/apps/dav/l10n/ro.js
+++ /dev/null
@@ -1,60 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Calendar",
- "Todos" : "De făcut",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} a creat calendarul {calendar}",
- "You created calendar {calendar}" : "Ai creat calendarul {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} a șters calendarul {calendar}",
- "You deleted calendar {calendar}" : "Ai șters calendarul {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} a actualiza calendarul {calendar}",
- "You updated calendar {calendar}" : "Ai actualizat calendarul {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} a partajat calendarul {calendar} cu tine",
- "You shared calendar {calendar} with {user}" : "Ai partajat calendarul {calendar} cu {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} a partajat calendarul {calendar} cu {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} a eliminat partajarea calendarului {calendar} cu tine",
- "You unshared calendar {calendar} from {user}" : "Ai eliminat partajarea calendarului {calendar} cu {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} a eliminat partajarea calendarului {calendar} cu {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} a eliminat partajarea calendarului {calendar} catre sine",
- "You shared calendar {calendar} with group {group}" : "Ai partajat calendarul {calendar} cu grupul {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} a partajat calendarul {calendar} cu grupul {group}",
- "You unshared calendar {calendar} from group {group}" : "Ai eliminat partajarea calendarului {calendar} către grupul {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} a elimina partajarea calendarului {calendar} către grupul {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} a creat evenimentul {event} în calendarul {calendar}",
- "You created event {event} in calendar {calendar}" : "Ai creat evenimentul {event} în calendarul {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} a șters evenimentul {event} din calendarul {calendar}",
- "You deleted event {event} from calendar {calendar}" : "AI șters evenimentul {event} din calendarul {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} a actualizat evenimentul {event} din calendarul {calendar}",
- "You updated event {event} in calendar {calendar}" : "Ai actualizat evenimentul {event} din calendarul {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} a creat lista {todo} în calendarul {calendar}",
- "You created todo {todo} in list {calendar}" : "Ai creat lista {todo} în lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} a șters lista {todo} din calendarul {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Ai șters lista {todo} din calendarul {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} a actualizat lista {todo} din calendarul {calendar}",
- "You updated todo {todo} in list {calendar}" : "Ai actualizat lista {todo} din calendarul {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} a completat lista {todo} din calendarul {calendar}",
- "You solved todo {todo} in list {calendar}" : "Ai completat lista {todo} din calendarul {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} a redeschis lista {todo} din calendarul {calendar}",
- "You reopened todo {todo} in list {calendar}" : "Ai redeschis lista {todo} din calendarul {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendar</strong> a fost modificat",
- "A calendar <strong>event</strong> was modified" : "Un <strong>eveniment</strong> din calendar a fost modificat",
- "A calendar <strong>todo</strong> was modified" : "O <strong>listă</strong> din calendar a fost modificată",
- "Contact birthdays" : "Zile de naștere ale persoanelor de contact",
- "Where:" : "Unde:",
- "Description:" : "Descriere:",
- "_%n year_::_%n years_" : ["%nan","%nani","%nani"],
- "%1$s via %2$s" : "%1$sprin %2$s",
- "Hello %s," : "Salut %s,",
- "Accept" : "Accept",
- "Decline" : "Refuză",
- "Contacts" : "Persoane de contact",
- "Tasks" : "Sarcini",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativă",
- "Save" : "Salvează",
- "Technical details" : "Detalii tehnice",
- "Remote Address: %s" : "Adresă la distanță: %s",
- "Request ID: %s" : "ID-ul cererii: %s"
-},
-"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));");
diff --git a/apps/dav/l10n/ro.json b/apps/dav/l10n/ro.json
deleted file mode 100644
index fb2c0a76987..00000000000
--- a/apps/dav/l10n/ro.json
+++ /dev/null
@@ -1,58 +0,0 @@
-{ "translations": {
- "Calendar" : "Calendar",
- "Todos" : "De făcut",
- "Personal" : "Personal",
- "{actor} created calendar {calendar}" : "{actor} a creat calendarul {calendar}",
- "You created calendar {calendar}" : "Ai creat calendarul {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} a șters calendarul {calendar}",
- "You deleted calendar {calendar}" : "Ai șters calendarul {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} a actualiza calendarul {calendar}",
- "You updated calendar {calendar}" : "Ai actualizat calendarul {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} a partajat calendarul {calendar} cu tine",
- "You shared calendar {calendar} with {user}" : "Ai partajat calendarul {calendar} cu {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} a partajat calendarul {calendar} cu {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} a eliminat partajarea calendarului {calendar} cu tine",
- "You unshared calendar {calendar} from {user}" : "Ai eliminat partajarea calendarului {calendar} cu {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} a eliminat partajarea calendarului {calendar} cu {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} a eliminat partajarea calendarului {calendar} catre sine",
- "You shared calendar {calendar} with group {group}" : "Ai partajat calendarul {calendar} cu grupul {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} a partajat calendarul {calendar} cu grupul {group}",
- "You unshared calendar {calendar} from group {group}" : "Ai eliminat partajarea calendarului {calendar} către grupul {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} a elimina partajarea calendarului {calendar} către grupul {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} a creat evenimentul {event} în calendarul {calendar}",
- "You created event {event} in calendar {calendar}" : "Ai creat evenimentul {event} în calendarul {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} a șters evenimentul {event} din calendarul {calendar}",
- "You deleted event {event} from calendar {calendar}" : "AI șters evenimentul {event} din calendarul {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} a actualizat evenimentul {event} din calendarul {calendar}",
- "You updated event {event} in calendar {calendar}" : "Ai actualizat evenimentul {event} din calendarul {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} a creat lista {todo} în calendarul {calendar}",
- "You created todo {todo} in list {calendar}" : "Ai creat lista {todo} în lista {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} a șters lista {todo} din calendarul {calendar}",
- "You deleted todo {todo} from list {calendar}" : "Ai șters lista {todo} din calendarul {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} a actualizat lista {todo} din calendarul {calendar}",
- "You updated todo {todo} in list {calendar}" : "Ai actualizat lista {todo} din calendarul {calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} a completat lista {todo} din calendarul {calendar}",
- "You solved todo {todo} in list {calendar}" : "Ai completat lista {todo} din calendarul {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} a redeschis lista {todo} din calendarul {calendar}",
- "You reopened todo {todo} in list {calendar}" : "Ai redeschis lista {todo} din calendarul {calendar}",
- "A <strong>calendar</strong> was modified" : "Un <strong>calendar</strong> a fost modificat",
- "A calendar <strong>event</strong> was modified" : "Un <strong>eveniment</strong> din calendar a fost modificat",
- "A calendar <strong>todo</strong> was modified" : "O <strong>listă</strong> din calendar a fost modificată",
- "Contact birthdays" : "Zile de naștere ale persoanelor de contact",
- "Where:" : "Unde:",
- "Description:" : "Descriere:",
- "_%n year_::_%n years_" : ["%nan","%nani","%nani"],
- "%1$s via %2$s" : "%1$sprin %2$s",
- "Hello %s," : "Salut %s,",
- "Accept" : "Accept",
- "Decline" : "Refuză",
- "Contacts" : "Persoane de contact",
- "Tasks" : "Sarcini",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativă",
- "Save" : "Salvează",
- "Technical details" : "Detalii tehnice",
- "Remote Address: %s" : "Adresă la distanță: %s",
- "Request ID: %s" : "ID-ul cererii: %s"
-},"pluralForm" :"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/ru.js b/apps/dav/l10n/ru.js
index 1b9aa0e5f13..e170bb36582 100644
--- a/apps/dav/l10n/ru.js
+++ b/apps/dav/l10n/ru.js
@@ -72,7 +72,77 @@ OC.L10N.register(
"Description: %s" : "Описание: %s",
"Where: %s" : "Где: %s",
"%1$s via %2$s" : "%1$s через %2$s",
+ "In the past on %1$s for the entire day" : "В прошлом, %1$s, в течение всего дня",
+ "_In a minute on %1$s for the entire day_::_In %n minutes on %1$s for the entire day_" : ["Через минуту, %1$s, в течение всего дня","Через %n минуты, %1$s, в течение всего дня","Через %n минут, %1$s, в течение всего дня","Через %n минут, %1$s, в течение всего дня"],
+ "_In a hour on %1$s for the entire day_::_In %n hours on %1$s for the entire day_" : ["Через час, %1$s, в течение всего дня","Через %n часа, %1$s, в течение всего дня","Через %n часов, %1$s, в течение всего дня","Через %n часов, %1$s, в течение всего дня"],
+ "_In a day on %1$s for the entire day_::_In %n days on %1$s for the entire day_" : ["Через день, %1$s, в течение всего дня","Через %n дня, %1$s, в течение всего дня","Через %n дней,%1$s, в течение всего дня","Через %n дней, %1$s, в течение всего дня"],
+ "_In a week on %1$s for the entire day_::_In %n weeks on %1$s for the entire day_" : ["Через неделю, %1$s, в течение всего дня","Через %n недели, %1$s, в течение всего дня","Через %n недель, %1$s, в течение всего дня","Через %n недель, %1$s, в течение всего дня"],
+ "_In a month on %1$s for the entire day_::_In %n months on %1$s for the entire day_" : ["Через месяц, %1$s, в течение всего дня","Через %n месяца, %1$s, в течение всего дня","Через %n месяцев, %1$s, в течение всего дня","Через %n месяцев, %1$s, в течение всего дня"],
+ "_In a year on %1$s for the entire day_::_In %n years on %1$s for the entire day_" : ["Через год, %1$s, в течение всего дня","Через %n года, %1$s, в течение всего дня","Через %n лет, %1$s, в течение всего дня","Через %n лет, %1$s, в течение всего дня"],
+ "In the past on %1$s between %2$s - %3$s" : "В прошлом, %1$s, с %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_" : ["Через минуту, %1$s, с %2$s до %3$s","Через %n минуты, %1$s, с %2$s до %3$s","Через %n минут, %1$s, с %2$s до %3$s","Через %n минут, %1$s, с %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_" : ["Через час, %1$s, с %2$s до %3$s","Через %n часа, %1$s, с %2$s до %3$s","Через %n часов, %1$s, с %2$s до %3$s","Через %n часов, %1$s, с %2$s до %3$s"],
+ "_In a day on %1$s between %2$s - %3$s_::_In %n days on %1$s between %2$s - %3$s_" : ["Через день, %1$s, с %2$s до %3$s","Через %n дня %1$s, с %2$s до %3$s","Через %n дней, %1$s, с %2$s до %3$s","Через %n дней, %1$s, с %2$s до %3$s"],
+ "_In a week on %1$s between %2$s - %3$s_::_In %n weeks on %1$s between %2$s - %3$s_" : ["Через неделю, %1$s, с %2$s до %3$s","Через %n недели, %1$s, с %2$s до %3$s","Через %n недель, %1$s, с %2$s до %3$s","Через %n недель, %1$s, с %2$s до %3$s"],
+ "_In a month on %1$s between %2$s - %3$s_::_In %n months on %1$s between %2$s - %3$s_" : ["Через месяц, %1$s, с %2$s до %3$s","Через %n месяца, %1$s, с %2$s до %3$s","Через %n месяцев, %1$s, с %2$s до %3$s","Через %n месяцев, %1$s, с %2$s до %3$s"],
+ "_In a year on %1$s between %2$s - %3$s_::_In %n years on %1$s between %2$s - %3$s_" : ["Через год, %1$s, с %2$s до %3$s","Через %n года, %1$s, с %2$s до %3$s","Через %n лет, %1$s, с %2$s до %3$s","Через %n лет, %1$s, с %2$s до %3$s"],
+ "Could not generate when statement" : "Не удалось сгенерировать выражение времени",
"Every Day for the entire day" : "Каждый день в течение всего дня",
+ "Every Day for the entire day until %1$s" : "Каждый день весь день до %1$s",
+ "Every Day between %1$s - %2$s" : "Каждый день с %1$s по %2$s",
+ "Every Day between %1$s - %2$s until %3$s" : "Каждый день с %1$s до %2$s до %3$s",
+ "Every %1$d Days for the entire day" : "Каждые %1$d дней в течение всего дня",
+ "Every %1$d Days for the entire day until %2$s" : "Каждые %1$d дней в течение всего дня до %2$s",
+ "Every %1$d Days between %2$s - %3$s" : "Каждые %1$d дней с %2$s до %3$s",
+ "Every %1$d Days between %2$s - %3$s until %4$s" : "Каждые %1$d дней с %2$s до %3$s до %4$s",
+ "Could not generate event recurrence statement" : "Не удалось сгенерировать правило повторения события",
+ "Every Week on %1$s for the entire day" : "Каждую неделю в %1$s в течение всего дня",
+ "Every Week on %1$s for the entire day until %2$s" : "Каждую неделю по %1$s в течение всего дня до %2$s",
+ "Every Week on %1$s between %2$s - %3$s" : "Каждую неделю в %1$s с %2$s до %3$s",
+ "Every Week on %1$s between %2$s - %3$s until %4$s" : "Каждую неделю по %1$s с %2$s до %3$s до %4$s",
+ "Every %1$d Weeks on %2$s for the entire day" : "Каждые %1$d недель по %2$s в течение всего дня",
+ "Every %1$d Weeks on %2$s for the entire day until %3$s" : "Каждые %1$d недель по %2$s в течение всего дня до %3$s",
+ "Every %1$d Weeks on %2$s between %3$s - %4$s" : "Каждые %1$d недель по %2$s с %3$s до %4$s",
+ "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Каждые %1$d недель по %2$s с %3$s до %4$s до %5$s",
+ "Every Month on the %1$s for the entire day" : "Каждый месяц %1$s в течение всего дня",
+ "Every Month on the %1$s for the entire day until %2$s" : "Каждый месяц %1$s в течение всего дня до %2$s",
+ "Every Month on the %1$s between %2$s - %3$s" : "Каждый месяц %1$s с %2$s до %3$s",
+ "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Каждый месяц %1$s с %2$s до %3$s до %4$s",
+ "Every %1$d Months on the %2$s for the entire day" : "Каждые %1$d месяцев %2$s в течение всего дня",
+ "Every %1$d Months on the %2$s for the entire day until %3$s" : "Каждые %1$d месяцев %2$s в течение всего дня до %3$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s" : "Каждые %1$d месяцев %2$s с %3$s до %4$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "Каждые %1$d месяцев %2$s с %3$s до %4$s до %5$s",
+ "Every Year in %1$s on the %2$s for the entire day" : "Каждый год в %1$s %2$s в течение всего дня",
+ "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Каждый год в %1$s %2$s в течение всего дня до %3$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Каждый год в %1$s %2$s с %3$s до %4$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Каждый год в %1$s %2$s с %3$s до %4$s до %5$s",
+ "Every %1$d Years in %2$s on the %3$s for the entire day" : "Каждые %1$d лет в %2$s %3$s в течение всего дня",
+ "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "Каждые %1$d лет в %2$s %3$s в течение всего дня до %4$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "Каждые %1$d лет в %2$s %3$s с %4$s до %5$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Каждые %1$d лет в %2$s %3$s с %4$s до %5$s до %6$s",
+ "On specific dates for the entire day until %1$s" : "В определённые даты, весь день до %1$s",
+ "On specific dates between %1$s - %2$s until %3$s" : "В определённые даты с %1$s по %2$s до %3$s",
+ "In the past on %1$s" : "В прошлом, %1$s",
+ "_In a minute on %1$s_::_In %n minutes on %1$s_" : ["Через минуту, %1$s","Через %n минуты, %1$s","Через %n минут, %1$s","Через %n минут, %1$s"],
+ "_In a hour on %1$s_::_In %n hours on %1$s_" : ["Через час, %1$s","Через %n часа, %1$s","Через %n часов, %1$s","Через %n часов, %1$s"],
+ "_In a day on %1$s_::_In %n days on %1$s_" : ["Через день, %1$s","Через %n дня, %1$s","Через %n дней, %1$s","Через %n дней, %1$s"],
+ "_In a week on %1$s_::_In %n weeks on %1$s_" : ["Через неделю, %1$s","Через %n недели,%1$s","Через %n недель, %1$s","Через %n недель, %1$s"],
+ "_In a month on %1$s_::_In %n months on %1$s_" : ["Через месяц, %1$s","Через %n месяца, %1$s","Через %n месяцев, %1$s","Через %n месяцев, %1$s"],
+ "_In a year on %1$s_::_In %n years on %1$s_" : ["Через год, %1$s","Через %n года, %1$s","Через %n лет, %1$s","Через %n лет, %1$s"],
+ "In the past on %1$s then on %2$s" : "В прошлом, %1$s, затем %2$s",
+ "_In a minute on %1$s then on %2$s_::_In %n minutes on %1$s then on %2$s_" : ["Через минуту, %1$s, затем %2$s","Через %n минуты, %1$s, затем %2$s","Через %n минут, %1$s, затем %2$s","Через %n минут, %1$s, затем %2$s"],
+ "_In a hour on %1$s then on %2$s_::_In %n hours on %1$s then on %2$s_" : ["Через час, %1$s, затем %2$s","Через %n часа, %1$s, затем %2$s","Через %n часов, %1$s, затем %2$s","Через %n часов, %1$s, затем %2$s"],
+ "_In a day on %1$s then on %2$s_::_In %n days on %1$s then on %2$s_" : ["Через день, %1$s, затем %2$s","Через %n дня, %1$s, затем %2$s","Через %n дней, %1$s, затем %2$s","Через %n дней, %1$s, затем %2$s"],
+ "_In a week on %1$s then on %2$s_::_In %n weeks on %1$s then on %2$s_" : ["Через неделю, %1$s, затем %2$s","Через %n недели, %1$s, затем %2$s","Через %n недель, %1$s, затем %2$s","Через %n недель, %1$s, затем %2$s"],
+ "_In a month on %1$s then on %2$s_::_In %n months on %1$s then on %2$s_" : ["Через месяц, %1$s, затем %2$s","Через %n месяца, %1$s, затем %2$s","Через %n месяцев, %1$s, затем %2$s","Через %n месяцев, %1$s, затем %2$s"],
+ "_In a year on %1$s then on %2$s_::_In %n years on %1$s then on %2$s_" : ["Через год, %1$s, затем %2$s","Через %n года, %1$s, затем %2$s","Через %n лет, %1$s, затем %2$s","Через %n лет, %1$s, затем %2$s"],
+ "In the past on %1$s then on %2$s and %3$s" : "В прошлом, %1$s, затем %2$s и %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_" : ["Через минуту, %1$s, затем %2$s и %3$s","Через %n минуты, %1$s, затем %2$s и %3$s","Через %n минут, %1$s, затем %2$s и %3$s","Через %n минут, %1$s, затем %2$s и %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_" : ["Через час, %1$s, затем %2$s и %3$s","Через %n часа, %1$s, затем %2$s и %3$s","Через %n часов, %1$s, затем %2$s и %3$s","Через %n часов, %1$s, затем %2$s и %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_" : ["Через день, %1$s, затем %2$s и %3$s","Через %n дня, %1$s, затем %2$s и %3$s","Через %n дней, %1$s, затем %2$s и %3$s","Через %n дней, %1$s, затем %2$s и %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_" : ["Через неделю, %1$s, затем %2$s и %3$s","Через %n недели, %1$s, затем %2$s и %3$s","Через %n недель, %1$s, затем %2$s и %3$s","Через %n недель, %1$s, затем %2$s и %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_" : ["Через месяц, %1$s, затем %2$s и %3$s","Через %n месяца, %1$s, затем %2$s и %3$s","Через %n месяцев, %1$s, затем %2$s и %3$s","Через %n месяцев, %1$s, затем %2$s и %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_" : ["Через год, %1$s, затем %2$s и %3$s","Через %n года, %1$s, затем %2$s и %3$s","Через %n лет, %1$s, затем %2$s и %3$s","Через %n лет, %1$s, затем %2$s и %3$s"],
"Could not generate next recurrence statement" : "Не удалось сгенерировать следующий оператор повторения",
"Cancelled: %1$s" : "Событие отменено: %1$s",
"\"%1$s\" has been canceled" : "Событие «%1$s» отменено",
@@ -119,10 +189,12 @@ OC.L10N.register(
"Second" : "Второй",
"Third" : "Третий",
"Fourth" : "Четвертый",
+ "Fifth" : "Пятый",
"Last" : "Последний",
"Second Last" : "Предпоследний",
- "Third Last" : "Третий по счету",
- "Fourth Last" : "Четвертый по счету",
+ "Third Last" : "Третий с конца",
+ "Fourth Last" : "Четвёртый с конца",
+ "Fifth Last" : "Пятый с конца",
"Contacts" : "Контакты",
"{actor} created address book {addressbook}" : "{actor} создал(а) адресную книгу «{addressbook}»",
"You created address book {addressbook}" : "Вы создали адресную книгу «{addressbook}»",
@@ -178,6 +250,9 @@ OC.L10N.register(
"Completed on %s" : "Завершено %s",
"Due on %s by %s" : "До %s %s",
"Due on %s" : "До %s",
+ "System Address Book" : "Системная адресная книга",
+ "The system address book contains contact information for all users in your instance." : "Системная адресная книга содержит контактную информацию всех пользователей в вашем инстансе.",
+ "Enable System Address Book" : "Включить системную адресную книгу",
"DAV system address book" : "Системная адресная книга DAV",
"No outstanding DAV system address book sync." : "Синхронизация системной адресной книги 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\"." : "Синхронизация системной адресной книги DAV ещё не запущена, поскольку в этом экземпляре более 1000 пользователей или произошла ошибка. Перезапустите синхронизацию вручную используя команду «occ dav:sync-system-addressbook».",
@@ -215,6 +290,25 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Выберите время начала в {dayName}",
"Pick a end time for {dayName}" : "Выберите время окончания в {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Автоматически изменять статус на «Не беспокоить» вне интервала доступности для отключения уведомлений.",
+ "Cancel" : "Отмена",
+ "Import" : "Импортировать",
+ "Error while saving settings" : "Ошибка при сохранении параметров",
+ "Contact reset successfully" : "Контакт успешно сброшен",
+ "Error while resetting contact" : "Ошибка при сбросе контакта",
+ "Contact imported successfully" : " Контакт успешно импортирован",
+ "Error while importing contact" : " Ошибка при импорте контакта",
+ "Import contact" : "Импортировать контакт",
+ "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" : "Отсутствие",
@@ -231,17 +325,12 @@ 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" : "Включить уведомления о событиях с помощью push",
- "Cancel" : "Отмена",
- "Import" : "Импортировать",
- "Error while saving settings" : "Ошибка при сохранении параметров",
+ "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. По умолчанию поставляется стандартное содержимое, которое можно заменить настраиваемым.",
"There was an error updating your attendance status." : "Ошибка обновления статуса участия.",
"Please contact the organizer directly." : "Обратитесь к организатору напрямую.",
"Are you accepting the invitation?" : "Принять приглашение?",
"Tentative" : "Под вопросом",
- "Your attendance was updated successfully." : "Статус участия обновлён.",
- "Time:" : "Время:",
- "Could not open file" : "Не удалось открыть файл",
- "Invalid chunk name" : "Недопустимое имя сегмента",
- "Could not rename part file assembled from chunks" : "Не удалось переименовать временный файл, сформированный из сегментов"
+ "Your attendance was updated successfully." : "Статус участия обновлён."
},
"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);");
diff --git a/apps/dav/l10n/ru.json b/apps/dav/l10n/ru.json
index 43211c3f748..d1da881a4c6 100644
--- a/apps/dav/l10n/ru.json
+++ b/apps/dav/l10n/ru.json
@@ -70,7 +70,77 @@
"Description: %s" : "Описание: %s",
"Where: %s" : "Где: %s",
"%1$s via %2$s" : "%1$s через %2$s",
+ "In the past on %1$s for the entire day" : "В прошлом, %1$s, в течение всего дня",
+ "_In a minute on %1$s for the entire day_::_In %n minutes on %1$s for the entire day_" : ["Через минуту, %1$s, в течение всего дня","Через %n минуты, %1$s, в течение всего дня","Через %n минут, %1$s, в течение всего дня","Через %n минут, %1$s, в течение всего дня"],
+ "_In a hour on %1$s for the entire day_::_In %n hours on %1$s for the entire day_" : ["Через час, %1$s, в течение всего дня","Через %n часа, %1$s, в течение всего дня","Через %n часов, %1$s, в течение всего дня","Через %n часов, %1$s, в течение всего дня"],
+ "_In a day on %1$s for the entire day_::_In %n days on %1$s for the entire day_" : ["Через день, %1$s, в течение всего дня","Через %n дня, %1$s, в течение всего дня","Через %n дней,%1$s, в течение всего дня","Через %n дней, %1$s, в течение всего дня"],
+ "_In a week on %1$s for the entire day_::_In %n weeks on %1$s for the entire day_" : ["Через неделю, %1$s, в течение всего дня","Через %n недели, %1$s, в течение всего дня","Через %n недель, %1$s, в течение всего дня","Через %n недель, %1$s, в течение всего дня"],
+ "_In a month on %1$s for the entire day_::_In %n months on %1$s for the entire day_" : ["Через месяц, %1$s, в течение всего дня","Через %n месяца, %1$s, в течение всего дня","Через %n месяцев, %1$s, в течение всего дня","Через %n месяцев, %1$s, в течение всего дня"],
+ "_In a year on %1$s for the entire day_::_In %n years on %1$s for the entire day_" : ["Через год, %1$s, в течение всего дня","Через %n года, %1$s, в течение всего дня","Через %n лет, %1$s, в течение всего дня","Через %n лет, %1$s, в течение всего дня"],
+ "In the past on %1$s between %2$s - %3$s" : "В прошлом, %1$s, с %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_" : ["Через минуту, %1$s, с %2$s до %3$s","Через %n минуты, %1$s, с %2$s до %3$s","Через %n минут, %1$s, с %2$s до %3$s","Через %n минут, %1$s, с %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_" : ["Через час, %1$s, с %2$s до %3$s","Через %n часа, %1$s, с %2$s до %3$s","Через %n часов, %1$s, с %2$s до %3$s","Через %n часов, %1$s, с %2$s до %3$s"],
+ "_In a day on %1$s between %2$s - %3$s_::_In %n days on %1$s between %2$s - %3$s_" : ["Через день, %1$s, с %2$s до %3$s","Через %n дня %1$s, с %2$s до %3$s","Через %n дней, %1$s, с %2$s до %3$s","Через %n дней, %1$s, с %2$s до %3$s"],
+ "_In a week on %1$s between %2$s - %3$s_::_In %n weeks on %1$s between %2$s - %3$s_" : ["Через неделю, %1$s, с %2$s до %3$s","Через %n недели, %1$s, с %2$s до %3$s","Через %n недель, %1$s, с %2$s до %3$s","Через %n недель, %1$s, с %2$s до %3$s"],
+ "_In a month on %1$s between %2$s - %3$s_::_In %n months on %1$s between %2$s - %3$s_" : ["Через месяц, %1$s, с %2$s до %3$s","Через %n месяца, %1$s, с %2$s до %3$s","Через %n месяцев, %1$s, с %2$s до %3$s","Через %n месяцев, %1$s, с %2$s до %3$s"],
+ "_In a year on %1$s between %2$s - %3$s_::_In %n years on %1$s between %2$s - %3$s_" : ["Через год, %1$s, с %2$s до %3$s","Через %n года, %1$s, с %2$s до %3$s","Через %n лет, %1$s, с %2$s до %3$s","Через %n лет, %1$s, с %2$s до %3$s"],
+ "Could not generate when statement" : "Не удалось сгенерировать выражение времени",
"Every Day for the entire day" : "Каждый день в течение всего дня",
+ "Every Day for the entire day until %1$s" : "Каждый день весь день до %1$s",
+ "Every Day between %1$s - %2$s" : "Каждый день с %1$s по %2$s",
+ "Every Day between %1$s - %2$s until %3$s" : "Каждый день с %1$s до %2$s до %3$s",
+ "Every %1$d Days for the entire day" : "Каждые %1$d дней в течение всего дня",
+ "Every %1$d Days for the entire day until %2$s" : "Каждые %1$d дней в течение всего дня до %2$s",
+ "Every %1$d Days between %2$s - %3$s" : "Каждые %1$d дней с %2$s до %3$s",
+ "Every %1$d Days between %2$s - %3$s until %4$s" : "Каждые %1$d дней с %2$s до %3$s до %4$s",
+ "Could not generate event recurrence statement" : "Не удалось сгенерировать правило повторения события",
+ "Every Week on %1$s for the entire day" : "Каждую неделю в %1$s в течение всего дня",
+ "Every Week on %1$s for the entire day until %2$s" : "Каждую неделю по %1$s в течение всего дня до %2$s",
+ "Every Week on %1$s between %2$s - %3$s" : "Каждую неделю в %1$s с %2$s до %3$s",
+ "Every Week on %1$s between %2$s - %3$s until %4$s" : "Каждую неделю по %1$s с %2$s до %3$s до %4$s",
+ "Every %1$d Weeks on %2$s for the entire day" : "Каждые %1$d недель по %2$s в течение всего дня",
+ "Every %1$d Weeks on %2$s for the entire day until %3$s" : "Каждые %1$d недель по %2$s в течение всего дня до %3$s",
+ "Every %1$d Weeks on %2$s between %3$s - %4$s" : "Каждые %1$d недель по %2$s с %3$s до %4$s",
+ "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Каждые %1$d недель по %2$s с %3$s до %4$s до %5$s",
+ "Every Month on the %1$s for the entire day" : "Каждый месяц %1$s в течение всего дня",
+ "Every Month on the %1$s for the entire day until %2$s" : "Каждый месяц %1$s в течение всего дня до %2$s",
+ "Every Month on the %1$s between %2$s - %3$s" : "Каждый месяц %1$s с %2$s до %3$s",
+ "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Каждый месяц %1$s с %2$s до %3$s до %4$s",
+ "Every %1$d Months on the %2$s for the entire day" : "Каждые %1$d месяцев %2$s в течение всего дня",
+ "Every %1$d Months on the %2$s for the entire day until %3$s" : "Каждые %1$d месяцев %2$s в течение всего дня до %3$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s" : "Каждые %1$d месяцев %2$s с %3$s до %4$s",
+ "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "Каждые %1$d месяцев %2$s с %3$s до %4$s до %5$s",
+ "Every Year in %1$s on the %2$s for the entire day" : "Каждый год в %1$s %2$s в течение всего дня",
+ "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Каждый год в %1$s %2$s в течение всего дня до %3$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Каждый год в %1$s %2$s с %3$s до %4$s",
+ "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Каждый год в %1$s %2$s с %3$s до %4$s до %5$s",
+ "Every %1$d Years in %2$s on the %3$s for the entire day" : "Каждые %1$d лет в %2$s %3$s в течение всего дня",
+ "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "Каждые %1$d лет в %2$s %3$s в течение всего дня до %4$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "Каждые %1$d лет в %2$s %3$s с %4$s до %5$s",
+ "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Каждые %1$d лет в %2$s %3$s с %4$s до %5$s до %6$s",
+ "On specific dates for the entire day until %1$s" : "В определённые даты, весь день до %1$s",
+ "On specific dates between %1$s - %2$s until %3$s" : "В определённые даты с %1$s по %2$s до %3$s",
+ "In the past on %1$s" : "В прошлом, %1$s",
+ "_In a minute on %1$s_::_In %n minutes on %1$s_" : ["Через минуту, %1$s","Через %n минуты, %1$s","Через %n минут, %1$s","Через %n минут, %1$s"],
+ "_In a hour on %1$s_::_In %n hours on %1$s_" : ["Через час, %1$s","Через %n часа, %1$s","Через %n часов, %1$s","Через %n часов, %1$s"],
+ "_In a day on %1$s_::_In %n days on %1$s_" : ["Через день, %1$s","Через %n дня, %1$s","Через %n дней, %1$s","Через %n дней, %1$s"],
+ "_In a week on %1$s_::_In %n weeks on %1$s_" : ["Через неделю, %1$s","Через %n недели,%1$s","Через %n недель, %1$s","Через %n недель, %1$s"],
+ "_In a month on %1$s_::_In %n months on %1$s_" : ["Через месяц, %1$s","Через %n месяца, %1$s","Через %n месяцев, %1$s","Через %n месяцев, %1$s"],
+ "_In a year on %1$s_::_In %n years on %1$s_" : ["Через год, %1$s","Через %n года, %1$s","Через %n лет, %1$s","Через %n лет, %1$s"],
+ "In the past on %1$s then on %2$s" : "В прошлом, %1$s, затем %2$s",
+ "_In a minute on %1$s then on %2$s_::_In %n minutes on %1$s then on %2$s_" : ["Через минуту, %1$s, затем %2$s","Через %n минуты, %1$s, затем %2$s","Через %n минут, %1$s, затем %2$s","Через %n минут, %1$s, затем %2$s"],
+ "_In a hour on %1$s then on %2$s_::_In %n hours on %1$s then on %2$s_" : ["Через час, %1$s, затем %2$s","Через %n часа, %1$s, затем %2$s","Через %n часов, %1$s, затем %2$s","Через %n часов, %1$s, затем %2$s"],
+ "_In a day on %1$s then on %2$s_::_In %n days on %1$s then on %2$s_" : ["Через день, %1$s, затем %2$s","Через %n дня, %1$s, затем %2$s","Через %n дней, %1$s, затем %2$s","Через %n дней, %1$s, затем %2$s"],
+ "_In a week on %1$s then on %2$s_::_In %n weeks on %1$s then on %2$s_" : ["Через неделю, %1$s, затем %2$s","Через %n недели, %1$s, затем %2$s","Через %n недель, %1$s, затем %2$s","Через %n недель, %1$s, затем %2$s"],
+ "_In a month on %1$s then on %2$s_::_In %n months on %1$s then on %2$s_" : ["Через месяц, %1$s, затем %2$s","Через %n месяца, %1$s, затем %2$s","Через %n месяцев, %1$s, затем %2$s","Через %n месяцев, %1$s, затем %2$s"],
+ "_In a year on %1$s then on %2$s_::_In %n years on %1$s then on %2$s_" : ["Через год, %1$s, затем %2$s","Через %n года, %1$s, затем %2$s","Через %n лет, %1$s, затем %2$s","Через %n лет, %1$s, затем %2$s"],
+ "In the past on %1$s then on %2$s and %3$s" : "В прошлом, %1$s, затем %2$s и %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_" : ["Через минуту, %1$s, затем %2$s и %3$s","Через %n минуты, %1$s, затем %2$s и %3$s","Через %n минут, %1$s, затем %2$s и %3$s","Через %n минут, %1$s, затем %2$s и %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_" : ["Через час, %1$s, затем %2$s и %3$s","Через %n часа, %1$s, затем %2$s и %3$s","Через %n часов, %1$s, затем %2$s и %3$s","Через %n часов, %1$s, затем %2$s и %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_" : ["Через день, %1$s, затем %2$s и %3$s","Через %n дня, %1$s, затем %2$s и %3$s","Через %n дней, %1$s, затем %2$s и %3$s","Через %n дней, %1$s, затем %2$s и %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_" : ["Через неделю, %1$s, затем %2$s и %3$s","Через %n недели, %1$s, затем %2$s и %3$s","Через %n недель, %1$s, затем %2$s и %3$s","Через %n недель, %1$s, затем %2$s и %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_" : ["Через месяц, %1$s, затем %2$s и %3$s","Через %n месяца, %1$s, затем %2$s и %3$s","Через %n месяцев, %1$s, затем %2$s и %3$s","Через %n месяцев, %1$s, затем %2$s и %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_" : ["Через год, %1$s, затем %2$s и %3$s","Через %n года, %1$s, затем %2$s и %3$s","Через %n лет, %1$s, затем %2$s и %3$s","Через %n лет, %1$s, затем %2$s и %3$s"],
"Could not generate next recurrence statement" : "Не удалось сгенерировать следующий оператор повторения",
"Cancelled: %1$s" : "Событие отменено: %1$s",
"\"%1$s\" has been canceled" : "Событие «%1$s» отменено",
@@ -117,10 +187,12 @@
"Second" : "Второй",
"Third" : "Третий",
"Fourth" : "Четвертый",
+ "Fifth" : "Пятый",
"Last" : "Последний",
"Second Last" : "Предпоследний",
- "Third Last" : "Третий по счету",
- "Fourth Last" : "Четвертый по счету",
+ "Third Last" : "Третий с конца",
+ "Fourth Last" : "Четвёртый с конца",
+ "Fifth Last" : "Пятый с конца",
"Contacts" : "Контакты",
"{actor} created address book {addressbook}" : "{actor} создал(а) адресную книгу «{addressbook}»",
"You created address book {addressbook}" : "Вы создали адресную книгу «{addressbook}»",
@@ -176,6 +248,9 @@
"Completed on %s" : "Завершено %s",
"Due on %s by %s" : "До %s %s",
"Due on %s" : "До %s",
+ "System Address Book" : "Системная адресная книга",
+ "The system address book contains contact information for all users in your instance." : "Системная адресная книга содержит контактную информацию всех пользователей в вашем инстансе.",
+ "Enable System Address Book" : "Включить системную адресную книгу",
"DAV system address book" : "Системная адресная книга DAV",
"No outstanding DAV system address book sync." : "Синхронизация системной адресной книги 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\"." : "Синхронизация системной адресной книги DAV ещё не запущена, поскольку в этом экземпляре более 1000 пользователей или произошла ошибка. Перезапустите синхронизацию вручную используя команду «occ dav:sync-system-addressbook».",
@@ -213,6 +288,25 @@
"Pick a start time for {dayName}" : "Выберите время начала в {dayName}",
"Pick a end time for {dayName}" : "Выберите время окончания в {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Автоматически изменять статус на «Не беспокоить» вне интервала доступности для отключения уведомлений.",
+ "Cancel" : "Отмена",
+ "Import" : "Импортировать",
+ "Error while saving settings" : "Ошибка при сохранении параметров",
+ "Contact reset successfully" : "Контакт успешно сброшен",
+ "Error while resetting contact" : "Ошибка при сбросе контакта",
+ "Contact imported successfully" : " Контакт успешно импортирован",
+ "Error while importing contact" : " Ошибка при импорте контакта",
+ "Import contact" : "Импортировать контакт",
+ "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" : "Отсутствие",
@@ -229,17 +323,12 @@
"Send reminder notifications to calendar sharees as well" : "Отправлять напоминания всем пользователям, имеющим доступ к календарю",
"Reminders are always sent to organizers and attendees." : "Организаторам и участникам уведомления отправляются во всех случаях.",
"Enable notifications for events via push" : "Включить уведомления о событиях с помощью push",
- "Cancel" : "Отмена",
- "Import" : "Импортировать",
- "Error while saving settings" : "Ошибка при сохранении параметров",
+ "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. По умолчанию поставляется стандартное содержимое, которое можно заменить настраиваемым.",
"There was an error updating your attendance status." : "Ошибка обновления статуса участия.",
"Please contact the organizer directly." : "Обратитесь к организатору напрямую.",
"Are you accepting the invitation?" : "Принять приглашение?",
"Tentative" : "Под вопросом",
- "Your attendance was updated successfully." : "Статус участия обновлён.",
- "Time:" : "Время:",
- "Could not open file" : "Не удалось открыть файл",
- "Invalid chunk name" : "Недопустимое имя сегмента",
- "Could not rename part file assembled from chunks" : "Не удалось переименовать временный файл, сформированный из сегментов"
+ "Your attendance was updated successfully." : "Статус участия обновлён."
},"pluralForm" :"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/sc.js b/apps/dav/l10n/sc.js
deleted file mode 100644
index 902dbd81dd0..00000000000
--- a/apps/dav/l10n/sc.js
+++ /dev/null
@@ -1,151 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Calendàriu",
- "Tasks" : "Fainas",
- "Personal" : "Personale",
- "{actor} created calendar {calendar}" : "{actor} at creadu su calendàriu {calendar}",
- "You created calendar {calendar}" : "As creadu su calendàriu {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} at cantzelladu su calendàriu {calendar}",
- "You deleted calendar {calendar}" : "As creadu su calendàriu {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} at agiornadu su calendàriu {calendar}",
- "You updated calendar {calendar}" : "As agiornadu su calendàriu {calendar}",
- "{actor} restored calendar {calendar}" : "{actor} at ripristinadu su calendàriu {calendar}",
- "You restored calendar {calendar}" : "As ripristinadu su calendàriu {calendar}",
- "You shared calendar {calendar} as public link" : "As cumpartzidu su calendàriu {calendar} comente ligòngiu pùblicu",
- "You removed public link for calendar {calendar}" : "Ci nd'as bogadu su ligòngiu pùblicu pro su calendàriu {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} at cumpartzidu su calendàriu {calendar} cun tegus",
- "You shared calendar {calendar} with {user}" : "As cumpartzidu su calendàriu {calendar} cun {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} at cumpartzidu su calendàriu {calendar} cun {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} at annulladu sa cumpartzidura de su calendàriu {calendar} cun tegus",
- "You unshared calendar {calendar} from {user}" : "As annulladu sa cumpartzidura de su calendàriu {calendar} cun {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} at annulladu sa cumpartzidura de su calendàriu {calendar} cun {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} at annulladu sa cumpartzidura de su calendàriu {calendar} cun issu etotu",
- "You shared calendar {calendar} with group {group}" : "As cumpartzidu su calendàriu {calendar} cun su grupu {group}",
- "{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}",
- "You deleted event {event} from calendar {calendar}" : "As cantzelladu s'eventu {event} dae su calendàriu {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} at agiornadu s'eventu {event} in su calendàriu {calendar}",
- "You updated event {event} in calendar {calendar}" : "As agiornadu s'eventu {event} in su calendàriu {calendar}",
- "{actor} restored event {event} of calendar {calendar}" : "{actor} at ripristinadu s'eventu {event} in su calendàriu {calendar}",
- "You restored event {event} of calendar {calendar}" : "As ripristinadu s'eventu {event} in su calendàriu {calendar}",
- "Busy" : "Impinnadu",
- "Calendar, contacts and tasks" : "Calendàriu, cuntatos e fainas",
- "A <strong>calendar</strong> was modified" : "Unu <strong>calendàriu</strong> est istadu modificadu",
- "A calendar <strong>event</strong> was modified" : "Un'<strong>eventu</strong> de su calendàriu est istadu modificadu",
- "Contact birthdays" : "Data de nàschida de is cuntatos",
- "Death of %s" : "Morte de %s",
- "Untitled calendar" : "Calendàriu chene tìtulu",
- "Calendar:" : "Calendàriu:",
- "Date:" : "Data:",
- "Where:" : "Ue:",
- "Description:" : "Descritzione:",
- "_%n year_::_%n years_" : ["%n annu","%n annos"],
- "_%n month_::_%n months_" : ["%n meses","%n meses"],
- "_%n day_::_%n days_" : ["%n die","%n days"],
- "_%n hour_::_%n hours_" : ["%n ora","%n ora"],
- "_%n minute_::_%n minutes_" : ["%n minutos","%n minutos"],
- "%s (in %s)" : "%s (in %s)",
- "%s (%s ago)" : "%s (%s a immoe)",
- "Calendar: %s" : "Calendàriu: %s",
- "Date: %s" : "Data: %s",
- "Description: %s" : "Descritzione: %s",
- "Where: %s" : "Ue: %s",
- "%1$s via %2$s" : "%1$s cun %2$s",
- "Cancelled: %1$s" : "Annulladu: %1$s",
- "Re: %1$s" : "Re: %1$s",
- "Invitation: %1$s" : "Invitu: %1$s",
- "Organizer:" : "Organizadore: ",
- "Attendees:" : "Partetzipadores:",
- "Title:" : "Tìtulos:",
- "When:" : "Cando:",
- "Location:" : "Positzione:",
- "Link:" : "Ligòngiu:",
- "Accept" : "Atzeta",
- "Decline" : "Refuda",
- "More options …" : "Àteras optziones ...",
- "More options at %s" : "Àteras optziones a is %s",
- "Monday" : "Lunis",
- "Tuesday" : "Martis",
- "Wednesday" : "Mércuris",
- "Thursday" : "Giòbia",
- "Friday" : "Chenàbura",
- "Saturday" : "Sàbudu",
- "Sunday" : "Domìnigu",
- "January" : "Ghennàrgiu",
- "February" : "Freàrgiu",
- "March" : "Martzu",
- "April" : "Abrile",
- "May" : "Maju",
- "June" : "Làmparas",
- "July" : "Mese de Trìulas/Argiolas",
- "August" : "Austu",
- "September" : "Cabudanni",
- "October" : "Mese de Ladàmini/ Santu Aine",
- "November" : "Sant'Andria",
- "December" : "Nadale",
- "First" : "Primu",
- "Last" : "Ùrtimu",
- "Contacts" : "Cuntatos",
- "{actor} created address book {addressbook}" : "{actor} at creadu sa rubrica {addressbook}",
- "You created address book {addressbook}" : "As creadu sa rubrica {addressbook}",
- "{actor} deleted address book {addressbook}" : "{actor} at cantzelladu sa rubrica {addressbook}",
- "You deleted address book {addressbook}" : "As cantzelladu sa rubrica {addressbook}",
- "{actor} updated address book {addressbook}" : "{actor} at agiornadu sa rubrica {addressbook}",
- "You updated address book {addressbook}" : "As agiornadu sa rubrica {addressbook}",
- "{actor} shared address book {addressbook} with you" : "{actor} at cumpartzidu sa rubrica {addressbook} cun tegus",
- "You shared address book {addressbook} with {user}" : "As cumpartzidu sa rubrica {addressbook} cun {user}",
- "{actor} shared address book {addressbook} with {user}" : "{actor} at cumpartzidu sa rubrica {addressbook} cun {user}",
- "{actor} unshared address book {addressbook} from you" : "{actor} at annulladu sa cumpartzidura de sa rubrica {addressbook} cun tegus",
- "You unshared address book {addressbook} from {user}" : "As annnulladu sa cumpartzidura de sa rubrica {addressbook} cun {user}",
- "{actor} unshared address book {addressbook} from {user}" : "{actor} at annulladu sa cumpartzidura de sa rubrica {addressbook} cun{user}",
- "{actor} unshared address book {addressbook} from themselves" : "{actor} at annulladu sa cumpartzidura de sa rubrica {addressbook} cun isse etotu",
- "You shared address book {addressbook} with group {group}" : "As cumpartzidu sa rubrica {addressbook} cun su grupu {group}",
- "{actor} shared address book {addressbook} with group {group}" : "{actor} at cumpartzidu sa rubrica {addressbook} cun su grupu {group}",
- "You unshared address book {addressbook} from group {group}" : "As annulladu sa cumpartzidura de sa rubrica {addressbook} cun su grupu {group}",
- "{actor} unshared address book {addressbook} from group {group}" : "{actor} at annulladu sa cumpartzidura de sa rubrica {addressbook} cun su grupu {group}",
- "{actor} created contact {card} in address book {addressbook}" : "{actor} at creadu su cuntatu {card} in sa rubrica {addressbook}",
- "You created contact {card} in address book {addressbook}" : "As creadu su cuntatu {card} in sa rubrica {addressbook}",
- "{actor} deleted contact {card} from address book {addressbook}" : "{actor} at cantzelladu su cuntatu {card} dae sa rubrica {addressbook}",
- "You deleted contact {card} from address book {addressbook}" : "As cantzelladu su cuntatu {card} dae sa rubrica {addressbook}",
- "{actor} updated contact {card} in address book {addressbook}" : "{actor} at agiornadu su cuntatu {card} in sa rubrica {addressbook}",
- "You updated contact {card} in address book {addressbook}" : "As agiornadu su cuntatu {card} in sa rubrica {addressbook}",
- "A <strong>contact</strong> or <strong>address book</strong> was modified" : "S'at modificadu unu <strong>cuntatu</strong> o <strong>rubrica</strong> ",
- "System is in maintenance mode." : "Sistema in modalidade de mantenidura.",
- "Upgrade needed" : "Tocat de agiornare",
- "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Su %s tuo tocat de lu cunfigurare pro s'impreu de HTTPS pro pòdere impreare CalDAV e CardDAV cun iOS/macOS.",
- "Configures a CalDAV account" : "Cunfigurat unu contu CalDAV",
- "Configures a CardDAV account" : "Configurat unu contu CardDAV ",
- "Events" : "Eventos",
- "Untitled task" : "Faina sena tìtulu",
- "Completed on %s" : "Cumpletada su %s",
- "Due on %s by %s" : "Iscadet su %s pro su %s",
- "Due on %s" : "iscadet su %s",
- "WebDAV endpoint" : "puntu finale WebDAV ",
- "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Su serbidore tuo no est cunfiguradu pro permìtere sa sincronizatzione de is archìvios, ca s'interfache WebDAV paret arrogada.",
- "WebDAV" : "WebDAV",
- "Save" : "Sarva",
- "to" : "a",
- "Calendar server" : "Serbidore calendàriu",
- "Send invitations to attendees" : "Imbia invitos de partetzipatziones",
- "Automatically generate a birthday calendar" : "Gènera in automàticu su calendàriu de cumpleannos",
- "Birthday calendars will be generated by a background job." : "Is calendàrios de cumpleannos ant a èssere generados pro mèdiu de un'atividade dae palas.",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Perintantu non ant a èssere a diponimentu deretu a pustis de s'abilitatzione, ma s'ant a pòdere bìdere in pagos segundos.",
- "Send notifications for events" : "Imbia is notìficas de is eventos",
- "Notifications are sent via background jobs, so these must occur often enough." : "Is notìficas sunt imbiadas tràmite atividades dae palas, pro cussu custas operatziones tocat de ddas fàghere bastante a s'ispissu.",
- "Enable notifications for events via push" : "Ativa is notìficas de is eventos tràmite push",
- "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Installa puru{calendarappstoreopen}s'aplicatzione calendàriu{linkclose}, o {calendardocopen}connete s'elaboradore de iscrivania e su telefoneddu pro ddos sincronizare↗{linkclose}.",
- "Please make sure to properly set up {emailopen}the email server{linkclose}." : "Assegura·ti de àere cunfiguradu bene {emailopen}su serbidore de posta{linkclose}.",
- "There was an error updating your attendance status." : "Ddoe at àpidu un'errore agiornende s'istadu de sa partetzipatzione tua.",
- "Please contact the organizer directly." : "Pro praghere, cuntata deretu a s'organizadore.",
- "Are you accepting the invitation?" : "Cheres atzetare s'invitu?",
- "Tentative" : "Intentu",
- "Your attendance was updated successfully." : "Sa partetzipatzione tua est istada agiornada in manera curreta.",
- "Time:" : "Tempus:"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/sc.json b/apps/dav/l10n/sc.json
deleted file mode 100644
index efc7b12079a..00000000000
--- a/apps/dav/l10n/sc.json
+++ /dev/null
@@ -1,149 +0,0 @@
-{ "translations": {
- "Calendar" : "Calendàriu",
- "Tasks" : "Fainas",
- "Personal" : "Personale",
- "{actor} created calendar {calendar}" : "{actor} at creadu su calendàriu {calendar}",
- "You created calendar {calendar}" : "As creadu su calendàriu {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} at cantzelladu su calendàriu {calendar}",
- "You deleted calendar {calendar}" : "As creadu su calendàriu {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} at agiornadu su calendàriu {calendar}",
- "You updated calendar {calendar}" : "As agiornadu su calendàriu {calendar}",
- "{actor} restored calendar {calendar}" : "{actor} at ripristinadu su calendàriu {calendar}",
- "You restored calendar {calendar}" : "As ripristinadu su calendàriu {calendar}",
- "You shared calendar {calendar} as public link" : "As cumpartzidu su calendàriu {calendar} comente ligòngiu pùblicu",
- "You removed public link for calendar {calendar}" : "Ci nd'as bogadu su ligòngiu pùblicu pro su calendàriu {calendar}",
- "{actor} shared calendar {calendar} with you" : "{actor} at cumpartzidu su calendàriu {calendar} cun tegus",
- "You shared calendar {calendar} with {user}" : "As cumpartzidu su calendàriu {calendar} cun {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} at cumpartzidu su calendàriu {calendar} cun {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} at annulladu sa cumpartzidura de su calendàriu {calendar} cun tegus",
- "You unshared calendar {calendar} from {user}" : "As annulladu sa cumpartzidura de su calendàriu {calendar} cun {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} at annulladu sa cumpartzidura de su calendàriu {calendar} cun {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} at annulladu sa cumpartzidura de su calendàriu {calendar} cun issu etotu",
- "You shared calendar {calendar} with group {group}" : "As cumpartzidu su calendàriu {calendar} cun su grupu {group}",
- "{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}",
- "You deleted event {event} from calendar {calendar}" : "As cantzelladu s'eventu {event} dae su calendàriu {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} at agiornadu s'eventu {event} in su calendàriu {calendar}",
- "You updated event {event} in calendar {calendar}" : "As agiornadu s'eventu {event} in su calendàriu {calendar}",
- "{actor} restored event {event} of calendar {calendar}" : "{actor} at ripristinadu s'eventu {event} in su calendàriu {calendar}",
- "You restored event {event} of calendar {calendar}" : "As ripristinadu s'eventu {event} in su calendàriu {calendar}",
- "Busy" : "Impinnadu",
- "Calendar, contacts and tasks" : "Calendàriu, cuntatos e fainas",
- "A <strong>calendar</strong> was modified" : "Unu <strong>calendàriu</strong> est istadu modificadu",
- "A calendar <strong>event</strong> was modified" : "Un'<strong>eventu</strong> de su calendàriu est istadu modificadu",
- "Contact birthdays" : "Data de nàschida de is cuntatos",
- "Death of %s" : "Morte de %s",
- "Untitled calendar" : "Calendàriu chene tìtulu",
- "Calendar:" : "Calendàriu:",
- "Date:" : "Data:",
- "Where:" : "Ue:",
- "Description:" : "Descritzione:",
- "_%n year_::_%n years_" : ["%n annu","%n annos"],
- "_%n month_::_%n months_" : ["%n meses","%n meses"],
- "_%n day_::_%n days_" : ["%n die","%n days"],
- "_%n hour_::_%n hours_" : ["%n ora","%n ora"],
- "_%n minute_::_%n minutes_" : ["%n minutos","%n minutos"],
- "%s (in %s)" : "%s (in %s)",
- "%s (%s ago)" : "%s (%s a immoe)",
- "Calendar: %s" : "Calendàriu: %s",
- "Date: %s" : "Data: %s",
- "Description: %s" : "Descritzione: %s",
- "Where: %s" : "Ue: %s",
- "%1$s via %2$s" : "%1$s cun %2$s",
- "Cancelled: %1$s" : "Annulladu: %1$s",
- "Re: %1$s" : "Re: %1$s",
- "Invitation: %1$s" : "Invitu: %1$s",
- "Organizer:" : "Organizadore: ",
- "Attendees:" : "Partetzipadores:",
- "Title:" : "Tìtulos:",
- "When:" : "Cando:",
- "Location:" : "Positzione:",
- "Link:" : "Ligòngiu:",
- "Accept" : "Atzeta",
- "Decline" : "Refuda",
- "More options …" : "Àteras optziones ...",
- "More options at %s" : "Àteras optziones a is %s",
- "Monday" : "Lunis",
- "Tuesday" : "Martis",
- "Wednesday" : "Mércuris",
- "Thursday" : "Giòbia",
- "Friday" : "Chenàbura",
- "Saturday" : "Sàbudu",
- "Sunday" : "Domìnigu",
- "January" : "Ghennàrgiu",
- "February" : "Freàrgiu",
- "March" : "Martzu",
- "April" : "Abrile",
- "May" : "Maju",
- "June" : "Làmparas",
- "July" : "Mese de Trìulas/Argiolas",
- "August" : "Austu",
- "September" : "Cabudanni",
- "October" : "Mese de Ladàmini/ Santu Aine",
- "November" : "Sant'Andria",
- "December" : "Nadale",
- "First" : "Primu",
- "Last" : "Ùrtimu",
- "Contacts" : "Cuntatos",
- "{actor} created address book {addressbook}" : "{actor} at creadu sa rubrica {addressbook}",
- "You created address book {addressbook}" : "As creadu sa rubrica {addressbook}",
- "{actor} deleted address book {addressbook}" : "{actor} at cantzelladu sa rubrica {addressbook}",
- "You deleted address book {addressbook}" : "As cantzelladu sa rubrica {addressbook}",
- "{actor} updated address book {addressbook}" : "{actor} at agiornadu sa rubrica {addressbook}",
- "You updated address book {addressbook}" : "As agiornadu sa rubrica {addressbook}",
- "{actor} shared address book {addressbook} with you" : "{actor} at cumpartzidu sa rubrica {addressbook} cun tegus",
- "You shared address book {addressbook} with {user}" : "As cumpartzidu sa rubrica {addressbook} cun {user}",
- "{actor} shared address book {addressbook} with {user}" : "{actor} at cumpartzidu sa rubrica {addressbook} cun {user}",
- "{actor} unshared address book {addressbook} from you" : "{actor} at annulladu sa cumpartzidura de sa rubrica {addressbook} cun tegus",
- "You unshared address book {addressbook} from {user}" : "As annnulladu sa cumpartzidura de sa rubrica {addressbook} cun {user}",
- "{actor} unshared address book {addressbook} from {user}" : "{actor} at annulladu sa cumpartzidura de sa rubrica {addressbook} cun{user}",
- "{actor} unshared address book {addressbook} from themselves" : "{actor} at annulladu sa cumpartzidura de sa rubrica {addressbook} cun isse etotu",
- "You shared address book {addressbook} with group {group}" : "As cumpartzidu sa rubrica {addressbook} cun su grupu {group}",
- "{actor} shared address book {addressbook} with group {group}" : "{actor} at cumpartzidu sa rubrica {addressbook} cun su grupu {group}",
- "You unshared address book {addressbook} from group {group}" : "As annulladu sa cumpartzidura de sa rubrica {addressbook} cun su grupu {group}",
- "{actor} unshared address book {addressbook} from group {group}" : "{actor} at annulladu sa cumpartzidura de sa rubrica {addressbook} cun su grupu {group}",
- "{actor} created contact {card} in address book {addressbook}" : "{actor} at creadu su cuntatu {card} in sa rubrica {addressbook}",
- "You created contact {card} in address book {addressbook}" : "As creadu su cuntatu {card} in sa rubrica {addressbook}",
- "{actor} deleted contact {card} from address book {addressbook}" : "{actor} at cantzelladu su cuntatu {card} dae sa rubrica {addressbook}",
- "You deleted contact {card} from address book {addressbook}" : "As cantzelladu su cuntatu {card} dae sa rubrica {addressbook}",
- "{actor} updated contact {card} in address book {addressbook}" : "{actor} at agiornadu su cuntatu {card} in sa rubrica {addressbook}",
- "You updated contact {card} in address book {addressbook}" : "As agiornadu su cuntatu {card} in sa rubrica {addressbook}",
- "A <strong>contact</strong> or <strong>address book</strong> was modified" : "S'at modificadu unu <strong>cuntatu</strong> o <strong>rubrica</strong> ",
- "System is in maintenance mode." : "Sistema in modalidade de mantenidura.",
- "Upgrade needed" : "Tocat de agiornare",
- "Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Su %s tuo tocat de lu cunfigurare pro s'impreu de HTTPS pro pòdere impreare CalDAV e CardDAV cun iOS/macOS.",
- "Configures a CalDAV account" : "Cunfigurat unu contu CalDAV",
- "Configures a CardDAV account" : "Configurat unu contu CardDAV ",
- "Events" : "Eventos",
- "Untitled task" : "Faina sena tìtulu",
- "Completed on %s" : "Cumpletada su %s",
- "Due on %s by %s" : "Iscadet su %s pro su %s",
- "Due on %s" : "iscadet su %s",
- "WebDAV endpoint" : "puntu finale WebDAV ",
- "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Su serbidore tuo no est cunfiguradu pro permìtere sa sincronizatzione de is archìvios, ca s'interfache WebDAV paret arrogada.",
- "WebDAV" : "WebDAV",
- "Save" : "Sarva",
- "to" : "a",
- "Calendar server" : "Serbidore calendàriu",
- "Send invitations to attendees" : "Imbia invitos de partetzipatziones",
- "Automatically generate a birthday calendar" : "Gènera in automàticu su calendàriu de cumpleannos",
- "Birthday calendars will be generated by a background job." : "Is calendàrios de cumpleannos ant a èssere generados pro mèdiu de un'atividade dae palas.",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Perintantu non ant a èssere a diponimentu deretu a pustis de s'abilitatzione, ma s'ant a pòdere bìdere in pagos segundos.",
- "Send notifications for events" : "Imbia is notìficas de is eventos",
- "Notifications are sent via background jobs, so these must occur often enough." : "Is notìficas sunt imbiadas tràmite atividades dae palas, pro cussu custas operatziones tocat de ddas fàghere bastante a s'ispissu.",
- "Enable notifications for events via push" : "Ativa is notìficas de is eventos tràmite push",
- "Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Installa puru{calendarappstoreopen}s'aplicatzione calendàriu{linkclose}, o {calendardocopen}connete s'elaboradore de iscrivania e su telefoneddu pro ddos sincronizare↗{linkclose}.",
- "Please make sure to properly set up {emailopen}the email server{linkclose}." : "Assegura·ti de àere cunfiguradu bene {emailopen}su serbidore de posta{linkclose}.",
- "There was an error updating your attendance status." : "Ddoe at àpidu un'errore agiornende s'istadu de sa partetzipatzione tua.",
- "Please contact the organizer directly." : "Pro praghere, cuntata deretu a s'organizadore.",
- "Are you accepting the invitation?" : "Cheres atzetare s'invitu?",
- "Tentative" : "Intentu",
- "Your attendance was updated successfully." : "Sa partetzipatzione tua est istada agiornada in manera curreta.",
- "Time:" : "Tempus:"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/sk.js b/apps/dav/l10n/sk.js
index 3441b763746..3282ec3109f 100644
--- a/apps/dav/l10n/sk.js
+++ b/apps/dav/l10n/sk.js
@@ -290,6 +290,17 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Vyberte začiatočný čas pre {dayName}",
"Pick a end time for {dayName}" : "Vyberte koncový čas pre {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automaticky nastaviť stav používateľa na „Nerušiť“ ak nie ste dostupný, pre stlmenie všetkých upozornení.",
+ "Cancel" : "Zrušiť",
+ "Import" : "Import",
+ "Error while saving settings" : "Chyba pri ukladaní nastavení",
+ "Contact reset successfully" : "Kontakt bol úspešne resetovaný",
+ "Error while resetting contact" : "Chyba počas resetovania kontaktu ",
+ "Contact imported successfully" : "Kontakt bol úspešne importovaný",
+ "Error while importing contact" : "Chyba pri importovaní kontaktu",
+ "Import contact" : "Importovať kontakt",
+ "Reset to default" : "Nastaviť predvolené",
+ "Import contacts" : "Importovať kontakty",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Importovaním nového súboru .vcf sa vymaže existujúci predvolený kontakt a nahradí sa novým. Chcete pokračovať?",
"Availability" : "Dostupnosť",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Ak nakonfigurujete svoj pracovný čas, ostatní užívatelia vás uvidia ako neprítomného, keď si rezervujete schôdzku",
"Absence" : "Neprítomnosť",
@@ -306,27 +317,10 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Posielať upozornenia na pripomienky aj zdieľaným osobám v kalendári",
"Reminders are always sent to organizers and attendees." : "Upozornenia sa vždy posielajú organizátorom a účastníkom.",
"Enable notifications for events via push" : "Zapnúť oznámenia o udalostiach prostredníctvom technológie push.",
- "Cancel" : "Zrušiť",
- "Import" : "Import",
- "Error while saving settings" : "Chyba pri ukladaní nastavení",
- "Contact reset successfully" : "Kontakt bol úspešne resetovaný",
- "Error while resetting contact" : "Chyba počas resetovania kontaktu ",
- "Contact imported successfully" : "Kontakt bol úspešne importovaný",
- "Error while importing contact" : "Chyba pri importovaní kontaktu",
- "Example Content" : "Príklad Obsahu",
- "Set example content to be created on new user first login." : "Nastavte vzorový obsah, ktorý sa vytvorí pri prvom prihlásení nového používateľa.",
- "Import contact" : "Importovať kontakt",
- "Reset to default contact" : "Resetovať na predvolený kontakt",
- "Import contacts" : "Importovať kontakty",
- "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Importovaním nového súboru .vcf sa vymaže existujúci predvolený kontakt a nahradí sa novým. Chcete pokračovať?",
"There was an error updating your attendance status." : "Nastal problém pri aktualizácii Vašej účasti.",
"Please contact the organizer directly." : "Prosím kontaktujte priamo organizátora.",
"Are you accepting the invitation?" : "Príjmate pozvánku?",
"Tentative" : "Neistý",
- "Your attendance was updated successfully." : "Vaša účasť bola aktualizovaná úspešne.",
- "Time:" : "Čas:",
- "Could not open file" : "Súbor sa nepodarilo otvoriť",
- "Invalid chunk name" : "Neplatný názov bloku",
- "Could not rename part file assembled from chunks" : "Nepodarilo sa premenovať dočasný súbor vytvorený z blokov"
+ "Your attendance was updated successfully." : "Vaša účasť bola aktualizovaná úspešne."
},
"nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);");
diff --git a/apps/dav/l10n/sk.json b/apps/dav/l10n/sk.json
index 06c7d094a5e..a0da2d19cd3 100644
--- a/apps/dav/l10n/sk.json
+++ b/apps/dav/l10n/sk.json
@@ -288,6 +288,17 @@
"Pick a start time for {dayName}" : "Vyberte začiatočný čas pre {dayName}",
"Pick a end time for {dayName}" : "Vyberte koncový čas pre {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automaticky nastaviť stav používateľa na „Nerušiť“ ak nie ste dostupný, pre stlmenie všetkých upozornení.",
+ "Cancel" : "Zrušiť",
+ "Import" : "Import",
+ "Error while saving settings" : "Chyba pri ukladaní nastavení",
+ "Contact reset successfully" : "Kontakt bol úspešne resetovaný",
+ "Error while resetting contact" : "Chyba počas resetovania kontaktu ",
+ "Contact imported successfully" : "Kontakt bol úspešne importovaný",
+ "Error while importing contact" : "Chyba pri importovaní kontaktu",
+ "Import contact" : "Importovať kontakt",
+ "Reset to default" : "Nastaviť predvolené",
+ "Import contacts" : "Importovať kontakty",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Importovaním nového súboru .vcf sa vymaže existujúci predvolený kontakt a nahradí sa novým. Chcete pokračovať?",
"Availability" : "Dostupnosť",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Ak nakonfigurujete svoj pracovný čas, ostatní užívatelia vás uvidia ako neprítomného, keď si rezervujete schôdzku",
"Absence" : "Neprítomnosť",
@@ -304,27 +315,10 @@
"Send reminder notifications to calendar sharees as well" : "Posielať upozornenia na pripomienky aj zdieľaným osobám v kalendári",
"Reminders are always sent to organizers and attendees." : "Upozornenia sa vždy posielajú organizátorom a účastníkom.",
"Enable notifications for events via push" : "Zapnúť oznámenia o udalostiach prostredníctvom technológie push.",
- "Cancel" : "Zrušiť",
- "Import" : "Import",
- "Error while saving settings" : "Chyba pri ukladaní nastavení",
- "Contact reset successfully" : "Kontakt bol úspešne resetovaný",
- "Error while resetting contact" : "Chyba počas resetovania kontaktu ",
- "Contact imported successfully" : "Kontakt bol úspešne importovaný",
- "Error while importing contact" : "Chyba pri importovaní kontaktu",
- "Example Content" : "Príklad Obsahu",
- "Set example content to be created on new user first login." : "Nastavte vzorový obsah, ktorý sa vytvorí pri prvom prihlásení nového používateľa.",
- "Import contact" : "Importovať kontakt",
- "Reset to default contact" : "Resetovať na predvolený kontakt",
- "Import contacts" : "Importovať kontakty",
- "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Importovaním nového súboru .vcf sa vymaže existujúci predvolený kontakt a nahradí sa novým. Chcete pokračovať?",
"There was an error updating your attendance status." : "Nastal problém pri aktualizácii Vašej účasti.",
"Please contact the organizer directly." : "Prosím kontaktujte priamo organizátora.",
"Are you accepting the invitation?" : "Príjmate pozvánku?",
"Tentative" : "Neistý",
- "Your attendance was updated successfully." : "Vaša účasť bola aktualizovaná úspešne.",
- "Time:" : "Čas:",
- "Could not open file" : "Súbor sa nepodarilo otvoriť",
- "Invalid chunk name" : "Neplatný názov bloku",
- "Could not rename part file assembled from chunks" : "Nepodarilo sa premenovať dočasný súbor vytvorený z blokov"
+ "Your attendance was updated successfully." : "Vaša účasť bola aktualizovaná úspešne."
},"pluralForm" :"nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/sl.js b/apps/dav/l10n/sl.js
index 586b8446c5d..f33a677c95c 100644
--- a/apps/dav/l10n/sl.js
+++ b/apps/dav/l10n/sl.js
@@ -198,6 +198,10 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Izbor časa začetka za {dayName}",
"Pick a end time for {dayName}" : "Izbor časa konca za {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Samodejno nastavi stanje uporabnika na »Ne moti« in zavračaj prikaz obvestil izven časa razpoložljivosti.",
+ "Cancel" : "Prekliči",
+ "Import" : "Uvozi",
+ "Error while saving settings" : "Prišlo je do napake med shranjevanjem nastavitev",
+ "Reset to default" : "Ponastavi na privzeto",
"Availability" : "Razpoložljivost",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Če nastavite delovni čas, bodo drugi uporabniki pri izbiri časa sestanka videli, kdaj ste zasedeni.",
"Absence" : "Odsotnost",
@@ -214,17 +218,10 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Pošiljanje opomnikov tudi naročnikom koledarja.",
"Reminders are always sent to organizers and attendees." : "Opomniki bodo vedno poslani organizatorjem in udeležencem.",
"Enable notifications for events via push" : "Omogoči potisna obvestila za dogodke",
- "Cancel" : "Prekliči",
- "Import" : "Uvozi",
- "Error while saving settings" : "Prišlo je do napake med shranjevanjem nastavitev",
"There was an error updating your attendance status." : "Prišlo je do napake med posodabljanjem vaše udeležbe.",
"Please contact the organizer directly." : "Z organizatorjem stopite neposredno v stik.",
"Are you accepting the invitation?" : "Ali želite sprejeti povabilo?",
"Tentative" : "Začasno",
- "Your attendance was updated successfully." : "Vaša prisotnost je uspešno posodobljena.",
- "Time:" : "Čas:",
- "Could not open file" : "Datoteke ni mogoče odpreti",
- "Invalid chunk name" : "Neveljavno ime dela",
- "Could not rename part file assembled from chunks" : "Ni mogoče preimenovati delne datoteke, združene iz delov."
+ "Your attendance was updated successfully." : "Vaša prisotnost je uspešno posodobljena."
},
"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);");
diff --git a/apps/dav/l10n/sl.json b/apps/dav/l10n/sl.json
index 56efe70d043..423b215a669 100644
--- a/apps/dav/l10n/sl.json
+++ b/apps/dav/l10n/sl.json
@@ -196,6 +196,10 @@
"Pick a start time for {dayName}" : "Izbor časa začetka za {dayName}",
"Pick a end time for {dayName}" : "Izbor časa konca za {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Samodejno nastavi stanje uporabnika na »Ne moti« in zavračaj prikaz obvestil izven časa razpoložljivosti.",
+ "Cancel" : "Prekliči",
+ "Import" : "Uvozi",
+ "Error while saving settings" : "Prišlo je do napake med shranjevanjem nastavitev",
+ "Reset to default" : "Ponastavi na privzeto",
"Availability" : "Razpoložljivost",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Če nastavite delovni čas, bodo drugi uporabniki pri izbiri časa sestanka videli, kdaj ste zasedeni.",
"Absence" : "Odsotnost",
@@ -212,17 +216,10 @@
"Send reminder notifications to calendar sharees as well" : "Pošiljanje opomnikov tudi naročnikom koledarja.",
"Reminders are always sent to organizers and attendees." : "Opomniki bodo vedno poslani organizatorjem in udeležencem.",
"Enable notifications for events via push" : "Omogoči potisna obvestila za dogodke",
- "Cancel" : "Prekliči",
- "Import" : "Uvozi",
- "Error while saving settings" : "Prišlo je do napake med shranjevanjem nastavitev",
"There was an error updating your attendance status." : "Prišlo je do napake med posodabljanjem vaše udeležbe.",
"Please contact the organizer directly." : "Z organizatorjem stopite neposredno v stik.",
"Are you accepting the invitation?" : "Ali želite sprejeti povabilo?",
"Tentative" : "Začasno",
- "Your attendance was updated successfully." : "Vaša prisotnost je uspešno posodobljena.",
- "Time:" : "Čas:",
- "Could not open file" : "Datoteke ni mogoče odpreti",
- "Invalid chunk name" : "Neveljavno ime dela",
- "Could not rename part file assembled from chunks" : "Ni mogoče preimenovati delne datoteke, združene iz delov."
+ "Your attendance was updated successfully." : "Vaša prisotnost je uspešno posodobljena."
},"pluralForm" :"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/sq.js b/apps/dav/l10n/sq.js
deleted file mode 100644
index 0fc1d01d825..00000000000
--- a/apps/dav/l10n/sq.js
+++ /dev/null
@@ -1,63 +0,0 @@
-OC.L10N.register(
- "dav",
- {
- "Calendar" : "Kalendar",
- "Todos" : "Për tu bërë",
- "Personal" : "Personale",
- "{actor} created calendar {calendar}" : "{aktori} krijoi kalendarin {kalendarin}",
- "You created calendar {calendar}" : "Ju krijuat kalendarin {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} fshiu kalendarin {calendar}",
- "You deleted calendar {calendar}" : "Ju fshit kalendarin {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} përditësoi kalendarin {calendar}",
- "You updated calendar {calendar}" : "Ju përditësuat kalendarin {calendar}",
- "{actor} shared calendar {calendar} with you" : " {actor} ndau kalendarin {calendar} me ju",
- "You shared calendar {calendar} with {user}" : "Ju ndat kalendarin {calendar} me {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} ndau kalendarin {calendar} me {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ndaloj së ndari kalendarin {calendar} me ju",
- "You unshared calendar {calendar} from {user}" : "Ju ndaluat së ndari kalendarin {calendar} me {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} ndaloj së ndari kalendarin {calendar} me {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} ndaloj së ndari kalendarin {calendar} me veten",
- "You shared calendar {calendar} with group {group}" : "Ju ndat kalendarin {calendar} me grupin {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} ndau kalendarin {calendar} me grupin {group}",
- "You unshared calendar {calendar} from group {group}" : "Ju ndaluat së ndari kalendarin {calendar} me grupin {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} ndaloj së ndari kalendarin {calendar} me grupin {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} krijoj eventin {event} në kalendarin {calendar}",
- "You created event {event} in calendar {calendar}" : "Ju krijuat eventin {event} në kalendarin {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} fshiu eventin {event} nga kalendari {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Ju fshit eventin {event} nga kalndari {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} përditsoi eventin {event} në kalndarin {calendar}",
- "You updated event {event} in calendar {calendar}" : "Ju përditësuat eventin {event} në kalndarin {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} u krijua todo{todo} në listën {calendar}",
- "You created todo {todo} in list {calendar}" : "Ju krijuat todo {todo} në listën {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} u fshi todo{ todo} nga lista{calendar}",
- "You deleted todo {todo} from list {calendar}" : "Ju fshit todo{todo} nga lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} u përditësua todo{todo} në listën{calendar}",
- "You updated todo {todo} in list {calendar}" : "Ju përditësuat përtëbërë {todo} në listën{calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} zgjidhi përtëbërë {todo} në listën {calendar}",
- "You solved todo {todo} in list {calendar}" : "Ju zgjidhët përtëbërë {todo} në listën {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} rihapi përtëbërë {todo} në listën {calendar}",
- "You reopened todo {todo} in list {calendar}" : "Ju rihapët përtëbërë {todo} në listën {calendar}",
- "A <strong>calendar</strong> was modified" : "Një <strong>kalendar</strong> u modifikua",
- "A calendar <strong>event</strong> was modified" : "Një <strong>event</strong> në kalendar u modifikua",
- "A calendar <strong>todo</strong> was modified" : "Një kalendar <strong>todo<strong> u modifikua",
- "Contact birthdays" : "Ditëlindjet e kontakteve",
- "Where:" : "Ku:",
- "Description:" : "Përshkrimi:",
- "Invitation canceled" : "Ftesa u anullua",
- "Invitation updated" : "Ftesa u përditësua",
- "Location:" : "Vendndodhje:",
- "Link:" : "Link:",
- "Accept" : "Prano",
- "Decline" : "Refuzo",
- "More options …" : "Më shumë opsione ...",
- "Contacts" : "Kontaktet",
- "Tasks" : "Detyra",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativë",
- "Save" : "Ruaj",
- "Your attendance was updated successfully." : "Pjesëmarrja juaj u përditësua me sukses.",
- "Send invitations to attendees" : "Dërgo ftesa tek pjesëmarrësit",
- "Hello %s," : "Përshëndetje %s,",
- "When:" : "Kur:"
-},
-"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/sq.json b/apps/dav/l10n/sq.json
deleted file mode 100644
index 128ad854cac..00000000000
--- a/apps/dav/l10n/sq.json
+++ /dev/null
@@ -1,61 +0,0 @@
-{ "translations": {
- "Calendar" : "Kalendar",
- "Todos" : "Për tu bërë",
- "Personal" : "Personale",
- "{actor} created calendar {calendar}" : "{aktori} krijoi kalendarin {kalendarin}",
- "You created calendar {calendar}" : "Ju krijuat kalendarin {calendar}",
- "{actor} deleted calendar {calendar}" : "{actor} fshiu kalendarin {calendar}",
- "You deleted calendar {calendar}" : "Ju fshit kalendarin {calendar}",
- "{actor} updated calendar {calendar}" : "{actor} përditësoi kalendarin {calendar}",
- "You updated calendar {calendar}" : "Ju përditësuat kalendarin {calendar}",
- "{actor} shared calendar {calendar} with you" : " {actor} ndau kalendarin {calendar} me ju",
- "You shared calendar {calendar} with {user}" : "Ju ndat kalendarin {calendar} me {user}",
- "{actor} shared calendar {calendar} with {user}" : "{actor} ndau kalendarin {calendar} me {user}",
- "{actor} unshared calendar {calendar} from you" : "{actor} ndaloj së ndari kalendarin {calendar} me ju",
- "You unshared calendar {calendar} from {user}" : "Ju ndaluat së ndari kalendarin {calendar} me {user}",
- "{actor} unshared calendar {calendar} from {user}" : "{actor} ndaloj së ndari kalendarin {calendar} me {user}",
- "{actor} unshared calendar {calendar} from themselves" : "{actor} ndaloj së ndari kalendarin {calendar} me veten",
- "You shared calendar {calendar} with group {group}" : "Ju ndat kalendarin {calendar} me grupin {group}",
- "{actor} shared calendar {calendar} with group {group}" : "{actor} ndau kalendarin {calendar} me grupin {group}",
- "You unshared calendar {calendar} from group {group}" : "Ju ndaluat së ndari kalendarin {calendar} me grupin {group}",
- "{actor} unshared calendar {calendar} from group {group}" : "{actor} ndaloj së ndari kalendarin {calendar} me grupin {group}",
- "{actor} created event {event} in calendar {calendar}" : "{actor} krijoj eventin {event} në kalendarin {calendar}",
- "You created event {event} in calendar {calendar}" : "Ju krijuat eventin {event} në kalendarin {calendar}",
- "{actor} deleted event {event} from calendar {calendar}" : "{actor} fshiu eventin {event} nga kalendari {calendar}",
- "You deleted event {event} from calendar {calendar}" : "Ju fshit eventin {event} nga kalndari {calendar}",
- "{actor} updated event {event} in calendar {calendar}" : "{actor} përditsoi eventin {event} në kalndarin {calendar}",
- "You updated event {event} in calendar {calendar}" : "Ju përditësuat eventin {event} në kalndarin {calendar}",
- "{actor} created todo {todo} in list {calendar}" : "{actor} u krijua todo{todo} në listën {calendar}",
- "You created todo {todo} in list {calendar}" : "Ju krijuat todo {todo} në listën {calendar}",
- "{actor} deleted todo {todo} from list {calendar}" : "{actor} u fshi todo{ todo} nga lista{calendar}",
- "You deleted todo {todo} from list {calendar}" : "Ju fshit todo{todo} nga lista {calendar}",
- "{actor} updated todo {todo} in list {calendar}" : "{actor} u përditësua todo{todo} në listën{calendar}",
- "You updated todo {todo} in list {calendar}" : "Ju përditësuat përtëbërë {todo} në listën{calendar}",
- "{actor} solved todo {todo} in list {calendar}" : "{actor} zgjidhi përtëbërë {todo} në listën {calendar}",
- "You solved todo {todo} in list {calendar}" : "Ju zgjidhët përtëbërë {todo} në listën {calendar}",
- "{actor} reopened todo {todo} in list {calendar}" : "{actor} rihapi përtëbërë {todo} në listën {calendar}",
- "You reopened todo {todo} in list {calendar}" : "Ju rihapët përtëbërë {todo} në listën {calendar}",
- "A <strong>calendar</strong> was modified" : "Një <strong>kalendar</strong> u modifikua",
- "A calendar <strong>event</strong> was modified" : "Një <strong>event</strong> në kalendar u modifikua",
- "A calendar <strong>todo</strong> was modified" : "Një kalendar <strong>todo<strong> u modifikua",
- "Contact birthdays" : "Ditëlindjet e kontakteve",
- "Where:" : "Ku:",
- "Description:" : "Përshkrimi:",
- "Invitation canceled" : "Ftesa u anullua",
- "Invitation updated" : "Ftesa u përditësua",
- "Location:" : "Vendndodhje:",
- "Link:" : "Link:",
- "Accept" : "Prano",
- "Decline" : "Refuzo",
- "More options …" : "Më shumë opsione ...",
- "Contacts" : "Kontaktet",
- "Tasks" : "Detyra",
- "WebDAV" : "WebDAV",
- "Tentative" : "Tentativë",
- "Save" : "Ruaj",
- "Your attendance was updated successfully." : "Pjesëmarrja juaj u përditësua me sukses.",
- "Send invitations to attendees" : "Dërgo ftesa tek pjesëmarrësit",
- "Hello %s," : "Përshëndetje %s,",
- "When:" : "Kur:"
-},"pluralForm" :"nplurals=2; plural=(n != 1);"
-} \ No newline at end of file
diff --git a/apps/dav/l10n/sr.js b/apps/dav/l10n/sr.js
index 8655196e000..c33b7c28923 100644
--- a/apps/dav/l10n/sr.js
+++ b/apps/dav/l10n/sr.js
@@ -290,6 +290,25 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Изаберите време почетка за {dayName}",
"Pick a end time for {dayName}" : "Изаберите време завршетка за {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Аутоматски поставља статус кориниска на „Не узнемиравај” како би се ван доступности пригушила сва обавештења.",
+ "Cancel" : "Откажи",
+ "Import" : "Увоз",
+ "Error while saving settings" : "Грешка приликом чувања подешавања",
+ "Contact reset successfully" : "Контакт је успешно ресетован",
+ "Error while resetting contact" : "Грешка приликом ресетовања контакта",
+ "Contact imported successfully" : "Контакт је успешно увезен",
+ "Error while importing contact" : "Грешка током увоза контакта",
+ "Import contact" : "Увези контакт",
+ "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,27 +325,12 @@ 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" : "Укључи обавештења за догађаје преко гурања догађаја",
- "Cancel" : "Откажи",
- "Import" : "Увоз",
- "Error while saving settings" : "Грешка приликом чувања подешавања",
- "Contact reset successfully" : "Контакт је успешно ресетован",
- "Error while resetting contact" : "Грешка приликом ресетовања контакта",
- "Contact imported successfully" : "Контакт је успешно увезен",
- "Error while importing contact" : "Грешка током увоза контакта",
- "Example Content" : "Пример садржаја",
- "Set example content to be created on new user first login." : "Постављање примера садржаја који се креира приликом прве пријаве новог корисника.",
- "Import contact" : "Увези контакт",
- "Reset to default contact" : "Ресетуј на подразумевани контакт",
- "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 фајла ће да обрише постојећи подразумевани контакт и замениће га са новим. Желите ли да наставите?",
+ "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?" : "Да ли прихватате позивницу?",
"Tentative" : "Условна потврда",
- "Your attendance was updated successfully." : "Ваше присуство је успешно ажурирано.",
- "Time:" : "Време:",
- "Could not open file" : "Фајл не може да се отвори",
- "Invalid chunk name" : "Неисправни назив комада",
- "Could not rename part file assembled from chunks" : "Име делимичног фајла састављеног од комада не може да се промени"
+ "Your attendance was updated successfully." : "Ваше присуство је успешно ажурирано."
},
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);");
diff --git a/apps/dav/l10n/sr.json b/apps/dav/l10n/sr.json
index 597b4174ab4..7df27149b4f 100644
--- a/apps/dav/l10n/sr.json
+++ b/apps/dav/l10n/sr.json
@@ -288,6 +288,25 @@
"Pick a start time for {dayName}" : "Изаберите време почетка за {dayName}",
"Pick a end time for {dayName}" : "Изаберите време завршетка за {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Аутоматски поставља статус кориниска на „Не узнемиравај” како би се ван доступности пригушила сва обавештења.",
+ "Cancel" : "Откажи",
+ "Import" : "Увоз",
+ "Error while saving settings" : "Грешка приликом чувања подешавања",
+ "Contact reset successfully" : "Контакт је успешно ресетован",
+ "Error while resetting contact" : "Грешка приликом ресетовања контакта",
+ "Contact imported successfully" : "Контакт је успешно увезен",
+ "Error while importing contact" : "Грешка током увоза контакта",
+ "Import contact" : "Увези контакт",
+ "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" : "Одсутност",
@@ -304,27 +323,12 @@
"Send reminder notifications to calendar sharees as well" : "Пошаљи подсетнике и корисницима којима је календар подељен",
"Reminders are always sent to organizers and attendees." : "Подсетници се увек шаљу организаторима и учесницима.",
"Enable notifications for events via push" : "Укључи обавештења за догађаје преко гурања догађаја",
- "Cancel" : "Откажи",
- "Import" : "Увоз",
- "Error while saving settings" : "Грешка приликом чувања подешавања",
- "Contact reset successfully" : "Контакт је успешно ресетован",
- "Error while resetting contact" : "Грешка приликом ресетовања контакта",
- "Contact imported successfully" : "Контакт је успешно увезен",
- "Error while importing contact" : "Грешка током увоза контакта",
- "Example Content" : "Пример садржаја",
- "Set example content to be created on new user first login." : "Постављање примера садржаја који се креира приликом прве пријаве новог корисника.",
- "Import contact" : "Увези контакт",
- "Reset to default contact" : "Ресетуј на подразумевани контакт",
- "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 фајла ће да обрише постојећи подразумевани контакт и замениће га са новим. Желите ли да наставите?",
+ "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?" : "Да ли прихватате позивницу?",
"Tentative" : "Условна потврда",
- "Your attendance was updated successfully." : "Ваше присуство је успешно ажурирано.",
- "Time:" : "Време:",
- "Could not open file" : "Фајл не може да се отвори",
- "Invalid chunk name" : "Неисправни назив комада",
- "Could not rename part file assembled from chunks" : "Име делимичног фајла састављеног од комада не може да се промени"
+ "Your attendance was updated successfully." : "Ваше присуство је успешно ажурирано."
},"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/sv.js b/apps/dav/l10n/sv.js
index 018017b3b24..feb1adde944 100644
--- a/apps/dav/l10n/sv.js
+++ b/apps/dav/l10n/sv.js
@@ -290,6 +290,25 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Välj en starttid för {dayName}",
"Pick a end time for {dayName}" : "Välj en sluttid för {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Sätt automatiskt användarstatus till \"Stör ej\" utanför tillgängliga tider för att tysta alla notifikationer.",
+ "Cancel" : "Avbryt",
+ "Import" : "Importera",
+ "Error while saving settings" : "Fel vid sparande av inställningar",
+ "Contact reset successfully" : "Kontakten har återställts",
+ "Error while resetting contact" : "Fel vid återställning av kontakt",
+ "Contact imported successfully" : "Kontakten har importerats",
+ "Error while importing contact" : "Fel vid import av kontakt",
+ "Import contact" : "Importera kontakt",
+ "Reset to default" : "Återställ till grundinställningar",
+ "Import contacts" : "Importera kontakter",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Att importera en ny .vcf-fil kommer att radera den befintliga standardkontakten och ersätta den med den nya. Vill du fortsätta?",
+ "Failed to save example event creation setting" : "Kunde inte spara exemplet för inställning av händelseskapande",
+ "Failed to upload the example event" : "Kunde inte ladda upp exempelhändelsen",
+ "Custom example event was saved successfully" : "Anpassad exempelhändelse sparades",
+ "Failed to delete the custom example event" : "Kunde inte ta bort den anpassade exempelhändelsen",
+ "Custom example event was deleted successfully" : "Anpassad exempelhändelse har raderats",
+ "Import calendar event" : "Importera kalenderhändelse",
+ "Uploading a new event will overwrite the existing one." : "Om du laddar upp en ny händelse kommer den att skriva över den befintliga.",
+ "Upload event" : "Ladda upp händelse",
"Availability" : "Din tillgänglighet",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Om du konfigurerar dina arbetstider kommer andra att se när du är frånvarande när de bokar ett möte.",
"Absence" : "Frånvaro",
@@ -306,27 +325,12 @@ OC.L10N.register(
"Send reminder notifications to calendar sharees as well" : "Skicka även påminnelser till kalenderdeltagare",
"Reminders are always sent to organizers and attendees." : "Påminnelser skickas alltid till arrangörer och deltagare.",
"Enable notifications for events via push" : "Aktivera notiser för händelser via push",
- "Cancel" : "Avbryt",
- "Import" : "Importera",
- "Error while saving settings" : "Fel vid sparande av inställningar",
- "Contact reset successfully" : "Kontakten har återställts",
- "Error while resetting contact" : "Fel vid återställning av kontakt",
- "Contact imported successfully" : "Kontakten har importerats",
- "Error while importing contact" : "Fel vid import av kontakt",
- "Example Content" : "Exempelinnehåll",
- "Set example content to be created on new user first login." : "Ställ in exempelinnehåll som ska skapas vid ny användares första inloggning.",
- "Import contact" : "Importera kontakt",
- "Reset to default contact" : "Återställ till standardkontakt",
- "Import contacts" : "Importera kontakter",
- "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Att importera en ny .vcf-fil kommer att radera den befintliga standardkontakten och ersätta den med den nya. Vill du fortsätta?",
+ "Example content" : "Exempelinnehåll",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Exempelinnehåll används för att visa upp funktionerna i Nextcloud. Standardinnehåll levereras med Nextcloud och kan ersättas med anpassat innehåll.",
"There was an error updating your attendance status." : "Ett fel uppstod vid uppdatering av din närvarostatus.",
"Please contact the organizer directly." : "Vänligen kontakta arrangören direkt.",
"Are you accepting the invitation?" : "Acceptera inbjudan?",
"Tentative" : "Preliminärt",
- "Your attendance was updated successfully." : "Dina närvaro uppdaterades.",
- "Time:" : "Tid:",
- "Could not open file" : "Kunde inte öppna fil",
- "Invalid chunk name" : "Ogiltigt delnamn",
- "Could not rename part file assembled from chunks" : "Kunde inte ändra namn på temporära filen ihopsatt från delar"
+ "Your attendance was updated successfully." : "Dina närvaro uppdaterades."
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/sv.json b/apps/dav/l10n/sv.json
index 8fa63d882fb..0496461778f 100644
--- a/apps/dav/l10n/sv.json
+++ b/apps/dav/l10n/sv.json
@@ -288,6 +288,25 @@
"Pick a start time for {dayName}" : "Välj en starttid för {dayName}",
"Pick a end time for {dayName}" : "Välj en sluttid för {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Sätt automatiskt användarstatus till \"Stör ej\" utanför tillgängliga tider för att tysta alla notifikationer.",
+ "Cancel" : "Avbryt",
+ "Import" : "Importera",
+ "Error while saving settings" : "Fel vid sparande av inställningar",
+ "Contact reset successfully" : "Kontakten har återställts",
+ "Error while resetting contact" : "Fel vid återställning av kontakt",
+ "Contact imported successfully" : "Kontakten har importerats",
+ "Error while importing contact" : "Fel vid import av kontakt",
+ "Import contact" : "Importera kontakt",
+ "Reset to default" : "Återställ till grundinställningar",
+ "Import contacts" : "Importera kontakter",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Att importera en ny .vcf-fil kommer att radera den befintliga standardkontakten och ersätta den med den nya. Vill du fortsätta?",
+ "Failed to save example event creation setting" : "Kunde inte spara exemplet för inställning av händelseskapande",
+ "Failed to upload the example event" : "Kunde inte ladda upp exempelhändelsen",
+ "Custom example event was saved successfully" : "Anpassad exempelhändelse sparades",
+ "Failed to delete the custom example event" : "Kunde inte ta bort den anpassade exempelhändelsen",
+ "Custom example event was deleted successfully" : "Anpassad exempelhändelse har raderats",
+ "Import calendar event" : "Importera kalenderhändelse",
+ "Uploading a new event will overwrite the existing one." : "Om du laddar upp en ny händelse kommer den att skriva över den befintliga.",
+ "Upload event" : "Ladda upp händelse",
"Availability" : "Din tillgänglighet",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Om du konfigurerar dina arbetstider kommer andra att se när du är frånvarande när de bokar ett möte.",
"Absence" : "Frånvaro",
@@ -304,27 +323,12 @@
"Send reminder notifications to calendar sharees as well" : "Skicka även påminnelser till kalenderdeltagare",
"Reminders are always sent to organizers and attendees." : "Påminnelser skickas alltid till arrangörer och deltagare.",
"Enable notifications for events via push" : "Aktivera notiser för händelser via push",
- "Cancel" : "Avbryt",
- "Import" : "Importera",
- "Error while saving settings" : "Fel vid sparande av inställningar",
- "Contact reset successfully" : "Kontakten har återställts",
- "Error while resetting contact" : "Fel vid återställning av kontakt",
- "Contact imported successfully" : "Kontakten har importerats",
- "Error while importing contact" : "Fel vid import av kontakt",
- "Example Content" : "Exempelinnehåll",
- "Set example content to be created on new user first login." : "Ställ in exempelinnehåll som ska skapas vid ny användares första inloggning.",
- "Import contact" : "Importera kontakt",
- "Reset to default contact" : "Återställ till standardkontakt",
- "Import contacts" : "Importera kontakter",
- "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Att importera en ny .vcf-fil kommer att radera den befintliga standardkontakten och ersätta den med den nya. Vill du fortsätta?",
+ "Example content" : "Exempelinnehåll",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Exempelinnehåll används för att visa upp funktionerna i Nextcloud. Standardinnehåll levereras med Nextcloud och kan ersättas med anpassat innehåll.",
"There was an error updating your attendance status." : "Ett fel uppstod vid uppdatering av din närvarostatus.",
"Please contact the organizer directly." : "Vänligen kontakta arrangören direkt.",
"Are you accepting the invitation?" : "Acceptera inbjudan?",
"Tentative" : "Preliminärt",
- "Your attendance was updated successfully." : "Dina närvaro uppdaterades.",
- "Time:" : "Tid:",
- "Could not open file" : "Kunde inte öppna fil",
- "Invalid chunk name" : "Ogiltigt delnamn",
- "Could not rename part file assembled from chunks" : "Kunde inte ändra namn på temporära filen ihopsatt från delar"
+ "Your attendance was updated successfully." : "Dina närvaro uppdaterades."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/tr.js b/apps/dav/l10n/tr.js
index f98655d1efb..9d1ed13b4f9 100644
--- a/apps/dav/l10n/tr.js
+++ b/apps/dav/l10n/tr.js
@@ -250,6 +250,8 @@ OC.L10N.register(
"Completed on %s" : "%s tarihinde tamamlandı",
"Due on %s by %s" : "%s tarihine kadar %s tarafından",
"Due on %s" : "%s tarihine kadar",
+ "Welcome to Nextcloud Calendar!\n\nThis is a sample event - explore the flexibility of planning with Nextcloud Calendar by making any edits you want!\n\nWith Nextcloud Calendar, you can:\n- Create, edit, and manage events effortlessly.\n- Create multiple calendars and share them with teammates, friends, or family.\n- Check availability and display your busy times to others.\n- Seamlessly integrate with apps and devices via CalDAV.\n- Customize your experience: schedule recurring events, adjust notifications and other settings." : "Nextcloud Takvim uygulamasına hoş geldiniz!\n\nBu bir örnek etkinliktir. İstediğiniz düzenlemeleri yaparak Nextcloud Takvim ile planlamanın esnekliğini keşfedin!\n\nNextcloud Takvim ile şunları yapabilirsiniz:\n- Etkinlikleri kolayca oluşturabilir, düzenleyebilir ve yönetebilirsiniz.\n- Birden fazla takvim oluşturabilir ve bunları takım arkadaşlarınız, arkadaşlarınız veya ailenizle paylaşabilirsiniz.\n- Uygunluğunuzu kontrol edebilir ve yoğun zamanlarınızı başkalarına gösterebilirsiniz.\n- CalDAV aracılığıyla uygulamaları ve aygıtları sorunsuz bir şekilde bütünleştirebilirsiniz.\n- Deneyiminizi özelleştirebilirsiniz: Yinelenen etkinlikler planlayabilir, bildirimleri ve diğer ayarları ayarlayabilirsiniz.",
+ "Example event - open me!" : "Örnek etkinlik. Beni aç!",
"System Address Book" : "Sistem adres defteri",
"The system address book contains contact information for all users in your instance." : "Sistem adres defterinde, kopyanızdaki tüm kullanıcıların iletişim bilgileri bulunur.",
"Enable System Address Book" : "Sistem adres defteri kullanılsın",
@@ -290,6 +292,25 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "{dayName} için başlangıç zamanını seçin",
"Pick a end time for {dayName}" : "{dayName} için bitiş zamanını seçin",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Tüm bildirimleri sessize almak için, uygunluk durumu dışında kullanıcı durumu otomatik olarak \"Rahatsız etmeyin\" olarak ayarlanır.",
+ "Cancel" : "İptal",
+ "Import" : "İçe aktar",
+ "Error while saving settings" : "Ayarlar kaydedilirken sorun çıktı",
+ "Contact reset successfully" : "Kişi sıfırlandı",
+ "Error while resetting contact" : "Kişi sıfırlanırken sorun çıktı",
+ "Contact imported successfully" : "Kişi içe aktarıldı",
+ "Error while importing contact" : "Kişi içe aktarılırken sorun çıktı",
+ "Import contact" : "Kişiyi içe aktar",
+ "Reset to default" : "Varsayılanlara dön",
+ "Import contacts" : "Kişileri içe aktar",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Yeni bir .vcf dosyasını içe aktarmak, var olan varsayılan kişiyi siler ve yenisiyle değiştirir. İlerlemek istiyor musunuz?",
+ "Failed to save example event creation setting" : "Örnek etkinlik oluşturma ayarı kaydedilemedi",
+ "Failed to upload the example event" : "Örnek etkinlik yüklenemedi",
+ "Custom example event was saved successfully" : "Özel örnek etkinlik kaydedildi",
+ "Failed to delete the custom example event" : "Özel örnek etkinlik silinemedi",
+ "Custom example event was deleted successfully" : "Özel örnek etkinlik silindi",
+ "Import calendar event" : "Takvim etkinliğini içe aktar",
+ "Uploading a new event will overwrite the existing one." : "Yeni bir etkinlik yüklendiğinde eskisinin üzerine yazılır.",
+ "Upload event" : "Etkinlik yükle",
"Availability" : "Uygunluk",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Çalışma saatlerinizi ayarlarsanız, diğer kişiler bir toplantı ayarladıklarında ofis dışında olduğunuzu görürler.",
"Absence" : "Bulunmama",
@@ -299,34 +320,19 @@ OC.L10N.register(
"Calendar server" : "Takvim sunucusu",
"Send invitations to attendees" : "Katılımcılara davet gönder",
"Automatically generate a birthday calendar" : "Doğum günü takvimi otomatik oluşturulsun",
- "Birthday calendars will be generated by a background job." : "Bu seçenek kullanıma alındığında, doğum günü takvimi arka plan görevi olarak oluşturulur.",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Kullanıma alındıktan hemen sonra görüntülenmez, bir süre sonra görüntülenir.",
+ "Birthday calendars will be generated by a background job." : "Açıldığında, arka plan görevi olarak doğum günü takvimi oluşturulur.",
+ "Hence they will not be available immediately after enabling but will show up after some time." : "Açıldıktan hemen sonra değil bir süre sonra görüntülenir.",
"Send notifications for events" : "Etkinlik bildirimleri gönderilsin",
"Notifications are sent via background jobs, so these must occur often enough." : "Bildirimler arka plan işlemleri tarafından gönderilir. Bu nedenle sıklık değeri uygun şekilde ayarlanmalıdır.",
"Send reminder notifications to calendar sharees as well" : "Takvim paylaşımlarına da hatırlatma bildirimleri gönderilsin",
- "Reminders are always sent to organizers and attendees." : "Bu seçenek kullanıma alındığında, hatırlatıcılar her zaman düzenleyici ve katılımcılara gönderilir.",
+ "Reminders are always sent to organizers and attendees." : "Açıldığında, anımsatıcılar düzenleyici ve katılımcılara her zaman gönderilir.",
"Enable notifications for events via push" : "Anında etkinlik bildirimlerini aç",
- "Cancel" : "İptal",
- "Import" : "İçe aktar",
- "Error while saving settings" : "Ayarlar kaydedilirken sorun çıktı",
- "Contact reset successfully" : "Kişi sıfırlandı",
- "Error while resetting contact" : "Kişi sıfırlanırken sorun çıktı",
- "Contact imported successfully" : "Kişi içe aktarıldı",
- "Error while importing contact" : "Kişi içe aktarılırken sorun çıktı",
- "Example Content" : "Örnek içerik",
- "Set example content to be created on new user first login." : "Yeni kullanıcının ilk oturum açmasında oluşturulacak örnek içeriği ayarlayın.",
- "Import contact" : "Kişiyi içe aktar",
- "Reset to default contact" : "Varsayılan kişiye sıfırla",
- "Import contacts" : "Kişileri içe aktar",
- "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Yeni bir .vcf dosyasını içe aktarmak, var olan varsayılan kişiyi siler ve yenisiyle değiştirir. İlerlemek istiyor musunuz?",
+ "Example content" : "Örnek içerik",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Örnek içerik, Nextcloud özelliklerinin sunulmasını sağlar. Varsayılan içerik Nextcloud ile birlikte gelir ve özel içerikle değiştirilebilir.",
"There was an error updating your attendance status." : "Katılım durumunuz güncellenirken bir sorun çıktı.",
"Please contact the organizer directly." : "Lütfen düzenleyici ile doğrudan görüşün.",
"Are you accepting the invitation?" : "Daveti kabul ediyor musunuz?",
"Tentative" : "Kesin değil",
- "Your attendance was updated successfully." : "Katılımınız güncellendi.",
- "Time:" : "Zaman:",
- "Could not open file" : "Dosya açılamadı",
- "Invalid chunk name" : "Parça adı geçersiz",
- "Could not rename part file assembled from chunks" : "Parçalardan oluşturulan parça dosyası yeniden adlandırılamadı "
+ "Your attendance was updated successfully." : "Katılımınız güncellendi."
},
"nplurals=2; plural=(n > 1);");
diff --git a/apps/dav/l10n/tr.json b/apps/dav/l10n/tr.json
index 949b17d2278..31d00ec53eb 100644
--- a/apps/dav/l10n/tr.json
+++ b/apps/dav/l10n/tr.json
@@ -248,6 +248,8 @@
"Completed on %s" : "%s tarihinde tamamlandı",
"Due on %s by %s" : "%s tarihine kadar %s tarafından",
"Due on %s" : "%s tarihine kadar",
+ "Welcome to Nextcloud Calendar!\n\nThis is a sample event - explore the flexibility of planning with Nextcloud Calendar by making any edits you want!\n\nWith Nextcloud Calendar, you can:\n- Create, edit, and manage events effortlessly.\n- Create multiple calendars and share them with teammates, friends, or family.\n- Check availability and display your busy times to others.\n- Seamlessly integrate with apps and devices via CalDAV.\n- Customize your experience: schedule recurring events, adjust notifications and other settings." : "Nextcloud Takvim uygulamasına hoş geldiniz!\n\nBu bir örnek etkinliktir. İstediğiniz düzenlemeleri yaparak Nextcloud Takvim ile planlamanın esnekliğini keşfedin!\n\nNextcloud Takvim ile şunları yapabilirsiniz:\n- Etkinlikleri kolayca oluşturabilir, düzenleyebilir ve yönetebilirsiniz.\n- Birden fazla takvim oluşturabilir ve bunları takım arkadaşlarınız, arkadaşlarınız veya ailenizle paylaşabilirsiniz.\n- Uygunluğunuzu kontrol edebilir ve yoğun zamanlarınızı başkalarına gösterebilirsiniz.\n- CalDAV aracılığıyla uygulamaları ve aygıtları sorunsuz bir şekilde bütünleştirebilirsiniz.\n- Deneyiminizi özelleştirebilirsiniz: Yinelenen etkinlikler planlayabilir, bildirimleri ve diğer ayarları ayarlayabilirsiniz.",
+ "Example event - open me!" : "Örnek etkinlik. Beni aç!",
"System Address Book" : "Sistem adres defteri",
"The system address book contains contact information for all users in your instance." : "Sistem adres defterinde, kopyanızdaki tüm kullanıcıların iletişim bilgileri bulunur.",
"Enable System Address Book" : "Sistem adres defteri kullanılsın",
@@ -288,6 +290,25 @@
"Pick a start time for {dayName}" : "{dayName} için başlangıç zamanını seçin",
"Pick a end time for {dayName}" : "{dayName} için bitiş zamanını seçin",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Tüm bildirimleri sessize almak için, uygunluk durumu dışında kullanıcı durumu otomatik olarak \"Rahatsız etmeyin\" olarak ayarlanır.",
+ "Cancel" : "İptal",
+ "Import" : "İçe aktar",
+ "Error while saving settings" : "Ayarlar kaydedilirken sorun çıktı",
+ "Contact reset successfully" : "Kişi sıfırlandı",
+ "Error while resetting contact" : "Kişi sıfırlanırken sorun çıktı",
+ "Contact imported successfully" : "Kişi içe aktarıldı",
+ "Error while importing contact" : "Kişi içe aktarılırken sorun çıktı",
+ "Import contact" : "Kişiyi içe aktar",
+ "Reset to default" : "Varsayılanlara dön",
+ "Import contacts" : "Kişileri içe aktar",
+ "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Yeni bir .vcf dosyasını içe aktarmak, var olan varsayılan kişiyi siler ve yenisiyle değiştirir. İlerlemek istiyor musunuz?",
+ "Failed to save example event creation setting" : "Örnek etkinlik oluşturma ayarı kaydedilemedi",
+ "Failed to upload the example event" : "Örnek etkinlik yüklenemedi",
+ "Custom example event was saved successfully" : "Özel örnek etkinlik kaydedildi",
+ "Failed to delete the custom example event" : "Özel örnek etkinlik silinemedi",
+ "Custom example event was deleted successfully" : "Özel örnek etkinlik silindi",
+ "Import calendar event" : "Takvim etkinliğini içe aktar",
+ "Uploading a new event will overwrite the existing one." : "Yeni bir etkinlik yüklendiğinde eskisinin üzerine yazılır.",
+ "Upload event" : "Etkinlik yükle",
"Availability" : "Uygunluk",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Çalışma saatlerinizi ayarlarsanız, diğer kişiler bir toplantı ayarladıklarında ofis dışında olduğunuzu görürler.",
"Absence" : "Bulunmama",
@@ -297,34 +318,19 @@
"Calendar server" : "Takvim sunucusu",
"Send invitations to attendees" : "Katılımcılara davet gönder",
"Automatically generate a birthday calendar" : "Doğum günü takvimi otomatik oluşturulsun",
- "Birthday calendars will be generated by a background job." : "Bu seçenek kullanıma alındığında, doğum günü takvimi arka plan görevi olarak oluşturulur.",
- "Hence they will not be available immediately after enabling but will show up after some time." : "Kullanıma alındıktan hemen sonra görüntülenmez, bir süre sonra görüntülenir.",
+ "Birthday calendars will be generated by a background job." : "Açıldığında, arka plan görevi olarak doğum günü takvimi oluşturulur.",
+ "Hence they will not be available immediately after enabling but will show up after some time." : "Açıldıktan hemen sonra değil bir süre sonra görüntülenir.",
"Send notifications for events" : "Etkinlik bildirimleri gönderilsin",
"Notifications are sent via background jobs, so these must occur often enough." : "Bildirimler arka plan işlemleri tarafından gönderilir. Bu nedenle sıklık değeri uygun şekilde ayarlanmalıdır.",
"Send reminder notifications to calendar sharees as well" : "Takvim paylaşımlarına da hatırlatma bildirimleri gönderilsin",
- "Reminders are always sent to organizers and attendees." : "Bu seçenek kullanıma alındığında, hatırlatıcılar her zaman düzenleyici ve katılımcılara gönderilir.",
+ "Reminders are always sent to organizers and attendees." : "Açıldığında, anımsatıcılar düzenleyici ve katılımcılara her zaman gönderilir.",
"Enable notifications for events via push" : "Anında etkinlik bildirimlerini aç",
- "Cancel" : "İptal",
- "Import" : "İçe aktar",
- "Error while saving settings" : "Ayarlar kaydedilirken sorun çıktı",
- "Contact reset successfully" : "Kişi sıfırlandı",
- "Error while resetting contact" : "Kişi sıfırlanırken sorun çıktı",
- "Contact imported successfully" : "Kişi içe aktarıldı",
- "Error while importing contact" : "Kişi içe aktarılırken sorun çıktı",
- "Example Content" : "Örnek içerik",
- "Set example content to be created on new user first login." : "Yeni kullanıcının ilk oturum açmasında oluşturulacak örnek içeriği ayarlayın.",
- "Import contact" : "Kişiyi içe aktar",
- "Reset to default contact" : "Varsayılan kişiye sıfırla",
- "Import contacts" : "Kişileri içe aktar",
- "Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Yeni bir .vcf dosyasını içe aktarmak, var olan varsayılan kişiyi siler ve yenisiyle değiştirir. İlerlemek istiyor musunuz?",
+ "Example content" : "Örnek içerik",
+ "Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Örnek içerik, Nextcloud özelliklerinin sunulmasını sağlar. Varsayılan içerik Nextcloud ile birlikte gelir ve özel içerikle değiştirilebilir.",
"There was an error updating your attendance status." : "Katılım durumunuz güncellenirken bir sorun çıktı.",
"Please contact the organizer directly." : "Lütfen düzenleyici ile doğrudan görüşün.",
"Are you accepting the invitation?" : "Daveti kabul ediyor musunuz?",
"Tentative" : "Kesin değil",
- "Your attendance was updated successfully." : "Katılımınız güncellendi.",
- "Time:" : "Zaman:",
- "Could not open file" : "Dosya açılamadı",
- "Invalid chunk name" : "Parça adı geçersiz",
- "Could not rename part file assembled from chunks" : "Parçalardan oluşturulan parça dosyası yeniden adlandırılamadı "
+ "Your attendance was updated successfully." : "Katılımınız güncellendi."
},"pluralForm" :"nplurals=2; plural=(n > 1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/ug.js b/apps/dav/l10n/ug.js
index e5cb4e9ab2d..5915a185740 100644
--- a/apps/dav/l10n/ug.js
+++ b/apps/dav/l10n/ug.js
@@ -239,6 +239,10 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "{dayName} نىڭ باشلىنىش ۋاقتىنى تاللاڭ",
"Pick a end time for {dayName}" : "{dayName} نىڭ ئاخىرقى ۋاقتىنى تاللاڭ",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "بارلىق ئۇقتۇرۇشلارنى ئاۋازسىز قىلىش ئۈچۈن ئىشلەتكۈچى ھالىتىنى ئاپتوماتىك ھالدا «ئاۋارە قىلماڭ» قىلىپ تەڭشەڭ.",
+ "Cancel" : "بىكار قىلىش",
+ "Import" : "ئەكىر",
+ "Error while saving settings" : "تەڭشەكلەرنى ساقلاش جەريانىدا خاتالىق",
+ "Reset to default" : "سۈكۈتتىكى ھالىتىگە قايتىڭ",
"Availability" : "ئىشلەتكىلى بولىدۇ",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "ئەگەر خىزمەت ۋاقتىڭىزنى تەڭشىسىڭىز ، باشقىلار يىغىن زاكاز قىلغاندا سىزنىڭ ئىشتىن چۈشكەن ۋاقتىڭىزنى كۆرىدۇ.",
"Absence" : "يوق",
@@ -255,17 +259,10 @@ 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" : "ئىتتىرىش ئارقىلىق ۋەقەلەرگە ئۇقتۇرۇشنى قوزغىتىڭ",
- "Cancel" : "بىكار قىلىش",
- "Import" : "ئەكىر",
- "Error while saving settings" : "تەڭشەكلەرنى ساقلاش جەريانىدا خاتالىق",
"There was an error updating your attendance status." : "قاتنىشىش ھالىتىڭىزنى يېڭىلاشتا خاتالىق كۆرۈلدى.",
"Please contact the organizer directly." : "تەشكىللىگۈچى بىلەن بىۋاسىتە ئالاقىلىشىڭ.",
"Are you accepting the invitation?" : "تەكلىپنى قوبۇل قىلامسىز؟",
"Tentative" : "Tentative",
- "Your attendance was updated successfully." : "سىزنىڭ قاتنىشىشىڭىز مۇۋەپپەقىيەتلىك يېڭىلاندى.",
- "Time:" : "ۋاقىت:",
- "Could not open file" : "ھۆججەت ئاچالمىدى",
- "Invalid chunk name" : "ئىناۋەتسىز",
- "Could not rename part file assembled from chunks" : "بۆلەكلەردىن يىغىلغان قىسمەن ھۆججەتنىڭ نامىنى ئۆزگەرتەلمىدى"
+ "Your attendance was updated successfully." : "سىزنىڭ قاتنىشىشىڭىز مۇۋەپپەقىيەتلىك يېڭىلاندى."
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/dav/l10n/ug.json b/apps/dav/l10n/ug.json
index 5b05663b827..abbbc45161f 100644
--- a/apps/dav/l10n/ug.json
+++ b/apps/dav/l10n/ug.json
@@ -237,6 +237,10 @@
"Pick a start time for {dayName}" : "{dayName} نىڭ باشلىنىش ۋاقتىنى تاللاڭ",
"Pick a end time for {dayName}" : "{dayName} نىڭ ئاخىرقى ۋاقتىنى تاللاڭ",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "بارلىق ئۇقتۇرۇشلارنى ئاۋازسىز قىلىش ئۈچۈن ئىشلەتكۈچى ھالىتىنى ئاپتوماتىك ھالدا «ئاۋارە قىلماڭ» قىلىپ تەڭشەڭ.",
+ "Cancel" : "بىكار قىلىش",
+ "Import" : "ئەكىر",
+ "Error while saving settings" : "تەڭشەكلەرنى ساقلاش جەريانىدا خاتالىق",
+ "Reset to default" : "سۈكۈتتىكى ھالىتىگە قايتىڭ",
"Availability" : "ئىشلەتكىلى بولىدۇ",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "ئەگەر خىزمەت ۋاقتىڭىزنى تەڭشىسىڭىز ، باشقىلار يىغىن زاكاز قىلغاندا سىزنىڭ ئىشتىن چۈشكەن ۋاقتىڭىزنى كۆرىدۇ.",
"Absence" : "يوق",
@@ -253,17 +257,10 @@
"Send reminder notifications to calendar sharees as well" : "كالېندار ھەمبەھىرلىرىگىمۇ ئەسكەرتىش ئۇقتۇرۇشى ئەۋەتىڭ",
"Reminders are always sent to organizers and attendees." : "ئەسكەرتىش ھەمىشە تەشكىللىگۈچىلەر ۋە قاتناشقۇچىلارغا ئەۋەتىلىدۇ.",
"Enable notifications for events via push" : "ئىتتىرىش ئارقىلىق ۋەقەلەرگە ئۇقتۇرۇشنى قوزغىتىڭ",
- "Cancel" : "بىكار قىلىش",
- "Import" : "ئەكىر",
- "Error while saving settings" : "تەڭشەكلەرنى ساقلاش جەريانىدا خاتالىق",
"There was an error updating your attendance status." : "قاتنىشىش ھالىتىڭىزنى يېڭىلاشتا خاتالىق كۆرۈلدى.",
"Please contact the organizer directly." : "تەشكىللىگۈچى بىلەن بىۋاسىتە ئالاقىلىشىڭ.",
"Are you accepting the invitation?" : "تەكلىپنى قوبۇل قىلامسىز؟",
"Tentative" : "Tentative",
- "Your attendance was updated successfully." : "سىزنىڭ قاتنىشىشىڭىز مۇۋەپپەقىيەتلىك يېڭىلاندى.",
- "Time:" : "ۋاقىت:",
- "Could not open file" : "ھۆججەت ئاچالمىدى",
- "Invalid chunk name" : "ئىناۋەتسىز",
- "Could not rename part file assembled from chunks" : "بۆلەكلەردىن يىغىلغان قىسمەن ھۆججەتنىڭ نامىنى ئۆزگەرتەلمىدى"
+ "Your attendance was updated successfully." : "سىزنىڭ قاتنىشىشىڭىز مۇۋەپپەقىيەتلىك يېڭىلاندى."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/uk.js b/apps/dav/l10n/uk.js
index 94e82440454..c8beb750ce2 100644
--- a/apps/dav/l10n/uk.js
+++ b/apps/dav/l10n/uk.js
@@ -258,6 +258,12 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "Виберіть час початку для {dayName}",
"Pick a end time for {dayName}" : "Виберіть час завершення для {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Автоматично встановлювати статус користувача у \"Не турбувати\", коли ви не доступні. В цей проміжок часу ви не отримуватимете сповіщення.",
+ "Cancel" : "Скасувати",
+ "Import" : "Імпорт",
+ "Error while saving settings" : "Помилка під час збереження налаштувань",
+ "Import contact" : "Імпортувати контакт",
+ "Reset to default" : "Скинути до типового",
+ "Import contacts" : "Імпортувати контакти",
"Availability" : "Доступність",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Будь ласка, налаштуйте ваші робочі години, щоб інші користувачі могли бачити, коли ви відсутні під час створення зустрічей.",
"Absence" : "Відсутність",
@@ -274,20 +280,10 @@ 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" : "Увімкнути push-сповіщення для подій",
- "Cancel" : "Скасувати",
- "Import" : "Імпорт",
- "Error while saving settings" : "Помилка під час збереження налаштувань",
- "Import contact" : "Імпортувати контакт",
- "Reset to default contact" : "Скинути то типового контакту",
- "Import contacts" : "Імпортувати контакти",
"There was an error updating your attendance status." : "Виникла помилка при оновленні вашого статусу учасника.",
"Please contact the organizer directly." : "Будь-ласка повідомте організатора.",
"Are you accepting the invitation?" : "Чи приймаєте ви запрошення?",
"Tentative" : "Попередній",
- "Your attendance was updated successfully." : "Ваша участь успішно оновлена.",
- "Time:" : "Час:",
- "Could not open file" : "Не вдалося відкрити файл",
- "Invalid chunk name" : "Недійсна назва блоку",
- "Could not rename part file assembled from chunks" : "Не вдалося перейменувати файл частини, зібраний із фрагментів"
+ "Your attendance was updated successfully." : "Ваша участь успішно оновлена."
},
"nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);");
diff --git a/apps/dav/l10n/uk.json b/apps/dav/l10n/uk.json
index 3ea4f596e97..8ac5f933cf6 100644
--- a/apps/dav/l10n/uk.json
+++ b/apps/dav/l10n/uk.json
@@ -256,6 +256,12 @@
"Pick a start time for {dayName}" : "Виберіть час початку для {dayName}",
"Pick a end time for {dayName}" : "Виберіть час завершення для {dayName}",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Автоматично встановлювати статус користувача у \"Не турбувати\", коли ви не доступні. В цей проміжок часу ви не отримуватимете сповіщення.",
+ "Cancel" : "Скасувати",
+ "Import" : "Імпорт",
+ "Error while saving settings" : "Помилка під час збереження налаштувань",
+ "Import contact" : "Імпортувати контакт",
+ "Reset to default" : "Скинути до типового",
+ "Import contacts" : "Імпортувати контакти",
"Availability" : "Доступність",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Будь ласка, налаштуйте ваші робочі години, щоб інші користувачі могли бачити, коли ви відсутні під час створення зустрічей.",
"Absence" : "Відсутність",
@@ -272,20 +278,10 @@
"Send reminder notifications to calendar sharees as well" : "Також надсилайте нагадування користувачам вашого спільного календаря",
"Reminders are always sent to organizers and attendees." : "Нагадування завжди надсилаються організаторам і учасникам.",
"Enable notifications for events via push" : "Увімкнути push-сповіщення для подій",
- "Cancel" : "Скасувати",
- "Import" : "Імпорт",
- "Error while saving settings" : "Помилка під час збереження налаштувань",
- "Import contact" : "Імпортувати контакт",
- "Reset to default contact" : "Скинути то типового контакту",
- "Import contacts" : "Імпортувати контакти",
"There was an error updating your attendance status." : "Виникла помилка при оновленні вашого статусу учасника.",
"Please contact the organizer directly." : "Будь-ласка повідомте організатора.",
"Are you accepting the invitation?" : "Чи приймаєте ви запрошення?",
"Tentative" : "Попередній",
- "Your attendance was updated successfully." : "Ваша участь успішно оновлена.",
- "Time:" : "Час:",
- "Could not open file" : "Не вдалося відкрити файл",
- "Invalid chunk name" : "Недійсна назва блоку",
- "Could not rename part file assembled from chunks" : "Не вдалося перейменувати файл частини, зібраний із фрагментів"
+ "Your attendance was updated successfully." : "Ваша участь успішно оновлена."
},"pluralForm" :"nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);"
} \ No newline at end of file
diff --git a/apps/dav/l10n/zh_CN.js b/apps/dav/l10n/zh_CN.js
index 9b6eaa3b9e0..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" : "缺席已保存",
@@ -290,6 +290,25 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "选择 {dayName} 的开始时间",
"Pick a end time for {dayName}" : "选择 {dayName} 的结束时间",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "不在工作时间内时,自动将用户状态设置为“勿扰”并静音所有通知。",
+ "Cancel" : "取消",
+ "Import" : "导入",
+ "Error while saving settings" : "保存设置时出错",
+ "Contact reset successfully" : "联系人重置成功",
+ "Error while resetting contact" : "重置联系人时出错",
+ "Contact imported successfully" : "联系人导入成功",
+ "Error while importing contact" : "导入联系人时出错",
+ "Import contact" : "导入联系人",
+ "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" : "离开",
@@ -297,36 +316,21 @@ 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" : "启用推送事件通知",
- "Cancel" : "取消",
- "Import" : "导入",
- "Error while saving settings" : "保存设置时出错",
- "Contact reset successfully" : "联系人重置成功",
- "Error while resetting contact" : "重置联系人时出错",
- "Contact imported successfully" : "联系人导入成功",
- "Error while importing contact" : "导入联系人时出错",
- "Example Content" : "示例内容",
- "Set example content to be created on new user first login." : "设置新用户首次登录时要创建的示例内容。",
- "Import contact" : "导入联系人",
- "Reset to default contact" : "重置为默认联系人",
- "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 文件将删除现有的默认联系人,并用新联系人替换。是否要继续?",
+ "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?" : "您是否接受邀请?",
"Tentative" : "暂定",
- "Your attendance was updated successfully." : "您的出席状态更新成功。",
- "Time:" : "时间:",
- "Could not open file" : "无法打开文件",
- "Invalid chunk name" : "分片名称无效",
- "Could not rename part file assembled from chunks" : "无法重命名从分片组合的部分文件"
+ "Your attendance was updated successfully." : "您的出席状态更新成功。"
},
"nplurals=1; plural=0;");
diff --git a/apps/dav/l10n/zh_CN.json b/apps/dav/l10n/zh_CN.json
index e674599e183..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" : "缺席已保存",
@@ -288,6 +288,25 @@
"Pick a start time for {dayName}" : "选择 {dayName} 的开始时间",
"Pick a end time for {dayName}" : "选择 {dayName} 的结束时间",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "不在工作时间内时,自动将用户状态设置为“勿扰”并静音所有通知。",
+ "Cancel" : "取消",
+ "Import" : "导入",
+ "Error while saving settings" : "保存设置时出错",
+ "Contact reset successfully" : "联系人重置成功",
+ "Error while resetting contact" : "重置联系人时出错",
+ "Contact imported successfully" : "联系人导入成功",
+ "Error while importing contact" : "导入联系人时出错",
+ "Import contact" : "导入联系人",
+ "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" : "离开",
@@ -295,36 +314,21 @@
"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" : "启用推送事件通知",
- "Cancel" : "取消",
- "Import" : "导入",
- "Error while saving settings" : "保存设置时出错",
- "Contact reset successfully" : "联系人重置成功",
- "Error while resetting contact" : "重置联系人时出错",
- "Contact imported successfully" : "联系人导入成功",
- "Error while importing contact" : "导入联系人时出错",
- "Example Content" : "示例内容",
- "Set example content to be created on new user first login." : "设置新用户首次登录时要创建的示例内容。",
- "Import contact" : "导入联系人",
- "Reset to default contact" : "重置为默认联系人",
- "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 文件将删除现有的默认联系人,并用新联系人替换。是否要继续?",
+ "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?" : "您是否接受邀请?",
"Tentative" : "暂定",
- "Your attendance was updated successfully." : "您的出席状态更新成功。",
- "Time:" : "时间:",
- "Could not open file" : "无法打开文件",
- "Invalid chunk name" : "分片名称无效",
- "Could not rename part file assembled from chunks" : "无法重命名从分片组合的部分文件"
+ "Your attendance was updated successfully." : "您的出席状态更新成功。"
},"pluralForm" :"nplurals=1; plural=0;"
} \ No newline at end of file
diff --git a/apps/dav/l10n/zh_HK.js b/apps/dav/l10n/zh_HK.js
index 7acd613e17f..df201c06f90 100644
--- a/apps/dav/l10n/zh_HK.js
+++ b/apps/dav/l10n/zh_HK.js
@@ -290,6 +290,25 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "為 {dayName} 挑選開始時間",
"Pick a end time for {dayName}" : "為 {dayName} 挑選結束時間",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "在忙碌時,自動將用戶狀態設定為「請勿打擾」以靜音所有通知。",
+ "Cancel" : "取消",
+ "Import" : "導入",
+ "Error while saving settings" : "儲存設定時發生錯誤",
+ "Contact reset successfully" : "聯絡人重設成功",
+ "Error while resetting contact" : "重設聯絡人時發生錯誤",
+ "Contact imported successfully" : "成功導入了聯絡人",
+ "Error while importing contact" : "導入聯絡人時發生錯誤",
+ "Import contact" : "導入聯絡人",
+ "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,27 +325,12 @@ 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" : "啟用推送活動通知",
- "Cancel" : "取消",
- "Import" : "導入",
- "Error while saving settings" : "儲存設定時發生錯誤",
- "Contact reset successfully" : "聯絡人重設成功",
- "Error while resetting contact" : "重設聯絡人時發生錯誤",
- "Contact imported successfully" : "成功導入了聯絡人",
- "Error while importing contact" : "導入聯絡人時發生錯誤",
- "Example Content" : "範例內容",
- "Set example content to be created on new user first login." : "設定新用戶首次登入時所建立的範例內容。",
- "Import contact" : "導入聯絡人",
- "Reset to default contact" : "重設為默認聯絡人",
- "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 檔案將刪除現有的默認聯絡人並將其替換為新的聯絡人。您想繼續嗎?",
+ "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?" : "接受邀請嗎?",
"Tentative" : "暫定",
- "Your attendance was updated successfully." : "您的參與狀況成功更新",
- "Time:" : "時間:",
- "Could not open file" : "無法開啟檔案",
- "Invalid chunk name" : "無效的區塊名稱",
- "Could not rename part file assembled from chunks" : "無法重新命名從區塊組合成的部份檔案"
+ "Your attendance was updated successfully." : "您的參與狀況成功更新"
},
"nplurals=1; plural=0;");
diff --git a/apps/dav/l10n/zh_HK.json b/apps/dav/l10n/zh_HK.json
index 32b7afce5f8..0cafd6ec077 100644
--- a/apps/dav/l10n/zh_HK.json
+++ b/apps/dav/l10n/zh_HK.json
@@ -288,6 +288,25 @@
"Pick a start time for {dayName}" : "為 {dayName} 挑選開始時間",
"Pick a end time for {dayName}" : "為 {dayName} 挑選結束時間",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "在忙碌時,自動將用戶狀態設定為「請勿打擾」以靜音所有通知。",
+ "Cancel" : "取消",
+ "Import" : "導入",
+ "Error while saving settings" : "儲存設定時發生錯誤",
+ "Contact reset successfully" : "聯絡人重設成功",
+ "Error while resetting contact" : "重設聯絡人時發生錯誤",
+ "Contact imported successfully" : "成功導入了聯絡人",
+ "Error while importing contact" : "導入聯絡人時發生錯誤",
+ "Import contact" : "導入聯絡人",
+ "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" : "缺席",
@@ -304,27 +323,12 @@
"Send reminder notifications to calendar sharees as well" : "也向共享日曆者傳送提醒通告",
"Reminders are always sent to organizers and attendees." : "一律傳送提醒通知給舉辦者與參與者。",
"Enable notifications for events via push" : "啟用推送活動通知",
- "Cancel" : "取消",
- "Import" : "導入",
- "Error while saving settings" : "儲存設定時發生錯誤",
- "Contact reset successfully" : "聯絡人重設成功",
- "Error while resetting contact" : "重設聯絡人時發生錯誤",
- "Contact imported successfully" : "成功導入了聯絡人",
- "Error while importing contact" : "導入聯絡人時發生錯誤",
- "Example Content" : "範例內容",
- "Set example content to be created on new user first login." : "設定新用戶首次登入時所建立的範例內容。",
- "Import contact" : "導入聯絡人",
- "Reset to default contact" : "重設為默認聯絡人",
- "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 檔案將刪除現有的默認聯絡人並將其替換為新的聯絡人。您想繼續嗎?",
+ "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?" : "接受邀請嗎?",
"Tentative" : "暫定",
- "Your attendance was updated successfully." : "您的參與狀況成功更新",
- "Time:" : "時間:",
- "Could not open file" : "無法開啟檔案",
- "Invalid chunk name" : "無效的區塊名稱",
- "Could not rename part file assembled from chunks" : "無法重新命名從區塊組合成的部份檔案"
+ "Your attendance was updated successfully." : "您的參與狀況成功更新"
},"pluralForm" :"nplurals=1; plural=0;"
} \ No newline at end of file
diff --git a/apps/dav/l10n/zh_TW.js b/apps/dav/l10n/zh_TW.js
index e1e5f759f12..191f6631bbf 100644
--- a/apps/dav/l10n/zh_TW.js
+++ b/apps/dav/l10n/zh_TW.js
@@ -290,6 +290,25 @@ OC.L10N.register(
"Pick a start time for {dayName}" : "為 {dayName} 挑選開始時間",
"Pick a end time for {dayName}" : "為 {dayName} 挑選結束時間",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "在空閒時間以外,自動將使用者狀態設定為「請勿打擾」以靜音所有通知。",
+ "Cancel" : "取消",
+ "Import" : "匯入",
+ "Error while saving settings" : "儲存設定時發生錯誤",
+ "Contact reset successfully" : "成功重設聯絡人",
+ "Error while resetting contact" : "重設聯絡人時發生錯誤",
+ "Contact imported successfully" : "成功匯入聯絡人",
+ "Error while importing contact" : "匯入聯絡人時發生錯誤",
+ "Import contact" : "匯入聯絡人",
+ "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,27 +325,12 @@ 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" : "啟用行程通知推播",
- "Cancel" : "取消",
- "Import" : "匯入",
- "Error while saving settings" : "儲存設定時發生錯誤",
- "Contact reset successfully" : "成功重設聯絡人",
- "Error while resetting contact" : "重設聯絡人時發生錯誤",
- "Contact imported successfully" : "成功匯入聯絡人",
- "Error while importing contact" : "匯入聯絡人時發生錯誤",
- "Example Content" : "範例內容",
- "Set example content to be created on new user first login." : "設定新使用者首次登入時要建立的範例內容。",
- "Import contact" : "匯入聯絡人",
- "Reset to default contact" : "重設回預設聯絡人",
- "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 檔案將會刪除現有的預設聯絡人並將其取代為新的聯絡人。您想要繼續嗎?",
+ "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?" : "您要接受邀請嗎?",
"Tentative" : "考慮接受",
- "Your attendance was updated successfully." : "您的參與狀態已成功更新。",
- "Time:" : "時間:",
- "Could not open file" : "無法開啟檔案",
- "Invalid chunk name" : "無效的片段名稱",
- "Could not rename part file assembled from chunks" : "無法重新命名從片段組合成的部份檔案"
+ "Your attendance was updated successfully." : "您的參與狀態已成功更新。"
},
"nplurals=1; plural=0;");
diff --git a/apps/dav/l10n/zh_TW.json b/apps/dav/l10n/zh_TW.json
index 0e2bd2af98f..53990163a73 100644
--- a/apps/dav/l10n/zh_TW.json
+++ b/apps/dav/l10n/zh_TW.json
@@ -288,6 +288,25 @@
"Pick a start time for {dayName}" : "為 {dayName} 挑選開始時間",
"Pick a end time for {dayName}" : "為 {dayName} 挑選結束時間",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "在空閒時間以外,自動將使用者狀態設定為「請勿打擾」以靜音所有通知。",
+ "Cancel" : "取消",
+ "Import" : "匯入",
+ "Error while saving settings" : "儲存設定時發生錯誤",
+ "Contact reset successfully" : "成功重設聯絡人",
+ "Error while resetting contact" : "重設聯絡人時發生錯誤",
+ "Contact imported successfully" : "成功匯入聯絡人",
+ "Error while importing contact" : "匯入聯絡人時發生錯誤",
+ "Import contact" : "匯入聯絡人",
+ "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" : "不在",
@@ -304,27 +323,12 @@
"Send reminder notifications to calendar sharees as well" : "也向共享行事曆傳送提醒通知",
"Reminders are always sent to organizers and attendees." : "一律傳送提醒給主辦者與參與者。",
"Enable notifications for events via push" : "啟用行程通知推播",
- "Cancel" : "取消",
- "Import" : "匯入",
- "Error while saving settings" : "儲存設定時發生錯誤",
- "Contact reset successfully" : "成功重設聯絡人",
- "Error while resetting contact" : "重設聯絡人時發生錯誤",
- "Contact imported successfully" : "成功匯入聯絡人",
- "Error while importing contact" : "匯入聯絡人時發生錯誤",
- "Example Content" : "範例內容",
- "Set example content to be created on new user first login." : "設定新使用者首次登入時要建立的範例內容。",
- "Import contact" : "匯入聯絡人",
- "Reset to default contact" : "重設回預設聯絡人",
- "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 檔案將會刪除現有的預設聯絡人並將其取代為新的聯絡人。您想要繼續嗎?",
+ "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?" : "您要接受邀請嗎?",
"Tentative" : "考慮接受",
- "Your attendance was updated successfully." : "您的參與狀態已成功更新。",
- "Time:" : "時間:",
- "Could not open file" : "無法開啟檔案",
- "Invalid chunk name" : "無效的片段名稱",
- "Could not rename part file assembled from chunks" : "無法重新命名從片段組合成的部份檔案"
+ "Your attendance was updated successfully." : "您的參與狀態已成功更新。"
},"pluralForm" :"nplurals=1; plural=0;"
} \ No newline at end of file
diff --git a/apps/dav/lib/AppInfo/Application.php b/apps/dav/lib/AppInfo/Application.php
index edf7dd1214f..9d5921a1e83 100644
--- a/apps/dav/lib/AppInfo/Application.php
+++ b/apps/dav/lib/AppInfo/Application.php
@@ -20,7 +20,6 @@ use OCA\DAV\CalDAV\Reminder\NotificationProviderManager;
use OCA\DAV\CalDAV\Reminder\Notifier;
use OCA\DAV\Capabilities;
use OCA\DAV\CardDAV\ContactsManager;
-use OCA\DAV\CardDAV\PhotoCache;
use OCA\DAV\CardDAV\SyncService;
use OCA\DAV\Events\AddressBookCreatedEvent;
use OCA\DAV\Events\AddressBookDeletedEvent;
@@ -82,7 +81,6 @@ use OCP\Config\BeforePreferenceSetEvent;
use OCP\Contacts\IManager as IContactsManager;
use OCP\DB\Events\AddMissingIndicesEvent;
use OCP\Federation\Events\TrustedServerRemovedEvent;
-use OCP\Files\AppData\IAppDataFactory;
use OCP\IUserSession;
use OCP\Server;
use OCP\Settings\Events\DeclarativeSettingsGetValueEvent;
@@ -112,12 +110,6 @@ class Application extends App implements IBootstrap {
public function register(IRegistrationContext $context): void {
$context->registerServiceAlias('CardDAVSyncService', SyncService::class);
- $context->registerService(PhotoCache::class, function (ContainerInterface $c) {
- return new PhotoCache(
- $c->get(IAppDataFactory::class)->get('dav-photocache'),
- $c->get(LoggerInterface::class)
- );
- });
$context->registerService(AppCalendarPlugin::class, function (ContainerInterface $c) {
return new AppCalendarPlugin(
$c->get(ICalendarManager::class),
diff --git a/apps/dav/lib/Avatars/RootCollection.php b/apps/dav/lib/Avatars/RootCollection.php
index ec88c65793f..033dcaf7a5c 100644
--- a/apps/dav/lib/Avatars/RootCollection.php
+++ b/apps/dav/lib/Avatars/RootCollection.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2017 ownCloud GmbH
diff --git a/apps/dav/lib/BackgroundJob/CleanupOrphanedChildrenJob.php b/apps/dav/lib/BackgroundJob/CleanupOrphanedChildrenJob.php
new file mode 100644
index 00000000000..8a5e34381a7
--- /dev/null
+++ b/apps/dav/lib/BackgroundJob/CleanupOrphanedChildrenJob.php
@@ -0,0 +1,89 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\BackgroundJob;
+
+use OCA\DAV\CalDAV\CalDavBackend;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\BackgroundJob\IJobList;
+use OCP\BackgroundJob\QueuedJob;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+use Psr\Log\LoggerInterface;
+
+class CleanupOrphanedChildrenJob extends QueuedJob {
+ public const ARGUMENT_CHILD_TABLE = 'childTable';
+ public const ARGUMENT_PARENT_TABLE = 'parentTable';
+ public const ARGUMENT_PARENT_ID = 'parentId';
+ public const ARGUMENT_LOG_MESSAGE = 'logMessage';
+
+ private const BATCH_SIZE = 1000;
+
+ public function __construct(
+ ITimeFactory $time,
+ private readonly IDBConnection $connection,
+ private readonly LoggerInterface $logger,
+ private readonly IJobList $jobList,
+ ) {
+ parent::__construct($time);
+ }
+
+ protected function run($argument): void {
+ $childTable = $argument[self::ARGUMENT_CHILD_TABLE];
+ $parentTable = $argument[self::ARGUMENT_PARENT_TABLE];
+ $parentId = $argument[self::ARGUMENT_PARENT_ID];
+ $logMessage = $argument[self::ARGUMENT_LOG_MESSAGE];
+
+ $orphanCount = $this->cleanUpOrphans($childTable, $parentTable, $parentId);
+ $this->logger->debug(sprintf($logMessage, $orphanCount));
+
+ // Requeue if there might be more orphans
+ if ($orphanCount >= self::BATCH_SIZE) {
+ $this->jobList->add(self::class, $argument);
+ }
+ }
+
+ private function cleanUpOrphans(
+ string $childTable,
+ string $parentTable,
+ string $parentId,
+ ): int {
+ // We can't merge both queries into a single one here as DELETEing from a table while
+ // SELECTing it in a sub query is not supported by Oracle DB.
+ // Ref https://docs.oracle.com/cd/E17952_01/mysql-8.0-en/delete.html#idm46006185488144
+
+ $selectQb = $this->connection->getQueryBuilder();
+
+ $selectQb->select('c.id')
+ ->from($childTable, 'c')
+ ->leftJoin('c', $parentTable, 'p', $selectQb->expr()->eq('c.' . $parentId, 'p.id'))
+ ->where($selectQb->expr()->isNull('p.id'))
+ ->setMaxResults(self::BATCH_SIZE);
+
+ if (\in_array($parentTable, ['calendars', 'calendarsubscriptions'], true)) {
+ $calendarType = $parentTable === 'calendarsubscriptions' ? CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION : CalDavBackend::CALENDAR_TYPE_CALENDAR;
+ $selectQb->andWhere($selectQb->expr()->eq('c.calendartype', $selectQb->createNamedParameter($calendarType, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT));
+ }
+
+ $result = $selectQb->executeQuery();
+ $rows = $result->fetchAll();
+ $result->closeCursor();
+ if (empty($rows)) {
+ return 0;
+ }
+
+ $orphanItems = array_map(static fn ($row) => $row['id'], $rows);
+ $deleteQb = $this->connection->getQueryBuilder();
+ $deleteQb->delete($childTable)
+ ->where($deleteQb->expr()->in('id', $deleteQb->createNamedParameter($orphanItems, IQueryBuilder::PARAM_INT_ARRAY)));
+ $deleteQb->executeStatement();
+
+ return count($orphanItems);
+ }
+}
diff --git a/apps/dav/lib/BulkUpload/BulkUploadPlugin.php b/apps/dav/lib/BulkUpload/BulkUploadPlugin.php
index 137bad34bf5..d4faf3764e1 100644
--- a/apps/dav/lib/BulkUpload/BulkUploadPlugin.php
+++ b/apps/dav/lib/BulkUpload/BulkUploadPlugin.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-only
diff --git a/apps/dav/lib/BulkUpload/MultipartRequestParser.php b/apps/dav/lib/BulkUpload/MultipartRequestParser.php
index 96a90f82cde..50f8cff76ba 100644
--- a/apps/dav/lib/BulkUpload/MultipartRequestParser.php
+++ b/apps/dav/lib/BulkUpload/MultipartRequestParser.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-only
@@ -57,7 +58,13 @@ class MultipartRequestParser {
*/
private function parseBoundaryFromHeaders(string $contentType): string {
try {
+ if (!str_contains($contentType, ';')) {
+ throw new \InvalidArgumentException('No semicolon in header');
+ }
[$mimeType, $boundary] = explode(';', $contentType);
+ if (!str_contains($boundary, '=')) {
+ throw new \InvalidArgumentException('No equal in boundary header');
+ }
[$boundaryKey, $boundaryValue] = explode('=', $boundary);
} catch (\Exception $e) {
throw new BadRequest('Error while parsing boundary in Content-Type header.', Http::STATUS_BAD_REQUEST, $e);
diff --git a/apps/dav/lib/CalDAV/Activity/Backend.php b/apps/dav/lib/CalDAV/Activity/Backend.php
index 5ae71f4ecc6..f0c49e6e28c 100644
--- a/apps/dav/lib/CalDAV/Activity/Backend.php
+++ b/apps/dav/lib/CalDAV/Activity/Backend.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Activity/Filter/Calendar.php b/apps/dav/lib/CalDAV/Activity/Filter/Calendar.php
index 7411202044d..78579ee84b7 100644
--- a/apps/dav/lib/CalDAV/Activity/Filter/Calendar.php
+++ b/apps/dav/lib/CalDAV/Activity/Filter/Calendar.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Activity/Filter/Todo.php b/apps/dav/lib/CalDAV/Activity/Filter/Todo.php
index 6bc7bd4b308..b001f90c28d 100644
--- a/apps/dav/lib/CalDAV/Activity/Filter/Todo.php
+++ b/apps/dav/lib/CalDAV/Activity/Filter/Todo.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Activity/Provider/Base.php b/apps/dav/lib/CalDAV/Activity/Provider/Base.php
index 9a75acb878c..558abe0ca1a 100644
--- a/apps/dav/lib/CalDAV/Activity/Provider/Base.php
+++ b/apps/dav/lib/CalDAV/Activity/Provider/Base.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -40,8 +41,8 @@ abstract class Base implements IProvider {
* @return array
*/
protected function generateCalendarParameter($data, IL10N $l) {
- if ($data['uri'] === CalDavBackend::PERSONAL_CALENDAR_URI &&
- $data['name'] === CalDavBackend::PERSONAL_CALENDAR_NAME) {
+ if ($data['uri'] === CalDavBackend::PERSONAL_CALENDAR_URI
+ && $data['name'] === CalDavBackend::PERSONAL_CALENDAR_NAME) {
return [
'type' => 'calendar',
'id' => (string)$data['id'],
diff --git a/apps/dav/lib/CalDAV/Activity/Provider/Calendar.php b/apps/dav/lib/CalDAV/Activity/Provider/Calendar.php
index 898eb2b5cb6..8c93ddae431 100644
--- a/apps/dav/lib/CalDAV/Activity/Provider/Calendar.php
+++ b/apps/dav/lib/CalDAV/Activity/Provider/Calendar.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Activity/Provider/Event.php b/apps/dav/lib/CalDAV/Activity/Provider/Event.php
index 41b610542df..87551d7840b 100644
--- a/apps/dav/lib/CalDAV/Activity/Provider/Event.php
+++ b/apps/dav/lib/CalDAV/Activity/Provider/Event.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -78,14 +79,9 @@ class Event extends Base {
// as seen from the affected user.
$objectId = base64_encode($this->url->getWebroot() . '/remote.php/dav/calendars/' . $affectedUser . '/' . $calendarUri . '_shared_by_' . $linkData['owner'] . '/' . $linkData['object_uri']);
}
- $link = [
- 'view' => 'dayGridMonth',
- 'timeRange' => 'now',
- 'mode' => 'sidebar',
+ $params['link'] = $this->url->linkToRouteAbsolute('calendar.view.indexdirect.edit', [
'objectId' => $objectId,
- 'recurrenceId' => 'next'
- ];
- $params['link'] = $this->url->linkToRouteAbsolute('calendar.view.indexview.timerange.edit', $link);
+ ]);
} catch (\Exception $error) {
// Do nothing
}
diff --git a/apps/dav/lib/CalDAV/Activity/Provider/Todo.php b/apps/dav/lib/CalDAV/Activity/Provider/Todo.php
index 1e817663439..fc0625ec970 100644
--- a/apps/dav/lib/CalDAV/Activity/Provider/Todo.php
+++ b/apps/dav/lib/CalDAV/Activity/Provider/Todo.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Activity/Setting/Calendar.php b/apps/dav/lib/CalDAV/Activity/Setting/Calendar.php
index a201213f784..0ad86a919bc 100644
--- a/apps/dav/lib/CalDAV/Activity/Setting/Calendar.php
+++ b/apps/dav/lib/CalDAV/Activity/Setting/Calendar.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Activity/Setting/Event.php b/apps/dav/lib/CalDAV/Activity/Setting/Event.php
index ea049738251..ea9476d6f08 100644
--- a/apps/dav/lib/CalDAV/Activity/Setting/Event.php
+++ b/apps/dav/lib/CalDAV/Activity/Setting/Event.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Activity/Setting/Todo.php b/apps/dav/lib/CalDAV/Activity/Setting/Todo.php
index 7ac3b1e0f76..ed8377b0ffa 100644
--- a/apps/dav/lib/CalDAV/Activity/Setting/Todo.php
+++ b/apps/dav/lib/CalDAV/Activity/Setting/Todo.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/BirthdayCalendar/EnablePlugin.php b/apps/dav/lib/CalDAV/BirthdayCalendar/EnablePlugin.php
index cd0b58c53d2..681709cdb6f 100644
--- a/apps/dav/lib/CalDAV/BirthdayCalendar/EnablePlugin.php
+++ b/apps/dav/lib/CalDAV/BirthdayCalendar/EnablePlugin.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/BirthdayService.php b/apps/dav/lib/CalDAV/BirthdayService.php
index e1e46316d74..680b228766f 100644
--- a/apps/dav/lib/CalDAV/BirthdayService.php
+++ b/apps/dav/lib/CalDAV/BirthdayService.php
@@ -295,8 +295,8 @@ class BirthdayService {
}
return (
- $newCalendarData->VEVENT->DTSTART->getValue() !== $existingBirthday->VEVENT->DTSTART->getValue() ||
- $newCalendarData->VEVENT->SUMMARY->getValue() !== $existingBirthday->VEVENT->SUMMARY->getValue()
+ $newCalendarData->VEVENT->DTSTART->getValue() !== $existingBirthday->VEVENT->DTSTART->getValue()
+ || $newCalendarData->VEVENT->SUMMARY->getValue() !== $existingBirthday->VEVENT->SUMMARY->getValue()
);
}
diff --git a/apps/dav/lib/CalDAV/CachedSubscriptionImpl.php b/apps/dav/lib/CalDAV/CachedSubscriptionImpl.php
index 4d25f5bb501..cc1bab6d4fc 100644
--- a/apps/dav/lib/CalDAV/CachedSubscriptionImpl.php
+++ b/apps/dav/lib/CalDAV/CachedSubscriptionImpl.php
@@ -9,11 +9,12 @@ declare(strict_types=1);
namespace OCA\DAV\CalDAV;
use OCP\Calendar\ICalendar;
+use OCP\Calendar\ICalendarIsEnabled;
use OCP\Calendar\ICalendarIsShared;
use OCP\Calendar\ICalendarIsWritable;
use OCP\Constants;
-class CachedSubscriptionImpl implements ICalendar, ICalendarIsShared, ICalendarIsWritable {
+class CachedSubscriptionImpl implements ICalendar, ICalendarIsEnabled, ICalendarIsShared, ICalendarIsWritable {
public function __construct(
private CachedSubscription $calendar,
@@ -54,16 +55,6 @@ class CachedSubscriptionImpl implements ICalendar, ICalendarIsShared, ICalendarI
return $this->calendarInfo['{http://apple.com/ns/ical/}calendar-color'];
}
- /**
- * @param string $pattern which should match within the $searchProperties
- * @param array $searchProperties defines the properties within the query pattern should match
- * @param array $options - optional parameters:
- * ['timerange' => ['start' => new DateTime(...), 'end' => new DateTime(...)]]
- * @param int|null $limit - limit number of search results
- * @param int|null $offset - offset for paging of search results
- * @return array an array of events/journals/todos which are arrays of key-value-pairs
- * @since 13.0.0
- */
public function search(string $pattern, array $searchProperties = [], array $options = [], $limit = null, $offset = null): array {
return $this->backend->search($this->calendarInfo, $pattern, $searchProperties, $options, $limit, $offset);
}
@@ -86,6 +77,13 @@ class CachedSubscriptionImpl implements ICalendar, ICalendarIsShared, ICalendarI
return $result;
}
+ /**
+ * @since 32.0.0
+ */
+ public function isEnabled(): bool {
+ return $this->calendarInfo['{http://owncloud.org/ns}calendar-enabled'] ?? true;
+ }
+
public function isWritable(): bool {
return false;
}
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php
index 81e999cc356..27750913105 100644
--- a/apps/dav/lib/CalDAV/CalDavBackend.php
+++ b/apps/dav/lib/CalDAV/CalDavBackend.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -9,6 +10,7 @@ namespace OCA\DAV\CalDAV;
use DateTime;
use DateTimeImmutable;
use DateTimeInterface;
+use Generator;
use OCA\DAV\AppInfo\Application;
use OCA\DAV\CalDAV\Sharing\Backend;
use OCA\DAV\Connector\Sabre\Principal;
@@ -28,6 +30,7 @@ use OCA\DAV\Events\SubscriptionCreatedEvent;
use OCA\DAV\Events\SubscriptionDeletedEvent;
use OCA\DAV\Events\SubscriptionUpdatedEvent;
use OCP\AppFramework\Db\TTransactional;
+use OCP\Calendar\CalendarExportOptions;
use OCP\Calendar\Events\CalendarObjectCreatedEvent;
use OCP\Calendar\Events\CalendarObjectDeletedEvent;
use OCP\Calendar\Events\CalendarObjectMovedEvent;
@@ -88,6 +91,19 @@ use function time;
* Code is heavily inspired by https://github.com/fruux/sabre-dav/blob/master/lib/CalDAV/Backend/PDO.php
*
* @package OCA\DAV\CalDAV
+ *
+ * @psalm-type CalendarInfo = array{
+ * id: int,
+ * uri: string,
+ * principaluri: string,
+ * '{http://calendarserver.org/ns/}getctag': string,
+ * '{http://sabredav.org/ns}sync-token': int,
+ * '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set': \Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet,
+ * '{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp': \Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp,
+ * '{DAV:}displayname': string,
+ * '{urn:ietf:params:xml:ns:caldav}calendar-timezone': ?string,
+ * '{http://nextcloud.com/ns}owner-displayname': string,
+ * }
*/
class CalDavBackend extends AbstractBackend implements SyncSupport, SubscriptionSupport, SchedulingSupport {
use TTransactional;
@@ -197,15 +213,13 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
}
/**
- * Return the number of calendars for a principal
+ * Return the number of calendars owned by the given principal.
*
- * By default this excludes the automatically generated birthday calendar
+ * Calendars shared with the given principal are not counted!
*
- * @param $principalUri
- * @param bool $excludeBirthday
- * @return int
+ * By default, this excludes the automatically generated birthday calendar.
*/
- public function getCalendarsForUserCount($principalUri, $excludeBirthday = true) {
+ public function getCalendarsForUserCount(string $principalUri, bool $excludeBirthday = true): int {
$principalUri = $this->convertPrincipal($principalUri, true);
$query = $this->db->getQueryBuilder();
$query->select($query->func()->count('*'))
@@ -372,7 +386,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$subSelect->select('resourceid')
->from('dav_shares', 'd')
->where($subSelect->expr()->eq('d.access', $select->createNamedParameter(Backend::ACCESS_UNSHARED, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT))
- ->andWhere($subSelect->expr()->in('d.principaluri', $select->createNamedParameter($principals, IQueryBuilder::PARAM_STR_ARRAY), IQueryBuilder::PARAM_STR_ARRAY));
+ ->andWhere($subSelect->expr()->eq('d.principaluri', $select->createNamedParameter($principalUri, IQueryBuilder::PARAM_STR), IQueryBuilder::PARAM_STR));
$select->select($fields)
->from('dav_shares', 's')
@@ -396,8 +410,8 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
// New share can not have more permissions than the old one.
continue;
}
- if (isset($calendars[$row['id']][$readOnlyPropertyName]) &&
- $calendars[$row['id']][$readOnlyPropertyName] === 0) {
+ if (isset($calendars[$row['id']][$readOnlyPropertyName])
+ && $calendars[$row['id']][$readOnlyPropertyName] === 0) {
// Old share is already read-write, no more permissions can be gained
continue;
}
@@ -649,7 +663,8 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
}
/**
- * @return array{id: int, uri: string, '{http://calendarserver.org/ns/}getctag': string, '{http://sabredav.org/ns}sync-token': int, '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set': SupportedCalendarComponentSet, '{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp': ScheduleCalendarTransp, '{urn:ietf:params:xml:ns:caldav}calendar-timezone': ?string }|null
+ * @psalm-return CalendarInfo|null
+ * @return array|null
*/
public function getCalendarById(int $calendarId): ?array {
$fields = array_column($this->propertyMap, 0);
@@ -988,6 +1003,44 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
}
/**
+ * Returns all calendar entries as a stream of data
+ *
+ * @since 32.0.0
+ *
+ * @return Generator<array>
+ */
+ public function exportCalendar(int $calendarId, int $calendarType = self::CALENDAR_TYPE_CALENDAR, ?CalendarExportOptions $options = null): Generator {
+ // extract options
+ $rangeStart = $options?->getRangeStart();
+ $rangeCount = $options?->getRangeCount();
+ // construct query
+ $qb = $this->db->getQueryBuilder();
+ $qb->select('*')
+ ->from('calendarobjects')
+ ->where($qb->expr()->eq('calendarid', $qb->createNamedParameter($calendarId)))
+ ->andWhere($qb->expr()->eq('calendartype', $qb->createNamedParameter($calendarType)))
+ ->andWhere($qb->expr()->isNull('deleted_at'));
+ if ($rangeStart !== null) {
+ $qb->andWhere($qb->expr()->gt('uid', $qb->createNamedParameter($rangeStart)));
+ }
+ if ($rangeCount !== null) {
+ $qb->setMaxResults($rangeCount);
+ }
+ if ($rangeStart !== null || $rangeCount !== null) {
+ $qb->orderBy('uid', 'ASC');
+ }
+ $rs = $qb->executeQuery();
+ // iterate through results
+ try {
+ while (($row = $rs->fetch()) !== false) {
+ yield $row;
+ }
+ } finally {
+ $rs->closeCursor();
+ }
+ }
+
+ /**
* Returns all calendar objects with limited metadata for a calendar
*
* Every item contains an array with the following keys:
@@ -1429,37 +1482,40 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
/**
* Moves a calendar object from calendar to calendar.
*
- * @param int $sourceCalendarId
+ * @param string $sourcePrincipalUri
+ * @param int $sourceObjectId
+ * @param string $targetPrincipalUri
* @param int $targetCalendarId
- * @param int $objectId
- * @param string $oldPrincipalUri
- * @param string $newPrincipalUri
+ * @param string $tragetObjectUri
* @param int $calendarType
* @return bool
* @throws Exception
*/
- public function moveCalendarObject(int $sourceCalendarId, int $targetCalendarId, int $objectId, string $oldPrincipalUri, string $newPrincipalUri, int $calendarType = self::CALENDAR_TYPE_CALENDAR): bool {
+ public function moveCalendarObject(string $sourcePrincipalUri, int $sourceObjectId, string $targetPrincipalUri, int $targetCalendarId, string $tragetObjectUri, int $calendarType = self::CALENDAR_TYPE_CALENDAR): bool {
$this->cachedObjects = [];
- return $this->atomic(function () use ($sourceCalendarId, $targetCalendarId, $objectId, $oldPrincipalUri, $newPrincipalUri, $calendarType) {
- $object = $this->getCalendarObjectById($oldPrincipalUri, $objectId);
+ return $this->atomic(function () use ($sourcePrincipalUri, $sourceObjectId, $targetPrincipalUri, $targetCalendarId, $tragetObjectUri, $calendarType) {
+ $object = $this->getCalendarObjectById($sourcePrincipalUri, $sourceObjectId);
if (empty($object)) {
return false;
}
+ $sourceCalendarId = $object['calendarid'];
+ $sourceObjectUri = $object['uri'];
+
$query = $this->db->getQueryBuilder();
$query->update('calendarobjects')
->set('calendarid', $query->createNamedParameter($targetCalendarId, IQueryBuilder::PARAM_INT))
- ->where($query->expr()->eq('id', $query->createNamedParameter($objectId, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT))
- ->andWhere($query->expr()->eq('calendartype', $query->createNamedParameter($calendarType, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT))
+ ->set('uri', $query->createNamedParameter($tragetObjectUri, IQueryBuilder::PARAM_STR))
+ ->where($query->expr()->eq('id', $query->createNamedParameter($sourceObjectId, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT))
->executeStatement();
- $this->purgeProperties($sourceCalendarId, $objectId);
- $this->updateProperties($targetCalendarId, $object['uri'], $object['calendardata'], $calendarType);
+ $this->purgeProperties($sourceCalendarId, $sourceObjectId);
+ $this->updateProperties($targetCalendarId, $tragetObjectUri, $object['calendardata'], $calendarType);
- $this->addChanges($sourceCalendarId, [$object['uri']], 3, $calendarType);
- $this->addChanges($targetCalendarId, [$object['uri']], 1, $calendarType);
+ $this->addChanges($sourceCalendarId, [$sourceObjectUri], 3, $calendarType);
+ $this->addChanges($targetCalendarId, [$tragetObjectUri], 1, $calendarType);
- $object = $this->getCalendarObjectById($newPrincipalUri, $objectId);
+ $object = $this->getCalendarObjectById($targetPrincipalUri, $sourceObjectId);
// Calendar Object wasn't found - possibly because it was deleted in the meantime by a different client
if (empty($object)) {
return false;
@@ -1481,25 +1537,6 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
}, $this->db);
}
-
- /**
- * @param int $calendarObjectId
- * @param int $classification
- */
- public function setClassification($calendarObjectId, $classification) {
- $this->cachedObjects = [];
- if (!in_array($classification, [
- self::CLASSIFICATION_PUBLIC, self::CLASSIFICATION_PRIVATE, self::CLASSIFICATION_CONFIDENTIAL
- ])) {
- throw new \InvalidArgumentException();
- }
- $query = $this->db->getQueryBuilder();
- $query->update('calendarobjects')
- ->set('classification', $query->createNamedParameter($classification))
- ->where($query->expr()->eq('id', $query->createNamedParameter($calendarObjectId)))
- ->executeStatement();
- }
-
/**
* Deletes an existing calendar object.
*
@@ -1973,8 +2010,8 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
if ($pattern !== '') {
$innerQuery->andWhere($innerQuery->expr()->iLike('op.value',
- $outerQuery->createNamedParameter('%' .
- $this->db->escapeLikeParameter($pattern) . '%')));
+ $outerQuery->createNamedParameter('%'
+ . $this->db->escapeLikeParameter($pattern) . '%')));
}
$start = null;
@@ -2950,7 +2987,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);
@@ -3628,4 +3665,26 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
->where($cmd->expr()->eq('uid', $cmd->createNamedParameter($eventId, IQueryBuilder::PARAM_STR), IQueryBuilder::PARAM_STR));
$cmd->executeStatement();
}
+
+ public function unshare(IShareable $shareable, string $principal): void {
+ $this->atomic(function () use ($shareable, $principal): void {
+ $calendarData = $this->getCalendarById($shareable->getResourceId());
+ if ($calendarData === null) {
+ throw new \RuntimeException('Trying to update shares for non-existing calendar: ' . $shareable->getResourceId());
+ }
+
+ $oldShares = $this->getShares($shareable->getResourceId());
+ $unshare = $this->calendarSharingBackend->unshare($shareable, $principal);
+
+ if ($unshare) {
+ $this->dispatcher->dispatchTyped(new CalendarShareUpdatedEvent(
+ $shareable->getResourceId(),
+ $calendarData,
+ $oldShares,
+ [],
+ [$principal]
+ ));
+ }
+ }, $this->db);
+ }
}
diff --git a/apps/dav/lib/CalDAV/Calendar.php b/apps/dav/lib/CalDAV/Calendar.php
index 6fd7d147131..dd3a4cf3f69 100644
--- a/apps/dav/lib/CalDAV/Calendar.php
+++ b/apps/dav/lib/CalDAV/Calendar.php
@@ -53,8 +53,8 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IRestorable, IShareable
if ($this->getName() === BirthdayService::BIRTHDAY_CALENDAR_URI && strcasecmp($this->calendarInfo['{DAV:}displayname'], 'Contact birthdays') === 0) {
$this->calendarInfo['{DAV:}displayname'] = $l10n->t('Contact birthdays');
}
- if ($this->getName() === CalDavBackend::PERSONAL_CALENDAR_URI &&
- $this->calendarInfo['{DAV:}displayname'] === CalDavBackend::PERSONAL_CALENDAR_NAME) {
+ if ($this->getName() === CalDavBackend::PERSONAL_CALENDAR_URI
+ && $this->calendarInfo['{DAV:}displayname'] === CalDavBackend::PERSONAL_CALENDAR_NAME) {
$this->calendarInfo['{DAV:}displayname'] = $l10n->t('Personal');
}
$this->l10n = $l10n;
@@ -214,12 +214,8 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IRestorable, IShareable
}
public function delete() {
- if (isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal']) &&
- $this->calendarInfo['{http://owncloud.org/ns}owner-principal'] !== $this->calendarInfo['principaluri']) {
- $principal = 'principal:' . parent::getOwner();
- $this->caldavBackend->updateShares($this, [], [
- $principal
- ]);
+ if ($this->isShared()) {
+ $this->caldavBackend->unshare($this, 'principal:' . $this->getPrincipalURI());
return;
}
@@ -391,9 +387,14 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IRestorable, IShareable
if (!($sourceNode instanceof CalendarObject)) {
return false;
}
-
try {
- return $this->caldavBackend->moveCalendarObject($sourceNode->getCalendarId(), (int)$this->calendarInfo['id'], $sourceNode->getId(), $sourceNode->getOwner(), $this->getOwner());
+ return $this->caldavBackend->moveCalendarObject(
+ $sourceNode->getOwner(),
+ $sourceNode->getId(),
+ $this->getOwner(),
+ $this->getResourceId(),
+ $targetName,
+ );
} catch (Exception $e) {
$this->logger->error('Could not move calendar object: ' . $e->getMessage(), ['exception' => $e]);
return false;
diff --git a/apps/dav/lib/CalDAV/CalendarImpl.php b/apps/dav/lib/CalDAV/CalendarImpl.php
index b3062f005ee..b79bf7ea2d0 100644
--- a/apps/dav/lib/CalDAV/CalendarImpl.php
+++ b/apps/dav/lib/CalDAV/CalendarImpl.php
@@ -8,9 +8,15 @@ declare(strict_types=1);
*/
namespace OCA\DAV\CalDAV;
+use Generator;
use OCA\DAV\CalDAV\Auth\CustomPrincipalPlugin;
use OCA\DAV\CalDAV\InvitationResponse\InvitationResponseServer;
+use OCP\Calendar\CalendarExportOptions;
use OCP\Calendar\Exceptions\CalendarException;
+use OCP\Calendar\ICalendarExport;
+use OCP\Calendar\ICalendarIsEnabled;
+use OCP\Calendar\ICalendarIsShared;
+use OCP\Calendar\ICalendarIsWritable;
use OCP\Calendar\ICreateFromString;
use OCP\Calendar\IHandleImipMessage;
use OCP\Constants;
@@ -24,7 +30,7 @@ use Sabre\VObject\Property;
use Sabre\VObject\Reader;
use function Sabre\Uri\split as uriSplit;
-class CalendarImpl implements ICreateFromString, IHandleImipMessage {
+class CalendarImpl implements ICreateFromString, IHandleImipMessage, ICalendarIsWritable, ICalendarIsShared, ICalendarExport, ICalendarIsEnabled {
public function __construct(
private Calendar $calendar,
/** @var array<string, mixed> */
@@ -87,16 +93,6 @@ class CalendarImpl implements ICreateFromString, IHandleImipMessage {
return $vtimezone;
}
- /**
- * @param string $pattern which should match within the $searchProperties
- * @param array $searchProperties defines the properties within the query pattern should match
- * @param array $options - optional parameters:
- * ['timerange' => ['start' => new DateTime(...), 'end' => new DateTime(...)]]
- * @param int|null $limit - limit number of search results
- * @param int|null $offset - offset for paging of search results
- * @return array an array of events/journals/todos which are arrays of key-value-pairs
- * @since 13.0.0
- */
public function search(string $pattern, array $searchProperties = [], array $options = [], $limit = null, $offset = null): array {
return $this->backend->search($this->calendarInfo, $pattern,
$searchProperties, $options, $limit, $offset);
@@ -132,6 +128,13 @@ class CalendarImpl implements ICreateFromString, IHandleImipMessage {
}
/**
+ * @since 32.0.0
+ */
+ public function isEnabled(): bool {
+ return $this->calendarInfo['{http://owncloud.org/ns}calendar-enabled'] ?? true;
+ }
+
+ /**
* @since 31.0.0
*/
public function isWritable(): bool {
@@ -257,4 +260,27 @@ class CalendarImpl implements ICreateFromString, IHandleImipMessage {
public function getInvitationResponseServer(): InvitationResponseServer {
return new InvitationResponseServer(false);
}
+
+ /**
+ * Export objects
+ *
+ * @since 32.0.0
+ *
+ * @return Generator<mixed, \Sabre\VObject\Component\VCalendar, mixed, mixed>
+ */
+ public function export(?CalendarExportOptions $options = null): Generator {
+ foreach (
+ $this->backend->exportCalendar(
+ $this->calendarInfo['id'],
+ $this->backend::CALENDAR_TYPE_CALENDAR,
+ $options
+ ) as $event
+ ) {
+ $vObject = Reader::read($event['calendardata']);
+ if ($vObject instanceof VCalendar) {
+ yield $vObject;
+ }
+ }
+ }
+
}
diff --git a/apps/dav/lib/CalDAV/CalendarManager.php b/apps/dav/lib/CalDAV/CalendarManager.php
index 1baf53ee457..a2d2f1cda8a 100644
--- a/apps/dav/lib/CalDAV/CalendarManager.php
+++ b/apps/dav/lib/CalDAV/CalendarManager.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/CalendarObject.php b/apps/dav/lib/CalDAV/CalendarObject.php
index 90a1e97ec4d..02178b4236f 100644
--- a/apps/dav/lib/CalDAV/CalendarObject.php
+++ b/apps/dav/lib/CalDAV/CalendarObject.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
diff --git a/apps/dav/lib/CalDAV/CalendarProvider.php b/apps/dav/lib/CalDAV/CalendarProvider.php
index a31322b2b49..3cc4039ed36 100644
--- a/apps/dav/lib/CalDAV/CalendarProvider.php
+++ b/apps/dav/lib/CalDAV/CalendarProvider.php
@@ -8,6 +8,8 @@ declare(strict_types=1);
*/
namespace OCA\DAV\CalDAV;
+use OCA\DAV\Db\Property;
+use OCA\DAV\Db\PropertyMapper;
use OCP\Calendar\ICalendarProvider;
use OCP\IConfig;
use OCP\IL10N;
@@ -20,6 +22,7 @@ class CalendarProvider implements ICalendarProvider {
private IL10N $l10n,
private IConfig $config,
private LoggerInterface $logger,
+ private PropertyMapper $propertyMapper,
) {
}
@@ -35,6 +38,7 @@ class CalendarProvider implements ICalendarProvider {
$iCalendars = [];
foreach ($calendarInfos as $calendarInfo) {
+ $calendarInfo = array_merge($calendarInfo, $this->getAdditionalProperties($calendarInfo['principaluri'], $calendarInfo['uri']));
$calendar = new Calendar($this->calDavBackend, $calendarInfo, $this->l10n, $this->config, $this->logger);
$iCalendars[] = new CalendarImpl(
$calendar,
@@ -44,4 +48,23 @@ class CalendarProvider implements ICalendarProvider {
}
return $iCalendars;
}
+
+ public function getAdditionalProperties(string $principalUri, string $calendarUri): array {
+ $user = str_replace('principals/users/', '', $principalUri);
+ $path = 'calendars/' . $user . '/' . $calendarUri;
+
+ $properties = $this->propertyMapper->findPropertiesByPath($user, $path);
+
+ $list = [];
+ foreach ($properties as $property) {
+ if ($property instanceof Property) {
+ $list[$property->getPropertyname()] = match ($property->getPropertyname()) {
+ '{http://owncloud.org/ns}calendar-enabled' => (bool)$property->getPropertyvalue(),
+ default => $property->getPropertyvalue()
+ };
+ }
+ }
+
+ return $list;
+ }
}
diff --git a/apps/dav/lib/CalDAV/CalendarRoot.php b/apps/dav/lib/CalDAV/CalendarRoot.php
index bfe5f84ce31..c0a313955bb 100644
--- a/apps/dav/lib/CalDAV/CalendarRoot.php
+++ b/apps/dav/lib/CalDAV/CalendarRoot.php
@@ -33,8 +33,8 @@ class CalendarRoot extends \Sabre\CalDAV\CalendarRoot {
}
public function getName() {
- if ($this->principalPrefix === 'principals/calendar-resources' ||
- $this->principalPrefix === 'principals/calendar-rooms') {
+ if ($this->principalPrefix === 'principals/calendar-resources'
+ || $this->principalPrefix === 'principals/calendar-rooms') {
$parts = explode('/', $this->principalPrefix);
return $parts[1];
diff --git a/apps/dav/lib/CalDAV/EventReader.php b/apps/dav/lib/CalDAV/EventReader.php
index 7e337f3108a..b7dd2889956 100644
--- a/apps/dav/lib/CalDAV/EventReader.php
+++ b/apps/dav/lib/CalDAV/EventReader.php
@@ -169,9 +169,9 @@ class EventReader {
if (isset($this->baseEvent->DTEND)) {
$this->baseEventEndDate = $this->baseEvent->DTEND->getDateTime($this->baseEventEndTimeZone);
$this->baseEventEndDateFloating = $this->baseEvent->DTEND->isFloating();
- $this->baseEventDuration =
- $this->baseEvent->DTEND->getDateTime($this->baseEventEndTimeZone)->getTimeStamp() -
- $this->baseEventStartDate->getTimeStamp();
+ $this->baseEventDuration
+ = $this->baseEvent->DTEND->getDateTime($this->baseEventEndTimeZone)->getTimeStamp()
+ - $this->baseEventStartDate->getTimeStamp();
}
// evaluate if duration exists
// extract duration and calculate end date
@@ -362,8 +362,8 @@ class EventReader {
public function recurringConcludes(): bool {
// retrieve rrule conclusions
- if ($this->rruleIterator?->concludesOn() !== null ||
- $this->rruleIterator?->concludesAfter() !== null) {
+ if ($this->rruleIterator?->concludesOn() !== null
+ || $this->rruleIterator?->concludesAfter() !== null) {
return true;
}
// retrieve rdate conclusions
diff --git a/apps/dav/lib/CalDAV/Export/ExportService.php b/apps/dav/lib/CalDAV/Export/ExportService.php
new file mode 100644
index 00000000000..552b9e2b675
--- /dev/null
+++ b/apps/dav/lib/CalDAV/Export/ExportService.php
@@ -0,0 +1,107 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\DAV\CalDAV\Export;
+
+use Generator;
+use OCP\Calendar\CalendarExportOptions;
+use OCP\Calendar\ICalendarExport;
+use OCP\ServerVersion;
+use Sabre\VObject\Component;
+use Sabre\VObject\Writer;
+
+/**
+ * Calendar Export Service
+ */
+class ExportService {
+
+ public const FORMATS = ['ical', 'jcal', 'xcal'];
+ private string $systemVersion;
+
+ public function __construct(ServerVersion $serverVersion) {
+ $this->systemVersion = $serverVersion->getVersionString();
+ }
+
+ /**
+ * Generates serialized content stream for a calendar and objects based in selected format
+ *
+ * @return Generator<string>
+ */
+ public function export(ICalendarExport $calendar, CalendarExportOptions $options): Generator {
+ // output start of serialized content based on selected format
+ yield $this->exportStart($options->getFormat());
+ // iterate through each returned vCalendar entry
+ // extract each component except timezones, convert to appropriate format and output
+ // extract any timezones and save them but do not output
+ $timezones = [];
+ foreach ($calendar->export($options) as $entry) {
+ $consecutive = false;
+ foreach ($entry->getComponents() as $vComponent) {
+ if ($vComponent->name === 'VTIMEZONE') {
+ if (isset($vComponent->TZID) && !isset($timezones[$vComponent->TZID->getValue()])) {
+ $timezones[$vComponent->TZID->getValue()] = clone $vComponent;
+ }
+ } else {
+ yield $this->exportObject($vComponent, $options->getFormat(), $consecutive);
+ $consecutive = true;
+ }
+ }
+ }
+ // iterate through each saved vTimezone entry, convert to appropriate format and output
+ foreach ($timezones as $vComponent) {
+ yield $this->exportObject($vComponent, $options->getFormat(), $consecutive);
+ $consecutive = true;
+ }
+ // output end of serialized content based on selected format
+ yield $this->exportFinish($options->getFormat());
+ }
+
+ /**
+ * Generates serialized content start based on selected format
+ */
+ private function exportStart(string $format): string {
+ return match ($format) {
+ 'jcal' => '["vcalendar",[["version",{},"text","2.0"],["prodid",{},"text","-\/\/IDN nextcloud.com\/\/Calendar Export v' . $this->systemVersion . '\/\/EN"]],[',
+ 'xcal' => '<?xml version="1.0" encoding="UTF-8"?><icalendar xmlns="urn:ietf:params:xml:ns:icalendar-2.0"><vcalendar><properties><version><text>2.0</text></version><prodid><text>-//IDN nextcloud.com//Calendar Export v' . $this->systemVersion . '//EN</text></prodid></properties><components>',
+ default => "BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//IDN nextcloud.com//Calendar Export v" . $this->systemVersion . "//EN\n"
+ };
+ }
+
+ /**
+ * Generates serialized content end based on selected format
+ */
+ private function exportFinish(string $format): string {
+ return match ($format) {
+ 'jcal' => ']]',
+ 'xcal' => '</components></vcalendar></icalendar>',
+ default => "END:VCALENDAR\n"
+ };
+ }
+
+ /**
+ * Generates serialized content for a component based on selected format
+ */
+ private function exportObject(Component $vobject, string $format, bool $consecutive): string {
+ return match ($format) {
+ 'jcal' => $consecutive ? ',' . Writer::writeJson($vobject) : Writer::writeJson($vobject),
+ 'xcal' => $this->exportObjectXml($vobject),
+ default => Writer::write($vobject)
+ };
+ }
+
+ /**
+ * Generates serialized content for a component in xml format
+ */
+ private function exportObjectXml(Component $vobject): string {
+ $writer = new \Sabre\Xml\Writer();
+ $writer->openMemory();
+ $writer->setIndent(false);
+ $vobject->xmlSerialize($writer);
+ return $writer->outputMemory();
+ }
+
+}
diff --git a/apps/dav/lib/CalDAV/ICSExportPlugin/ICSExportPlugin.php b/apps/dav/lib/CalDAV/ICSExportPlugin/ICSExportPlugin.php
index 3f71b1db24c..08dc10f7bf4 100644
--- a/apps/dav/lib/CalDAV/ICSExportPlugin/ICSExportPlugin.php
+++ b/apps/dav/lib/CalDAV/ICSExportPlugin/ICSExportPlugin.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Integration/ExternalCalendar.php b/apps/dav/lib/CalDAV/Integration/ExternalCalendar.php
index 6e755716397..acf81638679 100644
--- a/apps/dav/lib/CalDAV/Integration/ExternalCalendar.php
+++ b/apps/dav/lib/CalDAV/Integration/ExternalCalendar.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Integration/ICalendarProvider.php b/apps/dav/lib/CalDAV/Integration/ICalendarProvider.php
index bbee4cbda7c..40a8860dcb4 100644
--- a/apps/dav/lib/CalDAV/Integration/ICalendarProvider.php
+++ b/apps/dav/lib/CalDAV/Integration/ICalendarProvider.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php b/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php
index 3d650a4a059..c8a7109abde 100644
--- a/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php
+++ b/apps/dav/lib/CalDAV/InvitationResponse/InvitationResponseServer.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Outbox.php b/apps/dav/lib/CalDAV/Outbox.php
index fc9dc87a574..608114d8093 100644
--- a/apps/dav/lib/CalDAV/Outbox.php
+++ b/apps/dav/lib/CalDAV/Outbox.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Principal/Collection.php b/apps/dav/lib/CalDAV/Principal/Collection.php
index f2cea0b5136..b76fde66464 100644
--- a/apps/dav/lib/CalDAV/Principal/Collection.php
+++ b/apps/dav/lib/CalDAV/Principal/Collection.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Principal/User.php b/apps/dav/lib/CalDAV/Principal/User.php
index 60b7953ea62..047d83827ed 100644
--- a/apps/dav/lib/CalDAV/Principal/User.php
+++ b/apps/dav/lib/CalDAV/Principal/User.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/PublicCalendar.php b/apps/dav/lib/CalDAV/PublicCalendar.php
index 4ee811efeae..9af6e544165 100644
--- a/apps/dav/lib/CalDAV/PublicCalendar.php
+++ b/apps/dav/lib/CalDAV/PublicCalendar.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/PublicCalendarObject.php b/apps/dav/lib/CalDAV/PublicCalendarObject.php
index c3dc5ab1843..2ab40b94347 100644
--- a/apps/dav/lib/CalDAV/PublicCalendarObject.php
+++ b/apps/dav/lib/CalDAV/PublicCalendarObject.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php b/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php
index db73a761b0d..76378e7a1c5 100644
--- a/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php
+++ b/apps/dav/lib/CalDAV/Publishing/PublishPlugin.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Publishing/Xml/Publisher.php b/apps/dav/lib/CalDAV/Publishing/Xml/Publisher.php
index 2fd55a12643..fb9b7298f9b 100644
--- a/apps/dav/lib/CalDAV/Publishing/Xml/Publisher.php
+++ b/apps/dav/lib/CalDAV/Publishing/Xml/Publisher.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Reminder/ReminderService.php b/apps/dav/lib/CalDAV/Reminder/ReminderService.php
index e2d44535ce0..c75090e1560 100644
--- a/apps/dav/lib/CalDAV/Reminder/ReminderService.php
+++ b/apps/dav/lib/CalDAV/Reminder/ReminderService.php
@@ -441,10 +441,10 @@ class ReminderService {
*/
private function deleteOrProcessNext(array $reminder,
VObject\Component\VEvent $vevent):void {
- if ($reminder['is_repeat_based'] ||
- !$reminder['is_recurring'] ||
- !$reminder['is_relative'] ||
- $reminder['is_recurrence_exception']) {
+ if ($reminder['is_repeat_based']
+ || !$reminder['is_recurring']
+ || !$reminder['is_relative']
+ || $reminder['is_recurrence_exception']) {
$this->backend->removeReminder($reminder['id']);
return;
}
diff --git a/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php b/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php
index e1bd2f5be29..68bb3373346 100644
--- a/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php
+++ b/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -25,12 +26,6 @@ use function array_values;
abstract class AbstractPrincipalBackend implements BackendInterface {
- /** @var ProxyMapper */
- private $proxyMapper;
-
- /** @var string */
- private $principalPrefix;
-
/** @var string */
private $dbTableName;
@@ -45,13 +40,11 @@ abstract class AbstractPrincipalBackend implements BackendInterface {
private IUserSession $userSession,
private IGroupManager $groupManager,
private LoggerInterface $logger,
- ProxyMapper $proxyMapper,
- string $principalPrefix,
+ private ProxyMapper $proxyMapper,
+ private string $principalPrefix,
string $dbPrefix,
private string $cuType,
) {
- $this->proxyMapper = $proxyMapper;
- $this->principalPrefix = $principalPrefix;
$this->dbTableName = 'calendar_' . $dbPrefix . 's';
$this->dbMetaDataTableName = $this->dbTableName . '_md';
$this->dbForeignKeyName = $dbPrefix . '_id';
@@ -93,8 +86,8 @@ abstract class AbstractPrincipalBackend implements BackendInterface {
$metaDataById[$metaDataRow[$this->dbForeignKeyName]] = [];
}
- $metaDataById[$metaDataRow[$this->dbForeignKeyName]][$metaDataRow['key']] =
- $metaDataRow['value'];
+ $metaDataById[$metaDataRow[$this->dbForeignKeyName]][$metaDataRow['key']]
+ = $metaDataRow['value'];
}
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
@@ -478,9 +471,9 @@ abstract class AbstractPrincipalBackend implements BackendInterface {
* @return bool
*/
private function isAllowedToAccessResource(array $row, array $userGroups): bool {
- if (!isset($row['group_restrictions']) ||
- $row['group_restrictions'] === null ||
- $row['group_restrictions'] === '') {
+ if (!isset($row['group_restrictions'])
+ || $row['group_restrictions'] === null
+ || $row['group_restrictions'] === '') {
return true;
}
diff --git a/apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php b/apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php
index 40396f67ce9..c70d93daf52 100644
--- a/apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php
+++ b/apps/dav/lib/CalDAV/ResourceBooking/ResourcePrincipalBackend.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php b/apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php
index 91cf78c296f..5704b23ae14 100644
--- a/apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php
+++ b/apps/dav/lib/CalDAV/ResourceBooking/RoomPrincipalBackend.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php
index 7e79388c53a..1f063540df6 100644
--- a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php
+++ b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php
@@ -45,7 +45,7 @@ use Sabre\VObject\Reader;
* @license http://sabre.io/license/ Modified BSD License
*/
class IMipPlugin extends SabreIMipPlugin {
-
+
private ?VCalendar $vCalendar = null;
public const MAX_DATE = '2038-01-01';
public const METHOD_REQUEST = 'request';
@@ -156,9 +156,10 @@ class IMipPlugin extends SabreIMipPlugin {
$iTipMessage->scheduleStatus = '5.0; EMail delivery failed';
return;
}
- // Don't send emails to things
- if ($this->imipService->isRoomOrResource($attendee)) {
- $this->logger->debug('No invitation sent as recipient is room or resource', [
+ // Don't send emails to rooms, resources and circles
+ if ($this->imipService->isRoomOrResource($attendee)
+ || $this->imipService->isCircle($attendee)) {
+ $this->logger->debug('No invitation sent as recipient is room, resource or circle', [
'attendee' => $recipient,
]);
$iTipMessage->scheduleStatus = '1.0;We got the message, but it\'s not significant enough to warrant an email';
@@ -185,7 +186,7 @@ class IMipPlugin extends SabreIMipPlugin {
switch (strtolower($iTipMessage->method)) {
case self::METHOD_REPLY:
$method = self::METHOD_REPLY;
- $data = $this->imipService->buildBodyData($vEvent, $oldVevent);
+ $data = $this->imipService->buildReplyBodyData($vEvent);
$replyingAttendee = $this->imipService->getReplyingAttendee($iTipMessage);
break;
case self::METHOD_CANCEL:
diff --git a/apps/dav/lib/CalDAV/Schedule/IMipService.php b/apps/dav/lib/CalDAV/Schedule/IMipService.php
index e2844960a23..f7054eb2d34 100644
--- a/apps/dav/lib/CalDAV/Schedule/IMipService.php
+++ b/apps/dav/lib/CalDAV/Schedule/IMipService.php
@@ -159,7 +159,35 @@ class IMipService {
if ($eventReaderCurrent->recurs()) {
$data['meeting_occurring'] = $this->generateOccurringString($eventReaderCurrent);
}
-
+ return $data;
+ }
+
+ /**
+ * @param VEvent $vEvent
+ * @return array
+ */
+ public function buildReplyBodyData(VEvent $vEvent): array {
+ // construct event reader
+ $eventReader = new EventReader($vEvent);
+ $defaultVal = '';
+ $data = [];
+ $data['meeting_when'] = $this->generateWhenString($eventReader);
+
+ foreach (self::STRING_DIFF as $key => $property) {
+ $data[$key] = self::readPropertyWithDefault($vEvent, $property, $defaultVal);
+ }
+
+ if (($locationHtml = $this->linkify($data['meeting_location'])) !== null) {
+ $data['meeting_location_html'] = $locationHtml;
+ }
+
+ $data['meeting_url_html'] = $data['meeting_url'] ? sprintf('<a href="%1$s">%1$s</a>', $data['meeting_url']) : '';
+
+ // generate occurring next string
+ if ($eventReader->recurs()) {
+ $data['meeting_occurring'] = $this->generateOccurringString($eventReader);
+ }
+
return $data;
}
@@ -324,7 +352,7 @@ class IMipService {
* @return string
*/
public function generateWhenStringRecurringDaily(EventReader $er): string {
-
+
// initialize
$interval = (int)$er->recurringInterval();
$startTime = null;
@@ -375,7 +403,7 @@ class IMipService {
* @return string
*/
public function generateWhenStringRecurringWeekly(EventReader $er): string {
-
+
// initialize
$interval = (int)$er->recurringInterval();
$startTime = null;
@@ -428,15 +456,15 @@ class IMipService {
* @return string
*/
public function generateWhenStringRecurringMonthly(EventReader $er): string {
-
+
// initialize
$interval = (int)$er->recurringInterval();
$startTime = null;
$conclusion = null;
// days of month
if ($er->recurringPattern() === 'R') {
- $days = implode(', ', array_map(function ($value) { return $this->localizeRelativePositionName($value); }, $er->recurringRelativePositionNamed())) . ' ' .
- implode(', ', array_map(function ($value) { return $this->localizeDayName($value); }, $er->recurringDaysOfWeekNamed()));
+ $days = implode(', ', array_map(function ($value) { return $this->localizeRelativePositionName($value); }, $er->recurringRelativePositionNamed())) . ' '
+ . implode(', ', array_map(function ($value) { return $this->localizeDayName($value); }, $er->recurringDaysOfWeekNamed()));
} else {
$days = implode(', ', $er->recurringDaysOfMonth());
}
@@ -493,7 +521,7 @@ class IMipService {
* @return string
*/
public function generateWhenStringRecurringYearly(EventReader $er): string {
-
+
// initialize
$interval = (int)$er->recurringInterval();
$startTime = null;
@@ -502,8 +530,8 @@ class IMipService {
$months = implode(', ', array_map(function ($value) { return $this->localizeMonthName($value); }, $er->recurringMonthsOfYearNamed()));
// days of month
if ($er->recurringPattern() === 'R') {
- $days = implode(', ', array_map(function ($value) { return $this->localizeRelativePositionName($value); }, $er->recurringRelativePositionNamed())) . ' ' .
- implode(', ', array_map(function ($value) { return $this->localizeDayName($value); }, $er->recurringDaysOfWeekNamed()));
+ $days = implode(', ', array_map(function ($value) { return $this->localizeRelativePositionName($value); }, $er->recurringRelativePositionNamed())) . ' '
+ . implode(', ', array_map(function ($value) { return $this->localizeDayName($value); }, $er->recurringDaysOfWeekNamed()));
} else {
$days = $er->startDateTime()->format('jS');
}
@@ -582,7 +610,7 @@ class IMipService {
true => $this->l10n->t('On specific dates between %1$s - %2$s until %3$s', [$startTime, $endTime, $conclusion]),
};
}
-
+
/**
* generates a occurring next string for a recurring event
*
@@ -1080,8 +1108,8 @@ class IMipService {
$attendee = $iTipMessage->recipient;
$organizer = $iTipMessage->sender;
$sequence = $iTipMessage->sequence;
- $recurrenceId = isset($vevent->{'RECURRENCE-ID'}) ?
- $vevent->{'RECURRENCE-ID'}->serialize() : null;
+ $recurrenceId = isset($vevent->{'RECURRENCE-ID'})
+ ? $vevent->{'RECURRENCE-ID'}->serialize() : null;
$uid = $vevent->{'UID'};
$query = $this->db->getQueryBuilder();
@@ -1155,6 +1183,21 @@ class IMipService {
return false;
}
+ public function isCircle(Property $attendee): bool {
+ $cuType = $attendee->offsetGet('CUTYPE');
+ if (!$cuType instanceof Parameter) {
+ return false;
+ }
+
+ $uri = $attendee->getValue();
+ if (!$uri) {
+ return false;
+ }
+
+ $cuTypeValue = $cuType->getValue();
+ return $cuTypeValue === 'GROUP' && str_starts_with($uri, 'mailto:circle+');
+ }
+
public function minimizeInterval(\DateInterval $dateInterval): array {
// evaluate if time interval is in the past
if ($dateInterval->invert == 1) {
diff --git a/apps/dav/lib/CalDAV/Schedule/Plugin.php b/apps/dav/lib/CalDAV/Schedule/Plugin.php
index da0f9ea5637..a001df8b2a8 100644
--- a/apps/dav/lib/CalDAV/Schedule/Plugin.php
+++ b/apps/dav/lib/CalDAV/Schedule/Plugin.php
@@ -372,8 +372,8 @@ EOF;
return null;
}
- $isResourceOrRoom = str_starts_with($principalUrl, 'principals/calendar-resources') ||
- str_starts_with($principalUrl, 'principals/calendar-rooms');
+ $isResourceOrRoom = str_starts_with($principalUrl, 'principals/calendar-resources')
+ || str_starts_with($principalUrl, 'principals/calendar-rooms');
if (str_starts_with($principalUrl, 'principals/users')) {
[, $userId] = split($principalUrl);
diff --git a/apps/dav/lib/CalDAV/Search/SearchPlugin.php b/apps/dav/lib/CalDAV/Search/SearchPlugin.php
index 602ce151e12..27e39a76305 100644
--- a/apps/dav/lib/CalDAV/Search/SearchPlugin.php
+++ b/apps/dav/lib/CalDAV/Search/SearchPlugin.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -61,8 +62,8 @@ class SearchPlugin extends ServerPlugin {
$server->on('report', [$this, 'report']);
- $server->xml->elementMap['{' . self::NS_Nextcloud . '}calendar-search'] =
- CalendarSearchReport::class;
+ $server->xml->elementMap['{' . self::NS_Nextcloud . '}calendar-search']
+ = CalendarSearchReport::class;
}
/**
diff --git a/apps/dav/lib/CalDAV/Search/Xml/Filter/CompFilter.php b/apps/dav/lib/CalDAV/Search/Xml/Filter/CompFilter.php
index 8a130865842..21a4fff1caf 100644
--- a/apps/dav/lib/CalDAV/Search/Xml/Filter/CompFilter.php
+++ b/apps/dav/lib/CalDAV/Search/Xml/Filter/CompFilter.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Search/Xml/Filter/LimitFilter.php b/apps/dav/lib/CalDAV/Search/Xml/Filter/LimitFilter.php
index 943e657903e..a98b325397b 100644
--- a/apps/dav/lib/CalDAV/Search/Xml/Filter/LimitFilter.php
+++ b/apps/dav/lib/CalDAV/Search/Xml/Filter/LimitFilter.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Search/Xml/Filter/OffsetFilter.php b/apps/dav/lib/CalDAV/Search/Xml/Filter/OffsetFilter.php
index 439a795dde9..ef438aa0258 100644
--- a/apps/dav/lib/CalDAV/Search/Xml/Filter/OffsetFilter.php
+++ b/apps/dav/lib/CalDAV/Search/Xml/Filter/OffsetFilter.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Search/Xml/Filter/ParamFilter.php b/apps/dav/lib/CalDAV/Search/Xml/Filter/ParamFilter.php
index 3b03b63e909..0c31f32348a 100644
--- a/apps/dav/lib/CalDAV/Search/Xml/Filter/ParamFilter.php
+++ b/apps/dav/lib/CalDAV/Search/Xml/Filter/ParamFilter.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Search/Xml/Filter/PropFilter.php b/apps/dav/lib/CalDAV/Search/Xml/Filter/PropFilter.php
index 42ecf630f44..251120e35cc 100644
--- a/apps/dav/lib/CalDAV/Search/Xml/Filter/PropFilter.php
+++ b/apps/dav/lib/CalDAV/Search/Xml/Filter/PropFilter.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Search/Xml/Filter/SearchTermFilter.php b/apps/dav/lib/CalDAV/Search/Xml/Filter/SearchTermFilter.php
index b10cf3140cf..6d6bf958496 100644
--- a/apps/dav/lib/CalDAV/Search/Xml/Filter/SearchTermFilter.php
+++ b/apps/dav/lib/CalDAV/Search/Xml/Filter/SearchTermFilter.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/Search/Xml/Request/CalendarSearchReport.php b/apps/dav/lib/CalDAV/Search/Xml/Request/CalendarSearchReport.php
index 639d0b32655..6ece88fa87b 100644
--- a/apps/dav/lib/CalDAV/Search/Xml/Request/CalendarSearchReport.php
+++ b/apps/dav/lib/CalDAV/Search/Xml/Request/CalendarSearchReport.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CalDAV/TipBroker.php b/apps/dav/lib/CalDAV/TipBroker.php
index 43eff124f0b..16e68fde1f0 100644
--- a/apps/dav/lib/CalDAV/TipBroker.php
+++ b/apps/dav/lib/CalDAV/TipBroker.php
@@ -97,7 +97,7 @@ class TipBroker extends Broker {
// Also If the meeting STATUS property was changed to CANCELLED
// we need to send the attendee a CANCEL message.
if (!$attendee['newInstances'] || $eventInfo['status'] === 'CANCELLED') {
-
+
$message->method = $icalMsg->METHOD = 'CANCEL';
$message->significantChange = true;
// clone base event
@@ -108,7 +108,7 @@ class TipBroker extends Broker {
$event->DTSTAMP = gmdate('Ymd\\THis\\Z');
$event->SEQUENCE = $message->sequence;
$icalMsg->add($event);
-
+
} else {
// The attendee gets the updated event body
$message->method = $icalMsg->METHOD = 'REQUEST';
@@ -124,11 +124,11 @@ class TipBroker extends Broker {
$oldAttendeeInstances = array_keys($attendee['oldInstances']);
$newAttendeeInstances = array_keys($attendee['newInstances']);
- $message->significantChange =
- $attendee['forceSend'] === 'REQUEST' ||
- count($oldAttendeeInstances) !== count($newAttendeeInstances) ||
- count(array_diff($oldAttendeeInstances, $newAttendeeInstances)) > 0 ||
- $oldEventInfo['significantChangeHash'] !== $eventInfo['significantChangeHash'];
+ $message->significantChange
+ = $attendee['forceSend'] === 'REQUEST'
+ || count($oldAttendeeInstances) !== count($newAttendeeInstances)
+ || count(array_diff($oldAttendeeInstances, $newAttendeeInstances)) > 0
+ || $oldEventInfo['significantChangeHash'] !== $eventInfo['significantChangeHash'];
foreach ($attendee['newInstances'] as $instanceId => $instanceInfo) {
$currentEvent = clone $eventInfo['instances'][$instanceId];
diff --git a/apps/dav/lib/CalDAV/UpcomingEventsService.php b/apps/dav/lib/CalDAV/UpcomingEventsService.php
index 9c054deb4e0..6614d937ff7 100644
--- a/apps/dav/lib/CalDAV/UpcomingEventsService.php
+++ b/apps/dav/lib/CalDAV/UpcomingEventsService.php
@@ -47,20 +47,36 @@ class UpcomingEventsService {
$this->userManager->get($userId),
);
- return array_map(fn (array $event) => new UpcomingEvent(
- $event['uri'],
- ($event['objects'][0]['RECURRENCE-ID'][0] ?? null)?->getTimeStamp(),
- $event['calendar-uri'],
- $event['objects'][0]['DTSTART'][0]?->getTimestamp(),
- $event['objects'][0]['SUMMARY'][0] ?? null,
- $event['objects'][0]['LOCATION'][0] ?? null,
- match ($calendarAppEnabled) {
- // TODO: create a named, deep route in calendar
- // TODO: it's a code smell to just assume this route exists, find an abstraction
- true => $this->urlGenerator->linkToRouteAbsolute('calendar.view.index'),
- false => null,
- },
- ), $events);
+ return array_map(function (array $event) use ($userId, $calendarAppEnabled) {
+ $calendarAppUrl = null;
+
+ if ($calendarAppEnabled) {
+ $arguments = [
+ 'objectId' => base64_encode($this->urlGenerator->getWebroot() . '/remote.php/dav/calendars/' . $userId . '/' . $event['calendar-uri'] . '/' . $event['uri']),
+ ];
+
+ if (isset($event['RECURRENCE-ID'])) {
+ $arguments['recurrenceId'] = $event['RECURRENCE-ID'][0];
+ }
+ /**
+ * TODO: create a named, deep route in calendar (it's a code smell to just assume this route exists, find an abstraction)
+ * When changing, also adjust for:
+ * - spreed/lib/Service/CalendarIntegrationService.php#getDashboardEvents
+ * - spreed/lib/Service/CalendarIntegrationService.php#getMutualEvents
+ */
+ $calendarAppUrl = $this->urlGenerator->linkToRouteAbsolute('calendar.view.indexdirect.edit', $arguments);
+ }
+
+ return new UpcomingEvent(
+ $event['uri'],
+ ($event['objects'][0]['RECURRENCE-ID'][0] ?? null)?->getTimeStamp(),
+ $event['calendar-uri'],
+ $event['objects'][0]['DTSTART'][0]?->getTimestamp(),
+ $event['objects'][0]['SUMMARY'][0] ?? null,
+ $event['objects'][0]['LOCATION'][0] ?? null,
+ $calendarAppUrl,
+ );
+ }, $events);
}
}
diff --git a/apps/dav/lib/Capabilities.php b/apps/dav/lib/Capabilities.php
index ab4e53fce37..f9bad25bf31 100644
--- a/apps/dav/lib/Capabilities.php
+++ b/apps/dav/lib/Capabilities.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 ownCloud GmbH
* SPDX-License-Identifier: AGPL-3.0-only
@@ -17,12 +18,13 @@ class Capabilities implements ICapability {
}
/**
- * @return array{dav: array{chunking: string, bulkupload?: string, absence-supported?: bool, absence-replacement?: bool}}
+ * @return array{dav: array{chunking: string, public_shares_chunking: bool, bulkupload?: string, absence-supported?: bool, absence-replacement?: bool}}
*/
public function getCapabilities() {
$capabilities = [
'dav' => [
'chunking' => '1.0',
+ 'public_shares_chunking' => true,
]
];
if ($this->config->getSystemValueBool('bulkupload.enabled', true)) {
diff --git a/apps/dav/lib/CardDAV/Activity/Filter.php b/apps/dav/lib/CardDAV/Activity/Filter.php
index 8934c455def..8b221a29ff0 100644
--- a/apps/dav/lib/CardDAV/Activity/Filter.php
+++ b/apps/dav/lib/CardDAV/Activity/Filter.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/CardDAV/Activity/Provider/Base.php b/apps/dav/lib/CardDAV/Activity/Provider/Base.php
index 0c73c8558d0..ea7680aed60 100644
--- a/apps/dav/lib/CardDAV/Activity/Provider/Base.php
+++ b/apps/dav/lib/CardDAV/Activity/Provider/Base.php
@@ -41,8 +41,8 @@ abstract class Base implements IProvider {
* @return array
*/
protected function generateAddressbookParameter(array $data, IL10N $l): array {
- if ($data['uri'] === CardDavBackend::PERSONAL_ADDRESSBOOK_URI &&
- $data['name'] === CardDavBackend::PERSONAL_ADDRESSBOOK_NAME) {
+ if ($data['uri'] === CardDavBackend::PERSONAL_ADDRESSBOOK_URI
+ && $data['name'] === CardDavBackend::PERSONAL_ADDRESSBOOK_NAME) {
return [
'type' => 'addressbook',
'id' => (string)$data['id'],
diff --git a/apps/dav/lib/CardDAV/AddressBook.php b/apps/dav/lib/CardDAV/AddressBook.php
index 2ec645f04d2..67c0b7167fa 100644
--- a/apps/dav/lib/CardDAV/AddressBook.php
+++ b/apps/dav/lib/CardDAV/AddressBook.php
@@ -38,8 +38,8 @@ class AddressBook extends \Sabre\CardDAV\AddressBook implements IShareable, IMov
parent::__construct($carddavBackend, $addressBookInfo);
- if ($this->addressBookInfo['{DAV:}displayname'] === CardDavBackend::PERSONAL_ADDRESSBOOK_NAME &&
- $this->getName() === CardDavBackend::PERSONAL_ADDRESSBOOK_URI) {
+ if ($this->addressBookInfo['{DAV:}displayname'] === CardDavBackend::PERSONAL_ADDRESSBOOK_NAME
+ && $this->getName() === CardDavBackend::PERSONAL_ADDRESSBOOK_URI) {
$this->addressBookInfo['{DAV:}displayname'] = $l10n->t('Contacts');
}
}
diff --git a/apps/dav/lib/CardDAV/AddressBookImpl.php b/apps/dav/lib/CardDAV/AddressBookImpl.php
index 8657460d0c6..6bb8e24f628 100644
--- a/apps/dav/lib/CardDAV/AddressBookImpl.php
+++ b/apps/dav/lib/CardDAV/AddressBookImpl.php
@@ -307,8 +307,8 @@ class AddressBookImpl implements IAddressBookEnabled {
*/
public function isSystemAddressBook(): bool {
return $this->addressBookInfo['principaluri'] === 'principals/system/system' && (
- $this->addressBookInfo['uri'] === 'system' ||
- $this->addressBookInfo['{DAV:}displayname'] === $this->urlGenerator->getBaseUrl()
+ $this->addressBookInfo['uri'] === 'system'
+ || $this->addressBookInfo['{DAV:}displayname'] === $this->urlGenerator->getBaseUrl()
);
}
@@ -324,7 +324,7 @@ class AddressBookImpl implements IAddressBookEnabled {
$user = str_replace('principals/users/', '', $this->addressBookInfo['principaluri']);
$uri = $this->addressBookInfo['uri'];
}
-
+
$path = 'addressbooks/users/' . $user . '/' . $uri;
$properties = $this->propertyMapper->findPropertyByPathAndName($user, $path, '{http://owncloud.org/ns}enabled');
if (count($properties) > 0) {
diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php
index b15ed607076..06f6bf9448e 100644
--- a/apps/dav/lib/CardDAV/CardDavBackend.php
+++ b/apps/dav/lib/CardDAV/CardDavBackend.php
@@ -127,7 +127,6 @@ class CardDavBackend implements BackendInterface, SyncSupport {
// query for shared addressbooks
$principals = $this->principalBackend->getGroupMembership($principalUriOriginal, true);
- $principals = array_merge($principals, $this->principalBackend->getCircleMembership($principalUriOriginal));
$principals[] = $principalUri;
@@ -137,7 +136,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
$subSelect->select('id')
->from('dav_shares', 'd')
->where($subSelect->expr()->eq('d.access', $select->createNamedParameter(\OCA\DAV\CardDAV\Sharing\Backend::ACCESS_UNSHARED, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT))
- ->andWhere($subSelect->expr()->in('d.principaluri', $select->createNamedParameter($principals, IQueryBuilder::PARAM_STR_ARRAY), IQueryBuilder::PARAM_STR_ARRAY));
+ ->andWhere($subSelect->expr()->eq('d.principaluri', $select->createNamedParameter($principalUri, IQueryBuilder::PARAM_STR), IQueryBuilder::PARAM_STR));
$select->select(['a.id', 'a.uri', 'a.displayname', 'a.principaluri', 'a.description', 'a.synctoken', 's.access'])
@@ -160,8 +159,8 @@ class CardDavBackend implements BackendInterface, SyncSupport {
// New share can not have more permissions then the old one.
continue;
}
- if (isset($addressBooks[$row['id']][$readOnlyPropertyName]) &&
- $addressBooks[$row['id']][$readOnlyPropertyName] === 0) {
+ if (isset($addressBooks[$row['id']][$readOnlyPropertyName])
+ && $addressBooks[$row['id']][$readOnlyPropertyName] === 0) {
// Old share is already read-write, no more permissions can be gained
continue;
}
diff --git a/apps/dav/lib/CardDAV/PhotoCache.php b/apps/dav/lib/CardDAV/PhotoCache.php
index 2f1999b6b1c..03c71f7e4a3 100644
--- a/apps/dav/lib/CardDAV/PhotoCache.php
+++ b/apps/dav/lib/CardDAV/PhotoCache.php
@@ -1,10 +1,13 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
+
namespace OCA\DAV\CardDAV;
+use OCP\Files\AppData\IAppDataFactory;
use OCP\Files\IAppData;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
@@ -19,6 +22,7 @@ use Sabre\VObject\Property\Binary;
use Sabre\VObject\Reader;
class PhotoCache {
+ private ?IAppData $photoCacheAppData = null;
/** @var array */
public const ALLOWED_CONTENT_TYPES = [
@@ -30,12 +34,9 @@ class PhotoCache {
'image/avif' => 'avif',
];
- /**
- * PhotoCache constructor.
- */
public function __construct(
- protected IAppData $appData,
- protected LoggerInterface $logger,
+ private IAppDataFactory $appDataFactory,
+ private LoggerInterface $logger,
) {
}
@@ -142,13 +143,12 @@ class PhotoCache {
private function getFolder(int $addressBookId, string $cardUri, bool $createIfNotExists = true): ISimpleFolder {
$hash = md5($addressBookId . ' ' . $cardUri);
try {
- return $this->appData->getFolder($hash);
+ return $this->getPhotoCacheAppData()->getFolder($hash);
} catch (NotFoundException $e) {
if ($createIfNotExists) {
- return $this->appData->newFolder($hash);
- } else {
- throw $e;
+ return $this->getPhotoCacheAppData()->newFolder($hash);
}
+ throw $e;
}
}
@@ -265,4 +265,11 @@ class PhotoCache {
// that's OK, nothing to do
}
}
+
+ private function getPhotoCacheAppData(): IAppData {
+ if ($this->photoCacheAppData === null) {
+ $this->photoCacheAppData = $this->appDataFactory->get('dav-photocache');
+ }
+ return $this->photoCacheAppData;
+ }
}
diff --git a/apps/dav/lib/Command/ClearCalendarUnshares.php b/apps/dav/lib/Command/ClearCalendarUnshares.php
new file mode 100644
index 00000000000..bb367a9cd0f
--- /dev/null
+++ b/apps/dav/lib/Command/ClearCalendarUnshares.php
@@ -0,0 +1,114 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Command;
+
+use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\CalDAV\Sharing\Backend;
+use OCA\DAV\CalDAV\Sharing\Service;
+use OCA\DAV\Connector\Sabre\Principal;
+use OCA\DAV\DAV\Sharing\Backend as BackendAlias;
+use OCA\DAV\DAV\Sharing\SharingMapper;
+use OCP\IAppConfig;
+use OCP\IUserManager;
+use Symfony\Component\Console\Attribute\AsCommand;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Helper\QuestionHelper;
+use Symfony\Component\Console\Helper\Table;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Question\ConfirmationQuestion;
+
+#[AsCommand(
+ name: 'dav:clear-calendar-unshares',
+ description: 'Clear calendar unshares for a user',
+ hidden: false,
+)]
+class ClearCalendarUnshares extends Command {
+ public function __construct(
+ private IUserManager $userManager,
+ private IAppConfig $appConfig,
+ private Principal $principal,
+ private CalDavBackend $caldav,
+ private Backend $sharingBackend,
+ private Service $sharingService,
+ private SharingMapper $mapper,
+ ) {
+ parent::__construct();
+ }
+
+ protected function configure(): void {
+ $this->addArgument(
+ 'uid',
+ InputArgument::REQUIRED,
+ 'User whose unshares to clear'
+ );
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int {
+ $user = (string)$input->getArgument('uid');
+ if (!$this->userManager->userExists($user)) {
+ throw new \InvalidArgumentException("User $user is unknown");
+ }
+
+ $principal = $this->principal->getPrincipalByPath('principals/users/' . $user);
+ if ($principal === null) {
+ throw new \InvalidArgumentException("Unable to fetch principal for user $user ");
+ }
+
+ $shares = $this->mapper->getSharesByPrincipals([$principal['uri']], 'calendar');
+ $unshares = array_filter($shares, static fn ($share) => $share['access'] === BackendAlias::ACCESS_UNSHARED);
+
+ if (count($unshares) === 0) {
+ $output->writeln("User $user has no calendar unshares");
+ return self::SUCCESS;
+ }
+
+ $rows = array_map(fn ($share) => $this->formatCalendarUnshare($share), $shares);
+
+ $table = new Table($output);
+ $table
+ ->setHeaders(['Share Id', 'Calendar Id', 'Calendar URI', 'Calendar Name'])
+ ->setRows($rows)
+ ->render();
+
+ $output->writeln('');
+
+ /** @var QuestionHelper $helper */
+ $helper = $this->getHelper('question');
+ $question = new ConfirmationQuestion('Please confirm to delete the above calendar unshare entries [y/n]', false);
+
+ if ($helper->ask($input, $output, $question)) {
+ $this->mapper->deleteUnsharesByPrincipal($principal['uri'], 'calendar');
+ $output->writeln("Calendar unshares for user $user deleted");
+ }
+
+ return self::SUCCESS;
+ }
+
+ private function formatCalendarUnshare(array $share): array {
+ $calendarInfo = $this->caldav->getCalendarById($share['resourceid']);
+
+ $resourceUri = 'Resource not found';
+ $resourceName = '';
+
+ if ($calendarInfo !== null) {
+ $resourceUri = $calendarInfo['uri'];
+ $resourceName = $calendarInfo['{DAV:}displayname'];
+ }
+
+ return [
+ $share['id'],
+ $share['resourceid'],
+ $resourceUri,
+ $resourceName,
+ ];
+ }
+}
diff --git a/apps/dav/lib/Command/ClearContactsPhotoCache.php b/apps/dav/lib/Command/ClearContactsPhotoCache.php
new file mode 100644
index 00000000000..82e64c3145a
--- /dev/null
+++ b/apps/dav/lib/Command/ClearContactsPhotoCache.php
@@ -0,0 +1,75 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Command;
+
+use OCP\Files\AppData\IAppDataFactory;
+use OCP\Files\NotPermittedException;
+use Symfony\Component\Console\Attribute\AsCommand;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Helper\ProgressBar;
+use Symfony\Component\Console\Helper\QuestionHelper;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Question\ConfirmationQuestion;
+
+#[AsCommand(
+ name: 'dav:clear-contacts-photo-cache',
+ description: 'Clear cached contact photos',
+ hidden: false,
+)]
+class ClearContactsPhotoCache extends Command {
+
+ public function __construct(
+ private IAppDataFactory $appDataFactory,
+ ) {
+ parent::__construct();
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int {
+ $photoCacheAppData = $this->appDataFactory->get('dav-photocache');
+
+ $folders = $photoCacheAppData->getDirectoryListing();
+ $countFolders = count($folders);
+
+ if ($countFolders === 0) {
+ $output->writeln('No cached contact photos found.');
+ return self::SUCCESS;
+ }
+
+ $output->writeln('Found ' . count($folders) . ' cached contact photos.');
+
+ /** @var QuestionHelper $helper */
+ $helper = $this->getHelper('question');
+ $question = new ConfirmationQuestion('Please confirm to clear the contacts photo cache [y/n] ', true);
+
+ if ($helper->ask($input, $output, $question) === false) {
+ $output->writeln('Clearing the contacts photo cache aborted.');
+ return self::SUCCESS;
+ }
+
+ $progressBar = new ProgressBar($output, $countFolders);
+ $progressBar->start();
+
+ foreach ($folders as $folder) {
+ try {
+ $folder->delete();
+ } catch (NotPermittedException) {
+ }
+ $progressBar->advance();
+ }
+
+ $progressBar->finish();
+
+ $output->writeln('');
+ $output->writeln('Contacts photo cache cleared.');
+
+ return self::SUCCESS;
+ }
+}
diff --git a/apps/dav/lib/Command/ExportCalendar.php b/apps/dav/lib/Command/ExportCalendar.php
new file mode 100644
index 00000000000..6ed8aa2cfe4
--- /dev/null
+++ b/apps/dav/lib/Command/ExportCalendar.php
@@ -0,0 +1,95 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\DAV\Command;
+
+use InvalidArgumentException;
+use OCA\DAV\CalDAV\Export\ExportService;
+use OCP\Calendar\CalendarExportOptions;
+use OCP\Calendar\ICalendarExport;
+use OCP\Calendar\IManager;
+use OCP\IUserManager;
+use Symfony\Component\Console\Attribute\AsCommand;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * Calendar Export Command
+ *
+ * Used to export data from supported calendars to disk or stdout
+ */
+#[AsCommand(
+ name: 'calendar:export',
+ description: 'Export calendar data from supported calendars to disk or stdout',
+ hidden: false
+)]
+class ExportCalendar extends Command {
+ public function __construct(
+ private IUserManager $userManager,
+ private IManager $calendarManager,
+ private ExportService $exportService,
+ ) {
+ parent::__construct();
+ }
+
+ protected function configure(): void {
+ $this->setName('calendar:export')
+ ->setDescription('Export calendar data from supported calendars to disk or stdout')
+ ->addArgument('uid', InputArgument::REQUIRED, 'Id of system user')
+ ->addArgument('uri', InputArgument::REQUIRED, 'Uri of calendar')
+ ->addOption('format', null, InputOption::VALUE_REQUIRED, 'Format of output (ical, jcal, xcal) defaults to ical', 'ical')
+ ->addOption('location', null, InputOption::VALUE_REQUIRED, 'Location of where to write the output. defaults to stdout');
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int {
+ $userId = $input->getArgument('uid');
+ $calendarId = $input->getArgument('uri');
+ $format = $input->getOption('format');
+ $location = $input->getOption('location');
+
+ if (!$this->userManager->userExists($userId)) {
+ throw new InvalidArgumentException("User <$userId> not found.");
+ }
+ // retrieve calendar and evaluate if export is supported
+ $calendars = $this->calendarManager->getCalendarsForPrincipal('principals/users/' . $userId, [$calendarId]);
+ if ($calendars === []) {
+ throw new InvalidArgumentException("Calendar <$calendarId> not found.");
+ }
+ $calendar = $calendars[0];
+ if (!$calendar instanceof ICalendarExport) {
+ throw new InvalidArgumentException("Calendar <$calendarId> does not support exporting");
+ }
+ // construct options object
+ $options = new CalendarExportOptions();
+ // evaluate if provided format is supported
+ if (!in_array($format, ExportService::FORMATS, true)) {
+ throw new InvalidArgumentException("Format <$format> is not valid.");
+ }
+ $options->setFormat($format);
+ // evaluate is a valid location was given and is usable otherwise output to stdout
+ if ($location !== null) {
+ $handle = fopen($location, 'wb');
+ if ($handle === false) {
+ throw new InvalidArgumentException("Location <$location> is not valid. Can not open location for write operation.");
+ }
+
+ foreach ($this->exportService->export($calendar, $options) as $chunk) {
+ fwrite($handle, $chunk);
+ }
+ fclose($handle);
+ } else {
+ foreach ($this->exportService->export($calendar, $options) as $chunk) {
+ $output->writeln($chunk);
+ }
+ }
+
+ return self::SUCCESS;
+ }
+}
diff --git a/apps/dav/lib/Command/ListCalendarShares.php b/apps/dav/lib/Command/ListCalendarShares.php
new file mode 100644
index 00000000000..2729bc80530
--- /dev/null
+++ b/apps/dav/lib/Command/ListCalendarShares.php
@@ -0,0 +1,131 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Command;
+
+use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\CalDAV\Sharing\Backend;
+use OCA\DAV\Connector\Sabre\Principal;
+use OCA\DAV\DAV\Sharing\SharingMapper;
+use OCP\IUserManager;
+use Symfony\Component\Console\Attribute\AsCommand;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Helper\Table;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+#[AsCommand(
+ name: 'dav:list-calendar-shares',
+ description: 'List all calendar shares for a user',
+ hidden: false,
+)]
+class ListCalendarShares extends Command {
+ public function __construct(
+ private IUserManager $userManager,
+ private Principal $principal,
+ private CalDavBackend $caldav,
+ private SharingMapper $mapper,
+ ) {
+ parent::__construct();
+ }
+
+ protected function configure(): void {
+ $this->addArgument(
+ 'uid',
+ InputArgument::REQUIRED,
+ 'User whose calendar shares will be listed'
+ );
+ $this->addOption(
+ 'calendar-id',
+ '',
+ InputOption::VALUE_REQUIRED,
+ 'List only shares for the given calendar id id',
+ null,
+ );
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int {
+ $user = (string)$input->getArgument('uid');
+ if (!$this->userManager->userExists($user)) {
+ throw new \InvalidArgumentException("User $user is unknown");
+ }
+
+ $principal = $this->principal->getPrincipalByPath('principals/users/' . $user);
+ if ($principal === null) {
+ throw new \InvalidArgumentException("Unable to fetch principal for user $user");
+ }
+
+ $memberships = array_merge(
+ [$principal['uri']],
+ $this->principal->getGroupMembership($principal['uri']),
+ $this->principal->getCircleMembership($principal['uri']),
+ );
+
+ $shares = $this->mapper->getSharesByPrincipals($memberships, 'calendar');
+
+ $calendarId = $input->getOption('calendar-id');
+ if ($calendarId !== null) {
+ $shares = array_filter($shares, fn ($share) => $share['resourceid'] === (int)$calendarId);
+ }
+
+ $rows = array_map(fn ($share) => $this->formatCalendarShare($share), $shares);
+
+ if (count($rows) > 0) {
+ $table = new Table($output);
+ $table
+ ->setHeaders(['Share Id', 'Calendar Id', 'Calendar URI', 'Calendar Name', 'Calendar Owner', 'Access By', 'Permissions'])
+ ->setRows($rows)
+ ->render();
+ } else {
+ $output->writeln("User $user has no calendar shares");
+ }
+
+ return self::SUCCESS;
+ }
+
+ private function formatCalendarShare(array $share): array {
+ $calendarInfo = $this->caldav->getCalendarById($share['resourceid']);
+
+ $calendarUri = 'Resource not found';
+ $calendarName = '';
+ $calendarOwner = '';
+
+ if ($calendarInfo !== null) {
+ $calendarUri = $calendarInfo['uri'];
+ $calendarName = $calendarInfo['{DAV:}displayname'];
+ $calendarOwner = $calendarInfo['{http://nextcloud.com/ns}owner-displayname'] . ' (' . $calendarInfo['principaluri'] . ')';
+ }
+
+ $accessBy = match (true) {
+ str_starts_with($share['principaluri'], 'principals/users/') => 'Individual',
+ str_starts_with($share['principaluri'], 'principals/groups/') => 'Group (' . $share['principaluri'] . ')',
+ str_starts_with($share['principaluri'], 'principals/circles/') => 'Team (' . $share['principaluri'] . ')',
+ default => $share['principaluri'],
+ };
+
+ $permissions = match ($share['access']) {
+ Backend::ACCESS_READ => 'Read',
+ Backend::ACCESS_READ_WRITE => 'Read/Write',
+ Backend::ACCESS_UNSHARED => 'Unshare',
+ default => $share['access'],
+ };
+
+ return [
+ $share['id'],
+ $share['resourceid'],
+ $calendarUri,
+ $calendarName,
+ $calendarOwner,
+ $accessBy,
+ $permissions,
+ ];
+ }
+}
diff --git a/apps/dav/lib/Command/ListCalendars.php b/apps/dav/lib/Command/ListCalendars.php
index 06a1f7397c4..408a7e5247f 100644
--- a/apps/dav/lib/Command/ListCalendars.php
+++ b/apps/dav/lib/Command/ListCalendars.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Command/MoveCalendar.php b/apps/dav/lib/Command/MoveCalendar.php
index 36f20e5b547..b8acc191cc3 100644
--- a/apps/dav/lib/Command/MoveCalendar.php
+++ b/apps/dav/lib/Command/MoveCalendar.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Command/SendEventReminders.php b/apps/dav/lib/Command/SendEventReminders.php
index f5afb30ed70..89bb5ce8c20 100644
--- a/apps/dav/lib/Command/SendEventReminders.php
+++ b/apps/dav/lib/Command/SendEventReminders.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Connector/Sabre/AnonymousOptionsPlugin.php b/apps/dav/lib/Connector/Sabre/AnonymousOptionsPlugin.php
index b39dc7197b0..0e2b1c58748 100644
--- a/apps/dav/lib/Connector/Sabre/AnonymousOptionsPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/AnonymousOptionsPlugin.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Connector/Sabre/AppleQuirksPlugin.php b/apps/dav/lib/Connector/Sabre/AppleQuirksPlugin.php
index 88fff5e6a5a..9cff113140a 100644
--- a/apps/dav/lib/Connector/Sabre/AppleQuirksPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/AppleQuirksPlugin.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Connector/Sabre/Auth.php b/apps/dav/lib/Connector/Sabre/Auth.php
index d977721bdfa..a174920946a 100644
--- a/apps/dav/lib/Connector/Sabre/Auth.php
+++ b/apps/dav/lib/Connector/Sabre/Auth.php
@@ -55,8 +55,8 @@ class Auth extends AbstractBasic {
* @see https://github.com/owncloud/core/issues/13245
*/
public function isDavAuthenticated(string $username): bool {
- return !is_null($this->session->get(self::DAV_AUTHENTICATED)) &&
- $this->session->get(self::DAV_AUTHENTICATED) === $username;
+ return !is_null($this->session->get(self::DAV_AUTHENTICATED))
+ && $this->session->get(self::DAV_AUTHENTICATED) === $username;
}
/**
@@ -71,8 +71,8 @@ class Auth extends AbstractBasic {
* @throws PasswordLoginForbidden
*/
protected function validateUserPass($username, $password) {
- if ($this->userSession->isLoggedIn() &&
- $this->isDavAuthenticated($this->userSession->getUser()->getUID())
+ if ($this->userSession->isLoggedIn()
+ && $this->isDavAuthenticated($this->userSession->getUser()->getUID())
) {
$this->session->close();
return true;
@@ -118,7 +118,7 @@ class Auth extends AbstractBasic {
* Checks whether a CSRF check is required on the request
*/
private function requiresCSRFCheck(): bool {
-
+
$methodsWithoutCsrf = ['GET', 'HEAD', 'OPTIONS'];
if (in_array($this->request->getMethod(), $methodsWithoutCsrf)) {
return false;
@@ -144,8 +144,8 @@ class Auth extends AbstractBasic {
}
// If logged-in AND DAV authenticated no check is required
- if ($this->userSession->isLoggedIn() &&
- $this->isDavAuthenticated($this->userSession->getUser()->getUID())) {
+ if ($this->userSession->isLoggedIn()
+ && $this->isDavAuthenticated($this->userSession->getUser()->getUID())) {
return false;
}
@@ -159,8 +159,8 @@ class Auth extends AbstractBasic {
private function auth(RequestInterface $request, ResponseInterface $response): array {
$forcedLogout = false;
- if (!$this->request->passesCSRFCheck() &&
- $this->requiresCSRFCheck()) {
+ if (!$this->request->passesCSRFCheck()
+ && $this->requiresCSRFCheck()) {
// In case of a fail with POST we need to recheck the credentials
if ($this->request->getMethod() === 'POST') {
$forcedLogout = true;
@@ -178,10 +178,10 @@ class Auth extends AbstractBasic {
}
if (
//Fix for broken webdav clients
- ($this->userSession->isLoggedIn() && is_null($this->session->get(self::DAV_AUTHENTICATED))) ||
+ ($this->userSession->isLoggedIn() && is_null($this->session->get(self::DAV_AUTHENTICATED)))
//Well behaved clients that only send the cookie are allowed
- ($this->userSession->isLoggedIn() && $this->session->get(self::DAV_AUTHENTICATED) === $this->userSession->getUser()->getUID() && empty($request->getHeader('Authorization'))) ||
- \OC_User::handleApacheAuth()
+ || ($this->userSession->isLoggedIn() && $this->session->get(self::DAV_AUTHENTICATED) === $this->userSession->getUser()->getUID() && empty($request->getHeader('Authorization')))
+ || \OC_User::handleApacheAuth()
) {
$user = $this->userSession->getUser()->getUID();
$this->currentUser = $user;
diff --git a/apps/dav/lib/Connector/Sabre/BearerAuth.php b/apps/dav/lib/Connector/Sabre/BearerAuth.php
index e189d8fa128..23453ae8efb 100644
--- a/apps/dav/lib/Connector/Sabre/BearerAuth.php
+++ b/apps/dav/lib/Connector/Sabre/BearerAuth.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Connector/Sabre/CachingTree.php b/apps/dav/lib/Connector/Sabre/CachingTree.php
index 86e102677c1..5d72b530f58 100644
--- a/apps/dav/lib/Connector/Sabre/CachingTree.php
+++ b/apps/dav/lib/Connector/Sabre/CachingTree.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Connector/Sabre/ChecksumUpdatePlugin.php b/apps/dav/lib/Connector/Sabre/ChecksumUpdatePlugin.php
index 64a61a43a9b..18009080585 100644
--- a/apps/dav/lib/Connector/Sabre/ChecksumUpdatePlugin.php
+++ b/apps/dav/lib/Connector/Sabre/ChecksumUpdatePlugin.php
@@ -27,20 +27,6 @@ class ChecksumUpdatePlugin extends ServerPlugin {
}
/** @return string[] */
- public function getHTTPMethods($path): array {
- $tree = $this->server->tree;
-
- if ($tree->nodeExists($path)) {
- $node = $tree->getNodeForPath($path);
- if ($node instanceof File) {
- return ['PATCH'];
- }
- }
-
- return [];
- }
-
- /** @return string[] */
public function getFeatures(): array {
return ['nextcloud-checksum-update'];
}
diff --git a/apps/dav/lib/Connector/Sabre/DavAclPlugin.php b/apps/dav/lib/Connector/Sabre/DavAclPlugin.php
index 7846896182f..100d719ef01 100644
--- a/apps/dav/lib/Connector/Sabre/DavAclPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/DavAclPlugin.php
@@ -62,7 +62,7 @@ class DavAclPlugin extends \Sabre\DAVACL\Plugin {
)
);
}
-
+
}
return $access;
diff --git a/apps/dav/lib/Connector/Sabre/Directory.php b/apps/dav/lib/Connector/Sabre/Directory.php
index 7f8fe3a84de..fe09c3f423f 100644
--- a/apps/dav/lib/Connector/Sabre/Directory.php
+++ b/apps/dav/lib/Connector/Sabre/Directory.php
@@ -13,7 +13,9 @@ use OCA\DAV\AppInfo\Application;
use OCA\DAV\Connector\Sabre\Exception\FileLocked;
use OCA\DAV\Connector\Sabre\Exception\Forbidden;
use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
+use OCA\DAV\Storage\PublicShareWrapper;
use OCP\App\IAppManager;
+use OCP\Constants;
use OCP\Files\FileInfo;
use OCP\Files\Folder;
use OCP\Files\ForbiddenException;
@@ -172,7 +174,20 @@ class Directory extends Node implements \Sabre\DAV\ICollection, \Sabre\DAV\IQuot
* @throws \Sabre\DAV\Exception\ServiceUnavailable
*/
public function getChild($name, $info = null, ?IRequest $request = null, ?IL10N $l10n = null) {
- if (!$this->info->isReadable()) {
+ $storage = $this->info->getStorage();
+ $allowDirectory = false;
+
+ // Checking if we're in a file drop
+ // If we are, then only PUT and MKCOL are allowed (see plugin)
+ // so we are safe to return the directory without a risk of
+ // leaking files and folders structure.
+ if ($storage instanceof PublicShareWrapper) {
+ $share = $storage->getShare();
+ $allowDirectory = ($share->getPermissions() & Constants::PERMISSION_READ) !== Constants::PERMISSION_READ;
+ }
+
+ // For file drop we need to be allowed to read the directory with the nickname
+ if (!$allowDirectory && !$this->info->isReadable()) {
// avoid detecting files through this way
throw new NotFound();
}
@@ -198,6 +213,11 @@ class Directory extends Node implements \Sabre\DAV\ICollection, \Sabre\DAV\IQuot
if ($info->getMimeType() === FileInfo::MIMETYPE_FOLDER) {
$node = new \OCA\DAV\Connector\Sabre\Directory($this->fileView, $info, $this->tree, $this->shareManager);
} else {
+ // In case reading a directory was allowed but it turns out the node was a not a directory, reject it now.
+ if (!$this->info->isReadable()) {
+ throw new NotFound();
+ }
+
$node = new File($this->fileView, $info, $this->shareManager, $request, $l10n);
}
if ($this->tree) {
diff --git a/apps/dav/lib/Connector/Sabre/DummyGetResponsePlugin.php b/apps/dav/lib/Connector/Sabre/DummyGetResponsePlugin.php
index 4a7e30caa10..f6baceb748b 100644
--- a/apps/dav/lib/Connector/Sabre/DummyGetResponsePlugin.php
+++ b/apps/dav/lib/Connector/Sabre/DummyGetResponsePlugin.php
@@ -43,8 +43,8 @@ class DummyGetResponsePlugin extends \Sabre\DAV\ServerPlugin {
* @return false
*/
public function httpGet(RequestInterface $request, ResponseInterface $response) {
- $string = 'This is the WebDAV interface. It can only be accessed by ' .
- 'WebDAV clients such as the Nextcloud desktop sync client.';
+ $string = 'This is the WebDAV interface. It can only be accessed by '
+ . 'WebDAV clients such as the Nextcloud desktop sync client.';
$stream = fopen('php://memory', 'r+');
fwrite($stream, $string);
rewind($stream);
diff --git a/apps/dav/lib/Connector/Sabre/Exception/BadGateway.php b/apps/dav/lib/Connector/Sabre/Exception/BadGateway.php
index 41ace002660..1e1e4aaed04 100644
--- a/apps/dav/lib/Connector/Sabre/Exception/BadGateway.php
+++ b/apps/dav/lib/Connector/Sabre/Exception/BadGateway.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-only
diff --git a/apps/dav/lib/Connector/Sabre/FakeLockerPlugin.php b/apps/dav/lib/Connector/Sabre/FakeLockerPlugin.php
index 61ecfaf845c..b0c5a079ce1 100644
--- a/apps/dav/lib/Connector/Sabre/FakeLockerPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/FakeLockerPlugin.php
@@ -117,8 +117,8 @@ class FakeLockerPlugin extends ServerPlugin {
$lockInfo->timeout = 1800;
$body = $this->server->xml->write('{DAV:}prop', [
- '{DAV:}lockdiscovery' =>
- new LockDiscovery([$lockInfo])
+ '{DAV:}lockdiscovery'
+ => new LockDiscovery([$lockInfo])
]);
$response->setStatus(Http::STATUS_OK);
diff --git a/apps/dav/lib/Connector/Sabre/File.php b/apps/dav/lib/Connector/Sabre/File.php
index 045b9d7e784..218d38e1c4b 100644
--- a/apps/dav/lib/Connector/Sabre/File.php
+++ b/apps/dav/lib/Connector/Sabre/File.php
@@ -19,6 +19,7 @@ use OCA\DAV\Connector\Sabre\Exception\Forbidden as DAVForbiddenException;
use OCA\DAV\Connector\Sabre\Exception\UnsupportedMediaType;
use OCP\App\IAppManager;
use OCP\Encryption\Exceptions\GenericEncryptionException;
+use OCP\Files;
use OCP\Files\EntityTooLargeException;
use OCP\Files\FileInfo;
use OCP\Files\ForbiddenException;
@@ -215,7 +216,9 @@ class File extends Node implements IFile {
try {
/** @var IWriteStreamStorage $partStorage */
$count = $partStorage->writeStream($internalPartPath, $wrappedData);
- } catch (GenericFileException) {
+ } catch (GenericFileException $e) {
+ $logger = Server::get(LoggerInterface::class);
+ $logger->error('Error while writing stream to storage: ' . $e->getMessage(), ['exception' => $e, 'app' => 'webdav']);
$result = $isEOF;
if (is_resource($wrappedData)) {
$result = feof($wrappedData);
@@ -229,7 +232,7 @@ class File extends Node implements IFile {
// because we have no clue about the cause we can only throw back a 500/Internal Server Error
throw new Exception($this->l10n->t('Could not write file contents'));
}
- [$count, $result] = \OC_Helper::streamCopy($data, $target);
+ [$count, $result] = Files::streamCopy($data, $target, true);
fclose($target);
}
diff --git a/apps/dav/lib/Connector/Sabre/FilesPlugin.php b/apps/dav/lib/Connector/Sabre/FilesPlugin.php
index 34f48384e12..843383a0452 100644
--- a/apps/dav/lib/Connector/Sabre/FilesPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/FilesPlugin.php
@@ -9,8 +9,10 @@ namespace OCA\DAV\Connector\Sabre;
use OC\AppFramework\Http\Request;
use OC\FilesMetadata\Model\FilesMetadata;
+use OC\User\NoUserException;
use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
use OCA\Files_Sharing\External\Mount as SharingExternalMount;
+use OCP\Accounts\IAccountManager;
use OCP\Constants;
use OCP\Files\ForbiddenException;
use OCP\Files\IFilenameValidator;
@@ -91,6 +93,7 @@ class FilesPlugin extends ServerPlugin {
private IPreview $previewManager,
private IUserSession $userSession,
private IFilenameValidator $validator,
+ private IAccountManager $accountManager,
private bool $isPublic = false,
private bool $downloadAttachment = true,
) {
@@ -254,8 +257,8 @@ class FilesPlugin extends ServerPlugin {
// adds a 'Content-Disposition: attachment' header in case no disposition
// header has been set before
- if ($this->downloadAttachment &&
- $response->getHeader('Content-Disposition') === null) {
+ if ($this->downloadAttachment
+ && $response->getHeader('Content-Disposition') === null) {
$filename = $node->getName();
if ($this->request->isUserAgent(
[
@@ -361,9 +364,32 @@ class FilesPlugin extends ServerPlugin {
$owner = $node->getOwner();
if (!$owner) {
return null;
- } else {
+ }
+
+ // Get current user to see if we're in a public share or not
+ $user = $this->userSession->getUser();
+
+ // If the user is logged in, we can return the display name
+ if ($user !== null) {
return $owner->getDisplayName();
}
+
+ // Check if the user published their display name
+ try {
+ $ownerAccount = $this->accountManager->getAccount($owner);
+ } catch (NoUserException) {
+ // do not lock process if owner is not local
+ return null;
+ }
+
+ $ownerNameProperty = $ownerAccount->getProperty(IAccountManager::PROPERTY_DISPLAYNAME);
+
+ // Since we are not logged in, we need to have at least the published scope
+ if ($ownerNameProperty->getScope() === IAccountManager::SCOPE_PUBLISHED) {
+ return $owner->getDisplayName();
+ }
+
+ return null;
});
$propFind->handle(self::HAS_PREVIEW_PROPERTYNAME, function () use ($node) {
@@ -515,8 +541,8 @@ class FilesPlugin extends ServerPlugin {
$ocmPermissions[] = 'read';
}
- if (($ncPermissions & Constants::PERMISSION_CREATE) ||
- ($ncPermissions & Constants::PERMISSION_UPDATE)) {
+ if (($ncPermissions & Constants::PERMISSION_CREATE)
+ || ($ncPermissions & Constants::PERMISSION_UPDATE)) {
$ocmPermissions[] = 'write';
}
@@ -701,15 +727,15 @@ class FilesPlugin extends ServerPlugin {
*/
public function sendFileIdHeader($filePath, ?\Sabre\DAV\INode $node = null) {
// we get the node for the given $filePath here because in case of afterCreateFile $node is the parent folder
- if (!$this->server->tree->nodeExists($filePath)) {
- return;
- }
- $node = $this->server->tree->getNodeForPath($filePath);
- if ($node instanceof Node) {
- $fileId = $node->getFileId();
- if (!is_null($fileId)) {
- $this->server->httpResponse->setHeader('OC-FileId', $fileId);
+ try {
+ $node = $this->server->tree->getNodeForPath($filePath);
+ if ($node instanceof Node) {
+ $fileId = $node->getFileId();
+ if (!is_null($fileId)) {
+ $this->server->httpResponse->setHeader('OC-FileId', $fileId);
+ }
}
+ } catch (NotFound) {
}
}
}
diff --git a/apps/dav/lib/Connector/Sabre/MtimeSanitizer.php b/apps/dav/lib/Connector/Sabre/MtimeSanitizer.php
index efed6ce09f8..e18ef58149a 100644
--- a/apps/dav/lib/Connector/Sabre/MtimeSanitizer.php
+++ b/apps/dav/lib/Connector/Sabre/MtimeSanitizer.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-only
diff --git a/apps/dav/lib/Connector/Sabre/Principal.php b/apps/dav/lib/Connector/Sabre/Principal.php
index 515ef807a25..b61cabedf5f 100644
--- a/apps/dav/lib/Connector/Sabre/Principal.php
+++ b/apps/dav/lib/Connector/Sabre/Principal.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -41,9 +42,6 @@ class Principal implements BackendInterface {
/** @var bool */
private $hasCircles;
- /** @var ProxyMapper */
- private $proxyMapper;
-
/** @var KnownUserService */
private $knownUserService;
@@ -54,7 +52,7 @@ class Principal implements BackendInterface {
private IShareManager $shareManager,
private IUserSession $userSession,
private IAppManager $appManager,
- ProxyMapper $proxyMapper,
+ private ProxyMapper $proxyMapper,
KnownUserService $knownUserService,
private IConfig $config,
private IFactory $languageFactory,
@@ -62,7 +60,6 @@ class Principal implements BackendInterface {
) {
$this->principalPrefix = trim($principalPrefix, '/');
$this->hasGroups = $this->hasCircles = ($principalPrefix === 'principals/users/');
- $this->proxyMapper = $proxyMapper;
$this->knownUserService = $knownUserService;
}
@@ -155,6 +152,11 @@ class Principal implements BackendInterface {
'uri' => 'principals/system/' . $name,
'{DAV:}displayname' => $this->languageFactory->get('dav')->t('Accounts'),
];
+ } elseif ($prefix === 'principals/shares') {
+ return [
+ 'uri' => 'principals/shares/' . $name,
+ '{DAV:}displayname' => $name,
+ ];
}
return null;
}
diff --git a/apps/dav/lib/Connector/Sabre/PublicAuth.php b/apps/dav/lib/Connector/Sabre/PublicAuth.php
index ea59d9efc8f..2ca1c25e2f6 100644
--- a/apps/dav/lib/Connector/Sabre/PublicAuth.php
+++ b/apps/dav/lib/Connector/Sabre/PublicAuth.php
@@ -14,7 +14,9 @@ namespace OCA\DAV\Connector\Sabre;
use OCP\Defaults;
use OCP\IRequest;
use OCP\ISession;
+use OCP\IURLGenerator;
use OCP\Security\Bruteforce\IThrottler;
+use OCP\Security\Bruteforce\MaxDelayReached;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager;
use OCP\Share\IShare;
@@ -22,6 +24,7 @@ use Psr\Log\LoggerInterface;
use Sabre\DAV\Auth\Backend\AbstractBasic;
use Sabre\DAV\Exception\NotAuthenticated;
use Sabre\DAV\Exception\NotFound;
+use Sabre\DAV\Exception\PreconditionFailed;
use Sabre\DAV\Exception\ServiceUnavailable;
use Sabre\HTTP;
use Sabre\HTTP\RequestInterface;
@@ -44,6 +47,7 @@ class PublicAuth extends AbstractBasic {
private ISession $session,
private IThrottler $throttler,
private LoggerInterface $logger,
+ private IURLGenerator $urlGenerator,
) {
// setup realm
$defaults = new Defaults();
@@ -51,17 +55,18 @@ class PublicAuth extends AbstractBasic {
}
/**
- * @param RequestInterface $request
- * @param ResponseInterface $response
- *
- * @return array
* @throws NotAuthenticated
+ * @throws MaxDelayReached
* @throws ServiceUnavailable
*/
public function check(RequestInterface $request, ResponseInterface $response): array {
try {
$this->throttler->sleepDelayOrThrowOnMax($this->request->getRemoteAddress(), self::BRUTEFORCE_ACTION);
+ if (count($_COOKIE) > 0 && !$this->request->passesStrictCookieCheck() && $this->getShare()->getPassword() !== null) {
+ throw new PreconditionFailed('Strict cookie check failed');
+ }
+
$auth = new HTTP\Auth\Basic(
$this->realm,
$request,
@@ -75,7 +80,17 @@ class PublicAuth extends AbstractBasic {
}
return $this->checkToken();
- } catch (NotAuthenticated $e) {
+ } catch (NotAuthenticated|MaxDelayReached $e) {
+ $this->throttler->registerAttempt(self::BRUTEFORCE_ACTION, $this->request->getRemoteAddress());
+ throw $e;
+ } catch (PreconditionFailed $e) {
+ $response->setHeader(
+ 'Location',
+ $this->urlGenerator->linkToRoute(
+ 'files_sharing.share.showShare',
+ [ 'token' => $this->getToken() ],
+ ),
+ );
throw $e;
} catch (\Exception $e) {
$class = get_class($e);
@@ -87,14 +102,13 @@ class PublicAuth extends AbstractBasic {
/**
* Extract token from request url
- * @return string
* @throws NotFound
*/
private function getToken(): string {
$path = $this->request->getPathInfo() ?: '';
// ['', 'dav', 'files', 'token']
$splittedPath = explode('/', $path);
-
+
if (count($splittedPath) < 4 || $splittedPath[3] === '') {
throw new NotFound();
}
@@ -104,7 +118,7 @@ class PublicAuth extends AbstractBasic {
/**
* Check token validity
- * @return array
+ *
* @throws NotFound
* @throws NotAuthenticated
*/
@@ -152,15 +166,13 @@ class PublicAuth extends AbstractBasic {
protected function validateUserPass($username, $password) {
$this->throttler->sleepDelayOrThrowOnMax($this->request->getRemoteAddress(), self::BRUTEFORCE_ACTION);
- $token = $this->getToken();
try {
- $share = $this->shareManager->getShareByToken($token);
+ $share = $this->getShare();
} catch (ShareNotFound $e) {
$this->throttler->registerAttempt(self::BRUTEFORCE_ACTION, $this->request->getRemoteAddress());
return false;
}
- $this->share = $share;
\OC_User::setIncognitoMode(true);
// check if the share is password protected
@@ -176,7 +188,7 @@ class PublicAuth extends AbstractBasic {
}
return true;
}
-
+
if ($this->session->exists(PublicAuth::DAV_AUTHENTICATED)
&& $this->session->get(PublicAuth::DAV_AUTHENTICATED) === $share->getId()) {
return true;
@@ -203,7 +215,13 @@ class PublicAuth extends AbstractBasic {
}
public function getShare(): IShare {
- assert($this->share !== null);
+ $token = $this->getToken();
+
+ if ($this->share === null) {
+ $share = $this->shareManager->getShareByToken($token);
+ $this->share = $share;
+ }
+
return $this->share;
}
}
diff --git a/apps/dav/lib/Connector/Sabre/ServerFactory.php b/apps/dav/lib/Connector/Sabre/ServerFactory.php
index f035ff8d625..214412e1744 100644
--- a/apps/dav/lib/Connector/Sabre/ServerFactory.php
+++ b/apps/dav/lib/Connector/Sabre/ServerFactory.php
@@ -8,17 +8,23 @@
namespace OCA\DAV\Connector\Sabre;
use OC\Files\View;
+use OC\KnownUser\KnownUserService;
use OCA\DAV\AppInfo\PluginManager;
use OCA\DAV\CalDAV\DefaultCalendarValidator;
+use OCA\DAV\CalDAV\Proxy\ProxyMapper;
use OCA\DAV\DAV\CustomPropertiesBackend;
use OCA\DAV\DAV\ViewOnlyPlugin;
use OCA\DAV\Files\BrowserErrorPagePlugin;
+use OCA\DAV\Files\Sharing\RootCollection;
+use OCA\DAV\Upload\CleanupService;
use OCA\Theming\ThemingDefaults;
+use OCP\Accounts\IAccountManager;
use OCP\App\IAppManager;
use OCP\Comments\ICommentsManager;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Folder;
use OCP\Files\IFilenameValidator;
+use OCP\Files\IRootFolder;
use OCP\Files\Mount\IMountManager;
use OCP\IConfig;
use OCP\IDBConnection;
@@ -27,12 +33,14 @@ use OCP\IL10N;
use OCP\IPreview;
use OCP\IRequest;
use OCP\ITagManager;
+use OCP\IUserManager;
use OCP\IUserSession;
use OCP\SabrePluginEvent;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Auth\Plugin;
+use Sabre\DAV\SimpleCollection;
class ServerFactory {
@@ -53,13 +61,22 @@ class ServerFactory {
/**
* @param callable $viewCallBack callback that should return the view for the dav endpoint
*/
- public function createServer(string $baseUri,
+ public function createServer(
+ bool $isPublicShare,
+ string $baseUri,
string $requestUri,
Plugin $authPlugin,
- callable $viewCallBack): Server {
+ callable $viewCallBack,
+ ): Server {
// Fire up server
- $objectTree = new ObjectTree();
- $server = new Server($objectTree);
+ if ($isPublicShare) {
+ $rootCollection = new SimpleCollection('root');
+ $tree = new CachingTree($rootCollection);
+ } else {
+ $rootCollection = null;
+ $tree = new ObjectTree();
+ }
+ $server = new Server($tree);
// Set URL explicitly due to reverse-proxy situations
$server->httpRequest->setUrl($requestUri);
$server->setBaseUri($baseUri);
@@ -80,7 +97,7 @@ class ServerFactory {
$server->addPlugin(new RequestIdHeaderPlugin($this->request));
$server->addPlugin(new ZipFolderPlugin(
- $objectTree,
+ $tree,
$this->logger,
$this->eventDispatcher,
));
@@ -100,7 +117,7 @@ class ServerFactory {
}
// wait with registering these until auth is handled and the filesystem is setup
- $server->on('beforeMethod:*', function () use ($server, $objectTree, $viewCallBack): void {
+ $server->on('beforeMethod:*', function () use ($server, $tree, $viewCallBack, $isPublicShare, $rootCollection): void {
// ensure the skeleton is copied
$userFolder = \OC::$server->getUserFolder();
@@ -114,20 +131,55 @@ class ServerFactory {
// Create Nextcloud Dir
if ($rootInfo->getType() === 'dir') {
- $root = new Directory($view, $rootInfo, $objectTree);
+ $root = new Directory($view, $rootInfo, $tree);
} else {
$root = new File($view, $rootInfo);
}
- $objectTree->init($root, $view, $this->mountManager);
+
+ if ($isPublicShare) {
+ $userPrincipalBackend = new Principal(
+ \OCP\Server::get(IUserManager::class),
+ \OCP\Server::get(IGroupManager::class),
+ \OCP\Server::get(IAccountManager::class),
+ \OCP\Server::get(\OCP\Share\IManager::class),
+ \OCP\Server::get(IUserSession::class),
+ \OCP\Server::get(IAppManager::class),
+ \OCP\Server::get(ProxyMapper::class),
+ \OCP\Server::get(KnownUserService::class),
+ \OCP\Server::get(IConfig::class),
+ \OC::$server->getL10NFactory(),
+ );
+
+ // Mount the share collection at /public.php/dav/shares/<share token>
+ $rootCollection->addChild(new RootCollection(
+ $root,
+ $userPrincipalBackend,
+ 'principals/shares',
+ ));
+
+ // Mount the upload collection at /public.php/dav/uploads/<share token>
+ $rootCollection->addChild(new \OCA\DAV\Upload\RootCollection(
+ $userPrincipalBackend,
+ 'principals/shares',
+ \OCP\Server::get(CleanupService::class),
+ \OCP\Server::get(IRootFolder::class),
+ \OCP\Server::get(IUserSession::class),
+ \OCP\Server::get(\OCP\Share\IManager::class),
+ ));
+ } else {
+ /** @var ObjectTree $tree */
+ $tree->init($root, $view, $this->mountManager);
+ }
$server->addPlugin(
new FilesPlugin(
- $objectTree,
+ $tree,
$this->config,
$this->request,
$this->previewManager,
$this->userSession,
\OCP\Server::get(IFilenameValidator::class),
+ \OCP\Server::get(IAccountManager::class),
false,
!$this->config->getSystemValue('debug', false)
)
@@ -141,16 +193,16 @@ class ServerFactory {
));
if ($this->userSession->isLoggedIn()) {
- $server->addPlugin(new TagsPlugin($objectTree, $this->tagManager, $this->eventDispatcher, $this->userSession));
+ $server->addPlugin(new TagsPlugin($tree, $this->tagManager, $this->eventDispatcher, $this->userSession));
$server->addPlugin(new SharesPlugin(
- $objectTree,
+ $tree,
$this->userSession,
$userFolder,
\OCP\Server::get(\OCP\Share\IManager::class)
));
$server->addPlugin(new CommentPropertiesPlugin(\OCP\Server::get(ICommentsManager::class), $this->userSession));
$server->addPlugin(new FilesReportPlugin(
- $objectTree,
+ $tree,
$view,
\OCP\Server::get(ISystemTagManager::class),
\OCP\Server::get(ISystemTagObjectMapper::class),
@@ -165,7 +217,7 @@ class ServerFactory {
new \Sabre\DAV\PropertyStorage\Plugin(
new CustomPropertiesBackend(
$server,
- $objectTree,
+ $tree,
$this->databaseConnection,
$this->userSession->getUser(),
\OCP\Server::get(DefaultCalendarValidator::class),
diff --git a/apps/dav/lib/Connector/Sabre/SharesPlugin.php b/apps/dav/lib/Connector/Sabre/SharesPlugin.php
index 088cf33d85f..f49e85333f3 100644
--- a/apps/dav/lib/Connector/Sabre/SharesPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/SharesPlugin.php
@@ -176,8 +176,8 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin {
if ($sabreNode instanceof Directory
&& $propFind->getDepth() !== 0
&& (
- !is_null($propFind->getStatus(self::SHARETYPES_PROPERTYNAME)) ||
- !is_null($propFind->getStatus(self::SHAREES_PROPERTYNAME))
+ !is_null($propFind->getStatus(self::SHARETYPES_PROPERTYNAME))
+ || !is_null($propFind->getStatus(self::SHAREES_PROPERTYNAME))
)
) {
$folderNode = $sabreNode->getNode();
diff --git a/apps/dav/lib/Connector/Sabre/TagsPlugin.php b/apps/dav/lib/Connector/Sabre/TagsPlugin.php
index eb06fa5cef6..25c1633df36 100644
--- a/apps/dav/lib/Connector/Sabre/TagsPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/TagsPlugin.php
@@ -94,6 +94,7 @@ class TagsPlugin extends \Sabre\DAV\ServerPlugin {
$this->server = $server;
$this->server->on('propFind', [$this, 'handleGetProperties']);
$this->server->on('propPatch', [$this, 'handleUpdateProperties']);
+ $this->server->on('preloadProperties', [$this, 'handlePreloadProperties']);
}
/**
@@ -150,6 +151,24 @@ class TagsPlugin extends \Sabre\DAV\ServerPlugin {
}
/**
+ * Prefetches tags for a list of file IDs and caches the results
+ *
+ * @param array $fileIds List of file IDs to prefetch tags for
+ * @return void
+ */
+ private function prefetchTagsForFileIds(array $fileIds) {
+ $tags = $this->getTagger()->getTagsForObjects($fileIds);
+ if ($tags === false) {
+ // the tags API returns false on error...
+ $tags = [];
+ }
+
+ foreach ($fileIds as $fileId) {
+ $this->cachedTags[$fileId] = $tags[$fileId] ?? [];
+ }
+ }
+
+ /**
* Updates the tags of the given file id
*
* @param int $fileId
@@ -199,22 +218,11 @@ class TagsPlugin extends \Sabre\DAV\ServerPlugin {
)) {
// note: pre-fetching only supported for depth <= 1
$folderContent = $node->getChildren();
- $fileIds[] = (int)$node->getId();
+ $fileIds = [(int)$node->getId()];
foreach ($folderContent as $info) {
$fileIds[] = (int)$info->getId();
}
- $tags = $this->getTagger()->getTagsForObjects($fileIds);
- if ($tags === false) {
- // the tags API returns false on error...
- $tags = [];
- }
-
- $this->cachedTags = $this->cachedTags + $tags;
- $emptyFileIds = array_diff($fileIds, array_keys($tags));
- // also cache the ones that were not found
- foreach ($emptyFileIds as $fileId) {
- $this->cachedTags[$fileId] = [];
- }
+ $this->prefetchTagsForFileIds($fileIds);
}
$isFav = null;
@@ -270,4 +278,14 @@ class TagsPlugin extends \Sabre\DAV\ServerPlugin {
return 200;
});
}
+
+ public function handlePreloadProperties(array $nodes, array $requestProperties): void {
+ if (
+ !in_array(self::FAVORITE_PROPERTYNAME, $requestProperties, true)
+ && !in_array(self::TAGS_PROPERTYNAME, $requestProperties, true)
+ ) {
+ return;
+ }
+ $this->prefetchTagsForFileIds(array_map(fn ($node) => $node->getId(), $nodes));
+ }
}
diff --git a/apps/dav/lib/Controller/BirthdayCalendarController.php b/apps/dav/lib/Controller/BirthdayCalendarController.php
index d3a9239dd22..f6bfb229a9c 100644
--- a/apps/dav/lib/Controller/BirthdayCalendarController.php
+++ b/apps/dav/lib/Controller/BirthdayCalendarController.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Controller/ExampleContentController.php b/apps/dav/lib/Controller/ExampleContentController.php
index 9146eeb639d..e20ee4b7f49 100644
--- a/apps/dav/lib/Controller/ExampleContentController.php
+++ b/apps/dav/lib/Controller/ExampleContentController.php
@@ -10,77 +10,89 @@ declare(strict_types=1);
namespace OCA\DAV\Controller;
use OCA\DAV\AppInfo\Application;
-use OCP\App\IAppManager;
+use OCA\DAV\Service\ExampleContactService;
+use OCA\DAV\Service\ExampleEventService;
use OCP\AppFramework\ApiController;
use OCP\AppFramework\Http;
+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\IConfig;
use OCP\IRequest;
use Psr\Log\LoggerInterface;
class ExampleContentController extends ApiController {
- private IAppData $appData;
public function __construct(
IRequest $request,
- private IConfig $config,
- private IAppDataFactory $appDataFactory,
- private IAppManager $appManager,
- private LoggerInterface $logger,
+ 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->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', 'no')) {
+ 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 setCard(?string $cardData = null) {
- try {
- $folder = $this->appData->getFolder('defaultContact');
- } catch (NotFoundException $e) {
- $folder = $this->appData->newFolder('defaultContact');
- }
+ #[FrontpageRoute(verb: 'POST', url: '/api/exampleEvent/enable')]
+ public function setCreateExampleEvent(bool $enable): JSONResponse {
+ $this->exampleEventService->setCreateExampleEvent($enable);
+ return new JsonResponse([]);
+ }
- if (is_null($cardData)) {
- $cardData = file_get_contents(__DIR__ . '/../ExampleContentFiles/exampleContact.vcf');
- }
+ #[FrontpageRoute(verb: 'GET', url: '/api/exampleEvent/event')]
+ #[NoCSRFRequired]
+ public function downloadExampleEvent(): DataDownloadResponse {
+ $exampleEvent = $this->exampleEventService->getExampleEvent();
+ return new DataDownloadResponse(
+ $exampleEvent->getIcs(),
+ 'example_event.ics',
+ 'text/calendar',
+ );
+ }
- if (!$cardData) {
- throw new \Exception('Could not read exampleContact.vcf');
+ #[FrontpageRoute(verb: 'POST', url: '/api/exampleEvent/event')]
+ public function uploadExampleEvent(string $ics): JSONResponse {
+ if (!$this->exampleEventService->shouldCreateExampleEvent()) {
+ return new JSONResponse([], Http::STATUS_FORBIDDEN);
}
- $file = (!$folder->fileExists('defaultContact.vcf')) ? $folder->newFile('defaultContact.vcf') : $folder->getFile('defaultContact.vcf');
- $file->putContent($cardData);
+ $this->exampleEventService->saveCustomExampleEvent($ics);
+ return new JsonResponse([]);
}
- private function defaultContactExists(): bool {
- try {
- $folder = $this->appData->getFolder('defaultContact');
- } catch (NotFoundException $e) {
- return false;
- }
- return $folder->fileExists('defaultContact.vcf');
+ #[FrontpageRoute(verb: 'DELETE', url: '/api/exampleEvent/event')]
+ public function deleteExampleEvent(): JSONResponse {
+ $this->exampleEventService->deleteCustomExampleEvent();
+ return new JsonResponse([]);
}
}
diff --git a/apps/dav/lib/DAV/CustomPropertiesBackend.php b/apps/dav/lib/DAV/CustomPropertiesBackend.php
index c41ecd8450e..f3fff11b3da 100644
--- a/apps/dav/lib/DAV/CustomPropertiesBackend.php
+++ b/apps/dav/lib/DAV/CustomPropertiesBackend.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -92,6 +93,11 @@ class CustomPropertiesBackend implements BackendInterface {
'{http://nextcloud.org/ns}lock-time',
'{http://nextcloud.org/ns}lock-timeout',
'{http://nextcloud.org/ns}lock-token',
+ // photos
+ '{http://nextcloud.org/ns}realpath',
+ '{http://nextcloud.org/ns}nbItems',
+ '{http://nextcloud.org/ns}face-detections',
+ '{http://nextcloud.org/ns}face-preview-image',
];
/**
@@ -277,8 +283,8 @@ class CustomPropertiesBackend implements BackendInterface {
*/
public function move($source, $destination) {
$statement = $this->connection->prepare(
- 'UPDATE `*PREFIX*properties` SET `propertypath` = ?' .
- ' WHERE `userid` = ? AND `propertypath` = ?'
+ 'UPDATE `*PREFIX*properties` SET `propertypath` = ?'
+ . ' WHERE `userid` = ? AND `propertypath` = ?'
);
$statement->execute([$this->formatPath($destination), $this->user->getUID(), $this->formatPath($source)]);
$statement->closeCursor();
diff --git a/apps/dav/lib/DAV/GroupPrincipalBackend.php b/apps/dav/lib/DAV/GroupPrincipalBackend.php
index 143fc7d69f1..77ba45182c9 100644
--- a/apps/dav/lib/DAV/GroupPrincipalBackend.php
+++ b/apps/dav/lib/DAV/GroupPrincipalBackend.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -50,8 +51,10 @@ class GroupPrincipalBackend implements BackendInterface {
$principals = [];
if ($prefixPath === self::PRINCIPAL_PREFIX) {
- foreach ($this->groupManager->search('') as $user) {
- $principals[] = $this->groupToPrincipal($user);
+ foreach ($this->groupManager->search('') as $group) {
+ if (!$group->hideFromCollaboration()) {
+ $principals[] = $this->groupToPrincipal($group);
+ }
}
}
@@ -77,7 +80,7 @@ class GroupPrincipalBackend implements BackendInterface {
$name = urldecode($elements[2]);
$group = $this->groupManager->get($name);
- if (!is_null($group)) {
+ if ($group !== null && !$group->hideFromCollaboration()) {
return $this->groupToPrincipal($group);
}
@@ -186,6 +189,10 @@ class GroupPrincipalBackend implements BackendInterface {
$groups = $this->groupManager->search($value, $searchLimit);
$results[] = array_reduce($groups, function (array $carry, IGroup $group) use ($restrictGroups) {
+ if ($group->hideFromCollaboration()) {
+ return $carry;
+ }
+
$gid = $group->getGID();
// is sharing restricted to groups only?
if ($restrictGroups !== false) {
diff --git a/apps/dav/lib/DAV/Sharing/Backend.php b/apps/dav/lib/DAV/Sharing/Backend.php
index 06a082628d3..d60f5cca7c6 100644
--- a/apps/dav/lib/DAV/Sharing/Backend.php
+++ b/apps/dav/lib/DAV/Sharing/Backend.php
@@ -64,8 +64,8 @@ abstract class Backend {
}
$principalparts[2] = urldecode($principalparts[2]);
- if (($principalparts[1] === 'users' && !$this->userManager->userExists($principalparts[2])) ||
- ($principalparts[1] === 'groups' && !$this->groupManager->groupExists($principalparts[2]))) {
+ if (($principalparts[1] === 'users' && !$this->userManager->userExists($principalparts[2]))
+ || ($principalparts[1] === 'groups' && !$this->groupManager->groupExists($principalparts[2]))) {
// User or group does not exist
continue;
}
@@ -90,14 +90,6 @@ abstract class Backend {
// Delete any possible direct shares (since the frontend does not separate between them)
$this->service->deleteShare($shareable->getResourceId(), $principal);
-
- // Check if a user has a groupshare that they're trying to free themselves from
- // If so we need to add a self::ACCESS_UNSHARED row
- if (!str_contains($principal, 'group')
- && $this->service->hasGroupShare($oldShares)
- ) {
- $this->service->unshare($shareable->getResourceId(), $principal);
- }
}
}
@@ -204,4 +196,45 @@ abstract class Backend {
}
return $acl;
}
+
+ public function unshare(IShareable $shareable, string $principalUri): bool {
+ $this->shareCache->clear();
+
+ $principal = $this->principalBackend->findByUri($principalUri, '');
+ if (empty($principal)) {
+ return false;
+ }
+
+ if ($shareable->getOwner() === $principal) {
+ return false;
+ }
+
+ // Delete any possible direct shares (since the frontend does not separate between them)
+ $this->service->deleteShare($shareable->getResourceId(), $principal);
+
+ $needsUnshare = $this->hasAccessByGroupOrCirclesMembership(
+ $shareable->getResourceId(),
+ $principal
+ );
+
+ if ($needsUnshare) {
+ $this->service->unshare($shareable->getResourceId(), $principal);
+ }
+
+ return true;
+ }
+
+ private function hasAccessByGroupOrCirclesMembership(int $resourceId, string $principal) {
+ $memberships = array_merge(
+ $this->principalBackend->getGroupMembership($principal, true),
+ $this->principalBackend->getCircleMembership($principal)
+ );
+
+ $shares = array_column(
+ $this->service->getShares($resourceId),
+ 'principaluri'
+ );
+
+ return count(array_intersect($memberships, $shares)) > 0;
+ }
}
diff --git a/apps/dav/lib/DAV/Sharing/SharingMapper.php b/apps/dav/lib/DAV/Sharing/SharingMapper.php
index 0aec5b7fe81..e4722208189 100644
--- a/apps/dav/lib/DAV/Sharing/SharingMapper.php
+++ b/apps/dav/lib/DAV/Sharing/SharingMapper.php
@@ -110,4 +110,28 @@ class SharingMapper {
->andWhere($query->expr()->eq('type', $query->createNamedParameter($resourceType)))
->executeStatement();
}
+
+ public function getSharesByPrincipals(array $principals, string $resourceType): array {
+ $query = $this->db->getQueryBuilder();
+ $result = $query->select(['id', 'principaluri', 'type', 'access', 'resourceid'])
+ ->from('dav_shares')
+ ->where($query->expr()->in('principaluri', $query->createNamedParameter($principals, IQueryBuilder::PARAM_STR_ARRAY), IQueryBuilder::PARAM_STR_ARRAY))
+ ->andWhere($query->expr()->eq('type', $query->createNamedParameter($resourceType)))
+ ->orderBy('id')
+ ->executeQuery();
+
+ $rows = $result->fetchAll();
+ $result->closeCursor();
+
+ return $rows;
+ }
+
+ public function deleteUnsharesByPrincipal(string $principal, string $resourceType): void {
+ $query = $this->db->getQueryBuilder();
+ $query->delete('dav_shares')
+ ->where($query->expr()->eq('principaluri', $query->createNamedParameter($principal)))
+ ->andWhere($query->expr()->eq('type', $query->createNamedParameter($resourceType)))
+ ->andWhere($query->expr()->eq('access', $query->createNamedParameter(Backend::ACCESS_UNSHARED, IQueryBuilder::PARAM_INT)))
+ ->executeStatement();
+ }
}
diff --git a/apps/dav/lib/DAV/Sharing/SharingService.php b/apps/dav/lib/DAV/Sharing/SharingService.php
index b9ac36ea066..11459e12d74 100644
--- a/apps/dav/lib/DAV/Sharing/SharingService.php
+++ b/apps/dav/lib/DAV/Sharing/SharingService.php
@@ -50,14 +50,4 @@ abstract class SharingService {
public function getSharesForIds(array $resourceIds): array {
return $this->mapper->getSharesForIds($resourceIds, $this->getResourceType());
}
-
- /**
- * @param array $oldShares
- * @return bool
- */
- public function hasGroupShare(array $oldShares): bool {
- return !empty(array_filter($oldShares, function (array $share) {
- return $share['{http://owncloud.org/ns}group-share'] === true;
- }));
- }
}
diff --git a/apps/dav/lib/DAV/ViewOnlyPlugin.php b/apps/dav/lib/DAV/ViewOnlyPlugin.php
index 4c3b49a45b0..9b9615b8063 100644
--- a/apps/dav/lib/DAV/ViewOnlyPlugin.php
+++ b/apps/dav/lib/DAV/ViewOnlyPlugin.php
@@ -84,18 +84,25 @@ class ViewOnlyPlugin extends ServerPlugin {
if (!$storage->instanceOfStorage(ISharedStorage::class)) {
return true;
}
+
// Extract extra permissions
/** @var ISharedStorage $storage */
$share = $storage->getShare();
-
$attributes = $share->getAttributes();
if ($attributes === null) {
return true;
}
- // Check if read-only and on whether permission can download is both set and disabled.
+ // We have two options here, if download is disabled, but viewing is allowed,
+ // we still allow the GET request to return the file content.
$canDownload = $attributes->getAttribute('permissions', 'download');
- if ($canDownload !== null && !$canDownload) {
+ if (!$share->canSeeContent()) {
+ throw new Forbidden('Access to this shared resource has been denied because its download permission is disabled.');
+ }
+
+ // If download is disabled, we disable the COPY and MOVE methods even if the
+ // shareapi_allow_view_without_download is set to true.
+ if ($request->getMethod() !== 'GET' && ($canDownload !== null && !$canDownload)) {
throw new Forbidden('Access to this shared resource has been denied because its download permission is disabled.');
}
} catch (NotFound $e) {
diff --git a/apps/dav/lib/Db/PropertyMapper.php b/apps/dav/lib/Db/PropertyMapper.php
index a0ecb348ba4..1789194ee7a 100644
--- a/apps/dav/lib/Db/PropertyMapper.php
+++ b/apps/dav/lib/Db/PropertyMapper.php
@@ -38,4 +38,18 @@ class PropertyMapper extends QBMapper {
return $this->findEntities($selectQb);
}
+ /**
+ * @return Property[]
+ */
+ public function findPropertiesByPath(string $userId, string $path): array {
+ $selectQb = $this->db->getQueryBuilder();
+ $selectQb->select('*')
+ ->from(self::TABLE_NAME)
+ ->where(
+ $selectQb->expr()->eq('userid', $selectQb->createNamedParameter($userId)),
+ $selectQb->expr()->eq('propertypath', $selectQb->createNamedParameter($path)),
+ );
+ return $this->findEntities($selectQb);
+ }
+
}
diff --git a/apps/dav/lib/Direct/DirectHome.php b/apps/dav/lib/Direct/DirectHome.php
index 10e1017f5a4..ac411c9b52f 100644
--- a/apps/dav/lib/Direct/DirectHome.php
+++ b/apps/dav/lib/Direct/DirectHome.php
@@ -53,7 +53,7 @@ class DirectHome implements ICollection {
} catch (DoesNotExistException $e) {
// Since the token space is so huge only throttle on non-existing token
$this->throttler->registerAttempt('directlink', $this->request->getRemoteAddress());
- $this->throttler->sleepDelay($this->request->getRemoteAddress(), 'directlink');
+ $this->throttler->sleepDelayOrThrowOnMax($this->request->getRemoteAddress(), 'directlink');
throw new NotFound();
}
diff --git a/apps/dav/lib/Events/CalendarShareUpdatedEvent.php b/apps/dav/lib/Events/CalendarShareUpdatedEvent.php
index 762307b202f..0f8b23ad3ac 100644
--- a/apps/dav/lib/Events/CalendarShareUpdatedEvent.php
+++ b/apps/dav/lib/Events/CalendarShareUpdatedEvent.php
@@ -8,22 +8,24 @@ declare(strict_types=1);
*/
namespace OCA\DAV\Events;
+use OCA\DAV\CalDAV\CalDavBackend;
use OCP\EventDispatcher\Event;
-use Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp;
-use Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet;
/**
* Class CalendarShareUpdatedEvent
*
* @package OCA\DAV\Events
* @since 20.0.0
+ *
+ * @psalm-import-type CalendarInfo from CalDavBackend
*/
class CalendarShareUpdatedEvent extends Event {
/**
* CalendarShareUpdatedEvent constructor.
*
* @param int $calendarId
- * @param array{id: int, uri: string, '{http://calendarserver.org/ns/}getctag': string, '{http://sabredav.org/ns}sync-token': int, '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set': SupportedCalendarComponentSet, '{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp': ScheduleCalendarTransp, '{urn:ietf:params:xml:ns:caldav}calendar-timezone': ?string } $calendarData
+ * @psalm-param CalendarInfo $calendarData
+ * @param array $calendarData
* @param list<array{href: string, commonName: string, status: int, readOnly: bool, '{http://owncloud.org/ns}principal': string, '{http://owncloud.org/ns}group-share': bool}> $oldShares
* @param list<array{href: string, commonName: string, readOnly: bool}> $added
* @param list<string> $removed
@@ -47,7 +49,8 @@ class CalendarShareUpdatedEvent extends Event {
}
/**
- * @return array{id: int, uri: string, '{http://calendarserver.org/ns/}getctag': string, '{http://sabredav.org/ns}sync-token': int, '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set': SupportedCalendarComponentSet, '{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp': ScheduleCalendarTransp, '{urn:ietf:params:xml:ns:caldav}calendar-timezone': ?string }
+ * @psalm-return CalendarInfo
+ * @return array
* @since 20.0.0
*/
public function getCalendarData(): array {
diff --git a/apps/dav/lib/Exception/ExampleEventException.php b/apps/dav/lib/Exception/ExampleEventException.php
new file mode 100644
index 00000000000..2d77cc443cb
--- /dev/null
+++ b/apps/dav/lib/Exception/ExampleEventException.php
@@ -0,0 +1,13 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Exception;
+
+class ExampleEventException extends \Exception {
+}
diff --git a/apps/dav/lib/Exception/UnsupportedLimitOnInitialSyncException.php b/apps/dav/lib/Exception/UnsupportedLimitOnInitialSyncException.php
index 1022625c23b..c6b7f8564c5 100644
--- a/apps/dav/lib/Exception/UnsupportedLimitOnInitialSyncException.php
+++ b/apps/dav/lib/Exception/UnsupportedLimitOnInitialSyncException.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Files/BrowserErrorPagePlugin.php b/apps/dav/lib/Files/BrowserErrorPagePlugin.php
index de86c4995e2..85ed975a409 100644
--- a/apps/dav/lib/Files/BrowserErrorPagePlugin.php
+++ b/apps/dav/lib/Files/BrowserErrorPagePlugin.php
@@ -11,6 +11,7 @@ use OC\AppFramework\Http\Request;
use OCP\AppFramework\Http\ContentSecurityPolicy;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\IRequest;
+use OCP\Security\Bruteforce\MaxDelayReached;
use OCP\Template\ITemplateManager;
use Sabre\DAV\Exception;
use Sabre\DAV\Server;
@@ -60,6 +61,9 @@ class BrowserErrorPagePlugin extends ServerPlugin {
if ($ex instanceof Exception) {
$httpCode = $ex->getHTTPCode();
$headers = $ex->getHTTPHeaders($this->server);
+ } elseif ($ex instanceof MaxDelayReached) {
+ $httpCode = 429;
+ $headers = [];
} else {
$httpCode = 500;
$headers = [];
@@ -81,7 +85,7 @@ class BrowserErrorPagePlugin extends ServerPlugin {
$request = \OCP\Server::get(IRequest::class);
$templateName = 'exception';
- if ($httpCode === 403 || $httpCode === 404) {
+ if ($httpCode === 403 || $httpCode === 404 || $httpCode === 429) {
$templateName = (string)$httpCode;
}
diff --git a/apps/dav/lib/Files/FileSearchBackend.php b/apps/dav/lib/Files/FileSearchBackend.php
index ace367e4490..eb548bbd55c 100644
--- a/apps/dav/lib/Files/FileSearchBackend.php
+++ b/apps/dav/lib/Files/FileSearchBackend.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -15,6 +16,7 @@ use OCA\DAV\Connector\Sabre\CachingTree;
use OCA\DAV\Connector\Sabre\Directory;
use OCA\DAV\Connector\Sabre\File;
use OCA\DAV\Connector\Sabre\FilesPlugin;
+use OCA\DAV\Connector\Sabre\Server;
use OCA\DAV\Connector\Sabre\TagsPlugin;
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\Folder;
@@ -44,6 +46,7 @@ class FileSearchBackend implements ISearchBackend {
public const OPERATOR_LIMIT = 100;
public function __construct(
+ private Server $server,
private CachingTree $tree,
private IUser $user,
private IRootFolder $rootFolder,
@@ -133,6 +136,7 @@ class FileSearchBackend implements ISearchBackend {
* @param string[] $requestProperties
*/
public function preloadPropertyFor(array $nodes, array $requestProperties): void {
+ $this->server->emit('preloadProperties', [$nodes, $requestProperties]);
}
private function getFolderForPath(?string $path = null): Folder {
diff --git a/apps/dav/lib/Files/LazySearchBackend.php b/apps/dav/lib/Files/LazySearchBackend.php
index a0ad730ff2b..6ba539ddd87 100644
--- a/apps/dav/lib/Files/LazySearchBackend.php
+++ b/apps/dav/lib/Files/LazySearchBackend.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Files/Sharing/FilesDropPlugin.php b/apps/dav/lib/Files/Sharing/FilesDropPlugin.php
index 9d883be81fc..a3dbd32ce6b 100644
--- a/apps/dav/lib/Files/Sharing/FilesDropPlugin.php
+++ b/apps/dav/lib/Files/Sharing/FilesDropPlugin.php
@@ -1,12 +1,15 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\DAV\Files\Sharing;
-use OC\Files\View;
+use OCP\Files\Folder;
+use OCP\Files\NotFoundException;
use OCP\Share\IShare;
+use Sabre\DAV\Exception\BadRequest;
use Sabre\DAV\Exception\MethodNotAllowed;
use Sabre\DAV\ServerPlugin;
use Sabre\HTTP\RequestInterface;
@@ -17,14 +20,9 @@ use Sabre\HTTP\ResponseInterface;
*/
class FilesDropPlugin extends ServerPlugin {
- private ?View $view = null;
private ?IShare $share = null;
private bool $enabled = false;
- public function setView(View $view): void {
- $this->view = $view;
- }
-
public function setShare(IShare $share): void {
$this->share = $share;
}
@@ -33,60 +31,169 @@ class FilesDropPlugin extends ServerPlugin {
$this->enabled = true;
}
-
/**
* This initializes the plugin.
- *
- * @param \Sabre\DAV\Server $server Sabre server
- *
- * @return void
- * @throws MethodNotAllowed
+ * It is ONLY initialized by the server on a file drop request.
*/
public function initialize(\Sabre\DAV\Server $server): void {
$server->on('beforeMethod:*', [$this, 'beforeMethod'], 999);
+ $server->on('method:MKCOL', [$this, 'onMkcol']);
$this->enabled = false;
}
- public function beforeMethod(RequestInterface $request, ResponseInterface $response): void {
- if (!$this->enabled || $this->share === null || $this->view === null) {
+ public function onMkcol(RequestInterface $request, ResponseInterface $response) {
+ if (!$this->enabled || $this->share === null) {
+ return;
+ }
+
+ $node = $this->share->getNode();
+ if (!($node instanceof Folder)) {
+ return;
+ }
+
+ // If this is a folder creation request we need
+ // to fake a success so we can pretend every
+ // folder now exists.
+ $response->setStatus(201);
+ return false;
+ }
+
+ public function beforeMethod(RequestInterface $request, ResponseInterface $response) {
+ if (!$this->enabled || $this->share === null) {
return;
}
- // Only allow file drop
+ $node = $this->share->getNode();
+ if (!($node instanceof Folder)) {
+ return;
+ }
+
+ // Retrieve the nickname from the request
+ $nickname = $request->hasHeader('X-NC-Nickname')
+ ? trim(urldecode($request->getHeader('X-NC-Nickname')))
+ : null;
+
if ($request->getMethod() !== 'PUT') {
- throw new MethodNotAllowed('Only PUT is allowed on files drop');
+ // If uploading subfolders we need to ensure they get created
+ // within the nickname folder
+ if ($request->getMethod() === 'MKCOL') {
+ if (!$nickname) {
+ throw new BadRequest('A nickname header is required when uploading subfolders');
+ }
+ } else {
+ throw new MethodNotAllowed('Only PUT is allowed on files drop');
+ }
+ }
+
+ // If this is a folder creation request
+ // let's stop there and let the onMkcol handle it
+ if ($request->getMethod() === 'MKCOL') {
+ return;
}
- // Always upload at the root level
- $path = explode('/', $request->getPath());
- $path = array_pop($path);
+ // Now if we create a file, we need to create the
+ // full path along the way. We'll only handle conflict
+ // resolution on file conflicts, but not on folders.
+
+ // e.g files/dCP8yn3N86EK9sL/Folder/image.jpg
+ $path = $request->getPath();
+ $token = $this->share->getToken();
+
+ // e.g files/dCP8yn3N86EK9sL
+ $rootPath = substr($path, 0, strpos($path, $token) + strlen($token));
+ // e.g /Folder/image.jpg
+ $relativePath = substr($path, strlen($rootPath));
+ $isRootUpload = substr_count($relativePath, '/') === 1;
// Extract the attributes for the file request
$isFileRequest = false;
$attributes = $this->share->getAttributes();
- $nickName = $request->hasHeader('X-NC-Nickname') ? urldecode($request->getHeader('X-NC-Nickname')) : null;
if ($attributes !== null) {
$isFileRequest = $attributes->getAttribute('fileRequest', 'enabled') === true;
}
// We need a valid nickname for file requests
- if ($isFileRequest && ($nickName == null || trim($nickName) === '')) {
- throw new MethodNotAllowed('Nickname is required for file requests');
+ if ($isFileRequest && !$nickname) {
+ throw new BadRequest('A nickname header is required for file requests');
+ }
+
+ // We're only allowing the upload of
+ // long path with subfolders if a nickname is set.
+ // This prevents confusion when uploading files and help
+ // classify them by uploaders.
+ if (!$nickname && !$isRootUpload) {
+ throw new BadRequest('A nickname header is required when uploading subfolders');
+ }
+
+ if ($nickname) {
+ try {
+ $node->verifyPath($nickname);
+ } catch (\Exception $e) {
+ // If the path is not valid, we throw an exception
+ throw new BadRequest('Invalid nickname: ' . $nickname);
+ }
+
+ // Forbid nicknames starting with a dot
+ if (str_starts_with($nickname, '.')) {
+ throw new BadRequest('Invalid nickname: ' . $nickname);
+ }
+
+ // If we have a nickname, let's put
+ // all files in the subfolder
+ $relativePath = '/' . $nickname . '/' . $relativePath;
+ $relativePath = str_replace('//', '/', $relativePath);
}
-
- // If this is a file request we need to create a folder for the user
- if ($isFileRequest) {
- // Check if the folder already exists
- if (!($this->view->file_exists($nickName) === true)) {
- $this->view->mkdir($nickName);
+
+ // Create the folders along the way
+ $folder = $node;
+ $pathSegments = $this->getPathSegments(dirname($relativePath));
+ foreach ($pathSegments as $pathSegment) {
+ if ($pathSegment === '') {
+ continue;
+ }
+
+ try {
+ // get the current folder
+ $currentFolder = $folder->get($pathSegment);
+ // check target is a folder
+ if ($currentFolder instanceof Folder) {
+ $folder = $currentFolder;
+ } else {
+ // otherwise look in the parent folder if we already create an unique folder name
+ foreach ($folder->getDirectoryListing() as $child) {
+ // we look for folders which match "NAME (SUFFIX)"
+ if ($child instanceof Folder && str_starts_with($child->getName(), $pathSegment)) {
+ $suffix = substr($child->getName(), strlen($pathSegment));
+ if (preg_match('/^ \(\d+\)$/', $suffix)) {
+ // we found the unique folder name and can use it
+ $folder = $child;
+ break;
+ }
+ }
+ }
+ // no folder found so we need to create a new unique folder name
+ if (!isset($child) || $child !== $folder) {
+ $folder = $folder->newFolder($folder->getNonExistingName($pathSegment));
+ }
+ }
+ } catch (NotFoundException) {
+ // the folder does simply not exist so we create it
+ $folder = $folder->newFolder($pathSegment);
}
- // Put all files in the subfolder
- $path = $nickName . '/' . $path;
}
-
- $newName = \OC_Helper::buildNotExistingFileNameForView('/', $path, $this->view);
- $url = $request->getBaseUrl() . $newName;
+
+ // Finally handle conflicts on the end files
+ $uniqueName = $folder->getNonExistingName(basename($relativePath));
+ $relativePath = substr($folder->getPath(), strlen($node->getPath()));
+ $path = '/files/' . $token . '/' . $relativePath . '/' . $uniqueName;
+ $url = rtrim($request->getBaseUrl(), '/') . str_replace('//', '/', $path);
$request->setUrl($url);
}
+ private function getPathSegments(string $path): array {
+ // Normalize slashes and remove trailing slash
+ $path = trim(str_replace('\\', '/', $path), '/');
+
+ return explode('/', $path);
+ }
}
diff --git a/apps/dav/lib/Files/Sharing/RootCollection.php b/apps/dav/lib/Files/Sharing/RootCollection.php
new file mode 100644
index 00000000000..dd585fbb59b
--- /dev/null
+++ b/apps/dav/lib/Files/Sharing/RootCollection.php
@@ -0,0 +1,32 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Files\Sharing;
+
+use Sabre\DAV\INode;
+use Sabre\DAVACL\AbstractPrincipalCollection;
+use Sabre\DAVACL\PrincipalBackend\BackendInterface;
+
+class RootCollection extends AbstractPrincipalCollection {
+ public function __construct(
+ private INode $root,
+ BackendInterface $principalBackend,
+ string $principalPrefix = 'principals',
+ ) {
+ parent::__construct($principalBackend, $principalPrefix);
+ }
+
+ public function getChildForPrincipal(array $principalInfo): INode {
+ return $this->root;
+ }
+
+ public function getName() {
+ return 'files';
+ }
+}
diff --git a/apps/dav/lib/Listener/AddMissingIndicesListener.php b/apps/dav/lib/Listener/AddMissingIndicesListener.php
index 035c6c9582e..d3a1cf4b224 100644
--- a/apps/dav/lib/Listener/AddMissingIndicesListener.php
+++ b/apps/dav/lib/Listener/AddMissingIndicesListener.php
@@ -30,6 +30,11 @@ class AddMissingIndicesListener implements IEventListener {
'dav_shares_resourceid_access',
['resourceid', 'access']
);
+ $event->addMissingIndex(
+ 'calendarobjects',
+ 'calobjects_by_uid_index',
+ ['calendarid', 'calendartype', 'uid']
+ );
}
}
diff --git a/apps/dav/lib/Listener/DavAdminSettingsListener.php b/apps/dav/lib/Listener/DavAdminSettingsListener.php
index c59c2df1575..69501915208 100644
--- a/apps/dav/lib/Listener/DavAdminSettingsListener.php
+++ b/apps/dav/lib/Listener/DavAdminSettingsListener.php
@@ -42,11 +42,11 @@ class DavAdminSettingsListener implements IEventListener {
$this->handleSetValue($event);
return;
}
-
+
}
private function handleGetValue(DeclarativeSettingsGetValueEvent $event): void {
-
+
if ($event->getFieldId() === 'system_addressbook_enabled') {
$event->setValue((int)$this->config->getValueBool('dav', 'system_addressbook_exposed', true));
}
diff --git a/apps/dav/lib/Listener/UserEventsListener.php b/apps/dav/lib/Listener/UserEventsListener.php
index 61d945e829b..c876192d67f 100644
--- a/apps/dav/lib/Listener/UserEventsListener.php
+++ b/apps/dav/lib/Listener/UserEventsListener.php
@@ -12,14 +12,14 @@ 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;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\IUser;
use OCP\IUserManager;
-use OCP\Server;
use OCP\User\Events\BeforeUserDeletedEvent;
use OCP\User\Events\BeforeUserIdUnassignedEvent;
use OCP\User\Events\UserChangedEvent;
@@ -46,7 +46,9 @@ 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,
) {
}
@@ -137,17 +139,31 @@ class UserEventsListener implements IEventListener {
public function firstLogin(IUser $user): void {
$principal = 'principals/users/' . $user->getUID();
+
+ $calendarId = null;
if ($this->calDav->getCalendarsForUserCount($principal) === 0) {
try {
- $this->calDav->createCalendar($principal, CalDavBackend::PERSONAL_CALENDAR_URI, [
+ $calendarId = $this->calDav->createCalendar($principal, CalDavBackend::PERSONAL_CALENDAR_URI, [
'{DAV:}displayname' => CalDavBackend::PERSONAL_CALENDAR_NAME,
'{http://apple.com/ns/ical/}calendar-color' => $this->themingDefaults->getColorPrimary(),
'components' => 'VEVENT'
]);
} catch (\Exception $e) {
- Server::get(LoggerInterface::class)->error($e->getMessage(), ['exception' => $e]);
+ $this->logger->error($e->getMessage(), ['exception' => $e]);
}
}
+ if ($calendarId !== null) {
+ try {
+ $this->exampleEventService->createExampleEvent($calendarId);
+ } catch (\Exception $e) {
+ $this->logger->error('Failed to create example event: ' . $e->getMessage(), [
+ 'exception' => $e,
+ 'userId' => $user->getUID(),
+ 'calendarId' => $calendarId,
+ ]);
+ }
+ }
+
$addressBookId = null;
if ($this->cardDav->getAddressBooksForUserCount($principal) === 0) {
try {
@@ -155,11 +171,11 @@ class UserEventsListener implements IEventListener {
'{DAV:}displayname' => CardDavBackend::PERSONAL_ADDRESSBOOK_NAME,
]);
} catch (\Exception $e) {
- Server::get(LoggerInterface::class)->error($e->getMessage(), ['exception' => $e]);
+ $this->logger->error($e->getMessage(), ['exception' => $e]);
}
}
if ($addressBookId) {
- $this->defaultContactService->createDefaultContact($addressBookId);
+ $this->exampleContactService->createDefaultContact($addressBookId);
}
}
}
diff --git a/apps/dav/lib/Migration/BuildCalendarSearchIndex.php b/apps/dav/lib/Migration/BuildCalendarSearchIndex.php
index b157934a1ff..d8f906f22ee 100644
--- a/apps/dav/lib/Migration/BuildCalendarSearchIndex.php
+++ b/apps/dav/lib/Migration/BuildCalendarSearchIndex.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Migration/BuildSocialSearchIndex.php b/apps/dav/lib/Migration/BuildSocialSearchIndex.php
index 5fab3f4ef77..a808034365a 100644
--- a/apps/dav/lib/Migration/BuildSocialSearchIndex.php
+++ b/apps/dav/lib/Migration/BuildSocialSearchIndex.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Migration/CalDAVRemoveEmptyValue.php b/apps/dav/lib/Migration/CalDAVRemoveEmptyValue.php
index ecc462e153b..24e182e46eb 100644
--- a/apps/dav/lib/Migration/CalDAVRemoveEmptyValue.php
+++ b/apps/dav/lib/Migration/CalDAVRemoveEmptyValue.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Migration/RegenerateBirthdayCalendars.php b/apps/dav/lib/Migration/RegenerateBirthdayCalendars.php
index 14037801eb4..ef8e9002e9d 100644
--- a/apps/dav/lib/Migration/RegenerateBirthdayCalendars.php
+++ b/apps/dav/lib/Migration/RegenerateBirthdayCalendars.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Migration/RegisterUpdateCalendarResourcesRoomBackgroundJob.php b/apps/dav/lib/Migration/RegisterUpdateCalendarResourcesRoomBackgroundJob.php
new file mode 100644
index 00000000000..9d77aefafd2
--- /dev/null
+++ b/apps/dav/lib/Migration/RegisterUpdateCalendarResourcesRoomBackgroundJob.php
@@ -0,0 +1,30 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Migration;
+
+use OCA\DAV\BackgroundJob\UpdateCalendarResourcesRoomsBackgroundJob;
+use OCP\BackgroundJob\IJobList;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
+
+class RegisterUpdateCalendarResourcesRoomBackgroundJob implements IRepairStep {
+ public function __construct(
+ private readonly IJobList $jobList,
+ ) {
+ }
+
+ public function getName() {
+ return 'Register a background job to update rooms and resources';
+ }
+
+ public function run(IOutput $output) {
+ $this->jobList->add(UpdateCalendarResourcesRoomsBackgroundJob::class);
+ }
+}
diff --git a/apps/dav/lib/Migration/RemoveObjectProperties.php b/apps/dav/lib/Migration/RemoveObjectProperties.php
index 3f505ecb1e2..f09293ae0bb 100644
--- a/apps/dav/lib/Migration/RemoveObjectProperties.php
+++ b/apps/dav/lib/Migration/RemoveObjectProperties.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-only
diff --git a/apps/dav/lib/Migration/RemoveOrphanEventsAndContacts.php b/apps/dav/lib/Migration/RemoveOrphanEventsAndContacts.php
index ead2645779b..143dc3cd1e6 100644
--- a/apps/dav/lib/Migration/RemoveOrphanEventsAndContacts.php
+++ b/apps/dav/lib/Migration/RemoveOrphanEventsAndContacts.php
@@ -8,82 +8,45 @@ declare(strict_types=1);
*/
namespace OCA\DAV\Migration;
-use OCA\DAV\CalDAV\CalDavBackend;
-use OCP\DB\QueryBuilder\IQueryBuilder;
-use OCP\IDBConnection;
+use OCA\DAV\BackgroundJob\CleanupOrphanedChildrenJob;
+use OCP\BackgroundJob\IJobList;
use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep;
class RemoveOrphanEventsAndContacts implements IRepairStep {
-
public function __construct(
- private IDBConnection $connection,
+ private readonly IJobList $jobList,
) {
}
- /**
- * @inheritdoc
- */
public function getName(): string {
- return 'Clean up orphan event and contact data';
+ return 'Queue jobs to clean up orphan event and contact data';
}
- /**
- * @inheritdoc
- */
- public function run(IOutput $output) {
- $orphanItems = $this->removeOrphanChildren('calendarobjects', 'calendars', 'calendarid');
- $output->info(sprintf('%d events without a calendar have been cleaned up', $orphanItems));
- $orphanItems = $this->removeOrphanChildren('calendarobjects_props', 'calendarobjects', 'objectid');
- $output->info(sprintf('%d properties without an events have been cleaned up', $orphanItems));
- $orphanItems = $this->removeOrphanChildren('calendarchanges', 'calendars', 'calendarid');
- $output->info(sprintf('%d changes without a calendar have been cleaned up', $orphanItems));
+ public function run(IOutput $output): void {
+ $this->queueJob('calendarobjects', 'calendars', 'calendarid', '%d events without a calendar have been cleaned up');
+ $this->queueJob('calendarobjects_props', 'calendarobjects', 'objectid', '%d properties without an events have been cleaned up');
+ $this->queueJob('calendarchanges', 'calendars', 'calendarid', '%d changes without a calendar have been cleaned up');
- $orphanItems = $this->removeOrphanChildren('calendarobjects', 'calendarsubscriptions', 'calendarid');
- $output->info(sprintf('%d cached events without a calendar subscription have been cleaned up', $orphanItems));
- $orphanItems = $this->removeOrphanChildren('calendarchanges', 'calendarsubscriptions', 'calendarid');
- $output->info(sprintf('%d changes without a calendar subscription have been cleaned up', $orphanItems));
+ $this->queueJob('calendarobjects', 'calendarsubscriptions', 'calendarid', '%d cached events without a calendar subscription have been cleaned up');
+ $this->queueJob('calendarchanges', 'calendarsubscriptions', 'calendarid', '%d changes without a calendar subscription have been cleaned up');
- $orphanItems = $this->removeOrphanChildren('cards', 'addressbooks', 'addressbookid');
- $output->info(sprintf('%d contacts without an addressbook have been cleaned up', $orphanItems));
- $orphanItems = $this->removeOrphanChildren('cards_properties', 'cards', 'cardid');
- $output->info(sprintf('%d properties without a contact have been cleaned up', $orphanItems));
- $orphanItems = $this->removeOrphanChildren('addressbookchanges', 'addressbooks', 'addressbookid');
- $output->info(sprintf('%d changes without an addressbook have been cleaned up', $orphanItems));
+ $this->queueJob('cards', 'addressbooks', 'addressbookid', '%d contacts without an addressbook have been cleaned up');
+ $this->queueJob('cards_properties', 'cards', 'cardid', '%d properties without a contact have been cleaned up');
+ $this->queueJob('addressbookchanges', 'addressbooks', 'addressbookid', '%d changes without an addressbook have been cleaned up');
}
- protected function removeOrphanChildren($childTable, $parentTable, $parentId): int {
- $qb = $this->connection->getQueryBuilder();
-
- $qb->select('c.id')
- ->from($childTable, 'c')
- ->leftJoin('c', $parentTable, 'p', $qb->expr()->eq('c.' . $parentId, 'p.id'))
- ->where($qb->expr()->isNull('p.id'));
-
- if (\in_array($parentTable, ['calendars', 'calendarsubscriptions'], true)) {
- $calendarType = $parentTable === 'calendarsubscriptions' ? CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION : CalDavBackend::CALENDAR_TYPE_CALENDAR;
- $qb->andWhere($qb->expr()->eq('c.calendartype', $qb->createNamedParameter($calendarType, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT));
- }
-
- $result = $qb->executeQuery();
-
- $orphanItems = [];
- while ($row = $result->fetch()) {
- $orphanItems[] = (int)$row['id'];
- }
- $result->closeCursor();
-
- if (!empty($orphanItems)) {
- $qb->delete($childTable)
- ->where($qb->expr()->in('id', $qb->createParameter('ids')));
-
- $orphanItemsBatch = array_chunk($orphanItems, 200);
- foreach ($orphanItemsBatch as $items) {
- $qb->setParameter('ids', $items, IQueryBuilder::PARAM_INT_ARRAY);
- $qb->executeStatement();
- }
- }
-
- return count($orphanItems);
+ private function queueJob(
+ string $childTable,
+ string $parentTable,
+ string $parentId,
+ string $logMessage,
+ ): void {
+ $this->jobList->add(CleanupOrphanedChildrenJob::class, [
+ CleanupOrphanedChildrenJob::ARGUMENT_CHILD_TABLE => $childTable,
+ CleanupOrphanedChildrenJob::ARGUMENT_PARENT_TABLE => $parentTable,
+ CleanupOrphanedChildrenJob::ARGUMENT_PARENT_ID => $parentId,
+ CleanupOrphanedChildrenJob::ARGUMENT_LOG_MESSAGE => $logMessage,
+ ]);
}
}
diff --git a/apps/dav/lib/Migration/Version1004Date20170825134824.php b/apps/dav/lib/Migration/Version1004Date20170825134824.php
index 54c4c194778..4bf9637b697 100644
--- a/apps/dav/lib/Migration/Version1004Date20170825134824.php
+++ b/apps/dav/lib/Migration/Version1004Date20170825134824.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Migration/Version1004Date20170919104507.php b/apps/dav/lib/Migration/Version1004Date20170919104507.php
index ca20e2fb4e7..678d92d2b83 100644
--- a/apps/dav/lib/Migration/Version1004Date20170919104507.php
+++ b/apps/dav/lib/Migration/Version1004Date20170919104507.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Migration/Version1004Date20170924124212.php b/apps/dav/lib/Migration/Version1004Date20170924124212.php
index fbfec7e8e2d..4d221e91132 100644
--- a/apps/dav/lib/Migration/Version1004Date20170924124212.php
+++ b/apps/dav/lib/Migration/Version1004Date20170924124212.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Migration/Version1004Date20170926103422.php b/apps/dav/lib/Migration/Version1004Date20170926103422.php
index 38506b0fc5d..ec56e035006 100644
--- a/apps/dav/lib/Migration/Version1004Date20170926103422.php
+++ b/apps/dav/lib/Migration/Version1004Date20170926103422.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Migration/Version1005Date20180530124431.php b/apps/dav/lib/Migration/Version1005Date20180530124431.php
index ac1994893fd..b5f9ff26962 100644
--- a/apps/dav/lib/Migration/Version1005Date20180530124431.php
+++ b/apps/dav/lib/Migration/Version1005Date20180530124431.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Migration/Version1006Date20180619154313.php b/apps/dav/lib/Migration/Version1006Date20180619154313.php
index 195209ed046..231861a68c4 100644
--- a/apps/dav/lib/Migration/Version1006Date20180619154313.php
+++ b/apps/dav/lib/Migration/Version1006Date20180619154313.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Migration/Version1006Date20180628111625.php b/apps/dav/lib/Migration/Version1006Date20180628111625.php
index 5f3aa4b6fe2..f4be26e6ad0 100644
--- a/apps/dav/lib/Migration/Version1006Date20180628111625.php
+++ b/apps/dav/lib/Migration/Version1006Date20180628111625.php
@@ -49,6 +49,7 @@ class Version1006Date20180628111625 extends SimpleMigrationStep {
$calendarObjectsTable->dropIndex('calobjects_index');
}
$calendarObjectsTable->addUniqueIndex(['calendarid', 'calendartype', 'uri'], 'calobjects_index');
+ $calendarObjectsTable->addUniqueIndex(['calendarid', 'calendartype', 'uid'], 'calobjects_by_uid_index');
}
if ($schema->hasTable('calendarobjects_props')) {
diff --git a/apps/dav/lib/Model/ExampleEvent.php b/apps/dav/lib/Model/ExampleEvent.php
new file mode 100644
index 00000000000..d2a5b8ad2d1
--- /dev/null
+++ b/apps/dav/lib/Model/ExampleEvent.php
@@ -0,0 +1,31 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Model;
+
+use Sabre\VObject\Component\VCalendar;
+
+/**
+ * Simple DTO to store a parsed example event and its UID.
+ */
+final class ExampleEvent {
+ public function __construct(
+ private readonly VCalendar $vCalendar,
+ private readonly string $uid,
+ ) {
+ }
+
+ public function getUid(): string {
+ return $this->uid;
+ }
+
+ public function getIcs(): string {
+ return $this->vCalendar->serialize();
+ }
+}
diff --git a/apps/dav/lib/Paginate/PaginatePlugin.php b/apps/dav/lib/Paginate/PaginatePlugin.php
index c02eb9f21eb..c5da18f5c47 100644
--- a/apps/dav/lib/Paginate/PaginatePlugin.php
+++ b/apps/dav/lib/Paginate/PaginatePlugin.php
@@ -49,8 +49,8 @@ class PaginatePlugin extends ServerPlugin {
}
$url = $request->getUrl();
if (
- $request->hasHeader(self::PAGINATE_HEADER) &&
- (!$request->hasHeader(self::PAGINATE_TOKEN_HEADER) || !$this->cache->exists($url, $request->getHeader(self::PAGINATE_TOKEN_HEADER)))
+ $request->hasHeader(self::PAGINATE_HEADER)
+ && (!$request->hasHeader(self::PAGINATE_TOKEN_HEADER) || !$this->cache->exists($url, $request->getHeader(self::PAGINATE_TOKEN_HEADER)))
) {
$pageSize = (int)$request->getHeader(self::PAGINATE_COUNT_HEADER) ?: $this->pageSize;
$offset = (int)$request->getHeader(self::PAGINATE_OFFSET_HEADER);
@@ -68,9 +68,9 @@ class PaginatePlugin extends ServerPlugin {
public function onMethod(RequestInterface $request, ResponseInterface $response) {
$url = $this->server->httpRequest->getUrl();
if (
- $request->hasHeader(self::PAGINATE_TOKEN_HEADER) &&
- $request->hasHeader(self::PAGINATE_OFFSET_HEADER) &&
- $this->cache->exists($url, $request->getHeader(self::PAGINATE_TOKEN_HEADER))
+ $request->hasHeader(self::PAGINATE_TOKEN_HEADER)
+ && $request->hasHeader(self::PAGINATE_OFFSET_HEADER)
+ && $this->cache->exists($url, $request->getHeader(self::PAGINATE_TOKEN_HEADER))
) {
$token = $request->getHeader(self::PAGINATE_TOKEN_HEADER);
$offset = (int)$request->getHeader(self::PAGINATE_OFFSET_HEADER);
diff --git a/apps/dav/lib/Provisioning/Apple/AppleProvisioningNode.php b/apps/dav/lib/Provisioning/Apple/AppleProvisioningNode.php
index 198a09b4bc8..bb098a0f107 100644
--- a/apps/dav/lib/Provisioning/Apple/AppleProvisioningNode.php
+++ b/apps/dav/lib/Provisioning/Apple/AppleProvisioningNode.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -57,7 +58,7 @@ class AppleProvisioningNode implements INode, IProperties {
return [
'{DAV:}getcontentlength' => 42,
- '{DAV:}getlastmodified' => $datetime->format(\DateTimeInterface::RFC2822),
+ '{DAV:}getlastmodified' => $datetime->format(\DateTimeInterface::RFC7231),
];
}
diff --git a/apps/dav/lib/Provisioning/Apple/AppleProvisioningPlugin.php b/apps/dav/lib/Provisioning/Apple/AppleProvisioningPlugin.php
index be5831feee3..258138caa42 100644
--- a/apps/dav/lib/Provisioning/Apple/AppleProvisioningPlugin.php
+++ b/apps/dav/lib/Provisioning/Apple/AppleProvisioningPlugin.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/RootCollection.php b/apps/dav/lib/RootCollection.php
index b2b34b26980..f1963c0ef01 100644
--- a/apps/dav/lib/RootCollection.php
+++ b/apps/dav/lib/RootCollection.php
@@ -160,6 +160,7 @@ class RootCollection extends SimpleCollection {
Server::get(CleanupService::class),
$rootFolder,
$userSession,
+ $shareManager,
);
$uploadCollection->disableListing = $disableListing;
diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php
index 9ea18c029c8..f81c7fa6f29 100644
--- a/apps/dav/lib/Server.php
+++ b/apps/dav/lib/Server.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -63,7 +64,9 @@ use OCA\DAV\Provisioning\Apple\AppleProvisioningPlugin;
use OCA\DAV\SystemTag\SystemTagPlugin;
use OCA\DAV\Upload\ChunkingPlugin;
use OCA\DAV\Upload\ChunkingV2Plugin;
+use OCA\DAV\Upload\UploadAutoMkcolPlugin;
use OCA\Theming\ThemingDefaults;
+use OCP\Accounts\IAccountManager;
use OCP\App\IAppManager;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Utility\ITimeFactory;
@@ -71,7 +74,6 @@ use OCP\Comments\ICommentsManager;
use OCP\Defaults;
use OCP\Diagnostics\IEventLogger;
use OCP\EventDispatcher\IEventDispatcher;
-use OCP\Files\AppData\IAppDataFactory;
use OCP\Files\IFilenameValidator;
use OCP\Files\IRootFolder;
use OCP\FilesMetadata\IFilesMetadataManager;
@@ -215,10 +217,7 @@ class Server {
$this->server->addPlugin(new VCFExportPlugin());
$this->server->addPlugin(new MultiGetExportPlugin());
$this->server->addPlugin(new HasPhotoPlugin());
- $this->server->addPlugin(new ImageExportPlugin(new PhotoCache(
- \OCP\Server::get(IAppDataFactory::class)->get('dav-photocache'),
- $logger)
- ));
+ $this->server->addPlugin(new ImageExportPlugin(\OCP\Server::get(PhotoCache::class)));
$this->server->addPlugin(\OCP\Server::get(CardDavRateLimitingPlugin::class));
$this->server->addPlugin(\OCP\Server::get(CardDavValidatePlugin::class));
@@ -235,6 +234,7 @@ class Server {
$this->server->addPlugin(new CopyEtagHeaderPlugin());
$this->server->addPlugin(new RequestIdHeaderPlugin(\OCP\Server::get(IRequest::class)));
+ $this->server->addPlugin(new UploadAutoMkcolPlugin());
$this->server->addPlugin(new ChunkingV2Plugin(\OCP\Server::get(ICacheFactory::class)));
$this->server->addPlugin(new ChunkingPlugin());
$this->server->addPlugin(new ZipFolderPlugin(
@@ -287,6 +287,7 @@ class Server {
\OCP\Server::get(IPreview::class),
\OCP\Server::get(IUserSession::class),
\OCP\Server::get(IFilenameValidator::class),
+ \OCP\Server::get(IAccountManager::class),
false,
$config->getSystemValueBool('debug', false) === false,
)
@@ -354,6 +355,7 @@ class Server {
\OCP\Server::get(IAppManager::class)
));
$lazySearchBackend->setBackend(new FileSearchBackend(
+ $this->server,
$this->server->tree,
$user,
\OCP\Server::get(IRootFolder::class),
diff --git a/apps/dav/lib/Service/DefaultContactService.php b/apps/dav/lib/Service/DefaultContactService.php
deleted file mode 100644
index ad7a1179195..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', 'no');
- 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/Service/ExampleEventService.php b/apps/dav/lib/Service/ExampleEventService.php
new file mode 100644
index 00000000000..3b2b07fe416
--- /dev/null
+++ b/apps/dav/lib/Service/ExampleEventService.php
@@ -0,0 +1,205 @@
+<?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\CalDAV\CalDavBackend;
+use OCA\DAV\Exception\ExampleEventException;
+use OCA\DAV\Model\ExampleEvent;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Files\IAppData;
+use OCP\Files\NotFoundException;
+use OCP\Files\NotPermittedException;
+use OCP\IAppConfig;
+use OCP\IL10N;
+use OCP\Security\ISecureRandom;
+use Sabre\VObject\Component\VCalendar;
+use Sabre\VObject\Component\VEvent;
+
+class ExampleEventService {
+ private const FOLDER_NAME = 'example_event';
+ private const FILE_NAME = 'example_event.ics';
+ private const ENABLE_CONFIG_KEY = 'create_example_event';
+
+ public function __construct(
+ private readonly CalDavBackend $calDavBackend,
+ private readonly ISecureRandom $random,
+ private readonly ITimeFactory $time,
+ private readonly IAppData $appData,
+ private readonly IAppConfig $appConfig,
+ private readonly IL10N $l10n,
+ ) {
+ }
+
+ public function createExampleEvent(int $calendarId): void {
+ if (!$this->shouldCreateExampleEvent()) {
+ return;
+ }
+
+ $exampleEvent = $this->getExampleEvent();
+ $uid = $exampleEvent->getUid();
+ $this->calDavBackend->createCalendarObject(
+ $calendarId,
+ "$uid.ics",
+ $exampleEvent->getIcs(),
+ );
+ }
+
+ private function getStartDate(): \DateTimeInterface {
+ return $this->time->now()
+ ->add(new \DateInterval('P7D'))
+ ->setTime(10, 00);
+ }
+
+ private function getEndDate(): \DateTimeInterface {
+ return $this->time->now()
+ ->add(new \DateInterval('P7D'))
+ ->setTime(11, 00);
+ }
+
+ private function getDefaultEvent(string $uid): VCalendar {
+ $defaultDescription = $this->l10n->t(<<<EOF
+Welcome to Nextcloud Calendar!
+
+This is a sample event - explore the flexibility of planning with Nextcloud Calendar by making any edits you want!
+
+With Nextcloud Calendar, you can:
+- Create, edit, and manage events effortlessly.
+- Create multiple calendars and share them with teammates, friends, or family.
+- Check availability and display your busy times to others.
+- Seamlessly integrate with apps and devices via CalDAV.
+- Customize your experience: schedule recurring events, adjust notifications and other settings.
+EOF);
+
+ $vCalendar = new VCalendar();
+ $props = [
+ 'UID' => $uid,
+ 'DTSTAMP' => $this->time->now(),
+ 'SUMMARY' => $this->l10n->t('Example event - open me!'),
+ 'DTSTART' => $this->getStartDate(),
+ 'DTEND' => $this->getEndDate(),
+ 'DESCRIPTION' => $defaultDescription,
+ ];
+ $vCalendar->add('VEVENT', $props);
+ return $vCalendar;
+ }
+
+ /**
+ * @return string|null The ics of the custom example event or null if no custom event was uploaded.
+ * @throws ExampleEventException If reading the custom ics file fails.
+ */
+ private function getCustomExampleEvent(): ?string {
+ try {
+ $folder = $this->appData->getFolder(self::FOLDER_NAME);
+ $icsFile = $folder->getFile(self::FILE_NAME);
+ } catch (NotFoundException $e) {
+ return null;
+ }
+
+ try {
+ return $icsFile->getContent();
+ } catch (NotFoundException|NotPermittedException $e) {
+ throw new ExampleEventException(
+ 'Failed to read custom example event',
+ 0,
+ $e,
+ );
+ }
+ }
+
+ /**
+ * Get the configured example event or the default one.
+ *
+ * @throws ExampleEventException If loading the custom example event fails.
+ */
+ public function getExampleEvent(): ExampleEvent {
+ $uid = $this->random->generate(32, ISecureRandom::CHAR_ALPHANUMERIC);
+ $customIcs = $this->getCustomExampleEvent();
+ if ($customIcs === null) {
+ return new ExampleEvent($this->getDefaultEvent($uid), $uid);
+ }
+
+ [$vCalendar, $vEvent] = $this->parseEvent($customIcs);
+ $vEvent->UID = $uid;
+ $vEvent->DTSTART = $this->getStartDate();
+ $vEvent->DTEND = $this->getEndDate();
+ $vEvent->remove('ORGANIZER');
+ $vEvent->remove('ATTENDEE');
+ return new ExampleEvent($vCalendar, $uid);
+ }
+
+ /**
+ * @psalm-return list{VCalendar, VEvent} The VCALENDAR document and its VEVENT child component
+ * @throws ExampleEventException If parsing the event fails or if it is invalid.
+ */
+ private function parseEvent(string $ics): array {
+ try {
+ $vCalendar = \Sabre\VObject\Reader::read($ics);
+ if (!($vCalendar instanceof VCalendar)) {
+ throw new ExampleEventException('Custom event does not contain a VCALENDAR component');
+ }
+
+ /** @var VEvent|null $vEvent */
+ $vEvent = $vCalendar->getBaseComponent('VEVENT');
+ if ($vEvent === null) {
+ throw new ExampleEventException('Custom event does not contain a VEVENT component');
+ }
+ } catch (\Exception $e) {
+ throw new ExampleEventException('Failed to parse custom event: ' . $e->getMessage(), 0, $e);
+ }
+
+ return [$vCalendar, $vEvent];
+ }
+
+ public function saveCustomExampleEvent(string $ics): void {
+ // Parse and validate the event before attempting to save it to prevent run time errors
+ $this->parseEvent($ics);
+
+ try {
+ $folder = $this->appData->getFolder(self::FOLDER_NAME);
+ } catch (NotFoundException $e) {
+ $folder = $this->appData->newFolder(self::FOLDER_NAME);
+ }
+
+ try {
+ $existingFile = $folder->getFile(self::FILE_NAME);
+ $existingFile->putContent($ics);
+ } catch (NotFoundException $e) {
+ $folder->newFile(self::FILE_NAME, $ics);
+ }
+ }
+
+ public function deleteCustomExampleEvent(): void {
+ try {
+ $folder = $this->appData->getFolder(self::FOLDER_NAME);
+ $file = $folder->getFile(self::FILE_NAME);
+ } catch (NotFoundException $e) {
+ return;
+ }
+
+ $file->delete();
+ }
+
+ public function hasCustomExampleEvent(): bool {
+ try {
+ return $this->getCustomExampleEvent() !== null;
+ } catch (ExampleEventException $e) {
+ return false;
+ }
+ }
+
+ public function setCreateExampleEvent(bool $enable): void {
+ $this->appConfig->setValueBool(Application::APP_ID, self::ENABLE_CONFIG_KEY, $enable);
+ }
+
+ public function shouldCreateExampleEvent(): bool {
+ return $this->appConfig->getValueBool(Application::APP_ID, self::ENABLE_CONFIG_KEY, true);
+ }
+}
diff --git a/apps/dav/lib/Settings/CalDAVSettings.php b/apps/dav/lib/Settings/CalDAVSettings.php
index 5b6b7fa7e3d..5e19539a899 100644
--- a/apps/dav/lib/Settings/CalDAVSettings.php
+++ b/apps/dav/lib/Settings/CalDAVSettings.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Settings/ExampleContentSettings.php b/apps/dav/lib/Settings/ExampleContentSettings.php
index f5607b6a31b..7b6f9b03a3a 100644
--- a/apps/dav/lib/Settings/ExampleContentSettings.php
+++ b/apps/dav/lib/Settings/ExampleContentSettings.php
@@ -9,28 +9,56 @@ 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\IConfig;
use OCP\Settings\ISettings;
class ExampleContentSettings implements ISettings {
-
public function __construct(
- private IConfig $config,
- private IInitialState $initialState,
- private IAppManager $appManager,
+ private readonly IAppConfig $appConfig,
+ private readonly IInitialState $initialState,
+ private readonly IAppManager $appManager,
+ private readonly ExampleEventService $exampleEventService,
+ private readonly ExampleContactService $exampleContactService,
) {
}
public function getForm(): TemplateResponse {
- $enableDefaultContact = $this->config->getAppValue(Application::APP_ID, 'enableDefaultContact', 'no');
- $this->initialState->provideInitialState('enableDefaultContact', $enableDefaultContact);
+ $calendarEnabled = $this->appManager->isEnabledForUser('calendar');
+ $contactsEnabled = $this->appManager->isEnabledForUser('contacts');
+ $this->initialState->provideInitialState('calendarEnabled', $calendarEnabled);
+ $this->initialState->provideInitialState('contactsEnabled', $contactsEnabled);
+
+ if ($calendarEnabled) {
+ $enableDefaultEvent = $this->exampleEventService->shouldCreateExampleEvent();
+ $this->initialState->provideInitialState('create_example_event', $enableDefaultEvent);
+ $this->initialState->provideInitialState(
+ 'has_custom_example_event',
+ $this->exampleEventService->hasCustomExampleEvent(),
+ );
+ }
+
+ if ($contactsEnabled) {
+ $this->initialState->provideInitialState(
+ 'enableDefaultContact',
+ $this->exampleContactService->isDefaultContactEnabled(),
+ );
+ $this->initialState->provideInitialState(
+ 'hasCustomDefaultContact',
+ $this->appConfig->getAppValueBool('hasCustomDefaultContact'),
+ );
+ }
+
return new TemplateResponse(Application::APP_ID, 'settings-example-content');
}
+
public function getSection(): ?string {
- if (!$this->appManager->isEnabledForUser('contacts')) {
+ if (!$this->appManager->isEnabledForUser('contacts')
+ && !$this->appManager->isEnabledForUser('calendar')) {
return null;
}
@@ -40,5 +68,4 @@ class ExampleContentSettings implements ISettings {
public function getPriority(): int {
return 10;
}
-
}
diff --git a/apps/dav/lib/SystemTag/SystemTagList.php b/apps/dav/lib/SystemTag/SystemTagList.php
index 546467f562e..b55f10164d7 100644
--- a/apps/dav/lib/SystemTag/SystemTagList.php
+++ b/apps/dav/lib/SystemTag/SystemTagList.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-only
diff --git a/apps/dav/lib/SystemTag/SystemTagNode.php b/apps/dav/lib/SystemTag/SystemTagNode.php
index da51279a9d2..2341d4823ba 100644
--- a/apps/dav/lib/SystemTag/SystemTagNode.php
+++ b/apps/dav/lib/SystemTag/SystemTagNode.php
@@ -122,8 +122,8 @@ class SystemTagNode implements \Sabre\DAV\ICollection {
throw new NotFound('Tag with id ' . $this->tag->getId() . ' does not exist');
} catch (TagAlreadyExistsException $e) {
throw new Conflict(
- 'Tag with the properties "' . $name . '", ' .
- $userVisible . ', ' . $userAssignable . ' already exists'
+ 'Tag with the properties "' . $name . '", '
+ . $userVisible . ', ' . $userAssignable . ' already exists'
);
}
}
@@ -176,15 +176,15 @@ class SystemTagNode implements \Sabre\DAV\ICollection {
public function createFile($name, $data = null) {
throw new MethodNotAllowed();
}
-
+
public function createDirectory($name) {
throw new MethodNotAllowed();
}
-
+
public function getChild($name) {
return new SystemTagObjectType($this->tag, $name, $this->tagManager, $this->tagMapper);
}
-
+
public function childExists($name) {
$objectTypes = $this->tagMapper->getAvailableObjectTypes();
return in_array($name, $objectTypes);
diff --git a/apps/dav/lib/SystemTag/SystemTagObjectType.php b/apps/dav/lib/SystemTag/SystemTagObjectType.php
index 0e1368854cd..0d348cd95f4 100644
--- a/apps/dav/lib/SystemTag/SystemTagObjectType.php
+++ b/apps/dav/lib/SystemTag/SystemTagObjectType.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-only
diff --git a/apps/dav/lib/SystemTag/SystemTagsObjectList.php b/apps/dav/lib/SystemTag/SystemTagsObjectList.php
index 5ccc924eb53..64e8b1bbebb 100644
--- a/apps/dav/lib/SystemTag/SystemTagsObjectList.php
+++ b/apps/dav/lib/SystemTag/SystemTagsObjectList.php
@@ -45,7 +45,7 @@ class SystemTagsObjectList implements XmlSerializable, XmlDeserializable {
if ($tree === null) {
return null;
}
-
+
$objects = [];
foreach ($tree as $elem) {
if ($elem['name'] === self::OBJECTID_ROOT_PROPERTYNAME) {
diff --git a/apps/dav/lib/Traits/PrincipalProxyTrait.php b/apps/dav/lib/Traits/PrincipalProxyTrait.php
index 279f796b720..feec485fe5c 100644
--- a/apps/dav/lib/Traits/PrincipalProxyTrait.php
+++ b/apps/dav/lib/Traits/PrincipalProxyTrait.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/lib/Upload/CleanupService.php b/apps/dav/lib/Upload/CleanupService.php
index 36b75280504..ffa6bad533c 100644
--- a/apps/dav/lib/Upload/CleanupService.php
+++ b/apps/dav/lib/Upload/CleanupService.php
@@ -10,20 +10,18 @@ namespace OCA\DAV\Upload;
use OCA\DAV\BackgroundJob\UploadCleanup;
use OCP\BackgroundJob\IJobList;
-use OCP\IUserSession;
class CleanupService {
public function __construct(
- private IUserSession $userSession,
private IJobList $jobList,
) {
}
- public function addJob(string $folder) {
- $this->jobList->add(UploadCleanup::class, ['uid' => $this->userSession->getUser()->getUID(), 'folder' => $folder]);
+ public function addJob(string $uid, string $folder) {
+ $this->jobList->add(UploadCleanup::class, ['uid' => $uid, 'folder' => $folder]);
}
- public function removeJob(string $folder) {
- $this->jobList->remove(UploadCleanup::class, ['uid' => $this->userSession->getUser()->getUID(), 'folder' => $folder]);
+ public function removeJob(string $uid, string $folder) {
+ $this->jobList->remove(UploadCleanup::class, ['uid' => $uid, 'folder' => $folder]);
}
}
diff --git a/apps/dav/lib/Upload/RootCollection.php b/apps/dav/lib/Upload/RootCollection.php
index 9ea2592702b..cd7ab7f5e0a 100644
--- a/apps/dav/lib/Upload/RootCollection.php
+++ b/apps/dav/lib/Upload/RootCollection.php
@@ -11,6 +11,7 @@ namespace OCA\DAV\Upload;
use OCP\Files\IRootFolder;
use OCP\IUserSession;
+use OCP\Share\IManager;
use Sabre\DAVACL\AbstractPrincipalCollection;
use Sabre\DAVACL\PrincipalBackend;
@@ -22,6 +23,7 @@ class RootCollection extends AbstractPrincipalCollection {
private CleanupService $cleanupService,
private IRootFolder $rootFolder,
private IUserSession $userSession,
+ private IManager $shareManager,
) {
parent::__construct($principalBackend, $principalPrefix);
}
@@ -30,7 +32,13 @@ class RootCollection extends AbstractPrincipalCollection {
* @inheritdoc
*/
public function getChildForPrincipal(array $principalInfo): UploadHome {
- return new UploadHome($principalInfo, $this->cleanupService, $this->rootFolder, $this->userSession);
+ return new UploadHome(
+ $principalInfo,
+ $this->cleanupService,
+ $this->rootFolder,
+ $this->userSession,
+ $this->shareManager,
+ );
}
/**
diff --git a/apps/dav/lib/Upload/UploadAutoMkcolPlugin.php b/apps/dav/lib/Upload/UploadAutoMkcolPlugin.php
new file mode 100644
index 00000000000..a7030ba1133
--- /dev/null
+++ b/apps/dav/lib/Upload/UploadAutoMkcolPlugin.php
@@ -0,0 +1,68 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\DAV\Upload;
+
+use Sabre\DAV\Exception\NotFound;
+use Sabre\DAV\ICollection;
+use Sabre\DAV\Server;
+use Sabre\DAV\ServerPlugin;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+use function Sabre\Uri\split as uriSplit;
+
+/**
+ * Class that allows automatically creating non-existing collections on file
+ * upload.
+ *
+ * Since this functionality is not WebDAV compliant, it needs a special
+ * header to be activated.
+ */
+class UploadAutoMkcolPlugin extends ServerPlugin {
+
+ private Server $server;
+
+ public function initialize(Server $server): void {
+ $server->on('beforeMethod:PUT', [$this, 'beforeMethod']);
+ $this->server = $server;
+ }
+
+ /**
+ * @throws NotFound a node expected to exist cannot be found
+ */
+ public function beforeMethod(RequestInterface $request, ResponseInterface $response): bool {
+ if ($request->getHeader('X-NC-WebDAV-Auto-Mkcol') !== '1') {
+ return true;
+ }
+
+ [$path,] = uriSplit($request->getPath());
+
+ if ($this->server->tree->nodeExists($path)) {
+ return true;
+ }
+
+ $parts = explode('/', trim($path, '/'));
+ $rootPath = array_shift($parts);
+ $node = $this->server->tree->getNodeForPath('/' . $rootPath);
+
+ if (!($node instanceof ICollection)) {
+ // the root node is not a collection, let SabreDAV handle it
+ return true;
+ }
+
+ foreach ($parts as $part) {
+ if (!$node->childExists($part)) {
+ $node->createDirectory($part);
+ }
+
+ $node = $node->getChild($part);
+ }
+
+ return true;
+ }
+}
diff --git a/apps/dav/lib/Upload/UploadFolder.php b/apps/dav/lib/Upload/UploadFolder.php
index 57e95d2b17b..8890d472f87 100644
--- a/apps/dav/lib/Upload/UploadFolder.php
+++ b/apps/dav/lib/Upload/UploadFolder.php
@@ -21,6 +21,7 @@ class UploadFolder implements ICollection {
private Directory $node,
private CleanupService $cleanupService,
private IStorage $storage,
+ private string $uid,
) {
}
@@ -89,7 +90,7 @@ class UploadFolder implements ICollection {
$this->node->delete();
// Background cleanup job is not needed anymore
- $this->cleanupService->removeJob($this->getName());
+ $this->cleanupService->removeJob($this->uid, $this->getName());
}
public function getName() {
diff --git a/apps/dav/lib/Upload/UploadHome.php b/apps/dav/lib/Upload/UploadHome.php
index a6551d4d079..4042f1c4101 100644
--- a/apps/dav/lib/Upload/UploadHome.php
+++ b/apps/dav/lib/Upload/UploadHome.php
@@ -17,6 +17,7 @@ use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\ICollection;
class UploadHome implements ICollection {
+ private string $uid;
private ?Folder $uploadFolder = null;
public function __construct(
@@ -24,7 +25,19 @@ class UploadHome implements ICollection {
private readonly CleanupService $cleanupService,
private readonly IRootFolder $rootFolder,
private readonly IUserSession $userSession,
+ private readonly \OCP\Share\IManager $shareManager,
) {
+ [$prefix, $name] = \Sabre\Uri\split($principalInfo['uri']);
+ if ($prefix === 'principals/shares') {
+ $this->uid = $this->shareManager->getShareByToken($name)->getShareOwner();
+ } else {
+ $user = $this->userSession->getUser();
+ if (!$user) {
+ throw new Forbidden('Not logged in');
+ }
+
+ $this->uid = $user->getUID();
+ }
}
public function createFile($name, $data = null) {
@@ -35,16 +48,26 @@ class UploadHome implements ICollection {
$this->impl()->createDirectory($name);
// Add a cleanup job
- $this->cleanupService->addJob($name);
+ $this->cleanupService->addJob($this->uid, $name);
}
public function getChild($name): UploadFolder {
- return new UploadFolder($this->impl()->getChild($name), $this->cleanupService, $this->getStorage());
+ return new UploadFolder(
+ $this->impl()->getChild($name),
+ $this->cleanupService,
+ $this->getStorage(),
+ $this->uid,
+ );
}
public function getChildren(): array {
return array_map(function ($node) {
- return new UploadFolder($node, $this->cleanupService, $this->getStorage());
+ return new UploadFolder(
+ $node,
+ $this->cleanupService,
+ $this->getStorage(),
+ $this->uid,
+ );
}, $this->impl()->getChildren());
}
@@ -71,11 +94,7 @@ class UploadHome implements ICollection {
private function getUploadFolder(): Folder {
if ($this->uploadFolder === null) {
- $user = $this->userSession->getUser();
- if (!$user) {
- throw new Forbidden('Not logged in');
- }
- $path = '/' . $user->getUID() . '/uploads';
+ $path = '/' . $this->uid . '/uploads';
try {
$folder = $this->rootFolder->get($path);
if (!$folder instanceof Folder) {
diff --git a/apps/dav/openapi.json b/apps/dav/openapi.json
index 449ae09dff1..27904636def 100644
--- a/apps/dav/openapi.json
+++ b/apps/dav/openapi.json
@@ -29,12 +29,16 @@
"dav": {
"type": "object",
"required": [
- "chunking"
+ "chunking",
+ "public_shares_chunking"
],
"properties": {
"chunking": {
"type": "string"
},
+ "public_shares_chunking": {
+ "type": "boolean"
+ },
"bulkupload": {
"type": "string"
},
@@ -395,7 +399,8 @@
"description": "location/URL to filter by",
"schema": {
"type": "string",
- "nullable": true
+ "nullable": true,
+ "default": null
}
},
{
diff --git a/apps/dav/src/views/ExampleContactSettings.vue b/apps/dav/src/components/ExampleContactSettings.vue
index d4d1c7d31d0..cdfdc130189 100644
--- a/apps/dav/src/views/ExampleContactSettings.vue
+++ b/apps/dav/src/components/ExampleContactSettings.vue
@@ -4,35 +4,34 @@
-->
<template>
- <NcSettingsSection id="exmaple-content"
- :name="$t('dav', 'Example Content')"
- class="example-content-setting"
- :description="$t('dav', 'Set example content to be created on new user first login.')">
- <div class="example-content-setting__contacts">
- <input id="enable-default-contact"
- v-model="enableDefaultContact"
- type="checkbox"
- class="checkbox"
- @change="updateEnableDefaultContact">
- <label for="enable-default-contact"> {{ $t('dav',"Default contact is added to the user's own address book on user's first login.") }} </label>
- <div v-if="enableDefaultContact" class="example-content-setting__contacts__buttons">
- <NcButton type="primary"
- class="example-content-setting__contacts__buttons__button"
- @click="toggleModal">
- <template #icon>
- <IconUpload :size="20" />
- </template>
- {{ $t('dav', 'Import contact') }}
- </NcButton>
- <NcButton type="secondary"
- class="example-content-setting__contacts__buttons__button"
- @click="resetContact">
- <template #icon>
- <IconRestore :size="20" />
- </template>
- {{ $t('dav', 'Reset to default contact') }}
- </NcButton>
- </div>
+ <div class="example-contact-settings">
+ <NcCheckboxRadioSwitch :checked="enableDefaultContact"
+ type="switch"
+ @update:model-value="updateEnableDefaultContact">
+ {{ $t('dav', "Add example contact to user's address book when they first log in") }}
+ </NcCheckboxRadioSwitch>
+ <div v-if="enableDefaultContact" class="example-contact-settings__buttons">
+ <ExampleContentDownloadButton :href="downloadUrl">
+ <template #icon>
+ <IconAccount :size="20" />
+ </template>
+ example_contact.vcf
+ </ExampleContentDownloadButton>
+ <NcButton type="secondary"
+ @click="toggleModal">
+ <template #icon>
+ <IconUpload :size="20" />
+ </template>
+ {{ $t('dav', 'Import contact') }}
+ </NcButton>
+ <NcButton v-if="hasCustomDefaultContact"
+ type="tertiary"
+ @click="resetContact">
+ <template #icon>
+ <IconRestore :size="20" />
+ </template>
+ {{ $t('dav', 'Reset to default') }}
+ </NcButton>
</div>
<NcDialog :open.sync="isModalOpen"
:name="$t('dav', 'Import contacts')"
@@ -48,33 +47,40 @@
accept=".vcf"
class="hidden-visually"
@change="processFile">
- </NcSettingsSection>
+ </div>
</template>
<script>
import axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'
import { loadState } from '@nextcloud/initial-state'
-import { NcDialog, NcButton, NcSettingsSection } from '@nextcloud/vue'
+import { NcDialog, NcButton, NcCheckboxRadioSwitch } from '@nextcloud/vue'
import { showError, showSuccess } from '@nextcloud/dialogs'
import IconUpload from 'vue-material-design-icons/Upload.vue'
import IconRestore from 'vue-material-design-icons/Restore.vue'
+import IconAccount from 'vue-material-design-icons/Account.vue'
import IconCancel from '@mdi/svg/svg/cancel.svg?raw'
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 {
name: 'ExampleContactSettings',
components: {
NcDialog,
NcButton,
- NcSettingsSection,
+ NcCheckboxRadioSwitch,
IconUpload,
IconRestore,
+ IconAccount,
+ ExampleContentDownloadButton,
},
data() {
return {
enableDefaultContact,
+ hasCustomDefaultContact,
isModalOpen: false,
loading: false,
buttons: [
@@ -92,12 +98,18 @@ export default {
],
}
},
+ computed: {
+ downloadUrl() {
+ return generateUrl('/apps/dav/api/defaultcontact/contact')
+ },
+ },
methods: {
updateEnableDefaultContact() {
axios.put(generateUrl('apps/dav/api/defaultcontact/config'), {
- allow: this.enableDefaultContact ? 'yes' : 'no',
- }).catch(() => {
+ allow: !this.enableDefaultContact,
+ }).then(() => {
this.enableDefaultContact = !this.enableDefaultContact
+ }).catch(() => {
showError(this.$t('dav', 'Error while saving settings'))
})
},
@@ -111,10 +123,11 @@ export default {
this.loading = true
axios.put(generateUrl('/apps/dav/api/defaultcontact/contact'))
.then(() => {
+ this.hasCustomDefaultContact = false
showSuccess(this.$t('dav', 'Contact reset successfully'))
})
.catch((error) => {
- console.error('Error importing contact:', error)
+ logger.error('Error importing contact:', { error })
showError(this.$t('dav', 'Error while resetting contact'))
})
.finally(() => {
@@ -131,9 +144,10 @@ export default {
this.isModalOpen = false
try {
await axios.put(generateUrl('/apps/dav/api/defaultcontact/contact'), { contactData: reader.result })
+ this.hasCustomDefaultContact = true
showSuccess(this.$t('dav', 'Contact imported successfully'))
} catch (error) {
- console.error('Error importing contact:', error)
+ logger.error('Error importing contact:', { error })
showError(this.$t('dav', 'Error while importing contact'))
} finally {
this.loading = false
@@ -146,15 +160,13 @@ export default {
}
</script>
<style lang="scss" scoped>
-.example-content-setting{
- &__contacts{
- &__buttons{
- margin-top: 1rem;
- display: flex;
- &__button{
- margin-inline-end: 5px;
- }
- }
+.example-contact-settings {
+ margin-block-start: 2rem;
+
+ &__buttons {
+ display: flex;
+ gap: calc(var(--default-grid-baseline) * 2);
+ margin-top: calc(var(--default-grid-baseline) * 2);
}
}
</style>
diff --git a/apps/dav/src/components/ExampleContentDownloadButton.vue b/apps/dav/src/components/ExampleContentDownloadButton.vue
new file mode 100644
index 00000000000..d3ee793eddc
--- /dev/null
+++ b/apps/dav/src/components/ExampleContentDownloadButton.vue
@@ -0,0 +1,57 @@
+<!--
+ - SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+ -->
+
+<template>
+ <NcButton type="tertiary" :href="href">
+ <template #icon>
+ <slot name="icon" />
+ </template>
+ <div class="download-button">
+ <span class="download-button__label">
+ <slot name="default" />
+ </span>
+ <IconDownload class="download-button__icon"
+ :size="20" />
+ </div>
+ </NcButton>
+</template>
+
+<script>
+import { NcButton } from '@nextcloud/vue'
+import IconDownload from 'vue-material-design-icons/Download.vue'
+
+export default {
+ name: 'ExampleContentDownloadButton',
+ components: {
+ NcButton,
+ IconDownload
+ },
+ props: {
+ href: {
+ type: String,
+ required: true,
+ }
+ },
+}
+</script>
+
+<style lang="scss" scoped>
+.download-button {
+ display: flex;
+ max-width: 200px;
+
+ &__label {
+ font-weight: initial;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ }
+
+ &__icon {
+ margin-top: 2px;
+ margin-inline-start: var(--default-grid-baseline);
+ }
+}
+</style>
diff --git a/apps/dav/src/components/ExampleEventSettings.vue b/apps/dav/src/components/ExampleEventSettings.vue
new file mode 100644
index 00000000000..c7a90b71a4a
--- /dev/null
+++ b/apps/dav/src/components/ExampleEventSettings.vue
@@ -0,0 +1,217 @@
+<!--
+ - SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+ -->
+
+<template>
+ <div class="example-event-settings">
+ <NcCheckboxRadioSwitch :checked="createExampleEvent"
+ :disabled="savingConfig"
+ type="switch"
+ @update:model-value="updateCreateExampleEvent">
+ {{ t('dav', "Add example event to user's calendar when they first log in") }}
+ </NcCheckboxRadioSwitch>
+ <div v-if="createExampleEvent"
+ class="example-event-settings__buttons">
+ <ExampleContentDownloadButton :href="downloadUrl">
+ <template #icon>
+ <IconCalendarBlank :size="20" />
+ </template>
+ example_event.ics
+ </ExampleContentDownloadButton>
+ <NcButton type="secondary"
+ @click="showImportModal = true">
+ <template #icon>
+ <IconUpload :size="20" />
+ </template>
+ {{ t('dav', 'Import calendar event') }}
+ </NcButton>
+ <NcButton v-if="hasCustomEvent"
+ type="tertiary"
+ :disabled="deleting"
+ @click="deleteCustomEvent">
+ <template #icon>
+ <IconRestore :size="20" />
+ </template>
+ {{ t('dav', 'Reset to default') }}
+ </NcButton>
+ </div>
+ <NcDialog :open.sync="showImportModal"
+ :name="t('dav', 'Import calendar event')">
+ <div class="import-event-modal">
+ <p>
+ {{ t('dav', 'Uploading a new event will overwrite the existing one.') }}
+ </p>
+ <input ref="event-file"
+ :disabled="uploading"
+ type="file"
+ accept=".ics,text/calendar"
+ class="import-event-modal__file-picker"
+ @change="selectFile" />
+ <div class="import-event-modal__buttons">
+ <NcButton :disabled="uploading || !selectedFile"
+ type="primary"
+ @click="uploadCustomEvent()">
+ <template #icon>
+ <IconUpload :size="20" />
+ </template>
+ {{ t('dav', 'Upload event') }}
+ </NcButton>
+ </div>
+ </div>
+ </NcDialog>
+ </div>
+</template>
+
+<script>
+import { NcButton, NcCheckboxRadioSwitch, NcDialog } from '@nextcloud/vue'
+import { loadState } from '@nextcloud/initial-state'
+import IconCalendarBlank from 'vue-material-design-icons/CalendarBlank.vue'
+import IconUpload from 'vue-material-design-icons/Upload.vue'
+import IconRestore from 'vue-material-design-icons/Restore.vue'
+import * as ExampleEventService from '../service/ExampleEventService.js'
+import { showError, showSuccess } from '@nextcloud/dialogs'
+import logger from '../service/logger.js'
+import { generateUrl } from '@nextcloud/router'
+import ExampleContentDownloadButton from './ExampleContentDownloadButton.vue'
+
+export default {
+ name: 'ExampleEventSettings',
+ components: {
+ NcButton,
+ NcCheckboxRadioSwitch,
+ NcDialog,
+ IconCalendarBlank,
+ IconUpload,
+ IconRestore,
+ ExampleContentDownloadButton,
+ },
+ data() {
+ return {
+ createExampleEvent: loadState('dav', 'create_example_event', false),
+ hasCustomEvent: loadState('dav', 'has_custom_example_event', false),
+ showImportModal: false,
+ uploading: false,
+ deleting: false,
+ savingConfig: false,
+ selectedFile: undefined,
+ }
+ },
+ computed: {
+ downloadUrl() {
+ return generateUrl('/apps/dav/api/exampleEvent/event')
+ },
+ },
+ methods: {
+ selectFile() {
+ this.selectedFile = this.$refs['event-file']?.files[0]
+ },
+ async updateCreateExampleEvent() {
+ this.savingConfig = true
+
+ const enable = !this.createExampleEvent
+ try {
+ await ExampleEventService.setCreateExampleEvent(enable)
+ } catch (error) {
+ showError(t('dav', 'Failed to save example event creation setting'))
+ logger.error('Failed to save example event creation setting', {
+ error,
+ enable,
+ })
+ } finally {
+ this.savingConfig = false
+ }
+
+ this.createExampleEvent = enable
+ },
+ uploadCustomEvent() {
+ if (!this.selectedFile) {
+ return
+ }
+
+ this.uploading = true
+
+ const reader = new FileReader()
+ reader.addEventListener('load', async () => {
+ const ics = reader.result
+
+ try {
+ await ExampleEventService.uploadExampleEvent(ics)
+ } catch (error) {
+ showError(t('dav', 'Failed to upload the example event'))
+ logger.error('Failed to upload example ICS', {
+ error,
+ ics,
+ })
+ return
+ } finally {
+ this.uploading = false
+ }
+
+ showSuccess(t('dav', 'Custom example event was saved successfully'))
+ this.showImportModal = false
+ this.hasCustomEvent = true
+ })
+ reader.readAsText(this.selectedFile)
+ },
+ async deleteCustomEvent() {
+ this.deleting = true
+
+ try {
+ await ExampleEventService.deleteExampleEvent()
+ } catch (error) {
+ showError(t('dav', 'Failed to delete the custom example event'))
+ logger.error('Failed to delete the custom example event', {
+ error,
+ })
+ return
+ } finally {
+ this.deleting = false
+ }
+
+ showSuccess(t('dav', 'Custom example event was deleted successfully'))
+ this.hasCustomEvent = false
+ },
+ },
+}
+</script>
+
+<style lang="scss" scoped>
+.example-event-settings {
+ margin-block: 2rem;
+
+ &__buttons {
+ display: flex;
+ gap: calc(var(--default-grid-baseline) * 2);
+ margin-top: calc(var(--default-grid-baseline) * 2);
+
+ &__download-link {
+ display: flex;
+ max-width: 100px;
+
+ &__label {
+ text-decoration: underline;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ }
+ }
+ }
+}
+
+.import-event-modal {
+ display: flex;
+ flex-direction: column;
+ gap: calc(var(--default-grid-baseline) * 2);
+ padding: calc(var(--default-grid-baseline) * 2);
+
+ &__file-picker {
+ width: 100%;
+ }
+
+ &__buttons {
+ display: flex;
+ justify-content: flex-end;
+ }
+}
+</style>
diff --git a/apps/dav/src/service/ExampleEventService.js b/apps/dav/src/service/ExampleEventService.js
new file mode 100644
index 00000000000..a39e3641bd9
--- /dev/null
+++ b/apps/dav/src/service/ExampleEventService.js
@@ -0,0 +1,43 @@
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import { generateUrl } from '@nextcloud/router'
+import axios from '@nextcloud/axios'
+
+/**
+ * Configure the creation of example events on a user's first login.
+ *
+ * @param {boolean} enable Whether to enable or disable the feature.
+ * @return {Promise<void>}
+ */
+export async function setCreateExampleEvent(enable) {
+ const url = generateUrl('/apps/dav/api/exampleEvent/enable')
+ await axios.post(url, {
+ enable,
+ })
+}
+
+/**
+ * Upload a custom example event.
+ *
+ * @param {string} ics The ICS data of the event.
+ * @return {Promise<void>}
+ */
+export async function uploadExampleEvent(ics) {
+ const url = generateUrl('/apps/dav/api/exampleEvent/event')
+ await axios.post(url, {
+ ics,
+ })
+}
+
+/**
+ * Delete a previously uploaded custom example event.
+ *
+ * @return {Promise<void>}
+ */
+export async function deleteExampleEvent() {
+ const url = generateUrl('/apps/dav/api/exampleEvent/event')
+ await axios.delete(url)
+}
diff --git a/apps/dav/src/settings-example-content.js b/apps/dav/src/settings-example-content.js
index f1374027bf3..ca0291ace4f 100644
--- a/apps/dav/src/settings-example-content.js
+++ b/apps/dav/src/settings-example-content.js
@@ -4,10 +4,15 @@
*/
import Vue from 'vue'
import { translate } from '@nextcloud/l10n'
-import ExampleContactSettings from './views/ExampleContactSettings.vue'
+import ExampleContentSettingsSection from './views/ExampleContentSettingsSection.vue'
-Vue.prototype.$t = translate
+Vue.mixin({
+ methods: {
+ t: translate,
+ $t: translate,
+ }
+})
-const View = Vue.extend(ExampleContactSettings);
+const View = Vue.extend(ExampleContentSettingsSection);
(new View({})).$mount('#settings-example-content')
diff --git a/apps/dav/src/views/ExampleContentSettingsSection.vue b/apps/dav/src/views/ExampleContentSettingsSection.vue
new file mode 100644
index 00000000000..5e65a1ba3b4
--- /dev/null
+++ b/apps/dav/src/views/ExampleContentSettingsSection.vue
@@ -0,0 +1,38 @@
+<!--
+ - SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+-->
+
+<template>
+ <NcSettingsSection id="example-content"
+ :name="$t('dav', 'Example content')"
+ class="example-content-setting"
+ :description="$t('dav', 'Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content.')">
+ <ExampleContactSettings v-if="hasContactsApp" />
+ <ExampleEventSettings v-if="hasCalendarApp" />
+ </NcSettingsSection>
+</template>
+
+<script>
+import { loadState } from '@nextcloud/initial-state'
+import { NcSettingsSection } from '@nextcloud/vue'
+import ExampleEventSettings from '../components/ExampleEventSettings.vue'
+import ExampleContactSettings from '../components/ExampleContactSettings.vue'
+
+export default {
+ name: 'ExampleContentSettingsSection',
+ components: {
+ NcSettingsSection,
+ ExampleContactSettings,
+ ExampleEventSettings,
+ },
+ computed: {
+ hasContactsApp() {
+ return loadState('dav', 'contactsEnabled')
+ },
+ hasCalendarApp() {
+ return loadState('dav', 'calendarEnabled')
+ },
+ }
+}
+</script>
diff --git a/apps/dav/templates/settings-example-content.php b/apps/dav/templates/settings-example-content.php
index b2b051d745d..7c6f15bd82b 100644
--- a/apps/dav/templates/settings-example-content.php
+++ b/apps/dav/templates/settings-example-content.php
@@ -4,7 +4,7 @@
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-script('dav', 'settings-example-content');
+\OCP\Util::addScript('dav', 'settings-example-content', 'core');
?>
diff --git a/apps/dav/tests/integration/DAV/Sharing/CalDavSharingBackendTest.php b/apps/dav/tests/integration/DAV/Sharing/CalDavSharingBackendTest.php
new file mode 100644
index 00000000000..be06e8e4d4b
--- /dev/null
+++ b/apps/dav/tests/integration/DAV/Sharing/CalDavSharingBackendTest.php
@@ -0,0 +1,251 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Tests\integration\DAV\Sharing;
+
+use OC\Memcache\NullCache;
+use OCA\DAV\CalDAV\Calendar;
+use OCA\DAV\CalDAV\Sharing\Service;
+use OCA\DAV\Connector\Sabre\Principal;
+use OCA\DAV\DAV\Sharing\Backend;
+use OCA\DAV\DAV\Sharing\SharingMapper;
+use OCA\DAV\DAV\Sharing\SharingService;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\ICacheFactory;
+use OCP\IDBConnection;
+use OCP\IGroupManager;
+use OCP\IUserManager;
+use OCP\Server;
+use Psr\Log\LoggerInterface;
+use Test\TestCase;
+
+/**
+ * @group DB
+ */
+class CalDavSharingBackendTest extends TestCase {
+
+ private IDBConnection $db;
+ private IUserManager $userManager;
+ private IGroupManager $groupManager;
+ private Principal $principalBackend;
+ private ICacheFactory $cacheFactory;
+ private LoggerInterface $logger;
+ private SharingMapper $sharingMapper;
+ private SharingService $sharingService;
+ private Backend $sharingBackend;
+
+ private $resourceIds = [10001];
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->db = Server::get(IDBConnection::class);
+
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->groupManager = $this->createMock(IGroupManager::class);
+ $this->principalBackend = $this->createMock(Principal::class);
+ $this->cacheFactory = $this->createMock(ICacheFactory::class);
+ $this->cacheFactory->method('createInMemory')
+ ->willReturn(new NullCache());
+ $this->logger = new \Psr\Log\NullLogger();
+
+ $this->sharingMapper = new SharingMapper($this->db);
+ $this->sharingService = new Service($this->sharingMapper);
+
+ $this->sharingBackend = new \OCA\DAV\CalDAV\Sharing\Backend(
+ $this->userManager,
+ $this->groupManager,
+ $this->principalBackend,
+ $this->cacheFactory,
+ $this->sharingService,
+ $this->logger
+ );
+
+ $this->removeFixtures();
+ }
+
+ protected function tearDown(): void {
+ $this->removeFixtures();
+ }
+
+ protected function removeFixtures(): void {
+ $qb = $this->db->getQueryBuilder();
+ $qb->delete('dav_shares')
+ ->where($qb->expr()->in('resourceid', $qb->createNamedParameter($this->resourceIds, IQueryBuilder::PARAM_INT_ARRAY)));
+ $qb->executeStatement();
+ }
+
+ public function testShareCalendarWithGroup(): void {
+ $calendar = $this->createMock(Calendar::class);
+ $calendar->method('getResourceId')
+ ->willReturn(10001);
+ $calendar->method('getOwner')
+ ->willReturn('principals/users/admin');
+
+ $this->principalBackend->method('findByUri')
+ ->willReturn('principals/groups/alice_bob');
+
+ $this->groupManager->method('groupExists')
+ ->willReturn(true);
+
+ $this->sharingBackend->updateShares(
+ $calendar,
+ [['href' => 'principals/groups/alice_bob']],
+ [],
+ []
+ );
+
+ $this->assertCount(1, $this->sharingService->getShares(10001));
+ }
+
+ public function testUnshareCalendarFromGroup(): void {
+ $calendar = $this->createMock(Calendar::class);
+ $calendar->method('getResourceId')
+ ->willReturn(10001);
+ $calendar->method('getOwner')
+ ->willReturn('principals/users/admin');
+
+ $this->principalBackend->method('findByUri')
+ ->willReturn('principals/groups/alice_bob');
+
+ $this->groupManager->method('groupExists')
+ ->willReturn(true);
+
+ $this->sharingBackend->updateShares(
+ shareable: $calendar,
+ add: [['href' => 'principals/groups/alice_bob']],
+ remove: [],
+ );
+
+ $this->assertCount(1, $this->sharingService->getShares(10001));
+
+ $this->sharingBackend->updateShares(
+ shareable: $calendar,
+ add: [],
+ remove: ['principals/groups/alice_bob'],
+ );
+
+ $this->assertCount(0, $this->sharingService->getShares(10001));
+ }
+
+ public function testShareCalendarWithGroupAndUnshareAsUser(): void {
+ $calendar = $this->createMock(Calendar::class);
+ $calendar->method('getResourceId')
+ ->willReturn(10001);
+ $calendar->method('getOwner')
+ ->willReturn('principals/users/admin');
+
+ $this->principalBackend->method('findByUri')
+ ->willReturnMap([
+ ['principals/groups/alice_bob', '', 'principals/groups/alice_bob'],
+ ['principals/users/bob', '', 'principals/users/bob'],
+ ]);
+ $this->principalBackend->method('getGroupMembership')
+ ->willReturn([
+ 'principals/groups/alice_bob',
+ ]);
+ $this->principalBackend->method('getCircleMembership')
+ ->willReturn([]);
+
+ $this->groupManager->method('groupExists')
+ ->willReturn(true);
+
+ /*
+ * Owner is sharing the calendar with a group.
+ */
+ $this->sharingBackend->updateShares(
+ shareable: $calendar,
+ add: [['href' => 'principals/groups/alice_bob']],
+ remove: [],
+ );
+
+ $this->assertCount(1, $this->sharingService->getShares(10001));
+
+ /*
+ * Member of the group unshares the calendar.
+ */
+ $this->sharingBackend->unshare(
+ shareable: $calendar,
+ principalUri: 'principals/users/bob'
+ );
+
+ $this->assertCount(1, $this->sharingService->getShares(10001));
+ $this->assertCount(1, $this->sharingService->getUnshares(10001));
+ }
+
+ /**
+ * Tests the functionality of sharing a calendar with a user, then with a group (that includes the shared user),
+ * and subsequently unsharing it from the individual user. Verifies that the unshare operation correctly removes the specific user share
+ * without creating an additional unshare entry.
+ */
+ public function testShareCalendarWithUserThenGroupThenUnshareUser(): void {
+ $calendar = $this->createMock(Calendar::class);
+ $calendar->method('getResourceId')
+ ->willReturn(10001);
+ $calendar->method('getOwner')
+ ->willReturn('principals/users/admin');
+
+ $this->principalBackend->method('findByUri')
+ ->willReturnMap([
+ ['principals/groups/alice_bob', '', 'principals/groups/alice_bob'],
+ ['principals/users/bob', '', 'principals/users/bob'],
+ ]);
+ $this->principalBackend->method('getGroupMembership')
+ ->willReturn([
+ 'principals/groups/alice_bob',
+ ]);
+ $this->principalBackend->method('getCircleMembership')
+ ->willReturn([]);
+
+ $this->userManager->method('userExists')
+ ->willReturn(true);
+ $this->groupManager->method('groupExists')
+ ->willReturn(true);
+
+ /*
+ * Step 1) The owner shares the calendar with a user.
+ */
+ $this->sharingBackend->updateShares(
+ shareable: $calendar,
+ add: [['href' => 'principals/users/bob']],
+ remove: [],
+ );
+
+ $this->assertCount(1, $this->sharingService->getShares(10001));
+
+ /*
+ * Step 2) The owner shares the calendar with a group that includes the
+ * user from step 1 as a member.
+ */
+ $this->sharingBackend->updateShares(
+ shareable: $calendar,
+ add: [['href' => 'principals/groups/alice_bob']],
+ remove: [],
+ );
+
+ $this->assertCount(2, $this->sharingService->getShares(10001));
+
+ /*
+ * Step 3) Unshare the calendar from user as owner.
+ */
+ $this->sharingBackend->updateShares(
+ shareable: $calendar,
+ add: [],
+ remove: ['principals/users/bob'],
+ );
+
+ /*
+ * The purpose of this test is to ensure that removing a user from a share, as the owner, does not result in an "unshare" row being added.
+ * Instead, the actual user share should be removed.
+ */
+ $this->assertCount(1, $this->sharingService->getShares(10001));
+ $this->assertCount(0, $this->sharingService->getUnshares(10001));
+ }
+
+}
diff --git a/apps/dav/tests/integration/DAV/Sharing/SharingMapperTest.php b/apps/dav/tests/integration/DAV/Sharing/SharingMapperTest.php
index bde6b1060c8..bcf84254034 100644
--- a/apps/dav/tests/integration/DAV/Sharing/SharingMapperTest.php
+++ b/apps/dav/tests/integration/DAV/Sharing/SharingMapperTest.php
@@ -7,6 +7,8 @@ declare(strict_types=1);
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
+namespace OCA\DAV\Tests\integration\DAV\Sharing;
+
use OCA\DAV\DAV\Sharing\SharingMapper;
use OCP\IDBConnection;
use OCP\Server;
diff --git a/apps/dav/tests/unit/AppInfo/ApplicationTest.php b/apps/dav/tests/unit/AppInfo/ApplicationTest.php
index f8ddd9bb821..336f487e0b8 100644
--- a/apps/dav/tests/unit/AppInfo/ApplicationTest.php
+++ b/apps/dav/tests/unit/AppInfo/ApplicationTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
diff --git a/apps/dav/tests/unit/AppInfo/PluginManagerTest.php b/apps/dav/tests/unit/AppInfo/PluginManagerTest.php
index 7a60888a838..0082aa45286 100644
--- a/apps/dav/tests/unit/AppInfo/PluginManagerTest.php
+++ b/apps/dav/tests/unit/AppInfo/PluginManagerTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 ownCloud GmbH.
* SPDX-License-Identifier: AGPL-3.0-only
diff --git a/apps/dav/tests/unit/Avatars/AvatarHomeTest.php b/apps/dav/tests/unit/Avatars/AvatarHomeTest.php
index 9699c146c8a..aaa930b6c19 100644
--- a/apps/dav/tests/unit/Avatars/AvatarHomeTest.php
+++ b/apps/dav/tests/unit/Avatars/AvatarHomeTest.php
@@ -1,27 +1,25 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2017 ownCloud GmbH
* SPDX-License-Identifier: AGPL-3.0-only
*/
-namespace OCA\DAV\Tests\Unit\Avatars;
+namespace OCA\DAV\Tests\unit\Avatars;
use OCA\DAV\Avatars\AvatarHome;
use OCA\DAV\Avatars\AvatarNode;
use OCP\IAvatar;
use OCP\IAvatarManager;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Exception\MethodNotAllowed;
use Sabre\DAV\Exception\NotFound;
use Test\TestCase;
class AvatarHomeTest extends TestCase {
-
- /** @var AvatarHome */
- private $home;
-
- /** @var IAvatarManager | \PHPUnit\Framework\MockObject\MockObject */
- private $avatarManager;
+ private AvatarHome $home;
+ private IAvatarManager&MockObject $avatarManager;
protected function setUp(): void {
parent::setUp();
@@ -38,7 +36,7 @@ class AvatarHomeTest extends TestCase {
$this->home->$method('');
}
- public function providesForbiddenMethods() {
+ public static function providesForbiddenMethods(): array {
return [
['createFile'],
['createDirectory'],
@@ -52,7 +50,7 @@ class AvatarHomeTest extends TestCase {
self::assertEquals('admin', $n);
}
- public function providesTestGetChild() {
+ public static function providesTestGetChild(): array {
return [
[MethodNotAllowed::class, false, ''],
[MethodNotAllowed::class, false, 'bla.foo'],
@@ -65,7 +63,7 @@ class AvatarHomeTest extends TestCase {
/**
* @dataProvider providesTestGetChild
*/
- public function testGetChild($expectedException, $hasAvatar, $path): void {
+ public function testGetChild(?string $expectedException, bool $hasAvatar, string $path): void {
if ($expectedException !== null) {
$this->expectException($expectedException);
}
@@ -92,7 +90,7 @@ class AvatarHomeTest extends TestCase {
/**
* @dataProvider providesTestGetChild
*/
- public function testChildExists($expectedException, $hasAvatar, $path): void {
+ public function testChildExists(?string $expectedException, bool $hasAvatar, string $path): void {
$avatar = $this->createMock(IAvatar::class);
$avatar->method('exists')->willReturn($hasAvatar);
diff --git a/apps/dav/tests/unit/Avatars/AvatarNodeTest.php b/apps/dav/tests/unit/Avatars/AvatarNodeTest.php
index 92c02e17ff8..0ca147a1f3b 100644
--- a/apps/dav/tests/unit/Avatars/AvatarNodeTest.php
+++ b/apps/dav/tests/unit/Avatars/AvatarNodeTest.php
@@ -1,26 +1,28 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2017 ownCloud GmbH
* SPDX-License-Identifier: AGPL-3.0-only
*/
-namespace OCA\DAV\Tests\Unit\Avatars;
+namespace OCA\DAV\Tests\unit\Avatars;
use OCA\DAV\Avatars\AvatarNode;
use OCP\IAvatar;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class AvatarNodeTest extends TestCase {
public function testGetName(): void {
- /** @var IAvatar | \PHPUnit\Framework\MockObject\MockObject $a */
+ /** @var IAvatar&MockObject $a */
$a = $this->createMock(IAvatar::class);
$n = new AvatarNode(1024, 'png', $a);
$this->assertEquals('1024.png', $n->getName());
}
public function testGetContentType(): void {
- /** @var IAvatar | \PHPUnit\Framework\MockObject\MockObject $a */
+ /** @var IAvatar&MockObject $a */
$a = $this->createMock(IAvatar::class);
$n = new AvatarNode(1024, 'png', $a);
$this->assertEquals('image/png', $n->getContentType());
diff --git a/apps/dav/tests/unit/BackgroundJob/CleanupInvitationTokenJobTest.php b/apps/dav/tests/unit/BackgroundJob/CleanupInvitationTokenJobTest.php
index 21e999d34be..b2199e3e657 100644
--- a/apps/dav/tests/unit/BackgroundJob/CleanupInvitationTokenJobTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/CleanupInvitationTokenJobTest.php
@@ -13,17 +13,13 @@ use OCP\AppFramework\Utility\ITimeFactory;
use OCP\DB\QueryBuilder\IExpressionBuilder;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class CleanupInvitationTokenJobTest extends TestCase {
- /** @var IDBConnection | \PHPUnit\Framework\MockObject\MockObject */
- private $dbConnection;
-
- /** @var ITimeFactory | \PHPUnit\Framework\MockObject\MockObject */
- private $timeFactory;
-
- /** @var CleanupInvitationTokenJob */
- private $backgroundJob;
+ private IDBConnection&MockObject $dbConnection;
+ private ITimeFactory&MockObject $timeFactory;
+ private CleanupInvitationTokenJob $backgroundJob;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/BackgroundJob/CleanupOrphanedChildrenJobTest.php b/apps/dav/tests/unit/BackgroundJob/CleanupOrphanedChildrenJobTest.php
new file mode 100644
index 00000000000..2065b8fe946
--- /dev/null
+++ b/apps/dav/tests/unit/BackgroundJob/CleanupOrphanedChildrenJobTest.php
@@ -0,0 +1,170 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Tests\unit\BackgroundJob;
+
+use OCA\DAV\BackgroundJob\CleanupOrphanedChildrenJob;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\BackgroundJob\IJobList;
+use OCP\DB\IResult;
+use OCP\DB\QueryBuilder\IExpressionBuilder;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
+use Test\TestCase;
+
+class CleanupOrphanedChildrenJobTest extends TestCase {
+ private CleanupOrphanedChildrenJob $job;
+
+ private ITimeFactory&MockObject $timeFactory;
+ private IDBConnection&MockObject $connection;
+ private LoggerInterface&MockObject $logger;
+ private IJobList&MockObject $jobList;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->timeFactory = $this->createMock(ITimeFactory::class);
+ $this->connection = $this->createMock(IDBConnection::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
+ $this->jobList = $this->createMock(IJobList::class);
+
+ $this->job = new CleanupOrphanedChildrenJob(
+ $this->timeFactory,
+ $this->connection,
+ $this->logger,
+ $this->jobList,
+ );
+ }
+
+ private function getArgument(): array {
+ return [
+ 'childTable' => 'childTable',
+ 'parentTable' => 'parentTable',
+ 'parentId' => 'parentId',
+ 'logMessage' => 'logMessage',
+ ];
+ }
+
+ private function getMockQueryBuilder(): IQueryBuilder&MockObject {
+ $expr = $this->createMock(IExpressionBuilder::class);
+ $qb = $this->createMock(IQueryBuilder::class);
+ $qb->method('select')
+ ->willReturnSelf();
+ $qb->method('from')
+ ->willReturnSelf();
+ $qb->method('leftJoin')
+ ->willReturnSelf();
+ $qb->method('where')
+ ->willReturnSelf();
+ $qb->method('setMaxResults')
+ ->willReturnSelf();
+ $qb->method('andWhere')
+ ->willReturnSelf();
+ $qb->method('expr')
+ ->willReturn($expr);
+ $qb->method('delete')
+ ->willReturnSelf();
+ return $qb;
+ }
+
+ public function testRunWithoutOrphans(): void {
+ $argument = $this->getArgument();
+ $selectQb = $this->getMockQueryBuilder();
+ $result = $this->createMock(IResult::class);
+
+ $this->connection->expects(self::once())
+ ->method('getQueryBuilder')
+ ->willReturn($selectQb);
+ $selectQb->expects(self::once())
+ ->method('executeQuery')
+ ->willReturn($result);
+ $result->expects(self::once())
+ ->method('fetchAll')
+ ->willReturn([]);
+ $result->expects(self::once())
+ ->method('closeCursor');
+ $this->jobList->expects(self::never())
+ ->method('add');
+
+ self::invokePrivate($this->job, 'run', [$argument]);
+ }
+
+ public function testRunWithPartialBatch(): void {
+ $argument = $this->getArgument();
+ $selectQb = $this->getMockQueryBuilder();
+ $deleteQb = $this->getMockQueryBuilder();
+ $result = $this->createMock(IResult::class);
+
+ $calls = [
+ $selectQb,
+ $deleteQb,
+ ];
+ $this->connection->method('getQueryBuilder')
+ ->willReturnCallback(function () use (&$calls) {
+ return array_shift($calls);
+ });
+ $selectQb->expects(self::once())
+ ->method('executeQuery')
+ ->willReturn($result);
+ $result->expects(self::once())
+ ->method('fetchAll')
+ ->willReturn([
+ ['id' => 42],
+ ['id' => 43],
+ ]);
+ $result->expects(self::once())
+ ->method('closeCursor');
+ $deleteQb->expects(self::once())
+ ->method('delete')
+ ->willReturnSelf();
+ $deleteQb->expects(self::once())
+ ->method('executeStatement');
+ $this->jobList->expects(self::never())
+ ->method('add');
+
+ self::invokePrivate($this->job, 'run', [$argument]);
+ }
+
+ public function testRunWithFullBatch(): void {
+ $argument = $this->getArgument();
+ $selectQb = $this->getMockQueryBuilder();
+ $deleteQb = $this->getMockQueryBuilder();
+ $result = $this->createMock(IResult::class);
+
+ $calls = [
+ $selectQb,
+ $deleteQb,
+ ];
+ $this->connection->method('getQueryBuilder')
+ ->willReturnCallback(function () use (&$calls) {
+ return array_shift($calls);
+ });
+
+ $selectQb->expects(self::once())
+ ->method('executeQuery')
+ ->willReturn($result);
+ $result->expects(self::once())
+ ->method('fetchAll')
+ ->willReturn(array_map(static fn ($i) => ['id' => 42 + $i], range(0, 999)));
+ $result->expects(self::once())
+ ->method('closeCursor');
+ $deleteQb->expects(self::once())
+ ->method('delete')
+ ->willReturnSelf();
+ $deleteQb->expects(self::once())
+ ->method('executeStatement');
+ $this->jobList->expects(self::once())
+ ->method('add')
+ ->with(CleanupOrphanedChildrenJob::class, $argument);
+
+ self::invokePrivate($this->job, 'run', [$argument]);
+ }
+}
diff --git a/apps/dav/tests/unit/BackgroundJob/EventReminderJobTest.php b/apps/dav/tests/unit/BackgroundJob/EventReminderJobTest.php
index 1173e516a22..1f70869f211 100644
--- a/apps/dav/tests/unit/BackgroundJob/EventReminderJobTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/EventReminderJobTest.php
@@ -16,17 +16,10 @@ use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class EventReminderJobTest extends TestCase {
- /** @var ITimeFactory|MockObject */
- private $time;
-
- /** @var ReminderService|MockObject */
- private $reminderService;
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var EventReminderJob|MockObject */
- private $backgroundJob;
+ private ITimeFactory&MockObject $time;
+ private ReminderService&MockObject $reminderService;
+ private IConfig&MockObject $config;
+ private EventReminderJob $backgroundJob;
protected function setUp(): void {
parent::setUp();
@@ -42,7 +35,7 @@ class EventReminderJobTest extends TestCase {
);
}
- public function data(): array {
+ public static function data(): array {
return [
[true, true, true],
[true, false, false],
@@ -61,14 +54,10 @@ class EventReminderJobTest extends TestCase {
public function testRun(bool $sendEventReminders, bool $sendEventRemindersMode, bool $expectCall): void {
$this->config->expects($this->exactly($sendEventReminders ? 2 : 1))
->method('getAppValue')
- ->withConsecutive(
- ['dav', 'sendEventReminders', 'yes'],
- ['dav', 'sendEventRemindersMode', 'backgroundjob'],
- )
- ->willReturnOnConsecutiveCalls(
- $sendEventReminders ? 'yes' : 'no',
- $sendEventRemindersMode ? 'backgroundjob' : 'cron'
- );
+ ->willReturnMap([
+ ['dav', 'sendEventReminders', 'yes', ($sendEventReminders ? 'yes' : 'no')],
+ ['dav', 'sendEventRemindersMode', 'backgroundjob', ($sendEventRemindersMode ? 'backgroundjob' : 'cron')],
+ ]);
if ($expectCall) {
$this->reminderService->expects($this->once())
diff --git a/apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php b/apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php
index 82d2251f17a..88a76ae1332 100644
--- a/apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/GenerateBirthdayCalendarBackgroundJobTest.php
@@ -16,18 +16,10 @@ use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class GenerateBirthdayCalendarBackgroundJobTest extends TestCase {
-
- /** @var ITimeFactory|MockObject */
- private $time;
-
- /** @var BirthdayService | MockObject */
- private $birthdayService;
-
- /** @var IConfig | MockObject */
- private $config;
-
- /** @var GenerateBirthdayCalendarBackgroundJob */
- private $backgroundJob;
+ private ITimeFactory&MockObject $time;
+ private BirthdayService&MockObject $birthdayService;
+ private IConfig&MockObject $config;
+ private GenerateBirthdayCalendarBackgroundJob $backgroundJob;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/BackgroundJob/OutOfOfficeEventDispatcherJobTest.php b/apps/dav/tests/unit/BackgroundJob/OutOfOfficeEventDispatcherJobTest.php
index 5ddd9eba6f8..6135fd00fdc 100644
--- a/apps/dav/tests/unit/BackgroundJob/OutOfOfficeEventDispatcherJobTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/OutOfOfficeEventDispatcherJobTest.php
@@ -25,21 +25,11 @@ use Test\TestCase;
class OutOfOfficeEventDispatcherJobTest extends TestCase {
private OutOfOfficeEventDispatcherJob $job;
-
- /** @var MockObject|ITimeFactory */
- private $timeFactory;
-
- /** @var MockObject|AbsenceMapper */
- private $absenceMapper;
-
- /** @var MockObject|LoggerInterface */
- private $logger;
-
- /** @var MockObject|IEventDispatcher */
- private $eventDispatcher;
-
- /** @var MockObject|IUserManager */
- private $userManager;
+ private ITimeFactory&MockObject $timeFactory;
+ private AbsenceMapper&MockObject $absenceMapper;
+ private LoggerInterface&MockObject $logger;
+ private IEventDispatcher&MockObject $eventDispatcher;
+ private IUserManager&MockObject $userManager;
private MockObject|TimezoneService $timezoneService;
protected function setUp(): void {
diff --git a/apps/dav/tests/unit/BackgroundJob/PruneOutdatedSyncTokensJobTest.php b/apps/dav/tests/unit/BackgroundJob/PruneOutdatedSyncTokensJobTest.php
index d08d0fd4496..eb471189c24 100644
--- a/apps/dav/tests/unit/BackgroundJob/PruneOutdatedSyncTokensJobTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/PruneOutdatedSyncTokensJobTest.php
@@ -20,21 +20,11 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class PruneOutdatedSyncTokensJobTest extends TestCase {
- /** @var ITimeFactory | MockObject */
- private $timeFactory;
-
- /** @var CalDavBackend | MockObject */
- private $calDavBackend;
-
- /** @var CardDavBackend | MockObject */
- private $cardDavBackend;
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var LoggerInterface|MockObject */
- private $logger;
-
+ private ITimeFactory&MockObject $timeFactory;
+ private CalDavBackend&MockObject $calDavBackend;
+ private CardDavBackend&MockObject $cardDavBackend;
+ private IConfig&MockObject $config;
+ private LoggerInterface&MockObject $logger;
private PruneOutdatedSyncTokensJob $backgroundJob;
protected function setUp(): void {
@@ -84,7 +74,7 @@ class PruneOutdatedSyncTokensJobTest extends TestCase {
$this->backgroundJob->run(null);
}
- public function dataForTestRun(): array {
+ public static function dataForTestRun(): array {
return [
['100', '2', 100, 7 * 24 * 3600, 2, 3],
['100', '14', 100, 14 * 24 * 3600, 2, 3],
diff --git a/apps/dav/tests/unit/BackgroundJob/RefreshWebcalJobTest.php b/apps/dav/tests/unit/BackgroundJob/RefreshWebcalJobTest.php
index 2b11223210e..0cdeb6436e2 100644
--- a/apps/dav/tests/unit/BackgroundJob/RefreshWebcalJobTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/RefreshWebcalJobTest.php
@@ -19,20 +19,11 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class RefreshWebcalJobTest extends TestCase {
-
- /** @var RefreshWebcalService | MockObject */
- private $refreshWebcalService;
-
- /** @var IConfig | MockObject */
- private $config;
-
+ private RefreshWebcalService&MockObject $refreshWebcalService;
+ private IConfig&MockObject $config;
private LoggerInterface $logger;
-
- /** @var ITimeFactory | MockObject */
- private $timeFactory;
-
- /** @var IJobList | MockObject */
- private $jobList;
+ private ITimeFactory&MockObject $timeFactory;
+ private IJobList&MockObject $jobList;
protected function setUp(): void {
parent::setUp();
@@ -97,10 +88,7 @@ class RefreshWebcalJobTest extends TestCase {
$backgroundJob->start($this->jobList);
}
- /**
- * @return array
- */
- public function runDataProvider():array {
+ public static function runDataProvider():array {
return [
[0, 100000, true],
[100000, 100000, false]
diff --git a/apps/dav/tests/unit/BackgroundJob/RegisterRegenerateBirthdayCalendarsTest.php b/apps/dav/tests/unit/BackgroundJob/RegisterRegenerateBirthdayCalendarsTest.php
index 88493d91d9b..6c9214d0268 100644
--- a/apps/dav/tests/unit/BackgroundJob/RegisterRegenerateBirthdayCalendarsTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/RegisterRegenerateBirthdayCalendarsTest.php
@@ -14,20 +14,14 @@ use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\IJobList;
use OCP\IUser;
use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class RegisterRegenerateBirthdayCalendarsTest extends TestCase {
- /** @var ITimeFactory | \PHPUnit\Framework\MockObject\MockObject */
- private $time;
-
- /** @var IUserManager | \PHPUnit\Framework\MockObject\MockObject */
- private $userManager;
-
- /** @var IJobList | \PHPUnit\Framework\MockObject\MockObject */
- private $jobList;
-
- /** @var RegisterRegenerateBirthdayCalendars */
- private $backgroundJob;
+ private ITimeFactory&MockObject $time;
+ private IUserManager&MockObject $userManager;
+ private IJobList&MockObject $jobList;
+ private RegisterRegenerateBirthdayCalendars $backgroundJob;
protected function setUp(): void {
parent::setUp();
@@ -59,22 +53,26 @@ class RegisterRegenerateBirthdayCalendarsTest extends TestCase {
$closure($user3);
});
+ $calls = [
+ 'uid1',
+ 'uid2',
+ 'uid3',
+ ];
$this->jobList->expects($this->exactly(3))
->method('add')
- ->withConsecutive(
- [GenerateBirthdayCalendarBackgroundJob::class, [
- 'userId' => 'uid1',
- 'purgeBeforeGenerating' => true
- ]],
- [GenerateBirthdayCalendarBackgroundJob::class, [
- 'userId' => 'uid2',
- 'purgeBeforeGenerating' => true
- ]],
- [GenerateBirthdayCalendarBackgroundJob::class, [
- 'userId' => 'uid3',
- 'purgeBeforeGenerating' => true
- ]],
- );
+ ->willReturnCallback(function () use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals(
+ [
+ GenerateBirthdayCalendarBackgroundJob::class,
+ [
+ 'userId' => $expected,
+ 'purgeBeforeGenerating' => true
+ ]
+ ],
+ func_get_args()
+ );
+ });
$this->backgroundJob->run([]);
}
diff --git a/apps/dav/tests/unit/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJobTest.php b/apps/dav/tests/unit/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJobTest.php
index 18ee0c5c61d..38a981787cd 100644
--- a/apps/dav/tests/unit/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJobTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/UpdateCalendarResourcesRoomsBackgroundJobTest.php
@@ -18,15 +18,9 @@ use Test\TestCase;
class UpdateCalendarResourcesRoomsBackgroundJobTest extends TestCase {
private UpdateCalendarResourcesRoomsBackgroundJob $backgroundJob;
-
- /** @var ITimeFactory|MockObject */
- private $time;
-
- /** @var IResourceManager|MockObject */
- private $resourceManager;
-
- /** @var IRoomManager|MockObject */
- private $roomManager;
+ private ITimeFactory&MockObject $time;
+ private IResourceManager&MockObject $resourceManager;
+ private IRoomManager&MockObject $roomManager;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/BackgroundJob/UserStatusAutomationTest.php b/apps/dav/tests/unit/BackgroundJob/UserStatusAutomationTest.php
index ce3871aa400..369242ad488 100644
--- a/apps/dav/tests/unit/BackgroundJob/UserStatusAutomationTest.php
+++ b/apps/dav/tests/unit/BackgroundJob/UserStatusAutomationTest.php
@@ -29,14 +29,13 @@ use Test\TestCase;
* @group DB
*/
class UserStatusAutomationTest extends TestCase {
-
- protected MockObject|ITimeFactory $time;
- protected MockObject|IJobList $jobList;
- protected MockObject|LoggerInterface $logger;
- protected MockObject|IManager $statusManager;
- protected MockObject|IConfig $config;
- private IAvailabilityCoordinator|MockObject $coordinator;
- private IUserManager|MockObject $userManager;
+ protected ITimeFactory&MockObject $time;
+ protected IJobList&MockObject $jobList;
+ protected LoggerInterface&MockObject $logger;
+ protected IManager&MockObject $statusManager;
+ protected IConfig&MockObject $config;
+ private IAvailabilityCoordinator&MockObject $coordinator;
+ private IUserManager&MockObject $userManager;
protected function setUp(): void {
parent::setUp();
@@ -76,11 +75,11 @@ class UserStatusAutomationTest extends TestCase {
$this->coordinator,
$this->userManager,
])
- ->setMethods($methods)
+ ->onlyMethods($methods)
->getMock();
}
- public function dataRun(): array {
+ public static function dataRun(): array {
return [
['20230217', '2023-02-24 10:49:36.613834', true],
['20230224', '2023-02-24 10:49:36.613834', true],
diff --git a/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php
index c1d8e8609b6..45937d86873 100644
--- a/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php
+++ b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackend.php
@@ -44,12 +44,12 @@ abstract class AbstractCalDavBackend extends TestCase {
protected CalDavBackend $backend;
- protected Principal|MockObject $principal;
- protected IUserManager|MockObject $userManager;
- protected IGroupManager|MockObject $groupManager;
- protected IEventDispatcher|MockObject $dispatcher;
- private LoggerInterface|MockObject $logger;
- private IConfig|MockObject $config;
+ protected Principal&MockObject $principal;
+ protected IUserManager&MockObject $userManager;
+ protected IGroupManager&MockObject $groupManager;
+ protected IEventDispatcher&MockObject $dispatcher;
+ private LoggerInterface&MockObject $logger;
+ private IConfig&MockObject $config;
private ISecureRandom $random;
protected SharingBackend $sharingBackend;
protected IDBConnection $db;
@@ -77,7 +77,7 @@ abstract class AbstractCalDavBackend extends TestCase {
$this->createMock(IConfig::class),
$this->createMock(IFactory::class)
])
- ->setMethods(['getPrincipalByPath', 'getGroupMembership', 'findByUri'])
+ ->onlyMethods(['getPrincipalByPath', 'getGroupMembership', 'findByUri'])
->getMock();
$this->principal->expects($this->any())->method('getPrincipalByPath')
->willReturn([
@@ -143,7 +143,7 @@ abstract class AbstractCalDavBackend extends TestCase {
}
}
- protected function createTestCalendar() {
+ protected function createTestCalendar(): int {
$this->dispatcher->expects(self::any())
->method('dispatchTyped');
@@ -160,9 +160,7 @@ abstract class AbstractCalDavBackend extends TestCase {
$this->assertEquals('#1C4587FF', $color);
$this->assertEquals('Example', $calendars[0]['uri']);
$this->assertEquals('Example', $calendars[0]['{DAV:}displayname']);
- $calendarId = $calendars[0]['id'];
-
- return $calendarId;
+ return (int)$calendars[0]['id'];
}
protected function createTestSubscription() {
diff --git a/apps/dav/tests/unit/CalDAV/Activity/BackendTest.php b/apps/dav/tests/unit/CalDAV/Activity/BackendTest.php
index 6ace633b072..ebe989ad815 100644
--- a/apps/dav/tests/unit/CalDAV/Activity/BackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/Activity/BackendTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -19,21 +21,11 @@ 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;
-
- /** @var IUserManager|MockObject */
- protected $userManager;
+ protected IManager&MockObject $activityManager;
+ protected IGroupManager&MockObject $groupManager;
+ protected IUserSession&MockObject $userSession;
+ protected IAppManager&MockObject $appManager;
+ protected IUserManager&MockObject $userManager;
protected function setUp(): void {
parent::setUp();
@@ -45,10 +37,9 @@ class BackendTest extends TestCase {
}
/**
- * @param array $methods
- * @return Backend|MockObject
+ * @return Backend|(Backend&MockObject)
*/
- protected function getBackend(array $methods = []) {
+ protected function getBackend(array $methods = []): Backend {
if (empty($methods)) {
return new Backend(
$this->activityManager,
@@ -71,7 +62,7 @@ class BackendTest extends TestCase {
}
}
- public function dataCallTriggerCalendarActivity() {
+ public static function dataCallTriggerCalendarActivity(): array {
return [
['onCalendarAdd', [['data']], Calendar::SUBJECT_ADD, [['data'], [], []]],
['onCalendarUpdate', [['data'], ['shares'], ['changed-properties']], Calendar::SUBJECT_UPDATE, [['data'], ['shares'], ['changed-properties']]],
@@ -82,13 +73,8 @@ class BackendTest extends TestCase {
/**
* @dataProvider dataCallTriggerCalendarActivity
- *
- * @param string $method
- * @param array $payload
- * @param string $expectedSubject
- * @param array $expectedPayload
*/
- public function testCallTriggerCalendarActivity($method, array $payload, $expectedSubject, array $expectedPayload): void {
+ public function testCallTriggerCalendarActivity(string $method, array $payload, string $expectedSubject, array $expectedPayload): void {
$backend = $this->getBackend(['triggerCalendarActivity']);
$backend->expects($this->once())
->method('triggerCalendarActivity')
@@ -101,7 +87,7 @@ class BackendTest extends TestCase {
call_user_func_array([$backend, $method], $payload);
}
- public function dataTriggerCalendarActivity() {
+ public static function dataTriggerCalendarActivity(): array {
return [
// Add calendar
[Calendar::SUBJECT_ADD, [], [], [], '', '', null, []],
@@ -184,16 +170,8 @@ class BackendTest extends TestCase {
/**
* @dataProvider dataTriggerCalendarActivity
- * @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 testTriggerCalendarActivity($action, array $data, array $shares, array $changedProperties, $currentUser, $author, $shareUsers, array $users): void {
+ public function testTriggerCalendarActivity(string $action, array $data, array $shares, array $changedProperties, string $currentUser, string $author, ?array $shareUsers, array $users): void {
$backend = $this->getBackend(['getUsersForShares']);
if ($shareUsers === null) {
@@ -278,7 +256,7 @@ class BackendTest extends TestCase {
], [], []]);
}
- public function dataGetUsersForShares() {
+ public static function dataGetUsersForShares(): array {
return [
[
[],
@@ -323,9 +301,6 @@ class BackendTest extends TestCase {
/**
* @dataProvider dataGetUsersForShares
- * @param array $shares
- * @param array $groups
- * @param array $expected
*/
public function testGetUsersForShares(array $shares, array $groups, array $expected): void {
$backend = $this->getBackend();
@@ -356,7 +331,7 @@ class BackendTest extends TestCase {
/**
* @param string[] $users
- * @return IUser[]|MockObject[]
+ * @return IUser[]&MockObject[]
*/
protected function getUsers(array $users) {
$list = [];
@@ -368,7 +343,7 @@ class BackendTest extends TestCase {
/**
* @param string $uid
- * @return IUser|MockObject
+ * @return IUser&MockObject
*/
protected function getUserMock($uid) {
$user = $this->createMock(IUser::class);
diff --git a/apps/dav/tests/unit/CalDAV/Activity/Filter/CalendarTest.php b/apps/dav/tests/unit/CalDAV/Activity/Filter/CalendarTest.php
index a7c84260f21..a31907b4b0a 100644
--- a/apps/dav/tests/unit/CalDAV/Activity/Filter/CalendarTest.php
+++ b/apps/dav/tests/unit/CalDAV/Activity/Filter/CalendarTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -9,15 +11,12 @@ use OCA\DAV\CalDAV\Activity\Filter\Calendar;
use OCP\Activity\IFilter;
use OCP\IL10N;
use OCP\IURLGenerator;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class CalendarTest extends TestCase {
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- protected $url;
-
- /** @var IFilter|\PHPUnit\Framework\MockObject\MockObject */
- protected $filter;
+ protected IURLGenerator&MockObject $url;
+ protected IFilter $filter;
protected function setUp(): void {
parent::setUp();
@@ -48,7 +47,7 @@ class CalendarTest extends TestCase {
$this->assertEquals('absolute-path-to-icon', $this->filter->getIcon());
}
- public function dataFilterTypes() {
+ public static function dataFilterTypes(): array {
return [
[[], []],
[['calendar', 'calendar_event'], ['calendar', 'calendar_event']],
@@ -62,7 +61,7 @@ class CalendarTest extends TestCase {
* @param string[] $types
* @param string[] $expected
*/
- public function testFilterTypes($types, $expected): void {
+ public function testFilterTypes(array $types, array $expected): void {
$this->assertEquals($expected, $this->filter->filterTypes($types));
}
}
diff --git a/apps/dav/tests/unit/CalDAV/Activity/Filter/GenericTest.php b/apps/dav/tests/unit/CalDAV/Activity/Filter/GenericTest.php
index 392759206ed..468dd15f480 100644
--- a/apps/dav/tests/unit/CalDAV/Activity/Filter/GenericTest.php
+++ b/apps/dav/tests/unit/CalDAV/Activity/Filter/GenericTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -15,7 +17,7 @@ use Test\TestCase;
* @group DB
*/
class GenericTest extends TestCase {
- public function dataFilters() {
+ public static function dataFilters(): array {
return [
[Calendar::class],
[Todo::class],
@@ -24,18 +26,16 @@ class GenericTest extends TestCase {
/**
* @dataProvider dataFilters
- * @param string $filterClass
*/
- public function testImplementsInterface($filterClass): void {
+ public function testImplementsInterface(string $filterClass): void {
$filter = Server::get($filterClass);
$this->assertInstanceOf(IFilter::class, $filter);
}
/**
* @dataProvider dataFilters
- * @param string $filterClass
*/
- public function testGetIdentifier($filterClass): void {
+ public function testGetIdentifier(string $filterClass): void {
/** @var IFilter $filter */
$filter = Server::get($filterClass);
$this->assertIsString($filter->getIdentifier());
@@ -43,9 +43,8 @@ class GenericTest extends TestCase {
/**
* @dataProvider dataFilters
- * @param string $filterClass
*/
- public function testGetName($filterClass): void {
+ public function testGetName(string $filterClass): void {
/** @var IFilter $filter */
$filter = Server::get($filterClass);
$this->assertIsString($filter->getName());
@@ -53,9 +52,8 @@ class GenericTest extends TestCase {
/**
* @dataProvider dataFilters
- * @param string $filterClass
*/
- public function testGetPriority($filterClass): void {
+ public function testGetPriority(string $filterClass): void {
/** @var IFilter $filter */
$filter = Server::get($filterClass);
$priority = $filter->getPriority();
@@ -66,9 +64,8 @@ class GenericTest extends TestCase {
/**
* @dataProvider dataFilters
- * @param string $filterClass
*/
- public function testGetIcon($filterClass): void {
+ public function testGetIcon(string $filterClass): void {
/** @var IFilter $filter */
$filter = Server::get($filterClass);
$this->assertIsString($filter->getIcon());
@@ -77,9 +74,8 @@ class GenericTest extends TestCase {
/**
* @dataProvider dataFilters
- * @param string $filterClass
*/
- public function testFilterTypes($filterClass): void {
+ public function testFilterTypes(string $filterClass): void {
/** @var IFilter $filter */
$filter = Server::get($filterClass);
$this->assertIsArray($filter->filterTypes([]));
@@ -87,9 +83,8 @@ class GenericTest extends TestCase {
/**
* @dataProvider dataFilters
- * @param string $filterClass
*/
- public function testAllowedApps($filterClass): void {
+ public function testAllowedApps(string $filterClass): void {
/** @var IFilter $filter */
$filter = Server::get($filterClass);
$this->assertIsArray($filter->allowedApps());
diff --git a/apps/dav/tests/unit/CalDAV/Activity/Filter/TodoTest.php b/apps/dav/tests/unit/CalDAV/Activity/Filter/TodoTest.php
index 6aa47f33750..6ef7289e156 100644
--- a/apps/dav/tests/unit/CalDAV/Activity/Filter/TodoTest.php
+++ b/apps/dav/tests/unit/CalDAV/Activity/Filter/TodoTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -9,15 +11,12 @@ use OCA\DAV\CalDAV\Activity\Filter\Todo;
use OCP\Activity\IFilter;
use OCP\IL10N;
use OCP\IURLGenerator;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class TodoTest extends TestCase {
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- protected $url;
-
- /** @var IFilter|\PHPUnit\Framework\MockObject\MockObject */
- protected $filter;
+ protected IURLGenerator&MockObject $url;
+ protected IFilter $filter;
protected function setUp(): void {
parent::setUp();
@@ -48,7 +47,7 @@ class TodoTest extends TestCase {
$this->assertEquals('absolute-path-to-icon', $this->filter->getIcon());
}
- public function dataFilterTypes() {
+ public static function dataFilterTypes(): array {
return [
[[], []],
[['calendar_todo'], ['calendar_todo']],
@@ -62,7 +61,7 @@ class TodoTest extends TestCase {
* @param string[] $types
* @param string[] $expected
*/
- public function testFilterTypes($types, $expected): void {
+ public function testFilterTypes(array $types, array $expected): void {
$this->assertEquals($expected, $this->filter->filterTypes($types));
}
}
diff --git a/apps/dav/tests/unit/CalDAV/Activity/Provider/BaseTest.php b/apps/dav/tests/unit/CalDAV/Activity/Provider/BaseTest.php
index ba97c888b0c..113af7ed240 100644
--- a/apps/dav/tests/unit/CalDAV/Activity/Provider/BaseTest.php
+++ b/apps/dav/tests/unit/CalDAV/Activity/Provider/BaseTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -7,7 +9,6 @@ namespace OCA\DAV\Tests\unit\CalDAV\Activity\Provider;
use OCA\DAV\CalDAV\Activity\Provider\Base;
use OCP\Activity\IEvent;
-use OCP\Activity\IProvider;
use OCP\IGroupManager;
use OCP\IL10N;
use OCP\IURLGenerator;
@@ -16,17 +17,10 @@ use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class BaseTest extends TestCase {
- /** @var IUserManager|MockObject */
- protected $userManager;
-
- /** @var IGroupManager|MockObject */
- protected $groupManager;
-
- /** @var IURLGenerator|MockObject */
- protected $url;
-
- /** @var IProvider|Base|MockObject */
- protected $provider;
+ protected IUserManager&MockObject $userManager;
+ protected IGroupManager&MockObject $groupManager;
+ protected IURLGenerator&MockObject $url;
+ protected Base&MockObject $provider;
protected function setUp(): void {
parent::setUp();
@@ -39,24 +33,21 @@ class BaseTest extends TestCase {
$this->groupManager,
$this->url,
])
- ->setMethods(['parse'])
+ ->onlyMethods(['parse'])
->getMock();
}
- public function dataSetSubjects() {
+ public static function dataSetSubjects(): array {
return [
- ['abc', [], 'abc'],
- ['{actor} created {calendar}', ['actor' => ['name' => 'abc'], 'calendar' => ['name' => 'xyz']], 'abc created xyz'],
+ ['abc', []],
+ ['{actor} created {calendar}', ['actor' => ['name' => 'abc'], 'calendar' => ['name' => 'xyz']]],
];
}
/**
* @dataProvider dataSetSubjects
- * @param string $subject
- * @param array $parameters
- * @param string $parsedSubject
*/
- public function testSetSubjects(string $subject, array $parameters, string $parsedSubject): void {
+ public function testSetSubjects(string $subject, array $parameters): void {
$event = $this->createMock(IEvent::class);
$event->expects($this->once())
->method('setRichSubject')
@@ -68,7 +59,7 @@ class BaseTest extends TestCase {
$this->invokePrivate($this->provider, 'setSubjects', [$event, $subject, $parameters]);
}
- public function dataGenerateCalendarParameter() {
+ public static function dataGenerateCalendarParameter(): array {
return [
[['id' => 23, 'uri' => 'foo', 'name' => 'bar'], 'bar'],
[['id' => 42, 'uri' => 'foo', 'name' => 'Personal'], 'Personal'],
@@ -79,8 +70,6 @@ class BaseTest extends TestCase {
/**
* @dataProvider dataGenerateCalendarParameter
- * @param array $data
- * @param string $name
*/
public function testGenerateCalendarParameter(array $data, string $name): void {
$l = $this->createMock(IL10N::class);
@@ -97,7 +86,7 @@ class BaseTest extends TestCase {
], $this->invokePrivate($this->provider, 'generateCalendarParameter', [$data, $l]));
}
- public function dataGenerateLegacyCalendarParameter() {
+ public static function dataGenerateLegacyCalendarParameter(): array {
return [
[23, 'c1'],
[42, 'c2'],
@@ -106,8 +95,6 @@ class BaseTest extends TestCase {
/**
* @dataProvider dataGenerateLegacyCalendarParameter
- * @param int $id
- * @param string $name
*/
public function testGenerateLegacyCalendarParameter(int $id, string $name): void {
$this->assertEquals([
@@ -117,7 +104,7 @@ class BaseTest extends TestCase {
], $this->invokePrivate($this->provider, 'generateLegacyCalendarParameter', [$id, $name]));
}
- public function dataGenerateGroupParameter() {
+ public static function dataGenerateGroupParameter(): array {
return [
['g1'],
['g2'],
@@ -126,7 +113,6 @@ class BaseTest extends TestCase {
/**
* @dataProvider dataGenerateGroupParameter
- * @param string $gid
*/
public function testGenerateGroupParameter(string $gid): void {
$this->assertEquals([
diff --git a/apps/dav/tests/unit/CalDAV/Activity/Provider/EventTest.php b/apps/dav/tests/unit/CalDAV/Activity/Provider/EventTest.php
index ec237825731..52d3dfa64cb 100644
--- a/apps/dav/tests/unit/CalDAV/Activity/Provider/EventTest.php
+++ b/apps/dav/tests/unit/CalDAV/Activity/Provider/EventTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -6,11 +8,9 @@
namespace OCA\DAV\Tests\unit\CalDAV\Activity\Provider;
use InvalidArgumentException;
-use OCA\DAV\CalDAV\Activity\Provider\Base;
use OCA\DAV\CalDAV\Activity\Provider\Event;
use OCP\Activity\IEventMerger;
use OCP\Activity\IManager;
-use OCP\Activity\IProvider;
use OCP\App\IAppManager;
use OCP\IGroupManager;
use OCP\IURLGenerator;
@@ -21,30 +21,14 @@ use Test\TestCase;
use TypeError;
class EventTest extends TestCase {
-
- /** @var IUserManager|MockObject */
- protected $userManager;
-
- /** @var IGroupManager|MockObject */
- protected $groupManager;
-
- /** @var IURLGenerator|MockObject */
- protected $url;
-
- /** @var IProvider|Base|MockObject */
- protected $provider;
-
- /** @var IAppManager|MockObject */
- protected $appManager;
-
- /** @var IFactory|MockObject */
- protected $i10nFactory;
-
- /** @var IManager|MockObject */
- protected $activityManager;
-
- /** @var IEventMerger|MockObject */
- protected $eventMerger;
+ protected IUserManager&MockObject $userManager;
+ protected IGroupManager&MockObject $groupManager;
+ protected IURLGenerator&MockObject $url;
+ protected IAppManager&MockObject $appManager;
+ protected IFactory&MockObject $i10nFactory;
+ protected IManager&MockObject $activityManager;
+ protected IEventMerger&MockObject $eventMerger;
+ protected Event&MockObject $provider;
protected function setUp(): void {
parent::setUp();
@@ -65,11 +49,11 @@ class EventTest extends TestCase {
$this->eventMerger,
$this->appManager
])
- ->setMethods(['parse'])
+ ->onlyMethods(['parse'])
->getMock();
}
- public function dataGenerateObjectParameter() {
+ public static function dataGenerateObjectParameter(): array {
$link = [
'object_uri' => 'someuuid.ics',
'calendar_uri' => 'personal',
@@ -85,21 +69,13 @@ class EventTest extends TestCase {
/**
* @dataProvider dataGenerateObjectParameter
- * @param int $id
- * @param string $name
- * @param array|null $link
- * @param bool $calendarAppEnabled
*/
public function testGenerateObjectParameter(int $id, string $name, ?array $link, bool $calendarAppEnabled = true): void {
$affectedUser = 'otheruser';
if ($link) {
$affectedUser = $link['owner'];
$generatedLink = [
- 'view' => 'dayGridMonth',
- 'timeRange' => 'now',
- 'mode' => 'sidebar',
'objectId' => base64_encode('/remote.php/dav/calendars/' . $link['owner'] . '/' . $link['calendar_uri'] . '/' . $link['object_uri']),
- 'recurrenceId' => 'next'
];
$this->appManager->expects($this->once())
->method('isEnabledForUser')
@@ -110,7 +86,7 @@ class EventTest extends TestCase {
->method('getWebroot');
$this->url->expects($this->once())
->method('linkToRouteAbsolute')
- ->with('calendar.view.indexview.timerange.edit', $generatedLink)
+ ->with('calendar.view.indexdirect.edit', $generatedLink)
->willReturn('fullLink');
}
}
@@ -174,14 +150,12 @@ class EventTest extends TestCase {
];
}
- /** @dataProvider generateObjectParameterLinkEncodingDataProvider */
+ /**
+ * @dataProvider generateObjectParameterLinkEncodingDataProvider
+ */
public function testGenerateObjectParameterLinkEncoding(array $link, string $objectId): void {
$generatedLink = [
- 'view' => 'dayGridMonth',
- 'timeRange' => 'now',
- 'mode' => 'sidebar',
'objectId' => $objectId,
- 'recurrenceId' => 'next'
];
$this->appManager->expects($this->once())
->method('isEnabledForUser')
@@ -191,7 +165,7 @@ class EventTest extends TestCase {
->method('getWebroot');
$this->url->expects($this->once())
->method('linkToRouteAbsolute')
- ->with('calendar.view.indexview.timerange.edit', $generatedLink)
+ ->with('calendar.view.indexdirect.edit', $generatedLink)
->willReturn('fullLink');
$objectParameter = ['id' => 42, 'name' => 'calendar', 'link' => $link];
$result = [
@@ -203,7 +177,7 @@ class EventTest extends TestCase {
$this->assertEquals($result, $this->invokePrivate($this->provider, 'generateObjectParameter', [$objectParameter, 'sharee']));
}
- public function dataGenerateObjectParameterThrows() {
+ public static function dataGenerateObjectParameterThrows(): array {
return [
['event', TypeError::class],
[['name' => 'event']],
@@ -213,10 +187,8 @@ class EventTest extends TestCase {
/**
* @dataProvider dataGenerateObjectParameterThrows
- * @param mixed $eventData
- * @param string $exception
*/
- public function testGenerateObjectParameterThrows($eventData, string $exception = InvalidArgumentException::class): void {
+ public function testGenerateObjectParameterThrows(string|array $eventData, string $exception = InvalidArgumentException::class): void {
$this->expectException($exception);
$this->invokePrivate($this->provider, 'generateObjectParameter', [$eventData, 'no_user']);
diff --git a/apps/dav/tests/unit/CalDAV/Activity/Setting/GenericTest.php b/apps/dav/tests/unit/CalDAV/Activity/Setting/GenericTest.php
index 42b565b9d8b..2ed3bab02e6 100644
--- a/apps/dav/tests/unit/CalDAV/Activity/Setting/GenericTest.php
+++ b/apps/dav/tests/unit/CalDAV/Activity/Setting/GenericTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -13,7 +15,7 @@ use OCP\Server;
use Test\TestCase;
class GenericTest extends TestCase {
- public function dataSettings() {
+ public static function dataSettings(): array {
return [
[Calendar::class],
[Event::class],
@@ -23,18 +25,16 @@ class GenericTest extends TestCase {
/**
* @dataProvider dataSettings
- * @param string $settingClass
*/
- public function testImplementsInterface($settingClass): void {
+ public function testImplementsInterface(string $settingClass): void {
$setting = Server::get($settingClass);
$this->assertInstanceOf(ISetting::class, $setting);
}
/**
* @dataProvider dataSettings
- * @param string $settingClass
*/
- public function testGetIdentifier($settingClass): void {
+ public function testGetIdentifier(string $settingClass): void {
/** @var ISetting $setting */
$setting = Server::get($settingClass);
$this->assertIsString($setting->getIdentifier());
@@ -42,9 +42,8 @@ class GenericTest extends TestCase {
/**
* @dataProvider dataSettings
- * @param string $settingClass
*/
- public function testGetName($settingClass): void {
+ public function testGetName(string $settingClass): void {
/** @var ISetting $setting */
$setting = Server::get($settingClass);
$this->assertIsString($setting->getName());
@@ -52,9 +51,8 @@ class GenericTest extends TestCase {
/**
* @dataProvider dataSettings
- * @param string $settingClass
*/
- public function testGetPriority($settingClass): void {
+ public function testGetPriority(string $settingClass): void {
/** @var ISetting $setting */
$setting = Server::get($settingClass);
$priority = $setting->getPriority();
@@ -65,9 +63,8 @@ class GenericTest extends TestCase {
/**
* @dataProvider dataSettings
- * @param string $settingClass
*/
- public function testCanChangeStream($settingClass): void {
+ public function testCanChangeStream(string $settingClass): void {
/** @var ISetting $setting */
$setting = Server::get($settingClass);
$this->assertIsBool($setting->canChangeStream());
@@ -75,9 +72,8 @@ class GenericTest extends TestCase {
/**
* @dataProvider dataSettings
- * @param string $settingClass
*/
- public function testIsDefaultEnabledStream($settingClass): void {
+ public function testIsDefaultEnabledStream(string $settingClass): void {
/** @var ISetting $setting */
$setting = Server::get($settingClass);
$this->assertIsBool($setting->isDefaultEnabledStream());
@@ -85,9 +81,8 @@ class GenericTest extends TestCase {
/**
* @dataProvider dataSettings
- * @param string $settingClass
*/
- public function testCanChangeMail($settingClass): void {
+ public function testCanChangeMail(string $settingClass): void {
/** @var ISetting $setting */
$setting = Server::get($settingClass);
$this->assertIsBool($setting->canChangeMail());
@@ -95,9 +90,8 @@ class GenericTest extends TestCase {
/**
* @dataProvider dataSettings
- * @param string $settingClass
*/
- public function testIsDefaultEnabledMail($settingClass): void {
+ public function testIsDefaultEnabledMail(string $settingClass): void {
/** @var ISetting $setting */
$setting = Server::get($settingClass);
$this->assertIsBool($setting->isDefaultEnabledMail());
diff --git a/apps/dav/tests/unit/CalDAV/AppCalendar/AppCalendarTest.php b/apps/dav/tests/unit/CalDAV/AppCalendar/AppCalendarTest.php
index f7fa114ff28..bac2094f734 100644
--- a/apps/dav/tests/unit/CalDAV/AppCalendar/AppCalendarTest.php
+++ b/apps/dav/tests/unit/CalDAV/AppCalendar/AppCalendarTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -16,13 +17,13 @@ use Test\TestCase;
use function rewind;
class AppCalendarTest extends TestCase {
- private $principal = 'principals/users/foo';
+ private string $principal = 'principals/users/foo';
private AppCalendar $appCalendar;
private AppCalendar $writeableAppCalendar;
- private ICalendar|MockObject $calendar;
- private ICalendar|MockObject $writeableCalendar;
+ private ICalendar&MockObject $calendar;
+ private ICalendar&MockObject $writeableCalendar;
protected function setUp(): void {
parent::setUp();
@@ -53,9 +54,17 @@ class AppCalendarTest extends TestCase {
}
public function testCreateFile(): void {
+ $calls = [
+ ['some-name', 'data'],
+ ['other-name', ''],
+ ['name', 'some data'],
+ ];
$this->writeableCalendar->expects($this->exactly(3))
->method('createFromString')
- ->withConsecutive(['some-name', 'data'], ['other-name', ''], ['name', 'some data']);
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
// pass data
$this->assertNull($this->writeableAppCalendar->createFile('some-name', 'data'));
diff --git a/apps/dav/tests/unit/CalDAV/AppCalendar/CalendarObjectTest.php b/apps/dav/tests/unit/CalDAV/AppCalendar/CalendarObjectTest.php
index a913c2dde6f..3d72d5c97b8 100644
--- a/apps/dav/tests/unit/CalDAV/AppCalendar/CalendarObjectTest.php
+++ b/apps/dav/tests/unit/CalDAV/AppCalendar/CalendarObjectTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -17,9 +18,9 @@ use Test\TestCase;
class CalendarObjectTest extends TestCase {
private CalendarObject $calendarObject;
- private AppCalendar|MockObject $calendar;
- private ICalendar|MockObject $backend;
- private VCalendar|MockObject $vobject;
+ private AppCalendar&MockObject $calendar;
+ private ICalendar&MockObject $backend;
+ private VCalendar&MockObject $vobject;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php b/apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php
index e60efc6fb19..a5811271ce2 100644
--- a/apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/BirthdayCalendar/EnablePluginTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -11,24 +13,15 @@ use OCA\DAV\CalDAV\Calendar;
use OCA\DAV\CalDAV\CalendarHome;
use OCP\IConfig;
use OCP\IUser;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class EnablePluginTest extends TestCase {
-
- /** @var \Sabre\DAV\Server|\PHPUnit\Framework\MockObject\MockObject */
- protected $server;
-
- /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
- protected $config;
-
- /** @var BirthdayService |\PHPUnit\Framework\MockObject\MockObject */
- protected $birthdayService;
-
- /** @var IUser|\PHPUnit\Framework\MockObject\MockObject */
- protected $user;
-
- /** @var EnablePlugin $plugin */
- protected $plugin;
+ protected \Sabre\DAV\Server&MockObject $server;
+ protected IConfig&MockObject $config;
+ protected BirthdayService&MockObject $birthdayService;
+ protected IUser&MockObject $user;
+ protected EnablePlugin $plugin;
protected $request;
diff --git a/apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php b/apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php
index 2378a75a7d5..935d8314f29 100644
--- a/apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php
+++ b/apps/dav/tests/unit/CalDAV/CachedSubscriptionImplTest.php
@@ -12,13 +12,14 @@ namespace OCA\DAV\Tests\unit\CalDAV;
use OCA\DAV\CalDAV\CachedSubscription;
use OCA\DAV\CalDAV\CachedSubscriptionImpl;
use OCA\DAV\CalDAV\CalDavBackend;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class CachedSubscriptionImplTest extends TestCase {
- private CachedSubscription $cachedSubscription;
+ private CachedSubscription&MockObject $cachedSubscription;
private array $cachedSubscriptionInfo;
+ private CalDavBackend&MockObject $backend;
private CachedSubscriptionImpl $cachedSubscriptionImpl;
- private CalDavBackend $backend;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/CalDAV/CachedSubscriptionObjectTest.php b/apps/dav/tests/unit/CalDAV/CachedSubscriptionObjectTest.php
index 56e4930d3b3..03a2c9f20ee 100644
--- a/apps/dav/tests/unit/CalDAV/CachedSubscriptionObjectTest.php
+++ b/apps/dav/tests/unit/CalDAV/CachedSubscriptionObjectTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -32,7 +34,7 @@ class CachedSubscriptionObjectTest extends \Test\TestCase {
$this->assertEquals('BEGIN...', $calendarObject->get());
}
-
+
public function testPut(): void {
$this->expectException(\Sabre\DAV\Exception\MethodNotAllowed::class);
$this->expectExceptionMessage('Creating objects in a cached subscription is not allowed');
@@ -52,7 +54,7 @@ class CachedSubscriptionObjectTest extends \Test\TestCase {
$calendarObject->put('');
}
-
+
public function testDelete(): void {
$this->expectException(\Sabre\DAV\Exception\MethodNotAllowed::class);
$this->expectExceptionMessage('Deleting objects in a cached subscription is not allowed');
diff --git a/apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php b/apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php
index be47b2bf640..58d5ca7835c 100644
--- a/apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php
+++ b/apps/dav/tests/unit/CalDAV/CachedSubscriptionProviderTest.php
@@ -12,11 +12,12 @@ namespace OCA\DAV\Tests\unit\CalDAV;
use OCA\DAV\CalDAV\CachedSubscriptionImpl;
use OCA\DAV\CalDAV\CachedSubscriptionProvider;
use OCA\DAV\CalDAV\CalDavBackend;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class CachedSubscriptionProviderTest extends TestCase {
- private CalDavBackend $backend;
+ private CalDavBackend&MockObject $backend;
private CachedSubscriptionProvider $provider;
protected function setUp(): void {
diff --git a/apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php b/apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php
index e1d22bc3e7b..ba0da422290 100644
--- a/apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php
+++ b/apps/dav/tests/unit/CalDAV/CachedSubscriptionTest.php
@@ -1,4 +1,5 @@
<?php
+
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -140,19 +141,21 @@ class CachedSubscriptionTest extends \Test\TestCase {
'uri' => 'cal',
];
+ $calls = [
+ [666, 'foo1', 1, [
+ 'id' => 99,
+ 'uri' => 'foo1'
+ ]],
+ [666, 'foo2', 1, null],
+ ];
$backend->expects($this->exactly(2))
->method('getCalendarObject')
- ->withConsecutive(
- [666, 'foo1', 1],
- [666, 'foo2', 1],
- )
- ->willReturnOnConsecutiveCalls(
- [
- 'id' => 99,
- 'uri' => 'foo1'
- ],
- null
- );
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $return = array_pop($expected);
+ $this->assertEquals($expected, func_get_args());
+ return $return;
+ });
$calendar = new CachedSubscription($backend, $calendarInfo);
@@ -250,19 +253,21 @@ class CachedSubscriptionTest extends \Test\TestCase {
'uri' => 'cal',
];
+ $calls = [
+ [666, 'foo1', 1, [
+ 'id' => 99,
+ 'uri' => 'foo1'
+ ]],
+ [666, 'foo2', 1, null],
+ ];
$backend->expects($this->exactly(2))
->method('getCalendarObject')
- ->withConsecutive(
- [666, 'foo1', 1],
- [666, 'foo2', 1],
- )
- ->willReturnOnConsecutiveCalls(
- [
- 'id' => 99,
- 'uri' => 'foo1'
- ],
- null
- );
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $return = array_pop($expected);
+ $this->assertEquals($expected, func_get_args());
+ return $return;
+ });
$calendar = new CachedSubscription($backend, $calendarInfo);
diff --git a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
index 61c03c9e4c1..f8368660626 100644
--- a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -17,6 +19,7 @@ use OCA\DAV\DAV\Sharing\Plugin as SharingPlugin;
use OCA\DAV\Events\CalendarDeletedEvent;
use OCP\IConfig;
use OCP\IL10N;
+use Psr\Log\NullLogger;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\PropPatch;
use Sabre\DAV\Xml\Property\Href;
@@ -27,8 +30,6 @@ use function time;
* Class CalDavBackendTest
*
* @group DB
- *
- * @package OCA\DAV\Tests\unit\CalDAV
*/
class CalDavBackendTest extends AbstractCalDavBackend {
public function testCalendarOperations(): void {
@@ -58,7 +59,7 @@ class CalDavBackendTest extends AbstractCalDavBackend {
self::assertEmpty($calendars);
}
- public function providesSharingData() {
+ public static function providesSharingData(): array {
return [
[true, true, true, false, [
[
@@ -457,7 +458,7 @@ EOD;
$this->assertNotNull($co);
}
- public function providesCalendarQueryParameters() {
+ public static function providesCalendarQueryParameters(): array {
return [
'all' => [[0, 1, 2, 3], [], []],
'only-todos' => [[], ['name' => 'VTODO'], []],
@@ -519,7 +520,7 @@ EOD;
sort($stateLive['deleted']);
// test live state
$this->assertEquals($stateTest, $stateLive, 'Failed test delta sync state with events in calendar');
-
+
/** modify/delete events in calendar */
$this->deleteEvent($calendarId, $event1);
$this->modifyEvent($calendarId, $event2, '20250701T140000Z', '20250701T150000Z');
@@ -618,7 +619,7 @@ EOD;
$this->assertCount(0, $subscriptions);
}
- public function providesSchedulingData() {
+ public static function providesSchedulingData(): array {
$data = <<<EOS
BEGIN:VCALENDAR
VERSION:2.0
@@ -724,7 +725,7 @@ EOS;
}
}
- public function providesCalDataForGetDenormalizedData(): array {
+ public static function providesCalDataForGetDenormalizedData(): array {
return [
'first occurrence before unix epoch starts' => [0, 'firstOccurence', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:413F269B-B51B-46B1-AFB6-40055C53A4DC\r\nDTSTAMP:20160309T095056Z\r\nDTSTART;VALUE=DATE:16040222\r\nDTEND;VALUE=DATE:16040223\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:SUMMARY\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"],
'no first occurrence because yearly' => [null, 'firstOccurence', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:413F269B-B51B-46B1-AFB6-40055C53A4DC\r\nDTSTAMP:20160309T095056Z\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:SUMMARY\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"],
@@ -979,7 +980,7 @@ EOD;
$this->assertCount($count, $result);
}
- public function searchDataProvider() {
+ public static function searchDataProvider(): array {
return [
[false, [], 4],
[true, ['timerange' => ['start' => new DateTime('2013-09-12 13:00:00'), 'end' => new DateTime('2013-09-12 14:00:00')]], 2],
@@ -1847,4 +1848,46 @@ EOD;
$this->assertEquals('Missing DTSTART 1', $results[2]['objects'][0]['SUMMARY'][0]);
$this->assertEquals('Missing DTSTART 2', $results[3]['objects'][0]['SUMMARY'][0]);
}
+
+ public function testUnshare(): void {
+ $principalGroup = 'principal:' . self::UNIT_TEST_GROUP;
+ $principalUser = 'principal:' . self::UNIT_TEST_USER;
+
+ $l10n = $this->createMock(IL10N::class);
+ $l10n->method('t')
+ ->willReturnCallback(fn ($text, $parameters = []) => vsprintf($text, $parameters));
+ $config = $this->createMock(IConfig::class);
+ $logger = new NullLogger();
+
+ $this->principal->expects($this->exactly(2))
+ ->method('findByUri')
+ ->willReturnMap([
+ [$principalGroup, '', self::UNIT_TEST_GROUP],
+ [$principalUser, '', self::UNIT_TEST_USER],
+ ]);
+ $this->groupManager->expects($this->once())
+ ->method('groupExists')
+ ->willReturn(true);
+ $this->dispatcher->expects($this->exactly(2))
+ ->method('dispatchTyped');
+
+ $calendarId = $this->createTestCalendar();
+ $calendarInfo = $this->backend->getCalendarById($calendarId);
+
+ $calendar = new Calendar($this->backend, $calendarInfo, $l10n, $config, $logger);
+
+ $this->backend->updateShares(
+ shareable: $calendar,
+ add: [
+ ['href' => $principalGroup, 'readOnly' => false]
+ ],
+ remove: []
+ );
+
+ $this->backend->unshare(
+ shareable: $calendar,
+ principal: $principalUser
+ );
+
+ }
}
diff --git a/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php b/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php
index 9956c17fff3..e25cc099bd6 100644
--- a/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalendarHomeTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -22,21 +24,11 @@ use Sabre\DAV\MkCol;
use Test\TestCase;
class CalendarHomeTest extends TestCase {
-
- /** @var CalDavBackend | MockObject */
- private $backend;
-
- /** @var array */
- private $principalInfo = [];
-
- /** @var PluginManager */
- private $pluginManager;
-
- /** @var CalendarHome */
- private $calendarHome;
-
- /** @var MockObject|LoggerInterface */
- private $logger;
+ private CalDavBackend&MockObject $backend;
+ private array $principalInfo = [];
+ private PluginManager&MockObject $pluginManager;
+ private LoggerInterface&MockObject $logger;
+ private CalendarHome $calendarHome;
protected function setUp(): void {
parent::setUp();
@@ -62,7 +54,7 @@ class CalendarHomeTest extends TestCase {
}
public function testCreateCalendarValidName(): void {
- /** @var MkCol | MockObject $mkCol */
+ /** @var MkCol&MockObject $mkCol */
$mkCol = $this->createMock(MkCol::class);
$mkCol->method('getResourceType')
@@ -82,7 +74,7 @@ class CalendarHomeTest extends TestCase {
$this->expectException(\Sabre\DAV\Exception\MethodNotAllowed::class);
$this->expectExceptionMessage('The resource you tried to create has a reserved name');
- /** @var MkCol | MockObject $mkCol */
+ /** @var MkCol&MockObject $mkCol */
$mkCol = $this->createMock(MkCol::class);
$this->calendarHome->createExtendedCollection('contact_birthdays', $mkCol);
@@ -92,7 +84,7 @@ class CalendarHomeTest extends TestCase {
$this->expectException(\Sabre\DAV\Exception\MethodNotAllowed::class);
$this->expectExceptionMessage('The resource you tried to create has a reserved name');
- /** @var MkCol | MockObject $mkCol */
+ /** @var MkCol&MockObject $mkCol */
$mkCol = $this->createMock(MkCol::class);
$this->calendarHome->createExtendedCollection('app-generated--example--foo-1', $mkCol);
diff --git a/apps/dav/tests/unit/CalDAV/CalendarImplTest.php b/apps/dav/tests/unit/CalDAV/CalendarImplTest.php
index ee9b85fafe8..d6a8f3b910e 100644
--- a/apps/dav/tests/unit/CalDAV/CalendarImplTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalendarImplTest.php
@@ -1,10 +1,13 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\DAV\Tests\unit\CalDAV;
+use Generator;
use OCA\DAV\CalDAV\Auth\CustomPrincipalPlugin;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\CalDAV\Calendar;
@@ -20,24 +23,18 @@ use Sabre\VObject\ITip\Message;
use Sabre\VObject\Reader;
class CalendarImplTest extends \Test\TestCase {
- /** @var CalendarImpl */
- private $calendarImpl;
-
- /** @var Calendar | \PHPUnit\Framework\MockObject\MockObject */
- private $calendar;
-
- /** @var array */
- private $calendarInfo;
-
- /** @var CalDavBackend | \PHPUnit\Framework\MockObject\MockObject */
- private $backend;
+ private Calendar&MockObject $calendar;
+ private array $calendarInfo;
+ private CalDavBackend&MockObject $backend;
+ private CalendarImpl $calendarImpl;
+ private array $mockExportCollection;
protected function setUp(): void {
parent::setUp();
$this->calendar = $this->createMock(Calendar::class);
$this->calendarInfo = [
- 'id' => 'fancy_id_123',
+ 'id' => 1,
'{DAV:}displayname' => 'user readable name 123',
'{http://apple.com/ns/ical/}calendar-color' => '#AABBCC',
'uri' => '/this/is/a/uri',
@@ -45,13 +42,16 @@ class CalendarImplTest extends \Test\TestCase {
];
$this->backend = $this->createMock(CalDavBackend::class);
- $this->calendarImpl = new CalendarImpl($this->calendar,
- $this->calendarInfo, $this->backend);
+ $this->calendarImpl = new CalendarImpl(
+ $this->calendar,
+ $this->calendarInfo,
+ $this->backend
+ );
}
public function testGetKey(): void {
- $this->assertEquals($this->calendarImpl->getKey(), 'fancy_id_123');
+ $this->assertEquals($this->calendarImpl->getKey(), 1);
}
public function testGetDisplayname(): void {
@@ -198,8 +198,8 @@ EOF;
/** @var \Sabre\DAVACL\Plugin|MockObject $schedulingPlugin */
$aclPlugin = $this->createMock(\Sabre\DAVACL\Plugin::class);
- $server =
- $this->createMock(Server::class);
+ $server
+ = $this->createMock(Server::class);
$server->expects($this->any())
->method('getPlugin')
->willReturnMap([
@@ -261,4 +261,48 @@ EOF;
$iTipMessage->message = $vObject;
return $iTipMessage;
}
+
+ protected function mockExportGenerator(): Generator {
+ foreach ($this->mockExportCollection as $entry) {
+ yield $entry;
+ }
+ }
+
+ public function testExport(): void {
+ // Arrange
+ // construct calendar with a 1 hour event and same start/end time zones
+ $vCalendar = new VCalendar();
+ /** @var VEvent $vEvent */
+ $vEvent = $vCalendar->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('SUMMARY', 'Test Recurrence Event');
+ $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
+ $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
+ 'CN' => 'Attendee One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+ // construct data store return
+ $this->mockExportCollection[] = [
+ 'id' => 1,
+ 'calendardata' => $vCalendar->serialize()
+ ];
+ $this->backend->expects($this->once())
+ ->method('exportCalendar')
+ ->with(1, $this->backend::CALENDAR_TYPE_CALENDAR, null)
+ ->willReturn($this->mockExportGenerator());
+
+ // Act
+ foreach ($this->calendarImpl->export(null) as $entry) {
+ $exported[] = $entry;
+ }
+
+ // Assert
+ $this->assertCount(1, $exported, 'Invalid exported items count');
+ }
+
}
diff --git a/apps/dav/tests/unit/CalDAV/CalendarManagerTest.php b/apps/dav/tests/unit/CalDAV/CalendarManagerTest.php
index 63d92dff40d..e8159ffe07c 100644
--- a/apps/dav/tests/unit/CalDAV/CalendarManagerTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalendarManagerTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -16,20 +18,11 @@ use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
class CalendarManagerTest extends \Test\TestCase {
- /** @var CalDavBackend | MockObject */
- private $backend;
-
- /** @var IL10N | MockObject */
- private $l10n;
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var CalendarManager */
- private $manager;
-
- /** @var MockObject|LoggerInterface */
- private $logger;
+ private CalDavBackend&MockObject $backend;
+ private IL10N&MockObject $l10n;
+ private IConfig&MockObject $config;
+ private LoggerInterface&MockObject $logger;
+ private CalendarManager $manager;
protected function setUp(): void {
parent::setUp();
@@ -54,7 +47,7 @@ class CalendarManagerTest extends \Test\TestCase {
['id' => 456, 'uri' => 'blablub2'],
]);
- /** @var IManager | MockObject $calendarManager */
+ /** @var IManager&MockObject $calendarManager */
$calendarManager = $this->createMock(Manager::class);
$registeredIds = [];
$calendarManager->expects($this->exactly(2))
diff --git a/apps/dav/tests/unit/CalDAV/CalendarTest.php b/apps/dav/tests/unit/CalDAV/CalendarTest.php
index 6433af8c340..0eff72c5c3d 100644
--- a/apps/dav/tests/unit/CalDAV/CalendarTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalendarTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -18,20 +20,13 @@ use Sabre\VObject\Reader;
use Test\TestCase;
class CalendarTest extends TestCase {
-
- /** @var IL10N */
- protected $l10n;
-
- /** @var IConfig */
- protected $config;
-
- /** @var MockObject|LoggerInterface */
- protected $logger;
+ protected IL10N&MockObject $l10n;
+ protected IConfig&MockObject $config;
+ protected LoggerInterface&MockObject $logger;
protected function setUp(): void {
parent::setUp();
- $this->l10n = $this->getMockBuilder(IL10N::class)
- ->disableOriginalConstructor()->getMock();
+ $this->l10n = $this->createMock(IL10N::class);
$this->config = $this->createMock(IConfig::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->l10n
@@ -43,12 +38,13 @@ class CalendarTest extends TestCase {
}
public function testDelete(): void {
- /** @var MockObject | CalDavBackend $backend */
- $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
- $backend->expects($this->once())->method('updateShares');
- $backend->expects($this->any())->method('getShares')->willReturn([
- ['href' => 'principal:user2']
- ]);
+ /** @var CalDavBackend&MockObject $backend */
+ $backend = $this->createMock(CalDavBackend::class);
+ $backend->expects($this->never())
+ ->method('updateShares');
+ $backend->expects($this->once())
+ ->method('unshare');
+
$calendarInfo = [
'{http://owncloud.org/ns}owner-principal' => 'user1',
'principaluri' => 'user2',
@@ -61,12 +57,13 @@ class CalendarTest extends TestCase {
public function testDeleteFromGroup(): void {
- /** @var MockObject | CalDavBackend $backend */
- $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
- $backend->expects($this->once())->method('updateShares');
- $backend->expects($this->any())->method('getShares')->willReturn([
- ['href' => 'principal:group2']
- ]);
+ /** @var CalDavBackend&MockObject $backend */
+ $backend = $this->createMock(CalDavBackend::class);
+ $backend->expects($this->never())
+ ->method('updateShares');
+ $backend->expects($this->once())
+ ->method('unshare');
+
$calendarInfo = [
'{http://owncloud.org/ns}owner-principal' => 'user1',
'principaluri' => 'user2',
@@ -78,7 +75,7 @@ class CalendarTest extends TestCase {
}
public function testDeleteOwn(): void {
- /** @var MockObject | CalDavBackend $backend */
+ /** @var CalDavBackend&MockObject $backend */
$backend = $this->createMock(CalDavBackend::class);
$backend->expects($this->never())->method('updateShares');
$backend->expects($this->never())->method('getShares');
@@ -99,7 +96,7 @@ class CalendarTest extends TestCase {
}
public function testDeleteBirthdayCalendar(): void {
- /** @var MockObject | CalDavBackend $backend */
+ /** @var CalDavBackend&MockObject $backend */
$backend = $this->createMock(CalDavBackend::class);
$backend->expects($this->once())->method('deleteCalendar')
->with(666);
@@ -120,7 +117,7 @@ class CalendarTest extends TestCase {
$c->delete();
}
- public function dataPropPatch() {
+ public static function dataPropPatch(): array {
return [
['user1', 'user2', [], true],
['user1', 'user2', [
@@ -150,9 +147,9 @@ class CalendarTest extends TestCase {
/**
* @dataProvider dataPropPatch
*/
- public function testPropPatch($ownerPrincipal, $principalUri, $mutations, $shared): void {
- /** @var MockObject | CalDavBackend $backend */
- $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
+ public function testPropPatch(string $ownerPrincipal, string $principalUri, array $mutations, bool $shared): void {
+ /** @var CalDavBackend&MockObject $backend */
+ $backend = $this->createMock(CalDavBackend::class);
$calendarInfo = [
'{http://owncloud.org/ns}owner-principal' => $ownerPrincipal,
'principaluri' => $principalUri,
@@ -175,8 +172,8 @@ class CalendarTest extends TestCase {
* @dataProvider providesReadOnlyInfo
*/
public function testAcl($expectsWrite, $readOnlyValue, $hasOwnerSet, $uri = 'default'): void {
- /** @var MockObject | CalDavBackend $backend */
- $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
+ /** @var CalDavBackend&MockObject $backend */
+ $backend = $this->createMock(CalDavBackend::class);
$backend->expects($this->any())->method('applyShareAcl')->willReturnArgument(1);
$calendarInfo = [
'principaluri' => 'user2',
@@ -261,7 +258,7 @@ class CalendarTest extends TestCase {
$this->assertEquals($expectedAcl, $childAcl);
}
- public function providesReadOnlyInfo() {
+ public static function providesReadOnlyInfo(): array {
return [
'read-only property not set' => [true, null, true],
'read-only property is false' => [true, false, true],
@@ -275,16 +272,14 @@ class CalendarTest extends TestCase {
/**
* @dataProvider providesConfidentialClassificationData
- * @param int $expectedChildren
- * @param bool $isShared
*/
- public function testPrivateClassification($expectedChildren, $isShared): void {
+ public function testPrivateClassification(int $expectedChildren, bool $isShared): void {
$calObject0 = ['uri' => 'event-0', 'classification' => CalDavBackend::CLASSIFICATION_PUBLIC];
$calObject1 = ['uri' => 'event-1', 'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL];
$calObject2 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PRIVATE];
- /** @var MockObject | CalDavBackend $backend */
- $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
+ /** @var CalDavBackend&MockObject $backend */
+ $backend = $this->createMock(CalDavBackend::class);
$backend->expects($this->any())->method('getCalendarObjects')->willReturn([
$calObject0, $calObject1, $calObject2
]);
@@ -317,10 +312,8 @@ class CalendarTest extends TestCase {
/**
* @dataProvider providesConfidentialClassificationData
- * @param int $expectedChildren
- * @param bool $isShared
*/
- public function testConfidentialClassification($expectedChildren, $isShared): void {
+ public function testConfidentialClassification(int $expectedChildren, bool $isShared): void {
$start = '20160609';
$end = '20160610';
@@ -370,8 +363,8 @@ EOD;
$calObject1 = ['uri' => 'event-1', 'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL, 'calendardata' => $calData];
$calObject2 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PRIVATE];
- /** @var MockObject | CalDavBackend $backend */
- $backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
+ /** @var CalDavBackend&MockObject $backend */
+ $backend = $this->createMock(CalDavBackend::class);
$backend->expects($this->any())->method('getCalendarObjects')->willReturn([
$calObject0, $calObject1, $calObject2
]);
@@ -435,7 +428,7 @@ EOD;
}
}
- public function providesConfidentialClassificationData() {
+ public static function providesConfidentialClassificationData(): array {
return [
[3, false],
[2, true]
@@ -538,7 +531,7 @@ EOD;
'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL,
'calendardata' => $confidentialObjectData];
- /** @var MockObject | CalDavBackend $backend */
+ /** @var CalDavBackend&MockObject $backend */
$backend = $this->createMock(CalDavBackend::class);
$backend->expects($this->any())
->method('getCalendarObjects')
@@ -617,7 +610,7 @@ EOD;
$this->fixLinebreak($confidentialObjectCleaned));
}
- private function fixLinebreak($str) {
+ private function fixLinebreak(string $str): string {
return preg_replace('~(*BSR_ANYCRLF)\R~', "\r\n", $str);
}
}
diff --git a/apps/dav/tests/unit/CalDAV/EventComparisonServiceTest.php b/apps/dav/tests/unit/CalDAV/EventComparisonServiceTest.php
index 43a7180647f..90b6f9ec0db 100644
--- a/apps/dav/tests/unit/CalDAV/EventComparisonServiceTest.php
+++ b/apps/dav/tests/unit/CalDAV/EventComparisonServiceTest.php
@@ -14,8 +14,7 @@ use Sabre\VObject\Component\VCalendar;
use Test\TestCase;
class EventComparisonServiceTest extends TestCase {
- /** @var EventComparisonService */
- private $eventComparisonService;
+ private EventComparisonService $eventComparisonService;
protected function setUp(): void {
$this->eventComparisonService = new EventComparisonService();
diff --git a/apps/dav/tests/unit/CalDAV/EventReaderTest.php b/apps/dav/tests/unit/CalDAV/EventReaderTest.php
index a5ce3e3f2c2..3bd4f9d85c2 100644
--- a/apps/dav/tests/unit/CalDAV/EventReaderTest.php
+++ b/apps/dav/tests/unit/CalDAV/EventReaderTest.php
@@ -23,7 +23,7 @@ class EventReaderTest extends TestCase {
private VCalendar $vCalendar1e;
private VCalendar $vCalendar2;
private VCalendar $vCalendar3;
-
+
protected function setUp(): void {
parent::setUp();
@@ -151,7 +151,7 @@ class EventReaderTest extends TestCase {
'ROLE' => 'REQ-PARTICIPANT',
'RSVP' => 'TRUE'
]);
-
+
}
public function testConstructFromCalendarString(): void {
@@ -188,19 +188,19 @@ class EventReaderTest extends TestCase {
$er = new EventReader($this->vCalendar1a, $this->vCalendar1a->VEVENT[0]->UID->getValue());
// test set by constructor
$this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->startDateTime());
-
+
/** test day part event with different start/end time zone */
// construct event reader
$er = new EventReader($this->vCalendar1b, $this->vCalendar1b->VEVENT[0]->UID->getValue());
// test set by constructor
$this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->startDateTime());
-
+
/** test day part event with global time zone */
// construct event reader
$er = new EventReader($this->vCalendar1c, $this->vCalendar1c->VEVENT[0]->UID->getValue());
// test set by constructor
$this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->startDateTime());
-
+
/** test day part event with no time zone */
// construct event reader
$er = new EventReader($this->vCalendar1d, $this->vCalendar1d->VEVENT[0]->UID->getValue());
@@ -212,13 +212,13 @@ class EventReaderTest extends TestCase {
$er = new EventReader($this->vCalendar1e, $this->vCalendar1e->VEVENT[0]->UID->getValue());
// test set by constructor
$this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->startDateTime());
-
+
/** test full day event */
// construct event reader
$er = new EventReader($this->vCalendar2, $this->vCalendar2->VEVENT[0]->UID->getValue());
// test set by constructor
$this->assertEquals((new \DateTime('20240701T000000', (new DateTimeZone('America/Toronto')))), $er->startDateTime());
-
+
/** test multi day event */
// construct event reader
$er = new EventReader($this->vCalendar3, $this->vCalendar3->VEVENT[0]->UID->getValue());
@@ -234,7 +234,7 @@ class EventReaderTest extends TestCase {
$er = new EventReader($this->vCalendar1a, $this->vCalendar1a->VEVENT[0]->UID->getValue());
// test set by constructor
$this->assertEquals((new DateTimeZone('America/Toronto')), $er->startTimeZone());
-
+
/** test day part event with different start/end time zone */
// construct event reader
$er = new EventReader($this->vCalendar1b, $this->vCalendar1b->VEVENT[0]->UID->getValue());
@@ -264,7 +264,7 @@ class EventReaderTest extends TestCase {
$er = new EventReader($this->vCalendar2, $this->vCalendar2->VEVENT[0]->UID->getValue());
// test set by constructor
$this->assertEquals((new DateTimeZone('America/Toronto')), $er->startTimeZone());
-
+
/** test multi day event */
// construct event reader
$er = new EventReader($this->vCalendar3, $this->vCalendar3->VEVENT[0]->UID->getValue());
@@ -280,19 +280,19 @@ class EventReaderTest extends TestCase {
$er = new EventReader($this->vCalendar1a, $this->vCalendar1a->VEVENT[0]->UID->getValue());
// test set by constructor
$this->assertEquals((new \DateTime('20240701T090000', (new DateTimeZone('America/Toronto')))), $er->endDateTime());
-
+
/** test day part event with different start/end time zone */
// construct event reader
$er = new EventReader($this->vCalendar1b, $this->vCalendar1b->VEVENT[0]->UID->getValue());
// test set by constructor
$this->assertEquals((new \DateTime('20240701T090000', (new DateTimeZone('America/Vancouver')))), $er->endDateTime());
-
+
/** test day part event with global time zone */
// construct event reader
$er = new EventReader($this->vCalendar1c, $this->vCalendar1c->VEVENT[0]->UID->getValue());
// test set by constructor
$this->assertEquals((new \DateTime('20240701T090000', (new DateTimeZone('America/Toronto')))), $er->endDateTime());
-
+
/** test day part event with no time zone */
// construct event reader
$er = new EventReader($this->vCalendar1d, $this->vCalendar1d->VEVENT[0]->UID->getValue());
@@ -304,13 +304,13 @@ class EventReaderTest extends TestCase {
$er = new EventReader($this->vCalendar1e, $this->vCalendar1e->VEVENT[0]->UID->getValue());
// test set by constructor
$this->assertEquals((new \DateTime('20240701T090000', (new DateTimeZone('America/Toronto')))), $er->endDateTime());
-
+
/** test full day event */
// construct event reader
$er = new EventReader($this->vCalendar2, $this->vCalendar2->VEVENT[0]->UID->getValue());
// test set by constructor
$this->assertEquals((new \DateTime('20240702T000000', (new DateTimeZone('America/Toronto')))), $er->endDateTime());
-
+
/** test multi day event */
// construct event reader
$er = new EventReader($this->vCalendar3, $this->vCalendar3->VEVENT[0]->UID->getValue());
@@ -326,7 +326,7 @@ class EventReaderTest extends TestCase {
$er = new EventReader($this->vCalendar1a, $this->vCalendar1a->VEVENT[0]->UID->getValue());
// test set by constructor
$this->assertEquals((new DateTimeZone('America/Toronto')), $er->endTimeZone());
-
+
/** test day part event with different start/end time zone */
// construct event reader
$er = new EventReader($this->vCalendar1b, $this->vCalendar1b->VEVENT[0]->UID->getValue());
@@ -356,7 +356,7 @@ class EventReaderTest extends TestCase {
$er = new EventReader($this->vCalendar2, $this->vCalendar2->VEVENT[0]->UID->getValue());
// test set by constructor
$this->assertEquals((new DateTimeZone('America/Toronto')), $er->endTimeZone());
-
+
/** test multi day event */
// construct event reader
$er = new EventReader($this->vCalendar3, $this->vCalendar3->VEVENT[0]->UID->getValue());
diff --git a/apps/dav/tests/unit/CalDAV/Export/ExportServiceTest.php b/apps/dav/tests/unit/CalDAV/Export/ExportServiceTest.php
new file mode 100644
index 00000000000..838dfc18f2f
--- /dev/null
+++ b/apps/dav/tests/unit/CalDAV/Export/ExportServiceTest.php
@@ -0,0 +1,81 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\DAV\Tests\unit\CalDAV\Export;
+
+use Generator;
+use OCA\DAV\CalDAV\Export\ExportService;
+use OCP\Calendar\CalendarExportOptions;
+use OCP\Calendar\ICalendarExport;
+use OCP\ServerVersion;
+use PHPUnit\Framework\MockObject\MockObject;
+use Sabre\VObject\Component\VCalendar;
+
+class ExportServiceTest extends \Test\TestCase {
+ private ServerVersion&MockObject $serverVersion;
+ private ExportService $service;
+ private ICalendarExport&MockObject $calendar;
+ private array $mockExportCollection;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->serverVersion = $this->createMock(ServerVersion::class);
+ $this->serverVersion->method('getVersionString')
+ ->willReturn('32.0.0.0');
+ $this->service = new ExportService($this->serverVersion);
+ $this->calendar = $this->createMock(ICalendarExport::class);
+
+ }
+
+ protected function mockGenerator(): Generator {
+ foreach ($this->mockExportCollection as $entry) {
+ yield $entry;
+ }
+ }
+
+ public function testExport(): void {
+ // Arrange
+ // construct calendar with a 1 hour event and same start/end time zones
+ $vCalendar = new VCalendar();
+ /** @var \Sabre\VObject\Component\VEvent $vEvent */
+ $vEvent = $vCalendar->add('VEVENT', []);
+ $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc');
+ $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Toronto']);
+ $vEvent->add('SUMMARY', 'Test Recurrence Event');
+ $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']);
+ $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [
+ 'CN' => 'Attendee One',
+ 'CUTYPE' => 'INDIVIDUAL',
+ 'PARTSTAT' => 'NEEDS-ACTION',
+ 'ROLE' => 'REQ-PARTICIPANT',
+ 'RSVP' => 'TRUE'
+ ]);
+ // construct calendar return
+ $options = new CalendarExportOptions();
+ $this->mockExportCollection[] = $vCalendar;
+ $this->calendar->expects($this->once())
+ ->method('export')
+ ->with($options)
+ ->willReturn($this->mockGenerator());
+
+ // Act
+ $document = '';
+ foreach ($this->service->export($this->calendar, $options) as $chunk) {
+ $document .= $chunk;
+ }
+
+ // Assert
+ $this->assertStringContainsString('BEGIN:VCALENDAR', $document, 'Exported document calendar start missing');
+ $this->assertStringContainsString('BEGIN:VEVENT', $document, 'Exported document event start missing');
+ $this->assertStringContainsString('END:VEVENT', $document, 'Exported document event end missing');
+ $this->assertStringContainsString('END:VCALENDAR', $document, 'Exported document calendar end missing');
+
+ }
+
+}
diff --git a/apps/dav/tests/unit/CalDAV/Integration/ExternalCalendarTest.php b/apps/dav/tests/unit/CalDAV/Integration/ExternalCalendarTest.php
index 778df5697f0..5bf247719f7 100644
--- a/apps/dav/tests/unit/CalDAV/Integration/ExternalCalendarTest.php
+++ b/apps/dav/tests/unit/CalDAV/Integration/ExternalCalendarTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -6,16 +8,17 @@
namespace OCA\DAV\Tests\unit\CalDAV\Integration;
use OCA\DAV\CalDAV\Integration\ExternalCalendar;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class ExternalCalendarTest extends TestCase {
- private $abstractExternalCalendar;
+ private ExternalCalendar&MockObject $abstractExternalCalendar;
protected function setUp(): void {
parent::setUp();
- $this->abstractExternalCalendar =
- $this->getMockForAbstractClass(ExternalCalendar::class, ['example-app-id', 'calendar-uri-in-backend']);
+ $this->abstractExternalCalendar
+ = $this->getMockForAbstractClass(ExternalCalendar::class, ['example-app-id', 'calendar-uri-in-backend']);
}
public function testGetName():void {
@@ -39,7 +42,7 @@ class ExternalCalendarTest extends TestCase {
$this->abstractExternalCalendar->setName('other-name');
}
- public function createDirectory():void {
+ public function createDirectory(): void {
// Check that the method is final and can't be overridden by other classes
$reflectionMethod = new \ReflectionMethod(ExternalCalendar::class, 'createDirectory');
$this->assertTrue($reflectionMethod->isFinal());
@@ -73,7 +76,7 @@ class ExternalCalendarTest extends TestCase {
ExternalCalendar::splitAppGeneratedCalendarUri($name);
}
- public function splitAppGeneratedCalendarUriDataProvider():array {
+ public static function splitAppGeneratedCalendarUriDataProvider():array {
return [
['personal'],
['foo_shared_by_admin'],
diff --git a/apps/dav/tests/unit/CalDAV/Listener/CalendarPublicationListenerTest.php b/apps/dav/tests/unit/CalDAV/Listener/CalendarPublicationListenerTest.php
index b55359cd208..3ba0b832593 100644
--- a/apps/dav/tests/unit/CalDAV/Listener/CalendarPublicationListenerTest.php
+++ b/apps/dav/tests/unit/CalDAV/Listener/CalendarPublicationListenerTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -15,20 +17,11 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class CalendarPublicationListenerTest extends TestCase {
-
- /** @var Backend|MockObject */
- private $activityBackend;
-
- /** @var LoggerInterface|MockObject */
- private $logger;
-
+ private Backend&MockObject $activityBackend;
+ private LoggerInterface&MockObject $logger;
private CalendarPublicationListener $calendarPublicationListener;
-
- /** @var CalendarPublishedEvent|MockObject */
- private $publicationEvent;
-
- /** @var CalendarUnpublishedEvent|MockObject */
- private $unpublicationEvent;
+ private CalendarPublishedEvent&MockObject $publicationEvent;
+ private CalendarUnpublishedEvent&MockObject $unpublicationEvent;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/CalDAV/Listener/CalendarShareUpdateListenerTest.php b/apps/dav/tests/unit/CalDAV/Listener/CalendarShareUpdateListenerTest.php
index b8414ecd695..d5697a862db 100644
--- a/apps/dav/tests/unit/CalDAV/Listener/CalendarShareUpdateListenerTest.php
+++ b/apps/dav/tests/unit/CalDAV/Listener/CalendarShareUpdateListenerTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -14,17 +16,10 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class CalendarShareUpdateListenerTest extends TestCase {
-
- /** @var Backend|MockObject */
- private $activityBackend;
-
- /** @var LoggerInterface|MockObject */
- private $logger;
-
+ private Backend&MockObject $activityBackend;
+ private LoggerInterface&MockObject $logger;
private CalendarShareUpdateListener $calendarPublicationListener;
-
- /** @var CalendarShareUpdatedEvent|MockObject */
- private $event;
+ private CalendarShareUpdatedEvent&MockObject $event;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/CalDAV/Listener/SubscriptionListenerTest.php b/apps/dav/tests/unit/CalDAV/Listener/SubscriptionListenerTest.php
index 589e659b9ea..cbfdfd6b9b7 100644
--- a/apps/dav/tests/unit/CalDAV/Listener/SubscriptionListenerTest.php
+++ b/apps/dav/tests/unit/CalDAV/Listener/SubscriptionListenerTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -18,26 +20,13 @@ 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 RefreshWebcalService&MockObject $refreshWebcalService;
+ private Backend&MockObject $reminderBackend;
+ private IJobList&MockObject $jobList;
+ private LoggerInterface&MockObject $logger;
private SubscriptionListener $calendarPublicationListener;
-
- /** @var SubscriptionCreatedEvent|MockObject */
- private $subscriptionCreatedEvent;
-
- /** @var SubscriptionDeletedEvent|MockObject */
- private $subscriptionDeletedEvent;
+ private SubscriptionCreatedEvent&MockObject $subscriptionCreatedEvent;
+ private SubscriptionDeletedEvent&MockObject $subscriptionDeletedEvent;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/CalDAV/OutboxTest.php b/apps/dav/tests/unit/CalDAV/OutboxTest.php
index def2bd80157..cc0a3f0405f 100644
--- a/apps/dav/tests/unit/CalDAV/OutboxTest.php
+++ b/apps/dav/tests/unit/CalDAV/OutboxTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -7,15 +9,12 @@ namespace OCA\DAV\Tests\unit\CalDAV;
use OCA\DAV\CalDAV\Outbox;
use OCP\IConfig;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class OutboxTest extends TestCase {
-
- /** @var IConfig */
- private $config;
-
- /** @var Outbox */
- private $outbox;
+ private IConfig&MockObject $config;
+ private Outbox $outbox;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/CalDAV/PluginTest.php b/apps/dav/tests/unit/CalDAV/PluginTest.php
index 0915fdf2646..647e4b0da81 100644
--- a/apps/dav/tests/unit/CalDAV/PluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/PluginTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -9,8 +11,7 @@ use OCA\DAV\CalDAV\Plugin;
use Test\TestCase;
class PluginTest extends TestCase {
- /** @var Plugin */
- private $plugin;
+ private Plugin $plugin;
protected function setUp(): void {
parent::setUp();
@@ -18,7 +19,7 @@ class PluginTest extends TestCase {
$this->plugin = new Plugin();
}
- public function linkProvider() {
+ public static function linkProvider(): array {
return [
[
'principals/users/MyUserName',
@@ -37,11 +38,8 @@ class PluginTest extends TestCase {
/**
* @dataProvider linkProvider
- *
- * @param $input
- * @param $expected
*/
- public function testGetCalendarHomeForPrincipal($input, $expected): void {
+ public function testGetCalendarHomeForPrincipal(string $input, string $expected): void {
$this->assertSame($expected, $this->plugin->getCalendarHomeForPrincipal($input));
}
diff --git a/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php b/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php
index 075681eff7f..6acceed6f64 100644
--- a/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php
+++ b/apps/dav/tests/unit/CalDAV/PublicCalendarRootTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -18,6 +20,7 @@ use OCP\IL10N;
use OCP\IUserManager;
use OCP\Security\ISecureRandom;
use OCP\Server;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Test\TestCase;
@@ -30,25 +33,15 @@ use Test\TestCase;
*/
class PublicCalendarRootTest extends TestCase {
public const UNIT_TEST_USER = '';
- /** @var CalDavBackend */
- private $backend;
- /** @var PublicCalendarRoot */
- private $publicCalendarRoot;
- /** @var IL10N */
- private $l10n;
- /** @var Principal|\PHPUnit\Framework\MockObject\MockObject */
- private $principal;
- /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $userManager;
- /** @var IGroupManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $groupManager;
- /** @var IConfig */
- protected $config;
-
- /** @var ISecureRandom */
- private $random;
- /** @var LoggerInterface */
- private $logger;
+ private CalDavBackend $backend;
+ private PublicCalendarRoot $publicCalendarRoot;
+ private IL10N&MockObject $l10n;
+ private Principal&MockObject $principal;
+ protected IUserManager&MockObject $userManager;
+ protected IGroupManager&MockObject $groupManager;
+ protected IConfig&MockObject $config;
+ private ISecureRandom $random;
+ private LoggerInterface&MockObject $logger;
protected function setUp(): void {
parent::setUp();
@@ -82,8 +75,7 @@ class PublicCalendarRootTest extends TestCase {
$sharingBackend,
false,
);
- $this->l10n = $this->getMockBuilder(IL10N::class)
- ->disableOriginalConstructor()->getMock();
+ $this->l10n = $this->createMock(IL10N::class);
$this->config = $this->createMock(IConfig::class);
$this->publicCalendarRoot = new PublicCalendarRoot($this->backend,
@@ -134,10 +126,7 @@ class PublicCalendarRootTest extends TestCase {
$this->assertSame([], $calendarResults);
}
- /**
- * @return Calendar
- */
- protected function createPublicCalendar() {
+ protected function createPublicCalendar(): Calendar {
$this->backend->createCalendar(self::UNIT_TEST_USER, 'Example', []);
$calendarInfo = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER)[0];
diff --git a/apps/dav/tests/unit/CalDAV/PublicCalendarTest.php b/apps/dav/tests/unit/CalDAV/PublicCalendarTest.php
index 0609892c279..7e8f714ef42 100644
--- a/apps/dav/tests/unit/CalDAV/PublicCalendarTest.php
+++ b/apps/dav/tests/unit/CalDAV/PublicCalendarTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -16,15 +18,13 @@ class PublicCalendarTest extends CalendarTest {
/**
* @dataProvider providesConfidentialClassificationData
- * @param int $expectedChildren
- * @param bool $isShared
*/
- public function testPrivateClassification($expectedChildren, $isShared): void {
+ public function testPrivateClassification(int $expectedChildren, bool $isShared): void {
$calObject0 = ['uri' => 'event-0', 'classification' => CalDavBackend::CLASSIFICATION_PUBLIC];
$calObject1 = ['uri' => 'event-1', 'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL];
$calObject2 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PRIVATE];
- /** @var MockObject | CalDavBackend $backend */
+ /** @var CalDavBackend&MockObject $backend */
$backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
$backend->expects($this->any())->method('getCalendarObjects')->willReturn([
$calObject0, $calObject1, $calObject2
@@ -44,9 +44,9 @@ class PublicCalendarTest extends CalendarTest {
'id' => 666,
'uri' => 'cal',
];
- /** @var MockObject | IConfig $config */
+ /** @var IConfig&MockObject $config */
$config = $this->createMock(IConfig::class);
- /** @var MockObject | LoggerInterface $logger */
+ /** @var LoggerInterface&MockObject $logger */
$logger = $this->createMock(LoggerInterface::class);
$c = new PublicCalendar($backend, $calendarInfo, $this->l10n, $config, $logger);
$children = $c->getChildren();
@@ -59,10 +59,8 @@ class PublicCalendarTest extends CalendarTest {
/**
* @dataProvider providesConfidentialClassificationData
- * @param int $expectedChildren
- * @param bool $isShared
*/
- public function testConfidentialClassification($expectedChildren, $isShared): void {
+ public function testConfidentialClassification(int $expectedChildren, bool $isShared): void {
$start = '20160609';
$end = '20160610';
@@ -112,7 +110,7 @@ EOD;
$calObject1 = ['uri' => 'event-1', 'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL, 'calendardata' => $calData];
$calObject2 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PRIVATE];
- /** @var MockObject | CalDavBackend $backend */
+ /** @var CalDavBackend&MockObject $backend */
$backend = $this->getMockBuilder(CalDavBackend::class)->disableOriginalConstructor()->getMock();
$backend->expects($this->any())->method('getCalendarObjects')->willReturn([
$calObject0, $calObject1, $calObject2
@@ -132,9 +130,9 @@ EOD;
'id' => 666,
'uri' => 'cal',
];
- /** @var MockObject | IConfig $config */
+ /** @var IConfig&MockObject $config */
$config = $this->createMock(IConfig::class);
- /** @var MockObject | LoggerInterface $logger */
+ /** @var LoggerInterface&MockObject $logger */
$logger = $this->createMock(LoggerInterface::class);
$c = new PublicCalendar($backend, $calendarInfo, $this->l10n, $config, $logger);
diff --git a/apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php b/apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php
index 769e1537646..5344ec5d7cd 100644
--- a/apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php
+++ b/apps/dav/tests/unit/CalDAV/Publishing/PublisherTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -43,9 +45,9 @@ class PublisherTest extends TestCase {
}
- protected $elementMap = [];
- protected $namespaceMap = ['DAV:' => 'd'];
- protected $contextUri = '/';
+ protected array $elementMap = [];
+ protected array $namespaceMap = ['DAV:' => 'd'];
+ protected string $contextUri = '/';
private function write($input) {
$writer = new Writer();
diff --git a/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php b/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php
index 8aecdf7f0dd..ec2ae37a929 100644
--- a/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php
+++ b/apps/dav/tests/unit/CalDAV/Publishing/PublishingTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -10,6 +12,7 @@ use OCA\DAV\CalDAV\Publishing\PublishPlugin;
use OCP\IConfig;
use OCP\IRequest;
use OCP\IURLGenerator;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Server;
use Sabre\DAV\SimpleCollection;
use Sabre\HTTP\Request;
@@ -17,31 +20,21 @@ use Sabre\HTTP\Response;
use Test\TestCase;
class PublishingTest extends TestCase {
-
- /** @var PublishPlugin */
- private $plugin;
- /** @var Server */
- private $server;
- /** @var Calendar | \PHPUnit\Framework\MockObject\MockObject */
- private $book;
- /** @var IConfig | \PHPUnit\Framework\MockObject\MockObject */
- private $config;
- /** @var IURLGenerator | \PHPUnit\Framework\MockObject\MockObject */
- private $urlGenerator;
+ private PublishPlugin $plugin;
+ private Server $server;
+ private Calendar&MockObject $book;
+ private IConfig&MockObject $config;
+ private IURLGenerator&MockObject $urlGenerator;
protected function setUp(): void {
parent::setUp();
- $this->config = $this->getMockBuilder(IConfig::class)->
- disableOriginalConstructor()->
- getMock();
+ $this->config = $this->createMock(IConfig::class);
$this->config->expects($this->any())->method('getSystemValue')
->with($this->equalTo('secret'))
->willReturn('mysecret');
- $this->urlGenerator = $this->getMockBuilder(IURLGenerator::class)->
- disableOriginalConstructor()->
- getMock();
+ $this->urlGenerator = $this->createMock(IURLGenerator::class);
/** @var IRequest $request */
$this->plugin = new PublishPlugin($this->config, $this->urlGenerator);
@@ -49,9 +42,9 @@ class PublishingTest extends TestCase {
$root = new SimpleCollection('calendars');
$this->server = new Server($root);
/** @var SimpleCollection $node */
- $this->book = $this->getMockBuilder(Calendar::class)->
- disableOriginalConstructor()->
- getMock();
+ $this->book = $this->getMockBuilder(Calendar::class)
+ ->disableOriginalConstructor()
+ ->getMock();
$this->book->method('getName')->willReturn('cal1');
$root->addChild($this->book);
$this->plugin->initialize($this->server);
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/BackendTest.php b/apps/dav/tests/unit/CalDAV/Reminder/BackendTest.php
index e1a0485f8a9..356acf2dd7f 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/BackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/BackendTest.php
@@ -10,27 +10,20 @@ namespace OCA\DAV\Tests\unit\CalDAV\Reminder;
use OCA\DAV\CalDAV\Reminder\Backend as ReminderBackend;
use OCP\AppFramework\Utility\ITimeFactory;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class BackendTest extends TestCase {
-
- /**
- * Reminder Backend
- *
- * @var ReminderBackend|\PHPUnit\Framework\MockObject\MockObject
- */
- private $reminderBackend;
-
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
- private $timeFactory;
+ private ReminderBackend $reminderBackend;
+ private ITimeFactory&MockObject $timeFactory;
protected function setUp(): void {
parent::setUp();
$query = self::$realDatabase->getQueryBuilder();
- $query->delete('calendar_reminders')->execute();
- $query->delete('calendarobjects')->execute();
- $query->delete('calendars')->execute();
+ $query->delete('calendar_reminders')->executeStatement();
+ $query->delete('calendarobjects')->executeStatement();
+ $query->delete('calendars')->executeStatement();
$this->timeFactory = $this->createMock(ITimeFactory::class);
$this->reminderBackend = new ReminderBackend(self::$realDatabase, $this->timeFactory);
@@ -40,9 +33,11 @@ class BackendTest extends TestCase {
protected function tearDown(): void {
$query = self::$realDatabase->getQueryBuilder();
- $query->delete('calendar_reminders')->execute();
- $query->delete('calendarobjects')->execute();
- $query->delete('calendars')->execute();
+ $query->delete('calendar_reminders')->executeStatement();
+ $query->delete('calendarobjects')->executeStatement();
+ $query->delete('calendars')->executeStatement();
+
+ parent::tearDown();
}
@@ -235,7 +230,7 @@ class BackendTest extends TestCase {
$query = self::$realDatabase->getQueryBuilder();
$rows = $query->select('*')
->from('calendar_reminders')
- ->execute()
+ ->executeQuery()
->fetchAll();
$this->assertCount(4, $rows);
@@ -251,7 +246,7 @@ class BackendTest extends TestCase {
$row = $query->select('notification_date')
->from('calendar_reminders')
->where($query->expr()->eq('id', $query->createNamedParameter($reminderId)))
- ->execute()
+ ->executeQuery()
->fetch();
$this->assertEquals((int)$row['notification_date'], 123700);
@@ -266,7 +261,7 @@ class BackendTest extends TestCase {
'principaluri' => $query->createNamedParameter('principals/users/user001'),
'displayname' => $query->createNamedParameter('Displayname 123'),
])
- ->execute();
+ ->executeStatement();
$query = self::$realDatabase->getQueryBuilder();
$query->insert('calendars')
@@ -275,7 +270,7 @@ class BackendTest extends TestCase {
'principaluri' => $query->createNamedParameter('principals/users/user002'),
'displayname' => $query->createNamedParameter('Displayname 99'),
])
- ->execute();
+ ->executeStatement();
$query = self::$realDatabase->getQueryBuilder();
$query->insert('calendarobjects')
@@ -285,7 +280,7 @@ class BackendTest extends TestCase {
'calendarid' => $query->createNamedParameter(1),
'size' => $query->createNamedParameter(42),
])
- ->execute();
+ ->executeStatement();
$query = self::$realDatabase->getQueryBuilder();
$query->insert('calendarobjects')
@@ -295,7 +290,7 @@ class BackendTest extends TestCase {
'calendarid' => $query->createNamedParameter(1),
'size' => $query->createNamedParameter(42),
])
- ->execute();
+ ->executeStatement();
$query = self::$realDatabase->getQueryBuilder();
$query->insert('calendarobjects')
@@ -305,7 +300,7 @@ class BackendTest extends TestCase {
'calendarid' => $query->createNamedParameter(99),
'size' => $query->createNamedParameter(42),
])
- ->execute();
+ ->executeStatement();
$query = self::$realDatabase->getQueryBuilder();
$query->insert('calendar_reminders')
@@ -323,7 +318,7 @@ class BackendTest extends TestCase {
'notification_date' => $query->createNamedParameter(123456),
'is_repeat_based' => $query->createNamedParameter(0),
])
- ->execute();
+ ->executeStatement();
$query = self::$realDatabase->getQueryBuilder();
$query->insert('calendar_reminders')
@@ -341,7 +336,7 @@ class BackendTest extends TestCase {
'notification_date' => $query->createNamedParameter(123456),
'is_repeat_based' => $query->createNamedParameter(0),
])
- ->execute();
+ ->executeStatement();
$query = self::$realDatabase->getQueryBuilder();
$query->insert('calendar_reminders')
@@ -359,7 +354,7 @@ class BackendTest extends TestCase {
'notification_date' => $query->createNamedParameter(123499),
'is_repeat_based' => $query->createNamedParameter(0),
])
- ->execute();
+ ->executeStatement();
$query = self::$realDatabase->getQueryBuilder();
$query->insert('calendar_reminders')
@@ -377,6 +372,6 @@ class BackendTest extends TestCase {
'notification_date' => $query->createNamedParameter(123600),
'is_repeat_based' => $query->createNamedParameter(0),
])
- ->execute();
+ ->executeStatement();
}
}
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/AbstractNotificationProviderTest.php b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/AbstractNotificationProviderTestCase.php
index 60ef1df43d5..70b374298ea 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/AbstractNotificationProviderTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/AbstractNotificationProviderTestCase.php
@@ -14,44 +14,21 @@ use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\L10N\IFactory as L10NFactory;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\VObject\Component\VCalendar;
use Test\TestCase;
-abstract class AbstractNotificationProviderTest extends TestCase {
-
- /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
- protected $logger;
-
- /** @var L10NFactory|\PHPUnit\Framework\MockObject\MockObject */
- protected $l10nFactory;
-
- /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
- protected $l10n;
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- protected $urlGenerator;
-
- /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
- protected $config;
-
- /** @var AbstractProvider|\PHPUnit\Framework\MockObject\MockObject */
- protected $provider;
-
- /**
- * @var VCalendar
- */
- protected $vcalendar;
-
- /**
- * @var string
- */
- protected $calendarDisplayName;
-
- /**
- * @var IUser|\PHPUnit\Framework\MockObject\MockObject
- */
- protected $user;
+abstract class AbstractNotificationProviderTestCase extends TestCase {
+ protected LoggerInterface&MockObject $logger;
+ protected L10NFactory&MockObject $l10nFactory;
+ protected IL10N&MockObject $l10n;
+ protected IURLGenerator&MockObject $urlGenerator;
+ protected IConfig&MockObject $config;
+ protected AbstractProvider $provider;
+ protected VCalendar $vcalendar;
+ protected string $calendarDisplayName;
+ protected IUser&MockObject $user;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php
index 42eb0b0faa3..f7fbac2c407 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/EmailProviderTest.php
@@ -18,11 +18,9 @@ use OCP\Util;
use PHPUnit\Framework\MockObject\MockObject;
use Sabre\VObject\Component\VCalendar;
-class EmailProviderTest extends AbstractNotificationProviderTest {
+class EmailProviderTest extends AbstractNotificationProviderTestCase {
public const USER_EMAIL = 'frodo@hobb.it';
-
- /** @var IMailer|MockObject */
- private $mailer;
+ private IMailer&MockObject $mailer;
protected function setUp(): void {
parent::setUp();
@@ -97,18 +95,12 @@ class EmailProviderTest extends AbstractNotificationProviderTest {
$this->mailer->expects($this->exactly(4))
->method('validateMailAddress')
- ->withConsecutive(
- ['uid1@example.com'],
- ['uid2@example.com'],
- ['uid3@example.com'],
- ['invalid'],
- )
- ->willReturnOnConsecutiveCalls(
- true,
- true,
- true,
- false,
- );
+ ->willReturnMap([
+ ['uid1@example.com', true],
+ ['uid2@example.com', true],
+ ['uid3@example.com', true],
+ ['invalid', false],
+ ]);
$this->mailer->expects($this->exactly(3))
->method('createMessage')
@@ -119,14 +111,18 @@ class EmailProviderTest extends AbstractNotificationProviderTest {
$message22
);
- $this->mailer->expects($this->exactly(3))
+ $calls = [
+ [$message11],
+ [$message21],
+ [$message22],
+ ];
+ $this->mailer->expects($this->exactly(count($calls)))
->method('send')
- ->withConsecutive(
- [$message11],
- [$message21],
- [$message22],
- )
- ->willReturn([]);
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ return [];
+ });
$this->setupURLGeneratorMock(2);
@@ -215,16 +211,22 @@ class EmailProviderTest extends AbstractNotificationProviderTest {
$message22,
$message23,
);
- $this->mailer->expects($this->exactly(6))
+
+ $calls = [
+ [$message11],
+ [$message12],
+ [$message13],
+ [$message21],
+ [$message22],
+ [$message23],
+ ];
+ $this->mailer->expects($this->exactly(count($calls)))
->method('send')
- ->withConsecutive(
- [$message11],
- [$message12],
- [$message13],
- [$message21],
- [$message22],
- [$message23],
- )->willReturn([]);
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ return [];
+ });
$this->setupURLGeneratorMock(2);
$vcalendar = $this->getAttendeeVCalendar();
@@ -293,12 +295,18 @@ class EmailProviderTest extends AbstractNotificationProviderTest {
$message12,
$message13,
);
- $this->mailer->expects($this->exactly(2))
+
+ $calls = [
+ [$message12],
+ [$message13],
+ ];
+ $this->mailer->expects($this->exactly(count($calls)))
->method('send')
- ->withConsecutive(
- [$message12],
- [$message13],
- )->willReturn([]);
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ return [];
+ });
$this->setupURLGeneratorMock(1);
$vcalendar = $this->getAttendeeVCalendar();
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/PushProviderTest.php b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/PushProviderTest.php
index b090fa0e5e7..c601463363b 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/PushProviderTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProvider/PushProviderTest.php
@@ -13,13 +13,11 @@ use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IUser;
use OCP\Notification\IManager;
use OCP\Notification\INotification;
+use PHPUnit\Framework\MockObject\MockObject;
-class PushProviderTest extends AbstractNotificationProviderTest {
- /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
- private $manager;
-
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
- private $timeFactory;
+class PushProviderTest extends AbstractNotificationProviderTestCase {
+ private IManager&MockObject $manager;
+ private ITimeFactory&MockObject $timeFactory;
protected function setUp(): void {
parent::setUp();
@@ -96,20 +94,23 @@ class PushProviderTest extends AbstractNotificationProviderTest {
$this->manager->expects($this->exactly(3))
->method('createNotification')
- ->with()
->willReturnOnConsecutiveCalls(
$notification1,
$notification2,
$notification3
);
+ $calls = [
+ $notification1,
+ $notification2,
+ $notification3,
+ ];
$this->manager->expects($this->exactly(3))
->method('notify')
- ->withConsecutive(
- [$notification1],
- [$notification2],
- [$notification3],
- );
+ ->willReturnCallback(function ($notification) use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, $notification);
+ });
$this->provider->send($this->vcalendar->VEVENT, $this->calendarDisplayName, [], $users);
}
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProviderManagerTest.php b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProviderManagerTest.php
index 6d0e62f505b..6b813ed0228 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/NotificationProviderManagerTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/NotificationProviderManagerTest.php
@@ -21,9 +21,7 @@ use Test\TestCase;
* @group DB
*/
class NotificationProviderManagerTest extends TestCase {
-
- /** @var NotificationProviderManager|\PHPUnit\Framework\MockObject\MockObject */
- private $providerManager;
+ private NotificationProviderManager $providerManager;
/**
* @throws QueryException
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/NotifierTest.php b/apps/dav/tests/unit/CalDAV/Reminder/NotifierTest.php
index dcf11a1a6b8..147446152d8 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/NotifierTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/NotifierTest.php
@@ -21,20 +21,11 @@ use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class NotifierTest extends TestCase {
- /** @var Notifier */
- protected $notifier;
-
- /** @var IFactory|MockObject */
- protected $factory;
-
- /** @var IURLGenerator|MockObject */
- protected $urlGenerator;
-
- /** @var IL10N|MockObject */
- protected $l10n;
-
- /** @var ITimeFactory|MockObject */
- protected $timeFactory;
+ protected IFactory&MockObject $factory;
+ protected IURLGenerator&MockObject $urlGenerator;
+ protected IL10N&MockObject $l10n;
+ protected ITimeFactory&MockObject $timeFactory;
+ protected Notifier $notifier;
protected function setUp(): void {
parent::setUp();
@@ -92,7 +83,7 @@ class NotifierTest extends TestCase {
$this->expectException(UnknownNotificationException::class);
$this->expectExceptionMessage('Notification not from this app');
- /** @var INotification|MockObject $notification */
+ /** @var INotification&MockObject $notification */
$notification = $this->createMock(INotification::class);
$notification->expects($this->once())
@@ -109,7 +100,7 @@ class NotifierTest extends TestCase {
$this->expectException(UnknownNotificationException::class);
$this->expectExceptionMessage('Unknown subject');
- /** @var INotification|MockObject $notification */
+ /** @var INotification&MockObject $notification */
$notification = $this->createMock(INotification::class);
$notification->expects($this->once())
@@ -130,7 +121,7 @@ class NotifierTest extends TestCase {
return $d1->diff($d2)->y < 0;
}
- public function dataPrepare(): array {
+ public static function dataPrepare(): array {
return [
[
'calendar_reminder',
@@ -181,16 +172,9 @@ class NotifierTest extends TestCase {
/**
* @dataProvider dataPrepare
- *
- * @param string $subjectType
- * @param array $subjectParams
- * @param string $subject
- * @param array $messageParams
- * @param string $message
- * @throws \Exception
*/
public function testPrepare(string $subjectType, array $subjectParams, string $subject, array $messageParams, string $message): void {
- /** @var INotification|MockObject $notification */
+ /** @var INotification&MockObject $notification */
$notification = $this->createMock(INotification::class);
$notification->expects($this->once())
@@ -235,7 +219,7 @@ class NotifierTest extends TestCase {
}
public function testPassedEvent(): void {
- /** @var INotification|MockObject $notification */
+ /** @var INotification&MockObject $notification */
$notification = $this->createMock(INotification::class);
$notification->expects($this->once())
diff --git a/apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php b/apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php
index 198c8d97b12..4b6735ee297 100644
--- a/apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php
+++ b/apps/dav/tests/unit/CalDAV/Reminder/ReminderServiceTest.php
@@ -26,35 +26,16 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class ReminderServiceTest extends TestCase {
- /** @var Backend|MockObject */
- private $backend;
-
- /** @var NotificationProviderManager|MockObject */
- private $notificationProviderManager;
-
- /** @var IUserManager|MockObject */
- private $userManager;
-
- /** @var IGroupManager|MockObject */
- private $groupManager;
-
- /** @var CalDavBackend|MockObject */
- private $caldavBackend;
-
- /** @var ITimeFactory|MockObject */
- private $timeFactory;
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var ReminderService */
- private $reminderService;
-
- /** @var MockObject|LoggerInterface */
- private $logger;
-
- /** @var MockObject|Principal */
- private $principalConnector;
+ private Backend&MockObject $backend;
+ private NotificationProviderManager&MockObject $notificationProviderManager;
+ private IUserManager&MockObject $userManager;
+ private IGroupManager&MockObject $groupManager;
+ private CalDavBackend&MockObject $caldavBackend;
+ private ITimeFactory&MockObject $timeFactory;
+ private IConfig&MockObject $config;
+ private LoggerInterface&MockObject $logger;
+ private Principal&MockObject $principalConnector;
+ private ReminderService $reminderService;
public const CALENDAR_DATA = <<<EOD
BEGIN:VCALENDAR
@@ -252,9 +233,7 @@ END:VTIMEZONE
END:VCALENDAR
ICS;
-
- /** @var null|string */
- private $oldTimezone;
+ private ?string $oldTimezone;
protected function setUp(): void {
parent::setUp();
@@ -305,13 +284,17 @@ ICS;
'component' => 'vevent',
];
- $this->backend->expects($this->exactly(2))
+ $calls = [
+ [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'de919af7429d3b5c11e8b9d289b411a6', 'EMAIL', true, 1465429500, false],
+ [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', '35b3eae8e792aa2209f0b4e1a302f105', 'DISPLAY', false, 1465344000, false]
+ ];
+ $this->backend->expects($this->exactly(count($calls)))
->method('insertReminder')
- ->withConsecutive(
- [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'de919af7429d3b5c11e8b9d289b411a6', 'EMAIL', true, 1465429500, false],
- [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', '35b3eae8e792aa2209f0b4e1a302f105', 'DISPLAY', false, 1465344000, false]
- )
- ->willReturn(1);
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ return 1;
+ });
$this->timeFactory->expects($this->once())
->method('getDateTime')
@@ -353,12 +336,7 @@ EOD;
];
$this->backend->expects($this->never())
- ->method('insertReminder')
- ->withConsecutive(
- [1337, 42, 'wej2z68l9h', false, null, false, '5c70531aab15c92b52518ae10a2f78a4', 'de919af7429d3b5c11e8b9d289b411a6', 'EMAIL', true, 1465429500, false],
- [1337, 42, 'wej2z68l9h', false, null, false, '5c70531aab15c92b52518ae10a2f78a4', '35b3eae8e792aa2209f0b4e1a302f105', 'DISPLAY', false, 1465344000, false]
- )
- ->willReturn(1);
+ ->method('insertReminder');
$this->reminderService->onCalendarObjectCreate($objectData);
}
@@ -371,16 +349,20 @@ EOD;
'component' => 'vevent',
];
- $this->backend->expects($this->exactly(5))
+ $calls = [
+ [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429500, false],
+ [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429620, true],
+ [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429740, true],
+ [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429860, true],
+ [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429980, true]
+ ];
+ $this->backend->expects($this->exactly(count($calls)))
->method('insertReminder')
- ->withConsecutive(
- [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429500, false],
- [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429620, true],
- [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429740, true],
- [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429860, true],
- [1337, 42, 'wej2z68l9h', false, 1465430400, false, '5c70531aab15c92b52518ae10a2f78a4', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1465429980, true]
- )
- ->willReturn(1);
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ return 1;
+ });
$this->timeFactory->expects($this->once())
->method('getDateTime')
@@ -398,13 +380,17 @@ EOD;
'component' => 'vevent',
];
- $this->backend->expects($this->exactly(2))
+ $calls = [
+ [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'de919af7429d3b5c11e8b9d289b411a6', 'EMAIL', true, 1467243900, false],
+ [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', '8996992118817f9f311ac5cc56d1cc97', 'EMAIL', true, 1467158400, false]
+ ];
+ $this->backend->expects($this->exactly(count($calls)))
->method('insertReminder')
- ->withConsecutive(
- [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'de919af7429d3b5c11e8b9d289b411a6', 'EMAIL', true, 1467243900, false],
- [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', '8996992118817f9f311ac5cc56d1cc97', 'EMAIL', true, 1467158400, false]
- )
- ->willReturn(1);
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ return 1;
+ });
$this->timeFactory->expects($this->once())
->method('getDateTime')
@@ -521,17 +507,23 @@ EOD;
->willReturn([
'{urn:ietf:params:xml:ns:caldav}calendar-timezone' => null,
]);
- $this->backend->expects($this->exactly(6))
+
+ $calls = [
+ [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467243900, false],
+ [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244020, true],
+ [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244140, true],
+ [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244260, true],
+ [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244380, true],
+ [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', '8996992118817f9f311ac5cc56d1cc97', 'EMAIL', true, 1467158400, false]
+ ];
+ $this->backend->expects($this->exactly(count($calls)))
->method('insertReminder')
- ->withConsecutive(
- [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467243900, false],
- [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244020, true],
- [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244140, true],
- [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244260, true],
- [1337, 42, 'wej2z68l9h', true, 1467244800, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467244380, true],
- [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', '8996992118817f9f311ac5cc56d1cc97', 'EMAIL', true, 1467158400, false]
- )
- ->willReturn(1);
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ return 1;
+ });
+
$this->timeFactory->expects($this->once())
->method('getDateTime')
->with()
@@ -556,9 +548,7 @@ EOD;
$expectedReminderTimstamp = (new DateTime('2023-02-04T08:00:00', new DateTimeZone('Europe/Vienna')))->getTimestamp();
$this->backend->expects(self::once())
->method('insertReminder')
- ->withConsecutive(
- [1337, 42, self::anything(), false, self::anything(), false, self::anything(), self::anything(), self::anything(), true, $expectedReminderTimstamp, false],
- )
+ ->with(1337, 42, self::anything(), false, self::anything(), false, self::anything(), self::anything(), self::anything(), true, $expectedReminderTimstamp, false)
->willReturn(1);
$this->caldavBackend->expects(self::once())
->method('getCalendarById')
@@ -684,22 +674,22 @@ EOD;
$provider3 = $this->createMock(INotificationProvider::class);
$provider4 = $this->createMock(INotificationProvider::class);
$provider5 = $this->createMock(INotificationProvider::class);
- $this->notificationProviderManager->expects($this->exactly(5))
+
+ $getProviderCalls = [
+ ['EMAIL', $provider1],
+ ['EMAIL', $provider2],
+ ['DISPLAY', $provider3],
+ ['EMAIL', $provider4],
+ ['EMAIL', $provider5],
+ ];
+ $this->notificationProviderManager->expects($this->exactly(count($getProviderCalls)))
->method('getProvider')
- ->withConsecutive(
- ['EMAIL'],
- ['EMAIL'],
- ['DISPLAY'],
- ['EMAIL'],
- ['EMAIL'],
- )
- ->willReturnOnConsecutiveCalls(
- $provider1,
- $provider2,
- $provider3,
- $provider4,
- $provider5,
- );
+ ->willReturnCallback(function () use (&$getProviderCalls) {
+ $expected = array_shift($getProviderCalls);
+ $return = array_pop($expected);
+ $this->assertEquals($expected, func_get_args());
+ return $return;
+ });
$user = $this->createMock(IUser::class);
$this->userManager->expects($this->exactly(5))
@@ -748,20 +738,36 @@ EOD;
return true;
}, 'Displayname 123', $user));
+ $removeReminderCalls = [
+ [1],
+ [2],
+ [3],
+ [4],
+ [5],
+ ];
$this->backend->expects($this->exactly(5))
->method('removeReminder')
- ->withConsecutive([1], [2], [3], [4], [5]);
- $this->backend->expects($this->exactly(6))
+ ->willReturnCallback(function () use (&$removeReminderCalls) {
+ $expected = array_shift($removeReminderCalls);
+ $this->assertEquals($expected, func_get_args());
+ });
+
+
+ $insertReminderCalls = [
+ [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467848700, false],
+ [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467848820, true],
+ [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467848940, true],
+ [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467849060, true],
+ [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467849180, true],
+ [1337, 42, 'wej2z68l9h', true, 1468454400, false, 'fbdb2726bc0f7dfacac1d881c1453e20', '8996992118817f9f311ac5cc56d1cc97', 'EMAIL', true, 1467763200, false],
+ ];
+ $this->backend->expects($this->exactly(count($insertReminderCalls)))
->method('insertReminder')
- ->withConsecutive(
- [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467848700, false],
- [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467848820, true],
- [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467848940, true],
- [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467849060, true],
- [1337, 42, 'wej2z68l9h', true, 1467849600, false, 'fbdb2726bc0f7dfacac1d881c1453e20', 'ecacbf07d413c3c78d1ac7ad8c469602', 'EMAIL', true, 1467849180, true],
- [1337, 42, 'wej2z68l9h', true, 1468454400, false, 'fbdb2726bc0f7dfacac1d881c1453e20', '8996992118817f9f311ac5cc56d1cc97', 'EMAIL', true, 1467763200, false],
- )
- ->willReturn(99);
+ ->willReturnCallback(function () use (&$insertReminderCalls) {
+ $expected = array_shift($insertReminderCalls);
+ $this->assertEquals($expected, func_get_args());
+ return 99;
+ });
$this->timeFactory->method('getDateTime')
->willReturn(DateTime::createFromFormat(DateTime::ATOM, '2016-06-08T00:00:00+00:00'));
diff --git a/apps/dav/tests/unit/CalDAV/ResourceBooking/AbstractPrincipalBackendTest.php b/apps/dav/tests/unit/CalDAV/ResourceBooking/AbstractPrincipalBackendTestCase.php
index b2fd9cfb93f..26dbcc0f38c 100644
--- a/apps/dav/tests/unit/CalDAV/ResourceBooking/AbstractPrincipalBackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/ResourceBooking/AbstractPrincipalBackendTestCase.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -12,40 +14,22 @@ use OCA\DAV\CalDAV\ResourceBooking\RoomPrincipalBackend;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\DAV\PropPatch;
use Test\TestCase;
-abstract class AbstractPrincipalBackendTest extends TestCase {
- /** @var ResourcePrincipalBackend|RoomPrincipalBackend */
- protected $principalBackend;
-
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- protected $userSession;
-
- /** @var IGroupManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $groupManager;
-
- /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
- protected $logger;
-
- /** @var ProxyMapper|\PHPUnit\Framework\MockObject\MockObject */
- protected $proxyMapper;
-
- /** @var string */
- protected $mainDbTable;
-
- /** @var string */
- protected $metadataDbTable;
-
- /** @var string */
- protected $foreignKey;
-
- /** @var string */
- protected $principalPrefix;
-
- /** @var string */
- protected $expectedCUType;
+abstract class AbstractPrincipalBackendTestCase extends TestCase {
+ protected ResourcePrincipalBackend|RoomPrincipalBackend $principalBackend;
+ protected IUserSession&MockObject $userSession;
+ protected IGroupManager&MockObject $groupManager;
+ protected LoggerInterface&MockObject $logger;
+ protected ProxyMapper&MockObject $proxyMapper;
+ protected string $mainDbTable;
+ protected string $metadataDbTable;
+ protected string $foreignKey;
+ protected string $principalPrefix;
+ protected string $expectedCUType;
protected function setUp(): void {
parent::setUp();
@@ -59,10 +43,10 @@ abstract class AbstractPrincipalBackendTest extends TestCase {
protected function tearDown(): void {
$query = self::$realDatabase->getQueryBuilder();
- $query->delete('calendar_resources')->execute();
- $query->delete('calendar_resources_md')->execute();
- $query->delete('calendar_rooms')->execute();
- $query->delete('calendar_rooms_md')->execute();
+ $query->delete('calendar_resources')->executeStatement();
+ $query->delete('calendar_resources_md')->executeStatement();
+ $query->delete('calendar_rooms')->executeStatement();
+ $query->delete('calendar_rooms_md')->executeStatement();
}
public function testGetPrincipalsByPrefix(): void {
@@ -214,38 +198,43 @@ abstract class AbstractPrincipalBackendTest extends TestCase {
->with($this->principalPrefix . '/backend1-res1')
->willReturn([]);
+ $calls = [
+ function ($proxy) {
+ /** @var Proxy $proxy */
+ if ($proxy->getOwnerId() !== $this->principalPrefix . '/backend1-res1') {
+ return false;
+ }
+ if ($proxy->getProxyId() !== $this->principalPrefix . '/backend1-res2') {
+ return false;
+ }
+ if ($proxy->getPermissions() !== 3) {
+ return false;
+ }
+
+ return true;
+ },
+ function ($proxy) {
+ /** @var Proxy $proxy */
+ if ($proxy->getOwnerId() !== $this->principalPrefix . '/backend1-res1') {
+ return false;
+ }
+ if ($proxy->getProxyId() !== $this->principalPrefix . '/backend2-res3') {
+ return false;
+ }
+ if ($proxy->getPermissions() !== 3) {
+ return false;
+ }
+
+ return true;
+ }
+ ];
$this->proxyMapper->expects($this->exactly(2))
->method('insert')
- ->withConsecutive(
- [$this->callback(function ($proxy) {
- /** @var Proxy $proxy */
- if ($proxy->getOwnerId() !== $this->principalPrefix . '/backend1-res1') {
- return false;
- }
- if ($proxy->getProxyId() !== $this->principalPrefix . '/backend1-res2') {
- return false;
- }
- if ($proxy->getPermissions() !== 3) {
- return false;
- }
-
- return true;
- })],
- [$this->callback(function ($proxy) {
- /** @var Proxy $proxy */
- if ($proxy->getOwnerId() !== $this->principalPrefix . '/backend1-res1') {
- return false;
- }
- if ($proxy->getProxyId() !== $this->principalPrefix . '/backend2-res3') {
- return false;
- }
- if ($proxy->getPermissions() !== 3) {
- return false;
- }
-
- return true;
- })],
- );
+ ->willReturnCallback(function ($proxy) use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertTrue($expected($proxy));
+ return $proxy;
+ });
$this->principalBackend->setGroupMemberSet($this->principalPrefix . '/backend1-res1/calendar-proxy-write', [$this->principalPrefix . '/backend1-res2', $this->principalPrefix . '/backend2-res3']);
}
@@ -281,7 +270,7 @@ abstract class AbstractPrincipalBackendTest extends TestCase {
$actual);
}
- public function dataSearchPrincipals() {
+ public static function dataSearchPrincipals(): array {
// data providers are called before we subclass
// this class, $this->principalPrefix is null
// at that point, so we need this hack
diff --git a/apps/dav/tests/unit/CalDAV/ResourceBooking/ResourcePrincipalBackendTest.php b/apps/dav/tests/unit/CalDAV/ResourceBooking/ResourcePrincipalBackendTest.php
index d430afb0b01..168e21c3a91 100644
--- a/apps/dav/tests/unit/CalDAV/ResourceBooking/ResourcePrincipalBackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/ResourceBooking/ResourcePrincipalBackendTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -7,7 +9,7 @@ namespace OCA\DAV\Tests\unit\CalDAV\ResourceBooking;
use OCA\DAV\CalDAV\ResourceBooking\ResourcePrincipalBackend;
-class ResourcePrincipalBackendTest extends AbstractPrincipalBackendTest {
+class ResourcePrincipalBackendTest extends AbstractPrincipalBackendTestCase {
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/CalDAV/ResourceBooking/RoomPrincipalBackendTest.php b/apps/dav/tests/unit/CalDAV/ResourceBooking/RoomPrincipalBackendTest.php
index cd63a3512ae..8a53b0ee25e 100644
--- a/apps/dav/tests/unit/CalDAV/ResourceBooking/RoomPrincipalBackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/ResourceBooking/RoomPrincipalBackendTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -7,7 +9,7 @@ namespace OCA\DAV\Tests\unit\CalDAV\ResourceBooking;
use OCA\DAV\CalDAV\ResourceBooking\RoomPrincipalBackend;
-class RoomPrincipalBackendTest extends AbstractPrincipalBackendTest {
+class RoomPrincipalBackendTest extends AbstractPrincipalBackendTestCase {
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php
index 0137f528355..8e71bfa6edf 100644
--- a/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -36,54 +38,22 @@ interface IMailServiceMock extends IMailService, IMailMessageSend {
}
class IMipPluginTest extends TestCase {
-
- /** @var IMessage|MockObject */
- private $mailMessage;
-
- /** @var IMailer|MockObject */
- private $mailer;
-
- /** @var IEMailTemplate|MockObject */
- private $emailTemplate;
-
- /** @var IAttachment|MockObject */
- private $emailAttachment;
-
- /** @var ITimeFactory|MockObject */
- private $timeFactory;
-
- /** @var IAppConfig|MockObject */
- private $config;
-
- /** @var IUserSession|MockObject */
- private $userSession;
-
- /** @var IUser|MockObject */
- private $user;
-
- /** @var IMipPlugin */
- private $plugin;
-
- /** @var IMipService|MockObject */
- private $service;
-
- /** @var Defaults|MockObject */
- private $defaults;
-
- /** @var LoggerInterface|MockObject */
- private $logger;
-
- /** @var EventComparisonService|MockObject */
- private $eventComparisonService;
-
- /** @var IMailManager|MockObject */
- private $mailManager;
-
- /** @var IMailService|IMailMessageSend|MockObject */
- private $mailService;
-
- /** @var IMailMessageNew|MockObject */
- private $mailMessageNew;
+ private IMessage&MockObject $mailMessage;
+ private IMailer&MockObject $mailer;
+ private IEMailTemplate&MockObject $emailTemplate;
+ private IAttachment&MockObject $emailAttachment;
+ private ITimeFactory&MockObject $timeFactory;
+ private IAppConfig&MockObject $config;
+ private IUserSession&MockObject $userSession;
+ private IUser&MockObject $user;
+ private IMipPlugin $plugin;
+ private IMipService&MockObject $service;
+ private Defaults&MockObject $defaults;
+ private LoggerInterface&MockObject $logger;
+ private EventComparisonService&MockObject $eventComparisonService;
+ private IMailManager&MockObject $mailManager;
+ private IMailServiceMock&MockObject $mailService;
+ private IMailMessageNew&MockObject $mailMessageNew;
protected function setUp(): void {
$this->mailMessage = $this->createMock(IMessage::class);
@@ -219,6 +189,10 @@ class IMipPluginTest extends TestCase {
->with($atnd)
->willReturn(false);
$this->service->expects(self::once())
+ ->method('isCircle')
+ ->with($atnd)
+ ->willReturn(false);
+ $this->service->expects(self::once())
->method('buildBodyData')
->with($newVevent, $oldVEvent)
->willReturn($data);
@@ -322,6 +296,88 @@ class IMipPluginTest extends TestCase {
->with($room)
->willReturn(true);
$this->service->expects(self::never())
+ ->method('isCircle');
+ $this->service->expects(self::never())
+ ->method('buildBodyData');
+ $this->user->expects(self::any())
+ ->method('getUID')
+ ->willReturn('user1');
+ $this->user->expects(self::any())
+ ->method('getDisplayName')
+ ->willReturn('Mr. Wizard');
+ $this->userSession->expects(self::any())
+ ->method('getUser')
+ ->willReturn($this->user);
+ $this->service->expects(self::never())
+ ->method('getFrom');
+ $this->service->expects(self::never())
+ ->method('addSubjectAndHeading');
+ $this->service->expects(self::never())
+ ->method('addBulletList');
+ $this->service->expects(self::never())
+ ->method('getAttendeeRsvpOrReqForParticipant');
+ $this->config->expects(self::never())
+ ->method('getValueString');
+ $this->service->expects(self::never())
+ ->method('createInvitationToken');
+ $this->service->expects(self::never())
+ ->method('addResponseButtons');
+ $this->service->expects(self::never())
+ ->method('addMoreOptionsButton');
+ $this->mailer->expects(self::never())
+ ->method('send');
+ $this->plugin->schedule($message);
+ $this->assertEquals('1.0', $message->getScheduleStatus());
+ }
+
+ public function testAttendeeIsCircle(): void {
+ $message = new Message();
+ $message->method = 'REQUEST';
+ $newVCalendar = new VCalendar();
+ $newVevent = new VEvent($newVCalendar, 'one', array_merge([
+ 'UID' => 'uid-1234',
+ 'SEQUENCE' => 1,
+ 'SUMMARY' => 'Fellowship meeting without (!) Boromir',
+ 'DTSTART' => new \DateTime('2016-01-01 00:00:00')
+ ], []));
+ $newVevent->add('ORGANIZER', 'mailto:gandalf@wiz.ard');
+ $newVevent->add('ATTENDEE', 'mailto:' . 'circle+82utEV1Fle8wvxndZLK5TVAPtxj8IIe@middle.earth', ['RSVP' => 'TRUE', 'CN' => 'The Fellowship', 'CUTYPE' => 'GROUP']);
+ $newVevent->add('ATTENDEE', 'mailto:' . 'boromir@tra.it.or', ['RSVP' => 'TRUE', 'MEMBER' => 'circle+82utEV1Fle8wvxndZLK5TVAPtxj8IIe@middle.earth']);
+ $message->message = $newVCalendar;
+ $message->sender = 'mailto:gandalf@wiz.ard';
+ $message->senderName = 'Mr. Wizard';
+ $message->recipient = 'mailto:' . 'circle+82utEV1Fle8wvxndZLK5TVAPtxj8IIe@middle.earth';
+ $attendees = $newVevent->select('ATTENDEE');
+ $circle = '';
+ foreach ($attendees as $attendee) {
+ if (strcasecmp($attendee->getValue(), $message->recipient) === 0) {
+ $circle = $attendee;
+ }
+ }
+ $this->assertNotEmpty($circle, 'Failed to find attendee belonging to the circle');
+ $this->service->expects(self::once())
+ ->method('getLastOccurrence')
+ ->willReturn(1496912700);
+ $this->mailer->expects(self::once())
+ ->method('validateMailAddress')
+ ->with('circle+82utEV1Fle8wvxndZLK5TVAPtxj8IIe@middle.earth')
+ ->willReturn(true);
+ $this->eventComparisonService->expects(self::once())
+ ->method('findModified')
+ ->willReturn(['new' => [$newVevent], 'old' => null]);
+ $this->service->expects(self::once())
+ ->method('getCurrentAttendee')
+ ->with($message)
+ ->willReturn($circle);
+ $this->service->expects(self::once())
+ ->method('isRoomOrResource')
+ ->with($circle)
+ ->willReturn(false);
+ $this->service->expects(self::once())
+ ->method('isCircle')
+ ->with($circle)
+ ->willReturn(true);
+ $this->service->expects(self::never())
->method('buildBodyData');
$this->user->expects(self::any())
->method('getUID')
@@ -423,6 +479,10 @@ class IMipPluginTest extends TestCase {
->with($atnd)
->willReturn(false);
$this->service->expects(self::once())
+ ->method('isCircle')
+ ->with($atnd)
+ ->willReturn(false);
+ $this->service->expects(self::once())
->method('buildBodyData')
->with($newVevent, null)
->willReturn($data);
@@ -554,6 +614,10 @@ class IMipPluginTest extends TestCase {
->with($atnd)
->willReturn(false);
$this->service->expects(self::once())
+ ->method('isCircle')
+ ->with($atnd)
+ ->willReturn(false);
+ $this->service->expects(self::once())
->method('buildBodyData')
->with($newVevent, null)
->willReturn($data);
@@ -660,6 +724,10 @@ class IMipPluginTest extends TestCase {
->with($attendee)
->willReturn(false);
$this->service->expects(self::once())
+ ->method('isCircle')
+ ->with($attendee)
+ ->willReturn(false);
+ $this->service->expects(self::once())
->method('buildBodyData')
->with($event, null)
->willReturn($data);
@@ -767,6 +835,10 @@ class IMipPluginTest extends TestCase {
->with($atnd)
->willReturn(false);
$this->service->expects(self::once())
+ ->method('isCircle')
+ ->with($atnd)
+ ->willReturn(false);
+ $this->service->expects(self::once())
->method('buildBodyData')
->with($newVevent, $oldVEvent)
->willReturn($data);
@@ -862,6 +934,10 @@ class IMipPluginTest extends TestCase {
->with($atnd)
->willReturn(false);
$this->service->expects(self::once())
+ ->method('isCircle')
+ ->with($atnd)
+ ->willReturn(false);
+ $this->service->expects(self::once())
->method('buildBodyData')
->with($newVevent, null)
->willReturn($data);
@@ -955,6 +1031,10 @@ class IMipPluginTest extends TestCase {
->with($atnd)
->willReturn(false);
$this->service->expects(self::once())
+ ->method('isCircle')
+ ->with($atnd)
+ ->willReturn(false);
+ $this->service->expects(self::once())
->method('buildBodyData')
->with($newVevent, null)
->willReturn($data);
diff --git a/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php b/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php
index abf8cfe3177..2be6a1cf8b1 100644
--- a/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php
+++ b/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,15 +9,14 @@
namespace OCA\DAV\Tests\unit\CalDAV\Schedule;
-use OC\L10N\L10N;
-use OC\L10N\LazyL10N;
use OC\URLGenerator;
use OCA\DAV\CalDAV\EventReader;
use OCA\DAV\CalDAV\Schedule\IMipService;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
use OCP\IDBConnection;
-use OCP\L10N\IFactory as L10NFactory;
+use OCP\IL10N;
+use OCP\L10N\IFactory;
use OCP\Security\ISecureRandom;
use PHPUnit\Framework\MockObject\MockObject;
use Sabre\VObject\Component\VCalendar;
@@ -24,48 +24,32 @@ use Sabre\VObject\Property\ICalendar\DateTime;
use Test\TestCase;
class IMipServiceTest extends TestCase {
- /** @var URLGenerator|MockObject */
- private $urlGenerator;
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var IDBConnection|MockObject */
- private $db;
-
- /** @var ISecureRandom|MockObject */
- private $random;
-
- /** @var L10NFactory|MockObject */
- private $l10nFactory;
-
- /** @var L10N|MockObject */
- private $l10n;
-
- /** @var ITimeFactory|MockObject */
- private $timeFactory;
-
- /** @var IMipService */
- private $service;
-
- /** @var VCalendar */
- private $vCalendar1a;
- /** @var VCalendar */
- private $vCalendar1b;
- /** @var VCalendar */
- private $vCalendar2;
- /** @var VCalendar */
- private $vCalendar3;
+ private URLGenerator&MockObject $urlGenerator;
+ private IConfig&MockObject $config;
+ private IDBConnection&MockObject $db;
+ private ISecureRandom&MockObject $random;
+ private IFactory&MockObject $l10nFactory;
+ private IL10N&MockObject $l10n;
+ private ITimeFactory&MockObject $timeFactory;
+ private IMipService $service;
+
+
+ private VCalendar $vCalendar1a;
+ private VCalendar $vCalendar1b;
+ private VCalendar $vCalendar2;
+ private VCalendar $vCalendar3;
/** @var DateTime DateTime object that will be returned by DateTime() or DateTime('now') */
public static $datetimeNow;
protected function setUp(): void {
+ parent::setUp();
+
$this->urlGenerator = $this->createMock(URLGenerator::class);
$this->config = $this->createMock(IConfig::class);
$this->db = $this->createMock(IDBConnection::class);
$this->random = $this->createMock(ISecureRandom::class);
- $this->l10nFactory = $this->createMock(L10NFactory::class);
- $this->l10n = $this->createMock(LazyL10N::class);
+ $this->l10nFactory = $this->createMock(IFactory::class);
+ $this->l10n = $this->createMock(IL10N::class);
$this->timeFactory = $this->createMock(ITimeFactory::class);
$this->l10nFactory->expects(self::once())
->method('findGenericLanguage')
@@ -170,7 +154,7 @@ class IMipServiceTest extends TestCase {
}
public function testBuildBodyDataCreated(): void {
-
+
// construct l10n return(s)
$this->l10n->method('l')->willReturnCallback(
function ($v1, $v2, $v3) {
@@ -218,7 +202,7 @@ class IMipServiceTest extends TestCase {
}
public function testBuildBodyDataUpdate(): void {
-
+
// construct l10n return(s)
$this->l10n->method('l')->willReturnCallback(
function ($v1, $v2, $v3) {
@@ -349,7 +333,7 @@ class IMipServiceTest extends TestCase {
}
public function testGenerateWhenStringSingular(): void {
-
+
// construct l10n return(s)
$this->l10n->method('l')->willReturnCallback(
function ($v1, $v2, $v3) {
@@ -802,7 +786,7 @@ class IMipServiceTest extends TestCase {
'In 2 months on July 1, 2024 for the entire day',
$this->service->generateWhenString($eventReader)
);
-
+
/** test patrial day event in 1 year*/
$vCalendar = clone $this->vCalendar1a;
// construct event reader
@@ -846,7 +830,7 @@ class IMipServiceTest extends TestCase {
}
public function testGenerateWhenStringRecurringDaily(): void {
-
+
// construct l10n return maps
$this->l10n->method('l')->willReturnCallback(
function ($v1, $v2, $v3) {
@@ -960,7 +944,7 @@ class IMipServiceTest extends TestCase {
}
public function testGenerateWhenStringRecurringWeekly(): void {
-
+
// construct l10n return maps
$this->l10n->method('l')->willReturnCallback(
function ($v1, $v2, $v3) {
@@ -1077,7 +1061,7 @@ class IMipServiceTest extends TestCase {
}
public function testGenerateWhenStringRecurringMonthly(): void {
-
+
// construct l10n return maps
$this->l10n->method('l')->willReturnCallback(
function ($v1, $v2, $v3) {
@@ -1290,7 +1274,7 @@ class IMipServiceTest extends TestCase {
}
public function testGenerateWhenStringRecurringYearly(): void {
-
+
// construct l10n return maps
$this->l10n->method('l')->willReturnCallback(
function ($v1, $v2, $v3) {
@@ -1504,7 +1488,7 @@ class IMipServiceTest extends TestCase {
}
public function testGenerateWhenStringRecurringFixed(): void {
-
+
// construct l10n return maps
$this->l10n->method('l')->willReturnCallback(
function ($v1, $v2, $v3) {
@@ -1545,7 +1529,7 @@ class IMipServiceTest extends TestCase {
}
public function testGenerateOccurringStringWithRrule(): void {
-
+
// construct l10n return(s)
$this->l10n->method('l')->willReturnCallback(
function ($v1, $v2, $v3) {
@@ -1602,7 +1586,7 @@ class IMipServiceTest extends TestCase {
'In 2 days on July 1, 2024 then on July 3, 2024 and July 5, 2024'
],
]);
-
+
// construct time factory return(s)
$this->timeFactory->method('getDateTime')->willReturnOnConsecutiveCalls(
(new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))),
@@ -1687,7 +1671,7 @@ class IMipServiceTest extends TestCase {
}
public function testGenerateOccurringStringWithRdate(): void {
-
+
// construct l10n return(s)
$this->l10n->method('l')->willReturnCallback(
function ($v1, $v2, $v3) {
@@ -1838,7 +1822,7 @@ class IMipServiceTest extends TestCase {
}
public function testGenerateOccurringStringWithOneExdate(): void {
-
+
// construct l10n return(s)
$this->l10n->method('l')->willReturnCallback(
function ($v1, $v2, $v3) {
@@ -2022,7 +2006,7 @@ class IMipServiceTest extends TestCase {
}
public function testGenerateOccurringStringWithTwoExdate(): void {
-
+
// construct l10n return(s)
$this->l10n->method('l')->willReturnCallback(
function ($v1, $v2, $v3) {
diff --git a/apps/dav/tests/unit/CalDAV/Schedule/PluginTest.php b/apps/dav/tests/unit/CalDAV/Schedule/PluginTest.php
index f656a0fa33c..5dadb753a79 100644
--- a/apps/dav/tests/unit/CalDAV/Schedule/PluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/Schedule/PluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -35,21 +36,11 @@ use Sabre\Xml\Service;
use Test\TestCase;
class PluginTest extends TestCase {
-
- /** @var Plugin */
- private $plugin;
-
- /** @var Server|MockObject */
- private $server;
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var LoggerInterface&MockObject */
- private $logger;
-
- /** @var DefaultCalendarValidator */
- private $calendarValidator;
+ private Plugin $plugin;
+ private Server&MockObject $server;
+ private IConfig&MockObject $config;
+ private LoggerInterface&MockObject $logger;
+ private DefaultCalendarValidator $calendarValidator;
protected function setUp(): void {
parent::setUp();
@@ -59,9 +50,7 @@ class PluginTest extends TestCase {
$this->calendarValidator = new DefaultCalendarValidator();
$this->server = $this->createMock(Server::class);
- $this->server->httpResponse = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->server->httpResponse = $this->createMock(ResponseInterface::class);
$this->server->xml = new Service();
$this->plugin = new Plugin($this->config, $this->logger, $this->calendarValidator);
@@ -69,23 +58,26 @@ class PluginTest extends TestCase {
}
public function testInitialize(): void {
-
- $this->server->expects($this->exactly(10))
+ $calls = [
+ // Sabre\CalDAV\Schedule\Plugin events
+ ['method:POST', [$this->plugin, 'httpPost'], 100],
+ ['propFind', [$this->plugin, 'propFind'], 100],
+ ['propPatch', [$this->plugin, 'propPatch'], 100],
+ ['calendarObjectChange', [$this->plugin, 'calendarObjectChange'], 100],
+ ['beforeUnbind', [$this->plugin, 'beforeUnbind'], 100],
+ ['schedule', [$this->plugin, 'scheduleLocalDelivery'], 100],
+ ['getSupportedPrivilegeSet', [$this->plugin, 'getSupportedPrivilegeSet'], 100],
+ // OCA\DAV\CalDAV\Schedule\Plugin events
+ ['propFind', [$this->plugin, 'propFindDefaultCalendarUrl'], 90],
+ ['afterWriteContent', [$this->plugin, 'dispatchSchedulingResponses'], 100],
+ ['afterCreateFile', [$this->plugin, 'dispatchSchedulingResponses'], 100],
+ ];
+ $this->server->expects($this->exactly(count($calls)))
->method('on')
- ->withConsecutive(
- // Sabre\CalDAV\Schedule\Plugin events
- ['method:POST', [$this->plugin, 'httpPost']],
- ['propFind', [$this->plugin, 'propFind']],
- ['propPatch', [$this->plugin, 'propPatch']],
- ['calendarObjectChange', [$this->plugin, 'calendarObjectChange']],
- ['beforeUnbind', [$this->plugin, 'beforeUnbind']],
- ['schedule', [$this->plugin, 'scheduleLocalDelivery']],
- ['getSupportedPrivilegeSet', [$this->plugin, 'getSupportedPrivilegeSet']],
- // OCA\DAV\CalDAV\Schedule\Plugin events
- ['propFind', [$this->plugin, 'propFindDefaultCalendarUrl'], 90],
- ['afterWriteContent', [$this->plugin, 'dispatchSchedulingResponses']],
- ['afterCreateFile', [$this->plugin, 'dispatchSchedulingResponses']]
- );
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
$this->plugin->initialize($this->server);
}
@@ -168,7 +160,7 @@ class PluginTest extends TestCase {
$this->assertFalse($this->invokePrivate($this->plugin, 'getAttendeeRSVP', [$property3]));
}
- public function propFindDefaultCalendarUrlProvider(): array {
+ public static function propFindDefaultCalendarUrlProvider(): array {
return [
[
'principals/users/myuser',
@@ -270,7 +262,7 @@ class PluginTest extends TestCase {
],
0
);
- /** @var IPrincipal|MockObject $node */
+ /** @var IPrincipal&MockObject $node */
$node = $this->getMockBuilder(IPrincipal::class)
->disableOriginalConstructor()
->getMock();
@@ -367,7 +359,7 @@ class PluginTest extends TestCase {
}
}
- /** @var Tree|MockObject $tree */
+ /** @var Tree&MockObject $tree */
$tree = $this->createMock(Tree::class);
$tree->expects($this->once())
->method('getNodeForPath')
diff --git a/apps/dav/tests/unit/CalDAV/Search/Request/CalendarSearchReportTest.php b/apps/dav/tests/unit/CalDAV/Search/Request/CalendarSearchReportTest.php
index cbfd4639ed7..02ae504bce0 100644
--- a/apps/dav/tests/unit/CalDAV/Search/Request/CalendarSearchReportTest.php
+++ b/apps/dav/tests/unit/CalDAV/Search/Request/CalendarSearchReportTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -10,9 +12,9 @@ use Sabre\Xml\Reader;
use Test\TestCase;
class CalendarSearchReportTest extends TestCase {
- private $elementMap = [
- '{http://nextcloud.com/ns}calendar-search' =>
- 'OCA\\DAV\\CalDAV\\Search\\Xml\\Request\\CalendarSearchReport',
+ private array $elementMap = [
+ '{http://nextcloud.com/ns}calendar-search'
+ => 'OCA\\DAV\\CalDAV\\Search\\Xml\\Request\\CalendarSearchReport',
];
public function testFoo(): void {
@@ -112,7 +114,7 @@ XML;
);
}
-
+
public function testRequiresCompFilter(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
$this->expectExceptionMessage('{http://nextcloud.com/ns}prop-filter or {http://nextcloud.com/ns}param-filter given without any {http://nextcloud.com/ns}comp-filter');
@@ -139,7 +141,7 @@ XML;
$this->parse($xml);
}
-
+
public function testRequiresFilter(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
$this->expectExceptionMessage('The {http://nextcloud.com/ns}filter element is required for this request');
@@ -157,7 +159,7 @@ XML;
$this->parse($xml);
}
-
+
public function testNoSearchTerm(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
$this->expectExceptionMessage('{http://nextcloud.com/ns}search-term is required for this request');
@@ -185,7 +187,7 @@ XML;
$this->parse($xml);
}
-
+
public function testCompOnly(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
$this->expectExceptionMessage('At least one{http://nextcloud.com/ns}prop-filter or {http://nextcloud.com/ns}param-filter is required for this request');
@@ -313,7 +315,7 @@ XML;
);
}
- private function parse($xml, array $elementMap = []) {
+ private function parse(string $xml, array $elementMap = []): array {
$reader = new Reader();
$reader->elementMap = array_merge($this->elementMap, $elementMap);
$reader->xml($xml);
diff --git a/apps/dav/tests/unit/CalDAV/Search/SearchPluginTest.php b/apps/dav/tests/unit/CalDAV/Search/SearchPluginTest.php
index 0da971dc36b..e576fbae34c 100644
--- a/apps/dav/tests/unit/CalDAV/Search/SearchPluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/Search/SearchPluginTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/tests/unit/CalDAV/Security/RateLimitingPluginTest.php b/apps/dav/tests/unit/CalDAV/Security/RateLimitingPluginTest.php
index fc0bd1502b2..a5cf6a23c66 100644
--- a/apps/dav/tests/unit/CalDAV/Security/RateLimitingPluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/Security/RateLimitingPluginTest.php
@@ -24,11 +24,11 @@ use Test\TestCase;
class RateLimitingPluginTest extends TestCase {
- private Limiter|MockObject $limiter;
- private CalDavBackend|MockObject $caldavBackend;
- private IUserManager|MockObject $userManager;
- private LoggerInterface|MockObject $logger;
- private IAppConfig|MockObject $config;
+ private Limiter&MockObject $limiter;
+ private CalDavBackend&MockObject $caldavBackend;
+ private IUserManager&MockObject $userManager;
+ private LoggerInterface&MockObject $logger;
+ private IAppConfig&MockObject $config;
private string $userId = 'user123';
private RateLimitingPlugin $plugin;
diff --git a/apps/dav/tests/unit/CalDAV/Status/StatusServiceTest.php b/apps/dav/tests/unit/CalDAV/Status/StatusServiceTest.php
index 78e76cf507d..ee0ef2334ec 100644
--- a/apps/dav/tests/unit/CalDAV/Status/StatusServiceTest.php
+++ b/apps/dav/tests/unit/CalDAV/Status/StatusServiceTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -25,14 +27,14 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class StatusServiceTest extends TestCase {
- private ITimeFactory|MockObject $timeFactory;
- private IManager|MockObject $calendarManager;
- private IUserManager|MockObject $userManager;
- private UserStatusService|MockObject $userStatusService;
- private IAvailabilityCoordinator|MockObject $availabilityCoordinator;
- private ICacheFactory|MockObject $cacheFactory;
- private LoggerInterface|MockObject $logger;
- private ICache|MockObject $cache;
+ private ITimeFactory&MockObject $timeFactory;
+ private IManager&MockObject $calendarManager;
+ private IUserManager&MockObject $userManager;
+ private UserStatusService&MockObject $userStatusService;
+ private IAvailabilityCoordinator&MockObject $availabilityCoordinator;
+ private ICacheFactory&MockObject $cacheFactory;
+ private LoggerInterface&MockObject $logger;
+ private ICache&MockObject $cache;
private StatusService $service;
protected function setUp(): void {
diff --git a/apps/dav/tests/unit/CalDAV/TimeZoneFactoryTest.php b/apps/dav/tests/unit/CalDAV/TimeZoneFactoryTest.php
index d5a62a9732f..2d6d0e86358 100644
--- a/apps/dav/tests/unit/CalDAV/TimeZoneFactoryTest.php
+++ b/apps/dav/tests/unit/CalDAV/TimeZoneFactoryTest.php
@@ -1,7 +1,6 @@
<?php
declare(strict_types=1);
-
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/tests/unit/CalDAV/TimezoneServiceTest.php b/apps/dav/tests/unit/CalDAV/TimezoneServiceTest.php
index b01139e4093..5bb87be67c1 100644
--- a/apps/dav/tests/unit/CalDAV/TimezoneServiceTest.php
+++ b/apps/dav/tests/unit/CalDAV/TimezoneServiceTest.php
@@ -1,11 +1,6 @@
<?php
-/**
- * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
declare(strict_types=1);
-
/**
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -26,10 +21,9 @@ use Sabre\VObject\Component\VTimeZone;
use Test\TestCase;
class TimezoneServiceTest extends TestCase {
-
- private IConfig|MockObject $config;
- private PropertyMapper|MockObject $propertyMapper;
- private IManager|MockObject $calendarManager;
+ private IConfig&MockObject $config;
+ private PropertyMapper&MockObject $propertyMapper;
+ private IManager&MockObject $calendarManager;
private TimezoneService $service;
protected function setUp(): void {
diff --git a/apps/dav/tests/unit/CalDAV/TipBrokerTest.php b/apps/dav/tests/unit/CalDAV/TipBrokerTest.php
index 3a8e240c1d8..ddf992767d6 100644
--- a/apps/dav/tests/unit/CalDAV/TipBrokerTest.php
+++ b/apps/dav/tests/unit/CalDAV/TipBrokerTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -42,7 +44,7 @@ class TipBrokerTest extends TestCase {
}
public function testParseEventForOrganizerOnCreate(): void {
-
+
// construct calendar and generate event info for newly created event with one attendee
$calendar = clone $this->vCalendar1a;
$previousEventInfo = [
@@ -61,7 +63,7 @@ class TipBrokerTest extends TestCase {
}
public function testParseEventForOrganizerOnModify(): void {
-
+
// construct calendar and generate event info for modified event with one attendee
$calendar = clone $this->vCalendar1a;
$previousEventInfo = $this->invokePrivate($this->broker, 'parseEventInfo', [$calendar]);
@@ -79,7 +81,7 @@ class TipBrokerTest extends TestCase {
}
public function testParseEventForOrganizerOnDelete(): void {
-
+
// construct calendar and generate event info for modified event with one attendee
$calendar = clone $this->vCalendar1a;
$previousEventInfo = $this->invokePrivate($this->broker, 'parseEventInfo', [$calendar]);
@@ -96,7 +98,7 @@ class TipBrokerTest extends TestCase {
}
public function testParseEventForOrganizerOnStatusCancelled(): void {
-
+
// construct calendar and generate event info for modified event with one attendee
$calendar = clone $this->vCalendar1a;
$previousEventInfo = $this->invokePrivate($this->broker, 'parseEventInfo', [$calendar]);
@@ -114,7 +116,7 @@ class TipBrokerTest extends TestCase {
}
public function testParseEventForOrganizerOnAddAttendee(): void {
-
+
// construct calendar and generate event info for modified event with two attendees
$calendar = clone $this->vCalendar1a;
$previousEventInfo = $this->invokePrivate($this->broker, 'parseEventInfo', [$calendar]);
@@ -141,7 +143,7 @@ class TipBrokerTest extends TestCase {
}
public function testParseEventForOrganizerOnRemoveAttendee(): void {
-
+
// construct calendar and generate event info for modified event with two attendees
$calendar = clone $this->vCalendar1a;
$calendar->VEVENT->add('ATTENDEE', 'mailto:attendee2@testing.com', [
diff --git a/apps/dav/tests/unit/CalDAV/Validation/CalDavValidatePluginTest.php b/apps/dav/tests/unit/CalDAV/Validation/CalDavValidatePluginTest.php
index 0329279af09..74fb4b5e94e 100644
--- a/apps/dav/tests/unit/CalDAV/Validation/CalDavValidatePluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/Validation/CalDavValidatePluginTest.php
@@ -18,11 +18,11 @@ use Sabre\HTTP\ResponseInterface;
use Test\TestCase;
class CalDavValidatePluginTest extends TestCase {
+ private IAppConfig&MockObject $config;
+ private RequestInterface&MockObject $request;
+ private ResponseInterface&MockObject $response;
private CalDavValidatePlugin $plugin;
- private IAppConfig|MockObject $config;
- private RequestInterface|MockObject $request;
- private ResponseInterface|MockObject $response;
protected function setUp(): void {
parent::setUp();
@@ -36,7 +36,7 @@ class CalDavValidatePluginTest extends TestCase {
}
public function testPutSizeLessThenLimit(): void {
-
+
// construct method responses
$this->config
->method('getValueInt')
@@ -50,11 +50,11 @@ class CalDavValidatePluginTest extends TestCase {
$this->assertTrue(
$this->plugin->beforePut($this->request, $this->response)
);
-
+
}
public function testPutSizeMoreThenLimit(): void {
-
+
// construct method responses
$this->config
->method('getValueInt')
@@ -67,7 +67,7 @@ class CalDavValidatePluginTest extends TestCase {
$this->expectException(Forbidden::class);
// test condition
$this->plugin->beforePut($this->request, $this->response);
-
+
}
}
diff --git a/apps/dav/tests/unit/CalDAV/WebcalCaching/ConnectionTest.php b/apps/dav/tests/unit/CalDAV/WebcalCaching/ConnectionTest.php
index 5e9caaaeb44..35afc4d7ca7 100644
--- a/apps/dav/tests/unit/CalDAV/WebcalCaching/ConnectionTest.php
+++ b/apps/dav/tests/unit/CalDAV/WebcalCaching/ConnectionTest.php
@@ -13,7 +13,6 @@ use OCP\Http\Client\IClientService;
use OCP\Http\Client\IResponse;
use OCP\Http\Client\LocalServerException;
use OCP\IAppConfig;
-use OCP\IConfig;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
@@ -21,9 +20,9 @@ use Test\TestCase;
class ConnectionTest extends TestCase {
- private IClientService|MockObject $clientService;
- private IConfig|MockObject $config;
- private LoggerInterface|MockObject $logger;
+ private IClientService&MockObject $clientService;
+ private IAppConfig&MockObject $config;
+ private LoggerInterface&MockObject $logger;
private Connection $connection;
public function setUp(): void {
diff --git a/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php b/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php
index 82c03c5cf68..804af021d5a 100644
--- a/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php
+++ b/apps/dav/tests/unit/CalDAV/WebcalCaching/PluginTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php b/apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php
index d65a99a15e0..3252322ccff 100644
--- a/apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php
+++ b/apps/dav/tests/unit/CalDAV/WebcalCaching/RefreshWebcalServiceTest.php
@@ -20,10 +20,10 @@ use Sabre\VObject\Recur\NoInstancesException;
use Test\TestCase;
class RefreshWebcalServiceTest extends TestCase {
- private CalDavBackend|MockObject $caldavBackend;
- private Connection|MockObject $connection;
- private LoggerInterface|MockObject $logger;
- private ITimeFactory|MockObject $time;
+ private CalDavBackend&MockObject $caldavBackend;
+ private Connection&MockObject $connection;
+ private LoggerInterface&MockObject $logger;
+ private ITimeFactory&MockObject $time;
protected function setUp(): void {
parent::setUp();
@@ -35,10 +35,6 @@ class RefreshWebcalServiceTest extends TestCase {
}
/**
- * @param string $body
- * @param string $contentType
- * @param string $result
- *
* @dataProvider runDataProvider
*/
public function testRun(string $body, string $contentType, string $result): void {
@@ -88,10 +84,6 @@ class RefreshWebcalServiceTest extends TestCase {
}
/**
- * @param string $body
- * @param string $contentType
- * @param string $result
- *
* @dataProvider identicalDataProvider
*/
public function testRunIdentical(string $uid, array $calendarObject, string $body, string $contentType, string $result): void {
@@ -209,10 +201,6 @@ class RefreshWebcalServiceTest extends TestCase {
}
/**
- * @param string $body
- * @param string $contentType
- * @param string $result
- *
* @dataProvider runDataProvider
*/
public function testRunCreateCalendarNoException(string $body, string $contentType, string $result): void {
@@ -259,10 +247,6 @@ class RefreshWebcalServiceTest extends TestCase {
}
/**
- * @param string $body
- * @param string $contentType
- * @param string $result
- *
* @dataProvider runDataProvider
*/
public function testRunCreateCalendarBadRequest(string $body, string $contentType, string $result): void {
@@ -308,10 +292,7 @@ class RefreshWebcalServiceTest extends TestCase {
$refreshWebcalService->refreshSubscription('principals/users/testuser', 'sub123');
}
- /**
- * @return array
- */
- public static function identicalDataProvider():array {
+ public static function identicalDataProvider(): array {
return [
[
'12345',
@@ -330,10 +311,7 @@ class RefreshWebcalServiceTest extends TestCase {
];
}
- /**
- * @return array
- */
- public function runDataProvider():array {
+ public static function runDataProvider(): array {
return [
[
"BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:12345\r\nDTSTAMP:20160218T133704Z\r\nDTSTART;VALUE=DATE:19000101\r\nDTEND;VALUE=DATE:19000102\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:12345's Birthday (1900)\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n",
diff --git a/apps/dav/tests/unit/CapabilitiesTest.php b/apps/dav/tests/unit/CapabilitiesTest.php
index e99f7b8da5f..ad70d576d48 100644
--- a/apps/dav/tests/unit/CapabilitiesTest.php
+++ b/apps/dav/tests/unit/CapabilitiesTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -28,6 +30,7 @@ class CapabilitiesTest extends TestCase {
$expected = [
'dav' => [
'chunking' => '1.0',
+ 'public_shares_chunking' => true,
],
];
$this->assertSame($expected, $capabilities->getCapabilities());
@@ -47,6 +50,7 @@ class CapabilitiesTest extends TestCase {
$expected = [
'dav' => [
'chunking' => '1.0',
+ 'public_shares_chunking' => true,
'bulkupload' => '1.0',
],
];
@@ -67,6 +71,7 @@ class CapabilitiesTest extends TestCase {
$expected = [
'dav' => [
'chunking' => '1.0',
+ 'public_shares_chunking' => true,
'absence-supported' => true,
'absence-replacement' => true,
],
diff --git a/apps/dav/tests/unit/CardDAV/Activity/BackendTest.php b/apps/dav/tests/unit/CardDAV/Activity/BackendTest.php
index 134a6ca5ca0..4de1cf25cc5 100644
--- a/apps/dav/tests/unit/CardDAV/Activity/BackendTest.php
+++ b/apps/dav/tests/unit/CardDAV/Activity/BackendTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -20,20 +22,11 @@ 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;
-
- /** @var IUserManager|MockObject */
- protected $userManager;
+ protected IManager&MockObject $activityManager;
+ protected IGroupManager&MockObject $groupManager;
+ protected IUserSession&MockObject $userSession;
+ protected IAppManager&MockObject $appManager;
+ protected IUserManager&MockObject $userManager;
protected function setUp(): void {
parent::setUp();
@@ -45,10 +38,9 @@ class BackendTest extends TestCase {
}
/**
- * @param array $methods
* @return Backend|MockObject
*/
- protected function getBackend(array $methods = []) {
+ protected function getBackend(array $methods = []): Backend {
if (empty($methods)) {
return new Backend(
$this->activityManager,
@@ -71,7 +63,7 @@ class BackendTest extends TestCase {
}
}
- public function dataCallTriggerAddressBookActivity(): array {
+ public static function dataCallTriggerAddressBookActivity(): array {
return [
['onAddressbookCreate', [['data']], Addressbook::SUBJECT_ADD, [['data'], [], []]],
['onAddressbookUpdate', [['data'], ['shares'], ['changed-properties']], Addressbook::SUBJECT_UPDATE, [['data'], ['shares'], ['changed-properties']]],
@@ -95,7 +87,7 @@ class BackendTest extends TestCase {
call_user_func_array([$backend, $method], $payload);
}
- public function dataTriggerAddressBookActivity(): array {
+ public static function dataTriggerAddressBookActivity(): array {
return [
// Add addressbook
[Addressbook::SUBJECT_ADD, [], [], [], '', '', null, []],
@@ -160,12 +152,6 @@ class BackendTest extends TestCase {
/**
* @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
*/
@@ -219,13 +205,13 @@ class BackendTest extends TestCase {
->method('userExists')
->willReturn(true);
- $event->expects($this->exactly(sizeof($users)))
+ $event->expects($this->exactly(count($users)))
->method('setAffectedUser')
->willReturnSelf();
- $event->expects($this->exactly(sizeof($users)))
+ $event->expects($this->exactly(count($users)))
->method('setSubject')
->willReturnSelf();
- $this->activityManager->expects($this->exactly(sizeof($users)))
+ $this->activityManager->expects($this->exactly(count($users)))
->method('publish')
->with($event);
} else {
@@ -261,7 +247,7 @@ class BackendTest extends TestCase {
], [], []]);
}
- public function dataTriggerCardActivity(): array {
+ public static 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 [
@@ -330,12 +316,6 @@ class BackendTest extends TestCase {
/**
* @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
*/
@@ -385,13 +365,13 @@ class BackendTest extends TestCase {
->with($author)
->willReturnSelf();
- $event->expects($this->exactly(sizeof($users)))
+ $event->expects($this->exactly(count($users)))
->method('setAffectedUser')
->willReturnSelf();
- $event->expects($this->exactly(sizeof($users)))
+ $event->expects($this->exactly(count($users)))
->method('setSubject')
->willReturnSelf();
- $this->activityManager->expects($this->exactly(sizeof($users)))
+ $this->activityManager->expects($this->exactly(count($users)))
->method('publish')
->with($event);
} else {
@@ -409,7 +389,7 @@ class BackendTest extends TestCase {
$this->assertEmpty($this->invokePrivate($backend, 'triggerCardActivity', [Card::SUBJECT_UPDATE, ['principaluri' => 'principals/system/system'], [], []]));
}
- public function dataGetUsersForShares(): array {
+ public static function dataGetUsersForShares(): array {
return [
[
[],
@@ -454,9 +434,6 @@ class BackendTest extends TestCase {
/**
* @dataProvider dataGetUsersForShares
- * @param array $shares
- * @param array $groups
- * @param array $expected
*/
public function testGetUsersForShares(array $shares, array $groups, array $expected): void {
$backend = $this->getBackend();
@@ -498,10 +475,9 @@ class BackendTest extends TestCase {
}
/**
- * @param string $uid
* @return IUser|MockObject
*/
- protected function getUserMock(string $uid) {
+ protected function getUserMock(string $uid): IUser {
$user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('getUID')
diff --git a/apps/dav/tests/unit/CardDAV/AddressBookImplTest.php b/apps/dav/tests/unit/CardDAV/AddressBookImplTest.php
index a8bfc1b41fd..cfb14a5d567 100644
--- a/apps/dav/tests/unit/CardDAV/AddressBookImplTest.php
+++ b/apps/dav/tests/unit/CardDAV/AddressBookImplTest.php
@@ -12,32 +12,20 @@ use OCA\DAV\CardDAV\AddressBookImpl;
use OCA\DAV\CardDAV\CardDavBackend;
use OCA\DAV\Db\PropertyMapper;
use OCP\IURLGenerator;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\VObject\Component\VCard;
use Sabre\VObject\Property\Text;
//use Sabre\VObject\Property\;
use Test\TestCase;
class AddressBookImplTest extends TestCase {
- /** @var AddressBookImpl */
- private $addressBookImpl;
-
- /** @var array */
- private $addressBookInfo;
-
- /** @var AddressBook | \PHPUnit\Framework\MockObject\MockObject */
- private $addressBook;
-
- /** @var IURLGenerator | \PHPUnit\Framework\MockObject\MockObject */
- private $urlGenerator;
-
- /** @var CardDavBackend | \PHPUnit\Framework\MockObject\MockObject */
- private $backend;
-
- /** @var PropertyMapper | \PHPUnit\Framework\MockObject\MockObject */
- private $propertyMapper;
-
- /** @var VCard | \PHPUnit\Framework\MockObject\MockObject */
- private $vCard;
+ private array $addressBookInfo;
+ private AddressBook&MockObject $addressBook;
+ private IURLGenerator&MockObject $urlGenerator;
+ private CardDavBackend&MockObject $backend;
+ private PropertyMapper&MockObject $propertyMapper;
+ private VCard&MockObject $vCard;
+ private AddressBookImpl $addressBookImpl;
protected function setUp(): void {
parent::setUp();
@@ -48,10 +36,8 @@ class AddressBookImplTest extends TestCase {
'principaluri' => 'principals/system/system',
'{DAV:}displayname' => 'display name',
];
- $this->addressBook = $this->getMockBuilder(AddressBook::class)
- ->disableOriginalConstructor()->getMock();
- $this->backend = $this->getMockBuilder(CardDavBackend::class)
- ->disableOriginalConstructor()->getMock();
+ $this->addressBook = $this->createMock(AddressBook::class);
+ $this->backend = $this->createMock(CardDavBackend::class);
$this->vCard = $this->createMock(VCard::class);
$this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->propertyMapper = $this->createMock(PropertyMapper::class);
@@ -77,7 +63,7 @@ class AddressBookImplTest extends TestCase {
}
public function testSearch(): void {
- /** @var \PHPUnit\Framework\MockObject\MockObject | AddressBookImpl $addressBookImpl */
+ /** @var MockObject&AddressBookImpl $addressBookImpl */
$addressBookImpl = $this->getMockBuilder(AddressBookImpl::class)
->setConstructorArgs(
[
@@ -89,7 +75,7 @@ class AddressBookImplTest extends TestCase {
null
]
)
- ->setMethods(['vCard2Array', 'readCard'])
+ ->onlyMethods(['vCard2Array', 'readCard'])
->getMock();
$pattern = 'pattern';
@@ -107,10 +93,10 @@ class AddressBookImplTest extends TestCase {
$addressBookImpl->expects($this->exactly(2))->method('readCard')
->willReturn($this->vCard);
$addressBookImpl->expects($this->exactly(2))->method('vCard2Array')
- ->withConsecutive(
- ['foo.vcf', $this->vCard],
- ['bar.vcf', $this->vCard]
- )->willReturn('vCard');
+ ->willReturnMap([
+ ['foo.vcf', $this->vCard, 'vCard'],
+ ['bar.vcf', $this->vCard, 'vCard'],
+ ]);
$result = $addressBookImpl->search($pattern, $searchProperties, []);
$this->assertTrue((is_array($result)));
@@ -119,13 +105,11 @@ class AddressBookImplTest extends TestCase {
/**
* @dataProvider dataTestCreate
- *
- * @param array $properties
*/
- public function testCreate($properties): void {
+ public function testCreate(array $properties): void {
$uid = 'uid';
- /** @var \PHPUnit\Framework\MockObject\MockObject | AddressBookImpl $addressBookImpl */
+ /** @var MockObject&AddressBookImpl $addressBookImpl */
$addressBookImpl = $this->getMockBuilder(AddressBookImpl::class)
->setConstructorArgs(
[
@@ -137,7 +121,7 @@ class AddressBookImplTest extends TestCase {
null
]
)
- ->setMethods(['vCard2Array', 'createUid', 'createEmptyVCard'])
+ ->onlyMethods(['vCard2Array', 'createUid', 'createEmptyVCard'])
->getMock();
$expectedProperties = 0;
@@ -164,7 +148,7 @@ class AddressBookImplTest extends TestCase {
$this->assertTrue($addressBookImpl->createOrUpdate($properties));
}
- public function dataTestCreate() {
+ public static function dataTestCreate(): array {
return [
[[]],
[['FN' => 'John Doe']],
@@ -177,7 +161,7 @@ class AddressBookImplTest extends TestCase {
$uri = 'bla.vcf';
$properties = ['URI' => $uri, 'UID' => $uid, 'FN' => 'John Doe'];
- /** @var \PHPUnit\Framework\MockObject\MockObject | AddressBookImpl $addressBookImpl */
+ /** @var MockObject&AddressBookImpl $addressBookImpl */
$addressBookImpl = $this->getMockBuilder(AddressBookImpl::class)
->setConstructorArgs(
[
@@ -189,7 +173,7 @@ class AddressBookImplTest extends TestCase {
null
]
)
- ->setMethods(['vCard2Array', 'createUid', 'createEmptyVCard', 'readCard'])
+ ->onlyMethods(['vCard2Array', 'createUid', 'createEmptyVCard', 'readCard'])
->getMock();
$addressBookImpl->expects($this->never())->method('createUid');
@@ -216,7 +200,7 @@ class AddressBookImplTest extends TestCase {
$vCard = new vCard;
$textProperty = $vCard->createProperty('KEY', 'value');
- /** @var \PHPUnit\Framework\MockObject\MockObject | AddressBookImpl $addressBookImpl */
+ /** @var MockObject&AddressBookImpl $addressBookImpl */
$addressBookImpl = $this->getMockBuilder(AddressBookImpl::class)
->setConstructorArgs(
[
@@ -228,7 +212,7 @@ class AddressBookImplTest extends TestCase {
null
]
)
- ->setMethods(['vCard2Array', 'createUid', 'createEmptyVCard', 'readCard'])
+ ->onlyMethods(['vCard2Array', 'createUid', 'createEmptyVCard', 'readCard'])
->getMock();
$this->backend->expects($this->once())->method('getCard')
@@ -248,11 +232,8 @@ class AddressBookImplTest extends TestCase {
/**
* @dataProvider dataTestGetPermissions
- *
- * @param array $permissions
- * @param int $expected
*/
- public function testGetPermissions($permissions, $expected): void {
+ public function testGetPermissions(array $permissions, int $expected): void {
$this->addressBook->expects($this->once())->method('getACL')
->willReturn($permissions);
@@ -261,7 +242,7 @@ class AddressBookImplTest extends TestCase {
);
}
- public function dataTestGetPermissions() {
+ public static function dataTestGetPermissions(): array {
return [
[[], 0],
[[['privilege' => '{DAV:}read']], 1],
@@ -299,7 +280,7 @@ class AddressBookImplTest extends TestCase {
}
public function testCreateUid(): void {
- /** @var \PHPUnit\Framework\MockObject\MockObject | AddressBookImpl $addressBookImpl */
+ /** @var MockObject&AddressBookImpl $addressBookImpl */
$addressBookImpl = $this->getMockBuilder(AddressBookImpl::class)
->setConstructorArgs(
[
@@ -311,7 +292,7 @@ class AddressBookImplTest extends TestCase {
null
]
)
- ->setMethods(['getUid'])
+ ->onlyMethods(['getUid'])
->getMock();
$addressBookImpl->expects($this->exactly(2))
diff --git a/apps/dav/tests/unit/CardDAV/AddressBookTest.php b/apps/dav/tests/unit/CardDAV/AddressBookTest.php
index cbdb9a1402c..043b192e2c8 100644
--- a/apps/dav/tests/unit/CardDAV/AddressBookTest.php
+++ b/apps/dav/tests/unit/CardDAV/AddressBookTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -28,19 +29,20 @@ class AddressBookTest extends TestCase {
'uri' => 'default',
];
$l10n = $this->createMock(IL10N::class);
- $logger = $this->createMock(LoggerInterface::class);
- $addressBook = new AddressBook($backend, $addressBookInfo, $l10n, $logger);
+ $addressBook = new AddressBook($backend, $addressBookInfo, $l10n);
$card = new Card($backend, $addressBookInfo, ['id' => 5, 'carddata' => 'RANDOM VCF DATA', 'uri' => 'something', 'addressbookid' => 23]);
- $backend->expects($this->once())->method('moveCard')->with(23, 666, 'something', 'user1')->willReturn(true);
+ $backend->expects($this->once())->method('moveCard')
+ ->with(23, 666, 'something', 'user1')
+ ->willReturn(true);
$addressBook->moveInto('new', 'old', $card);
}
public function testDelete(): void {
/** @var MockObject | CardDavBackend $backend */
- $backend = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock();
+ $backend = $this->createMock(CardDavBackend::class);
$backend->expects($this->once())->method('updateShares');
$backend->expects($this->any())->method('getShares')->willReturn([
['href' => 'principal:user2']
@@ -54,7 +56,7 @@ class AddressBookTest extends TestCase {
];
$l10n = $this->createMock(IL10N::class);
$logger = $this->createMock(LoggerInterface::class);
- $addressBook = new AddressBook($backend, $addressBookInfo, $l10n, $logger);
+ $addressBook = new AddressBook($backend, $addressBookInfo, $l10n);
$addressBook->delete();
}
@@ -63,7 +65,7 @@ class AddressBookTest extends TestCase {
$this->expectException(Forbidden::class);
/** @var MockObject | CardDavBackend $backend */
- $backend = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock();
+ $backend = $this->createMock(CardDavBackend::class);
$backend->expects($this->never())->method('updateShares');
$backend->expects($this->any())->method('getShares')->willReturn([
['href' => 'principal:group2']
@@ -77,14 +79,14 @@ class AddressBookTest extends TestCase {
];
$l10n = $this->createMock(IL10N::class);
$logger = $this->createMock(LoggerInterface::class);
- $addressBook = new AddressBook($backend, $addressBookInfo, $l10n, $logger);
+ $addressBook = new AddressBook($backend, $addressBookInfo, $l10n);
$addressBook->delete();
}
public function testPropPatchShared(): void {
/** @var MockObject | CardDavBackend $backend */
- $backend = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock();
+ $backend = $this->createMock(CardDavBackend::class);
$backend->expects($this->never())->method('updateAddressBook');
$addressBookInfo = [
'{http://owncloud.org/ns}owner-principal' => 'user1',
@@ -95,13 +97,13 @@ class AddressBookTest extends TestCase {
];
$l10n = $this->createMock(IL10N::class);
$logger = $this->createMock(LoggerInterface::class);
- $addressBook = new AddressBook($backend, $addressBookInfo, $l10n, $logger);
+ $addressBook = new AddressBook($backend, $addressBookInfo, $l10n);
$addressBook->propPatch(new PropPatch(['{DAV:}displayname' => 'Test address book']));
}
public function testPropPatchNotShared(): void {
/** @var MockObject | CardDavBackend $backend */
- $backend = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock();
+ $backend = $this->createMock(CardDavBackend::class);
$backend->expects($this->atLeast(1))->method('updateAddressBook');
$addressBookInfo = [
'{DAV:}displayname' => 'Test address book',
@@ -111,16 +113,16 @@ class AddressBookTest extends TestCase {
];
$l10n = $this->createMock(IL10N::class);
$logger = $this->createMock(LoggerInterface::class);
- $addressBook = new AddressBook($backend, $addressBookInfo, $l10n, $logger);
+ $addressBook = new AddressBook($backend, $addressBookInfo, $l10n);
$addressBook->propPatch(new PropPatch(['{DAV:}displayname' => 'Test address book']));
}
/**
* @dataProvider providesReadOnlyInfo
*/
- public function testAcl($expectsWrite, $readOnlyValue, $hasOwnerSet): void {
+ public function testAcl(bool $expectsWrite, ?bool $readOnlyValue, bool $hasOwnerSet): void {
/** @var MockObject | CardDavBackend $backend */
- $backend = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock();
+ $backend = $this->createMock(CardDavBackend::class);
$backend->expects($this->any())->method('applyShareAcl')->willReturnArgument(1);
$addressBookInfo = [
'{DAV:}displayname' => 'Test address book',
@@ -136,7 +138,7 @@ class AddressBookTest extends TestCase {
}
$l10n = $this->createMock(IL10N::class);
$logger = $this->createMock(LoggerInterface::class);
- $addressBook = new AddressBook($backend, $addressBookInfo, $l10n, $logger);
+ $addressBook = new AddressBook($backend, $addressBookInfo, $l10n);
$acl = $addressBook->getACL();
$childAcl = $addressBook->getChildACL();
@@ -171,7 +173,7 @@ class AddressBookTest extends TestCase {
$this->assertEquals($expectedAcl, $childAcl);
}
- public function providesReadOnlyInfo(): array {
+ public static function providesReadOnlyInfo(): array {
return [
'read-only property not set' => [true, null, true],
'read-only property is false' => [true, false, true],
diff --git a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
index aeee04fd6ee..5a1210da339 100644
--- a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
+++ b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -14,25 +15,19 @@ use OCA\DAV\DAV\GroupPrincipalBackend;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IL10N;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\VObject\Component\VCalendar;
use Sabre\VObject\Reader;
use Test\TestCase;
class BirthdayServiceTest extends TestCase {
- /** @var BirthdayService */
- private $service;
- /** @var CalDavBackend | \PHPUnit\Framework\MockObject\MockObject */
- private $calDav;
- /** @var CardDavBackend | \PHPUnit\Framework\MockObject\MockObject */
- private $cardDav;
- /** @var GroupPrincipalBackend | \PHPUnit\Framework\MockObject\MockObject */
- private $groupPrincipalBackend;
- /** @var IConfig | \PHPUnit\Framework\MockObject\MockObject */
- private $config;
- /** @var IDBConnection | \PHPUnit\Framework\MockObject\MockObject */
- private $dbConnection;
- /** @var IL10N | \PHPUnit\Framework\MockObject\MockObject */
- private $l10n;
+ private CalDavBackend&MockObject $calDav;
+ private CardDavBackend&MockObject $cardDav;
+ private GroupPrincipalBackend&MockObject $groupPrincipalBackend;
+ private IConfig&MockObject $config;
+ private IDBConnection&MockObject $dbConnection;
+ private IL10N&MockObject $l10n;
+ private BirthdayService $service;
protected function setUp(): void {
parent::setUp();
@@ -57,16 +52,8 @@ class BirthdayServiceTest extends TestCase {
/**
* @dataProvider providesVCards
- * @param string $expectedSummary
- * @param string $expectedDTStart
- * @param string $expectedRrule
- * @param string $expectedFieldType
- * @param string $expectedUnknownYear
- * @param string $expectedOriginalYear
- * @param string|null $expectedReminder
- * @param string | null $data
*/
- public function testBuildBirthdayFromContact($expectedSummary, $expectedDTStart, $expectedRrule, $expectedFieldType, $expectedUnknownYear, $expectedOriginalYear, $expectedReminder, $data, $fieldType, $prefix, $supports4Bytes, $configuredReminder): void {
+ public function testBuildBirthdayFromContact(?string $expectedSummary, ?string $expectedDTStart, ?string $expectedRrule, ?string $expectedFieldType, ?string $expectedUnknownYear, ?string $expectedOriginalYear, ?string $expectedReminder, ?string $data, string $fieldType, string $prefix, bool $supports4Bytes, ?string $configuredReminder): void {
$this->dbConnection->method('supports4ByteText')->willReturn($supports4Bytes);
$cal = $this->service->buildDateFromContact($data, $fieldType, $prefix, $configuredReminder);
@@ -152,13 +139,17 @@ class BirthdayServiceTest extends TestCase {
->willReturn([
'id' => 1234
]);
- $this->calDav->expects($this->exactly(3))
+ $calls = [
+ [1234, 'default-gump.vcf.ics'],
+ [1234, 'default-gump.vcf-death.ics'],
+ [1234, 'default-gump.vcf-anniversary.ics'],
+ ];
+ $this->calDav->expects($this->exactly(count($calls)))
->method('deleteCalendarObject')
- ->withConsecutive(
- [1234, 'default-gump.vcf.ics'],
- [1234, 'default-gump.vcf-death.ics'],
- [1234, 'default-gump.vcf-anniversary.ics'],
- );
+ ->willReturnCallback(function ($calendarId, $objectUri) use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, [$calendarId, $objectUri]);
+ });
$this->cardDav->expects($this->once())->method('getShares')->willReturn([]);
$this->service->onCardDeleted(666, 'gump.vcf');
@@ -173,7 +164,7 @@ class BirthdayServiceTest extends TestCase {
$this->cardDav->expects($this->never())->method('getAddressBookById');
$service = $this->getMockBuilder(BirthdayService::class)
- ->setMethods(['buildDateFromContact', 'birthdayEvenChanged'])
+ ->onlyMethods(['buildDateFromContact', 'birthdayEvenChanged'])
->setConstructorArgs([$this->calDav, $this->cardDav, $this->groupPrincipalBackend, $this->config, $this->dbConnection, $this->l10n])
->getMock();
@@ -200,9 +191,9 @@ class BirthdayServiceTest extends TestCase {
$this->cardDav->expects($this->once())->method('getShares')->willReturn([]);
$this->calDav->expects($this->never())->method('getCalendarByUri');
- /** @var BirthdayService | \PHPUnit\Framework\MockObject\MockObject $service */
+ /** @var BirthdayService&MockObject $service */
$service = $this->getMockBuilder(BirthdayService::class)
- ->setMethods(['buildDateFromContact', 'birthdayEvenChanged'])
+ ->onlyMethods(['buildDateFromContact', 'birthdayEvenChanged'])
->setConstructorArgs([$this->calDav, $this->cardDav, $this->groupPrincipalBackend, $this->config, $this->dbConnection, $this->l10n])
->getMock();
@@ -212,7 +203,7 @@ class BirthdayServiceTest extends TestCase {
/**
* @dataProvider providesCardChanges
*/
- public function testOnCardChanged($expectedOp): void {
+ public function testOnCardChanged(string $expectedOp): void {
$this->config->expects($this->once())
->method('getAppValue')
->with('dav', 'generateBirthdayCalendar', 'yes')
@@ -220,11 +211,10 @@ class BirthdayServiceTest extends TestCase {
$this->config->expects($this->exactly(2))
->method('getUserValue')
- ->withConsecutive(
- ['user01', 'dav', 'generateBirthdayCalendar', 'yes'],
- ['user01', 'dav', 'birthdayCalendarReminderOffset', 'PT9H'],
- )
- ->willReturnOnConsecutiveCalls('yes', 'PT9H');
+ ->willReturnMap([
+ ['user01', 'dav', 'generateBirthdayCalendar', 'yes', 'yes'],
+ ['user01', 'dav', 'birthdayCalendarReminderOffset', 'PT9H', 'PT9H'],
+ ]);
$this->cardDav->expects($this->once())->method('getAddressBookById')
->with(666)
@@ -239,31 +229,45 @@ class BirthdayServiceTest extends TestCase {
]);
$this->cardDav->expects($this->once())->method('getShares')->willReturn([]);
- /** @var BirthdayService | \PHPUnit\Framework\MockObject\MockObject $service */
+ /** @var BirthdayService&MockObject $service */
$service = $this->getMockBuilder(BirthdayService::class)
- ->setMethods(['buildDateFromContact', 'birthdayEvenChanged'])
+ ->onlyMethods(['buildDateFromContact', 'birthdayEvenChanged'])
->setConstructorArgs([$this->calDav, $this->cardDav, $this->groupPrincipalBackend, $this->config, $this->dbConnection, $this->l10n])
->getMock();
if ($expectedOp === 'delete') {
$this->calDav->expects($this->exactly(3))->method('getCalendarObject')->willReturn('');
$service->expects($this->exactly(3))->method('buildDateFromContact')->willReturn(null);
- $this->calDav->expects($this->exactly(3))->method('deleteCalendarObject')->withConsecutive(
+
+ $calls = [
[1234, 'default-gump.vcf.ics'],
[1234, 'default-gump.vcf-death.ics'],
[1234, 'default-gump.vcf-anniversary.ics']
- );
+ ];
+ $this->calDav->expects($this->exactly(count($calls)))
+ ->method('deleteCalendarObject')
+ ->willReturnCallback(function ($calendarId, $objectUri) use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, [$calendarId, $objectUri]);
+ });
}
if ($expectedOp === 'create') {
$vCal = new VCalendar();
$vCal->PRODID = '-//Nextcloud testing//mocked object//';
$service->expects($this->exactly(3))->method('buildDateFromContact')->willReturn($vCal);
- $this->calDav->expects($this->exactly(3))->method('createCalendarObject')->withConsecutive(
+
+ $createCalendarObjectCalls = [
[1234, 'default-gump.vcf.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nCALSCALE:GREGORIAN\r\nPRODID:-//Nextcloud testing//mocked object//\r\nEND:VCALENDAR\r\n"],
[1234, 'default-gump.vcf-death.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nCALSCALE:GREGORIAN\r\nPRODID:-//Nextcloud testing//mocked object//\r\nEND:VCALENDAR\r\n"],
[1234, 'default-gump.vcf-anniversary.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nCALSCALE:GREGORIAN\r\nPRODID:-//Nextcloud testing//mocked object//\r\nEND:VCALENDAR\r\n"]
- );
+ ];
+ $this->calDav->expects($this->exactly(count($createCalendarObjectCalls)))
+ ->method('createCalendarObject')
+ ->willReturnCallback(function ($calendarId, $objectUri, $calendarData) use (&$createCalendarObjectCalls) {
+ $expected = array_shift($createCalendarObjectCalls);
+ $this->assertEquals($expected, [$calendarId, $objectUri, $calendarData]);
+ });
}
if ($expectedOp === 'update') {
$vCal = new VCalendar();
@@ -272,11 +276,18 @@ class BirthdayServiceTest extends TestCase {
$service->expects($this->exactly(3))->method('buildDateFromContact')->willReturn($vCal);
$service->expects($this->exactly(3))->method('birthdayEvenChanged')->willReturn(true);
$this->calDav->expects($this->exactly(3))->method('getCalendarObject')->willReturn(['calendardata' => '']);
- $this->calDav->expects($this->exactly(3))->method('updateCalendarObject')->withConsecutive(
+
+ $updateCalendarObjectCalls = [
[1234, 'default-gump.vcf.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nCALSCALE:GREGORIAN\r\nPRODID:-//Nextcloud testing//mocked object//\r\nEND:VCALENDAR\r\n"],
[1234, 'default-gump.vcf-death.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nCALSCALE:GREGORIAN\r\nPRODID:-//Nextcloud testing//mocked object//\r\nEND:VCALENDAR\r\n"],
[1234, 'default-gump.vcf-anniversary.ics', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nCALSCALE:GREGORIAN\r\nPRODID:-//Nextcloud testing//mocked object//\r\nEND:VCALENDAR\r\n"]
- );
+ ];
+ $this->calDav->expects($this->exactly(count($updateCalendarObjectCalls)))
+ ->method('updateCalendarObject')
+ ->willReturnCallback(function ($calendarId, $objectUri, $calendarData) use (&$updateCalendarObjectCalls) {
+ $expected = array_shift($updateCalendarObjectCalls);
+ $this->assertEquals($expected, [$calendarId, $objectUri, $calendarData]);
+ });
}
$service->onCardChanged(666, 'gump.vcf', '');
@@ -284,11 +295,8 @@ class BirthdayServiceTest extends TestCase {
/**
* @dataProvider providesBirthday
- * @param $expected
- * @param $old
- * @param $new
*/
- public function testBirthdayEvenChanged($expected, $old, $new): void {
+ public function testBirthdayEvenChanged(bool $expected, string $old, string $new): void {
$new = Reader::read($new);
$this->assertEquals($expected, $this->service->birthdayEvenChanged($old, $new));
}
@@ -354,18 +362,22 @@ class BirthdayServiceTest extends TestCase {
->with(42, 0)
->willReturn([['uri' => '1.ics'], ['uri' => '2.ics'], ['uri' => '3.ics']]);
- $this->calDav->expects($this->exactly(3))
+ $calls = [
+ [42, '1.ics', 0],
+ [42, '2.ics', 0],
+ [42, '3.ics', 0],
+ ];
+ $this->calDav->expects($this->exactly(count($calls)))
->method('deleteCalendarObject')
- ->withConsecutive(
- [42, '1.ics', 0],
- [42, '2.ics', 0],
- [42, '3.ics', 0],
- );
+ ->willReturnCallback(function ($calendarId, $objectUri, $calendarType) use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, [$calendarId, $objectUri, $calendarType]);
+ });
$this->service->resetForUser('user123');
}
- public function providesBirthday() {
+ public static function providesBirthday(): array {
return [
[true,
'',
@@ -382,7 +394,7 @@ class BirthdayServiceTest extends TestCase {
];
}
- public function providesCardChanges() {
+ public static function providesCardChanges(): array {
return[
['delete'],
['create'],
@@ -390,7 +402,7 @@ class BirthdayServiceTest extends TestCase {
];
}
- public function providesVCards() {
+ public static function providesVCards(): array {
return [
// $expectedSummary, $expectedDTStart, $expectedRrule, $expectedFieldType, $expectedUnknownYear, $expectedOriginalYear, $expectedReminder, $data, $fieldType, $prefix, $supports4Byte, $configuredReminder
[null, null, null, null, null, null, null, 'yasfewf', '', '', true, null],
diff --git a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
index 1516d41ea39..735f664a2bb 100644
--- a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
+++ b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
@@ -29,6 +29,7 @@ use OCP\IUserSession;
use OCP\L10N\IFactory;
use OCP\Server;
use OCP\Share\IManager as ShareManager;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Exception\BadRequest;
use Sabre\DAV\PropPatch;
@@ -45,64 +46,50 @@ use function time;
* @package OCA\DAV\Tests\unit\CardDAV
*/
class CardDavBackendTest extends TestCase {
- /** @var CardDavBackend */
- private $backend;
-
- /** @var Principal | \PHPUnit\Framework\MockObject\MockObject */
- private $principal;
-
- /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
- private $userManager;
-
- /** @var IGroupManager|\PHPUnit\Framework\MockObject\MockObject */
- private $groupManager;
-
- /** @var IEventDispatcher|MockObject */
- private $dispatcher;
+ private Principal&MockObject $principal;
+ private IUserManager&MockObject $userManager;
+ private IGroupManager&MockObject $groupManager;
+ private IEventDispatcher&MockObject $dispatcher;
private Backend $sharingBackend;
- /** @var IDBConnection */
- private $db;
-
- /** @var string */
- private $dbCardsTable = 'cards';
-
- /** @var string */
- private $dbCardsPropertiesTable = 'cards_properties';
+ private IDBConnection $db;
+ private CardDavBackend $backend;
+ private string $dbCardsTable = 'cards';
+ private string $dbCardsPropertiesTable = 'cards_properties';
public const UNIT_TEST_USER = 'principals/users/carddav-unit-test';
public const UNIT_TEST_USER1 = 'principals/users/carddav-unit-test1';
public const UNIT_TEST_GROUP = 'principals/groups/carddav-unit-test-group';
- private $vcardTest0 = 'BEGIN:VCARD' . PHP_EOL .
- 'VERSION:3.0' . PHP_EOL .
- 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL .
- 'UID:Test' . PHP_EOL .
- 'FN:Test' . PHP_EOL .
- 'N:Test;;;;' . PHP_EOL .
- 'END:VCARD';
-
- private $vcardTest1 = 'BEGIN:VCARD' . PHP_EOL .
- 'VERSION:3.0' . PHP_EOL .
- 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL .
- 'UID:Test2' . PHP_EOL .
- 'FN:Test2' . PHP_EOL .
- 'N:Test2;;;;' . PHP_EOL .
- 'END:VCARD';
-
- private $vcardTest2 = 'BEGIN:VCARD' . PHP_EOL .
- 'VERSION:3.0' . PHP_EOL .
- 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL .
- 'UID:Test3' . PHP_EOL .
- 'FN:Test3' . PHP_EOL .
- 'N:Test3;;;;' . PHP_EOL .
- 'END:VCARD';
-
- private $vcardTestNoUID = 'BEGIN:VCARD' . PHP_EOL .
- 'VERSION:3.0' . PHP_EOL .
- 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL .
- 'FN:TestNoUID' . PHP_EOL .
- 'N:TestNoUID;;;;' . PHP_EOL .
- 'END:VCARD';
+ private $vcardTest0 = 'BEGIN:VCARD' . PHP_EOL
+ . 'VERSION:3.0' . PHP_EOL
+ . 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL
+ . 'UID:Test' . PHP_EOL
+ . 'FN:Test' . PHP_EOL
+ . 'N:Test;;;;' . PHP_EOL
+ . 'END:VCARD';
+
+ private $vcardTest1 = 'BEGIN:VCARD' . PHP_EOL
+ . 'VERSION:3.0' . PHP_EOL
+ . 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL
+ . 'UID:Test2' . PHP_EOL
+ . 'FN:Test2' . PHP_EOL
+ . 'N:Test2;;;;' . PHP_EOL
+ . 'END:VCARD';
+
+ private $vcardTest2 = 'BEGIN:VCARD' . PHP_EOL
+ . 'VERSION:3.0' . PHP_EOL
+ . 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL
+ . 'UID:Test3' . PHP_EOL
+ . 'FN:Test3' . PHP_EOL
+ . 'N:Test3;;;;' . PHP_EOL
+ . 'END:VCARD';
+
+ private $vcardTestNoUID = 'BEGIN:VCARD' . PHP_EOL
+ . 'VERSION:3.0' . PHP_EOL
+ . 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL
+ . 'FN:TestNoUID' . PHP_EOL
+ . 'N:TestNoUID;;;;' . PHP_EOL
+ . 'END:VCARD';
protected function setUp(): void {
parent::setUp();
@@ -122,7 +109,7 @@ class CardDavBackendTest extends TestCase {
$this->createMock(IConfig::class),
$this->createMock(IFactory::class)
])
- ->setMethods(['getPrincipalByPath', 'getGroupMembership', 'findByUri'])
+ ->onlyMethods(['getPrincipalByPath', 'getGroupMembership', 'findByUri'])
->getMock();
$this->principal->method('getPrincipalByPath')
->willReturn([
@@ -151,16 +138,20 @@ class CardDavBackendTest extends TestCase {
);
// start every test with a empty cards_properties and cards table
$query = $this->db->getQueryBuilder();
- $query->delete('cards_properties')->execute();
+ $query->delete('cards_properties')->executeStatement();
$query = $this->db->getQueryBuilder();
- $query->delete('cards')->execute();
+ $query->delete('cards')->executeStatement();
- $this->tearDown();
+ $this->principal->method('getGroupMembership')
+ ->withAnyParameters()
+ ->willReturn([self::UNIT_TEST_GROUP]);
+ $books = $this->backend->getAddressBooksForUser(self::UNIT_TEST_USER);
+ foreach ($books as $book) {
+ $this->backend->deleteAddressBook($book['id']);
+ }
}
protected function tearDown(): void {
- parent::tearDown();
-
if (is_null($this->backend)) {
return;
}
@@ -172,6 +163,8 @@ class CardDavBackendTest extends TestCase {
foreach ($books as $book) {
$this->backend->deleteAddressBook($book['id']);
}
+
+ parent::tearDown();
}
public function testAddressBookOperations(): void {
@@ -236,10 +229,11 @@ class CardDavBackendTest extends TestCase {
}
public function testCardOperations(): void {
- /** @var CardDavBackend | \PHPUnit\Framework\MockObject\MockObject $backend */
+ /** @var CardDavBackend&MockObject $backend */
$backend = $this->getMockBuilder(CardDavBackend::class)
->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend])
- ->onlyMethods(['updateProperties', 'purgeProperties'])->getMock();
+ ->onlyMethods(['updateProperties', 'purgeProperties'])
+ ->getMock();
// create a new address book
$backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []);
@@ -249,12 +243,16 @@ class CardDavBackendTest extends TestCase {
$uri = $this->getUniqueID('card');
// updateProperties is expected twice, once for createCard and once for updateCard
- $backend->expects($this->exactly(2))
+ $calls = [
+ [$bookId, $uri, $this->vcardTest0],
+ [$bookId, $uri, $this->vcardTest1],
+ ];
+ $backend->expects($this->exactly(count($calls)))
->method('updateProperties')
- ->withConsecutive(
- [$bookId, $uri, $this->vcardTest0],
- [$bookId, $uri, $this->vcardTest1],
- );
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
// Expect event
$this->dispatcher
@@ -294,7 +292,8 @@ class CardDavBackendTest extends TestCase {
public function testMultiCard(): void {
$this->backend = $this->getMockBuilder(CardDavBackend::class)
->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend])
- ->setMethods(['updateProperties'])->getMock();
+ ->onlyMethods(['updateProperties'])
+ ->getMock();
// create a new address book
$this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []);
@@ -347,7 +346,8 @@ class CardDavBackendTest extends TestCase {
public function testMultipleUIDOnDifferentAddressbooks(): void {
$this->backend = $this->getMockBuilder(CardDavBackend::class)
->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend])
- ->onlyMethods(['updateProperties'])->getMock();
+ ->onlyMethods(['updateProperties'])
+ ->getMock();
// create 2 new address books
$this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []);
@@ -369,7 +369,8 @@ class CardDavBackendTest extends TestCase {
public function testMultipleUIDDenied(): void {
$this->backend = $this->getMockBuilder(CardDavBackend::class)
->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend])
- ->setMethods(['updateProperties'])->getMock();
+ ->onlyMethods(['updateProperties'])
+ ->getMock();
// create a new address book
$this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []);
@@ -390,7 +391,8 @@ class CardDavBackendTest extends TestCase {
public function testNoValidUID(): void {
$this->backend = $this->getMockBuilder(CardDavBackend::class)
->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend])
- ->setMethods(['updateProperties'])->getMock();
+ ->onlyMethods(['updateProperties'])
+ ->getMock();
// create a new address book
$this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []);
@@ -428,12 +430,17 @@ class CardDavBackendTest extends TestCase {
->method('getCardId')
->with($bookId, $uri)
->willThrowException(new \InvalidArgumentException());
- $this->backend->expects($this->exactly(2))
+
+ $calls = [
+ [$bookId, $uri, 1],
+ [$bookId, $uri, 3],
+ ];
+ $this->backend->expects($this->exactly(count($calls)))
->method('addChange')
- ->withConsecutive(
- [$bookId, $uri, 1],
- [$bookId, $uri, 3]
- );
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
$this->backend->expects($this->never())
->method('purgeProperties');
@@ -447,7 +454,8 @@ class CardDavBackendTest extends TestCase {
public function testSyncSupport(): void {
$this->backend = $this->getMockBuilder(CardDavBackend::class)
->setConstructorArgs([$this->db, $this->principal, $this->userManager, $this->dispatcher, $this->sharingBackend])
- ->setMethods(['updateProperties'])->getMock();
+ ->onlyMethods(['updateProperties'])
+ ->getMock();
// create a new address book
$this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []);
@@ -639,13 +647,8 @@ class CardDavBackendTest extends TestCase {
/**
* @dataProvider dataTestSearch
- *
- * @param string $pattern
- * @param array $properties
- * @param array $options
- * @param array $expected
*/
- public function testSearch($pattern, $properties, $options, $expected): void {
+ public function testSearch(string $pattern, array $properties, array $options, array $expected): void {
/** @var VCard $vCards */
$vCards = [];
$vCards[0] = new VCard();
@@ -756,7 +759,7 @@ class CardDavBackendTest extends TestCase {
$this->assertSame(count($expected), count($found));
}
- public function dataTestSearch() {
+ public static function dataTestSearch(): array {
return [
['John', ['FN'], [], [['uri0', 'John Doe'], ['uri1', 'John M. Doe']]],
['M. Doe', ['FN'], [], [['uri1', 'John M. Doe']]],
diff --git a/apps/dav/tests/unit/CardDAV/ContactsManagerTest.php b/apps/dav/tests/unit/CardDAV/ContactsManagerTest.php
index 80f1f2a4445..bdd826f671b 100644
--- a/apps/dav/tests/unit/CardDAV/ContactsManagerTest.php
+++ b/apps/dav/tests/unit/CardDAV/ContactsManagerTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -13,16 +14,17 @@ use OCA\DAV\Db\PropertyMapper;
use OCP\Contacts\IManager;
use OCP\IL10N;
use OCP\IURLGenerator;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class ContactsManagerTest extends TestCase {
public function test(): void {
- /** @var IManager | \PHPUnit\Framework\MockObject\MockObject $cm */
- $cm = $this->getMockBuilder(IManager::class)->disableOriginalConstructor()->getMock();
+ /** @var IManager&MockObject $cm */
+ $cm = $this->createMock(IManager::class);
$cm->expects($this->exactly(2))->method('registerAddressBook');
- $urlGenerator = $this->getMockBuilder(IURLGenerator::class)->disableOriginalConstructor()->getMock();
- /** @var CardDavBackend | \PHPUnit\Framework\MockObject\MockObject $backEnd */
- $backEnd = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock();
+ $urlGenerator = $this->createMock(IURLGenerator::class);
+ /** @var CardDavBackend&MockObject $backEnd */
+ $backEnd = $this->createMock(CardDavBackend::class);
$backEnd->method('getAddressBooksForUser')->willReturn([
['{DAV:}displayname' => 'Test address book', 'uri' => 'default'],
]);
diff --git a/apps/dav/tests/unit/CardDAV/ConverterTest.php b/apps/dav/tests/unit/CardDAV/ConverterTest.php
index c29e0db5070..59042ed91d4 100644
--- a/apps/dav/tests/unit/CardDAV/ConverterTest.php
+++ b/apps/dav/tests/unit/CardDAV/ConverterTest.php
@@ -22,17 +22,10 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class ConverterTest extends TestCase {
-
- /** @var IAccountManager|\PHPUnit\Framework\MockObject\MockObject */
- private $accountManager;
- /** @var IUserManager|(IUserManager&MockObject)|MockObject */
- private IUserManager|MockObject $userManager;
-
- /** @var IURLGenerator */
- private $urlGenerator;
-
- /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
- private $logger;
+ private IAccountManager&MockObject $accountManager;
+ private IUserManager&MockObject $userManager;
+ private IURLGenerator&MockObject $urlGenerator;
+ private LoggerInterface&MockObject $logger;
protected function setUp(): void {
parent::setUp();
@@ -44,7 +37,7 @@ class ConverterTest extends TestCase {
}
/**
- * @return IAccountProperty|MockObject
+ * @return IAccountProperty&MockObject
*/
protected function getAccountPropertyMock(string $name, ?string $value, string $scope) {
$property = $this->createMock(IAccountProperty::class);
@@ -77,10 +70,11 @@ class ConverterTest extends TestCase {
yield $this->getAccountPropertyMock(IAccountManager::PROPERTY_TWITTER, '', IAccountManager::SCOPE_LOCAL);
});
- $accountManager = $this->getMockBuilder(IAccountManager::class)
- ->disableOriginalConstructor()->getMock();
+ $accountManager = $this->createMock(IAccountManager::class);
- $accountManager->expects($this->any())->method('getAccount')->willReturn($account);
+ $accountManager->expects($this->any())
+ ->method('getAccount')
+ ->willReturn($account);
return $accountManager;
}
@@ -126,7 +120,7 @@ class ConverterTest extends TestCase {
);
}
- protected function compareData($expected, $data) {
+ protected function compareData(array $expected, array $data): void {
foreach ($expected as $key => $value) {
$found = false;
foreach ($data[1] as $d) {
@@ -141,7 +135,7 @@ class ConverterTest extends TestCase {
}
}
- public function providesNewUsers() {
+ public static function providesNewUsers(): array {
return [
[
null
@@ -197,17 +191,15 @@ class ConverterTest extends TestCase {
/**
* @dataProvider providesNames
- * @param $expected
- * @param $fullName
*/
- public function testNameSplitter($expected, $fullName): void {
+ public function testNameSplitter(string $expected, string $fullName): void {
$converter = new Converter($this->accountManager, $this->userManager, $this->urlGenerator, $this->logger);
$r = $converter->splitFullName($fullName);
$r = implode(';', $r);
$this->assertEquals($expected, $r);
}
- public function providesNames() {
+ public static function providesNames(): array {
return [
['Sauron;;;;', 'Sauron'],
['Baggins;Bilbo;;;', 'Bilbo Baggins'],
@@ -216,16 +208,13 @@ class ConverterTest extends TestCase {
}
/**
- * @param $displayName
- * @param $eMailAddress
- * @param $cloudId
- * @return IUser | \PHPUnit\Framework\MockObject\MockObject
+ * @return IUser&MockObject
*/
protected function getUserMock(string $displayName, ?string $eMailAddress, ?string $cloudId) {
- $image0 = $this->getMockBuilder(IImage::class)->disableOriginalConstructor()->getMock();
+ $image0 = $this->createMock(IImage::class);
$image0->method('mimeType')->willReturn('image/jpeg');
$image0->method('data')->willReturn('123456789');
- $user = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock();
+ $user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('12345');
$user->method('getDisplayName')->willReturn($displayName);
$user->method('getEMailAddress')->willReturn($eMailAddress);
diff --git a/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php b/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php
index d5c864d3e4e..8396234a819 100644
--- a/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php
+++ b/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -13,6 +14,7 @@ use OCA\DAV\CardDAV\PhotoCache;
use OCP\AppFramework\Http;
use OCP\Files\NotFoundException;
use OCP\Files\SimpleFS\ISimpleFile;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\CardDAV\Card;
use Sabre\DAV\Node;
use Sabre\DAV\Server;
@@ -22,18 +24,12 @@ use Sabre\HTTP\ResponseInterface;
use Test\TestCase;
class ImageExportPluginTest extends TestCase {
- /** @var ResponseInterface|\PHPUnit\Framework\MockObject\MockObject */
- private $response;
- /** @var RequestInterface|\PHPUnit\Framework\MockObject\MockObject */
- private $request;
- /** @var ImageExportPlugin|\PHPUnit\Framework\MockObject\MockObject */
- private $plugin;
- /** @var Server */
- private $server;
- /** @var Tree|\PHPUnit\Framework\MockObject\MockObject */
- private $tree;
- /** @var PhotoCache|\PHPUnit\Framework\MockObject\MockObject */
- private $cache;
+ private ResponseInterface&MockObject $response;
+ private RequestInterface&MockObject $request;
+ private Server&MockObject $server;
+ private Tree&MockObject $tree;
+ private PhotoCache&MockObject $cache;
+ private ImageExportPlugin $plugin;
protected function setUp(): void {
parent::setUp();
@@ -45,24 +41,20 @@ class ImageExportPluginTest extends TestCase {
$this->server->tree = $this->tree;
$this->cache = $this->createMock(PhotoCache::class);
- $this->plugin = $this->getMockBuilder(ImageExportPlugin::class)
- ->setMethods(['getPhoto'])
- ->setConstructorArgs([$this->cache])
- ->getMock();
+ $this->plugin = new ImageExportPlugin($this->cache);
$this->plugin->initialize($this->server);
}
/**
* @dataProvider providesQueryParams
- * @param $param
*/
- public function testQueryParams($param): void {
+ public function testQueryParams(array $param): void {
$this->request->expects($this->once())->method('getQueryParameters')->willReturn($param);
$result = $this->plugin->httpGet($this->request, $this->response);
$this->assertTrue($result);
}
- public function providesQueryParams() {
+ public static function providesQueryParams(): array {
return [
[[]],
[['1']],
@@ -87,7 +79,7 @@ class ImageExportPluginTest extends TestCase {
$this->assertTrue($result);
}
- public function dataTestCard() {
+ public static function dataTestCard(): array {
return [
[null, false],
[null, true],
@@ -98,11 +90,8 @@ class ImageExportPluginTest extends TestCase {
/**
* @dataProvider dataTestCard
- *
- * @param $size
- * @param bool $photo
*/
- public function testCard($size, $photo): void {
+ public function testCard(?int $size, bool $photo): void {
$query = ['photo' => null];
if ($size !== null) {
$query['size'] = $size;
@@ -145,14 +134,18 @@ class ImageExportPluginTest extends TestCase {
->with(1, 'card', $size, $card)
->willReturn($file);
- $this->response->expects($this->exactly(4))
+ $setHeaderCalls = [
+ ['Cache-Control', 'private, max-age=3600, must-revalidate'],
+ ['Etag', '"myEtag"'],
+ ['Content-Type', 'image/jpeg'],
+ ['Content-Disposition', 'attachment; filename=card.jpg'],
+ ];
+ $this->response->expects($this->exactly(count($setHeaderCalls)))
->method('setHeader')
- ->withConsecutive(
- ['Cache-Control', 'private, max-age=3600, must-revalidate'],
- ['Etag', '"myEtag"'],
- ['Content-Type', 'image/jpeg'],
- ['Content-Disposition', 'attachment; filename=card.jpg'],
- );
+ ->willReturnCallback(function () use (&$setHeaderCalls) {
+ $expected = array_shift($setHeaderCalls);
+ $this->assertEquals($expected, func_get_args());
+ });
$this->response->expects($this->once())
->method('setStatus')
@@ -161,12 +154,16 @@ class ImageExportPluginTest extends TestCase {
->method('setBody')
->with('imgdata');
} else {
- $this->response->expects($this->exactly(2))
+ $setHeaderCalls = [
+ ['Cache-Control', 'private, max-age=3600, must-revalidate'],
+ ['Etag', '"myEtag"'],
+ ];
+ $this->response->expects($this->exactly(count($setHeaderCalls)))
->method('setHeader')
- ->withConsecutive(
- ['Cache-Control', 'private, max-age=3600, must-revalidate'],
- ['Etag', '"myEtag"'],
- );
+ ->willReturnCallback(function () use (&$setHeaderCalls) {
+ $expected = array_shift($setHeaderCalls);
+ $this->assertEquals($expected, func_get_args());
+ });
$this->cache->method('get')
->with(1, 'card', $size, $card)
->willThrowException(new NotFoundException());
diff --git a/apps/dav/tests/unit/CardDAV/Security/CardDavRateLimitingPluginTest.php b/apps/dav/tests/unit/CardDAV/Security/CardDavRateLimitingPluginTest.php
index 33ab83a74ac..ee599d5a76c 100644
--- a/apps/dav/tests/unit/CardDAV/Security/CardDavRateLimitingPluginTest.php
+++ b/apps/dav/tests/unit/CardDAV/Security/CardDavRateLimitingPluginTest.php
@@ -24,11 +24,11 @@ use Test\TestCase;
class CardDavRateLimitingPluginTest extends TestCase {
- private Limiter|MockObject $limiter;
- private CardDavBackend|MockObject $cardDavBackend;
- private IUserManager|MockObject $userManager;
- private LoggerInterface|MockObject $logger;
- private IAppConfig|MockObject $config;
+ private Limiter&MockObject $limiter;
+ private CardDavBackend&MockObject $cardDavBackend;
+ private IUserManager&MockObject $userManager;
+ private LoggerInterface&MockObject $logger;
+ private IAppConfig&MockObject $config;
private string $userId = 'user123';
private CardDavRateLimitingPlugin $plugin;
diff --git a/apps/dav/tests/unit/CardDAV/Sharing/PluginTest.php b/apps/dav/tests/unit/CardDAV/Sharing/PluginTest.php
index f35eb9f0040..1e934a69a53 100644
--- a/apps/dav/tests/unit/CardDAV/Sharing/PluginTest.php
+++ b/apps/dav/tests/unit/CardDAV/Sharing/PluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -12,6 +13,7 @@ use OCA\DAV\DAV\Sharing\IShareable;
use OCA\DAV\DAV\Sharing\Plugin;
use OCP\IConfig;
use OCP\IRequest;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Server;
use Sabre\DAV\SimpleCollection;
use Sabre\HTTP\Request;
@@ -19,31 +21,25 @@ use Sabre\HTTP\Response;
use Test\TestCase;
class PluginTest extends TestCase {
-
- /** @var Plugin */
- private $plugin;
- /** @var Server */
- private $server;
- /** @var IShareable | \PHPUnit\Framework\MockObject\MockObject */
- private $book;
+ private Plugin $plugin;
+ private Server $server;
+ private IShareable&MockObject $book;
protected function setUp(): void {
parent::setUp();
- /** @var Auth | \PHPUnit\Framework\MockObject\MockObject $authBackend */
- $authBackend = $this->getMockBuilder(Auth::class)->disableOriginalConstructor()->getMock();
- $authBackend->method('isDavAuthenticated')->willReturn(true);
-
- /** @var IRequest $request */
- $request = $this->getMockBuilder(IRequest::class)->disableOriginalConstructor()->getMock();
+ $authBackend = $this->createMock(Auth::class);
+ $authBackend->method('isDavAuthenticated')
+ ->willReturn(true);
+ $request = $this->createMock(IRequest::class);
$config = $this->createMock(IConfig::class);
$this->plugin = new Plugin($authBackend, $request, $config);
$root = new SimpleCollection('root');
$this->server = new \Sabre\DAV\Server($root);
- /** @var SimpleCollection $node */
- $this->book = $this->getMockBuilder(IShareable::class)->disableOriginalConstructor()->getMock();
- $this->book->method('getName')->willReturn('addressbook1.vcf');
+ $this->book = $this->createMock(IShareable::class);
+ $this->book->method('getName')
+ ->willReturn('addressbook1.vcf');
$root->addChild($this->book);
$this->plugin->initialize($this->server);
}
diff --git a/apps/dav/tests/unit/CardDAV/SyncServiceTest.php b/apps/dav/tests/unit/CardDAV/SyncServiceTest.php
index 5af42e2ea4e..fd31ef36528 100644
--- a/apps/dav/tests/unit/CardDAV/SyncServiceTest.php
+++ b/apps/dav/tests/unit/CardDAV/SyncServiceTest.php
@@ -20,6 +20,7 @@ use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IUser;
use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Http\Client\ClientExceptionInterface;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
@@ -28,15 +29,18 @@ use Test\TestCase;
class SyncServiceTest extends TestCase {
- protected CardDavBackend $backend;
- protected IUserManager $userManager;
- protected IDBConnection $dbConnection;
+ protected CardDavBackend&MockObject $backend;
+ protected IUserManager&MockObject $userManager;
+ protected IDBConnection&MockObject $dbConnection;
protected LoggerInterface $logger;
- protected Converter $converter;
- protected IClient $client;
- protected IConfig $config;
+ protected Converter&MockObject $converter;
+ protected IClient&MockObject $client;
+ protected IConfig&MockObject $config;
protected SyncService $service;
+
public function setUp(): void {
+ parent::setUp();
+
$addressBook = [
'id' => 1,
'uri' => 'system',
@@ -293,8 +297,8 @@ END:VCARD';
}
public function testEnsureSystemAddressBookExists(): void {
- /** @var CardDavBackend | \PHPUnit\Framework\MockObject\MockObject $backend */
- $backend = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock();
+ /** @var CardDavBackend&MockObject $backend */
+ $backend = $this->createMock(CardDavBackend::class);
$backend->expects($this->exactly(1))->method('createAddressBook');
$backend->expects($this->exactly(2))
->method('getAddressBooksByUri')
@@ -303,10 +307,9 @@ END:VCARD';
[],
);
- /** @var IUserManager $userManager */
- $userManager = $this->getMockBuilder(IUserManager::class)->disableOriginalConstructor()->getMock();
+ $userManager = $this->createMock(IUserManager::class);
$dbConnection = $this->createMock(IDBConnection::class);
- $logger = $this->getMockBuilder(LoggerInterface::class)->disableOriginalConstructor()->getMock();
+ $logger = $this->createMock(LoggerInterface::class);
$converter = $this->createMock(Converter::class);
$clientService = $this->createMock(IClientService::class);
$config = $this->createMock(IConfig::class);
@@ -315,7 +318,7 @@ END:VCARD';
$ss->ensureSystemAddressBookExists('principals/users/adam', 'contacts', []);
}
- public function dataActivatedUsers() {
+ public static function dataActivatedUsers(): array {
return [
[true, 1, 1, 1],
[false, 0, 0, 3],
@@ -324,15 +327,9 @@ END:VCARD';
/**
* @dataProvider dataActivatedUsers
- *
- * @param boolean $activated
- * @param integer $createCalls
- * @param integer $updateCalls
- * @param integer $deleteCalls
- * @return void
*/
- public function testUpdateAndDeleteUser($activated, $createCalls, $updateCalls, $deleteCalls): void {
- /** @var CardDavBackend | \PHPUnit\Framework\MockObject\MockObject $backend */
+ public function testUpdateAndDeleteUser(bool $activated, int $createCalls, int $updateCalls, int $deleteCalls): void {
+ /** @var CardDavBackend | MockObject $backend */
$backend = $this->getMockBuilder(CardDavBackend::class)->disableOriginalConstructor()->getMock();
$logger = $this->getMockBuilder(LoggerInterface::class)->disableOriginalConstructor()->getMock();
@@ -348,12 +345,9 @@ END:VCARD';
->with('principals/system/system', 'system')
->willReturn(['id' => -1]);
- /** @var IUserManager | \PHPUnit\Framework\MockObject\MockObject $userManager */
- $userManager = $this->getMockBuilder(IUserManager::class)->disableOriginalConstructor()->getMock();
+ $userManager = $this->createMock(IUserManager::class);
$dbConnection = $this->createMock(IDBConnection::class);
-
- /** @var IUser | \PHPUnit\Framework\MockObject\MockObject $user */
- $user = $this->getMockBuilder(IUser::class)->disableOriginalConstructor()->getMock();
+ $user = $this->createMock(IUser::class);
$user->method('getBackendClassName')->willReturn('unittest');
$user->method('getUID')->willReturn('test-user');
$user->method('getCloudId')->willReturn('cloudId');
@@ -475,7 +469,7 @@ END:VCARD';
);
}
- public function providerUseAbsoluteUriReport(): array {
+ public static function providerUseAbsoluteUriReport(): array {
return [
['https://server.internal', 'https://server.internal/remote.php/dav/addressbooks/system/system/system'],
['https://server.internal/', 'https://server.internal/remote.php/dav/addressbooks/system/system/system'],
diff --git a/apps/dav/tests/unit/CardDAV/SystemAddressBookTest.php b/apps/dav/tests/unit/CardDAV/SystemAddressBookTest.php
index 806c71759f8..4a218fa4616 100644
--- a/apps/dav/tests/unit/CardDAV/SystemAddressBookTest.php
+++ b/apps/dav/tests/unit/CardDAV/SystemAddressBookTest.php
@@ -30,15 +30,15 @@ use Sabre\VObject\Reader;
use Test\TestCase;
class SystemAddressBookTest extends TestCase {
- private MockObject|BackendInterface $cardDavBackend;
+ private BackendInterface&MockObject $cardDavBackend;
private array $addressBookInfo;
- private IL10N|MockObject $l10n;
- private IConfig|MockObject $config;
+ private IL10N&MockObject $l10n;
+ private IConfig&MockObject $config;
private IUserSession $userSession;
- private IRequest|MockObject $request;
+ private IRequest&MockObject $request;
private array $server;
- private TrustedServers|MockObject $trustedServers;
- private IGroupManager|MockObject $groupManager;
+ private TrustedServers&MockObject $trustedServers;
+ private IGroupManager&MockObject $groupManager;
private SystemAddressbook $addressBook;
protected function setUp(): void {
diff --git a/apps/dav/tests/unit/CardDAV/Validation/CardDavValidatePluginTest.php b/apps/dav/tests/unit/CardDAV/Validation/CardDavValidatePluginTest.php
index 39155aace8b..058735ba32a 100644
--- a/apps/dav/tests/unit/CardDAV/Validation/CardDavValidatePluginTest.php
+++ b/apps/dav/tests/unit/CardDAV/Validation/CardDavValidatePluginTest.php
@@ -20,9 +20,9 @@ use Test\TestCase;
class CardDavValidatePluginTest extends TestCase {
private CardDavValidatePlugin $plugin;
- private IAppConfig|MockObject $config;
- private RequestInterface|MockObject $request;
- private ResponseInterface|MockObject $response;
+ private IAppConfig&MockObject $config;
+ private RequestInterface&MockObject $request;
+ private ResponseInterface&MockObject $response;
protected function setUp(): void {
parent::setUp();
@@ -36,7 +36,7 @@ class CardDavValidatePluginTest extends TestCase {
}
public function testPutSizeLessThenLimit(): void {
-
+
// construct method responses
$this->config
->method('getValueInt')
@@ -50,11 +50,11 @@ class CardDavValidatePluginTest extends TestCase {
$this->assertTrue(
$this->plugin->beforePut($this->request, $this->response)
);
-
+
}
public function testPutSizeMoreThenLimit(): void {
-
+
// construct method responses
$this->config
->method('getValueInt')
@@ -67,7 +67,7 @@ class CardDavValidatePluginTest extends TestCase {
$this->expectException(Forbidden::class);
// test condition
$this->plugin->beforePut($this->request, $this->response);
-
+
}
}
diff --git a/apps/dav/tests/unit/Command/DeleteCalendarTest.php b/apps/dav/tests/unit/Command/DeleteCalendarTest.php
index b621e6737d5..2bd269de6dc 100644
--- a/apps/dav/tests/unit/Command/DeleteCalendarTest.php
+++ b/apps/dav/tests/unit/Command/DeleteCalendarTest.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Command;
+namespace OCA\DAV\Tests\unit\Command;
use OCA\DAV\CalDAV\BirthdayService;
use OCA\DAV\CalDAV\CalDavBackend;
@@ -28,23 +28,12 @@ class DeleteCalendarTest extends TestCase {
public const USER = 'user';
public const NAME = 'calendar';
- /** @var CalDavBackend|MockObject */
- private $calDav;
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var IL10N|MockObject */
- private $l10n;
-
- /** @var IUserManager|MockObject */
- private $userManager;
-
- /** @var DeleteCalendar */
- private $command;
-
- /** @var MockObject|LoggerInterface */
- private $logger;
+ private CalDavBackend&MockObject $calDav;
+ private IConfig&MockObject $config;
+ private IL10N&MockObject $l10n;
+ private IUserManager&MockObject $userManager;
+ private LoggerInterface&MockObject $logger;
+ private DeleteCalendar $command;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/Command/ListAddressbooksTest.php b/apps/dav/tests/unit/Command/ListAddressbooksTest.php
index 2c6b1579042..624b0050bc5 100644
--- a/apps/dav/tests/unit/Command/ListAddressbooksTest.php
+++ b/apps/dav/tests/unit/Command/ListAddressbooksTest.php
@@ -5,7 +5,7 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Command;
+namespace OCA\DAV\Tests\unit\Command;
use OCA\DAV\CardDAV\CardDavBackend;
use OCA\DAV\Command\ListAddressbooks;
@@ -20,9 +20,8 @@ use Test\TestCase;
* @package OCA\DAV\Tests\Command
*/
class ListAddressbooksTest extends TestCase {
-
- private IUserManager|MockObject $userManager;
- private CardDavBackend|MockObject $cardDavBackend;
+ private IUserManager&MockObject $userManager;
+ private CardDavBackend&MockObject $cardDavBackend;
private ListAddressbooks $command;
public const USERNAME = 'username';
@@ -72,7 +71,7 @@ class ListAddressbooksTest extends TestCase {
$this->assertStringContainsString('User <' . self::USERNAME . "> has no addressbooks\n", $commandTester->getDisplay());
}
- public function dataExecute() {
+ public static function dataExecute(): array {
return [
[false, '✓'],
[true, 'x']
diff --git a/apps/dav/tests/unit/Command/ListCalendarSharesTest.php b/apps/dav/tests/unit/Command/ListCalendarSharesTest.php
new file mode 100644
index 00000000000..e5d4251cbf9
--- /dev/null
+++ b/apps/dav/tests/unit/Command/ListCalendarSharesTest.php
@@ -0,0 +1,172 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Tests\unit\Command;
+
+use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\Command\ListCalendarShares;
+use OCA\DAV\Connector\Sabre\Principal;
+use OCA\DAV\DAV\Sharing\SharingMapper;
+use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
+use Symfony\Component\Console\Tester\CommandTester;
+use Test\TestCase;
+
+class ListCalendarSharesTest extends TestCase {
+
+ private IUserManager&MockObject $userManager;
+ private Principal&MockObject $principal;
+ private CalDavBackend&MockObject $caldav;
+ private SharingMapper $sharingMapper;
+ private ListCalendarShares $command;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->principal = $this->createMock(Principal::class);
+ $this->caldav = $this->createMock(CalDavBackend::class);
+ $this->sharingMapper = $this->createMock(SharingMapper::class);
+
+ $this->command = new ListCalendarShares(
+ $this->userManager,
+ $this->principal,
+ $this->caldav,
+ $this->sharingMapper,
+ );
+ }
+
+ public function testUserUnknown(): void {
+ $user = 'bob';
+
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage("User $user is unknown");
+
+ $this->userManager->expects($this->once())
+ ->method('userExists')
+ ->with($user)
+ ->willReturn(false);
+
+ $commandTester = new CommandTester($this->command);
+ $commandTester->execute([
+ 'uid' => $user,
+ ]);
+ }
+
+ public function testPrincipalNotFound(): void {
+ $user = 'bob';
+
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage("Unable to fetch principal for user $user");
+
+ $this->userManager->expects($this->once())
+ ->method('userExists')
+ ->with($user)
+ ->willReturn(true);
+
+ $this->principal->expects($this->once())
+ ->method('getPrincipalByPath')
+ ->with('principals/users/' . $user)
+ ->willReturn(null);
+
+ $commandTester = new CommandTester($this->command);
+ $commandTester->execute([
+ 'uid' => $user,
+ ]);
+ }
+
+ public function testNoCalendarShares(): void {
+ $user = 'bob';
+
+ $this->userManager->expects($this->once())
+ ->method('userExists')
+ ->with($user)
+ ->willReturn(true);
+
+ $this->principal->expects($this->once())
+ ->method('getPrincipalByPath')
+ ->with('principals/users/' . $user)
+ ->willReturn([
+ 'uri' => 'principals/users/' . $user,
+ ]);
+
+ $this->principal->expects($this->once())
+ ->method('getGroupMembership')
+ ->willReturn([]);
+ $this->principal->expects($this->once())
+ ->method('getCircleMembership')
+ ->willReturn([]);
+
+ $this->sharingMapper->expects($this->once())
+ ->method('getSharesByPrincipals')
+ ->willReturn([]);
+
+ $commandTester = new CommandTester($this->command);
+ $commandTester->execute([
+ 'uid' => $user,
+ ]);
+
+ $this->assertStringContainsString(
+ "User $user has no calendar shares",
+ $commandTester->getDisplay()
+ );
+ }
+
+ public function testFilterByCalendarId(): void {
+ $user = 'bob';
+
+ $this->userManager->expects($this->once())
+ ->method('userExists')
+ ->with($user)
+ ->willReturn(true);
+
+ $this->principal->expects($this->once())
+ ->method('getPrincipalByPath')
+ ->with('principals/users/' . $user)
+ ->willReturn([
+ 'uri' => 'principals/users/' . $user,
+ ]);
+
+ $this->principal->expects($this->once())
+ ->method('getGroupMembership')
+ ->willReturn([]);
+ $this->principal->expects($this->once())
+ ->method('getCircleMembership')
+ ->willReturn([]);
+
+ $this->sharingMapper->expects($this->once())
+ ->method('getSharesByPrincipals')
+ ->willReturn([
+ [
+ 'id' => 1000,
+ 'principaluri' => 'principals/users/bob',
+ 'type' => 'calendar',
+ 'access' => 2,
+ 'resourceid' => 10
+ ],
+ [
+ 'id' => 1001,
+ 'principaluri' => 'principals/users/bob',
+ 'type' => 'calendar',
+ 'access' => 3,
+ 'resourceid' => 11
+ ],
+ ]);
+
+ $commandTester = new CommandTester($this->command);
+ $commandTester->execute([
+ 'uid' => $user,
+ '--calendar-id' => 10,
+ ]);
+
+ $this->assertStringNotContainsString(
+ '1001',
+ $commandTester->getDisplay()
+ );
+ }
+}
diff --git a/apps/dav/tests/unit/Command/ListCalendarsTest.php b/apps/dav/tests/unit/Command/ListCalendarsTest.php
index 1f5f9882ac4..247487433eb 100644
--- a/apps/dav/tests/unit/Command/ListCalendarsTest.php
+++ b/apps/dav/tests/unit/Command/ListCalendarsTest.php
@@ -1,14 +1,17 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Command;
+namespace OCA\DAV\Tests\unit\Command;
use OCA\DAV\CalDAV\BirthdayService;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\Command\ListCalendars;
use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\Console\Tester\CommandTester;
use Test\TestCase;
@@ -18,15 +21,9 @@ use Test\TestCase;
* @package OCA\DAV\Tests\Command
*/
class ListCalendarsTest extends TestCase {
-
- /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject $userManager */
- private $userManager;
-
- /** @var CalDavBackend|\PHPUnit\Framework\MockObject\MockObject $l10n */
- private $calDav;
-
- /** @var ListCalendars */
- private $command;
+ private IUserManager&MockObject $userManager;
+ private CalDavBackend&MockObject $calDav;
+ private ListCalendars $command;
public const USERNAME = 'username';
@@ -75,7 +72,7 @@ class ListCalendarsTest extends TestCase {
$this->assertStringContainsString('User <' . self::USERNAME . "> has no calendars\n", $commandTester->getDisplay());
}
- public function dataExecute() {
+ public static function dataExecute(): array {
return [
[false, '✓'],
[true, 'x']
diff --git a/apps/dav/tests/unit/Command/MoveCalendarTest.php b/apps/dav/tests/unit/Command/MoveCalendarTest.php
index 9b935ca3cdb..c481f5cf15b 100644
--- a/apps/dav/tests/unit/Command/MoveCalendarTest.php
+++ b/apps/dav/tests/unit/Command/MoveCalendarTest.php
@@ -1,9 +1,11 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Command;
+namespace OCA\DAV\Tests\unit\Command;
use InvalidArgumentException;
use OCA\DAV\CalDAV\CalDavBackend;
@@ -24,29 +26,14 @@ use Test\TestCase;
* @package OCA\DAV\Tests\Command
*/
class MoveCalendarTest extends TestCase {
- /** @var IUserManager|MockObject $userManager */
- private $userManager;
-
- /** @var IGroupManager|MockObject $groupManager */
- private $groupManager;
-
- /** @var \OCP\Share\IManager|MockObject $shareManager */
- private $shareManager;
-
- /** @var IConfig|MockObject $l10n */
- private $config;
-
- /** @var IL10N|MockObject $l10n */
- private $l10n;
-
- /** @var CalDavBackend|MockObject $l10n */
- private $calDav;
-
- /** @var MoveCalendar */
- private $command;
-
- /** @var LoggerInterface|MockObject */
- private $logger;
+ private IUserManager&MockObject $userManager;
+ private IGroupManager&MockObject $groupManager;
+ private \OCP\Share\IManager&MockObject $shareManager;
+ private IConfig&MockObject $config;
+ private IL10N&MockObject $l10n;
+ private CalDavBackend&MockObject $calDav;
+ private LoggerInterface&MockObject $logger;
+ private MoveCalendar $command;
protected function setUp(): void {
parent::setUp();
@@ -70,7 +57,7 @@ class MoveCalendarTest extends TestCase {
);
}
- public function dataExecute() {
+ public static function dataExecute(): array {
return [
[false, true],
[true, false]
@@ -79,23 +66,16 @@ class MoveCalendarTest extends TestCase {
/**
* @dataProvider dataExecute
- *
- * @param $userOriginExists
- * @param $userDestinationExists
*/
- public function testWithBadUserOrigin($userOriginExists, $userDestinationExists): void {
+ public function testWithBadUserOrigin(bool $userOriginExists, bool $userDestinationExists): void {
$this->expectException(\InvalidArgumentException::class);
$this->userManager->expects($this->exactly($userOriginExists ? 2 : 1))
->method('userExists')
- ->withConsecutive(
- ['user'],
- ['user2'],
- )
- ->willReturnOnConsecutiveCalls(
- $userOriginExists,
- $userDestinationExists,
- );
+ ->willReturnMap([
+ ['user', $userOriginExists],
+ ['user2', $userDestinationExists],
+ ]);
$commandTester = new CommandTester($this->command);
$commandTester->execute([
@@ -112,11 +92,10 @@ class MoveCalendarTest extends TestCase {
$this->userManager->expects($this->exactly(2))
->method('userExists')
- ->withConsecutive(
- ['user'],
- ['user2'],
- )
- ->willReturn(true);
+ ->willReturnMap([
+ ['user', true],
+ ['user2', true],
+ ]);
$this->calDav->expects($this->once())->method('getCalendarByUri')
->with('principals/users/user', 'personal')
@@ -137,20 +116,20 @@ class MoveCalendarTest extends TestCase {
$this->userManager->expects($this->exactly(2))
->method('userExists')
- ->withConsecutive(
- ['user'],
- ['user2'],
- )
- ->willReturn(true);
+ ->willReturnMap([
+ ['user', true],
+ ['user2', true],
+ ]);
$this->calDav->expects($this->exactly(2))
->method('getCalendarByUri')
- ->withConsecutive(
- ['principals/users/user', 'personal'],
- ['principals/users/user2', 'personal'],
- )
- ->willReturn([
- 'id' => 1234,
+ ->willReturnMap([
+ ['principals/users/user', 'personal', [
+ 'id' => 1234,
+ ]],
+ ['principals/users/user2', 'personal', [
+ 'id' => 1234,
+ ]],
]);
$commandTester = new CommandTester($this->command);
@@ -164,24 +143,19 @@ class MoveCalendarTest extends TestCase {
public function testMove(): void {
$this->userManager->expects($this->exactly(2))
->method('userExists')
- ->withConsecutive(
- ['user'],
- ['user2'],
- )
- ->willReturn(true);
+ ->willReturnMap([
+ ['user', true],
+ ['user2', true],
+ ]);
$this->calDav->expects($this->exactly(2))
->method('getCalendarByUri')
- ->withConsecutive(
- ['principals/users/user', 'personal'],
- ['principals/users/user2', 'personal'],
- )
- ->willReturnOnConsecutiveCalls(
- [
+ ->willReturnMap([
+ ['principals/users/user', 'personal', [
'id' => 1234,
- ],
- null,
- );
+ ]],
+ ['principals/users/user2', 'personal', null],
+ ]);
$this->calDav->expects($this->once())->method('getShares')
->with(1234)
@@ -197,7 +171,7 @@ class MoveCalendarTest extends TestCase {
$this->assertStringContainsString('[OK] Calendar <personal> was moved from user <user> to <user2>', $commandTester->getDisplay());
}
- public function dataTestMoveWithDestinationNotPartOfGroup(): array {
+ public static function dataTestMoveWithDestinationNotPartOfGroup(): array {
return [
[true],
[false]
@@ -210,25 +184,20 @@ class MoveCalendarTest extends TestCase {
public function testMoveWithDestinationNotPartOfGroup(bool $shareWithGroupMembersOnly): void {
$this->userManager->expects($this->exactly(2))
->method('userExists')
- ->withConsecutive(
- ['user'],
- ['user2'],
- )
- ->willReturn(true);
+ ->willReturnMap([
+ ['user', true],
+ ['user2', true],
+ ]);
$this->calDav->expects($this->exactly(2))
->method('getCalendarByUri')
- ->withConsecutive(
- ['principals/users/user', 'personal'],
- ['principals/users/user2', 'personal'],
- )
- ->willReturnOnConsecutiveCalls(
- [
+ ->willReturnMap([
+ ['principals/users/user', 'personal', [
'id' => 1234,
'uri' => 'personal',
- ],
- null,
- );
+ ]],
+ ['principals/users/user2', 'personal', null],
+ ]);
$this->shareManager->expects($this->once())->method('shareWithGroupMembersOnly')
->willReturn($shareWithGroupMembersOnly);
@@ -254,25 +223,20 @@ class MoveCalendarTest extends TestCase {
public function testMoveWithDestinationPartOfGroup(): void {
$this->userManager->expects($this->exactly(2))
->method('userExists')
- ->withConsecutive(
- ['user'],
- ['user2'],
- )
- ->willReturn(true);
+ ->willReturnMap([
+ ['user', true],
+ ['user2', true],
+ ]);
$this->calDav->expects($this->exactly(2))
->method('getCalendarByUri')
- ->withConsecutive(
- ['principals/users/user', 'personal'],
- ['principals/users/user2', 'personal'],
- )
- ->willReturnOnConsecutiveCalls(
- [
+ ->willReturnMap([
+ ['principals/users/user', 'personal', [
'id' => 1234,
'uri' => 'personal',
- ],
- null,
- );
+ ]],
+ ['principals/users/user2', 'personal', null],
+ ]);
$this->shareManager->expects($this->once())->method('shareWithGroupMembersOnly')
->willReturn(true);
@@ -300,26 +264,21 @@ class MoveCalendarTest extends TestCase {
public function testMoveWithDestinationNotPartOfGroupAndForce(): void {
$this->userManager->expects($this->exactly(2))
->method('userExists')
- ->withConsecutive(
- ['user'],
- ['user2'],
- )
- ->willReturn(true);
+ ->willReturnMap([
+ ['user', true],
+ ['user2', true],
+ ]);
$this->calDav->expects($this->exactly(2))
->method('getCalendarByUri')
- ->withConsecutive(
- ['principals/users/user', 'personal'],
- ['principals/users/user2', 'personal'],
- )
- ->willReturnOnConsecutiveCalls(
- [
+ ->willReturnMap([
+ ['principals/users/user', 'personal', [
'id' => 1234,
'uri' => 'personal',
'{DAV:}displayname' => 'Personal'
- ],
- null,
- );
+ ]],
+ ['principals/users/user2', 'personal', null],
+ ]);
$this->shareManager->expects($this->once())->method('shareWithGroupMembersOnly')
->willReturn(true);
@@ -345,7 +304,7 @@ class MoveCalendarTest extends TestCase {
$this->assertStringContainsString('[OK] Calendar <personal> was moved from user <user> to <user2>', $commandTester->getDisplay());
}
- public function dataTestMoveWithCalendarAlreadySharedToDestination(): array {
+ public static function dataTestMoveWithCalendarAlreadySharedToDestination(): array {
return [
[true],
[false]
@@ -358,26 +317,21 @@ class MoveCalendarTest extends TestCase {
public function testMoveWithCalendarAlreadySharedToDestination(bool $force): void {
$this->userManager->expects($this->exactly(2))
->method('userExists')
- ->withConsecutive(
- ['user'],
- ['user2'],
- )
- ->willReturn(true);
+ ->willReturnMap([
+ ['user', true],
+ ['user2', true],
+ ]);
$this->calDav->expects($this->exactly(2))
->method('getCalendarByUri')
- ->withConsecutive(
- ['principals/users/user', 'personal'],
- ['principals/users/user2', 'personal'],
- )
- ->willReturnOnConsecutiveCalls(
- [
+ ->willReturnMap([
+ ['principals/users/user', 'personal', [
'id' => 1234,
'uri' => 'personal',
'{DAV:}displayname' => 'Personal'
- ],
- null,
- );
+ ]],
+ ['principals/users/user2', 'personal', null],
+ ]);
$this->calDav->expects($this->once())->method('getShares')
->with(1234)
diff --git a/apps/dav/tests/unit/Command/RemoveInvalidSharesTest.php b/apps/dav/tests/unit/Command/RemoveInvalidSharesTest.php
index f2346c211ce..ec56aa64eb2 100644
--- a/apps/dav/tests/unit/Command/RemoveInvalidSharesTest.php
+++ b/apps/dav/tests/unit/Command/RemoveInvalidSharesTest.php
@@ -1,16 +1,16 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2018 ownCloud GmbH
* SPDX-License-Identifier: AGPL-3.0-only
*/
-namespace OCA\DAV\Tests\Unit\Command;
+namespace OCA\DAV\Tests\unit\Command;
use OCA\DAV\Command\RemoveInvalidShares;
use OCA\DAV\Connector\Sabre\Principal;
use OCP\IDBConnection;
-use OCP\Migration\IOutput;
use OCP\Server;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -37,18 +37,16 @@ class RemoveInvalidSharesTest extends TestCase {
public function test(): void {
$db = Server::get(IDBConnection::class);
- /** @var Principal | \PHPUnit\Framework\MockObject\MockObject $principal */
$principal = $this->createMock(Principal::class);
- /** @var IOutput | \PHPUnit\Framework\MockObject\MockObject $output */
- $output = $this->createMock(IOutput::class);
-
$repair = new RemoveInvalidShares($db, $principal);
$this->invokePrivate($repair, 'run', [$this->createMock(InputInterface::class), $this->createMock(OutputInterface::class)]);
$query = $db->getQueryBuilder();
- $result = $query->select('*')->from('dav_shares')
- ->where($query->expr()->eq('principaluri', $query->createNamedParameter('principal:unknown')))->execute();
+ $query->select('*')
+ ->from('dav_shares')
+ ->where($query->expr()->eq('principaluri', $query->createNamedParameter('principal:unknown')));
+ $result = $query->executeQuery();
$data = $result->fetchAll();
$result->closeCursor();
$this->assertEquals(0, count($data));
diff --git a/apps/dav/tests/unit/Comments/CommentsNodeTest.php b/apps/dav/tests/unit/Comments/CommentsNodeTest.php
index c253c59df0f..40da2e523c7 100644
--- a/apps/dav/tests/unit/Comments/CommentsNodeTest.php
+++ b/apps/dav/tests/unit/Comments/CommentsNodeTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -14,38 +15,26 @@ use OCP\Comments\MessageTooLongException;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\DAV\PropPatch;
class CommentsNodeTest extends \Test\TestCase {
-
- /** @var ICommentsManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $commentsManager;
-
- protected $comment;
- protected $node;
- protected $userManager;
- protected $logger;
- protected $userSession;
+ protected ICommentsManager&MockObject $commentsManager;
+ protected IComment&MockObject $comment;
+ protected IUserManager&MockObject $userManager;
+ protected LoggerInterface&MockObject $logger;
+ protected IUserSession&MockObject $userSession;
+ protected CommentNode $node;
protected function setUp(): void {
parent::setUp();
- $this->commentsManager = $this->getMockBuilder(ICommentsManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->comment = $this->getMockBuilder(IComment::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userSession = $this->getMockBuilder(IUserSession::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->logger = $this->getMockBuilder(LoggerInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->commentsManager = $this->createMock(ICommentsManager::class);
+ $this->comment = $this->createMock(IComment::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
$this->node = new CommentNode(
$this->commentsManager,
@@ -57,10 +46,7 @@ class CommentsNodeTest extends \Test\TestCase {
}
public function testDelete(): void {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('getUID')
->willReturn('alice');
@@ -92,10 +78,7 @@ class CommentsNodeTest extends \Test\TestCase {
public function testDeleteForbidden(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('getUID')
->willReturn('mallory');
@@ -144,10 +127,7 @@ class CommentsNodeTest extends \Test\TestCase {
public function testUpdateComment(): void {
$msg = 'Hello Earth';
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('getUID')
->willReturn('alice');
@@ -182,10 +162,7 @@ class CommentsNodeTest extends \Test\TestCase {
$msg = null;
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('getUID')
->willReturn('alice');
@@ -221,10 +198,7 @@ class CommentsNodeTest extends \Test\TestCase {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
$this->expectExceptionMessage('Message exceeds allowed character limit of');
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('getUID')
->willReturn('alice');
@@ -261,10 +235,7 @@ class CommentsNodeTest extends \Test\TestCase {
$msg = 'HaXX0r';
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('getUID')
->willReturn('mallory');
@@ -296,10 +267,7 @@ class CommentsNodeTest extends \Test\TestCase {
$msg = 'HaXX0r';
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $user = $this->createMock(IUser::class);
$user->expects($this->never())
->method('getUID');
@@ -344,10 +312,7 @@ class CommentsNodeTest extends \Test\TestCase {
}
public function testPropPatch(): void {
- $propPatch = $this->getMockBuilder(PropPatch::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $propPatch = $this->createMock(PropPatch::class);
$propPatch->expects($this->once())
->method('handle')
->with('{http://owncloud.org/ns}message');
@@ -396,11 +361,10 @@ class CommentsNodeTest extends \Test\TestCase {
$this->commentsManager->expects($this->exactly(2))
->method('resolveDisplayName')
- ->withConsecutive(
- [$this->equalTo('user'), $this->equalTo('alice')],
- [$this->equalTo('user'), $this->equalTo('bob')]
- )
- ->willReturnOnConsecutiveCalls('Alice Al-Isson', 'Unknown user');
+ ->willReturnMap([
+ ['user', 'alice', 'Alice Al-Isson'],
+ ['user', 'bob', 'Unknown user']
+ ]);
$this->comment->expects($this->once())
->method('getId')
@@ -491,7 +455,7 @@ class CommentsNodeTest extends \Test\TestCase {
$this->assertTrue(empty($expected));
}
- public function readCommentProvider() {
+ public static function readCommentProvider(): array {
$creationDT = new \DateTime('2016-01-19 18:48:00');
$diff = new \DateInterval('PT2H');
$readDT1 = clone $creationDT;
@@ -507,9 +471,8 @@ class CommentsNodeTest extends \Test\TestCase {
/**
* @dataProvider readCommentProvider
- * @param $expected
*/
- public function testGetPropertiesUnreadProperty($creationDT, $readDT, $expected): void {
+ public function testGetPropertiesUnreadProperty(\DateTime $creationDT, ?\DateTime $readDT, string $expected): void {
$this->comment->expects($this->any())
->method('getCreationDateTime')
->willReturn($creationDT);
diff --git a/apps/dav/tests/unit/Comments/CommentsPluginTest.php b/apps/dav/tests/unit/Comments/CommentsPluginTest.php
index 5ca0cedf04b..35638391e67 100644
--- a/apps/dav/tests/unit/Comments/CommentsPluginTest.php
+++ b/apps/dav/tests/unit/Comments/CommentsPluginTest.php
@@ -14,44 +14,30 @@ use OCP\Comments\IComment;
use OCP\Comments\ICommentsManager;
use OCP\IUser;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\INode;
use Sabre\DAV\Tree;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
class CommentsPluginTest extends \Test\TestCase {
- /** @var \Sabre\DAV\Server */
- private $server;
-
- /** @var Tree */
- private $tree;
-
- /** @var ICommentsManager */
- private $commentsManager;
-
- /** @var IUserSession */
- private $userSession;
-
- /** @var CommentsPluginImplementation */
- private $plugin;
+ private \Sabre\DAV\Server&MockObject $server;
+ private Tree&MockObject $tree;
+ private ICommentsManager&MockObject $commentsManager;
+ private IUserSession&MockObject $userSession;
+ private CommentsPluginImplementation $plugin;
protected function setUp(): void {
parent::setUp();
- $this->tree = $this->getMockBuilder(Tree::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->tree = $this->createMock(Tree::class);
- $this->server = $this->getMockBuilder('\Sabre\DAV\Server')
+ $this->server = $this->getMockBuilder(\Sabre\DAV\Server::class)
->setConstructorArgs([$this->tree])
- ->setMethods(['getRequestUri'])
+ ->onlyMethods(['getRequestUri'])
->getMock();
- $this->commentsManager = $this->getMockBuilder(ICommentsManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userSession = $this->getMockBuilder(IUserSession::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->commentsManager = $this->createMock(ICommentsManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
$this->plugin = new CommentsPluginImplementation($this->commentsManager, $this->userSession);
}
@@ -151,7 +137,7 @@ class CommentsPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
-
+
public function testCreateCommentInvalidObject(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
@@ -233,7 +219,7 @@ class CommentsPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
-
+
public function testCreateCommentInvalidActor(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
@@ -321,7 +307,7 @@ class CommentsPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
-
+
public function testCreateCommentUnsupportedMediaType(): void {
$this->expectException(\Sabre\DAV\Exception\UnsupportedMediaType::class);
@@ -409,7 +395,7 @@ class CommentsPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
-
+
public function testCreateCommentInvalidPayload(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
@@ -503,7 +489,7 @@ class CommentsPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
-
+
public function testCreateCommentMessageTooLong(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
$this->expectExceptionMessage('Message exceeds allowed character limit of');
@@ -597,7 +583,7 @@ class CommentsPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
-
+
public function testOnReportInvalidNode(): void {
$this->expectException(\Sabre\DAV\Exception\ReportNotSupported::class);
@@ -620,7 +606,7 @@ class CommentsPluginTest extends \Test\TestCase {
$this->plugin->onReport(CommentsPluginImplementation::REPORT_NAME, [], '/' . $path);
}
-
+
public function testOnReportInvalidReportName(): void {
$this->expectException(\Sabre\DAV\Exception\ReportNotSupported::class);
diff --git a/apps/dav/tests/unit/Comments/EntityCollectionTest.php b/apps/dav/tests/unit/Comments/EntityCollectionTest.php
index e5a68e5a726..fcf0748696c 100644
--- a/apps/dav/tests/unit/Comments/EntityCollectionTest.php
+++ b/apps/dav/tests/unit/Comments/EntityCollectionTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -14,36 +15,23 @@ use OCP\Comments\ICommentsManager;
use OCP\Comments\NotFoundException;
use OCP\IUserManager;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
class EntityCollectionTest extends \Test\TestCase {
-
- /** @var ICommentsManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $commentsManager;
- /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $userManager;
- /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
- protected $logger;
- /** @var EntityCollection */
- protected $collection;
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- protected $userSession;
+ protected ICommentsManager&MockObject $commentsManager;
+ protected IUserManager&MockObject $userManager;
+ protected LoggerInterface&MockObject $logger;
+ protected IUserSession&MockObject $userSession;
+ protected EntityCollection $collection;
protected function setUp(): void {
parent::setUp();
- $this->commentsManager = $this->getMockBuilder(ICommentsManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userSession = $this->getMockBuilder(IUserSession::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->logger = $this->getMockBuilder(LoggerInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->commentsManager = $this->createMock(ICommentsManager::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
$this->collection = new EntityCollection(
'19',
@@ -70,7 +58,7 @@ class EntityCollectionTest extends \Test\TestCase {
);
$node = $this->collection->getChild('55');
- $this->assertTrue($node instanceof CommentNode);
+ $this->assertInstanceOf(CommentNode::class, $node);
}
@@ -97,8 +85,8 @@ class EntityCollectionTest extends \Test\TestCase {
$result = $this->collection->getChildren();
- $this->assertSame(count($result), 1);
- $this->assertTrue($result[0] instanceof CommentNode);
+ $this->assertCount(1, $result);
+ $this->assertInstanceOf(CommentNode::class, $result[0]);
}
public function testFindChildren(): void {
@@ -114,8 +102,8 @@ class EntityCollectionTest extends \Test\TestCase {
$result = $this->collection->findChildren(5, 15, $dt);
- $this->assertSame(count($result), 1);
- $this->assertTrue($result[0] instanceof CommentNode);
+ $this->assertCount(1, $result);
+ $this->assertInstanceOf(CommentNode::class, $result[0]);
}
public function testChildExistsTrue(): void {
diff --git a/apps/dav/tests/unit/Comments/EntityTypeCollectionTest.php b/apps/dav/tests/unit/Comments/EntityTypeCollectionTest.php
index e5706099270..e5178a3e786 100644
--- a/apps/dav/tests/unit/Comments/EntityTypeCollectionTest.php
+++ b/apps/dav/tests/unit/Comments/EntityTypeCollectionTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -12,40 +13,25 @@ use OCA\DAV\Comments\EntityTypeCollection;
use OCP\Comments\ICommentsManager;
use OCP\IUserManager;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
class EntityTypeCollectionTest extends \Test\TestCase {
-
- /** @var ICommentsManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $commentsManager;
- /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $userManager;
- /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
- protected $logger;
- /** @var EntityTypeCollection */
- protected $collection;
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- protected $userSession;
+ protected ICommentsManager&MockObject $commentsManager;
+ protected IUserManager&MockObject $userManager;
+ protected LoggerInterface&MockObject $logger;
+ protected IUserSession&MockObject $userSession;
+ protected EntityTypeCollection $collection;
protected $childMap = [];
protected function setUp(): void {
parent::setUp();
- $this->commentsManager = $this->getMockBuilder(ICommentsManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userSession = $this->getMockBuilder(IUserSession::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->logger = $this->getMockBuilder(LoggerInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $instance = $this;
+ $this->commentsManager = $this->createMock(ICommentsManager::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
$this->collection = new EntityTypeCollection(
'files',
@@ -53,8 +39,8 @@ class EntityTypeCollectionTest extends \Test\TestCase {
$this->userManager,
$this->userSession,
$this->logger,
- function ($child) use ($instance) {
- return !empty($instance->childMap[$child]);
+ function ($child) {
+ return !empty($this->childMap[$child]);
}
);
}
@@ -72,7 +58,7 @@ class EntityTypeCollectionTest extends \Test\TestCase {
$this->childMap[17] = true;
$ec = $this->collection->getChild('17');
- $this->assertTrue($ec instanceof EntityCollectionImplemantation);
+ $this->assertInstanceOf(EntityCollectionImplemantation::class, $ec);
}
diff --git a/apps/dav/tests/unit/Comments/RootCollectionTest.php b/apps/dav/tests/unit/Comments/RootCollectionTest.php
index 5d9e828f687..9a05d996c8c 100644
--- a/apps/dav/tests/unit/Comments/RootCollectionTest.php
+++ b/apps/dav/tests/unit/Comments/RootCollectionTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -16,44 +17,27 @@ use OCP\EventDispatcher\IEventDispatcher;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
class RootCollectionTest extends \Test\TestCase {
-
- /** @var ICommentsManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $commentsManager;
- /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $userManager;
- /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
- protected $logger;
- /** @var RootCollection */
- protected $collection;
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- protected $userSession;
- /** @var IEventDispatcher */
- protected $dispatcher;
- /** @var IUser|\PHPUnit\Framework\MockObject\MockObject */
- protected $user;
+ protected ICommentsManager&MockObject $commentsManager;
+ protected IUserManager&MockObject $userManager;
+ protected LoggerInterface&MockObject $logger;
+ protected IUserSession&MockObject $userSession;
+ protected IEventDispatcher $dispatcher;
+ protected IUser&MockObject $user;
+ protected RootCollection $collection;
protected function setUp(): void {
parent::setUp();
- $this->user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->commentsManager = $this->getMockBuilder(ICommentsManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userSession = $this->getMockBuilder(IUserSession::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->logger = $this->getMockBuilder(LoggerInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->user = $this->createMock(IUser::class);
+
+ $this->commentsManager = $this->createMock(ICommentsManager::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->logger = $this->createMock(LoggerInterface::class);
$this->dispatcher = new EventDispatcher(
new \Symfony\Component\EventDispatcher\EventDispatcher(),
\OC::$server,
@@ -69,7 +53,7 @@ class RootCollectionTest extends \Test\TestCase {
);
}
- protected function prepareForInitCollections() {
+ protected function prepareForInitCollections(): void {
$this->user->expects($this->any())
->method('getUID')
->willReturn('alice');
@@ -102,7 +86,7 @@ class RootCollectionTest extends \Test\TestCase {
public function testGetChild(): void {
$this->prepareForInitCollections();
$etc = $this->collection->getChild('files');
- $this->assertTrue($etc instanceof EntityTypeCollectionImplementation);
+ $this->assertInstanceOf(EntityTypeCollectionImplementation::class, $etc);
}
@@ -125,7 +109,7 @@ class RootCollectionTest extends \Test\TestCase {
$children = $this->collection->getChildren();
$this->assertFalse(empty($children));
foreach ($children as $child) {
- $this->assertTrue($child instanceof EntityTypeCollectionImplementation);
+ $this->assertInstanceOf(EntityTypeCollectionImplementation::class, $child);
}
}
diff --git a/apps/dav/tests/unit/Connector/LegacyPublicAuthTest.php b/apps/dav/tests/unit/Connector/LegacyPublicAuthTest.php
index 2bb68374162..8b8c775c8ec 100644
--- a/apps/dav/tests/unit/Connector/LegacyPublicAuthTest.php
+++ b/apps/dav/tests/unit/Connector/LegacyPublicAuthTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -14,6 +15,7 @@ use OCP\Security\Bruteforce\IThrottler;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager;
use OCP\Share\IShare;
+use PHPUnit\Framework\MockObject\MockObject;
/**
* Class LegacyPublicAuthTest
@@ -23,36 +25,20 @@ use OCP\Share\IShare;
* @package OCA\DAV\Tests\unit\Connector
*/
class LegacyPublicAuthTest extends \Test\TestCase {
-
- /** @var ISession|\PHPUnit\Framework\MockObject\MockObject */
- private $session;
- /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
- private $request;
- /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
- private $shareManager;
- /** @var LegacyPublicAuth */
- private $auth;
- /** @var IThrottler|\PHPUnit\Framework\MockObject\MockObject */
- private $throttler;
-
- /** @var string */
- private $oldUser;
+ private ISession&MockObject $session;
+ private IRequest&MockObject $request;
+ private IManager&MockObject $shareManager;
+ private IThrottler&MockObject $throttler;
+ private LegacyPublicAuth $auth;
+ private string|false $oldUser;
protected function setUp(): void {
parent::setUp();
- $this->session = $this->getMockBuilder(ISession::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->request = $this->getMockBuilder(IRequest::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->shareManager = $this->getMockBuilder(IManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->throttler = $this->getMockBuilder(IThrottler::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->session = $this->createMock(ISession::class);
+ $this->request = $this->createMock(IRequest::class);
+ $this->shareManager = $this->createMock(IManager::class);
+ $this->throttler = $this->createMock(IThrottler::class);
$this->auth = new LegacyPublicAuth(
$this->request,
@@ -70,7 +56,9 @@ class LegacyPublicAuthTest extends \Test\TestCase {
// Set old user
\OC_User::setUserId($this->oldUser);
- \OC_Util::setupFS($this->oldUser);
+ if ($this->oldUser !== false) {
+ \OC_Util::setupFS($this->oldUser);
+ }
parent::tearDown();
}
@@ -86,9 +74,7 @@ class LegacyPublicAuthTest extends \Test\TestCase {
}
public function testShareNoPassword(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn(null);
$this->shareManager->expects($this->once())
@@ -101,9 +87,7 @@ class LegacyPublicAuthTest extends \Test\TestCase {
}
public function testSharePasswordFancyShareType(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(42);
@@ -118,9 +102,7 @@ class LegacyPublicAuthTest extends \Test\TestCase {
public function testSharePasswordRemote(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_REMOTE);
@@ -134,9 +116,7 @@ class LegacyPublicAuthTest extends \Test\TestCase {
}
public function testSharePasswordLinkValidPassword(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
@@ -156,9 +136,7 @@ class LegacyPublicAuthTest extends \Test\TestCase {
}
public function testSharePasswordMailValidPassword(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);
@@ -178,9 +156,7 @@ class LegacyPublicAuthTest extends \Test\TestCase {
}
public function testInvalidSharePasswordLinkValidSession(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
$share->method('getId')->willReturn('42');
@@ -204,9 +180,7 @@ class LegacyPublicAuthTest extends \Test\TestCase {
}
public function testSharePasswordLinkInvalidSession(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
$share->method('getId')->willReturn('42');
@@ -231,9 +205,7 @@ class LegacyPublicAuthTest extends \Test\TestCase {
public function testSharePasswordMailInvalidSession(): void {
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);
$share->method('getId')->willReturn('42');
diff --git a/apps/dav/tests/unit/Connector/Sabre/AuthTest.php b/apps/dav/tests/unit/Connector/Sabre/AuthTest.php
index c6d247b3951..501ef3ef1d1 100644
--- a/apps/dav/tests/unit/Connector/Sabre/AuthTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/AuthTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -29,33 +30,20 @@ use Test\TestCase;
* @group DB
*/
class AuthTest extends TestCase {
- /** @var ISession&MockObject */
- private $session;
- /** @var Auth */
- private $auth;
- /** @var Session&MockObject */
- private $userSession;
- /** @var IRequest&MockObject */
- private $request;
- /** @var Manager&MockObject */
- private $twoFactorManager;
- /** @var IThrottler&MockObject */
- private $throttler;
+ private ISession&MockObject $session;
+ private Session&MockObject $userSession;
+ private IRequest&MockObject $request;
+ private Manager&MockObject $twoFactorManager;
+ private IThrottler&MockObject $throttler;
+ private Auth $auth;
protected function setUp(): void {
parent::setUp();
- $this->session = $this->getMockBuilder(ISession::class)
- ->disableOriginalConstructor()->getMock();
- $this->userSession = $this->getMockBuilder(Session::class)
- ->disableOriginalConstructor()->getMock();
- $this->request = $this->getMockBuilder(IRequest::class)
- ->disableOriginalConstructor()->getMock();
- $this->twoFactorManager = $this->getMockBuilder(Manager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->throttler = $this->getMockBuilder(IThrottler::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->session = $this->createMock(ISession::class);
+ $this->userSession = $this->createMock(Session::class);
+ $this->request = $this->createMock(IRequest::class);
+ $this->twoFactorManager = $this->createMock(Manager::class);
+ $this->throttler = $this->createMock(IThrottler::class);
$this->auth = new Auth(
$this->session,
$this->userSession,
@@ -72,7 +60,7 @@ class AuthTest extends TestCase {
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn(null);
- $this->assertFalse($this->invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
+ $this->assertFalse(self::invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
}
public function testIsDavAuthenticatedWithWrongDavSession(): void {
@@ -82,7 +70,7 @@ class AuthTest extends TestCase {
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn('AnotherUser');
- $this->assertFalse($this->invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
+ $this->assertFalse(self::invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
}
public function testIsDavAuthenticatedWithCorrectDavSession(): void {
@@ -92,13 +80,11 @@ class AuthTest extends TestCase {
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn('MyTestUser');
- $this->assertTrue($this->invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
+ $this->assertTrue(self::invokePrivate($this->auth, 'isDavAuthenticated', ['MyTestUser']));
}
public function testValidateUserPassOfAlreadyDAVAuthenticatedUser(): void {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->exactly(1))
->method('getUID')
->willReturn('MyTestUser');
@@ -119,13 +105,11 @@ class AuthTest extends TestCase {
->expects($this->once())
->method('close');
- $this->assertTrue($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
+ $this->assertTrue(self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
}
public function testValidateUserPassOfInvalidDAVAuthenticatedUser(): void {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('getUID')
->willReturn('MyTestUser');
@@ -146,13 +130,11 @@ class AuthTest extends TestCase {
->expects($this->once())
->method('close');
- $this->assertFalse($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
+ $this->assertFalse(self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
}
public function testValidateUserPassOfInvalidDAVAuthenticatedUserWithValidPassword(): void {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->exactly(2))
->method('getUID')
->willReturn('MyTestUser');
@@ -182,7 +164,7 @@ class AuthTest extends TestCase {
->expects($this->once())
->method('close');
- $this->assertTrue($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
+ $this->assertTrue(self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
}
public function testValidateUserPassWithInvalidPassword(): void {
@@ -199,7 +181,7 @@ class AuthTest extends TestCase {
->expects($this->once())
->method('close');
- $this->assertFalse($this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
+ $this->assertFalse(self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']));
}
@@ -219,16 +201,12 @@ class AuthTest extends TestCase {
->expects($this->once())
->method('close');
- $this->invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']);
+ self::invokePrivate($this->auth, 'validateUserPass', ['MyTestUser', 'MyTestPassword']);
}
public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenForNonGet(): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->any())
->method('isLoggedIn')
@@ -242,9 +220,7 @@ class AuthTest extends TestCase {
->method('get')
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn(null);
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('MyWrongDavUser');
@@ -266,12 +242,8 @@ class AuthTest extends TestCase {
}
public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenAndCorrectlyDavAuthenticated(): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->any())
->method('isLoggedIn')
@@ -289,9 +261,7 @@ class AuthTest extends TestCase {
->method('get')
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn('LoggedInUser');
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('LoggedInUser');
@@ -311,12 +281,8 @@ class AuthTest extends TestCase {
$this->expectException(\Sabre\DAV\Exception\NotAuthenticated::class);
$this->expectExceptionMessage('2FA challenge not passed.');
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->any())
->method('isLoggedIn')
@@ -334,9 +300,7 @@ class AuthTest extends TestCase {
->method('get')
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn('LoggedInUser');
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('LoggedInUser');
@@ -360,12 +324,8 @@ class AuthTest extends TestCase {
$this->expectException(\Sabre\DAV\Exception\NotAuthenticated::class);
$this->expectExceptionMessage('CSRF check not passed.');
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->any())
->method('isLoggedIn')
@@ -383,9 +343,7 @@ class AuthTest extends TestCase {
->method('get')
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn('AnotherUser');
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('LoggedInUser');
@@ -401,12 +359,8 @@ class AuthTest extends TestCase {
}
public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenForNonGetAndDesktopClient(): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->any())
->method('isLoggedIn')
@@ -424,9 +378,7 @@ class AuthTest extends TestCase {
->method('get')
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn(null);
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('MyWrongDavUser');
@@ -443,12 +395,8 @@ class AuthTest extends TestCase {
}
public function testAuthenticateAlreadyLoggedInWithoutCsrfTokenForGet(): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->any())
->method('isLoggedIn')
@@ -458,9 +406,7 @@ class AuthTest extends TestCase {
->method('get')
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn(null);
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('MyWrongDavUser');
@@ -478,12 +424,8 @@ class AuthTest extends TestCase {
}
public function testAuthenticateAlreadyLoggedInWithCsrfTokenForGet(): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->any())
->method('isLoggedIn')
@@ -493,9 +435,7 @@ class AuthTest extends TestCase {
->method('get')
->with('AUTHENTICATED_TO_DAV_BACKEND')
->willReturn(null);
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('MyWrongDavUser');
@@ -513,15 +453,9 @@ class AuthTest extends TestCase {
}
public function testAuthenticateNoBasicAuthenticateHeadersProvided(): void {
- $server = $this->getMockBuilder(Server::class)
- ->disableOriginalConstructor()
- ->getMock();
- $server->httpRequest = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $server->httpResponse = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $server = $this->createMock(Server::class);
+ $server->httpRequest = $this->createMock(RequestInterface::class);
+ $server->httpResponse = $this->createMock(ResponseInterface::class);
$response = $this->auth->check($server->httpRequest, $server->httpResponse);
$this->assertEquals([false, 'No \'Authorization: Basic\' header found. Either the client didn\'t send one, or the server is misconfigured'], $response);
}
@@ -532,13 +466,9 @@ class AuthTest extends TestCase {
$this->expectExceptionMessage('Cannot authenticate over ajax calls');
/** @var \Sabre\HTTP\RequestInterface&MockObject $httpRequest */
- $httpRequest = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $httpRequest = $this->createMock(RequestInterface::class);
/** @var \Sabre\HTTP\ResponseInterface&MockObject $httpResponse */
- $httpResponse = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $httpResponse = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->any())
->method('isLoggedIn')
@@ -562,13 +492,9 @@ class AuthTest extends TestCase {
->willReturn(false);
/** @var \Sabre\HTTP\RequestInterface&MockObject $httpRequest */
- $httpRequest = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $httpRequest = $this->createMock(RequestInterface::class);
/** @var \Sabre\HTTP\ResponseInterface&MockObject $httpResponse */
- $httpResponse = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $httpResponse = $this->createMock(ResponseInterface::class);
$httpRequest
->expects($this->any())
->method('getHeader')
@@ -577,9 +503,7 @@ class AuthTest extends TestCase {
['Authorization', 'basic dXNlcm5hbWU6cGFzc3dvcmQ='],
]);
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('MyDavUser');
@@ -602,17 +526,10 @@ class AuthTest extends TestCase {
public function testAuthenticateNoBasicAuthenticateHeadersProvidedWithAjaxButUserIsStillLoggedIn(): void {
/** @var \Sabre\HTTP\RequestInterface $httpRequest */
- $httpRequest = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $httpRequest = $this->createMock(RequestInterface::class);
/** @var \Sabre\HTTP\ResponseInterface $httpResponse */
- $httpResponse = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- /** @var IUser */
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $httpResponse = $this->createMock(ResponseInterface::class);
+ $user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('MyTestUser');
$this->userSession
->expects($this->any())
@@ -643,29 +560,21 @@ class AuthTest extends TestCase {
}
public function testAuthenticateValidCredentials(): void {
- $server = $this->getMockBuilder(Server::class)
- ->disableOriginalConstructor()
- ->getMock();
- $server->httpRequest = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $server = $this->createMock(Server::class);
+ $server->httpRequest = $this->createMock(RequestInterface::class);
$server->httpRequest
->expects($this->once())
->method('getHeader')
->with('Authorization')
->willReturn('basic dXNlcm5hbWU6cGFzc3dvcmQ=');
- $server->httpResponse = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $server->httpResponse = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->once())
->method('logClientIn')
->with('username', 'password')
->willReturn(true);
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->exactly(2))
->method('getUID')
->willReturn('MyTestUser');
@@ -678,12 +587,8 @@ class AuthTest extends TestCase {
}
public function testAuthenticateInvalidCredentials(): void {
- $server = $this->getMockBuilder(Server::class)
- ->disableOriginalConstructor()
- ->getMock();
- $server->httpRequest = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $server = $this->createMock(Server::class);
+ $server->httpRequest = $this->createMock(RequestInterface::class);
$server->httpRequest
->expects($this->exactly(2))
->method('getHeader')
@@ -691,9 +596,7 @@ class AuthTest extends TestCase {
['Authorization', 'basic dXNlcm5hbWU6cGFzc3dvcmQ='],
['X-Requested-With', null],
]);
- $server->httpResponse = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $server->httpResponse = $this->createMock(ResponseInterface::class);
$this->userSession
->expects($this->once())
->method('logClientIn')
diff --git a/apps/dav/tests/unit/Connector/Sabre/BearerAuthTest.php b/apps/dav/tests/unit/Connector/Sabre/BearerAuthTest.php
index 99c2a461557..1e6267d4cbb 100644
--- a/apps/dav/tests/unit/Connector/Sabre/BearerAuthTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/BearerAuthTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -21,14 +23,10 @@ use Test\TestCase;
* @group DB
*/
class BearerAuthTest extends TestCase {
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- private $userSession;
- /** @var ISession|\PHPUnit\Framework\MockObject\MockObject */
- private $session;
- /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
- private $request;
- /** @var BearerAuth */
- private $bearerAuth;
+ private IUserSession&MockObject $userSession;
+ private ISession&MockObject $session;
+ private IRequest&MockObject $request;
+ private BearerAuth $bearerAuth;
private IConfig&MockObject $config;
@@ -74,9 +72,9 @@ class BearerAuthTest extends TestCase {
}
public function testChallenge(): void {
- /** @var \PHPUnit\Framework\MockObject\MockObject|RequestInterface $request */
+ /** @var RequestInterface&MockObject $request */
$request = $this->createMock(RequestInterface::class);
- /** @var \PHPUnit\Framework\MockObject\MockObject|ResponseInterface $response */
+ /** @var ResponseInterface&MockObject $response */
$response = $this->createMock(ResponseInterface::class);
$result = $this->bearerAuth->challenge($request, $response);
$this->assertEmpty($result);
diff --git a/apps/dav/tests/unit/Connector/Sabre/BlockLegacyClientPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/BlockLegacyClientPluginTest.php
index 072dd1a3b58..27ddd3f4a1f 100644
--- a/apps/dav/tests/unit/Connector/Sabre/BlockLegacyClientPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/BlockLegacyClientPluginTest.php
@@ -83,7 +83,7 @@ class BlockLegacyClientPluginTest extends TestCase {
}
/** @var RequestInterface|MockObject $request */
- $request = $this->createMock('\Sabre\HTTP\RequestInterface');
+ $request = $this->createMock(RequestInterface::class);
$request
->expects($this->once())
->method('getHeader')
diff --git a/apps/dav/tests/unit/Connector/Sabre/CommentsPropertiesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/CommentsPropertiesPluginTest.php
index 1cda0e4dbdb..6606dcd5717 100644
--- a/apps/dav/tests/unit/Connector/Sabre/CommentsPropertiesPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/CommentsPropertiesPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,62 +9,45 @@
namespace OCA\DAV\Tests\unit\Connector\Sabre;
use OCA\DAV\Connector\Sabre\CommentPropertiesPlugin as CommentPropertiesPluginImplementation;
+use OCA\DAV\Connector\Sabre\Directory;
use OCA\DAV\Connector\Sabre\File;
use OCP\Comments\ICommentsManager;
use OCP\IUser;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\PropFind;
+use Sabre\DAV\Server;
class CommentsPropertiesPluginTest extends \Test\TestCase {
-
- /** @var CommentPropertiesPluginImplementation */
- protected $plugin;
- protected $commentsManager;
- protected $userSession;
- protected $server;
+ protected CommentPropertiesPluginImplementation $plugin;
+ protected ICommentsManager&MockObject $commentsManager;
+ protected IUserSession&MockObject $userSession;
+ protected Server&MockObject $server;
protected function setUp(): void {
parent::setUp();
- $this->commentsManager = $this->getMockBuilder(ICommentsManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userSession = $this->getMockBuilder(IUserSession::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->server = $this->getMockBuilder('\Sabre\DAV\Server')
- ->disableOriginalConstructor()
- ->getMock();
+ $this->commentsManager = $this->createMock(ICommentsManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $this->server = $this->createMock(Server::class);
$this->plugin = new CommentPropertiesPluginImplementation($this->commentsManager, $this->userSession);
$this->plugin->initialize($this->server);
}
- public function nodeProvider() {
- $mocks = [];
- foreach (['\OCA\DAV\Connector\Sabre\File', '\OCA\DAV\Connector\Sabre\Directory', '\Sabre\DAV\INode'] as $class) {
- $mocks[] = $this->getMockBuilder($class)
- ->disableOriginalConstructor()
- ->getMock();
- }
-
+ public static function nodeProvider(): array {
return [
- [$mocks[0], true],
- [$mocks[1], true],
- [$mocks[2], false]
+ [File::class, true],
+ [Directory::class, true],
+ [\Sabre\DAV\INode::class, false]
];
}
/**
* @dataProvider nodeProvider
- * @param $node
- * @param $expectedSuccessful
*/
- public function testHandleGetProperties($node, $expectedSuccessful): void {
- $propFind = $this->getMockBuilder(PropFind::class)
- ->disableOriginalConstructor()
- ->getMock();
+ public function testHandleGetProperties(string $class, bool $expectedSuccessful): void {
+ $propFind = $this->createMock(PropFind::class);
if ($expectedSuccessful) {
$propFind->expects($this->exactly(3))
@@ -73,10 +57,11 @@ class CommentsPropertiesPluginTest extends \Test\TestCase {
->method('handle');
}
+ $node = $this->createMock($class);
$this->plugin->handleGetProperties($propFind, $node);
}
- public function baseUriProvider() {
+ public static function baseUriProvider(): array {
return [
['owncloud/remote.php/webdav/', '4567', 'owncloud/remote.php/dav/comments/files/4567'],
['owncloud/remote.php/files/', '4567', 'owncloud/remote.php/dav/comments/files/4567'],
@@ -86,14 +71,9 @@ class CommentsPropertiesPluginTest extends \Test\TestCase {
/**
* @dataProvider baseUriProvider
- * @param $baseUri
- * @param $fid
- * @param $expectedHref
*/
- public function testGetCommentsLink($baseUri, $fid, $expectedHref): void {
- $node = $this->getMockBuilder(File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ public function testGetCommentsLink(string $baseUri, string $fid, ?string $expectedHref): void {
+ $node = $this->createMock(File::class);
$node->expects($this->any())
->method('getId')
->willReturn($fid);
@@ -106,29 +86,25 @@ class CommentsPropertiesPluginTest extends \Test\TestCase {
$this->assertSame($expectedHref, $href);
}
- public function userProvider() {
+ public static function userProvider(): array {
return [
- [
- $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock()
- ],
+ [IUser::class],
[null]
];
}
/**
* @dataProvider userProvider
- * @param $user
*/
- public function testGetUnreadCount($user): void {
- $node = $this->getMockBuilder(File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ public function testGetUnreadCount(?string $user): void {
+ $node = $this->createMock(File::class);
$node->expects($this->any())
->method('getId')
->willReturn('4567');
+ if ($user !== null) {
+ $user = $this->createMock($user);
+ }
$this->userSession->expects($this->once())
->method('getUser')
->willReturn($user);
diff --git a/apps/dav/tests/unit/Connector/Sabre/CopyEtagHeaderPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/CopyEtagHeaderPluginTest.php
index bc19e071ee7..7067cf335ed 100644
--- a/apps/dav/tests/unit/Connector/Sabre/CopyEtagHeaderPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/CopyEtagHeaderPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -15,12 +16,8 @@ use Sabre\DAV\Tree;
use Test\TestCase;
class CopyEtagHeaderPluginTest extends TestCase {
-
- /** @var CopyEtagHeaderPlugin */
- private $plugin;
-
- /** @var Server */
- private $server;
+ private CopyEtagHeaderPlugin $plugin;
+ private Server $server;
protected function setUp(): void {
parent::setUp();
@@ -62,15 +59,11 @@ class CopyEtagHeaderPluginTest extends TestCase {
}
public function testAfterMove(): void {
- $node = $this->getMockBuilder(File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(File::class);
$node->expects($this->once())
->method('getETag')
->willReturn('123456');
- $tree = $this->getMockBuilder(Tree::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $tree = $this->createMock(Tree::class);
$tree->expects($this->once())
->method('getNodeForPath')
->with('test.txt')
diff --git a/apps/dav/tests/unit/Connector/Sabre/CustomPropertiesBackendTest.php b/apps/dav/tests/unit/Connector/Sabre/CustomPropertiesBackendTest.php
index eb3f291e9c0..d4021a66299 100644
--- a/apps/dav/tests/unit/Connector/Sabre/CustomPropertiesBackendTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/CustomPropertiesBackendTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -25,42 +26,21 @@ use Sabre\DAV\Tree;
* @package OCA\DAV\Tests\unit\Connector\Sabre
*/
class CustomPropertiesBackendTest extends \Test\TestCase {
-
- /**
- * @var \Sabre\DAV\Server
- */
- private $server;
-
- /**
- * @var \Sabre\DAV\Tree
- */
- private $tree;
-
- /**
- * @var CustomPropertiesBackend
- */
- private $plugin;
-
- /**
- * @var IUser
- */
- private $user;
-
- /** @property MockObject|DefaultCalendarValidator */
- private $defaultCalendarValidator;
+ private \Sabre\DAV\Server $server;
+ private \Sabre\DAV\Tree&MockObject $tree;
+ private IUser&MockObject $user;
+ private DefaultCalendarValidator&MockObject $defaultCalendarValidator;
+ private CustomPropertiesBackend $plugin;
protected function setUp(): void {
parent::setUp();
+
$this->server = new \Sabre\DAV\Server();
- $this->tree = $this->getMockBuilder(Tree::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->tree = $this->createMock(Tree::class);
- $userId = $this->getUniqueID('testcustompropertiesuser');
+ $userId = self::getUniqueID('testcustompropertiesuser');
- $this->user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->user = $this->createMock(IUser::class);
$this->user->expects($this->any())
->method('getUID')
->willReturn($userId);
@@ -79,8 +59,8 @@ class CustomPropertiesBackendTest extends \Test\TestCase {
protected function tearDown(): void {
$connection = Server::get(IDBConnection::class);
$deleteStatement = $connection->prepare(
- 'DELETE FROM `*PREFIX*properties`' .
- ' WHERE `userid` = ?'
+ 'DELETE FROM `*PREFIX*properties`'
+ . ' WHERE `userid` = ?'
);
$deleteStatement->execute(
[
@@ -88,12 +68,12 @@ class CustomPropertiesBackendTest extends \Test\TestCase {
]
);
$deleteStatement->closeCursor();
+
+ parent::tearDown();
}
- private function createTestNode($class) {
- $node = $this->getMockBuilder($class)
- ->disableOriginalConstructor()
- ->getMock();
+ private function createTestNode(string $class) {
+ $node = $this->createMock($class);
$node->expects($this->any())
->method('getId')
->willReturn(123);
diff --git a/apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php b/apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php
index f6c19787e94..85890c0f987 100644
--- a/apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php
@@ -1,11 +1,12 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
-namespace OCA\DAV\Tests\Unit\Connector\Sabre;
+namespace OCA\DAV\Tests\unit\Connector\Sabre;
use OC\Files\FileInfo;
use OC\Files\Filesystem;
@@ -15,11 +16,13 @@ use OC\Files\View;
use OCA\DAV\Connector\Sabre\Directory;
use OCA\DAV\Connector\Sabre\Exception\Forbidden;
use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
+use OCA\Files_Sharing\External\Storage;
use OCP\Constants;
use OCP\Files\ForbiddenException;
use OCP\Files\InvalidPathException;
use OCP\Files\Mount\IMountPoint;
use OCP\Files\StorageNotAvailableException;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\Traits\UserTrait;
class TestViewDirectory extends View {
@@ -42,7 +45,7 @@ class TestViewDirectory extends View {
return $this->deletables[$path];
}
- public function rename($path1, $path2, array $options = []) {
+ public function rename($source, $target, array $options = []) {
return $this->canRename;
}
@@ -58,16 +61,14 @@ class TestViewDirectory extends View {
class DirectoryTest extends \Test\TestCase {
use UserTrait;
- /** @var View|\PHPUnit\Framework\MockObject\MockObject */
- private $view;
- /** @var FileInfo|\PHPUnit\Framework\MockObject\MockObject */
- private $info;
+ private View&MockObject $view;
+ private FileInfo&MockObject $info;
protected function setUp(): void {
parent::setUp();
- $this->view = $this->createMock('OC\Files\View');
- $this->info = $this->createMock('OC\Files\FileInfo');
+ $this->view = $this->createMock(View::class);
+ $this->info = $this->createMock(FileInfo::class);
$this->info->method('isReadable')
->willReturn(true);
$this->info->method('getType')
@@ -80,7 +81,7 @@ class DirectoryTest extends \Test\TestCase {
->willReturn(Constants::PERMISSION_READ);
}
- private function getDir($path = '/') {
+ private function getDir(string $path = '/'): Directory {
$this->view->expects($this->once())
->method('getRelativePath')
->willReturn($path);
@@ -173,12 +174,8 @@ class DirectoryTest extends \Test\TestCase {
}
public function testGetChildren(): void {
- $info1 = $this->getMockBuilder(FileInfo::class)
- ->disableOriginalConstructor()
- ->getMock();
- $info2 = $this->getMockBuilder(FileInfo::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $info1 = $this->createMock(FileInfo::class);
+ $info2 = $this->createMock(FileInfo::class);
$info1->method('getName')
->willReturn('first');
$info1->method('getPath')
@@ -213,7 +210,7 @@ class DirectoryTest extends \Test\TestCase {
$dir = new Directory($this->view, $this->info);
$nodes = $dir->getChildren();
- $this->assertEquals(2, count($nodes));
+ $this->assertCount(2, $nodes);
// calling a second time just returns the cached values,
// does not call getDirectoryContents again
@@ -272,12 +269,10 @@ class DirectoryTest extends \Test\TestCase {
}
public function testGetQuotaInfoUnlimited(): void {
- self::createUser('user', 'password');
+ $this->createUser('user', 'password');
self::loginAsUser('user');
$mountPoint = $this->createMock(IMountPoint::class);
- $storage = $this->getMockBuilder(Quota::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $storage = $this->createMock(Quota::class);
$mountPoint->method('getStorage')
->willReturn($storage);
@@ -286,7 +281,7 @@ class DirectoryTest extends \Test\TestCase {
->willReturnMap([
['\OCA\Files_Sharing\SharedStorage', false],
['\OC\Files\Storage\Wrapper\Quota', false],
- [\OCA\Files_Sharing\External\Storage::class, false],
+ [Storage::class, false],
]);
$storage->expects($this->once())
@@ -328,12 +323,10 @@ class DirectoryTest extends \Test\TestCase {
}
public function testGetQuotaInfoSpecific(): void {
- self::createUser('user', 'password');
+ $this->createUser('user', 'password');
self::loginAsUser('user');
$mountPoint = $this->createMock(IMountPoint::class);
- $storage = $this->getMockBuilder(Quota::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $storage = $this->createMock(Quota::class);
$mountPoint->method('getStorage')
->willReturn($storage);
@@ -342,7 +335,7 @@ class DirectoryTest extends \Test\TestCase {
->willReturnMap([
['\OCA\Files_Sharing\SharedStorage', false],
['\OC\Files\Storage\Wrapper\Quota', true],
- [\OCA\Files_Sharing\External\Storage::class, false],
+ [Storage::class, false],
]);
$storage->expects($this->once())
@@ -383,7 +376,7 @@ class DirectoryTest extends \Test\TestCase {
/**
* @dataProvider moveFailedProvider
*/
- public function testMoveFailed($source, $destination, $updatables, $deletables): void {
+ public function testMoveFailed(string $source, string $destination, array $updatables, array $deletables): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
$this->moveTest($source, $destination, $updatables, $deletables);
@@ -392,7 +385,7 @@ class DirectoryTest extends \Test\TestCase {
/**
* @dataProvider moveSuccessProvider
*/
- public function testMoveSuccess($source, $destination, $updatables, $deletables): void {
+ public function testMoveSuccess(string $source, string $destination, array $updatables, array $deletables): void {
$this->moveTest($source, $destination, $updatables, $deletables);
$this->addToAssertionCount(1);
}
@@ -400,19 +393,19 @@ class DirectoryTest extends \Test\TestCase {
/**
* @dataProvider moveFailedInvalidCharsProvider
*/
- public function testMoveFailedInvalidChars($source, $destination, $updatables, $deletables): void {
+ public function testMoveFailedInvalidChars(string $source, string $destination, array $updatables, array $deletables): void {
$this->expectException(InvalidPath::class);
$this->moveTest($source, $destination, $updatables, $deletables);
}
- public function moveFailedInvalidCharsProvider() {
+ public static function moveFailedInvalidCharsProvider(): array {
return [
['a/valid', "a/i\nvalid", ['a' => true, 'a/valid' => true, 'a/c*' => false], []],
];
}
- public function moveFailedProvider() {
+ public static function moveFailedProvider(): array {
return [
['a/b', 'a/c', ['a' => false, 'a/b' => false, 'a/c' => false], []],
['a/b', 'b/b', ['a' => false, 'a/b' => false, 'b' => false, 'b/b' => false], []],
@@ -423,7 +416,7 @@ class DirectoryTest extends \Test\TestCase {
];
}
- public function moveSuccessProvider() {
+ public static function moveSuccessProvider(): array {
return [
['a/b', 'b/b', ['a' => true, 'a/b' => true, 'b' => true, 'b/b' => false], ['a/b' => true]],
// older files with special chars can still be renamed to valid names
@@ -431,12 +424,7 @@ class DirectoryTest extends \Test\TestCase {
];
}
- /**
- * @param $source
- * @param $destination
- * @param $updatables
- */
- private function moveTest($source, $destination, $updatables, $deletables): void {
+ private function moveTest(string $source, string $destination, array $updatables, array $deletables): void {
$view = new TestViewDirectory($updatables, $deletables);
$sourceInfo = new FileInfo($source, null, null, [
@@ -448,7 +436,7 @@ class DirectoryTest extends \Test\TestCase {
$sourceNode = new Directory($view, $sourceInfo);
$targetNode = $this->getMockBuilder(Directory::class)
- ->setMethods(['childExists'])
+ ->onlyMethods(['childExists'])
->setConstructorArgs([$view, $targetInfo])
->getMock();
$targetNode->expects($this->any())->method('childExists')
diff --git a/apps/dav/tests/unit/Connector/Sabre/DummyGetResponsePluginTest.php b/apps/dav/tests/unit/Connector/Sabre/DummyGetResponsePluginTest.php
index 03c31dc47f8..2d688d64600 100644
--- a/apps/dav/tests/unit/Connector/Sabre/DummyGetResponsePluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/DummyGetResponsePluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -19,8 +20,7 @@ use Test\TestCase;
* @package OCA\DAV\Tests\unit\Connector\Sabre
*/
class DummyGetResponsePluginTest extends TestCase {
- /** @var DummyGetResponsePlugin */
- private $dummyGetResponsePlugin;
+ private DummyGetResponsePlugin $dummyGetResponsePlugin;
protected function setUp(): void {
parent::setUp();
@@ -29,10 +29,7 @@ class DummyGetResponsePluginTest extends TestCase {
}
public function testInitialize(): void {
- /** @var Server $server */
- $server = $this->getMockBuilder(Server::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $server = $this->createMock(Server::class);
$server
->expects($this->once())
->method('on')
@@ -44,13 +41,9 @@ class DummyGetResponsePluginTest extends TestCase {
public function testHttpGet(): void {
/** @var \Sabre\HTTP\RequestInterface $request */
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
/** @var \Sabre\HTTP\ResponseInterface $response */
- $response = $server = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $response = $this->createMock(ResponseInterface::class);
$response
->expects($this->once())
->method('setBody');
diff --git a/apps/dav/tests/unit/Connector/Sabre/Exception/ForbiddenTest.php b/apps/dav/tests/unit/Connector/Sabre/Exception/ForbiddenTest.php
index c7fb6066ed4..2f9e0ae9196 100644
--- a/apps/dav/tests/unit/Connector/Sabre/Exception/ForbiddenTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/Exception/ForbiddenTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,6 +9,7 @@
namespace OCA\DAV\Tests\unit\Connector\Sabre\Exception;
use OCA\DAV\Connector\Sabre\Exception\Forbidden;
+use Sabre\DAV\Server;
class ForbiddenTest extends \Test\TestCase {
public function testSerialization(): void {
@@ -32,9 +34,7 @@ class ForbiddenTest extends \Test\TestCase {
EOD;
$ex = new Forbidden($message, $retry);
- $server = $this->getMockBuilder('Sabre\DAV\Server')
- ->disableOriginalConstructor()
- ->getMock();
+ $server = $this->createMock(Server::class);
$ex->serialize($server, $error);
// assert
diff --git a/apps/dav/tests/unit/Connector/Sabre/Exception/InvalidPathTest.php b/apps/dav/tests/unit/Connector/Sabre/Exception/InvalidPathTest.php
index 98921d735fa..6f62bef86a3 100644
--- a/apps/dav/tests/unit/Connector/Sabre/Exception/InvalidPathTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/Exception/InvalidPathTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,6 +9,7 @@
namespace OCA\DAV\Tests\unit\Connector\Sabre\Exception;
use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
+use Sabre\DAV\Server;
class InvalidPathTest extends \Test\TestCase {
public function testSerialization(): void {
@@ -32,9 +34,7 @@ class InvalidPathTest extends \Test\TestCase {
EOD;
$ex = new InvalidPath($message, $retry);
- $server = $this->getMockBuilder('Sabre\DAV\Server')
- ->disableOriginalConstructor()
- ->getMock();
+ $server = $this->createMock(Server::class);
$ex->serialize($server, $error);
// assert
diff --git a/apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php
index 1d50fb2fb9a..a330a885b1f 100644
--- a/apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/ExceptionLoggerPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -11,21 +12,16 @@ use OC\SystemConfig;
use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
use OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin;
use OCA\DAV\Exception\ServerMaintenanceMode;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\Server;
use Test\TestCase;
class ExceptionLoggerPluginTest extends TestCase {
-
- /** @var Server */
- private $server;
-
- /** @var ExceptionLoggerPlugin */
- private $plugin;
-
- /** @var LoggerInterface | \PHPUnit\Framework\MockObject\MockObject */
- private $logger;
+ private Server $server;
+ private ExceptionLoggerPlugin $plugin;
+ private LoggerInterface&MockObject $logger;
private function init(): void {
$config = $this->createMock(SystemConfig::class);
@@ -59,7 +55,7 @@ class ExceptionLoggerPluginTest extends TestCase {
$this->plugin->logException($e);
}
- public function providesExceptions() {
+ public static function providesExceptions(): array {
return [
['debug', new NotFound()],
['debug', new ServerMaintenanceMode('System is in maintenance mode.')],
diff --git a/apps/dav/tests/unit/Connector/Sabre/FakeLockerPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/FakeLockerPluginTest.php
index 18165b79cb2..ef744d13e6a 100644
--- a/apps/dav/tests/unit/Connector/Sabre/FakeLockerPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/FakeLockerPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -22,8 +23,7 @@ use Test\TestCase;
* @package OCA\DAV\Tests\unit\Connector\Sabre
*/
class FakeLockerPluginTest extends TestCase {
- /** @var FakeLockerPlugin */
- private $fakeLockerPlugin;
+ private FakeLockerPlugin $fakeLockerPlugin;
protected function setUp(): void {
parent::setUp();
@@ -32,18 +32,19 @@ class FakeLockerPluginTest extends TestCase {
public function testInitialize(): void {
/** @var Server $server */
- $server = $this->getMockBuilder(Server::class)
- ->disableOriginalConstructor()
- ->getMock();
- $server
- ->expects($this->exactly(4))
+ $server = $this->createMock(Server::class);
+ $calls = [
+ ['method:LOCK', [$this->fakeLockerPlugin, 'fakeLockProvider'], 1],
+ ['method:UNLOCK', [$this->fakeLockerPlugin, 'fakeUnlockProvider'], 1],
+ ['propFind', [$this->fakeLockerPlugin, 'propFind'], 100],
+ ['validateTokens', [$this->fakeLockerPlugin, 'validateTokens'], 100],
+ ];
+ $server->expects($this->exactly(count($calls)))
->method('on')
- ->withConsecutive(
- ['method:LOCK', [$this->fakeLockerPlugin, 'fakeLockProvider'], 1],
- ['method:UNLOCK', [$this->fakeLockerPlugin, 'fakeUnlockProvider'], 1],
- ['propFind', [$this->fakeLockerPlugin, 'propFind']],
- ['validateTokens', [$this->fakeLockerPlugin, 'validateTokens']],
- );
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
$this->fakeLockerPlugin->initialize($server);
}
@@ -64,24 +65,24 @@ class FakeLockerPluginTest extends TestCase {
}
public function testPropFind(): void {
- $propFind = $this->getMockBuilder(PropFind::class)
- ->disableOriginalConstructor()
- ->getMock();
- $node = $this->getMockBuilder(INode::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $propFind = $this->createMock(PropFind::class);
+ $node = $this->createMock(INode::class);
- $propFind->expects($this->exactly(2))
+ $calls = [
+ '{DAV:}supportedlock',
+ '{DAV:}lockdiscovery',
+ ];
+ $propFind->expects($this->exactly(count($calls)))
->method('handle')
- ->withConsecutive(
- ['{DAV:}supportedlock'],
- ['{DAV:}lockdiscovery'],
- );
+ ->willReturnCallback(function ($propertyName) use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, $propertyName);
+ });
$this->fakeLockerPlugin->propFind($propFind, $node);
}
- public function tokenDataProvider() {
+ public static function tokenDataProvider(): array {
return [
[
[
@@ -120,21 +121,15 @@ class FakeLockerPluginTest extends TestCase {
/**
* @dataProvider tokenDataProvider
- * @param array $input
- * @param array $expected
*/
public function testValidateTokens(array $input, array $expected): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
$this->fakeLockerPlugin->validateTokens($request, $input);
$this->assertSame($expected, $input);
}
public function testFakeLockProvider(): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
$response = new Response();
$server = $this->getMockBuilder(Server::class)
->getMock();
@@ -152,12 +147,8 @@ class FakeLockerPluginTest extends TestCase {
}
public function testFakeUnlockProvider(): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$response->expects($this->once())
->method('setStatus')
diff --git a/apps/dav/tests/unit/Connector/Sabre/FileTest.php b/apps/dav/tests/unit/Connector/Sabre/FileTest.php
index ef02f145375..4a7ddad7115 100644
--- a/apps/dav/tests/unit/Connector/Sabre/FileTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/FileTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -53,16 +54,9 @@ class FileTest extends TestCase {
use MountProviderTrait;
use UserTrait;
- /**
- * @var string
- */
- private $user;
-
- /** @var IConfig|MockObject */
- protected $config;
-
- /** @var IRequestId|MockObject */
- protected $requestId;
+ private string $user;
+ protected IConfig&MockObject $config;
+ protected IRequestId&MockObject $requestId;
protected function setUp(): void {
parent::setUp();
@@ -72,7 +66,7 @@ class FileTest extends TestCase {
$this->user = 'test_user';
$this->createUser($this->user, 'pass');
- $this->loginAsUser($this->user);
+ self::loginAsUser($this->user);
$this->config = $this->createMock(IConfig::class);
$this->requestId = $this->createMock(IRequestId::class);
@@ -86,9 +80,7 @@ class FileTest extends TestCase {
}
private function getMockStorage(): MockObject&IStorage {
- $storage = $this->getMockBuilder(IStorage::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $storage = $this->createMock(IStorage::class);
$storage->method('getId')
->willReturn('home::someuser');
return $storage;
@@ -102,7 +94,7 @@ class FileTest extends TestCase {
}
- public function fopenFailuresProvider() {
+ public static function fopenFailuresProvider(): array {
return [
[
// return false
@@ -161,14 +153,14 @@ class FileTest extends TestCase {
/**
* @dataProvider fopenFailuresProvider
*/
- public function testSimplePutFails($thrownException, $expectedException, $checkPreviousClass = true): void {
+ public function testSimplePutFails(?\Throwable $thrownException, string $expectedException, bool $checkPreviousClass = true): void {
// setup
$storage = $this->getMockBuilder(Local::class)
->onlyMethods(['writeStream'])
->setConstructorArgs([['datadir' => Server::get(ITempManager::class)->getTemporaryFolder()]])
->getMock();
Filesystem::mount($storage, [], $this->user . '/');
- /** @var View | MockObject $view */
+ /** @var View&MockObject $view */
$view = $this->getMockBuilder(View::class)
->onlyMethods(['getRelativePath', 'resolvePath'])
->getMock();
@@ -221,12 +213,12 @@ class FileTest extends TestCase {
* Simulate putting a file to the given path.
*
* @param string $path path to put the file into
- * @param string $viewRoot root to use for the view
+ * @param ?string $viewRoot root to use for the view
* @param null|Request $request the HTTP request
*
* @return null|string of the PUT operation which is usually the etag
*/
- private function doPut($path, $viewRoot = null, ?Request $request = null) {
+ private function doPut(string $path, ?string $viewRoot = null, ?Request $request = null) {
$view = Filesystem::getView();
if (!is_null($viewRoot)) {
$view = new View($viewRoot);
@@ -245,7 +237,7 @@ class FileTest extends TestCase {
null
);
- /** @var File|MockObject $file */
+ /** @var File&MockObject $file */
$file = $this->getMockBuilder(File::class)
->setConstructorArgs([$view, $info, null, $request])
->onlyMethods(['header'])
@@ -269,55 +261,55 @@ class FileTest extends TestCase {
$this->assertNotEmpty($this->doPut('/foo.txt'));
}
- public function legalMtimeProvider() {
+ public static function legalMtimeProvider(): array {
return [
'string' => [
- 'HTTP_X_OC_MTIME' => 'string',
- 'expected result' => null
+ 'requestMtime' => 'string',
+ 'resultMtime' => null
],
'castable string (int)' => [
- 'HTTP_X_OC_MTIME' => '987654321',
- 'expected result' => 987654321
+ 'requestMtime' => '987654321',
+ 'resultMtime' => 987654321
],
'castable string (float)' => [
- 'HTTP_X_OC_MTIME' => '123456789.56',
- 'expected result' => 123456789
+ 'requestMtime' => '123456789.56',
+ 'resultMtime' => 123456789
],
'float' => [
- 'HTTP_X_OC_MTIME' => 123456789.56,
- 'expected result' => 123456789
+ 'requestMtime' => 123456789.56,
+ 'resultMtime' => 123456789
],
'zero' => [
- 'HTTP_X_OC_MTIME' => 0,
- 'expected result' => null
+ 'requestMtime' => 0,
+ 'resultMtime' => null
],
'zero string' => [
- 'HTTP_X_OC_MTIME' => '0',
- 'expected result' => null
+ 'requestMtime' => '0',
+ 'resultMtime' => null
],
'negative zero string' => [
- 'HTTP_X_OC_MTIME' => '-0',
- 'expected result' => null
+ 'requestMtime' => '-0',
+ 'resultMtime' => null
],
'string starting with number following by char' => [
- 'HTTP_X_OC_MTIME' => '2345asdf',
- 'expected result' => null
+ 'requestMtime' => '2345asdf',
+ 'resultMtime' => null
],
'string castable hex int' => [
- 'HTTP_X_OC_MTIME' => '0x45adf',
- 'expected result' => null
+ 'requestMtime' => '0x45adf',
+ 'resultMtime' => null
],
'string that looks like invalid hex int' => [
- 'HTTP_X_OC_MTIME' => '0x123g',
- 'expected result' => null
+ 'requestMtime' => '0x123g',
+ 'resultMtime' => null
],
'negative int' => [
- 'HTTP_X_OC_MTIME' => -34,
- 'expected result' => null
+ 'requestMtime' => -34,
+ 'resultMtime' => null
],
'negative float' => [
- 'HTTP_X_OC_MTIME' => -34.43,
- 'expected result' => null
+ 'requestMtime' => -34.43,
+ 'resultMtime' => null
],
];
}
@@ -326,7 +318,7 @@ class FileTest extends TestCase {
* Test putting a file with string Mtime
* @dataProvider legalMtimeProvider
*/
- public function testPutSingleFileLegalMtime($requestMtime, $resultMtime): void {
+ public function testPutSingleFileLegalMtime(mixed $requestMtime, ?int $resultMtime): void {
$request = new Request([
'server' => [
'HTTP_X_OC_MTIME' => (string)$requestMtime,
@@ -482,7 +474,7 @@ class FileTest extends TestCase {
*/
public function testSimplePutFailsSizeCheck(): void {
// setup
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->onlyMethods(['rename', 'getRelativePath', 'filesize'])
->getMock();
@@ -569,7 +561,7 @@ class FileTest extends TestCase {
*/
public function testSimplePutInvalidChars(): void {
// setup
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->onlyMethods(['getRelativePath'])
->getMock();
@@ -609,7 +601,7 @@ class FileTest extends TestCase {
$this->expectException(InvalidPath::class);
// setup
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->onlyMethods(['getRelativePath'])
->getMock();
@@ -630,7 +622,7 @@ class FileTest extends TestCase {
public function testUploadAbort(): void {
// setup
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->onlyMethods(['rename', 'getRelativePath', 'filesize'])
->getMock();
@@ -680,7 +672,7 @@ class FileTest extends TestCase {
public function testDeleteWhenAllowed(): void {
// setup
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->getMock();
@@ -704,7 +696,7 @@ class FileTest extends TestCase {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
// setup
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->getMock();
@@ -724,7 +716,7 @@ class FileTest extends TestCase {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
// setup
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->getMock();
@@ -749,7 +741,7 @@ class FileTest extends TestCase {
$this->expectException(Forbidden::class);
// setup
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->getMock();
@@ -923,7 +915,7 @@ class FileTest extends TestCase {
public function testGetFopenFails(): void {
$this->expectException(\Sabre\DAV\Exception\ServiceUnavailable::class);
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->onlyMethods(['fopen'])
->getMock();
@@ -945,7 +937,7 @@ class FileTest extends TestCase {
public function testGetFopenThrows(): void {
$this->expectException(Forbidden::class);
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->onlyMethods(['fopen'])
->getMock();
@@ -967,7 +959,7 @@ class FileTest extends TestCase {
public function testGetThrowsIfNoPermission(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
- /** @var View|MockObject */
+ /** @var View&MockObject */
$view = $this->getMockBuilder(View::class)
->onlyMethods(['fopen'])
->getMock();
diff --git a/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php
index db07165ebf0..d8b32067dda 100644
--- a/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -7,12 +8,15 @@
*/
namespace OCA\DAV\Tests\unit\Connector\Sabre;
+use OC\Accounts\Account;
+use OC\Accounts\AccountProperty;
use OC\User\User;
use OCA\DAV\Connector\Sabre\Directory;
use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
use OCA\DAV\Connector\Sabre\File;
use OCA\DAV\Connector\Sabre\FilesPlugin;
use OCA\DAV\Connector\Sabre\Node;
+use OCP\Accounts\IAccountManager;
use OCP\Files\FileInfo;
use OCP\Files\IFilenameValidator;
use OCP\Files\InvalidPathException;
@@ -43,6 +47,7 @@ class FilesPluginTest extends TestCase {
private IPreview&MockObject $previewManager;
private IUserSession&MockObject $userSession;
private IFilenameValidator&MockObject $filenameValidator;
+ private IAccountManager&MockObject $accountManager;
private FilesPlugin $plugin;
protected function setUp(): void {
@@ -57,6 +62,7 @@ class FilesPluginTest extends TestCase {
$this->previewManager = $this->createMock(IPreview::class);
$this->userSession = $this->createMock(IUserSession::class);
$this->filenameValidator = $this->createMock(IFilenameValidator::class);
+ $this->accountManager = $this->createMock(IAccountManager::class);
$this->plugin = new FilesPlugin(
$this->tree,
@@ -65,25 +71,18 @@ class FilesPluginTest extends TestCase {
$this->previewManager,
$this->userSession,
$this->filenameValidator,
+ $this->accountManager,
);
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $response = $this->createMock(ResponseInterface::class);
$this->server->httpResponse = $response;
$this->server->xml = new Service();
$this->plugin->initialize($this->server);
}
- /**
- * @param string $class
- * @return \PHPUnit\Framework\MockObject\MockObject
- */
- private function createTestNode($class, $path = '/dummypath') {
- $node = $this->getMockBuilder($class)
- ->disableOriginalConstructor()
- ->getMock();
+ private function createTestNode(string $class, string $path = '/dummypath'): MockObject {
+ $node = $this->createMock($class);
$node->expects($this->any())
->method('getId')
@@ -123,8 +122,8 @@ class FilesPluginTest extends TestCase {
}
public function testGetPropertiesForFile(): void {
- /** @var File|\PHPUnit\Framework\MockObject\MockObject $node */
- $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\File');
+ /** @var File&MockObject $node */
+ $node = $this->createTestNode(File::class);
$propFind = new PropFind(
'/dummyPath',
@@ -143,8 +142,7 @@ class FilesPluginTest extends TestCase {
0
);
- $user = $this->getMockBuilder(User::class)
- ->disableOriginalConstructor()->getMock();
+ $user = $this->createMock(User::class);
$user
->expects($this->once())
->method('getUID')
@@ -154,6 +152,12 @@ class FilesPluginTest extends TestCase {
->method('getDisplayName')
->willReturn('M. Foo');
+ $owner = $this->createMock(Account::class);
+ $this->accountManager->expects($this->once())
+ ->method('getAccount')
+ ->with($user)
+ ->willReturn($owner);
+
$node->expects($this->once())
->method('getDirectDownload')
->willReturn(['url' => 'http://example.com/']);
@@ -161,6 +165,17 @@ class FilesPluginTest extends TestCase {
->method('getOwner')
->willReturn($user);
+ $displayNameProp = $this->createMock(AccountProperty::class);
+ $owner
+ ->expects($this->once())
+ ->method('getProperty')
+ ->with(IAccountManager::PROPERTY_DISPLAYNAME)
+ ->willReturn($displayNameProp);
+ $displayNameProp
+ ->expects($this->once())
+ ->method('getScope')
+ ->willReturn(IAccountManager::SCOPE_PUBLISHED);
+
$this->plugin->handleGetProperties(
$propFind,
$node
@@ -179,9 +194,95 @@ class FilesPluginTest extends TestCase {
$this->assertEquals([], $propFind->get404Properties());
}
+ public function testGetDisplayNamePropertyWhenNotPublished(): void {
+ $node = $this->createTestNode(File::class);
+ $propFind = new PropFind(
+ '/dummyPath',
+ [
+ FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME,
+ ],
+ 0
+ );
+
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->willReturn(null);
+
+ $user = $this->createMock(User::class);
+
+ $user->expects($this->never())
+ ->method('getDisplayName');
+
+ $owner = $this->createMock(Account::class);
+ $this->accountManager->expects($this->once())
+ ->method('getAccount')
+ ->with($user)
+ ->willReturn($owner);
+
+ $node->expects($this->once())
+ ->method('getOwner')
+ ->willReturn($user);
+
+ $displayNameProp = $this->createMock(AccountProperty::class);
+ $owner
+ ->expects($this->once())
+ ->method('getProperty')
+ ->with(IAccountManager::PROPERTY_DISPLAYNAME)
+ ->willReturn($displayNameProp);
+ $displayNameProp
+ ->expects($this->once())
+ ->method('getScope')
+ ->willReturn(IAccountManager::SCOPE_PRIVATE);
+
+ $this->plugin->handleGetProperties(
+ $propFind,
+ $node
+ );
+
+ $this->assertEquals(null, $propFind->get(FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME));
+ }
+
+ public function testGetDisplayNamePropertyWhenNotPublishedButLoggedIn(): void {
+ $node = $this->createTestNode(File::class);
+
+ $propFind = new PropFind(
+ '/dummyPath',
+ [
+ FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME,
+ ],
+ 0
+ );
+
+ $user = $this->createMock(User::class);
+
+ $node->expects($this->once())
+ ->method('getOwner')
+ ->willReturn($user);
+
+ $loggedInUser = $this->createMock(User::class);
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->willReturn($loggedInUser);
+
+ $user
+ ->expects($this->once())
+ ->method('getDisplayName')
+ ->willReturn('M. Foo');
+
+ $this->accountManager->expects($this->never())
+ ->method('getAccount');
+
+ $this->plugin->handleGetProperties(
+ $propFind,
+ $node
+ );
+
+ $this->assertEquals('M. Foo', $propFind->get(FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME));
+ }
+
public function testGetPropertiesStorageNotAvailable(): void {
- /** @var File|\PHPUnit\Framework\MockObject\MockObject $node */
- $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\File');
+ /** @var File&MockObject $node */
+ $node = $this->createTestNode(File::class);
$propFind = new PropFind(
'/dummyPath',
@@ -205,9 +306,7 @@ class FilesPluginTest extends TestCase {
public function testGetPublicPermissions(): void {
/** @var IRequest&MockObject */
- $request = $this->getMockBuilder(IRequest::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(IRequest::class);
$this->plugin = new FilesPlugin(
$this->tree,
$this->config,
@@ -215,6 +314,7 @@ class FilesPluginTest extends TestCase {
$this->previewManager,
$this->userSession,
$this->filenameValidator,
+ $this->accountManager,
true,
);
$this->plugin->initialize($this->server);
@@ -227,8 +327,8 @@ class FilesPluginTest extends TestCase {
0
);
- /** @var File|\PHPUnit\Framework\MockObject\MockObject $node */
- $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\File');
+ /** @var File&MockObject $node */
+ $node = $this->createTestNode(File::class);
$node->expects($this->any())
->method('getDavPermissions')
->willReturn('DWCKMSR');
@@ -242,8 +342,8 @@ class FilesPluginTest extends TestCase {
}
public function testGetPropertiesForDirectory(): void {
- /** @var Directory|\PHPUnit\Framework\MockObject\MockObject $node */
- $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\Directory');
+ /** @var Directory&MockObject $node */
+ $node = $this->createTestNode(Directory::class);
$propFind = new PropFind(
'/dummyPath',
@@ -277,10 +377,8 @@ class FilesPluginTest extends TestCase {
}
public function testGetPropertiesForRootDirectory(): void {
- /** @var Directory|\PHPUnit\Framework\MockObject\MockObject $node */
- $node = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
+ /** @var Directory&MockObject $node */
+ $node = $this->createMock(Directory::class);
$node->expects($this->any())->method('getPath')->willReturn('/');
$fileInfo = $this->createMock(FileInfo::class);
@@ -312,10 +410,8 @@ class FilesPluginTest extends TestCase {
// No read permissions can be caused by files access control.
// But we still want to load the directory list, so this is okay for us.
// $this->expectException(\Sabre\DAV\Exception\NotFound::class);
- /** @var Directory|\PHPUnit\Framework\MockObject\MockObject $node */
- $node = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
+ /** @var Directory&MockObject $node */
+ $node = $this->createMock(Directory::class);
$node->expects($this->any())->method('getPath')->willReturn('/');
$fileInfo = $this->createMock(FileInfo::class);
@@ -344,7 +440,7 @@ class FilesPluginTest extends TestCase {
}
public function testUpdateProps(): void {
- $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\File');
+ $node = $this->createTestNode(File::class);
$testDate = 'Fri, 13 Feb 2015 00:01:02 GMT';
$testCreationDate = '2007-08-31T16:47+00:00';
@@ -428,16 +524,12 @@ class FilesPluginTest extends TestCase {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
$this->expectExceptionMessage('FolderA/test.txt cannot be deleted');
- $fileInfoFolderATestTXT = $this->getMockBuilder(FileInfo::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $fileInfoFolderATestTXT = $this->createMock(FileInfo::class);
$fileInfoFolderATestTXT->expects($this->once())
->method('isDeletable')
->willReturn(false);
- $node = $this->getMockBuilder(Node::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(Node::class);
$node->expects($this->atLeastOnce())
->method('getFileInfo')
->willReturn($fileInfoFolderATestTXT);
@@ -450,16 +542,12 @@ class FilesPluginTest extends TestCase {
}
public function testMoveSrcDeletable(): void {
- $fileInfoFolderATestTXT = $this->getMockBuilder(FileInfo::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $fileInfoFolderATestTXT = $this->createMock(FileInfo::class);
$fileInfoFolderATestTXT->expects($this->once())
->method('isDeletable')
->willReturn(true);
- $node = $this->getMockBuilder(Node::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(Node::class);
$node->expects($this->atLeastOnce())
->method('getFileInfo')
->willReturn($fileInfoFolderATestTXT);
@@ -475,9 +563,7 @@ class FilesPluginTest extends TestCase {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
$this->expectExceptionMessage('FolderA/test.txt does not exist');
- $node = $this->getMockBuilder(Node::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(Node::class);
$node->expects($this->atLeastOnce())
->method('getFileInfo')
->willReturn(null);
@@ -553,7 +639,7 @@ class FilesPluginTest extends TestCase {
$this->plugin->checkCopy('FolderA/test.txt', 'invalid\\path.txt');
}
- public function downloadHeadersProvider() {
+ public static function downloadHeadersProvider(): array {
return [
[
false,
@@ -569,22 +655,16 @@ class FilesPluginTest extends TestCase {
/**
* @dataProvider downloadHeadersProvider
*/
- public function testDownloadHeaders($isClumsyAgent, $contentDispositionHeader): void {
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ public function testDownloadHeaders(bool $isClumsyAgent, string $contentDispositionHeader): void {
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$request
->expects($this->once())
->method('getPath')
->willReturn('test/somefile.xml');
- $node = $this->getMockBuilder(File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(File::class);
$node
->expects($this->once())
->method('getName')
@@ -601,20 +681,24 @@ class FilesPluginTest extends TestCase {
->method('isUserAgent')
->willReturn($isClumsyAgent);
+ $calls = [
+ ['Content-Disposition', $contentDispositionHeader],
+ ['X-Accel-Buffering', 'no'],
+ ];
$response
- ->expects($this->exactly(2))
+ ->expects($this->exactly(count($calls)))
->method('addHeader')
- ->withConsecutive(
- ['Content-Disposition', $contentDispositionHeader],
- ['X-Accel-Buffering', 'no']
- );
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertSame($expected, func_get_args());
+ });
$this->plugin->httpGet($request, $response);
}
public function testHasPreview(): void {
- /** @var Directory|\PHPUnit\Framework\MockObject\MockObject $node */
- $node = $this->createTestNode('\OCA\DAV\Connector\Sabre\Directory');
+ /** @var Directory&MockObject $node */
+ $node = $this->createTestNode(Directory::class);
$propFind = new PropFind(
'/dummyPath',
diff --git a/apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php
index 8b169dcd46f..e6cfb1f67b2 100644
--- a/apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -11,6 +12,7 @@ use OC\Files\View;
use OCA\DAV\Connector\Sabre\Directory;
use OCA\DAV\Connector\Sabre\FilesPlugin;
use OCA\DAV\Connector\Sabre\FilesReportPlugin as FilesReportPluginImplementation;
+use OCP\Accounts\IAccountManager;
use OCP\App\IAppManager;
use OCP\Files\File;
use OCP\Files\FileInfo;
@@ -30,6 +32,7 @@ use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagNotFoundException;
use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\INode;
+use Sabre\DAV\Server;
use Sabre\DAV\Tree;
use Sabre\HTTP\ResponseInterface;
@@ -51,15 +54,11 @@ class FilesReportPluginTest extends \Test\TestCase {
protected function setUp(): void {
parent::setUp();
- $this->tree = $this->getMockBuilder(Tree::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->view = $this->getMockBuilder(View::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->tree = $this->createMock(Tree::class);
+ $this->view = $this->createMock(View::class);
- $this->server = $this->getMockBuilder('\Sabre\DAV\Server')
+ $this->server = $this->getMockBuilder(Server::class)
->setConstructorArgs([$this->tree])
->onlyMethods(['getRequestUri', 'getBaseUri'])
->getMock();
@@ -68,22 +67,10 @@ class FilesReportPluginTest extends \Test\TestCase {
->method('getBaseUri')
->willReturn('http://example.com/owncloud/remote.php/dav');
- $this->groupManager = $this->getMockBuilder(IGroupManager::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->userFolder = $this->getMockBuilder(Folder::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->previewManager = $this->getMockBuilder(IPreview::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->appManager = $this->getMockBuilder(IAppManager::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $this->groupManager = $this->createMock(IGroupManager::class);
+ $this->userFolder = $this->createMock(Folder::class);
+ $this->previewManager = $this->createMock(IPreview::class);
+ $this->appManager = $this->createMock(IAppManager::class);
$this->tagManager = $this->createMock(ISystemTagManager::class);
$this->tagMapper = $this->createMock(ISystemTagObjectMapper::class);
$this->userSession = $this->createMock(IUserSession::class);
@@ -94,9 +81,7 @@ class FilesReportPluginTest extends \Test\TestCase {
->with('files')
->willReturn($this->privateTags);
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('testuser');
@@ -123,11 +108,7 @@ class FilesReportPluginTest extends \Test\TestCase {
$this->tree->expects($this->any())
->method('getNodeForPath')
->with('/' . $path)
- ->willReturn(
- $this->getMockBuilder(INode::class)
- ->disableOriginalConstructor()
- ->getMock()
- );
+ ->willReturn($this->createMock(INode::class));
$this->server->expects($this->any())
->method('getRequestUri')
@@ -181,16 +162,12 @@ class FilesReportPluginTest extends \Test\TestCase {
->method('isAdmin')
->willReturn(true);
- $reportTargetNode = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $reportTargetNode = $this->createMock(Directory::class);
$reportTargetNode->expects($this->any())
->method('getPath')
->willReturn('');
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $response = $this->createMock(ResponseInterface::class);
$response->expects($this->once())
->method('setHeader')
@@ -239,14 +216,10 @@ class FilesReportPluginTest extends \Test\TestCase {
$this->userFolder->expects($this->exactly(2))
->method('searchBySystemTag')
- ->withConsecutive(
- ['OneTwoThree'],
- ['FourFiveSix'],
- )
- ->willReturnOnConsecutiveCalls(
- [$filesNode1],
- [$filesNode2],
- );
+ ->willReturnMap([
+ ['OneTwoThree', 'testuser', 0, 0, [$filesNode1]],
+ ['FourFiveSix', 'testuser', 0, 0, [$filesNode2]],
+ ]);
$this->server->expects($this->any())
->method('getRequestUri')
@@ -258,74 +231,56 @@ class FilesReportPluginTest extends \Test\TestCase {
}
public function testFindNodesByFileIdsRoot(): void {
- $filesNode1 = $this->getMockBuilder(Folder::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $filesNode1 = $this->createMock(Folder::class);
$filesNode1->expects($this->once())
->method('getName')
->willReturn('first node');
- $filesNode2 = $this->getMockBuilder(File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $filesNode2 = $this->createMock(File::class);
$filesNode2->expects($this->once())
->method('getName')
->willReturn('second node');
- $reportTargetNode = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $reportTargetNode = $this->createMock(Directory::class);
$reportTargetNode->expects($this->any())
->method('getPath')
->willReturn('/');
$this->userFolder->expects($this->exactly(2))
->method('getFirstNodeById')
- ->withConsecutive(
- ['111'],
- ['222'],
- )
- ->willReturnOnConsecutiveCalls(
- $filesNode1,
- $filesNode2,
- );
+ ->willReturnMap([
+ [111, $filesNode1],
+ [222, $filesNode2],
+ ]);
/** @var Directory&MockObject $reportTargetNode */
$result = $this->plugin->findNodesByFileIds($reportTargetNode, ['111', '222']);
$this->assertCount(2, $result);
- $this->assertInstanceOf('\OCA\DAV\Connector\Sabre\Directory', $result[0]);
+ $this->assertInstanceOf(Directory::class, $result[0]);
$this->assertEquals('first node', $result[0]->getName());
- $this->assertInstanceOf('\OCA\DAV\Connector\Sabre\File', $result[1]);
+ $this->assertInstanceOf(\OCA\DAV\Connector\Sabre\File::class, $result[1]);
$this->assertEquals('second node', $result[1]->getName());
}
public function testFindNodesByFileIdsSubDir(): void {
- $filesNode1 = $this->getMockBuilder(Folder::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $filesNode1 = $this->createMock(Folder::class);
$filesNode1->expects($this->once())
->method('getName')
->willReturn('first node');
- $filesNode2 = $this->getMockBuilder(File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $filesNode2 = $this->createMock(File::class);
$filesNode2->expects($this->once())
->method('getName')
->willReturn('second node');
- $reportTargetNode = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $reportTargetNode = $this->createMock(Directory::class);
$reportTargetNode->expects($this->any())
->method('getPath')
->willReturn('/sub1/sub2');
- $subNode = $this->getMockBuilder(Folder::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $subNode = $this->createMock(Folder::class);
$this->userFolder->expects($this->once())
->method('get')
@@ -334,22 +289,18 @@ class FilesReportPluginTest extends \Test\TestCase {
$subNode->expects($this->exactly(2))
->method('getFirstNodeById')
- ->withConsecutive(
- ['111'],
- ['222'],
- )
- ->willReturnOnConsecutiveCalls(
- $filesNode1,
- $filesNode2,
- );
+ ->willReturnMap([
+ [111, $filesNode1],
+ [222, $filesNode2],
+ ]);
/** @var Directory&MockObject $reportTargetNode */
$result = $this->plugin->findNodesByFileIds($reportTargetNode, ['111', '222']);
$this->assertCount(2, $result);
- $this->assertInstanceOf('\OCA\DAV\Connector\Sabre\Directory', $result[0]);
+ $this->assertInstanceOf(Directory::class, $result[0]);
$this->assertEquals('first node', $result[0]->getName());
- $this->assertInstanceOf('\OCA\DAV\Connector\Sabre\File', $result[1]);
+ $this->assertInstanceOf(\OCA\DAV\Connector\Sabre\File::class, $result[1]);
$this->assertEquals('second node', $result[1]->getName());
}
@@ -359,12 +310,8 @@ class FilesReportPluginTest extends \Test\TestCase {
$fileInfo = $this->createMock(FileInfo::class);
$fileInfo->method('isReadable')->willReturn(true);
- $node1 = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
- $node2 = $this->getMockBuilder(\OCA\DAV\Connector\Sabre\File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node1 = $this->createMock(Directory::class);
+ $node2 = $this->createMock(\OCA\DAV\Connector\Sabre\File::class);
$node1->expects($this->once())
->method('getInternalFileId')
@@ -384,11 +331,9 @@ class FilesReportPluginTest extends \Test\TestCase {
->willReturn('/sub/node2');
$node2->method('getFileInfo')->willReturn($fileInfo);
- $config = $this->getMockBuilder(IConfig::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $config = $this->createMock(IConfig::class);
$validator = $this->createMock(IFilenameValidator::class);
+ $accountManager = $this->createMock(IAccountManager::class);
$this->server->addPlugin(
new FilesPlugin(
@@ -398,6 +343,7 @@ class FilesReportPluginTest extends \Test\TestCase {
$this->previewManager,
$this->createMock(IUserSession::class),
$validator,
+ $accountManager,
)
);
$this->plugin->initialize($this->server);
@@ -458,7 +404,7 @@ class FilesReportPluginTest extends \Test\TestCase {
->with('OneTwoThree')
->willReturn([$filesNode1, $filesNode2]);
- $this->assertEquals([$filesNode1, $filesNode2], $this->invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, 0, 0]));
+ $this->assertEquals([$filesNode1, $filesNode2], self::invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, 0, 0]));
}
public function testProcessFilterRulesAndCondition(): void {
@@ -510,21 +456,17 @@ class FilesReportPluginTest extends \Test\TestCase {
$this->userFolder->expects($this->exactly(2))
->method('searchBySystemTag')
- ->withConsecutive(
- ['OneTwoThree'],
- ['FourFiveSix'],
- )
- ->willReturnOnConsecutiveCalls(
- [$filesNode1, $filesNode2],
- [$filesNode2, $filesNode3],
- );
+ ->willReturnMap([
+ ['OneTwoThree', 'testuser', 0, 0, [$filesNode1, $filesNode2]],
+ ['FourFiveSix', 'testuser', 0, 0, [$filesNode2, $filesNode3]],
+ ]);
$rules = [
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'],
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '456'],
];
- $this->assertEquals([$filesNode2], array_values($this->invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null])));
+ $this->assertEquals([$filesNode2], array_values(self::invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null])));
}
public function testProcessFilterRulesAndConditionWithOneEmptyResult(): void {
@@ -569,21 +511,17 @@ class FilesReportPluginTest extends \Test\TestCase {
$this->userFolder->expects($this->exactly(2))
->method('searchBySystemTag')
- ->withConsecutive(
- ['OneTwoThree'],
- ['FourFiveSix'],
- )
- ->willReturnOnConsecutiveCalls(
- [$filesNode1, $filesNode2],
- [],
- );
+ ->willReturnMap([
+ ['OneTwoThree', 'testuser', 0, 0, [$filesNode1, $filesNode2]],
+ ['FourFiveSix', 'testuser', 0, 0, []],
+ ]);
$rules = [
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'],
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '456'],
];
- $this->assertEquals([], $this->invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null]));
+ $this->assertEquals([], self::invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null]));
}
public function testProcessFilterRulesAndConditionWithFirstEmptyResult(): void {
@@ -628,18 +566,16 @@ class FilesReportPluginTest extends \Test\TestCase {
$this->userFolder->expects($this->once())
->method('searchBySystemTag')
- ->with('OneTwoThree')
- ->willReturnOnConsecutiveCalls(
- [],
- [$filesNode1, $filesNode2],
- );
+ ->willReturnMap([
+ ['OneTwoThree', 'testuser', 0, 0, []],
+ ]);
$rules = [
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'],
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '456'],
];
- $this->assertEquals([], $this->invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null]));
+ $this->assertEquals([], self::invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null]));
}
public function testProcessFilterRulesAndConditionWithEmptyMidResult(): void {
@@ -686,7 +622,7 @@ class FilesReportPluginTest extends \Test\TestCase {
$tag789 = $this->createMock(ISystemTag::class);
$tag789->expects($this->any())
->method('getName')
- ->willReturn('SevenEightNein');
+ ->willReturn('SevenEightNine');
$tag789->expects($this->any())
->method('isUserVisible')
->willReturn(true);
@@ -698,12 +634,10 @@ class FilesReportPluginTest extends \Test\TestCase {
$this->userFolder->expects($this->exactly(2))
->method('searchBySystemTag')
- ->withConsecutive(['OneTwoThree'], ['FourFiveSix'], ['SevenEightNein'])
- ->willReturnOnConsecutiveCalls(
- [$filesNode1, $filesNode2],
- [$filesNode3],
- [$filesNode1, $filesNode2],
- );
+ ->willReturnMap([
+ ['OneTwoThree', 'testuser', 0, 0, [$filesNode1, $filesNode2]],
+ ['FourFiveSix', 'testuser', 0, 0, [$filesNode3]],
+ ]);
$rules = [
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'],
@@ -711,7 +645,7 @@ class FilesReportPluginTest extends \Test\TestCase {
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '789'],
];
- $this->assertEquals([], array_values($this->invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null])));
+ $this->assertEquals([], array_values(self::invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null])));
}
public function testProcessFilterRulesInvisibleTagAsAdmin(): void {
@@ -763,18 +697,17 @@ class FilesReportPluginTest extends \Test\TestCase {
$this->userFolder->expects($this->exactly(2))
->method('searchBySystemTag')
- ->withConsecutive(['OneTwoThree'], ['FourFiveSix'])
- ->willReturnOnConsecutiveCalls(
- [$filesNode1, $filesNode2],
- [$filesNode2, $filesNode3],
- );
+ ->willReturnMap([
+ ['OneTwoThree', 'testuser', 0, 0, [$filesNode1, $filesNode2]],
+ ['FourFiveSix', 'testuser', 0, 0, [$filesNode2, $filesNode3]],
+ ]);
$rules = [
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'],
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '456'],
];
- $this->assertEquals([$filesNode2], array_values($this->invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null])));
+ $this->assertEquals([$filesNode2], array_values(self::invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null])));
}
@@ -813,7 +746,7 @@ class FilesReportPluginTest extends \Test\TestCase {
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '456'],
];
- $this->invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null]);
+ self::invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null]);
}
public function testProcessFilterRulesVisibleTagAsUser(): void {
@@ -878,18 +811,17 @@ class FilesReportPluginTest extends \Test\TestCase {
// main assertion: only user visible tags are being passed through.
$this->userFolder->expects($this->exactly(2))
->method('searchBySystemTag')
- ->withConsecutive(['OneTwoThree'], ['FourFiveSix'])
- ->willReturnOnConsecutiveCalls(
- [$filesNode1, $filesNode2],
- [$filesNode2, $filesNode3],
- );
+ ->willReturnMap([
+ ['OneTwoThree', 'testuser', 0, 0, [$filesNode1, $filesNode2]],
+ ['FourFiveSix', 'testuser', 0, 0, [$filesNode2, $filesNode3]],
+ ]);
$rules = [
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '123'],
['name' => '{http://owncloud.org/ns}systemtag', 'value' => '456'],
];
- $this->assertEquals([$filesNode2], array_values($this->invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null])));
+ $this->assertEquals([$filesNode2], array_values(self::invokePrivate($this->plugin, 'processFilterRulesForFileNodes', [$rules, null, null])));
}
public function testProcessFavoriteFilter(): void {
@@ -901,10 +833,10 @@ class FilesReportPluginTest extends \Test\TestCase {
->method('getFavorites')
->willReturn(['456', '789']);
- $this->assertEquals(['456', '789'], array_values($this->invokePrivate($this->plugin, 'processFilterRulesForFileIDs', [$rules])));
+ $this->assertEquals(['456', '789'], array_values(self::invokePrivate($this->plugin, 'processFilterRulesForFileIDs', [$rules])));
}
- public function filesBaseUriProvider() {
+ public static function filesBaseUriProvider(): array {
return [
['', '', ''],
['files/username', '', '/files/username'],
@@ -917,7 +849,7 @@ class FilesReportPluginTest extends \Test\TestCase {
/**
* @dataProvider filesBaseUriProvider
*/
- public function testFilesBaseUri($uri, $reportPath, $expectedUri): void {
- $this->assertEquals($expectedUri, $this->invokePrivate($this->plugin, 'getFilesBaseUri', [$uri, $reportPath]));
+ public function testFilesBaseUri(string $uri, string $reportPath, string $expectedUri): void {
+ $this->assertEquals($expectedUri, self::invokePrivate($this->plugin, 'getFilesBaseUri', [$uri, $reportPath]));
}
}
diff --git a/apps/dav/tests/unit/Connector/Sabre/MaintenancePluginTest.php b/apps/dav/tests/unit/Connector/Sabre/MaintenancePluginTest.php
index 9ecc49222e9..bc1d50ac41f 100644
--- a/apps/dav/tests/unit/Connector/Sabre/MaintenancePluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/MaintenancePluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -10,6 +11,7 @@ namespace OCA\DAV\Tests\unit\Connector\Sabre;
use OCA\DAV\Connector\Sabre\MaintenancePlugin;
use OCP\IConfig;
use OCP\IL10N;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
/**
@@ -18,18 +20,15 @@ use Test\TestCase;
* @package OCA\DAV\Tests\unit\Connector\Sabre
*/
class MaintenancePluginTest extends TestCase {
- /** @var IConfig */
- private $config;
- /** @var \PHPUnit\Framework\MockObject\Builder\InvocationMocker|\PHPUnit_Framework_MockObject_Builder_InvocationMocker|IL10N */
- private $l10n;
- /** @var MaintenancePlugin */
- private $maintenancePlugin;
+ private IConfig&MockObject $config;
+ private IL10N&MockObject $l10n;
+ private MaintenancePlugin $maintenancePlugin;
protected function setUp(): void {
parent::setUp();
- $this->config = $this->getMockBuilder(IConfig::class)->getMock();
- $this->l10n = $this->getMockBuilder(IL10N::class)->getMock();
+ $this->config = $this->createMock(IConfig::class);
+ $this->l10n = $this->createMock(IL10N::class);
$this->maintenancePlugin = new MaintenancePlugin($this->config, $this->l10n);
}
diff --git a/apps/dav/tests/unit/Connector/Sabre/NodeTest.php b/apps/dav/tests/unit/Connector/Sabre/NodeTest.php
index 04cd60fbdaa..3dea5cf281b 100644
--- a/apps/dav/tests/unit/Connector/Sabre/NodeTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/NodeTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -32,7 +33,7 @@ use PHPUnit\Framework\MockObject\MockObject;
* @package OCA\DAV\Tests\unit\Connector\Sabre
*/
class NodeTest extends \Test\TestCase {
- public function davPermissionsProvider() {
+ public static function davPermissionsProvider(): array {
return [
[Constants::PERMISSION_ALL, 'file', false, Constants::PERMISSION_ALL, false, 'test', 'RGDNVW'],
[Constants::PERMISSION_ALL, 'dir', false, Constants::PERMISSION_ALL, false, 'test', 'RGDNVCK'],
@@ -53,7 +54,7 @@ class NodeTest extends \Test\TestCase {
/**
* @dataProvider davPermissionsProvider
*/
- public function testDavPermissions($permissions, $type, $shared, $shareRootPermissions, $mounted, $internalPath, $expected): void {
+ public function testDavPermissions(int $permissions, string $type, bool $shared, int $shareRootPermissions, bool $mounted, string $internalPath, string $expected): void {
$info = $this->getMockBuilder(FileInfo::class)
->disableOriginalConstructor()
->onlyMethods(['getPermissions', 'isShared', 'isMounted', 'getType', 'getInternalPath', 'getStorage', 'getMountPoint'])
@@ -94,15 +95,13 @@ class NodeTest extends \Test\TestCase {
}
$info->method('getStorage')
->willReturn($storage);
- $view = $this->getMockBuilder(View::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $view = $this->createMock(View::class);
$node = new File($view, $info);
$this->assertEquals($expected, $node->getDavPermissions());
}
- public function sharePermissionsProvider() {
+ public static function sharePermissionsProvider(): array {
return [
[\OCP\Files\FileInfo::TYPE_FILE, null, 1, 1],
[\OCP\Files\FileInfo::TYPE_FILE, null, 3, 3],
@@ -145,18 +144,14 @@ class NodeTest extends \Test\TestCase {
/**
* @dataProvider sharePermissionsProvider
*/
- public function testSharePermissions($type, $user, $permissions, $expected): void {
- $storage = $this->getMockBuilder(IStorage::class)
- ->disableOriginalConstructor()
- ->getMock();
+ public function testSharePermissions(string $type, ?string $user, int $permissions, int $expected): void {
+ $storage = $this->createMock(IStorage::class);
$storage->method('getPermissions')->willReturn($permissions);
- $mountpoint = $this->getMockBuilder(IMountPoint::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $mountpoint = $this->createMock(IMountPoint::class);
$mountpoint->method('getMountPoint')->willReturn('myPath');
- $shareManager = $this->getMockBuilder(IManager::class)->disableOriginalConstructor()->getMock();
- $share = $this->getMockBuilder(IShare::class)->disableOriginalConstructor()->getMock();
+ $shareManager = $this->createMock(IManager::class);
+ $share = $this->createMock(IShare::class);
if ($user === null) {
$shareManager->expects($this->never())->method('getShareByToken');
@@ -169,7 +164,7 @@ class NodeTest extends \Test\TestCase {
$info = $this->getMockBuilder(FileInfo::class)
->disableOriginalConstructor()
- ->setMethods(['getStorage', 'getType', 'getMountPoint', 'getPermissions'])
+ ->onlyMethods(['getStorage', 'getType', 'getMountPoint', 'getPermissions'])
->getMock();
$info->method('getStorage')->willReturn($storage);
@@ -177,9 +172,7 @@ class NodeTest extends \Test\TestCase {
$info->method('getMountPoint')->willReturn($mountpoint);
$info->method('getPermissions')->willReturn($permissions);
- $view = $this->getMockBuilder(View::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $view = $this->createMock(View::class);
$node = new File($view, $info);
$this->invokePrivate($node, 'shareManager', [$shareManager]);
@@ -189,11 +182,11 @@ class NodeTest extends \Test\TestCase {
public function testShareAttributes(): void {
$storage = $this->getMockBuilder(SharedStorage::class)
->disableOriginalConstructor()
- ->setMethods(['getShare'])
+ ->onlyMethods(['getShare'])
->getMock();
- $shareManager = $this->getMockBuilder(IManager::class)->disableOriginalConstructor()->getMock();
- $share = $this->getMockBuilder(IShare::class)->disableOriginalConstructor()->getMock();
+ $shareManager = $this->createMock(IManager::class);
+ $share = $this->createMock(IShare::class);
$storage->expects($this->once())
->method('getShare')
@@ -214,9 +207,7 @@ class NodeTest extends \Test\TestCase {
$info->method('getType')->willReturn(FileInfo::TYPE_FOLDER);
/** @var View&MockObject $view */
- $view = $this->getMockBuilder(View::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $view = $this->createMock(View::class);
$node = new File($view, $info);
$this->invokePrivate($node, 'shareManager', [$shareManager]);
@@ -224,11 +215,8 @@ class NodeTest extends \Test\TestCase {
}
public function testShareAttributesNonShare(): void {
- $storage = $this->getMockBuilder(IStorage::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $shareManager = $this->getMockBuilder(IManager::class)->disableOriginalConstructor()->getMock();
+ $storage = $this->createMock(IStorage::class);
+ $shareManager = $this->createMock(IManager::class);
/** @var Folder&MockObject */
$info = $this->getMockBuilder(Folder::class)
@@ -240,16 +228,14 @@ class NodeTest extends \Test\TestCase {
$info->method('getType')->willReturn(FileInfo::TYPE_FOLDER);
/** @var View&MockObject */
- $view = $this->getMockBuilder(View::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $view = $this->createMock(View::class);
$node = new File($view, $info);
$this->invokePrivate($node, 'shareManager', [$shareManager]);
$this->assertEquals([], $node->getShareAttributes());
}
- public function sanitizeMtimeProvider() {
+ public static function sanitizeMtimeProvider(): array {
return [
[123456789, 123456789],
['987654321', 987654321],
@@ -259,7 +245,7 @@ class NodeTest extends \Test\TestCase {
/**
* @dataProvider sanitizeMtimeProvider
*/
- public function testSanitizeMtime($mtime, $expected): void {
+ public function testSanitizeMtime(string|int $mtime, int $expected): void {
$view = $this->getMockBuilder(View::class)
->disableOriginalConstructor()
->getMock();
@@ -272,7 +258,7 @@ class NodeTest extends \Test\TestCase {
$this->assertEquals($expected, $result);
}
- public function invalidSanitizeMtimeProvider() {
+ public static function invalidSanitizeMtimeProvider(): array {
return [
[-1337], [0], ['abcdef'], ['-1337'], ['0'], [12321], [24 * 60 * 60 - 1],
];
@@ -281,17 +267,13 @@ class NodeTest extends \Test\TestCase {
/**
* @dataProvider invalidSanitizeMtimeProvider
*/
- public function testInvalidSanitizeMtime($mtime): void {
+ public function testInvalidSanitizeMtime(int|string $mtime): void {
$this->expectException(\InvalidArgumentException::class);
- $view = $this->getMockBuilder(View::class)
- ->disableOriginalConstructor()
- ->getMock();
- $info = $this->getMockBuilder(FileInfo::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $view = $this->createMock(View::class);
+ $info = $this->createMock(FileInfo::class);
$node = new File($view, $info);
- $result = $this->invokePrivate($node, 'sanitizeMtime', [$mtime]);
+ self::invokePrivate($node, 'sanitizeMtime', [$mtime]);
}
}
diff --git a/apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php b/apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php
index 393f3c72c20..4a5937e365b 100644
--- a/apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -27,7 +28,7 @@ use OCP\Files\Mount\IMountManager;
* @package OCA\DAV\Tests\Unit\Connector\Sabre
*/
class ObjectTreeTest extends \Test\TestCase {
- public function copyDataProvider() {
+ public static function copyDataProvider(): array {
return [
// copy into same dir
['a', 'b', ''],
@@ -41,7 +42,7 @@ class ObjectTreeTest extends \Test\TestCase {
/**
* @dataProvider copyDataProvider
*/
- public function testCopy($sourcePath, $targetPath, $targetParent): void {
+ public function testCopy(string $sourcePath, string $targetPath, string $targetParent): void {
$view = $this->createMock(View::class);
$view->expects($this->once())
->method('verifyPath')
@@ -67,7 +68,7 @@ class ObjectTreeTest extends \Test\TestCase {
$rootDir = new Directory($view, $info);
$objectTree = $this->getMockBuilder(ObjectTree::class)
- ->setMethods(['nodeExists', 'getNodeForPath'])
+ ->onlyMethods(['nodeExists', 'getNodeForPath'])
->setConstructorArgs([$rootDir, $view])
->getMock();
@@ -110,7 +111,7 @@ class ObjectTreeTest extends \Test\TestCase {
$rootDir = new Directory($view, $info);
$objectTree = $this->getMockBuilder(ObjectTree::class)
- ->setMethods(['nodeExists', 'getNodeForPath'])
+ ->onlyMethods(['nodeExists', 'getNodeForPath'])
->setConstructorArgs([$rootDir, $view])
->getMock();
@@ -127,23 +128,15 @@ class ObjectTreeTest extends \Test\TestCase {
* @dataProvider nodeForPathProvider
*/
public function testGetNodeForPath(
- $inputFileName,
- $fileInfoQueryPath,
- $outputFileName,
- $type,
+ string $inputFileName,
+ string $fileInfoQueryPath,
+ string $outputFileName,
+ string $type,
): void {
- $rootNode = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
- $mountManager = $this->getMockBuilder(Manager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $view = $this->getMockBuilder(View::class)
- ->disableOriginalConstructor()
- ->getMock();
- $fileInfo = $this->getMockBuilder(FileInfo::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $rootNode = $this->createMock(Directory::class);
+ $mountManager = $this->createMock(Manager::class);
+ $view = $this->createMock(View::class);
+ $fileInfo = $this->createMock(FileInfo::class);
$fileInfo->method('getType')
->willReturn($type);
$fileInfo->method('getName')
@@ -164,13 +157,13 @@ class ObjectTreeTest extends \Test\TestCase {
$this->assertEquals($outputFileName, $node->getName());
if ($type === 'file') {
- $this->assertTrue($node instanceof File);
+ $this->assertInstanceOf(File::class, $node);
} else {
- $this->assertTrue($node instanceof Directory);
+ $this->assertInstanceOf(Directory::class, $node);
}
}
- public function nodeForPathProvider() {
+ public static function nodeForPathProvider(): array {
return [
// regular file
[
@@ -213,7 +206,7 @@ class ObjectTreeTest extends \Test\TestCase {
$storage = new Temporary([]);
$view = $this->getMockBuilder(View::class)
- ->setMethods(['resolvePath'])
+ ->onlyMethods(['resolvePath'])
->getMock();
$view->expects($this->once())
->method('resolvePath')
@@ -221,9 +214,7 @@ class ObjectTreeTest extends \Test\TestCase {
return [$storage, ltrim($path, '/')];
});
- $rootNode = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $rootNode = $this->createMock(Directory::class);
$mountManager = $this->createMock(IMountManager::class);
$tree = new ObjectTree();
@@ -239,7 +230,7 @@ class ObjectTreeTest extends \Test\TestCase {
$storage = new Temporary([]);
$view = $this->getMockBuilder(View::class)
- ->setMethods(['resolvePath'])
+ ->onlyMethods(['resolvePath'])
->getMock();
$view->expects($this->any())
->method('resolvePath')
@@ -247,9 +238,7 @@ class ObjectTreeTest extends \Test\TestCase {
return [$storage, ltrim($path, '/')];
});
- $rootNode = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $rootNode = $this->createMock(Directory::class);
$mountManager = $this->createMock(IMountManager::class);
$tree = new ObjectTree();
diff --git a/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php b/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php
index 30e2c995d18..087bbd66107 100644
--- a/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -30,38 +32,21 @@ use Sabre\DAV\PropPatch;
use Test\TestCase;
class PrincipalTest extends TestCase {
- /** @var IUserManager | MockObject */
- private $userManager;
-
- /** @var Principal */
- private $connector;
-
- /** @var IGroupManager | MockObject */
- private $groupManager;
-
- /** @var IAccountManager|MockObject */
- private $accountManager;
-
- /** @var IManager | MockObject */
- private $shareManager;
-
- /** @var IUserSession | MockObject */
- private $userSession;
-
- /** @var IAppManager | MockObject */
- private $appManager;
-
- /** @var ProxyMapper | MockObject */
- private $proxyMapper;
-
- /** @var KnownUserService|MockObject */
- private $knownUserService;
- /** @var IConfig | MockObject */
- private $config;
- /** @var IFactory|MockObject */
- private $languageFactory;
+ private IUserManager&MockObject $userManager;
+ private IGroupManager&MockObject $groupManager;
+ private IAccountManager&MockObject $accountManager;
+ private IManager&MockObject $shareManager;
+ private IUserSession&MockObject $userSession;
+ private IAppManager&MockObject $appManager;
+ private ProxyMapper&MockObject $proxyMapper;
+ private KnownUserService&MockObject $knownUserService;
+ private IConfig&MockObject $config;
+ private IFactory&MockObject $languageFactory;
+ private Principal $connector;
protected function setUp(): void {
+ parent::setUp();
+
$this->userManager = $this->createMock(IUserManager::class);
$this->groupManager = $this->createMock(IGroupManager::class);
$this->accountManager = $this->createMock(IAccountManager::class);
@@ -85,7 +70,6 @@ class PrincipalTest extends TestCase {
$this->config,
$this->languageFactory
);
- parent::setUp();
}
public function testGetPrincipalsByPrefixWithoutPrefix(): void {
@@ -125,13 +109,14 @@ class PrincipalTest extends TestCase {
$this->languageFactory
->expects($this->exactly(2))
->method('getUserLanguage')
- ->withConsecutive([$fooUser], [$barUser])
- ->willReturnOnConsecutiveCalls('de', 'en');
+ ->willReturnMap([
+ [$fooUser, 'de'],
+ [$barUser, 'en'],
+ ]);
$fooAccountPropertyCollection = $this->createMock(IAccountPropertyCollection::class);
$fooAccountPropertyCollection->expects($this->once())
->method('getProperties')
- ->with()
->willReturn([]);
$fooAccount = $this->createMock(IAccount::class);
$fooAccount->expects($this->once())
@@ -142,18 +127,15 @@ class PrincipalTest extends TestCase {
$emailPropertyOne = $this->createMock(IAccountProperty::class);
$emailPropertyOne->expects($this->once())
->method('getValue')
- ->with()
->willReturn('alias@nextcloud.com');
$emailPropertyTwo = $this->createMock(IAccountProperty::class);
$emailPropertyTwo->expects($this->once())
->method('getValue')
- ->with()
->willReturn('alias2@nextcloud.com');
$barAccountPropertyCollection = $this->createMock(IAccountPropertyCollection::class);
$barAccountPropertyCollection->expects($this->once())
->method('getProperties')
- ->with()
->willReturn([$emailPropertyOne, $emailPropertyTwo]);
$barAccount = $this->createMock(IAccount::class);
$barAccount->expects($this->once())
@@ -164,8 +146,10 @@ class PrincipalTest extends TestCase {
$this->accountManager
->expects($this->exactly(2))
->method('getAccount')
- ->withConsecutive([$fooUser], [$barUser])
- ->willReturnOnConsecutiveCalls($fooAccount, $barAccount);
+ ->willReturnMap([
+ [$fooUser, $fooAccount],
+ [$barUser, $barAccount],
+ ]);
$expectedResponse = [
0 => [
@@ -482,7 +466,7 @@ class PrincipalTest extends TestCase {
/**
* @dataProvider searchPrincipalsDataProvider
*/
- public function testSearchPrincipals($sharingEnabled, $groupsOnly, $test, $result): void {
+ public function testSearchPrincipals(bool $sharingEnabled, bool $groupsOnly, string $test, array $result): void {
$this->shareManager->expects($this->once())
->method('shareAPIEnabled')
->willReturn($sharingEnabled);
@@ -556,7 +540,7 @@ class PrincipalTest extends TestCase {
'{DAV:}displayname' => 'User 12'], $test));
}
- public function searchPrincipalsDataProvider(): array {
+ public static function searchPrincipalsDataProvider(): array {
return [
[true, false, 'allof', ['principals/users/user3']],
[true, false, 'anyof', ['principals/users/user2', 'principals/users/user3', 'principals/users/user4']],
@@ -845,7 +829,7 @@ class PrincipalTest extends TestCase {
/**
* @dataProvider findByUriWithGroupRestrictionDataProvider
*/
- public function testFindByUriWithGroupRestriction($uri, $email, $expects): void {
+ public function testFindByUriWithGroupRestriction(string $uri, string $email, ?string $expects): void {
$this->shareManager->expects($this->once())
->method('shareApiEnabled')
->willReturn(true);
@@ -872,31 +856,23 @@ class PrincipalTest extends TestCase {
if ($email === 'user2@foo.bar') {
$this->groupManager->expects($this->exactly(2))
->method('getUserGroupIds')
- ->withConsecutive(
- [$user],
- [$user2],
- )
- ->willReturnOnConsecutiveCalls(
- ['group1', 'group2'],
- ['group1', 'group3'],
- );
+ ->willReturnMap([
+ [$user, ['group1', 'group2']],
+ [$user2, ['group1', 'group3']],
+ ]);
} else {
$this->groupManager->expects($this->exactly(2))
->method('getUserGroupIds')
- ->withConsecutive(
- [$user],
- [$user3],
- )
- ->willReturnOnConsecutiveCalls(
- ['group1', 'group2'],
- ['group3', 'group3'],
- );
+ ->willReturnMap([
+ [$user, ['group1', 'group2']],
+ [$user3, ['group3', 'group3']],
+ ]);
}
$this->assertEquals($expects, $this->connector->findByUri($uri, 'principals/users'));
}
- public function findByUriWithGroupRestrictionDataProvider(): array {
+ public static function findByUriWithGroupRestrictionDataProvider(): array {
return [
['mailto:user2@foo.bar', 'user2@foo.bar', 'principals/users/user2'],
['mailto:user3@foo.bar', 'user3@foo.bar', null],
@@ -906,7 +882,7 @@ class PrincipalTest extends TestCase {
/**
* @dataProvider findByUriWithoutGroupRestrictionDataProvider
*/
- public function testFindByUriWithoutGroupRestriction($uri, $email, $expects): void {
+ public function testFindByUriWithoutGroupRestriction(string $uri, string $email, string $expects): void {
$this->shareManager->expects($this->once())
->method('shareApiEnabled')
->willReturn(true);
@@ -928,7 +904,7 @@ class PrincipalTest extends TestCase {
$this->assertEquals($expects, $this->connector->findByUri($uri, 'principals/users'));
}
- public function findByUriWithoutGroupRestrictionDataProvider(): array {
+ public static function findByUriWithoutGroupRestrictionDataProvider(): array {
return [
['mailto:user2@foo.bar', 'user2@foo.bar', 'principals/users/user2'],
['mailto:user3@foo.bar', 'user3@foo.bar', 'principals/users/user3'],
diff --git a/apps/dav/tests/unit/Connector/Sabre/PropfindCompressionPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/PropfindCompressionPluginTest.php
index 42414ad6efb..e6f696ed160 100644
--- a/apps/dav/tests/unit/Connector/Sabre/PropfindCompressionPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/PropfindCompressionPluginTest.php
@@ -14,8 +14,7 @@ use Sabre\HTTP\Response;
use Test\TestCase;
class PropfindCompressionPluginTest extends TestCase {
- /** @var PropfindCompressionPlugin */
- private $plugin;
+ private PropfindCompressionPlugin $plugin;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/Connector/Sabre/PublicAuthTest.php b/apps/dav/tests/unit/Connector/Sabre/PublicAuthTest.php
index 00bddf2e69c..2340890ae5a 100644
--- a/apps/dav/tests/unit/Connector/Sabre/PublicAuthTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/PublicAuthTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -10,10 +11,12 @@ namespace OCA\DAV\Tests\unit\Connector;
use OCA\DAV\Connector\Sabre\PublicAuth;
use OCP\IRequest;
use OCP\ISession;
+use OCP\IURLGenerator;
use OCP\Security\Bruteforce\IThrottler;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager;
use OCP\Share\IShare;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
/**
@@ -25,21 +28,15 @@ use Psr\Log\LoggerInterface;
*/
class PublicAuthTest extends \Test\TestCase {
- /** @var ISession|MockObject */
- private $session;
- /** @var IRequest|MockObject */
- private $request;
- /** @var IManager|MockObject */
- private $shareManager;
- /** @var PublicAuth */
- private $auth;
- /** @var IThrottler|MockObject */
- private $throttler;
- /** @var LoggerInterface|MockObject */
- private $logger;
-
- /** @var string */
- private $oldUser;
+ private ISession&MockObject $session;
+ private IRequest&MockObject $request;
+ private IManager&MockObject $shareManager;
+ private IThrottler&MockObject $throttler;
+ private LoggerInterface&MockObject $logger;
+ private IURLGenerator&MockObject $urlGenerator;
+ private PublicAuth $auth;
+
+ private bool|string $oldUser;
protected function setUp(): void {
parent::setUp();
@@ -49,6 +46,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->shareManager = $this->createMock(IManager::class);
$this->throttler = $this->createMock(IThrottler::class);
$this->logger = $this->createMock(LoggerInterface::class);
+ $this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->auth = new PublicAuth(
$this->request,
@@ -56,6 +54,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->session,
$this->throttler,
$this->logger,
+ $this->urlGenerator,
);
// Store current user
@@ -67,7 +66,9 @@ class PublicAuthTest extends \Test\TestCase {
// Set old user
\OC_User::setUserId($this->oldUser);
- \OC_Util::setupFS($this->oldUser);
+ if ($this->oldUser !== false) {
+ \OC_Util::setupFS($this->oldUser);
+ }
parent::tearDown();
}
@@ -76,7 +77,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $result = $this->invokePrivate($this->auth, 'getToken');
+ $result = self::invokePrivate($this->auth, 'getToken');
$this->assertSame('GX9HSGQrGE', $result);
}
@@ -86,16 +87,14 @@ class PublicAuthTest extends \Test\TestCase {
->willReturn('/dav/files');
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
- $this->invokePrivate($this->auth, 'getToken');
+ self::invokePrivate($this->auth, 'getToken');
}
public function testCheckTokenValidShare(): void {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn(null);
$this->shareManager->expects($this->once())
@@ -103,7 +102,7 @@ class PublicAuthTest extends \Test\TestCase {
->with('GX9HSGQrGE')
->willReturn($share);
- $result = $this->invokePrivate($this->auth, 'checkToken');
+ $result = self::invokePrivate($this->auth, 'checkToken');
$this->assertSame([true, 'principals/GX9HSGQrGE'], $result);
}
@@ -118,16 +117,14 @@ class PublicAuthTest extends \Test\TestCase {
->will($this->throwException(new ShareNotFound()));
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
- $this->invokePrivate($this->auth, 'checkToken');
+ self::invokePrivate($this->auth, 'checkToken');
}
public function testCheckTokenAlreadyAuthenticated(): void {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getShareType')->willReturn(42);
$this->shareManager->expects($this->once())
@@ -137,8 +134,8 @@ class PublicAuthTest extends \Test\TestCase {
$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
$this->session->method('get')->with('public_link_authenticated')->willReturn('42');
-
- $result = $this->invokePrivate($this->auth, 'checkToken');
+
+ $result = self::invokePrivate($this->auth, 'checkToken');
$this->assertSame([true, 'principals/GX9HSGQrGE'], $result);
}
@@ -146,9 +143,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(42);
@@ -158,18 +153,16 @@ class PublicAuthTest extends \Test\TestCase {
->willReturn($share);
$this->session->method('exists')->with('public_link_authenticated')->willReturn(false);
-
+
$this->expectException(\Sabre\DAV\Exception\NotAuthenticated::class);
- $this->invokePrivate($this->auth, 'checkToken');
+ self::invokePrivate($this->auth, 'checkToken');
}
public function testCheckTokenPasswordAuthenticatedWrongShare(): void {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(42);
@@ -180,9 +173,9 @@ class PublicAuthTest extends \Test\TestCase {
$this->session->method('exists')->with('public_link_authenticated')->willReturn(false);
$this->session->method('get')->with('public_link_authenticated')->willReturn('43');
-
+
$this->expectException(\Sabre\DAV\Exception\NotAuthenticated::class);
- $this->invokePrivate($this->auth, 'checkToken');
+ self::invokePrivate($this->auth, 'checkToken');
}
public function testNoShare(): void {
@@ -194,7 +187,7 @@ class PublicAuthTest extends \Test\TestCase {
->with('GX9HSGQrGE')
->willThrowException(new ShareNotFound());
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertFalse($result);
}
@@ -203,9 +196,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn(null);
$this->shareManager->expects($this->once())
@@ -213,7 +204,7 @@ class PublicAuthTest extends \Test\TestCase {
->with('GX9HSGQrGE')
->willReturn($share);
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertTrue($result);
}
@@ -222,9 +213,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(42);
@@ -233,7 +222,7 @@ class PublicAuthTest extends \Test\TestCase {
->with('GX9HSGQrGE')
->willReturn($share);
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertFalse($result);
}
@@ -243,9 +232,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_REMOTE);
@@ -254,7 +241,7 @@ class PublicAuthTest extends \Test\TestCase {
->with('GX9HSGQrGE')
->willReturn($share);
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertTrue($result);
}
@@ -263,9 +250,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
@@ -280,7 +265,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->equalTo('password')
)->willReturn(true);
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertTrue($result);
}
@@ -289,9 +274,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);
@@ -306,7 +289,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->equalTo('password')
)->willReturn(true);
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertTrue($result);
}
@@ -315,9 +298,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
$share->method('getId')->willReturn('42');
@@ -337,7 +318,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
$this->session->method('get')->with('public_link_authenticated')->willReturn('42');
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertTrue($result);
}
@@ -346,9 +327,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
$share->method('getId')->willReturn('42');
@@ -368,7 +347,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
$this->session->method('get')->with('public_link_authenticated')->willReturn('43');
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertFalse($result);
}
@@ -378,9 +357,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->request->method('getPathInfo')
->willReturn('/dav/files/GX9HSGQrGE');
- $share = $this->getMockBuilder(IShare::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $share = $this->createMock(IShare::class);
$share->method('getPassword')->willReturn('password');
$share->method('getShareType')->willReturn(IShare::TYPE_EMAIL);
$share->method('getId')->willReturn('42');
@@ -400,7 +377,7 @@ class PublicAuthTest extends \Test\TestCase {
$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
$this->session->method('get')->with('public_link_authenticated')->willReturn('43');
- $result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
+ $result = self::invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
$this->assertFalse($result);
}
diff --git a/apps/dav/tests/unit/Connector/Sabre/QuotaPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/QuotaPluginTest.php
index c370e0fb0f7..a78a1a223c5 100644
--- a/apps/dav/tests/unit/Connector/Sabre/QuotaPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/QuotaPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2013-2016 ownCloud, Inc.
@@ -13,29 +14,23 @@ use OCP\Files\FileInfo;
use Test\TestCase;
class QuotaPluginTest extends TestCase {
- /** @var \Sabre\DAV\Server | \PHPUnit\Framework\MockObject\MockObject */
- private $server;
+ private \Sabre\DAV\Server $server;
- /** @var QuotaPlugin|\PHPUnit\Framework\MockObject\MockObject */
- private $plugin;
+ private QuotaPlugin $plugin;
- private function init($quota, $checkedPath = ''): void {
- $view = $this->buildFileViewMock($quota, $checkedPath);
+ private function init(int $quota, string $checkedPath = ''): void {
+ $view = $this->buildFileViewMock((string)$quota, $checkedPath);
$this->server = new \Sabre\DAV\Server();
- $this->plugin = $this->getMockBuilder(QuotaPlugin::class)
- ->setConstructorArgs([$view])
- ->setMethods(['getFileChunking'])
- ->getMock();
+ $this->plugin = new QuotaPlugin($view);
$this->plugin->initialize($this->server);
}
/**
* @dataProvider lengthProvider
*/
- public function testLength($expected, $headers): void {
+ public function testLength(?int $expected, array $headers): void {
$this->init(0);
- $this->plugin->expects($this->never())
- ->method('getFileChunking');
+
$this->server->httpRequest = new \Sabre\HTTP\Request('POST', 'dummy.file', $headers);
$length = $this->plugin->getLength();
$this->assertEquals($expected, $length);
@@ -44,10 +39,8 @@ class QuotaPluginTest extends TestCase {
/**
* @dataProvider quotaOkayProvider
*/
- public function testCheckQuota($quota, $headers): void {
+ public function testCheckQuota(int $quota, array $headers): void {
$this->init($quota);
- $this->plugin->expects($this->never())
- ->method('getFileChunking');
$this->server->httpRequest = new \Sabre\HTTP\Request('POST', 'dummy.file', $headers);
$result = $this->plugin->checkQuota('');
@@ -57,12 +50,10 @@ class QuotaPluginTest extends TestCase {
/**
* @dataProvider quotaExceededProvider
*/
- public function testCheckExceededQuota($quota, $headers): void {
+ public function testCheckExceededQuota(int $quota, array $headers): void {
$this->expectException(\Sabre\DAV\Exception\InsufficientStorage::class);
$this->init($quota);
- $this->plugin->expects($this->never())
- ->method('getFileChunking');
$this->server->httpRequest = new \Sabre\HTTP\Request('POST', 'dummy.file', $headers);
$this->plugin->checkQuota('');
@@ -71,17 +62,15 @@ class QuotaPluginTest extends TestCase {
/**
* @dataProvider quotaOkayProvider
*/
- public function testCheckQuotaOnPath($quota, $headers): void {
+ public function testCheckQuotaOnPath(int $quota, array $headers): void {
$this->init($quota, 'sub/test.txt');
- $this->plugin->expects($this->never())
- ->method('getFileChunking');
$this->server->httpRequest = new \Sabre\HTTP\Request('POST', 'dummy.file', $headers);
$result = $this->plugin->checkQuota('/sub/test.txt');
$this->assertTrue($result);
}
- public function quotaOkayProvider() {
+ public static function quotaOkayProvider(): array {
return [
[1024, []],
[1024, ['X-EXPECTED-ENTITY-LENGTH' => '1024']],
@@ -100,7 +89,7 @@ class QuotaPluginTest extends TestCase {
];
}
- public function quotaExceededProvider() {
+ public static function quotaExceededProvider(): array {
return [
[1023, ['X-EXPECTED-ENTITY-LENGTH' => '1024']],
[511, ['CONTENT-LENGTH' => '512']],
@@ -108,7 +97,7 @@ class QuotaPluginTest extends TestCase {
];
}
- public function lengthProvider() {
+ public static function lengthProvider(): array {
return [
[null, []],
[1024, ['X-EXPECTED-ENTITY-LENGTH' => '1024']],
@@ -124,7 +113,7 @@ class QuotaPluginTest extends TestCase {
];
}
- public function quotaChunkedOkProvider() {
+ public static function quotaChunkedOkProvider(): array {
return [
[1024, 0, ['X-EXPECTED-ENTITY-LENGTH' => '1024']],
[1024, 0, ['CONTENT-LENGTH' => '512']],
@@ -143,7 +132,7 @@ class QuotaPluginTest extends TestCase {
];
}
- public function quotaChunkedFailProvider() {
+ public static function quotaChunkedFailProvider(): array {
return [
[400, 0, ['X-EXPECTED-ENTITY-LENGTH' => '1024']],
[400, 0, ['CONTENT-LENGTH' => '512']],
@@ -155,15 +144,15 @@ class QuotaPluginTest extends TestCase {
];
}
- private function buildFileViewMock($quota, $checkedPath) {
- // mock filesysten
+ private function buildFileViewMock(string $quota, string $checkedPath): View {
+ // mock filesystem
$view = $this->getMockBuilder(View::class)
- ->setMethods(['free_space'])
+ ->onlyMethods(['free_space'])
->disableOriginalConstructor()
->getMock();
$view->expects($this->any())
->method('free_space')
- ->with($this->identicalTo($checkedPath))
+ ->with($checkedPath)
->willReturn($quota);
return $view;
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/Auth.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/Auth.php
index 836766b366d..b01807d5bbb 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/Auth.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/Auth.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/DeleteTest.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/DeleteTest.php
index e7f20fbadfa..c5c7e99c7e5 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/DeleteTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/DeleteTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -18,7 +19,7 @@ use OCP\AppFramework\Http;
*/
class DeleteTest extends RequestTestCase {
public function testBasicUpload(): void {
- $user = $this->getUniqueID();
+ $user = self::getUniqueID();
$view = $this->setupUser($user, 'pass');
$view->file_put_contents('foo.txt', 'asd');
@@ -29,7 +30,7 @@ class DeleteTest extends RequestTestCase {
$mount->getStorage()->unlink($mount->getInternalPath($internalPath));
// cache entry still exists
- $this->assertInstanceOf('\OCP\Files\FileInfo', $view->getFileInfo('foo.txt'));
+ $this->assertInstanceOf(\OCP\Files\FileInfo::class, $view->getFileInfo('foo.txt'));
$response = $this->request($view, $user, 'pass', 'DELETE', '/foo.txt');
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/DownloadTest.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/DownloadTest.php
index bec4cd9967b..34171963ef0 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/DownloadTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/DownloadTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -19,7 +20,7 @@ use OCP\Lock\ILockingProvider;
*/
class DownloadTest extends RequestTestCase {
public function testDownload(): void {
- $user = $this->getUniqueID();
+ $user = self::getUniqueID();
$view = $this->setupUser($user, 'pass');
$view->file_put_contents('foo.txt', 'bar');
@@ -30,7 +31,7 @@ class DownloadTest extends RequestTestCase {
}
public function testDownloadWriteLocked(): void {
- $user = $this->getUniqueID();
+ $user = self::getUniqueID();
$view = $this->setupUser($user, 'pass');
$view->file_put_contents('foo.txt', 'bar');
@@ -42,7 +43,7 @@ class DownloadTest extends RequestTestCase {
}
public function testDownloadReadLocked(): void {
- $user = $this->getUniqueID();
+ $user = self::getUniqueID();
$view = $this->setupUser($user, 'pass');
$view->file_put_contents('foo.txt', 'bar');
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionMasterKeyUploadTest.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionMasterKeyUploadTest.php
index 92d89d7753a..615490ddc92 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionMasterKeyUploadTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionMasterKeyUploadTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -23,7 +24,7 @@ use Test\Traits\EncryptionTrait;
class EncryptionMasterKeyUploadTest extends UploadTest {
use EncryptionTrait;
- protected function setupUser($name, $password) {
+ protected function setupUser($name, $password): View {
$this->createUser($name, $password);
$tmpFolder = Server::get(ITempManager::class)->getTemporaryFolder();
$this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionUploadTest.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionUploadTest.php
index 935ef6d9464..efa7bb54cf8 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionUploadTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/EncryptionUploadTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -23,7 +24,7 @@ use Test\Traits\EncryptionTrait;
class EncryptionUploadTest extends UploadTest {
use EncryptionTrait;
- protected function setupUser($name, $password) {
+ protected function setupUser($name, $password): View {
$this->createUser($name, $password);
$tmpFolder = Server::get(ITempManager::class)->getTemporaryFolder();
$this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/ExceptionPlugin.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/ExceptionPlugin.php
index b1e68f9597b..0c53e4b1009 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/ExceptionPlugin.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/ExceptionPlugin.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/PartFileInRootUploadTest.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/PartFileInRootUploadTest.php
index 5f3dc6f4e32..e6fa489fb24 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/PartFileInRootUploadTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/PartFileInRootUploadTest.php
@@ -21,9 +21,7 @@ use OCP\Server;
class PartFileInRootUploadTest extends UploadTest {
protected function setUp(): void {
$config = Server::get(IConfig::class);
- $mockConfig = $this->getMockBuilder(IConfig::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $mockConfig = $this->createMock(IConfig::class);
$mockConfig->expects($this->any())
->method('getSystemValue')
->willReturnCallback(function ($key, $default) use ($config) {
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/RequestTestCase.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/RequestTestCase.php
index a04aedb4e57..404dc7fa5d7 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/RequestTestCase.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/RequestTestCase.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -20,6 +21,7 @@ use OCP\IRequestId;
use OCP\ITagManager;
use OCP\ITempManager;
use OCP\IUserSession;
+use OCP\L10N\IFactory;
use Psr\Log\LoggerInterface;
use Sabre\HTTP\Request;
use Test\TestCase;
@@ -29,11 +31,7 @@ use Test\Traits\UserTrait;
abstract class RequestTestCase extends TestCase {
use UserTrait;
use MountProviderTrait;
-
- /**
- * @var ServerFactory
- */
- protected $serverFactory;
+ protected ServerFactory $serverFactory;
protected function getStream($string) {
$stream = fopen('php://temp', 'r+');
@@ -52,20 +50,18 @@ abstract class RequestTestCase extends TestCase {
\OCP\Server::get(IUserSession::class),
\OCP\Server::get(IMountManager::class),
\OCP\Server::get(ITagManager::class),
- $this->getMockBuilder(IRequest::class)
- ->disableOriginalConstructor()
- ->getMock(),
+ $this->createMock(IRequest::class),
\OCP\Server::get(IPreview::class),
\OCP\Server::get(IEventDispatcher::class),
- \OC::$server->getL10N('dav')
+ \OCP\Server::get(IFactory::class)->get('dav'),
);
}
- protected function setupUser($name, $password) {
+ protected function setupUser($name, $password): View {
$this->createUser($name, $password);
$tmpFolder = \OCP\Server::get(ITempManager::class)->getTemporaryFolder();
$this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
- $this->loginAsUser($name);
+ self::loginAsUser($name);
return new View('/' . $name . '/files');
}
@@ -137,7 +133,7 @@ abstract class RequestTestCase extends TestCase {
$authBackend = new Auth($user, $password);
$authPlugin = new \Sabre\DAV\Auth\Plugin($authBackend);
- $server = $this->serverFactory->createServer('/', 'dummy', $authPlugin, function () use ($view) {
+ $server = $this->serverFactory->createServer(false, '/', 'dummy', $authPlugin, function () use ($view) {
return $view;
});
$server->addPlugin($exceptionPlugin);
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/Sapi.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/Sapi.php
index f12c93468ff..08d774e56b8 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/Sapi.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/Sapi.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
diff --git a/apps/dav/tests/unit/Connector/Sabre/RequestTest/UploadTest.php b/apps/dav/tests/unit/Connector/Sabre/RequestTest/UploadTest.php
index 60decd4c846..5c6d0f03334 100644
--- a/apps/dav/tests/unit/Connector/Sabre/RequestTest/UploadTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/RequestTest/UploadTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -19,7 +20,7 @@ use OCP\Lock\ILockingProvider;
*/
class UploadTest extends RequestTestCase {
public function testBasicUpload(): void {
- $user = $this->getUniqueID();
+ $user = self::getUniqueID();
$view = $this->setupUser($user, 'pass');
$this->assertFalse($view->file_exists('foo.txt'));
@@ -35,7 +36,7 @@ class UploadTest extends RequestTestCase {
}
public function testUploadOverWrite(): void {
- $user = $this->getUniqueID();
+ $user = self::getUniqueID();
$view = $this->setupUser($user, 'pass');
$view->file_put_contents('foo.txt', 'foobar');
@@ -51,7 +52,7 @@ class UploadTest extends RequestTestCase {
}
public function testUploadOverWriteReadLocked(): void {
- $user = $this->getUniqueID();
+ $user = self::getUniqueID();
$view = $this->setupUser($user, 'pass');
$view->file_put_contents('foo.txt', 'bar');
@@ -63,7 +64,7 @@ class UploadTest extends RequestTestCase {
}
public function testUploadOverWriteWriteLocked(): void {
- $user = $this->getUniqueID();
+ $user = self::getUniqueID();
$view = $this->setupUser($user, 'pass');
$this->loginAsUser($user);
diff --git a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
index 97d3ba79046..00ac5b5543f 100644
--- a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -17,35 +18,17 @@ use OCP\IUser;
use OCP\IUserSession;
use OCP\Share\IManager;
use OCP\Share\IShare;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Tree;
class SharesPluginTest extends \Test\TestCase {
public const SHARETYPES_PROPERTYNAME = SharesPlugin::SHARETYPES_PROPERTYNAME;
- /**
- * @var \Sabre\DAV\Server
- */
- private $server;
-
- /**
- * @var \Sabre\DAV\Tree
- */
- private $tree;
-
- /**
- * @var \OCP\Share\IManager
- */
- private $shareManager;
-
- /**
- * @var Folder
- */
- private $userFolder;
-
- /**
- * @var SharesPlugin
- */
- private $plugin;
+ private \Sabre\DAV\Server $server;
+ private \Sabre\DAV\Tree&MockObject $tree;
+ private \OCP\Share\IManager&MockObject $shareManager;
+ private Folder&MockObject $userFolder;
+ private SharesPlugin $plugin;
protected function setUp(): void {
parent::setUp();
@@ -74,10 +57,8 @@ class SharesPluginTest extends \Test\TestCase {
/**
* @dataProvider sharesGetPropertiesDataProvider
*/
- public function testGetProperties($shareTypes): void {
- $sabreNode = $this->getMockBuilder(Node::class)
- ->disableOriginalConstructor()
- ->getMock();
+ public function testGetProperties(array $shareTypes): void {
+ $sabreNode = $this->createMock(Node::class);
$sabreNode->expects($this->any())
->method('getId')
->willReturn(123);
@@ -86,9 +67,7 @@ class SharesPluginTest extends \Test\TestCase {
->willReturn('/subdir');
// node API nodes
- $node = $this->getMockBuilder(Folder::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(Folder::class);
$sabreNode->method('getNode')
->willReturn($node);
@@ -143,7 +122,7 @@ class SharesPluginTest extends \Test\TestCase {
/**
* @dataProvider sharesGetPropertiesDataProvider
*/
- public function testPreloadThenGetProperties($shareTypes): void {
+ public function testPreloadThenGetProperties(array $shareTypes): void {
$sabreNode1 = $this->createMock(File::class);
$sabreNode1->method('getId')
->willReturn(111);
@@ -182,7 +161,7 @@ class SharesPluginTest extends \Test\TestCase {
->willReturn($node2);
$dummyShares = array_map(function ($type) {
- $share = $this->getMockBuilder(IShare::class)->getMock();
+ $share = $this->createMock(IShare::class);
$share->expects($this->any())
->method('getShareType')
->willReturn($type);
@@ -268,7 +247,7 @@ class SharesPluginTest extends \Test\TestCase {
$this->assertEquals($shareTypes, $result[200][self::SHARETYPES_PROPERTYNAME]->getShareTypes());
}
- public function sharesGetPropertiesDataProvider() {
+ public static function sharesGetPropertiesDataProvider(): array {
return [
[[]],
[[IShare::TYPE_USER]],
@@ -287,9 +266,7 @@ class SharesPluginTest extends \Test\TestCase {
}
public function testGetPropertiesSkipChunks(): void {
- $sabreNode = $this->getMockBuilder(UploadFile::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $sabreNode = $this->createMock(UploadFile::class);
$propFind = new \Sabre\DAV\PropFind(
'/dummyPath',
diff --git a/apps/dav/tests/unit/Connector/Sabre/TagsPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/TagsPluginTest.php
index 43c08a1a61c..bef508e08ca 100644
--- a/apps/dav/tests/unit/Connector/Sabre/TagsPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/TagsPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2014-2016 ownCloud, Inc.
@@ -18,6 +19,7 @@ use OCP\ITagManager;
use OCP\ITags;
use OCP\IUser;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Tree;
class TagsPluginTest extends \Test\TestCase {
@@ -25,61 +27,24 @@ class TagsPluginTest extends \Test\TestCase {
public const FAVORITE_PROPERTYNAME = TagsPlugin::FAVORITE_PROPERTYNAME;
public const TAG_FAVORITE = TagsPlugin::TAG_FAVORITE;
- /**
- * @var \Sabre\DAV\Server
- */
- private $server;
-
- /**
- * @var Tree
- */
- private $tree;
-
- /**
- * @var ITagManager
- */
- private $tagManager;
-
- /**
- * @var ITags
- */
- private $tagger;
-
- /**
- * @var IEventDispatcher
- */
- private $eventDispatcher;
-
- /**
- * @var IUserSession
- */
- private $userSession;
-
- /**
- * @var TagsPlugin
- */
- private $plugin;
+ private \Sabre\DAV\Server $server;
+ private Tree&MockObject $tree;
+ private ITagManager&MockObject $tagManager;
+ private ITags&MockObject $tagger;
+ private IEventDispatcher&MockObject $eventDispatcher;
+ private IUserSession&MockObject $userSession;
+ private TagsPlugin $plugin;
protected function setUp(): void {
parent::setUp();
+
$this->server = new \Sabre\DAV\Server();
- $this->tree = $this->getMockBuilder(Tree::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->tagger = $this->getMockBuilder(ITags::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->tagManager = $this->getMockBuilder(ITagManager::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->eventDispatcher = $this->getMockBuilder(IEventDispatcher::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->tree = $this->createMock(Tree::class);
+ $this->tagger = $this->createMock(ITags::class);
+ $this->tagManager = $this->createMock(ITagManager::class);
+ $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$user = $this->createMock(IUser::class);
- /**
- * @var IUserSession
- */
+
$this->userSession = $this->createMock(IUserSession::class);
$this->userSession->expects($this->any())
->method('getUser')
@@ -96,10 +61,8 @@ class TagsPluginTest extends \Test\TestCase {
/**
* @dataProvider tagsGetPropertiesDataProvider
*/
- public function testGetProperties($tags, $requestedProperties, $expectedProperties): void {
- $node = $this->getMockBuilder(Node::class)
- ->disableOriginalConstructor()
- ->getMock();
+ public function testGetProperties(array $tags, array $requestedProperties, array $expectedProperties): void {
+ $node = $this->createMock(Node::class);
$node->expects($this->any())
->method('getId')
->willReturn(123);
@@ -135,16 +98,12 @@ class TagsPluginTest extends \Test\TestCase {
/**
* @dataProvider tagsGetPropertiesDataProvider
*/
- public function testPreloadThenGetProperties($tags, $requestedProperties, $expectedProperties): void {
- $node1 = $this->getMockBuilder(File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ public function testPreloadThenGetProperties(array $tags, array $requestedProperties, array $expectedProperties): void {
+ $node1 = $this->createMock(File::class);
$node1->expects($this->any())
->method('getId')
->willReturn(111);
- $node2 = $this->getMockBuilder(File::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node2 = $this->createMock(File::class);
$node2->expects($this->any())
->method('getId')
->willReturn(222);
@@ -157,9 +116,7 @@ class TagsPluginTest extends \Test\TestCase {
$expectedCallCount = 1;
}
- $node = $this->getMockBuilder(Directory::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(Directory::class);
$node->expects($this->any())
->method('getId')
->willReturn(123);
@@ -214,7 +171,7 @@ class TagsPluginTest extends \Test\TestCase {
$this->assertEquals($expectedProperties, $result);
}
- public function tagsGetPropertiesDataProvider() {
+ public static function tagsGetPropertiesDataProvider(): array {
return [
// request both, receive both
[
@@ -270,9 +227,7 @@ class TagsPluginTest extends \Test\TestCase {
}
public function testGetPropertiesSkipChunks(): void {
- $sabreNode = $this->getMockBuilder(UploadFile::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $sabreNode = $this->createMock(UploadFile::class);
$propFind = new \Sabre\DAV\PropFind(
'/dummyPath',
@@ -292,9 +247,7 @@ class TagsPluginTest extends \Test\TestCase {
public function testUpdateTags(): void {
// this test will replace the existing tags "tagremove" with "tag1" and "tag2"
// and keep "tagkeep"
- $node = $this->getMockBuilder(Node::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(Node::class);
$node->expects($this->any())
->method('getId')
->willReturn(123);
@@ -310,12 +263,16 @@ class TagsPluginTest extends \Test\TestCase {
->willReturn([123 => ['tagkeep', 'tagremove', self::TAG_FAVORITE]]);
// then tag as tag1 and tag2
- $this->tagger->expects($this->exactly(2))
+ $calls = [
+ [123, 'tag1'],
+ [123, 'tag2'],
+ ];
+ $this->tagger->expects($this->exactly(count($calls)))
->method('tagAs')
- ->withConsecutive(
- [123, 'tag1'],
- [123, 'tag2'],
- );
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
// it will untag tag3
$this->tagger->expects($this->once())
@@ -339,13 +296,11 @@ class TagsPluginTest extends \Test\TestCase {
$result = $propPatch->getResult();
$this->assertEquals(200, $result[self::TAGS_PROPERTYNAME]);
- $this->assertFalse(isset($result[self::FAVORITE_PROPERTYNAME]));
+ $this->assertArrayNotHasKey(self::FAVORITE_PROPERTYNAME, $result);
}
public function testUpdateTagsFromScratch(): void {
- $node = $this->getMockBuilder(Node::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(Node::class);
$node->expects($this->any())
->method('getId')
->willReturn(123);
@@ -361,12 +316,16 @@ class TagsPluginTest extends \Test\TestCase {
->willReturn([]);
// then tag as tag1 and tag2
- $this->tagger->expects($this->exactly(2))
+ $calls = [
+ [123, 'tag1'],
+ [123, 'tag2'],
+ ];
+ $this->tagger->expects($this->exactly(count($calls)))
->method('tagAs')
- ->withConsecutive(
- [123, 'tag1'],
- [123, 'tag2'],
- );
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
// properties to set
$propPatch = new \Sabre\DAV\PropPatch([
@@ -385,15 +344,13 @@ class TagsPluginTest extends \Test\TestCase {
$result = $propPatch->getResult();
$this->assertEquals(200, $result[self::TAGS_PROPERTYNAME]);
- $this->assertFalse(false, isset($result[self::FAVORITE_PROPERTYNAME]));
+ $this->assertArrayNotHasKey(self::FAVORITE_PROPERTYNAME, $result);
}
public function testUpdateFav(): void {
// this test will replace the existing tags "tagremove" with "tag1" and "tag2"
// and keep "tagkeep"
- $node = $this->getMockBuilder(Node::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(Node::class);
$node->expects($this->any())
->method('getId')
->willReturn(123);
@@ -424,8 +381,8 @@ class TagsPluginTest extends \Test\TestCase {
$this->assertEmpty($propPatch->getRemainingMutations());
$result = $propPatch->getResult();
- $this->assertFalse(false, isset($result[self::TAGS_PROPERTYNAME]));
- $this->assertEquals(200, isset($result[self::FAVORITE_PROPERTYNAME]));
+ $this->assertArrayNotHasKey(self::TAGS_PROPERTYNAME, $result);
+ $this->assertEquals(200, $result[self::FAVORITE_PROPERTYNAME]);
// unfavorite now
// set favorite tag
@@ -449,7 +406,7 @@ class TagsPluginTest extends \Test\TestCase {
$this->assertEmpty($propPatch->getRemainingMutations());
$result = $propPatch->getResult();
- $this->assertFalse(false, isset($result[self::TAGS_PROPERTYNAME]));
- $this->assertEquals(200, isset($result[self::FAVORITE_PROPERTYNAME]));
+ $this->assertArrayNotHasKey(self::TAGS_PROPERTYNAME, $result);
+ $this->assertEquals(200, $result[self::FAVORITE_PROPERTYNAME]);
}
}
diff --git a/apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php b/apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php
index c7c2bf0e431..9aa0ef3a2a7 100644
--- a/apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php
+++ b/apps/dav/tests/unit/Controller/BirthdayCalendarControllerTest.php
@@ -1,43 +1,33 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\DAV\Controller;
+namespace OCA\DAV\Tests\unit\DAV\Controller;
use OCA\DAV\BackgroundJob\GenerateBirthdayCalendarBackgroundJob;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\Controller\BirthdayCalendarController;
+use OCP\AppFramework\Http\JSONResponse;
use OCP\BackgroundJob\IJobList;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class BirthdayCalendarControllerTest extends TestCase {
-
- /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
- private $config;
-
- /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
- private $request;
-
- /** @var IDBConnection|\PHPUnit\Framework\MockObject\MockObject */
- private $db;
-
- /** @var IJobList|\PHPUnit\Framework\MockObject\MockObject */
- private $jobList;
-
- /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
- private $userManager;
-
- /** @var CalDavBackend|\PHPUnit\Framework\MockObject\MockObject */
- private $caldav;
-
- /** @var BirthdayCalendarController|\PHPUnit\Framework\MockObject\MockObject */
- private $controller;
+ private IConfig&MockObject $config;
+ private IRequest&MockObject $request;
+ private IDBConnection&MockObject $db;
+ private IJobList&MockObject $jobList;
+ private IUserManager&MockObject $userManager;
+ private CalDavBackend&MockObject $caldav;
+ private BirthdayCalendarController $controller;
protected function setUp(): void {
parent::setUp();
@@ -74,16 +64,20 @@ class BirthdayCalendarControllerTest extends TestCase {
$closure($user3);
});
+ $calls = [
+ [GenerateBirthdayCalendarBackgroundJob::class, ['userId' => 'uid1']],
+ [GenerateBirthdayCalendarBackgroundJob::class, ['userId' => 'uid2']],
+ [GenerateBirthdayCalendarBackgroundJob::class, ['userId' => 'uid3']],
+ ];
$this->jobList->expects($this->exactly(3))
->method('add')
- ->withConsecutive(
- [GenerateBirthdayCalendarBackgroundJob::class, ['userId' => 'uid1']],
- [GenerateBirthdayCalendarBackgroundJob::class, ['userId' => 'uid2']],
- [GenerateBirthdayCalendarBackgroundJob::class, ['userId' => 'uid3']],
- );
+ ->willReturnCallback(function () use (&$calls): void {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
$response = $this->controller->enable();
- $this->assertInstanceOf('OCP\AppFramework\Http\JSONResponse', $response);
+ $this->assertInstanceOf(JSONResponse::class, $response);
}
public function testDisable(): void {
@@ -97,6 +91,6 @@ class BirthdayCalendarControllerTest extends TestCase {
->method('deleteAllBirthdayCalendars');
$response = $this->controller->disable();
- $this->assertInstanceOf('OCP\AppFramework\Http\JSONResponse', $response);
+ $this->assertInstanceOf(JSONResponse::class, $response);
}
}
diff --git a/apps/dav/tests/unit/Controller/DirectControllerTest.php b/apps/dav/tests/unit/Controller/DirectControllerTest.php
index faaf67d266b..837adde1da7 100644
--- a/apps/dav/tests/unit/Controller/DirectControllerTest.php
+++ b/apps/dav/tests/unit/Controller/DirectControllerTest.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\DAV\Controller;
+namespace OCA\DAV\Tests\unit\DAV\Controller;
use OCA\DAV\Controller\DirectController;
use OCA\DAV\Db\Direct;
@@ -20,29 +20,18 @@ use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\IRequest;
-use OCP\IUrlGenerator;
+use OCP\IURLGenerator;
use OCP\Security\ISecureRandom;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class DirectControllerTest extends TestCase {
-
- /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject */
- private $rootFolder;
-
- /** @var DirectMapper|\PHPUnit\Framework\MockObject\MockObject */
- private $directMapper;
-
- /** @var ISecureRandom|\PHPUnit\Framework\MockObject\MockObject */
- private $random;
-
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
- private $timeFactory;
-
- /** @var IUrlGenerator|\PHPUnit\Framework\MockObject\MockObject */
- private $urlGenerator;
-
- /** @var IEventDispatcher|\PHPUnit\Framework\MockObject\MockObject */
- private $eventDispatcher;
+ private IRootFolder&MockObject $rootFolder;
+ private DirectMapper&MockObject $directMapper;
+ private ISecureRandom&MockObject $random;
+ private ITimeFactory&MockObject $timeFactory;
+ private IURLGenerator&MockObject $urlGenerator;
+ private IEventDispatcher&MockObject $eventDispatcher;
private DirectController $controller;
@@ -53,7 +42,7 @@ class DirectControllerTest extends TestCase {
$this->directMapper = $this->createMock(DirectMapper::class);
$this->random = $this->createMock(ISecureRandom::class);
$this->timeFactory = $this->createMock(ITimeFactory::class);
- $this->urlGenerator = $this->createMock(IUrlGenerator::class);
+ $this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->controller = new DirectController(
diff --git a/apps/dav/tests/unit/Controller/InvitationResponseControllerTest.php b/apps/dav/tests/unit/Controller/InvitationResponseControllerTest.php
index 640c66b75e5..895a84b8404 100644
--- a/apps/dav/tests/unit/Controller/InvitationResponseControllerTest.php
+++ b/apps/dav/tests/unit/Controller/InvitationResponseControllerTest.php
@@ -7,7 +7,7 @@ declare(strict_types=1);
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\DAV\Controller;
+namespace OCA\DAV\Tests\unit\DAV\Controller;
use OCA\DAV\CalDAV\InvitationResponse\InvitationResponseServer;
use OCA\DAV\Controller\InvitationResponseController;
@@ -18,24 +18,16 @@ use OCP\DB\QueryBuilder\IExpressionBuilder;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCP\IRequest;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\VObject\ITip\Message;
use Test\TestCase;
class InvitationResponseControllerTest extends TestCase {
- /** @var InvitationResponseController */
- private $controller;
-
- /** @var IDBConnection|\PHPUnit\Framework\MockObject\MockObject */
- private $dbConnection;
-
- /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
- private $request;
-
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
- private $timeFactory;
-
- /** @var InvitationResponseServer|\PHPUnit\Framework\MockObject\MockObject */
- private $responseServer;
+ private IDBConnection&MockObject $dbConnection;
+ private IRequest&MockObject $request;
+ private ITimeFactory&MockObject $timeFactory;
+ private InvitationResponseServer&MockObject $responseServer;
+ private InvitationResponseController $controller;
protected function setUp(): void {
parent::setUp();
@@ -43,9 +35,7 @@ class InvitationResponseControllerTest extends TestCase {
$this->dbConnection = $this->createMock(IDBConnection::class);
$this->request = $this->createMock(IRequest::class);
$this->timeFactory = $this->createMock(ITimeFactory::class);
- $this->responseServer = $this->getMockBuilder(InvitationResponseServer::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->responseServer = $this->createMock(InvitationResponseServer::class);
$this->controller = new InvitationResponseController(
'appName',
@@ -56,7 +46,7 @@ class InvitationResponseControllerTest extends TestCase {
);
}
- public function attendeeProvider(): array {
+ public static function attendeeProvider(): array {
return [
'local attendee' => [false],
'external attendee' => [true]
@@ -424,7 +414,7 @@ EOF;
$this->assertTrue($called);
}
- private function buildQueryExpects($token, $return, $time): void {
+ private function buildQueryExpects(string $token, ?array $return, int $time): void {
$queryBuilder = $this->createMock(IQueryBuilder::class);
$stmt = $this->createMock(IResult::class);
$expr = $this->createMock(IExpressionBuilder::class);
diff --git a/apps/dav/tests/unit/Controller/UpcomingEventsControllerTest.php b/apps/dav/tests/unit/Controller/UpcomingEventsControllerTest.php
index bab0ef77bd0..527943e5221 100644
--- a/apps/dav/tests/unit/Controller/UpcomingEventsControllerTest.php
+++ b/apps/dav/tests/unit/Controller/UpcomingEventsControllerTest.php
@@ -7,7 +7,7 @@ declare(strict_types=1);
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\DAV\Service;
+namespace OCA\DAV\Tests\unit\DAV\Service;
use OCA\DAV\CalDAV\UpcomingEvent;
use OCA\DAV\CalDAV\UpcomingEventsService;
@@ -17,9 +17,8 @@ use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
class UpcomingEventsControllerTest extends TestCase {
-
- private IRequest|MockObject $request;
- private UpcomingEventsService|MockObject $service;
+ private IRequest&MockObject $request;
+ private UpcomingEventsService&MockObject $service;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/DAV/AnonymousOptionsTest.php b/apps/dav/tests/unit/DAV/AnonymousOptionsTest.php
index ea5450391e8..c99ebf327c8 100644
--- a/apps/dav/tests/unit/DAV/AnonymousOptionsTest.php
+++ b/apps/dav/tests/unit/DAV/AnonymousOptionsTest.php
@@ -1,9 +1,11 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\tests\unit\DAV;
+namespace OCA\DAV\Tests\unit\DAV;
use OCA\DAV\Connector\Sabre\AnonymousOptionsPlugin;
use Sabre\DAV\Auth\Backend\BasicCallBack;
@@ -14,7 +16,7 @@ use Sabre\HTTP\Sapi;
use Test\TestCase;
class AnonymousOptionsTest extends TestCase {
- private function sendRequest($method, $path, $userAgent = '') {
+ private function sendRequest(string $method, string $path, string $userAgent = '') {
$server = new Server();
$server->addPlugin(new AnonymousOptionsPlugin());
$server->addPlugin(new Plugin(new BasicCallBack(function () {
diff --git a/apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php b/apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php
index 088330cecff..23ee2b66f77 100644
--- a/apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php
+++ b/apps/dav/tests/unit/DAV/BrowserErrorPagePluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,6 +9,7 @@
namespace OCA\DAV\Tests\unit\DAV;
use OCA\DAV\Files\BrowserErrorPagePlugin;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Exception\NotFound;
use Sabre\HTTP\Response;
@@ -15,18 +17,16 @@ class BrowserErrorPagePluginTest extends \Test\TestCase {
/**
* @dataProvider providesExceptions
- * @param $expectedCode
- * @param $exception
*/
- public function test($expectedCode, $exception): void {
- /** @var BrowserErrorPagePlugin | \PHPUnit\Framework\MockObject\MockObject $plugin */
- $plugin = $this->getMockBuilder(BrowserErrorPagePlugin::class)->setMethods(['sendResponse', 'generateBody'])->getMock();
+ public function test(int $expectedCode, \Throwable $exception): void {
+ /** @var BrowserErrorPagePlugin&MockObject $plugin */
+ $plugin = $this->getMockBuilder(BrowserErrorPagePlugin::class)->onlyMethods(['sendResponse', 'generateBody'])->getMock();
$plugin->expects($this->once())->method('generateBody')->willReturn(':boom:');
$plugin->expects($this->once())->method('sendResponse');
- /** @var \Sabre\DAV\Server | \PHPUnit\Framework\MockObject\MockObject $server */
- $server = $this->getMockBuilder('Sabre\DAV\Server')->disableOriginalConstructor()->getMock();
+ /** @var \Sabre\DAV\Server&MockObject $server */
+ $server = $this->createMock('Sabre\DAV\Server');
$server->expects($this->once())->method('on');
- $httpResponse = $this->getMockBuilder(Response::class)->disableOriginalConstructor()->getMock();
+ $httpResponse = $this->createMock(Response::class);
$httpResponse->expects($this->once())->method('addHeaders');
$httpResponse->expects($this->once())->method('setStatus')->with($expectedCode);
$httpResponse->expects($this->once())->method('setBody')->with(':boom:');
@@ -35,7 +35,7 @@ class BrowserErrorPagePluginTest extends \Test\TestCase {
$plugin->logException($exception);
}
- public function providesExceptions() {
+ public static function providesExceptions(): array {
return [
[ 404, new NotFound()],
[ 500, new \RuntimeException()],
diff --git a/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php b/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php
index 5590e8c1ff0..7c77b3fcb28 100644
--- a/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php
+++ b/apps/dav/tests/unit/DAV/CustomPropertiesBackendTest.php
@@ -1,10 +1,11 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\DAV;
+namespace OCA\DAV\Tests\unit\DAV;
use OCA\DAV\CalDAV\Calendar;
use OCA\DAV\CalDAV\DefaultCalendarValidator;
@@ -12,6 +13,7 @@ use OCA\DAV\DAV\CustomPropertiesBackend;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCP\IUser;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\PropFind;
use Sabre\DAV\PropPatch;
@@ -28,23 +30,12 @@ use Test\TestCase;
class CustomPropertiesBackendTest extends TestCase {
private const BASE_URI = '/remote.php/dav/';
- /** @var Server | \PHPUnit\Framework\MockObject\MockObject */
- private $server;
-
- /** @var Tree | \PHPUnit\Framework\MockObject\MockObject */
- private $tree;
-
- /** @var IDBConnection */
- private $dbConnection;
-
- /** @var IUser | \PHPUnit\Framework\MockObject\MockObject */
- private $user;
-
- /** @var CustomPropertiesBackend | \PHPUnit\Framework\MockObject\MockObject */
- private $backend;
-
- /** @property DefaultCalendarValidator | \PHPUnit\Framework\MockObject\MockObject */
- private $defaultCalendarValidator;
+ private Server&MockObject $server;
+ private Tree&MockObject $tree;
+ private IDBConnection $dbConnection;
+ private IUser&MockObject $user;
+ private DefaultCalendarValidator&MockObject $defaultCalendarValidator;
+ private CustomPropertiesBackend $backend;
protected function setUp(): void {
parent::setUp();
@@ -85,13 +76,13 @@ class CustomPropertiesBackendTest extends TestCase {
}
}
- protected function insertProps(string $user, string $path, array $props) {
+ protected function insertProps(string $user, string $path, array $props): void {
foreach ($props as $name => $value) {
$this->insertProp($user, $path, $name, $value);
}
}
- protected function insertProp(string $user, string $path, string $name, mixed $value) {
+ protected function insertProp(string $user, string $path, string $name, mixed $value): void {
$type = CustomPropertiesBackend::PROPERTY_TYPE_STRING;
if ($value instanceof Href) {
$value = $value->getHref();
@@ -110,7 +101,7 @@ class CustomPropertiesBackendTest extends TestCase {
$query->execute();
}
- protected function getProps(string $user, string $path) {
+ protected function getProps(string $user, string $path): array {
$query = $this->dbConnection->getQueryBuilder();
$query->select('propertyname', 'propertyvalue', 'valuetype')
->from('properties')
@@ -245,7 +236,7 @@ class CustomPropertiesBackendTest extends TestCase {
$this->assertEquals($props, $setProps);
}
- public function propFindPrincipalScheduleDefaultCalendarProviderUrlProvider(): array {
+ public static function propFindPrincipalScheduleDefaultCalendarProviderUrlProvider(): array {
// [ user, nodes, existingProps, requestedProps, returnedProps ]
return [
[ // Exists
@@ -373,7 +364,7 @@ class CustomPropertiesBackendTest extends TestCase {
$this->assertEquals($result, $storedProps);
}
- public function propPatchProvider() {
+ public static function propPatchProvider(): array {
$longPath = str_repeat('long_path', 100);
return [
['foo_bar_path_1337', [], ['{DAV:}displayname' => 'anything'], ['{DAV:}displayname' => 'anything']],
@@ -436,7 +427,7 @@ class CustomPropertiesBackendTest extends TestCase {
$this->assertEquals([], $this->getProps('dummy_user_42', $path));
}
- public function deleteProvider() {
+ public static function deleteProvider(): array {
return [
['foo_bar_path_1337'],
[str_repeat('long_path', 100)]
@@ -453,7 +444,7 @@ class CustomPropertiesBackendTest extends TestCase {
$this->assertEquals(['foo' => 'bar'], $this->getProps('dummy_user_42', $target));
}
- public function moveProvider() {
+ public static function moveProvider(): array {
return [
['foo_bar_path_1337', 'foo_bar_path_7333'],
[str_repeat('long_path1', 100), str_repeat('long_path2', 100)]
@@ -475,5 +466,4 @@ class CustomPropertiesBackendTest extends TestCase {
$this->assertInstanceOf(\Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp::class, $decodeValue);
$this->assertEquals('opaque', $decodeValue->getValue());
}
-
}
diff --git a/apps/dav/tests/unit/DAV/GroupPrincipalTest.php b/apps/dav/tests/unit/DAV/GroupPrincipalTest.php
index bfc4c5b2493..2ede450c36b 100644
--- a/apps/dav/tests/unit/DAV/GroupPrincipalTest.php
+++ b/apps/dav/tests/unit/DAV/GroupPrincipalTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -18,20 +20,11 @@ use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\PropPatch;
class GroupPrincipalTest extends \Test\TestCase {
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var IGroupManager | MockObject */
- private $groupManager;
-
- /** @var IUserSession | MockObject */
- private $userSession;
-
- /** @var IManager | MockObject */
- private $shareManager;
-
- /** @var GroupPrincipalBackend */
- private $connector;
+ private IConfig&MockObject $config;
+ private IGroupManager&MockObject $groupManager;
+ private IUserSession&MockObject $userSession;
+ private IManager&MockObject $shareManager;
+ private GroupPrincipalBackend $connector;
protected function setUp(): void {
$this->groupManager = $this->createMock(IGroupManager::class);
@@ -201,11 +194,6 @@ class GroupPrincipalTest extends \Test\TestCase {
/**
* @dataProvider searchPrincipalsDataProvider
- * @param bool $sharingEnabled
- * @param bool $groupSharingEnabled
- * @param bool $groupsOnly
- * @param string $test
- * @param array $result
*/
public function testSearchPrincipals(bool $sharingEnabled, bool $groupSharingEnabled, bool $groupsOnly, string $test, array $result): void {
$this->shareManager->expects($this->once())
@@ -264,7 +252,7 @@ class GroupPrincipalTest extends \Test\TestCase {
['{DAV:}displayname' => 'Foo'], $test));
}
- public function searchPrincipalsDataProvider() {
+ public static function searchPrincipalsDataProvider(): array {
return [
[true, true, false, 'allof', ['principals/groups/group1', 'principals/groups/group2', 'principals/groups/group3', 'principals/groups/group4', 'principals/groups/group5']],
[true, true, false, 'anyof', ['principals/groups/group1', 'principals/groups/group2', 'principals/groups/group3', 'principals/groups/group4', 'principals/groups/group5']],
@@ -279,11 +267,6 @@ class GroupPrincipalTest extends \Test\TestCase {
/**
* @dataProvider findByUriDataProvider
- * @param bool $sharingEnabled
- * @param bool $groupSharingEnabled
- * @param bool $groupsOnly
- * @param string $findUri
- * @param string|null $result
*/
public function testFindByUri(bool $sharingEnabled, bool $groupSharingEnabled, bool $groupsOnly, string $findUri, ?string $result): void {
$this->shareManager->expects($this->once())
@@ -320,7 +303,7 @@ class GroupPrincipalTest extends \Test\TestCase {
$this->assertEquals($result, $this->connector->findByUri($findUri, 'principals/groups'));
}
- public function findByUriDataProvider() {
+ public static function findByUriDataProvider(): array {
return [
[false, false, false, 'principal:principals/groups/group1', null],
[false, false, false, 'principal:principals/groups/group3', null],
@@ -337,10 +320,7 @@ class GroupPrincipalTest extends \Test\TestCase {
];
}
- /**
- * @return Group|MockObject
- */
- private function mockGroup($gid) {
+ private function mockGroup(string $gid): Group&MockObject {
$fooGroup = $this->createMock(Group::class);
$fooGroup
->expects($this->exactly(1))
diff --git a/apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php b/apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php
index a0876d8e483..40d2fb62431 100644
--- a/apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php
+++ b/apps/dav/tests/unit/DAV/Listener/UserEventsListenerTest.php
@@ -14,11 +14,13 @@ 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;
use OCP\IUserManager;
use PHPUnit\Framework\MockObject\MockObject;
+use Psr\Log\LoggerInterface;
use Test\TestCase;
class UserEventsListenerTest extends TestCase {
@@ -27,33 +29,38 @@ 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;
private UserEventsListener $userEventsListener;
protected function setUp(): void {
parent::setUp();
+
$this->userManager = $this->createMock(IUserManager::class);
$this->syncService = $this->createMock(SyncService::class);
$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);
+
$this->userEventsListener = new UserEventsListener(
$this->userManager,
$this->syncService,
$this->calDavBackend,
$this->cardDavBackend,
$this->defaults,
- $this->defaultContactService,
+ $this->exampleContactService,
+ $this->exampleEventService,
+ $this->logger,
);
}
public function test(): void {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())->method('getUID')->willReturn('newUser');
$this->defaults->expects($this->once())->method('getColorPrimary')->willReturn('#745bca');
@@ -65,7 +72,13 @@ class UserEventsListenerTest extends TestCase {
'{DAV:}displayname' => 'Personal',
'{http://apple.com/ns/ical/}calendar-color' => '#745bca',
'components' => 'VEVENT'
- ]);
+ ])
+ ->willReturn(1000);
+ $this->calDavBackend->expects(self::never())
+ ->method('getCalendarsForUser');
+ $this->exampleEventService->expects(self::once())
+ ->method('createExampleEvent')
+ ->with(1000);
$this->cardDavBackend->expects($this->once())->method('getAddressBooksForUserCount')->willReturn(0);
$this->cardDavBackend->expects($this->once())->method('createAddressBook')->with(
@@ -76,13 +89,15 @@ class UserEventsListenerTest extends TestCase {
}
public function testWithExisting(): void {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())->method('getUID')->willReturn('newUser');
$this->calDavBackend->expects($this->once())->method('getCalendarsForUserCount')->willReturn(1);
$this->calDavBackend->expects($this->never())->method('createCalendar');
+ $this->calDavBackend->expects(self::never())
+ ->method('createCalendar');
+ $this->exampleEventService->expects(self::never())
+ ->method('createExampleEvent');
$this->cardDavBackend->expects($this->once())->method('getAddressBooksForUserCount')->willReturn(1);
$this->cardDavBackend->expects($this->never())->method('createAddressBook');
@@ -91,9 +106,7 @@ class UserEventsListenerTest extends TestCase {
}
public function testWithBirthdayCalendar(): void {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())->method('getUID')->willReturn('newUser');
$this->defaults->expects($this->once())->method('getColorPrimary')->willReturn('#745bca');
@@ -116,9 +129,7 @@ class UserEventsListenerTest extends TestCase {
}
public function testDeleteCalendar(): void {
- $user = $this->getMockBuilder(IUser::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->once())->method('getUID')->willReturn('newUser');
$this->syncService->expects($this->once())
diff --git a/apps/dav/tests/unit/DAV/Sharing/BackendTest.php b/apps/dav/tests/unit/DAV/Sharing/BackendTest.php
index 344d57d1808..556a623a73f 100644
--- a/apps/dav/tests/unit/DAV/Sharing/BackendTest.php
+++ b/apps/dav/tests/unit/DAV/Sharing/BackendTest.php
@@ -24,14 +24,14 @@ use Test\TestCase;
class BackendTest extends TestCase {
- private IDBConnection|MockObject $db;
- private IUserManager|MockObject $userManager;
- private IGroupManager|MockObject $groupManager;
- private MockObject|Principal $principalBackend;
- private MockObject|ICache $shareCache;
- private LoggerInterface|MockObject $logger;
- private MockObject|ICacheFactory $cacheFactory;
- private Service|MockObject $calendarService;
+ private IDBConnection&MockObject $db;
+ private IUserManager&MockObject $userManager;
+ private IGroupManager&MockObject $groupManager;
+ private Principal&MockObject $principalBackend;
+ private ICache&MockObject $shareCache;
+ private LoggerInterface&MockObject $logger;
+ private ICacheFactory&MockObject $cacheFactory;
+ private Service&MockObject $calendarService;
private CalendarSharingBackend $backend;
protected function setUp(): void {
@@ -214,10 +214,7 @@ class BackendTest extends TestCase {
'getResourceId' => 42,
]);
$remove = [
- [
- 'href' => 'principal:principals/users/bob',
- 'readOnly' => true,
- ]
+ 'principal:principals/users/bob',
];
$principal = 'principals/users/bob';
@@ -229,9 +226,6 @@ class BackendTest extends TestCase {
$this->calendarService->expects(self::once())
->method('deleteShare')
->with($shareable->getResourceId(), $principal);
- $this->calendarService->expects(self::once())
- ->method('hasGroupShare')
- ->willReturn(false);
$this->calendarService->expects(self::never())
->method('unshare');
@@ -244,10 +238,7 @@ class BackendTest extends TestCase {
'getResourceId' => 42,
]);
$remove = [
- [
- 'href' => 'principal:principals/users/bob',
- 'readOnly' => true,
- ]
+ 'principal:principals/users/bob',
];
$oldShares = [
[
@@ -269,13 +260,8 @@ class BackendTest extends TestCase {
$this->calendarService->expects(self::once())
->method('deleteShare')
->with($shareable->getResourceId(), 'principals/users/bob');
- $this->calendarService->expects(self::once())
- ->method('hasGroupShare')
- ->with($oldShares)
- ->willReturn(true);
- $this->calendarService->expects(self::once())
- ->method('unshare')
- ->with($shareable->getResourceId(), 'principals/users/bob');
+ $this->calendarService->expects(self::never())
+ ->method('unshare');
$this->backend->updateShares($shareable, [], $remove, $oldShares);
}
diff --git a/apps/dav/tests/unit/DAV/Sharing/PluginTest.php b/apps/dav/tests/unit/DAV/Sharing/PluginTest.php
index 9c6950f19e8..7a88f7cc5dd 100644
--- a/apps/dav/tests/unit/DAV/Sharing/PluginTest.php
+++ b/apps/dav/tests/unit/DAV/Sharing/PluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -12,6 +13,7 @@ use OCA\DAV\DAV\Sharing\IShareable;
use OCA\DAV\DAV\Sharing\Plugin;
use OCP\IConfig;
use OCP\IRequest;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Server;
use Sabre\DAV\SimpleCollection;
use Sabre\HTTP\Request;
@@ -19,32 +21,24 @@ use Sabre\HTTP\Response;
use Test\TestCase;
class PluginTest extends TestCase {
-
- /** @var Plugin */
- private $plugin;
- /** @var Server */
- private $server;
- /** @var IShareable | \PHPUnit\Framework\MockObject\MockObject */
- private $book;
+ private Plugin $plugin;
+ private Server $server;
+ private IShareable&MockObject $book;
protected function setUp(): void {
parent::setUp();
- /** @var Auth | \PHPUnit\Framework\MockObject\MockObject $authBackend */
- $authBackend = $this->getMockBuilder(Auth::class)->disableOriginalConstructor()->getMock();
+ $authBackend = $this->createMock(Auth::class);
$authBackend->method('isDavAuthenticated')->willReturn(true);
- /** @var IRequest $request */
- $request = $this->getMockBuilder(IRequest::class)->disableOriginalConstructor()->getMock();
+ $request = $this->createMock(IRequest::class);
$config = $this->createMock(IConfig::class);
$this->plugin = new Plugin($authBackend, $request, $config);
$root = new SimpleCollection('root');
$this->server = new \Sabre\DAV\Server($root);
/** @var SimpleCollection $node */
- $this->book = $this->getMockBuilder(IShareable::class)->
- disableOriginalConstructor()->
- getMock();
+ $this->book = $this->createMock(IShareable::class);
$this->book->method('getName')->willReturn('addressbook1.vcf');
$root->addChild($this->book);
$this->plugin->initialize($this->server);
diff --git a/apps/dav/tests/unit/DAV/Sharing/SharingServiceTest.php b/apps/dav/tests/unit/DAV/Sharing/SharingServiceTest.php
deleted file mode 100644
index fad077eeda3..00000000000
--- a/apps/dav/tests/unit/DAV/Sharing/SharingServiceTest.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-declare(strict_types=1);
-/**
- * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-namespace OCA\DAV\Tests\unit\DAV\Sharing;
-
-use OCA\DAV\CalDAV\Sharing\Service;
-use OCA\DAV\DAV\Sharing\SharingMapper;
-use OCA\DAV\DAV\Sharing\SharingService;
-use Test\TestCase;
-
-class SharingServiceTest extends TestCase {
-
- private SharingService $service;
-
- protected function setUp(): void {
- parent::setUp();
- $this->service = new Service($this->createMock(SharingMapper::class));
- }
-
- public function testHasGroupShare(): void {
- $oldShares = [
- [
- 'href' => 'principal:principals/groups/bob',
- 'commonName' => 'bob',
- 'status' => 1,
- 'readOnly' => true,
- '{http://owncloud.org/ns}principal' => 'principals/groups/bob',
- '{http://owncloud.org/ns}group-share' => true,
- ],
- [
- 'href' => 'principal:principals/users/bob',
- 'commonName' => 'bob',
- 'status' => 1,
- 'readOnly' => true,
- '{http://owncloud.org/ns}principal' => 'principals/users/bob',
- '{http://owncloud.org/ns}group-share' => false,
- ]
- ];
-
- $this->assertTrue($this->service->hasGroupShare($oldShares));
-
- $oldShares = [
- [
- 'href' => 'principal:principals/users/bob',
- 'commonName' => 'bob',
- 'status' => 1,
- 'readOnly' => true,
- '{http://owncloud.org/ns}principal' => 'principals/users/bob',
- '{http://owncloud.org/ns}group-share' => false,
- ]
- ];
- $this->assertFalse($this->service->hasGroupShare($oldShares));
- }
-}
diff --git a/apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php b/apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php
index 32916804080..127de1ede0a 100644
--- a/apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php
+++ b/apps/dav/tests/unit/DAV/SystemPrincipalBackendTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -8,22 +9,21 @@
namespace OCA\DAV\Tests\unit\DAV;
use OCA\DAV\DAV\SystemPrincipalBackend;
+use Sabre\DAV\Exception;
use Test\TestCase;
class SystemPrincipalBackendTest extends TestCase {
/**
* @dataProvider providesPrefix
- * @param $expected
- * @param $prefix
*/
- public function testGetPrincipalsByPrefix($expected, $prefix): void {
+ public function testGetPrincipalsByPrefix(array $expected, string $prefix): void {
$backend = new SystemPrincipalBackend();
$result = $backend->getPrincipalsByPrefix($prefix);
$this->assertEquals($expected, $result);
}
- public function providesPrefix() {
+ public static function providesPrefix(): array {
return [
[[], ''],
[[[
@@ -40,16 +40,14 @@ class SystemPrincipalBackendTest extends TestCase {
/**
* @dataProvider providesPath
- * @param $expected
- * @param $path
*/
- public function testGetPrincipalByPath($expected, $path): void {
+ public function testGetPrincipalByPath(?array $expected, string $path): void {
$backend = new SystemPrincipalBackend();
$result = $backend->getPrincipalByPath($path);
$this->assertEquals($expected, $result);
}
- public function providesPath() {
+ public static function providesPath(): array {
return [
[null, ''],
[null, 'principals'],
@@ -63,28 +61,22 @@ class SystemPrincipalBackendTest extends TestCase {
/**
* @dataProvider providesPrincipalForGetGroupMemberSet
- *
- * @param string $principal
- * @throws \Sabre\DAV\Exception
*/
- public function testGetGroupMemberSetExceptional($principal): void {
- $this->expectException(\Sabre\DAV\Exception::class);
+ public function testGetGroupMemberSetExceptional(?string $principal): void {
+ $this->expectException(Exception::class);
$this->expectExceptionMessage('Principal not found');
$backend = new SystemPrincipalBackend();
$backend->getGroupMemberSet($principal);
}
- public function providesPrincipalForGetGroupMemberSet() {
+ public static function providesPrincipalForGetGroupMemberSet(): array {
return [
[null],
['principals/system'],
];
}
- /**
- * @throws \Sabre\DAV\Exception
- */
public function testGetGroupMemberSet(): void {
$backend = new SystemPrincipalBackend();
$result = $backend->getGroupMemberSet('principals/system/system');
@@ -93,27 +85,21 @@ class SystemPrincipalBackendTest extends TestCase {
/**
* @dataProvider providesPrincipalForGetGroupMembership
- *
- * @param string $principal
- * @throws \Sabre\DAV\Exception
*/
- public function testGetGroupMembershipExceptional($principal): void {
- $this->expectException(\Sabre\DAV\Exception::class);
+ public function testGetGroupMembershipExceptional(string $principal): void {
+ $this->expectException(Exception::class);
$this->expectExceptionMessage('Principal not found');
$backend = new SystemPrincipalBackend();
$backend->getGroupMembership($principal);
}
- public function providesPrincipalForGetGroupMembership() {
+ public static function providesPrincipalForGetGroupMembership(): array {
return [
['principals/system/a'],
];
}
- /**
- * @throws \Sabre\DAV\Exception
- */
public function testGetGroupMembership(): void {
$backend = new SystemPrincipalBackend();
$result = $backend->getGroupMembership('principals/system/system');
diff --git a/apps/dav/tests/unit/DAV/ViewOnlyPluginTest.php b/apps/dav/tests/unit/DAV/ViewOnlyPluginTest.php
index 7a4828dd2de..ecb71bb7ae7 100644
--- a/apps/dav/tests/unit/DAV/ViewOnlyPluginTest.php
+++ b/apps/dav/tests/unit/DAV/ViewOnlyPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2019 ownCloud GmbH
@@ -20,30 +21,29 @@ use OCP\Files\Storage\IStorage;
use OCP\IUser;
use OCP\Share\IAttributes;
use OCP\Share\IShare;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Server;
use Sabre\DAV\Tree;
use Sabre\HTTP\RequestInterface;
use Test\TestCase;
class ViewOnlyPluginTest extends TestCase {
-
+ private Tree&MockObject $tree;
+ private RequestInterface&MockObject $request;
+ private Folder&MockObject $userFolder;
private ViewOnlyPlugin $plugin;
- /** @var Tree | \PHPUnit\Framework\MockObject\MockObject */
- private $tree;
- /** @var RequestInterface | \PHPUnit\Framework\MockObject\MockObject */
- private $request;
- /** @var Folder | \PHPUnit\Framework\MockObject\MockObject */
- private $userFolder;
public function setUp(): void {
+ parent::setUp();
+
$this->userFolder = $this->createMock(Folder::class);
- $this->plugin = new ViewOnlyPlugin(
- $this->userFolder,
- );
$this->request = $this->createMock(RequestInterface::class);
$this->tree = $this->createMock(Tree::class);
-
$server = $this->createMock(Server::class);
+
+ $this->plugin = new ViewOnlyPlugin(
+ $this->userFolder,
+ );
$server->tree = $this->tree;
$this->plugin->initialize($server);
@@ -71,27 +71,33 @@ class ViewOnlyPluginTest extends TestCase {
$this->assertTrue($this->plugin->checkViewOnly($this->request));
}
- public function providesDataForCanGet(): array {
+ public static function providesDataForCanGet(): array {
return [
// has attribute permissions-download enabled - can get file
- [false, true, true],
+ [false, true, true, true],
// has no attribute permissions-download - can get file
- [false, null, true],
- // has attribute permissions-download disabled- cannot get the file
- [false, false, false],
+ [false, null, true, true],
// has attribute permissions-download enabled - can get file version
- [true, true, true],
+ [true, true, true, true],
// has no attribute permissions-download - can get file version
- [true, null, true],
- // has attribute permissions-download disabled- cannot get the file version
- [true, false, false],
+ [true, null, true, true],
+ // has attribute permissions-download disabled - cannot get the file
+ [false, false, false, false],
+ // has attribute permissions-download disabled - cannot get the file version
+ [true, false, false, false],
+
+ // Has global allowViewWithoutDownload option enabled
+ // has attribute permissions-download disabled - can get file
+ [false, false, false, true],
+ // has attribute permissions-download disabled - can get file version
+ [true, false, false, true],
];
}
/**
* @dataProvider providesDataForCanGet
*/
- public function testCanGet(bool $isVersion, ?bool $attrEnabled, bool $expectCanDownloadFile): void {
+ public function testCanGet(bool $isVersion, ?bool $attrEnabled, bool $expectCanDownloadFile, bool $allowViewWithoutDownload): void {
$nodeInfo = $this->createMock(File::class);
if ($isVersion) {
$davPath = 'versions/alice/versions/117/123456';
@@ -151,6 +157,10 @@ class ViewOnlyPluginTest extends TestCase {
->with('permissions', 'download')
->willReturn($attrEnabled);
+ $share->expects($this->once())
+ ->method('canSeeContent')
+ ->willReturn($allowViewWithoutDownload);
+
if (!$expectCanDownloadFile) {
$this->expectException(Forbidden::class);
}
diff --git a/apps/dav/tests/unit/Direct/DirectFileTest.php b/apps/dav/tests/unit/Direct/DirectFileTest.php
index 07d19807ef0..f6f0f49fa8c 100644
--- a/apps/dav/tests/unit/Direct/DirectFileTest.php
+++ b/apps/dav/tests/unit/Direct/DirectFileTest.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\Direct;
+namespace OCA\DAV\Tests\unit\Direct;
use OCA\DAV\Db\Direct;
use OCA\DAV\Direct\DirectFile;
@@ -14,28 +14,17 @@ use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Exception\Forbidden;
use Test\TestCase;
class DirectFileTest extends TestCase {
-
- /** @var Direct */
- private $direct;
-
- /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject */
- private $rootFolder;
-
- /** @var Folder|\PHPUnit\Framework\MockObject\MockObject */
- private $userFolder;
-
- /** @var File|\PHPUnit\Framework\MockObject\MockObject */
- private $file;
-
- /** @var DirectFile */
- private $directFile;
-
- /** @var IEventDispatcher */
- private $eventDispatcher;
+ private Direct $direct;
+ private IRootFolder&MockObject $rootFolder;
+ private Folder&MockObject $userFolder;
+ private File&MockObject $file;
+ private IEventDispatcher&MockObject $eventDispatcher;
+ private DirectFile $directFile;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/Direct/DirectHomeTest.php b/apps/dav/tests/unit/Direct/DirectHomeTest.php
index 1134f0cd3af..94c82c2b7c5 100644
--- a/apps/dav/tests/unit/Direct/DirectHomeTest.php
+++ b/apps/dav/tests/unit/Direct/DirectHomeTest.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\Direct;
+namespace OCA\DAV\Tests\unit\Direct;
use OCA\DAV\Db\Direct;
use OCA\DAV\Db\DirectMapper;
@@ -18,33 +18,20 @@ use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\IRootFolder;
use OCP\IRequest;
use OCP\Security\Bruteforce\IThrottler;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\Exception\MethodNotAllowed;
use Sabre\DAV\Exception\NotFound;
use Test\TestCase;
class DirectHomeTest extends TestCase {
-
- /** @var DirectMapper|\PHPUnit\Framework\MockObject\MockObject */
- private $directMapper;
-
- /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject */
- private $rootFolder;
-
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
- private $timeFactory;
-
- /** @var IThrottler|\PHPUnit\Framework\MockObject\MockObject */
- private $throttler;
-
- /** @var IRequest */
- private $request;
-
- /** @var DirectHome */
- private $directHome;
-
- /** @var IEventDispatcher */
- private $eventDispatcher;
+ private DirectMapper&MockObject $directMapper;
+ private IRootFolder&MockObject $rootFolder;
+ private ITimeFactory&MockObject $timeFactory;
+ private IThrottler&MockObject $throttler;
+ private IRequest&MockObject $request;
+ private IEventDispatcher&MockObject $eventDispatcher;
+ private DirectHome $directHome;
protected function setUp(): void {
parent::setUp();
@@ -160,7 +147,7 @@ class DirectHomeTest extends TestCase {
'1.2.3.4'
);
$this->throttler->expects($this->once())
- ->method('sleepDelay')
+ ->method('sleepDelayOrThrowOnMax')
->with(
'1.2.3.4',
'directlink'
diff --git a/apps/dav/tests/unit/Files/FileSearchBackendTest.php b/apps/dav/tests/unit/Files/FileSearchBackendTest.php
index aaa3d8c147e..c6d6f85347b 100644
--- a/apps/dav/tests/unit/Files/FileSearchBackendTest.php
+++ b/apps/dav/tests/unit/Files/FileSearchBackendTest.php
@@ -1,10 +1,12 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Files;
+namespace OCA\DAV\Tests\unit\Files;
use OC\Files\Search\SearchComparison;
use OC\Files\Search\SearchQuery;
@@ -13,6 +15,7 @@ use OCA\DAV\Connector\Sabre\Directory;
use OCA\DAV\Connector\Sabre\File;
use OCA\DAV\Connector\Sabre\FilesPlugin;
use OCA\DAV\Connector\Sabre\ObjectTree;
+use OCA\DAV\Connector\Sabre\Server;
use OCA\DAV\Files\FileSearchBackend;
use OCP\Files\FileInfo;
use OCP\Files\Folder;
@@ -23,42 +26,27 @@ use OCP\Files\Search\ISearchQuery;
use OCP\FilesMetadata\IFilesMetadataManager;
use OCP\IUser;
use OCP\Share\IManager;
+use PHPUnit\Framework\MockObject\MockObject;
use SearchDAV\Backend\SearchPropertyDefinition;
use SearchDAV\Query\Limit;
+use SearchDAV\Query\Literal;
use SearchDAV\Query\Operator;
use SearchDAV\Query\Query;
+use SearchDAV\Query\Scope;
use Test\TestCase;
class FileSearchBackendTest extends TestCase {
- /** @var ObjectTree|\PHPUnit\Framework\MockObject\MockObject */
- private $tree;
-
- /** @var IUser */
- private $user;
-
- /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject */
- private $rootFolder;
-
- /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
- private $shareManager;
-
- /** @var View|\PHPUnit\Framework\MockObject\MockObject */
- private $view;
-
- /** @var Folder|\PHPUnit\Framework\MockObject\MockObject */
- private $searchFolder;
-
- /** @var FileSearchBackend */
- private $search;
-
- /** @var Directory|\PHPUnit\Framework\MockObject\MockObject */
- private $davFolder;
+ private ObjectTree&MockObject $tree;
+ private Server&MockObject $server;
+ private IUser&MockObject $user;
+ private IRootFolder&MockObject $rootFolder;
+ private IManager&MockObject $shareManager;
+ private View&MockObject $view;
+ private Folder&MockObject $searchFolder;
+ private Directory&MockObject $davFolder;
+ private FileSearchBackend $search;
protected function setUp(): void {
- if (PHP_VERSION_ID >= 80400) {
- $this->markTestSkipped('SearchDAV is not yet PHP 8.4 compatible');
- }
-
parent::setUp();
$this->user = $this->createMock(IUser::class);
@@ -66,11 +54,14 @@ class FileSearchBackendTest extends TestCase {
->method('getUID')
->willReturn('test');
- $this->tree = $this->getMockBuilder(ObjectTree::class)
- ->disableOriginalConstructor()
- ->getMock();
-
+ $this->tree = $this->createMock(ObjectTree::class);
+ $this->server = $this->createMock(Server::class);
$this->view = $this->createMock(View::class);
+ $this->rootFolder = $this->createMock(IRootFolder::class);
+ $this->shareManager = $this->createMock(IManager::class);
+ $this->searchFolder = $this->createMock(Folder::class);
+ $fileInfo = $this->createMock(FileInfo::class);
+ $this->davFolder = $this->createMock(Directory::class);
$this->view->expects($this->any())
->method('getRoot')
@@ -80,16 +71,6 @@ class FileSearchBackendTest extends TestCase {
->method('getRelativePath')
->willReturnArgument(0);
- $this->rootFolder = $this->createMock(IRootFolder::class);
-
- $this->shareManager = $this->createMock(IManager::class);
-
- $this->searchFolder = $this->createMock(Folder::class);
-
- $fileInfo = $this->createMock(FileInfo::class);
-
- $this->davFolder = $this->createMock(Directory::class);
-
$this->davFolder->expects($this->any())
->method('getFileInfo')
->willReturn($fileInfo);
@@ -100,7 +81,7 @@ class FileSearchBackendTest extends TestCase {
$filesMetadataManager = $this->createMock(IFilesMetadataManager::class);
- $this->search = new FileSearchBackend($this->tree, $this->user, $this->rootFolder, $this->shareManager, $this->view, $filesMetadataManager);
+ $this->search = new FileSearchBackend($this->server, $this->tree, $this->user, $this->rootFolder, $this->shareManager, $this->view, $filesMetadataManager);
}
public function testSearchFilename(): void {
@@ -263,8 +244,8 @@ class FileSearchBackendTest extends TestCase {
$this->search->search($query);
}
- private function getBasicQuery($type, $property, $value = null) {
- $scope = new \SearchDAV\Query\Scope('/', 'infinite');
+ private function getBasicQuery(string $type, string $property, int|string|null $value = null) {
+ $scope = new Scope('/', 'infinite');
$scope->path = '/';
$from = [$scope];
$orderBy = [];
@@ -272,12 +253,12 @@ class FileSearchBackendTest extends TestCase {
if (is_null($value)) {
$where = new Operator(
$type,
- [new \SearchDAV\Query\Literal($property)]
+ [new Literal($property)]
);
} else {
$where = new Operator(
$type,
- [new SearchPropertyDefinition($property, true, true, true), new \SearchDAV\Query\Literal($value)]
+ [new SearchPropertyDefinition($property, true, true, true), new Literal($value)]
);
}
$limit = new Limit();
@@ -350,11 +331,11 @@ class FileSearchBackendTest extends TestCase {
[
new Operator(
Operator::OPERATION_EQUAL,
- [new SearchPropertyDefinition('{DAV:}getcontenttype', true, true, true), new \SearchDAV\Query\Literal('image/png')]
+ [new SearchPropertyDefinition('{DAV:}getcontenttype', true, true, true), new Literal('image/png')]
),
new Operator(
Operator::OPERATION_EQUAL,
- [new SearchPropertyDefinition(FilesPlugin::OWNER_ID_PROPERTYNAME, true, true, true), new \SearchDAV\Query\Literal($this->user->getUID())]
+ [new SearchPropertyDefinition(FilesPlugin::OWNER_ID_PROPERTYNAME, true, true, true), new Literal($this->user->getUID())]
),
]
);
@@ -383,7 +364,7 @@ class FileSearchBackendTest extends TestCase {
$innerOperator = new Operator(
Operator::OPERATION_EQUAL,
- [new SearchPropertyDefinition('{DAV:}getcontenttype', true, true, true), new \SearchDAV\Query\Literal('image/png')]
+ [new SearchPropertyDefinition('{DAV:}getcontenttype', true, true, true), new Literal('image/png')]
);
// 5 child operators
$level1Operator = new Operator(
@@ -424,4 +405,17 @@ class FileSearchBackendTest extends TestCase {
$this->expectException(\InvalidArgumentException::class);
$this->search->search($query);
}
+
+ public function testPreloadPropertyFor(): void {
+ $node1 = $this->createMock(File::class);
+ $node2 = $this->createMock(Directory::class);
+ $nodes = [$node1, $node2];
+ $requestProperties = ['{DAV:}getcontenttype', '{DAV:}getlastmodified'];
+
+ $this->server->expects($this->once())
+ ->method('emit')
+ ->with('preloadProperties', [$nodes, $requestProperties]);
+
+ $this->search->preloadPropertyFor($nodes, $requestProperties);
+ }
}
diff --git a/apps/dav/tests/unit/Files/MultipartRequestParserTest.php b/apps/dav/tests/unit/Files/MultipartRequestParserTest.php
index 40880bdca9c..dc0e884f07c 100644
--- a/apps/dav/tests/unit/Files/MultipartRequestParserTest.php
+++ b/apps/dav/tests/unit/Files/MultipartRequestParserTest.php
@@ -1,10 +1,12 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
-namespace OCA\DAV\Tests\unit\DAV;
+namespace OCA\DAV\Tests\unit\Files;
use OCA\DAV\BulkUpload\MultipartRequestParser;
use PHPUnit\Framework\MockObject\MockObject;
@@ -17,10 +19,11 @@ class MultipartRequestParserTest extends TestCase {
protected LoggerInterface&MockObject $logger;
protected function setUp(): void {
+ parent::setUp();
$this->logger = $this->createMock(LoggerInterface::class);
}
- private function getValidBodyObject() {
+ private static function getValidBodyObject(): array {
return [
[
'headers' => [
@@ -99,7 +102,7 @@ class MultipartRequestParserTest extends TestCase {
* - valid file path
*/
public function testValidRequest(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
unset($bodyObject['0']['headers']['X-File-MD5']);
$multipartParser = $this->getMultipartParser($bodyObject);
@@ -122,7 +125,7 @@ class MultipartRequestParserTest extends TestCase {
* - valid file path
*/
public function testValidRequestWithMd5(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
unset($bodyObject['0']['headers']['OC-Checksum']);
$multipartParser = $this->getMultipartParser($bodyObject);
@@ -140,7 +143,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with invalid hash.
*/
public function testInvalidHash(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
$bodyObject['0']['headers']['OC-Checksum'] = 'md5:f2377b4d911f7ec46325fe603c3af03';
unset($bodyObject['0']['headers']['X-File-MD5']);
$multipartParser = $this->getMultipartParser(
@@ -155,7 +158,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with invalid md5 hash.
*/
public function testInvalidMd5Hash(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
unset($bodyObject['0']['headers']['OC-Checksum']);
$bodyObject['0']['headers']['X-File-MD5'] = 'f2377b4d911f7ec46325fe603c3af03';
$multipartParser = $this->getMultipartParser(
@@ -170,7 +173,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with a null hash headers.
*/
public function testNullHash(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
unset($bodyObject['0']['headers']['OC-Checksum']);
unset($bodyObject['0']['headers']['X-File-MD5']);
$multipartParser = $this->getMultipartParser(
@@ -185,7 +188,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with a null Content-Length.
*/
public function testNullContentLength(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
unset($bodyObject['0']['headers']['Content-Length']);
$multipartParser = $this->getMultipartParser(
$bodyObject
@@ -199,7 +202,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with a lower Content-Length.
*/
public function testLowerContentLength(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
$bodyObject['0']['headers']['Content-Length'] = 6;
$multipartParser = $this->getMultipartParser(
$bodyObject
@@ -213,7 +216,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with a higher Content-Length.
*/
public function testHigherContentLength(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
$bodyObject['0']['headers']['Content-Length'] = 8;
$multipartParser = $this->getMultipartParser(
$bodyObject
@@ -227,7 +230,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with wrong boundary in body.
*/
public function testWrongBoundary(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
$multipartParser = $this->getMultipartParser(
$bodyObject,
['Content-Type' => 'multipart/related; boundary=boundary_poiuytreza']
@@ -241,7 +244,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with no boundary in request headers.
*/
public function testNoBoundaryInHeader(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
$this->expectExceptionMessage('Error while parsing boundary in Content-Type header.');
$this->getMultipartParser(
$bodyObject,
@@ -253,7 +256,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with no boundary in the request's headers.
*/
public function testNoBoundaryInBody(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
$multipartParser = $this->getMultipartParser(
$bodyObject,
['Content-Type' => 'multipart/related; boundary=boundary_azertyuiop'],
@@ -268,7 +271,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with a boundary with quotes in the request's headers.
*/
public function testBoundaryWithQuotes(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
$multipartParser = $this->getMultipartParser(
$bodyObject,
['Content-Type' => 'multipart/related; boundary="boundary_azertyuiop"'],
@@ -284,7 +287,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with a wrong Content-Type in the request's headers.
*/
public function testWrongContentType(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
$this->expectExceptionMessage('Content-Type must be multipart/related');
$this->getMultipartParser(
$bodyObject,
@@ -296,7 +299,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with a wrong key after the content type in the request's headers.
*/
public function testWrongKeyInContentType(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
$this->expectExceptionMessage('Boundary is invalid');
$this->getMultipartParser(
$bodyObject,
@@ -308,7 +311,7 @@ class MultipartRequestParserTest extends TestCase {
* Test with a null Content-Type in the request's headers.
*/
public function testNullContentType(): void {
- $bodyObject = $this->getValidBodyObject();
+ $bodyObject = self::getValidBodyObject();
$this->expectExceptionMessage('Content-Type can not be null');
$this->getMultipartParser(
$bodyObject,
diff --git a/apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php b/apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php
index 7264119f8c6..1a7ab7179e1 100644
--- a/apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php
+++ b/apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php
@@ -1,15 +1,19 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Files\Sharing;
+namespace OCA\DAV\Tests\unit\Files\Sharing;
-use OC\Files\View;
use OCA\DAV\Files\Sharing\FilesDropPlugin;
+use OCP\Files\Folder;
+use OCP\Files\NotFoundException;
use OCP\Share\IAttributes;
use OCP\Share\IShare;
-use Sabre\DAV\Exception\MethodNotAllowed;
+use PHPUnit\Framework\MockObject\MockObject;
+use Sabre\DAV\Exception\BadRequest;
use Sabre\DAV\Server;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
@@ -17,60 +21,42 @@ use Test\TestCase;
class FilesDropPluginTest extends TestCase {
- /** @var View|\PHPUnit\Framework\MockObject\MockObject */
- private $view;
-
- /** @var IShare|\PHPUnit\Framework\MockObject\MockObject */
- private $share;
-
- /** @var Server|\PHPUnit\Framework\MockObject\MockObject */
- private $server;
-
- /** @var FilesDropPlugin */
- private $plugin;
+ private FilesDropPlugin $plugin;
- /** @var RequestInterface|\PHPUnit\Framework\MockObject\MockObject */
- private $request;
-
- /** @var ResponseInterface|\PHPUnit\Framework\MockObject\MockObject */
- private $response;
+ private Folder&MockObject $node;
+ private IShare&MockObject $share;
+ private Server&MockObject $server;
+ private RequestInterface&MockObject $request;
+ private ResponseInterface&MockObject $response;
protected function setUp(): void {
parent::setUp();
- $this->view = $this->createMock(View::class);
+ $this->node = $this->createMock(Folder::class);
+ $this->node->method('getPath')
+ ->willReturn('/files/token');
+
$this->share = $this->createMock(IShare::class);
+ $this->share->expects(self::any())
+ ->method('getNode')
+ ->willReturn($this->node);
$this->server = $this->createMock(Server::class);
$this->plugin = new FilesDropPlugin();
$this->request = $this->createMock(RequestInterface::class);
$this->response = $this->createMock(ResponseInterface::class);
- $this->response->expects($this->never())
- ->method($this->anything());
-
$attributes = $this->createMock(IAttributes::class);
$this->share->expects($this->any())
->method('getAttributes')
->willReturn($attributes);
- }
-
- public function testInitialize(): void {
- $this->server->expects($this->once())
- ->method('on')
- ->with(
- $this->equalTo('beforeMethod:*'),
- $this->equalTo([$this->plugin, 'beforeMethod']),
- $this->equalTo(999)
- );
- $this->plugin->initialize($this->server);
+ $this->share
+ ->method('getToken')
+ ->willReturn('token');
}
public function testNotEnabled(): void {
- $this->view->expects($this->never())
- ->method($this->anything());
-
$this->request->expects($this->never())
->method($this->anything());
@@ -79,99 +65,194 @@ class FilesDropPluginTest extends TestCase {
public function testValid(): void {
$this->plugin->enable();
- $this->plugin->setView($this->view);
$this->plugin->setShare($this->share);
$this->request->method('getMethod')
->willReturn('PUT');
$this->request->method('getPath')
- ->willReturn('file.txt');
+ ->willReturn('/files/token/file.txt');
$this->request->method('getBaseUrl')
->willReturn('https://example.com');
- $this->view->method('file_exists')
- ->with('/file.txt')
- ->willReturn(false);
+ $this->node->expects(self::once())
+ ->method('getNonExistingName')
+ ->with('file.txt')
+ ->willReturn('file.txt');
$this->request->expects($this->once())
->method('setUrl')
- ->with('https://example.com/file.txt');
+ ->with('https://example.com/files/token/file.txt');
$this->plugin->beforeMethod($this->request, $this->response);
}
public function testFileAlreadyExistsValid(): void {
$this->plugin->enable();
- $this->plugin->setView($this->view);
$this->plugin->setShare($this->share);
$this->request->method('getMethod')
->willReturn('PUT');
$this->request->method('getPath')
- ->willReturn('file.txt');
+ ->willReturn('/files/token/file.txt');
$this->request->method('getBaseUrl')
->willReturn('https://example.com');
- $this->view->method('file_exists')
- ->willReturnCallback(function ($path) {
- if ($path === 'file.txt' || $path === '/file.txt') {
- return true;
- } else {
- return false;
- }
- });
+ $this->node->method('getNonExistingName')
+ ->with('file.txt')
+ ->willReturn('file (2).txt');
$this->request->expects($this->once())
->method('setUrl')
- ->with($this->equalTo('https://example.com/file (2).txt'));
+ ->with($this->equalTo('https://example.com/files/token/file (2).txt'));
$this->plugin->beforeMethod($this->request, $this->response);
}
- public function testNoMKCOL(): void {
+ public function testNoMKCOLWithoutNickname(): void {
$this->plugin->enable();
- $this->plugin->setView($this->view);
$this->plugin->setShare($this->share);
$this->request->method('getMethod')
->willReturn('MKCOL');
- $this->expectException(MethodNotAllowed::class);
+ $this->expectException(BadRequest::class);
+
+ $this->plugin->beforeMethod($this->request, $this->response);
+ }
+
+ public function testMKCOLWithNickname(): void {
+ $this->plugin->enable();
+ $this->plugin->setShare($this->share);
+
+ $this->request->method('getMethod')
+ ->willReturn('MKCOL');
+
+ $this->request->method('hasHeader')
+ ->with('X-NC-Nickname')
+ ->willReturn(true);
+ $this->request->method('getHeader')
+ ->with('X-NC-Nickname')
+ ->willReturn('nickname');
+
+ $this->expectNotToPerformAssertions();
$this->plugin->beforeMethod($this->request, $this->response);
}
- public function testNoSubdirPut(): void {
+ public function testSubdirPut(): void {
$this->plugin->enable();
- $this->plugin->setView($this->view);
$this->plugin->setShare($this->share);
$this->request->method('getMethod')
->willReturn('PUT');
+ $this->request->method('hasHeader')
+ ->with('X-NC-Nickname')
+ ->willReturn(true);
+ $this->request->method('getHeader')
+ ->with('X-NC-Nickname')
+ ->willReturn('nickname');
+
$this->request->method('getPath')
- ->willReturn('folder/file.txt');
+ ->willReturn('/files/token/folder/file.txt');
$this->request->method('getBaseUrl')
->willReturn('https://example.com');
- $this->view->method('file_exists')
- ->willReturnCallback(function ($path) {
- if ($path === 'file.txt' || $path === '/file.txt') {
- return true;
- } else {
- return false;
- }
- });
+ $nodeName = $this->createMock(Folder::class);
+ $nodeFolder = $this->createMock(Folder::class);
+ $nodeFolder->expects(self::once())
+ ->method('getPath')
+ ->willReturn('/files/token/nickname/folder');
+ $nodeFolder->method('getNonExistingName')
+ ->with('file.txt')
+ ->willReturn('file.txt');
+ $nodeName->expects(self::once())
+ ->method('get')
+ ->with('folder')
+ ->willThrowException(new NotFoundException());
+ $nodeName->expects(self::once())
+ ->method('newFolder')
+ ->with('folder')
+ ->willReturn($nodeFolder);
+
+ $this->node->expects(self::once())
+ ->method('get')
+ ->willThrowException(new NotFoundException());
+ $this->node->expects(self::once())
+ ->method('newFolder')
+ ->with('nickname')
+ ->willReturn($nodeName);
$this->request->expects($this->once())
->method('setUrl')
- ->with($this->equalTo('https://example.com/file (2).txt'));
+ ->with($this->equalTo('https://example.com/files/token/nickname/folder/file.txt'));
$this->plugin->beforeMethod($this->request, $this->response);
}
+
+ public function testRecursiveFolderCreation(): void {
+ $this->plugin->enable();
+ $this->plugin->setShare($this->share);
+
+ $this->request->method('getMethod')
+ ->willReturn('PUT');
+ $this->request->method('hasHeader')
+ ->with('X-NC-Nickname')
+ ->willReturn(true);
+ $this->request->method('getHeader')
+ ->with('X-NC-Nickname')
+ ->willReturn('nickname');
+
+ $this->request->method('getPath')
+ ->willReturn('/files/token/folder/subfolder/file.txt');
+ $this->request->method('getBaseUrl')
+ ->willReturn('https://example.com');
+
+ $this->request->expects($this->once())
+ ->method('setUrl')
+ ->with($this->equalTo('https://example.com/files/token/nickname/folder/subfolder/file.txt'));
+
+ $subfolder = $this->createMock(Folder::class);
+ $subfolder->expects(self::once())
+ ->method('getNonExistingName')
+ ->with('file.txt')
+ ->willReturn('file.txt');
+ $subfolder->expects(self::once())
+ ->method('getPath')
+ ->willReturn('/files/token/nickname/folder/subfolder');
+
+ $folder = $this->createMock(Folder::class);
+ $folder->expects(self::once())
+ ->method('get')
+ ->with('subfolder')
+ ->willReturn($subfolder);
+
+ $nickname = $this->createMock(Folder::class);
+ $nickname->expects(self::once())
+ ->method('get')
+ ->with('folder')
+ ->willReturn($folder);
+
+ $this->node->method('get')
+ ->with('nickname')
+ ->willReturn($nickname);
+ $this->plugin->beforeMethod($this->request, $this->response);
+ }
+
+ public function testOnMkcol(): void {
+ $this->plugin->enable();
+ $this->plugin->setShare($this->share);
+
+ $this->response->expects($this->once())
+ ->method('setStatus')
+ ->with(201);
+
+ $response = $this->plugin->onMkcol($this->request, $this->response);
+ $this->assertFalse($response);
+ }
}
diff --git a/apps/dav/tests/unit/Listener/ActivityUpdaterListenerTest.php b/apps/dav/tests/unit/Listener/ActivityUpdaterListenerTest.php
index 78769c7fb47..7bd7bdc2167 100644
--- a/apps/dav/tests/unit/Listener/ActivityUpdaterListenerTest.php
+++ b/apps/dav/tests/unit/Listener/ActivityUpdaterListenerTest.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\Listener;
+namespace OCA\DAV\Tests\unit\Listener;
use OCA\DAV\CalDAV\Activity\Backend as ActivityBackend;
use OCA\DAV\CalDAV\Activity\Provider\Event;
@@ -20,10 +20,8 @@ use Test\TestCase;
class ActivityUpdaterListenerTest extends TestCase {
- /** @var ActivityBackend|MockObject */
- private $activityBackend;
- /** @var LoggerInterface|MockObject */
- private $logger;
+ private ActivityBackend&MockObject $activityBackend;
+ private LoggerInterface&MockObject $logger;
private ActivityUpdaterListener $listener;
protected function setUp(): void {
@@ -55,7 +53,7 @@ class ActivityUpdaterListenerTest extends TestCase {
$this->listener->handle($event);
}
- public function dataForTestHandleCalendarObjectDeletedEvent(): array {
+ public static function dataForTestHandleCalendarObjectDeletedEvent(): array {
return [
[1, [], [], [], true],
[1, [], [], ['{' . SharingPlugin::NS_NEXTCLOUD . '}deleted-at' => 120], false],
@@ -77,7 +75,7 @@ class ActivityUpdaterListenerTest extends TestCase {
$this->listener->handle($event);
}
- public function dataForTestHandleCalendarDeletedEvent(): array {
+ public static function dataForTestHandleCalendarDeletedEvent(): array {
return [
[1, [], [], true],
[1, ['{' . SharingPlugin::NS_NEXTCLOUD . '}deleted-at' => 120], [], false],
diff --git a/apps/dav/tests/unit/Listener/CalendarContactInteractionListenerTest.php b/apps/dav/tests/unit/Listener/CalendarContactInteractionListenerTest.php
index 96d8514da41..dc3dce8a62f 100644
--- a/apps/dav/tests/unit/Listener/CalendarContactInteractionListenerTest.php
+++ b/apps/dav/tests/unit/Listener/CalendarContactInteractionListenerTest.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\Listener;
+namespace OCA\DAV\Tests\unit\Listener;
use OCA\DAV\Connector\Sabre\Principal;
use OCA\DAV\Events\CalendarShareUpdatedEvent;
@@ -23,24 +23,12 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class CalendarContactInteractionListenerTest extends TestCase {
-
- /** @var IEventDispatcher|MockObject */
- private $eventDispatcher;
-
- /** @var IUserSession|MockObject */
- private $userSession;
-
- /** @var Principal|MockObject */
- private $principalConnector;
-
- /** @var LoggerInterface|MockObject */
- private $logger;
-
- /** @var IMailer|MockObject */
- private $mailer;
-
- /** @var CalendarContactInteractionListener */
- private $listener;
+ private IEventDispatcher&MockObject $eventDispatcher;
+ private IUserSession&MockObject $userSession;
+ private Principal&MockObject $principalConnector;
+ private LoggerInterface&MockObject $logger;
+ private IMailer&MockObject $mailer;
+ private CalendarContactInteractionListener $listener;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/Listener/OutOfOfficeListenerTest.php b/apps/dav/tests/unit/Listener/OutOfOfficeListenerTest.php
index a21d3a5e928..971d113b742 100644
--- a/apps/dav/tests/unit/Listener/OutOfOfficeListenerTest.php
+++ b/apps/dav/tests/unit/Listener/OutOfOfficeListenerTest.php
@@ -7,7 +7,7 @@ declare(strict_types=1);
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\Listener;
+namespace OCA\DAV\Tests\unit\Listener;
use DateTimeImmutable;
use InvalidArgumentException;
@@ -27,7 +27,6 @@ use OCP\User\Events\OutOfOfficeChangedEvent;
use OCP\User\Events\OutOfOfficeClearedEvent;
use OCP\User\Events\OutOfOfficeScheduledEvent;
use OCP\User\IOutOfOfficeData;
-use OCP\UserStatus\IManager;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Exception\NotFound;
@@ -42,11 +41,10 @@ use Test\TestCase;
*/
class OutOfOfficeListenerTest extends TestCase {
- private ServerFactory|MockObject $serverFactory;
- private IConfig|MockObject $appConfig;
- private LoggerInterface|MockObject $loggerInterface;
- private MockObject|TimezoneService $timezoneService;
- private IManager|MockObject $manager;
+ private ServerFactory&MockObject $serverFactory;
+ private IConfig&MockObject $appConfig;
+ private LoggerInterface&MockObject $loggerInterface;
+ private TimezoneService&MockObject $timezoneService;
private OutOfOfficeListener $listener;
protected function setUp(): void {
@@ -56,14 +54,12 @@ class OutOfOfficeListenerTest extends TestCase {
$this->appConfig = $this->createMock(IConfig::class);
$this->timezoneService = $this->createMock(TimezoneService::class);
$this->loggerInterface = $this->createMock(LoggerInterface::class);
- $this->manager = $this->createMock(IManager::class);
$this->listener = new OutOfOfficeListener(
$this->serverFactory,
$this->appConfig,
$this->timezoneService,
$this->loggerInterface,
- $this->manager
);
}
@@ -453,8 +449,6 @@ class OutOfOfficeListenerTest extends TestCase {
->method('getPlugin')
->with('caldav')
->willReturn($caldavPlugin);
- $this->manager->expects(self::never())
- ->method('revertUserStatus');
$event = new OutOfOfficeClearedEvent($data);
$this->listener->handle($event);
@@ -483,8 +477,6 @@ class OutOfOfficeListenerTest extends TestCase {
->method('getNodeForPath')
->with('/home/calendar')
->willThrowException(new NotFound('nope'));
- $this->manager->expects(self::never())
- ->method('revertUserStatus');
$event = new OutOfOfficeClearedEvent($data);
$this->listener->handle($event);
@@ -522,8 +514,6 @@ class OutOfOfficeListenerTest extends TestCase {
->method('getChild')
->with('personal-1')
->willThrowException(new NotFound('nope'));
- $this->manager->expects(self::never())
- ->method('revertUserStatus');
$event = new OutOfOfficeClearedEvent($data);
$this->listener->handle($event);
@@ -565,8 +555,6 @@ class OutOfOfficeListenerTest extends TestCase {
$calendar->expects(self::once())
->method('getChild')
->willThrowException(new NotFound());
- $this->manager->expects(self::never())
- ->method('revertUserStatus');
$event = new OutOfOfficeClearedEvent($data);
$this->listener->handle($event);
diff --git a/apps/dav/tests/unit/Migration/CalDAVRemoveEmptyValueTest.php b/apps/dav/tests/unit/Migration/CalDAVRemoveEmptyValueTest.php
index be2c64c47a4..1852d2709c1 100644
--- a/apps/dav/tests/unit/Migration/CalDAVRemoveEmptyValueTest.php
+++ b/apps/dav/tests/unit/Migration/CalDAVRemoveEmptyValueTest.php
@@ -1,15 +1,18 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\DAV\Migration;
+namespace OCA\DAV\Tests\unit\DAV\Migration;
use OCA\DAV\CalDAV\CalDavBackend;
use OCA\DAV\Migration\CalDAVRemoveEmptyValue;
use OCP\IDBConnection;
use OCP\Migration\IOutput;
use OCP\Server;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\VObject\InvalidDataException;
use Test\TestCase;
@@ -21,18 +24,10 @@ use Test\TestCase;
* @group DB
*/
class CalDAVRemoveEmptyValueTest extends TestCase {
-
- /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
- private $logger;
-
- /** @var CalDavBackend|\PHPUnit\Framework\MockObject\MockObject */
- private $backend;
-
- /** @var IOutput|\PHPUnit\Framework\MockObject\MockObject */
- private $output;
-
- /** @var string */
- private $invalid = 'BEGIN:VCALENDAR
+ private LoggerInterface&MockObject $logger;
+ private CalDavBackend&MockObject $backend;
+ private IOutput&MockObject $output;
+ private string $invalid = 'BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Apple Inc.//Mac OS X 10.11.2//EN
CALSCALE:GREGORIAN
@@ -52,8 +47,7 @@ CREATED;VALUE=:20151214T091032Z
END:VEVENT
END:VCALENDAR';
- /** @var string */
- private $valid = 'BEGIN:VCALENDAR
+ private string $valid = 'BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Apple Inc.//Mac OS X 10.11.2//EN
CALSCALE:GREGORIAN
@@ -82,14 +76,14 @@ END:VCALENDAR';
}
public function testRunAllValid(): void {
- /** @var CalDAVRemoveEmptyValue|\PHPUnit\Framework\MockObject\MockObject $step */
+ /** @var CalDAVRemoveEmptyValue&MockObject $step */
$step = $this->getMockBuilder(CalDAVRemoveEmptyValue::class)
->setConstructorArgs([
Server::get(IDBConnection::class),
$this->backend,
$this->logger
])
- ->setMethods(['getInvalidObjects'])
+ ->onlyMethods(['getInvalidObjects'])
->getMock();
$step->expects($this->once())
@@ -106,14 +100,14 @@ END:VCALENDAR';
}
public function testRunInvalid(): void {
- /** @var CalDAVRemoveEmptyValue|\PHPUnit\Framework\MockObject\MockObject $step */
+ /** @var CalDAVRemoveEmptyValue&MockObject $step */
$step = $this->getMockBuilder(CalDAVRemoveEmptyValue::class)
->setConstructorArgs([
Server::get(IDBConnection::class),
$this->backend,
$this->logger
])
- ->setMethods(['getInvalidObjects'])
+ ->onlyMethods(['getInvalidObjects'])
->getMock();
$step->expects($this->once())
@@ -149,14 +143,14 @@ END:VCALENDAR';
}
public function testRunValid(): void {
- /** @var CalDAVRemoveEmptyValue|\PHPUnit\Framework\MockObject\MockObject $step */
+ /** @var CalDAVRemoveEmptyValue&MockObject $step */
$step = $this->getMockBuilder(CalDAVRemoveEmptyValue::class)
->setConstructorArgs([
Server::get(IDBConnection::class),
$this->backend,
$this->logger
])
- ->setMethods(['getInvalidObjects'])
+ ->onlyMethods(['getInvalidObjects'])
->getMock();
$step->expects($this->once())
@@ -191,14 +185,14 @@ END:VCALENDAR';
}
public function testRunStillInvalid(): void {
- /** @var CalDAVRemoveEmptyValue|\PHPUnit\Framework\MockObject\MockObject $step */
+ /** @var CalDAVRemoveEmptyValue&MockObject $step */
$step = $this->getMockBuilder(CalDAVRemoveEmptyValue::class)
->setConstructorArgs([
Server::get(IDBConnection::class),
$this->backend,
$this->logger
])
- ->setMethods(['getInvalidObjects'])
+ ->onlyMethods(['getInvalidObjects'])
->getMock();
$step->expects($this->once())
diff --git a/apps/dav/tests/unit/Migration/CreateSystemAddressBookStepTest.php b/apps/dav/tests/unit/Migration/CreateSystemAddressBookStepTest.php
index bbecd0607b4..667d2e39d3a 100644
--- a/apps/dav/tests/unit/Migration/CreateSystemAddressBookStepTest.php
+++ b/apps/dav/tests/unit/Migration/CreateSystemAddressBookStepTest.php
@@ -7,7 +7,7 @@ declare(strict_types=1);
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\Migration;
+namespace OCA\DAV\Tests\unit\Migration;
use OCA\DAV\CardDAV\SyncService;
use OCA\DAV\Migration\CreateSystemAddressBookStep;
@@ -17,7 +17,7 @@ use PHPUnit\Framework\TestCase;
class CreateSystemAddressBookStepTest extends TestCase {
- private SyncService|MockObject $syncService;
+ private SyncService&MockObject $syncService;
private CreateSystemAddressBookStep $step;
protected function setUp(): void {
diff --git a/apps/dav/tests/unit/Migration/RefreshWebcalJobRegistrarTest.php b/apps/dav/tests/unit/Migration/RefreshWebcalJobRegistrarTest.php
index bf4c60b3cf1..73d9c1efd29 100644
--- a/apps/dav/tests/unit/Migration/RefreshWebcalJobRegistrarTest.php
+++ b/apps/dav/tests/unit/Migration/RefreshWebcalJobRegistrarTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -12,17 +14,13 @@ use OCP\DB\IResult;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCP\Migration\IOutput;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class RefreshWebcalJobRegistrarTest extends TestCase {
- /** @var IDBConnection | \PHPUnit\Framework\MockObject\MockObject */
- private $db;
-
- /** @var IJobList | \PHPUnit\Framework\MockObject\MockObject */
- private $jobList;
-
- /** @var RefreshWebcalJobRegistrar */
- private $migration;
+ private IDBConnection&MockObject $db;
+ private IJobList&MockObject $jobList;
+ private RefreshWebcalJobRegistrar $migration;
protected function setUp(): void {
parent::setUp();
@@ -80,35 +78,37 @@ class RefreshWebcalJobRegistrarTest extends TestCase {
$this->jobList->expects($this->exactly(3))
->method('has')
- ->withConsecutive(
+ ->willReturnMap([
[RefreshWebcalJob::class, [
'principaluri' => 'foo1',
'uri' => 'bar1',
- ]],
+ ], false],
[RefreshWebcalJob::class, [
'principaluri' => 'foo2',
'uri' => 'bar2',
- ]],
+ ], true ],
[RefreshWebcalJob::class, [
'principaluri' => 'foo3',
'uri' => 'bar3',
- ]])
- ->willReturnOnConsecutiveCalls(
- false,
- true,
- false,
- );
+ ], false],
+ ]);
+
+ $calls = [
+ [RefreshWebcalJob::class, [
+ 'principaluri' => 'foo1',
+ 'uri' => 'bar1',
+ ]],
+ [RefreshWebcalJob::class, [
+ 'principaluri' => 'foo3',
+ 'uri' => 'bar3',
+ ]]
+ ];
$this->jobList->expects($this->exactly(2))
->method('add')
- ->withConsecutive(
- [RefreshWebcalJob::class, [
- 'principaluri' => 'foo1',
- 'uri' => 'bar1',
- ]],
- [RefreshWebcalJob::class, [
- 'principaluri' => 'foo3',
- 'uri' => 'bar3',
- ]]);
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
$output->expects($this->once())
->method('info')
diff --git a/apps/dav/tests/unit/Migration/RegenerateBirthdayCalendarsTest.php b/apps/dav/tests/unit/Migration/RegenerateBirthdayCalendarsTest.php
index e2ac45526d2..6f681badb8b 100644
--- a/apps/dav/tests/unit/Migration/RegenerateBirthdayCalendarsTest.php
+++ b/apps/dav/tests/unit/Migration/RegenerateBirthdayCalendarsTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -10,18 +12,13 @@ use OCA\DAV\Migration\RegenerateBirthdayCalendars;
use OCP\BackgroundJob\IJobList;
use OCP\IConfig;
use OCP\Migration\IOutput;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class RegenerateBirthdayCalendarsTest extends TestCase {
-
- /** @var IJobList | \PHPUnit\Framework\MockObject\MockObject */
- private $jobList;
-
- /** @var IConfig | \PHPUnit\Framework\MockObject\MockObject */
- private $config;
-
- /** @var RegenerateBirthdayCalendars */
- private $migration;
+ private IJobList&MockObject $jobList;
+ private IConfig&MockObject $config;
+ private RegenerateBirthdayCalendars $migration;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/Migration/RemoveDeletedUsersCalendarSubscriptionsTest.php b/apps/dav/tests/unit/Migration/RemoveDeletedUsersCalendarSubscriptionsTest.php
index a3daf1c918a..0a646e91602 100644
--- a/apps/dav/tests/unit/Migration/RemoveDeletedUsersCalendarSubscriptionsTest.php
+++ b/apps/dav/tests/unit/Migration/RemoveDeletedUsersCalendarSubscriptionsTest.php
@@ -22,23 +22,10 @@ use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class RemoveDeletedUsersCalendarSubscriptionsTest extends TestCase {
- /**
- * @var IDBConnection|MockObject
- */
- private $dbConnection;
- /**
- * @var IUserManager|MockObject
- */
- private $userManager;
-
- /**
- * @var IOutput|MockObject
- */
- private $output;
- /**
- * @var RemoveDeletedUsersCalendarSubscriptions
- */
- private $migration;
+ private IDBConnection&MockObject $dbConnection;
+ private IUserManager&MockObject $userManager;
+ private IOutput&MockObject $output;
+ private RemoveDeletedUsersCalendarSubscriptions $migration;
protected function setUp(): void {
@@ -60,10 +47,6 @@ class RemoveDeletedUsersCalendarSubscriptionsTest extends TestCase {
/**
* @dataProvider dataTestRun
- * @param array $subscriptions
- * @param array $userExists
- * @param int $deletions
- * @throws \Exception
*/
public function testRun(array $subscriptions, array $userExists, int $deletions): void {
$qb = $this->createMock(IQueryBuilder::class);
@@ -132,21 +115,28 @@ class RemoveDeletedUsersCalendarSubscriptionsTest extends TestCase {
$this->migration->run($this->output);
}
- public function dataTestRun(): array {
+ public static function dataTestRun(): array {
return [
[[], [], 0],
- [[[
- 'id' => 1,
- 'principaluri' => 'users/principals/foo1',
- ],
+ [
[
- 'id' => 2,
- 'principaluri' => 'users/principals/bar1',
+ [
+ 'id' => 1,
+ 'principaluri' => 'users/principals/foo1',
+ ],
+ [
+ 'id' => 2,
+ 'principaluri' => 'users/principals/bar1',
+ ],
+ [
+ 'id' => 3,
+ 'principaluri' => 'users/principals/bar1',
+ ],
+ [],
],
- [
- 'id' => 3,
- 'principaluri' => 'users/principals/bar1',
- ]], ['foo1' => true, 'bar1' => false], 2]
+ ['foo1' => true, 'bar1' => false],
+ 2
+ ],
];
}
}
diff --git a/apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningNodeTest.php b/apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningNodeTest.php
index 0979aff8a81..4f04aebb3e8 100644
--- a/apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningNodeTest.php
+++ b/apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningNodeTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -7,15 +9,13 @@ namespace OCA\DAV\Tests\unit\Provisioning\Apple;
use OCA\DAV\Provisioning\Apple\AppleProvisioningNode;
use OCP\AppFramework\Utility\ITimeFactory;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\PropPatch;
use Test\TestCase;
class AppleProvisioningNodeTest extends TestCase {
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
- private $timeFactory;
-
- /** @var AppleProvisioningNode */
- private $node;
+ private ITimeFactory&MockObject $timeFactory;
+ private AppleProvisioningNode $node;
protected function setUp(): void {
parent::setUp();
@@ -28,7 +28,6 @@ class AppleProvisioningNodeTest extends TestCase {
$this->assertEquals('apple-provisioning.mobileconfig', $this->node->getName());
}
-
public function testSetName(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
$this->expectExceptionMessage('Renaming apple-provisioning.mobileconfig is forbidden');
@@ -55,7 +54,7 @@ class AppleProvisioningNodeTest extends TestCase {
$this->assertEquals([
'{DAV:}getcontentlength' => 42,
- '{DAV:}getlastmodified' => 'Sat, 01 Jan 2000 00:00:00 +0000',
+ '{DAV:}getlastmodified' => 'Sat, 01 Jan 2000 00:00:00 GMT',
], $this->node->getProperties([]));
}
diff --git a/apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningPluginTest.php b/apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningPluginTest.php
index dbb399ea7a6..ba44efe7421 100644
--- a/apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningPluginTest.php
+++ b/apps/dav/tests/unit/Provisioning/Apple/AppleProvisioningPluginTest.php
@@ -1,4 +1,6 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -12,40 +14,27 @@ use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
+use Sabre\DAV\Server;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
use Test\TestCase;
class AppleProvisioningPluginTest extends TestCase {
- /** @var \Sabre\DAV\Server|\PHPUnit\Framework\MockObject\MockObject */
- protected $server;
-
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- protected $userSession;
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- protected $urlGenerator;
-
- /** @var ThemingDefaults|\PHPUnit\Framework\MockObject\MockObject */
- protected $themingDefaults;
-
- /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
- protected $request;
-
- /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
- protected $l10n;
-
- /** @var \Sabre\HTTP\RequestInterface|\PHPUnit\Framework\MockObject\MockObject */
- protected $sabreRequest;
-
- /** @var \Sabre\HTTP\ResponseInterface|\PHPUnit\Framework\MockObject\MockObject */
- protected $sabreResponse;
-
- /** @var AppleProvisioningPlugin */
- protected $plugin;
+ protected Server&MockObject $server;
+ protected IUserSession&MockObject $userSession;
+ protected IURLGenerator&MockObject $urlGenerator;
+ protected ThemingDefaults&MockObject $themingDefaults;
+ protected IRequest&MockObject $request;
+ protected IL10N&MockObject $l10n;
+ protected RequestInterface&MockObject $sabreRequest;
+ protected ResponseInterface&MockObject $sabreResponse;
+ protected AppleProvisioningPlugin $plugin;
protected function setUp(): void {
parent::setUp();
- $this->server = $this->createMock(\Sabre\DAV\Server::class);
+ $this->server = $this->createMock(Server::class);
$this->userSession = $this->createMock(IUserSession::class);
$this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->themingDefaults = $this->createMock(ThemingDefaults::class);
@@ -62,12 +51,12 @@ class AppleProvisioningPluginTest extends TestCase {
}
);
- $this->sabreRequest = $this->createMock(\Sabre\HTTP\RequestInterface::class);
- $this->sabreResponse = $this->createMock(\Sabre\HTTP\ResponseInterface::class);
+ $this->sabreRequest = $this->createMock(RequestInterface::class);
+ $this->sabreResponse = $this->createMock(ResponseInterface::class);
}
public function testInitialize(): void {
- $server = $this->createMock(\Sabre\DAV\Server::class);
+ $server = $this->createMock(Server::class);
$plugin = new AppleProvisioningPlugin($this->userSession,
$this->urlGenerator, $this->themingDefaults, $this->request, $this->l10n,
@@ -149,24 +138,25 @@ class AppleProvisioningPluginTest extends TestCase {
$this->l10n->expects($this->exactly(2))
->method('t')
- ->withConsecutive(
- ['Configures a CalDAV account'],
- ['Configures a CardDAV account'],
- )
- ->willReturnOnConsecutiveCalls(
- 'LocalizedConfiguresCalDAV',
- 'LocalizedConfiguresCardDAV',
- );
+ ->willReturnMap([
+ ['Configures a CalDAV account', [], 'LocalizedConfiguresCalDAV'],
+ ['Configures a CardDAV account', [], 'LocalizedConfiguresCardDAV'],
+ ]);
$this->sabreResponse->expects($this->once())
->method('setStatus')
->with(200);
+
+ $calls = [
+ ['Content-Disposition', 'attachment; filename="userName-apple-provisioning.mobileconfig"'],
+ ['Content-Type', 'application/xml; charset=utf-8'],
+ ];
$this->sabreResponse->expects($this->exactly(2))
->method('setHeader')
- ->withConsecutive(
- ['Content-Disposition', 'attachment; filename="userName-apple-provisioning.mobileconfig"'],
- ['Content-Type', 'application/xml; charset=utf-8'],
- );
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
$this->sabreResponse->expects($this->once())
->method('setBody')
->with(<<<EOF
diff --git a/apps/dav/tests/unit/Search/ContactsSearchProviderTest.php b/apps/dav/tests/unit/Search/ContactsSearchProviderTest.php
index 0a83d238f0f..f4dc13a5c06 100644
--- a/apps/dav/tests/unit/Search/ContactsSearchProviderTest.php
+++ b/apps/dav/tests/unit/Search/ContactsSearchProviderTest.php
@@ -17,43 +17,34 @@ use OCP\IUser;
use OCP\Search\ISearchQuery;
use OCP\Search\SearchResult;
use OCP\Search\SearchResultEntry;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\VObject\Reader;
use Test\TestCase;
class ContactsSearchProviderTest extends TestCase {
-
- /** @var IAppManager|\PHPUnit\Framework\MockObject\MockObject */
- private $appManager;
-
- /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
- private $l10n;
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- private $urlGenerator;
-
- /** @var CardDavBackend|\PHPUnit\Framework\MockObject\MockObject */
- private $backend;
-
- /** @var ContactsSearchProvider */
- private $provider;
-
- private $vcardTest0 = 'BEGIN:VCARD' . PHP_EOL .
- 'VERSION:3.0' . PHP_EOL .
- 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL .
- 'UID:Test' . PHP_EOL .
- 'FN:FN of Test' . PHP_EOL .
- 'N:Test;;;;' . PHP_EOL .
- 'EMAIL:forrestgump@example.com' . PHP_EOL .
- 'END:VCARD';
-
- private $vcardTest1 = 'BEGIN:VCARD' . PHP_EOL .
- 'VERSION:3.0' . PHP_EOL .
- 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL .
- 'PHOTO;ENCODING=b;TYPE=image/jpeg:' . PHP_EOL .
- 'UID:Test2' . PHP_EOL .
- 'FN:FN of Test2' . PHP_EOL .
- 'N:Test2;;;;' . PHP_EOL .
- 'END:VCARD';
+ private IAppManager&MockObject $appManager;
+ private IL10N&MockObject $l10n;
+ private IURLGenerator&MockObject $urlGenerator;
+ private CardDavBackend&MockObject $backend;
+ private ContactsSearchProvider $provider;
+
+ private string $vcardTest0 = 'BEGIN:VCARD' . PHP_EOL
+ . 'VERSION:3.0' . PHP_EOL
+ . 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL
+ . 'UID:Test' . PHP_EOL
+ . 'FN:FN of Test' . PHP_EOL
+ . 'N:Test;;;;' . PHP_EOL
+ . 'EMAIL:forrestgump@example.com' . PHP_EOL
+ . 'END:VCARD';
+
+ private string $vcardTest1 = 'BEGIN:VCARD' . PHP_EOL
+ . 'VERSION:3.0' . PHP_EOL
+ . 'PRODID:-//Sabre//Sabre VObject 4.1.2//EN' . PHP_EOL
+ . 'PHOTO;ENCODING=b;TYPE=image/jpeg:' . PHP_EOL
+ . 'UID:Test2' . PHP_EOL
+ . 'FN:FN of Test2' . PHP_EOL
+ . 'N:Test2;;;;' . PHP_EOL
+ . 'END:VCARD';
protected function setUp(): void {
parent::setUp();
@@ -174,7 +165,7 @@ class ContactsSearchProviderTest extends TestCase {
$this->urlGenerator,
$this->backend,
])
- ->setMethods([
+ ->onlyMethods([
'getDavUrlForContact',
'getDeepLinkToContactsApp',
'generateSubline',
@@ -191,11 +182,10 @@ class ContactsSearchProviderTest extends TestCase {
->willReturn('subline');
$provider->expects($this->exactly(2))
->method('getDeepLinkToContactsApp')
- ->withConsecutive(
- ['addressbook-uri-99', 'Test'],
- ['addressbook-uri-123', 'Test2']
- )
- ->willReturn('deep-link-to-contacts');
+ ->willReturnMap([
+ ['addressbook-uri-99', 'Test', 'deep-link-to-contacts'],
+ ['addressbook-uri-123', 'Test2', 'deep-link-to-contacts'],
+ ]);
$actual = $provider->search($user, $query);
$data = $actual->jsonSerialize();
diff --git a/apps/dav/tests/unit/Search/EventsSearchProviderTest.php b/apps/dav/tests/unit/Search/EventsSearchProviderTest.php
index 0eafe0782e5..fb8d111ad26 100644
--- a/apps/dav/tests/unit/Search/EventsSearchProviderTest.php
+++ b/apps/dav/tests/unit/Search/EventsSearchProviderTest.php
@@ -18,204 +18,196 @@ use OCP\Search\IFilter;
use OCP\Search\ISearchQuery;
use OCP\Search\SearchResult;
use OCP\Search\SearchResultEntry;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\VObject\Reader;
use Test\TestCase;
class EventsSearchProviderTest extends TestCase {
- /** @var IAppManager|\PHPUnit\Framework\MockObject\MockObject */
- private $appManager;
-
- /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
- private $l10n;
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- private $urlGenerator;
-
- /** @var CalDavBackend|\PHPUnit\Framework\MockObject\MockObject */
- private $backend;
-
- /** @var EventsSearchProvider */
- private $provider;
+ private IAppManager&MockObject $appManager;
+ private IL10N&MockObject $l10n;
+ private IURLGenerator&MockObject $urlGenerator;
+ private CalDavBackend&MockObject $backend;
+ private EventsSearchProvider $provider;
// NO SUMMARY
- private $vEvent0 = 'BEGIN:VCALENDAR' . PHP_EOL .
- 'VERSION:2.0' . PHP_EOL .
- 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN' . PHP_EOL .
- 'CALSCALE:GREGORIAN' . PHP_EOL .
- 'BEGIN:VEVENT' . PHP_EOL .
- 'CREATED:20161004T144433Z' . PHP_EOL .
- 'UID:85560E76-1B0D-47E1-A735-21625767FCA4' . PHP_EOL .
- 'DTEND;VALUE=DATE:20161008' . PHP_EOL .
- 'TRANSP:TRANSPARENT' . PHP_EOL .
- 'DTSTART;VALUE=DATE:20161005' . PHP_EOL .
- 'DTSTAMP:20161004T144437Z' . PHP_EOL .
- 'SEQUENCE:0' . PHP_EOL .
- 'END:VEVENT' . PHP_EOL .
- 'END:VCALENDAR';
+ private static string $vEvent0 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN' . PHP_EOL
+ . 'CALSCALE:GREGORIAN' . PHP_EOL
+ . 'BEGIN:VEVENT' . PHP_EOL
+ . 'CREATED:20161004T144433Z' . PHP_EOL
+ . 'UID:85560E76-1B0D-47E1-A735-21625767FCA4' . PHP_EOL
+ . 'DTEND;VALUE=DATE:20161008' . PHP_EOL
+ . 'TRANSP:TRANSPARENT' . PHP_EOL
+ . 'DTSTART;VALUE=DATE:20161005' . PHP_EOL
+ . 'DTSTAMP:20161004T144437Z' . PHP_EOL
+ . 'SEQUENCE:0' . PHP_EOL
+ . 'END:VEVENT' . PHP_EOL
+ . 'END:VCALENDAR';
// TIMED SAME DAY
- private $vEvent1 = 'BEGIN:VCALENDAR' . PHP_EOL .
- 'VERSION:2.0' . PHP_EOL .
- 'PRODID:-//Tests//' . PHP_EOL .
- 'CALSCALE:GREGORIAN' . PHP_EOL .
- 'BEGIN:VTIMEZONE' . PHP_EOL .
- 'TZID:Europe/Berlin' . PHP_EOL .
- 'BEGIN:DAYLIGHT' . PHP_EOL .
- 'TZOFFSETFROM:+0100' . PHP_EOL .
- 'RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' . PHP_EOL .
- 'DTSTART:19810329T020000' . PHP_EOL .
- 'TZNAME:GMT+2' . PHP_EOL .
- 'TZOFFSETTO:+0200' . PHP_EOL .
- 'END:DAYLIGHT' . PHP_EOL .
- 'BEGIN:STANDARD' . PHP_EOL .
- 'TZOFFSETFROM:+0200' . PHP_EOL .
- 'RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU' . PHP_EOL .
- 'DTSTART:19961027T030000' . PHP_EOL .
- 'TZNAME:GMT+1' . PHP_EOL .
- 'TZOFFSETTO:+0100' . PHP_EOL .
- 'END:STANDARD' . PHP_EOL .
- 'END:VTIMEZONE' . PHP_EOL .
- 'BEGIN:VEVENT' . PHP_EOL .
- 'CREATED:20160809T163629Z' . PHP_EOL .
- 'UID:0AD16F58-01B3-463B-A215-FD09FC729A02' . PHP_EOL .
- 'DTEND;TZID=Europe/Berlin:20160816T100000' . PHP_EOL .
- 'TRANSP:OPAQUE' . PHP_EOL .
- 'SUMMARY:Test Europe Berlin' . PHP_EOL .
- 'DTSTART;TZID=Europe/Berlin:20160816T090000' . PHP_EOL .
- 'DTSTAMP:20160809T163632Z' . PHP_EOL .
- 'SEQUENCE:0' . PHP_EOL .
- 'END:VEVENT' . PHP_EOL .
- 'END:VCALENDAR';
+ private static string $vEvent1 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'PRODID:-//Tests//' . PHP_EOL
+ . 'CALSCALE:GREGORIAN' . PHP_EOL
+ . 'BEGIN:VTIMEZONE' . PHP_EOL
+ . 'TZID:Europe/Berlin' . PHP_EOL
+ . 'BEGIN:DAYLIGHT' . PHP_EOL
+ . 'TZOFFSETFROM:+0100' . PHP_EOL
+ . 'RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' . PHP_EOL
+ . 'DTSTART:19810329T020000' . PHP_EOL
+ . 'TZNAME:GMT+2' . PHP_EOL
+ . 'TZOFFSETTO:+0200' . PHP_EOL
+ . 'END:DAYLIGHT' . PHP_EOL
+ . 'BEGIN:STANDARD' . PHP_EOL
+ . 'TZOFFSETFROM:+0200' . PHP_EOL
+ . 'RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU' . PHP_EOL
+ . 'DTSTART:19961027T030000' . PHP_EOL
+ . 'TZNAME:GMT+1' . PHP_EOL
+ . 'TZOFFSETTO:+0100' . PHP_EOL
+ . 'END:STANDARD' . PHP_EOL
+ . 'END:VTIMEZONE' . PHP_EOL
+ . 'BEGIN:VEVENT' . PHP_EOL
+ . 'CREATED:20160809T163629Z' . PHP_EOL
+ . 'UID:0AD16F58-01B3-463B-A215-FD09FC729A02' . PHP_EOL
+ . 'DTEND;TZID=Europe/Berlin:20160816T100000' . PHP_EOL
+ . 'TRANSP:OPAQUE' . PHP_EOL
+ . 'SUMMARY:Test Europe Berlin' . PHP_EOL
+ . 'DTSTART;TZID=Europe/Berlin:20160816T090000' . PHP_EOL
+ . 'DTSTAMP:20160809T163632Z' . PHP_EOL
+ . 'SEQUENCE:0' . PHP_EOL
+ . 'END:VEVENT' . PHP_EOL
+ . 'END:VCALENDAR';
// TIMED DIFFERENT DAY
- private $vEvent2 = 'BEGIN:VCALENDAR' . PHP_EOL .
- 'VERSION:2.0' . PHP_EOL .
- 'PRODID:-//Tests//' . PHP_EOL .
- 'CALSCALE:GREGORIAN' . PHP_EOL .
- 'BEGIN:VTIMEZONE' . PHP_EOL .
- 'TZID:Europe/Berlin' . PHP_EOL .
- 'BEGIN:DAYLIGHT' . PHP_EOL .
- 'TZOFFSETFROM:+0100' . PHP_EOL .
- 'RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' . PHP_EOL .
- 'DTSTART:19810329T020000' . PHP_EOL .
- 'TZNAME:GMT+2' . PHP_EOL .
- 'TZOFFSETTO:+0200' . PHP_EOL .
- 'END:DAYLIGHT' . PHP_EOL .
- 'BEGIN:STANDARD' . PHP_EOL .
- 'TZOFFSETFROM:+0200' . PHP_EOL .
- 'RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU' . PHP_EOL .
- 'DTSTART:19961027T030000' . PHP_EOL .
- 'TZNAME:GMT+1' . PHP_EOL .
- 'TZOFFSETTO:+0100' . PHP_EOL .
- 'END:STANDARD' . PHP_EOL .
- 'END:VTIMEZONE' . PHP_EOL .
- 'BEGIN:VEVENT' . PHP_EOL .
- 'CREATED:20160809T163629Z' . PHP_EOL .
- 'UID:0AD16F58-01B3-463B-A215-FD09FC729A02' . PHP_EOL .
- 'DTEND;TZID=Europe/Berlin:20160817T100000' . PHP_EOL .
- 'TRANSP:OPAQUE' . PHP_EOL .
- 'SUMMARY:Test Europe Berlin' . PHP_EOL .
- 'DTSTART;TZID=Europe/Berlin:20160816T090000' . PHP_EOL .
- 'DTSTAMP:20160809T163632Z' . PHP_EOL .
- 'SEQUENCE:0' . PHP_EOL .
- 'END:VEVENT' . PHP_EOL .
- 'END:VCALENDAR';
+ private static string $vEvent2 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'PRODID:-//Tests//' . PHP_EOL
+ . 'CALSCALE:GREGORIAN' . PHP_EOL
+ . 'BEGIN:VTIMEZONE' . PHP_EOL
+ . 'TZID:Europe/Berlin' . PHP_EOL
+ . 'BEGIN:DAYLIGHT' . PHP_EOL
+ . 'TZOFFSETFROM:+0100' . PHP_EOL
+ . 'RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' . PHP_EOL
+ . 'DTSTART:19810329T020000' . PHP_EOL
+ . 'TZNAME:GMT+2' . PHP_EOL
+ . 'TZOFFSETTO:+0200' . PHP_EOL
+ . 'END:DAYLIGHT' . PHP_EOL
+ . 'BEGIN:STANDARD' . PHP_EOL
+ . 'TZOFFSETFROM:+0200' . PHP_EOL
+ . 'RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU' . PHP_EOL
+ . 'DTSTART:19961027T030000' . PHP_EOL
+ . 'TZNAME:GMT+1' . PHP_EOL
+ . 'TZOFFSETTO:+0100' . PHP_EOL
+ . 'END:STANDARD' . PHP_EOL
+ . 'END:VTIMEZONE' . PHP_EOL
+ . 'BEGIN:VEVENT' . PHP_EOL
+ . 'CREATED:20160809T163629Z' . PHP_EOL
+ . 'UID:0AD16F58-01B3-463B-A215-FD09FC729A02' . PHP_EOL
+ . 'DTEND;TZID=Europe/Berlin:20160817T100000' . PHP_EOL
+ . 'TRANSP:OPAQUE' . PHP_EOL
+ . 'SUMMARY:Test Europe Berlin' . PHP_EOL
+ . 'DTSTART;TZID=Europe/Berlin:20160816T090000' . PHP_EOL
+ . 'DTSTAMP:20160809T163632Z' . PHP_EOL
+ . 'SEQUENCE:0' . PHP_EOL
+ . 'END:VEVENT' . PHP_EOL
+ . 'END:VCALENDAR';
// ALL-DAY ONE-DAY
- private $vEvent3 = 'BEGIN:VCALENDAR' . PHP_EOL .
- 'VERSION:2.0' . PHP_EOL .
- 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN' . PHP_EOL .
- 'CALSCALE:GREGORIAN' . PHP_EOL .
- 'BEGIN:VEVENT' . PHP_EOL .
- 'CREATED:20161004T144433Z' . PHP_EOL .
- 'UID:85560E76-1B0D-47E1-A735-21625767FCA4' . PHP_EOL .
- 'DTEND;VALUE=DATE:20161006' . PHP_EOL .
- 'TRANSP:TRANSPARENT' . PHP_EOL .
- 'DTSTART;VALUE=DATE:20161005' . PHP_EOL .
- 'DTSTAMP:20161004T144437Z' . PHP_EOL .
- 'SEQUENCE:0' . PHP_EOL .
- 'END:VEVENT' . PHP_EOL .
- 'END:VCALENDAR';
+ private static string $vEvent3 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN' . PHP_EOL
+ . 'CALSCALE:GREGORIAN' . PHP_EOL
+ . 'BEGIN:VEVENT' . PHP_EOL
+ . 'CREATED:20161004T144433Z' . PHP_EOL
+ . 'UID:85560E76-1B0D-47E1-A735-21625767FCA4' . PHP_EOL
+ . 'DTEND;VALUE=DATE:20161006' . PHP_EOL
+ . 'TRANSP:TRANSPARENT' . PHP_EOL
+ . 'DTSTART;VALUE=DATE:20161005' . PHP_EOL
+ . 'DTSTAMP:20161004T144437Z' . PHP_EOL
+ . 'SEQUENCE:0' . PHP_EOL
+ . 'END:VEVENT' . PHP_EOL
+ . 'END:VCALENDAR';
// ALL-DAY MULTIPLE DAYS
- private $vEvent4 = 'BEGIN:VCALENDAR' . PHP_EOL .
- 'VERSION:2.0' . PHP_EOL .
- 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN' . PHP_EOL .
- 'CALSCALE:GREGORIAN' . PHP_EOL .
- 'BEGIN:VEVENT' . PHP_EOL .
- 'CREATED:20161004T144433Z' . PHP_EOL .
- 'UID:85560E76-1B0D-47E1-A735-21625767FCA4' . PHP_EOL .
- 'DTEND;VALUE=DATE:20161008' . PHP_EOL .
- 'TRANSP:TRANSPARENT' . PHP_EOL .
- 'DTSTART;VALUE=DATE:20161005' . PHP_EOL .
- 'DTSTAMP:20161004T144437Z' . PHP_EOL .
- 'SEQUENCE:0' . PHP_EOL .
- 'END:VEVENT' . PHP_EOL .
- 'END:VCALENDAR';
+ private static string $vEvent4 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN' . PHP_EOL
+ . 'CALSCALE:GREGORIAN' . PHP_EOL
+ . 'BEGIN:VEVENT' . PHP_EOL
+ . 'CREATED:20161004T144433Z' . PHP_EOL
+ . 'UID:85560E76-1B0D-47E1-A735-21625767FCA4' . PHP_EOL
+ . 'DTEND;VALUE=DATE:20161008' . PHP_EOL
+ . 'TRANSP:TRANSPARENT' . PHP_EOL
+ . 'DTSTART;VALUE=DATE:20161005' . PHP_EOL
+ . 'DTSTAMP:20161004T144437Z' . PHP_EOL
+ . 'SEQUENCE:0' . PHP_EOL
+ . 'END:VEVENT' . PHP_EOL
+ . 'END:VCALENDAR';
// DURATION
- private $vEvent5 = 'BEGIN:VCALENDAR' . PHP_EOL .
- 'VERSION:2.0' . PHP_EOL .
- 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN' . PHP_EOL .
- 'CALSCALE:GREGORIAN' . PHP_EOL .
- 'BEGIN:VEVENT' . PHP_EOL .
- 'CREATED:20161004T144433Z' . PHP_EOL .
- 'UID:85560E76-1B0D-47E1-A735-21625767FCA4' . PHP_EOL .
- 'DURATION:P5D' . PHP_EOL .
- 'TRANSP:TRANSPARENT' . PHP_EOL .
- 'DTSTART;VALUE=DATE:20161005' . PHP_EOL .
- 'DTSTAMP:20161004T144437Z' . PHP_EOL .
- 'SEQUENCE:0' . PHP_EOL .
- 'END:VEVENT' . PHP_EOL .
- 'END:VCALENDAR';
+ private static string $vEvent5 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN' . PHP_EOL
+ . 'CALSCALE:GREGORIAN' . PHP_EOL
+ . 'BEGIN:VEVENT' . PHP_EOL
+ . 'CREATED:20161004T144433Z' . PHP_EOL
+ . 'UID:85560E76-1B0D-47E1-A735-21625767FCA4' . PHP_EOL
+ . 'DURATION:P5D' . PHP_EOL
+ . 'TRANSP:TRANSPARENT' . PHP_EOL
+ . 'DTSTART;VALUE=DATE:20161005' . PHP_EOL
+ . 'DTSTAMP:20161004T144437Z' . PHP_EOL
+ . 'SEQUENCE:0' . PHP_EOL
+ . 'END:VEVENT' . PHP_EOL
+ . 'END:VCALENDAR';
// NO DTEND - DATE
- private $vEvent6 = 'BEGIN:VCALENDAR' . PHP_EOL .
- 'VERSION:2.0' . PHP_EOL .
- 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN' . PHP_EOL .
- 'CALSCALE:GREGORIAN' . PHP_EOL .
- 'BEGIN:VEVENT' . PHP_EOL .
- 'CREATED:20161004T144433Z' . PHP_EOL .
- 'UID:85560E76-1B0D-47E1-A735-21625767FCA4' . PHP_EOL .
- 'TRANSP:TRANSPARENT' . PHP_EOL .
- 'DTSTART;VALUE=DATE:20161005' . PHP_EOL .
- 'DTSTAMP:20161004T144437Z' . PHP_EOL .
- 'SEQUENCE:0' . PHP_EOL .
- 'END:VEVENT' . PHP_EOL .
- 'END:VCALENDAR';
+ private static string $vEvent6 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'PRODID:-//Apple Inc.//Mac OS X 10.11.6//EN' . PHP_EOL
+ . 'CALSCALE:GREGORIAN' . PHP_EOL
+ . 'BEGIN:VEVENT' . PHP_EOL
+ . 'CREATED:20161004T144433Z' . PHP_EOL
+ . 'UID:85560E76-1B0D-47E1-A735-21625767FCA4' . PHP_EOL
+ . 'TRANSP:TRANSPARENT' . PHP_EOL
+ . 'DTSTART;VALUE=DATE:20161005' . PHP_EOL
+ . 'DTSTAMP:20161004T144437Z' . PHP_EOL
+ . 'SEQUENCE:0' . PHP_EOL
+ . 'END:VEVENT' . PHP_EOL
+ . 'END:VCALENDAR';
// NO DTEND - DATE-TIME
- private $vEvent7 = 'BEGIN:VCALENDAR' . PHP_EOL .
- 'VERSION:2.0' . PHP_EOL .
- 'PRODID:-//Tests//' . PHP_EOL .
- 'CALSCALE:GREGORIAN' . PHP_EOL .
- 'BEGIN:VTIMEZONE' . PHP_EOL .
- 'TZID:Europe/Berlin' . PHP_EOL .
- 'BEGIN:DAYLIGHT' . PHP_EOL .
- 'TZOFFSETFROM:+0100' . PHP_EOL .
- 'RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' . PHP_EOL .
- 'DTSTART:19810329T020000' . PHP_EOL .
- 'TZNAME:GMT+2' . PHP_EOL .
- 'TZOFFSETTO:+0200' . PHP_EOL .
- 'END:DAYLIGHT' . PHP_EOL .
- 'BEGIN:STANDARD' . PHP_EOL .
- 'TZOFFSETFROM:+0200' . PHP_EOL .
- 'RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU' . PHP_EOL .
- 'DTSTART:19961027T030000' . PHP_EOL .
- 'TZNAME:GMT+1' . PHP_EOL .
- 'TZOFFSETTO:+0100' . PHP_EOL .
- 'END:STANDARD' . PHP_EOL .
- 'END:VTIMEZONE' . PHP_EOL .
- 'BEGIN:VEVENT' . PHP_EOL .
- 'CREATED:20160809T163629Z' . PHP_EOL .
- 'UID:0AD16F58-01B3-463B-A215-FD09FC729A02' . PHP_EOL .
- 'TRANSP:OPAQUE' . PHP_EOL .
- 'SUMMARY:Test Europe Berlin' . PHP_EOL .
- 'DTSTART;TZID=Europe/Berlin:20160816T090000' . PHP_EOL .
- 'DTSTAMP:20160809T163632Z' . PHP_EOL .
- 'SEQUENCE:0' . PHP_EOL .
- 'END:VEVENT' . PHP_EOL .
- 'END:VCALENDAR';
+ private static string $vEvent7 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'PRODID:-//Tests//' . PHP_EOL
+ . 'CALSCALE:GREGORIAN' . PHP_EOL
+ . 'BEGIN:VTIMEZONE' . PHP_EOL
+ . 'TZID:Europe/Berlin' . PHP_EOL
+ . 'BEGIN:DAYLIGHT' . PHP_EOL
+ . 'TZOFFSETFROM:+0100' . PHP_EOL
+ . 'RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU' . PHP_EOL
+ . 'DTSTART:19810329T020000' . PHP_EOL
+ . 'TZNAME:GMT+2' . PHP_EOL
+ . 'TZOFFSETTO:+0200' . PHP_EOL
+ . 'END:DAYLIGHT' . PHP_EOL
+ . 'BEGIN:STANDARD' . PHP_EOL
+ . 'TZOFFSETFROM:+0200' . PHP_EOL
+ . 'RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU' . PHP_EOL
+ . 'DTSTART:19961027T030000' . PHP_EOL
+ . 'TZNAME:GMT+1' . PHP_EOL
+ . 'TZOFFSETTO:+0100' . PHP_EOL
+ . 'END:STANDARD' . PHP_EOL
+ . 'END:VTIMEZONE' . PHP_EOL
+ . 'BEGIN:VEVENT' . PHP_EOL
+ . 'CREATED:20160809T163629Z' . PHP_EOL
+ . 'UID:0AD16F58-01B3-463B-A215-FD09FC729A02' . PHP_EOL
+ . 'TRANSP:OPAQUE' . PHP_EOL
+ . 'SUMMARY:Test Europe Berlin' . PHP_EOL
+ . 'DTSTART;TZID=Europe/Berlin:20160816T090000' . PHP_EOL
+ . 'DTSTAMP:20160809T163632Z' . PHP_EOL
+ . 'SEQUENCE:0' . PHP_EOL
+ . 'END:VEVENT' . PHP_EOL
+ . 'END:VCALENDAR';
protected function setUp(): void {
parent::setUp();
@@ -327,19 +319,19 @@ class EventsSearchProviderTest extends TestCase {
'calendarid' => 99,
'calendartype' => CalDavBackend::CALENDAR_TYPE_CALENDAR,
'uri' => 'event0.ics',
- 'calendardata' => $this->vEvent0,
+ 'calendardata' => self::$vEvent0,
],
[
'calendarid' => 123,
'calendartype' => CalDavBackend::CALENDAR_TYPE_CALENDAR,
'uri' => 'event1.ics',
- 'calendardata' => $this->vEvent1,
+ 'calendardata' => self::$vEvent1,
],
[
'calendarid' => 1337,
'calendartype' => CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION,
'uri' => 'event2.ics',
- 'calendardata' => $this->vEvent2,
+ 'calendardata' => self::$vEvent2,
]
]);
@@ -350,7 +342,7 @@ class EventsSearchProviderTest extends TestCase {
$this->urlGenerator,
$this->backend,
])
- ->setMethods([
+ ->onlyMethods([
'getDeepLinkToCalendarApp',
'generateSubline',
])
@@ -361,12 +353,11 @@ class EventsSearchProviderTest extends TestCase {
->willReturn('subline');
$provider->expects($this->exactly(3))
->method('getDeepLinkToCalendarApp')
- ->withConsecutive(
- ['principals/users/john.doe', 'calendar-uri-99', 'event0.ics'],
- ['principals/users/john.doe', 'calendar-uri-123', 'event1.ics'],
- ['principals/users/john.doe', 'subscription-uri-1337', 'event2.ics']
- )
- ->willReturn('deep-link-to-calendar');
+ ->willReturnMap([
+ ['principals/users/john.doe', 'calendar-uri-99', 'event0.ics', 'deep-link-to-calendar'],
+ ['principals/users/john.doe', 'calendar-uri-123', 'event1.ics', 'deep-link-to-calendar'],
+ ['principals/users/john.doe', 'subscription-uri-1337', 'event2.ics', 'deep-link-to-calendar']
+ ]);
$actual = $provider->search($user, $query);
$data = $actual->jsonSerialize();
@@ -428,9 +419,6 @@ class EventsSearchProviderTest extends TestCase {
}
/**
- * @param string $ics
- * @param string $expectedSubline
- *
* @dataProvider generateSublineDataProvider
*/
public function testGenerateSubline(string $ics, string $expectedSubline): void {
@@ -450,15 +438,15 @@ class EventsSearchProviderTest extends TestCase {
$this->assertEquals($expectedSubline, $actual);
}
- public function generateSublineDataProvider(): array {
+ public static function generateSublineDataProvider(): array {
return [
- [$this->vEvent1, '08-16 09:00 - 10:00'],
- [$this->vEvent2, '08-16 09:00 - 08-17 10:00'],
- [$this->vEvent3, '10-05'],
- [$this->vEvent4, '10-05 - 10-07'],
- [$this->vEvent5, '10-05 - 10-09'],
- [$this->vEvent6, '10-05'],
- [$this->vEvent7, '08-16 09:00 - 09:00'],
+ [self::$vEvent1, '08-16 09:00 - 10:00'],
+ [self::$vEvent2, '08-16 09:00 - 08-17 10:00'],
+ [self::$vEvent3, '10-05'],
+ [self::$vEvent4, '10-05 - 10-07'],
+ [self::$vEvent5, '10-05 - 10-09'],
+ [self::$vEvent6, '10-05'],
+ [self::$vEvent7, '08-16 09:00 - 09:00'],
];
}
}
diff --git a/apps/dav/tests/unit/Search/TasksSearchProviderTest.php b/apps/dav/tests/unit/Search/TasksSearchProviderTest.php
index de4e29058da..972db0b98ba 100644
--- a/apps/dav/tests/unit/Search/TasksSearchProviderTest.php
+++ b/apps/dav/tests/unit/Search/TasksSearchProviderTest.php
@@ -17,89 +17,80 @@ use OCP\IUser;
use OCP\Search\ISearchQuery;
use OCP\Search\SearchResult;
use OCP\Search\SearchResultEntry;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\VObject\Reader;
use Test\TestCase;
class TasksSearchProviderTest extends TestCase {
-
- /** @var IAppManager|\PHPUnit\Framework\MockObject\MockObject */
- private $appManager;
-
- /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
- private $l10n;
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- private $urlGenerator;
-
- /** @var CalDavBackend|\PHPUnit\Framework\MockObject\MockObject */
- private $backend;
-
- /** @var TasksSearchProvider */
- private $provider;
+ private IAppManager&MockObject $appManager;
+ private IL10N&MockObject $l10n;
+ private IURLGenerator&MockObject $urlGenerator;
+ private CalDavBackend&MockObject $backend;
+ private TasksSearchProvider $provider;
// NO DUE NOR COMPLETED NOR SUMMARY
- private $vTodo0 = 'BEGIN:VCALENDAR' . PHP_EOL .
- 'PRODID:TEST' . PHP_EOL .
- 'VERSION:2.0' . PHP_EOL .
- 'BEGIN:VTODO' . PHP_EOL .
- 'UID:20070313T123432Z-456553@example.com' . PHP_EOL .
- 'DTSTAMP:20070313T123432Z' . PHP_EOL .
- 'STATUS:NEEDS-ACTION' . PHP_EOL .
- 'END:VTODO' . PHP_EOL .
- 'END:VCALENDAR';
+ private static string $vTodo0 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'PRODID:TEST' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'BEGIN:VTODO' . PHP_EOL
+ . 'UID:20070313T123432Z-456553@example.com' . PHP_EOL
+ . 'DTSTAMP:20070313T123432Z' . PHP_EOL
+ . 'STATUS:NEEDS-ACTION' . PHP_EOL
+ . 'END:VTODO' . PHP_EOL
+ . 'END:VCALENDAR';
// DUE AND COMPLETED
- private $vTodo1 = 'BEGIN:VCALENDAR' . PHP_EOL .
- 'PRODID:TEST' . PHP_EOL .
- 'VERSION:2.0' . PHP_EOL .
- 'BEGIN:VTODO' . PHP_EOL .
- 'UID:20070313T123432Z-456553@example.com' . PHP_EOL .
- 'DTSTAMP:20070313T123432Z' . PHP_EOL .
- 'COMPLETED:20070707T100000Z' . PHP_EOL .
- 'DUE;VALUE=DATE:20070501' . PHP_EOL .
- 'SUMMARY:Task title' . PHP_EOL .
- 'STATUS:NEEDS-ACTION' . PHP_EOL .
- 'END:VTODO' . PHP_EOL .
- 'END:VCALENDAR';
+ private static string $vTodo1 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'PRODID:TEST' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'BEGIN:VTODO' . PHP_EOL
+ . 'UID:20070313T123432Z-456553@example.com' . PHP_EOL
+ . 'DTSTAMP:20070313T123432Z' . PHP_EOL
+ . 'COMPLETED:20070707T100000Z' . PHP_EOL
+ . 'DUE;VALUE=DATE:20070501' . PHP_EOL
+ . 'SUMMARY:Task title' . PHP_EOL
+ . 'STATUS:NEEDS-ACTION' . PHP_EOL
+ . 'END:VTODO' . PHP_EOL
+ . 'END:VCALENDAR';
// COMPLETED ONLY
- private $vTodo2 = 'BEGIN:VCALENDAR' . PHP_EOL .
- 'PRODID:TEST' . PHP_EOL .
- 'VERSION:2.0' . PHP_EOL .
- 'BEGIN:VTODO' . PHP_EOL .
- 'UID:20070313T123432Z-456553@example.com' . PHP_EOL .
- 'DTSTAMP:20070313T123432Z' . PHP_EOL .
- 'COMPLETED:20070707T100000Z' . PHP_EOL .
- 'SUMMARY:Task title' . PHP_EOL .
- 'STATUS:NEEDS-ACTION' . PHP_EOL .
- 'END:VTODO' . PHP_EOL .
- 'END:VCALENDAR';
+ private static string $vTodo2 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'PRODID:TEST' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'BEGIN:VTODO' . PHP_EOL
+ . 'UID:20070313T123432Z-456553@example.com' . PHP_EOL
+ . 'DTSTAMP:20070313T123432Z' . PHP_EOL
+ . 'COMPLETED:20070707T100000Z' . PHP_EOL
+ . 'SUMMARY:Task title' . PHP_EOL
+ . 'STATUS:NEEDS-ACTION' . PHP_EOL
+ . 'END:VTODO' . PHP_EOL
+ . 'END:VCALENDAR';
// DUE DATE
- private $vTodo3 = 'BEGIN:VCALENDAR' . PHP_EOL .
- 'PRODID:TEST' . PHP_EOL .
- 'VERSION:2.0' . PHP_EOL .
- 'BEGIN:VTODO' . PHP_EOL .
- 'UID:20070313T123432Z-456553@example.com' . PHP_EOL .
- 'DTSTAMP:20070313T123432Z' . PHP_EOL .
- 'DUE;VALUE=DATE:20070501' . PHP_EOL .
- 'SUMMARY:Task title' . PHP_EOL .
- 'STATUS:NEEDS-ACTION' . PHP_EOL .
- 'END:VTODO' . PHP_EOL .
- 'END:VCALENDAR';
+ private static string $vTodo3 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'PRODID:TEST' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'BEGIN:VTODO' . PHP_EOL
+ . 'UID:20070313T123432Z-456553@example.com' . PHP_EOL
+ . 'DTSTAMP:20070313T123432Z' . PHP_EOL
+ . 'DUE;VALUE=DATE:20070501' . PHP_EOL
+ . 'SUMMARY:Task title' . PHP_EOL
+ . 'STATUS:NEEDS-ACTION' . PHP_EOL
+ . 'END:VTODO' . PHP_EOL
+ . 'END:VCALENDAR';
// DUE DATETIME
- private $vTodo4 = 'BEGIN:VCALENDAR' . PHP_EOL .
- 'PRODID:TEST' . PHP_EOL .
- 'VERSION:2.0' . PHP_EOL .
- 'BEGIN:VTODO' . PHP_EOL .
- 'UID:20070313T123432Z-456553@example.com' . PHP_EOL .
- 'DTSTAMP:20070313T123432Z' . PHP_EOL .
- 'DUE:20070709T130000Z' . PHP_EOL .
- 'SUMMARY:Task title' . PHP_EOL .
- 'STATUS:NEEDS-ACTION' . PHP_EOL .
- 'END:VTODO' . PHP_EOL .
- 'END:VCALENDAR';
+ private static string $vTodo4 = 'BEGIN:VCALENDAR' . PHP_EOL
+ . 'PRODID:TEST' . PHP_EOL
+ . 'VERSION:2.0' . PHP_EOL
+ . 'BEGIN:VTODO' . PHP_EOL
+ . 'UID:20070313T123432Z-456553@example.com' . PHP_EOL
+ . 'DTSTAMP:20070313T123432Z' . PHP_EOL
+ . 'DUE:20070709T130000Z' . PHP_EOL
+ . 'SUMMARY:Task title' . PHP_EOL
+ . 'STATUS:NEEDS-ACTION' . PHP_EOL
+ . 'END:VTODO' . PHP_EOL
+ . 'END:VCALENDAR';
protected function setUp(): void {
parent::setUp();
@@ -204,19 +195,19 @@ class TasksSearchProviderTest extends TestCase {
'calendarid' => 99,
'calendartype' => CalDavBackend::CALENDAR_TYPE_CALENDAR,
'uri' => 'todo0.ics',
- 'calendardata' => $this->vTodo0,
+ 'calendardata' => self::$vTodo0,
],
[
'calendarid' => 123,
'calendartype' => CalDavBackend::CALENDAR_TYPE_CALENDAR,
'uri' => 'todo1.ics',
- 'calendardata' => $this->vTodo1,
+ 'calendardata' => self::$vTodo1,
],
[
'calendarid' => 1337,
'calendartype' => CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION,
'uri' => 'todo2.ics',
- 'calendardata' => $this->vTodo2,
+ 'calendardata' => self::$vTodo2,
]
]);
@@ -227,7 +218,7 @@ class TasksSearchProviderTest extends TestCase {
$this->urlGenerator,
$this->backend,
])
- ->setMethods([
+ ->onlyMethods([
'getDeepLinkToTasksApp',
'generateSubline',
])
@@ -238,12 +229,11 @@ class TasksSearchProviderTest extends TestCase {
->willReturn('subline');
$provider->expects($this->exactly(3))
->method('getDeepLinkToTasksApp')
- ->withConsecutive(
- ['calendar-uri-99', 'todo0.ics'],
- ['calendar-uri-123', 'todo1.ics'],
- ['subscription-uri-1337', 'todo2.ics']
- )
- ->willReturn('deep-link-to-tasks');
+ ->willReturnMap([
+ ['calendar-uri-99', 'todo0.ics', 'deep-link-to-tasks'],
+ ['calendar-uri-123', 'todo1.ics', 'deep-link-to-tasks'],
+ ['subscription-uri-1337', 'todo2.ics', 'deep-link-to-tasks']
+ ]);
$actual = $provider->search($user, $query);
$data = $actual->jsonSerialize();
@@ -300,9 +290,6 @@ class TasksSearchProviderTest extends TestCase {
}
/**
- * @param string $ics
- * @param string $expectedSubline
- *
* @dataProvider generateSublineDataProvider
*/
public function testGenerateSubline(string $ics, string $expectedSubline): void {
@@ -310,19 +297,19 @@ class TasksSearchProviderTest extends TestCase {
$taskComponent = $vCalendar->VTODO;
$this->l10n->method('t')->willReturnArgument(0);
- $this->l10n->method('l')->willReturnArgument('');
+ $this->l10n->method('l')->willReturnArgument(0);
$actual = self::invokePrivate($this->provider, 'generateSubline', [$taskComponent]);
$this->assertEquals($expectedSubline, $actual);
}
- public function generateSublineDataProvider(): array {
+ public static function generateSublineDataProvider(): array {
return [
- [$this->vTodo0, ''],
- [$this->vTodo1, 'Completed on %s'],
- [$this->vTodo2, 'Completed on %s'],
- [$this->vTodo3, 'Due on %s'],
- [$this->vTodo4, 'Due on %s by %s'],
+ [self::$vTodo0, ''],
+ [self::$vTodo1, 'Completed on %s'],
+ [self::$vTodo2, 'Completed on %s'],
+ [self::$vTodo3, 'Due on %s'],
+ [self::$vTodo4, 'Due on %s by %s'],
];
}
}
diff --git a/apps/dav/tests/unit/ServerTest.php b/apps/dav/tests/unit/ServerTest.php
index 16e0a5b80aa..0baef015056 100644
--- a/apps/dav/tests/unit/ServerTest.php
+++ b/apps/dav/tests/unit/ServerTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -22,7 +23,7 @@ class ServerTest extends \Test\TestCase {
/**
* @dataProvider providesUris
*/
- public function test($uri, array $plugins): void {
+ public function test(string $uri, array $plugins): void {
/** @var IRequest | \PHPUnit\Framework\MockObject\MockObject $r */
$r = $this->createMock(IRequest::class);
$r->expects($this->any())->method('getRequestUri')->willReturn($uri);
@@ -33,7 +34,7 @@ class ServerTest extends \Test\TestCase {
$this->assertNotNull($s->server->getPlugin($plugin));
}
}
- public function providesUris() {
+ public static function providesUris(): array {
return [
'principals' => ['principals/users/admin', ['caldav', 'oc-resource-sharing', 'carddav']],
'calendars' => ['calendars/admin', ['caldav', 'oc-resource-sharing']],
diff --git a/apps/dav/tests/unit/Service/AbsenceServiceTest.php b/apps/dav/tests/unit/Service/AbsenceServiceTest.php
index 5cff29a6f61..c16c715d5c2 100644
--- a/apps/dav/tests/unit/Service/AbsenceServiceTest.php
+++ b/apps/dav/tests/unit/Service/AbsenceServiceTest.php
@@ -7,7 +7,7 @@ declare(strict_types=1);
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\dav\tests\unit\Service;
+namespace OCA\DAV\Tests\unit\Service;
use DateTimeImmutable;
use DateTimeZone;
@@ -24,25 +24,16 @@ use OCP\EventDispatcher\IEventDispatcher;
use OCP\IUser;
use OCP\User\Events\OutOfOfficeChangedEvent;
use OCP\User\Events\OutOfOfficeScheduledEvent;
+use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
class AbsenceServiceTest extends TestCase {
private AbsenceService $absenceService;
-
- /** @var MockObject|AbsenceMapper */
- private $absenceMapper;
-
- /** @var MockObject|IEventDispatcher */
- private $eventDispatcher;
-
- /** @var MockObject|IJobList */
- private $jobList;
-
- /** @var MockObject|TimezoneService */
- private $timezoneService;
-
- /** @var MockObject|ITimeFactory */
- private $timeFactory;
+ private AbsenceMapper&MockObject $absenceMapper;
+ private IEventDispatcher&MockObject $eventDispatcher;
+ private IJobList&MockObject $jobList;
+ private TimezoneService&MockObject $timezoneService;
+ private ITimeFactory&MockObject $timeFactory;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dav/tests/unit/Service/DefaultContactServiceTest.php b/apps/dav/tests/unit/Service/ExampleContactServiceTest.php
index 68bbc02ed08..4c8d900ae86 100644
--- a/apps/dav/tests/unit/Service/DefaultContactServiceTest.php
+++ b/apps/dav/tests/unit/Service/ExampleContactServiceTest.php
@@ -7,59 +7,63 @@ declare(strict_types=1);
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\Service;
+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 {
- private DefaultContactService $service;
- private MockObject|CardDavBackend $cardDav;
- private MockObject|IAppManager $appManager;
- private MockObject|IAppDataFactory $appDataFactory;
- private MockObject|LoggerInterface $logger;
- private MockObject|IAppConfig $config;
+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 $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,15 +80,15 @@ 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())
->method('createCard')
@@ -97,9 +101,9 @@ class DefaultContactServiceTest extends TestCase {
}),
$this->anything()
)->willReturn(null);
-
+
$this->service->createDefaultContact(123);
-
+
$vcard = \Sabre\VObject\Reader::read($capturedCardData);
$this->assertNotEquals($originalUid, $vcard->UID->getValue());
$this->assertTrue(Uuid::isValid($vcard->UID->getValue()));
@@ -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);
+ }
}
diff --git a/apps/dav/tests/unit/Service/ExampleEventServiceTest.php b/apps/dav/tests/unit/Service/ExampleEventServiceTest.php
new file mode 100644
index 00000000000..e5961e66312
--- /dev/null
+++ b/apps/dav/tests/unit/Service/ExampleEventServiceTest.php
@@ -0,0 +1,196 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\DAV\Tests\unit\Service;
+
+use OCA\DAV\CalDAV\CalDavBackend;
+use OCA\DAV\Service\ExampleEventService;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Files\IAppData;
+use OCP\Files\NotFoundException;
+use OCP\Files\SimpleFS\ISimpleFile;
+use OCP\Files\SimpleFS\ISimpleFolder;
+use OCP\IAppConfig;
+use OCP\IL10N;
+use OCP\Security\ISecureRandom;
+use PHPUnit\Framework\MockObject\MockObject;
+use Test\TestCase;
+
+class ExampleEventServiceTest extends TestCase {
+ private ExampleEventService $service;
+
+ private CalDavBackend&MockObject $calDavBackend;
+ private ISecureRandom&MockObject $random;
+ private ITimeFactory&MockObject $time;
+ private IAppData&MockObject $appData;
+ private IAppConfig&MockObject $appConfig;
+ private IL10N&MockObject $l10n;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->calDavBackend = $this->createMock(CalDavBackend::class);
+ $this->random = $this->createMock(ISecureRandom::class);
+ $this->time = $this->createMock(ITimeFactory::class);
+ $this->appData = $this->createMock(IAppData::class);
+ $this->appConfig = $this->createMock(IAppConfig::class);
+ $this->l10n = $this->createMock(IL10N::class);
+
+ $this->l10n->method('t')
+ ->willReturnArgument(0);
+
+ $this->service = new ExampleEventService(
+ $this->calDavBackend,
+ $this->random,
+ $this->time,
+ $this->appData,
+ $this->appConfig,
+ $this->l10n,
+ );
+ }
+
+ public static function provideCustomEventData(): array {
+ return [
+ [file_get_contents(__DIR__ . '/../test_fixtures/example-event.ics')],
+ [file_get_contents(__DIR__ . '/../test_fixtures/example-event-with-attendees.ics')],
+ ];
+ }
+
+ /** @dataProvider provideCustomEventData */
+ public function testCreateExampleEventWithCustomEvent($customEventIcs): void {
+ $this->appConfig->expects(self::once())
+ ->method('getValueBool')
+ ->with('dav', 'create_example_event', true)
+ ->willReturn(true);
+
+ $exampleEventFolder = $this->createMock(ISimpleFolder::class);
+ $this->appData->expects(self::once())
+ ->method('getFolder')
+ ->with('example_event')
+ ->willReturn($exampleEventFolder);
+ $exampleEventFile = $this->createMock(ISimpleFile::class);
+ $exampleEventFolder->expects(self::once())
+ ->method('getFile')
+ ->with('example_event.ics')
+ ->willReturn($exampleEventFile);
+ $exampleEventFile->expects(self::once())
+ ->method('getContent')
+ ->willReturn($customEventIcs);
+
+ $this->random->expects(self::once())
+ ->method('generate')
+ ->with(32, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
+ ->willReturn('RANDOM-UID');
+
+ $now = new \DateTimeImmutable('2025-01-21T00:00:00Z');
+ $this->time->expects(self::exactly(2))
+ ->method('now')
+ ->willReturn($now);
+
+ $expectedIcs = file_get_contents(__DIR__ . '/../test_fixtures/example-event-expected.ics');
+ $this->calDavBackend->expects(self::once())
+ ->method('createCalendarObject')
+ ->with(1000, 'RANDOM-UID.ics', $expectedIcs);
+
+ $this->service->createExampleEvent(1000);
+ }
+
+ public function testCreateExampleEventWithDefaultEvent(): void {
+ $this->appConfig->expects(self::once())
+ ->method('getValueBool')
+ ->with('dav', 'create_example_event', true)
+ ->willReturn(true);
+
+ $this->appData->expects(self::once())
+ ->method('getFolder')
+ ->with('example_event')
+ ->willThrowException(new NotFoundException());
+
+ $this->random->expects(self::once())
+ ->method('generate')
+ ->with(32, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
+ ->willReturn('RANDOM-UID');
+
+ $now = new \DateTimeImmutable('2025-01-21T00:00:00Z');
+ $this->time->expects(self::exactly(3))
+ ->method('now')
+ ->willReturn($now);
+
+ $expectedIcs = file_get_contents(__DIR__ . '/../test_fixtures/example-event-default-expected.ics');
+ $this->calDavBackend->expects(self::once())
+ ->method('createCalendarObject')
+ ->with(1000, 'RANDOM-UID.ics', $expectedIcs);
+
+ $this->service->createExampleEvent(1000);
+ }
+
+ public function testCreateExampleWhenDisabled(): void {
+ $this->appConfig->expects(self::once())
+ ->method('getValueBool')
+ ->with('dav', 'create_example_event', true)
+ ->willReturn(false);
+
+ $this->calDavBackend->expects(self::never())
+ ->method('createCalendarObject');
+
+ $this->service->createExampleEvent(1000);
+ }
+
+ /** @dataProvider provideCustomEventData */
+ public function testGetExampleEventWithCustomEvent($customEventIcs): void {
+ $exampleEventFolder = $this->createMock(ISimpleFolder::class);
+ $this->appData->expects(self::once())
+ ->method('getFolder')
+ ->with('example_event')
+ ->willReturn($exampleEventFolder);
+ $exampleEventFile = $this->createMock(ISimpleFile::class);
+ $exampleEventFolder->expects(self::once())
+ ->method('getFile')
+ ->with('example_event.ics')
+ ->willReturn($exampleEventFile);
+ $exampleEventFile->expects(self::once())
+ ->method('getContent')
+ ->willReturn($customEventIcs);
+
+ $this->random->expects(self::once())
+ ->method('generate')
+ ->with(32, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
+ ->willReturn('RANDOM-UID');
+
+ $now = new \DateTimeImmutable('2025-01-21T00:00:00Z');
+ $this->time->expects(self::exactly(2))
+ ->method('now')
+ ->willReturn($now);
+
+ $expectedIcs = file_get_contents(__DIR__ . '/../test_fixtures/example-event-expected.ics');
+ $actualIcs = $this->service->getExampleEvent()->getIcs();
+ $this->assertEquals($expectedIcs, $actualIcs);
+ }
+
+ public function testGetExampleEventWithDefault(): void {
+ $this->appData->expects(self::once())
+ ->method('getFolder')
+ ->with('example_event')
+ ->willThrowException(new NotFoundException());
+
+ $this->random->expects(self::once())
+ ->method('generate')
+ ->with(32, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
+ ->willReturn('RANDOM-UID');
+
+ $now = new \DateTimeImmutable('2025-01-21T00:00:00Z');
+ $this->time->expects(self::exactly(3))
+ ->method('now')
+ ->willReturn($now);
+
+ $expectedIcs = file_get_contents(__DIR__ . '/../test_fixtures/example-event-default-expected.ics');
+ $actualIcs = $this->service->getExampleEvent()->getIcs();
+ $this->assertEquals($expectedIcs, $actualIcs);
+ }
+}
diff --git a/apps/dav/tests/unit/Service/UpcomingEventsServiceTest.php b/apps/dav/tests/unit/Service/UpcomingEventsServiceTest.php
index ecb0268c8c2..fdfe37d8918 100644
--- a/apps/dav/tests/unit/Service/UpcomingEventsServiceTest.php
+++ b/apps/dav/tests/unit/Service/UpcomingEventsServiceTest.php
@@ -7,7 +7,7 @@ declare(strict_types=1);
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\DAV\Service;
+namespace OCA\DAV\Tests\unit\DAV\Service;
use DateTimeImmutable;
use OCA\DAV\CalDAV\UpcomingEventsService;
@@ -22,11 +22,11 @@ use PHPUnit\Framework\TestCase;
class UpcomingEventsServiceTest extends TestCase {
- private MockObject|IManager $calendarManager;
- private ITimeFactory|MockObject $timeFactory;
- private IUserManager|MockObject $userManager;
- private IAppManager|MockObject $appManager;
- private IURLGenerator|MockObject $urlGenerator;
+ private IManager&MockObject $calendarManager;
+ private ITimeFactory&MockObject $timeFactory;
+ private IUserManager&MockObject $userManager;
+ private IAppManager&MockObject $appManager;
+ private IURLGenerator&MockObject $urlGenerator;
private UpcomingEventsService $service;
protected function setUp(): void {
diff --git a/apps/dav/tests/unit/Settings/CalDAVSettingsTest.php b/apps/dav/tests/unit/Settings/CalDAVSettingsTest.php
index 9f2d2582884..df7a08d5d08 100644
--- a/apps/dav/tests/unit/Settings/CalDAVSettingsTest.php
+++ b/apps/dav/tests/unit/Settings/CalDAVSettingsTest.php
@@ -1,9 +1,11 @@
<?php
+
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace OCA\DAV\Tests\Unit\DAV\Settings;
+namespace OCA\DAV\Tests\unit\DAV\Settings;
use OCA\DAV\Settings\CalDAVSettings;
use OCP\App\IAppManager;
@@ -15,19 +17,10 @@ use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class CalDAVSettingsTest extends TestCase {
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var IInitialState|MockObject */
- private $initialState;
-
- /** @var IURLGenerator|MockObject */
- private $urlGenerator;
-
- /** @var IAppManager|MockObject */
- private $appManager;
-
+ private IConfig&MockObject $config;
+ private IInitialState&MockObject $initialState;
+ private IURLGenerator&MockObject $urlGenerator;
+ private IAppManager&MockObject $appManager;
private CalDAVSettings $settings;
protected function setUp(): void {
@@ -42,28 +35,32 @@ class CalDAVSettingsTest extends TestCase {
public function testGetForm(): void {
$this->config->method('getAppValue')
- ->withConsecutive(
- ['dav', 'sendInvitations', 'yes'],
- ['dav', 'generateBirthdayCalendar', 'yes'],
- ['dav', 'sendEventReminders', 'yes'],
- ['dav', 'sendEventRemindersToSharedUsers', 'yes'],
- ['dav', 'sendEventRemindersPush', 'yes'],
- )
- ->will($this->onConsecutiveCalls('yes', 'no', 'yes', 'yes', 'yes'));
+ ->willReturnMap([
+ ['dav', 'sendInvitations', 'yes', 'yes'],
+ ['dav', 'generateBirthdayCalendar', 'yes', 'no'],
+ ['dav', 'sendEventReminders', 'yes', 'yes'],
+ ['dav', 'sendEventRemindersToSharedUsers', 'yes', 'yes'],
+ ['dav', 'sendEventRemindersPush', 'yes', 'yes'],
+ ]);
$this->urlGenerator
->expects($this->once())
->method('linkToDocs')
->with('user-sync-calendars')
->willReturn('Some docs URL');
+
+ $calls = [
+ ['userSyncCalendarsDocUrl', 'Some docs URL'],
+ ['sendInvitations', true],
+ ['generateBirthdayCalendar', false],
+ ['sendEventReminders', true],
+ ['sendEventRemindersToSharedUsers', true],
+ ['sendEventRemindersPush', true],
+ ];
$this->initialState->method('provideInitialState')
- ->withConsecutive(
- ['userSyncCalendarsDocUrl', 'Some docs URL'],
- ['sendInvitations', true],
- ['generateBirthdayCalendar', false],
- ['sendEventReminders', true],
- ['sendEventRemindersToSharedUsers', true],
- ['sendEventRemindersPush', true],
- );
+ ->willReturnCallback(function () use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertEquals($expected, func_get_args());
+ });
$result = $this->settings->getForm();
$this->assertInstanceOf(TemplateResponse::class, $result);
@@ -88,5 +85,4 @@ class CalDAVSettingsTest extends TestCase {
public function testGetPriority(): void {
$this->assertEquals(10, $this->settings->getPriority());
}
-
}
diff --git a/apps/dav/tests/unit/SystemTag/SystemTagMappingNodeTest.php b/apps/dav/tests/unit/SystemTag/SystemTagMappingNodeTest.php
index ed830685b7a..0096b188291 100644
--- a/apps/dav/tests/unit/SystemTag/SystemTagMappingNodeTest.php
+++ b/apps/dav/tests/unit/SystemTag/SystemTagMappingNodeTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -14,30 +15,28 @@ use OCP\SystemTag\ISystemTag;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagNotFoundException;
+use PHPUnit\Framework\MockObject\MockObject;
class SystemTagMappingNodeTest extends \Test\TestCase {
- private ISystemTagManager $tagManager;
- private ISystemTagObjectMapper $tagMapper;
- private IUser $user;
+ private ISystemTagManager&MockObject $tagManager;
+ private ISystemTagObjectMapper&MockObject $tagMapper;
+ private IUser&MockObject $user;
protected function setUp(): void {
parent::setUp();
- $this->tagManager = $this->getMockBuilder(ISystemTagManager::class)
- ->getMock();
- $this->tagMapper = $this->getMockBuilder(ISystemTagObjectMapper::class)
- ->getMock();
- $this->user = $this->getMockBuilder(IUser::class)
- ->getMock();
+ $this->tagManager = $this->createMock(ISystemTagManager::class);
+ $this->tagMapper = $this->createMock(ISystemTagObjectMapper::class);
+ $this->user = $this->createMock(IUser::class);
}
public function getMappingNode($tag = null, array $writableNodeIds = []) {
if ($tag === null) {
- $tag = new SystemTag(1, 'Test', true, true);
+ $tag = new SystemTag('1', 'Test', true, true);
}
return new SystemTagMappingNode(
$tag,
- 123,
+ '123',
'files',
$this->user,
$this->tagManager,
@@ -47,7 +46,7 @@ class SystemTagMappingNodeTest extends \Test\TestCase {
}
public function testGetters(): void {
- $tag = new SystemTag(1, 'Test', true, false);
+ $tag = new SystemTag('1', 'Test', true, false);
$node = $this->getMappingNode($tag);
$this->assertEquals('1', $node->getName());
$this->assertEquals($tag, $node->getSystemTag());
@@ -93,16 +92,16 @@ class SystemTagMappingNodeTest extends \Test\TestCase {
$node->delete();
}
- public function tagNodeDeleteProviderPermissionException() {
+ public static function tagNodeDeleteProviderPermissionException(): array {
return [
[
// cannot unassign invisible tag
- new SystemTag(1, 'Original', false, true),
+ new SystemTag('1', 'Original', false, true),
'Sabre\DAV\Exception\NotFound',
],
[
// cannot unassign non-assignable tag
- new SystemTag(1, 'Original', true, false),
+ new SystemTag('1', 'Original', true, false),
'Sabre\DAV\Exception\Forbidden',
],
];
@@ -141,7 +140,7 @@ class SystemTagMappingNodeTest extends \Test\TestCase {
// assuming the tag existed at the time the node was created,
// but got deleted concurrently in the database
- $tag = new SystemTag(1, 'Test', true, true);
+ $tag = new SystemTag('1', 'Test', true, true);
$this->tagManager->expects($this->once())
->method('canUserSeeTag')
->with($tag)
diff --git a/apps/dav/tests/unit/SystemTag/SystemTagNodeTest.php b/apps/dav/tests/unit/SystemTag/SystemTagNodeTest.php
index 32ee733dce8..642cc21319b 100644
--- a/apps/dav/tests/unit/SystemTag/SystemTagNodeTest.php
+++ b/apps/dav/tests/unit/SystemTag/SystemTagNodeTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -15,39 +16,25 @@ use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagAlreadyExistsException;
use OCP\SystemTag\TagNotFoundException;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Exception\Forbidden;
class SystemTagNodeTest extends \Test\TestCase {
-
- /**
- * @var ISystemTagManager|\PHPUnit\Framework\MockObject\MockObject
- */
- private $tagManager;
-
- /**
- * @var ISystemTagObjectMapper|\PHPUnit\Framework\MockObject\MockObject
- */
- private $tagMapper;
-
- /**
- * @var IUser
- */
- private $user;
+ private ISystemTagManager&MockObject $tagManager;
+ private ISystemTagObjectMapper&MockObject $tagMapper;
+ private IUser&MockObject $user;
protected function setUp(): void {
parent::setUp();
- $this->tagManager = $this->getMockBuilder(ISystemTagManager::class)
- ->getMock();
- $this->tagMapper = $this->getMockBuilder(ISystemTagObjectMapper::class)
- ->getMock();
- $this->user = $this->getMockBuilder(IUser::class)
- ->getMock();
+ $this->tagManager = $this->createMock(ISystemTagManager::class);
+ $this->tagMapper = $this->createMock(ISystemTagObjectMapper::class);
+ $this->user = $this->createMock(IUser::class);
}
protected function getTagNode($isAdmin = true, $tag = null) {
if ($tag === null) {
- $tag = new SystemTag(1, 'Test', true, true);
+ $tag = new SystemTag('1', 'Test', true, true);
}
return new SystemTagNode(
$tag,
@@ -58,14 +45,14 @@ class SystemTagNodeTest extends \Test\TestCase {
);
}
- public function adminFlagProvider() {
+ public static function adminFlagProvider(): array {
return [[true], [false]];
}
/**
* @dataProvider adminFlagProvider
*/
- public function testGetters($isAdmin): void {
+ public function testGetters(bool $isAdmin): void {
$tag = new SystemTag('1', 'Test', true, true);
$node = $this->getTagNode($isAdmin, $tag);
$this->assertEquals('1', $node->getName());
@@ -79,24 +66,24 @@ class SystemTagNodeTest extends \Test\TestCase {
$this->getTagNode()->setName('2');
}
- public function tagNodeProvider() {
+ public static function tagNodeProvider(): array {
return [
// admin
[
true,
- new SystemTag(1, 'Original', true, true),
+ new SystemTag('1', 'Original', true, true),
['Renamed', true, true, null]
],
[
true,
- new SystemTag(1, 'Original', true, true),
+ new SystemTag('1', 'Original', true, true),
['Original', false, false, null]
],
// non-admin
[
// renaming allowed
false,
- new SystemTag(1, 'Original', true, true),
+ new SystemTag('1', 'Original', true, true),
['Rename', true, true, '0082c9']
],
];
@@ -105,7 +92,7 @@ class SystemTagNodeTest extends \Test\TestCase {
/**
* @dataProvider tagNodeProvider
*/
- public function testUpdateTag($isAdmin, ISystemTag $originalTag, $changedArgs): void {
+ public function testUpdateTag(bool $isAdmin, ISystemTag $originalTag, array $changedArgs): void {
$this->tagManager->expects($this->once())
->method('canUserSeeTag')
->with($originalTag)
@@ -121,41 +108,41 @@ class SystemTagNodeTest extends \Test\TestCase {
->update($changedArgs[0], $changedArgs[1], $changedArgs[2], $changedArgs[3]);
}
- public function tagNodeProviderPermissionException() {
+ public static function tagNodeProviderPermissionException(): array {
return [
[
// changing permissions not allowed
- new SystemTag(1, 'Original', true, true),
+ new SystemTag('1', 'Original', true, true),
['Original', false, true, ''],
'Sabre\DAV\Exception\Forbidden',
],
[
// changing permissions not allowed
- new SystemTag(1, 'Original', true, true),
+ new SystemTag('1', 'Original', true, true),
['Original', true, false, ''],
'Sabre\DAV\Exception\Forbidden',
],
[
// changing permissions not allowed
- new SystemTag(1, 'Original', true, true),
+ new SystemTag('1', 'Original', true, true),
['Original', false, false, ''],
'Sabre\DAV\Exception\Forbidden',
],
[
// changing non-assignable not allowed
- new SystemTag(1, 'Original', true, false),
+ new SystemTag('1', 'Original', true, false),
['Rename', true, false, ''],
'Sabre\DAV\Exception\Forbidden',
],
[
// changing non-assignable not allowed
- new SystemTag(1, 'Original', true, false),
+ new SystemTag('1', 'Original', true, false),
['Original', true, true, ''],
'Sabre\DAV\Exception\Forbidden',
],
[
// invisible tag does not exist
- new SystemTag(1, 'Original', false, false),
+ new SystemTag('1', 'Original', false, false),
['Rename', false, false, ''],
'Sabre\DAV\Exception\NotFound',
],
@@ -165,7 +152,7 @@ class SystemTagNodeTest extends \Test\TestCase {
/**
* @dataProvider tagNodeProviderPermissionException
*/
- public function testUpdateTagPermissionException(ISystemTag $originalTag, $changedArgs, $expectedException = null): void {
+ public function testUpdateTagPermissionException(ISystemTag $originalTag, array $changedArgs, string $expectedException): void {
$this->tagManager->expects($this->any())
->method('canUserSeeTag')
->with($originalTag)
@@ -193,7 +180,7 @@ class SystemTagNodeTest extends \Test\TestCase {
public function testUpdateTagAlreadyExists(): void {
$this->expectException(\Sabre\DAV\Exception\Conflict::class);
- $tag = new SystemTag(1, 'tag1', true, true);
+ $tag = new SystemTag('1', 'tag1', true, true);
$this->tagManager->expects($this->any())
->method('canUserSeeTag')
->with($tag)
@@ -213,7 +200,7 @@ class SystemTagNodeTest extends \Test\TestCase {
public function testUpdateTagNotFound(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
- $tag = new SystemTag(1, 'tag1', true, true);
+ $tag = new SystemTag('1', 'tag1', true, true);
$this->tagManager->expects($this->any())
->method('canUserSeeTag')
->with($tag)
@@ -232,8 +219,8 @@ class SystemTagNodeTest extends \Test\TestCase {
/**
* @dataProvider adminFlagProvider
*/
- public function testDeleteTag($isAdmin): void {
- $tag = new SystemTag(1, 'tag1', true, true);
+ public function testDeleteTag(bool $isAdmin): void {
+ $tag = new SystemTag('1', 'tag1', true, true);
$this->tagManager->expects($isAdmin ? $this->once() : $this->never())
->method('canUserSeeTag')
->with($tag)
@@ -247,16 +234,16 @@ class SystemTagNodeTest extends \Test\TestCase {
$this->getTagNode($isAdmin, $tag)->delete();
}
- public function tagNodeDeleteProviderPermissionException() {
+ public static function tagNodeDeleteProviderPermissionException(): array {
return [
[
// cannot delete invisible tag
- new SystemTag(1, 'Original', false, true),
+ new SystemTag('1', 'Original', false, true),
'Sabre\DAV\Exception\Forbidden',
],
[
// cannot delete non-assignable tag
- new SystemTag(1, 'Original', true, false),
+ new SystemTag('1', 'Original', true, false),
'Sabre\DAV\Exception\Forbidden',
],
];
@@ -265,7 +252,7 @@ class SystemTagNodeTest extends \Test\TestCase {
/**
* @dataProvider tagNodeDeleteProviderPermissionException
*/
- public function testDeleteTagPermissionException(ISystemTag $tag, $expectedException): void {
+ public function testDeleteTagPermissionException(ISystemTag $tag, string $expectedException): void {
$this->tagManager->expects($this->any())
->method('canUserSeeTag')
->with($tag)
@@ -281,7 +268,7 @@ class SystemTagNodeTest extends \Test\TestCase {
public function testDeleteTagNotFound(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
- $tag = new SystemTag(1, 'tag1', true, true);
+ $tag = new SystemTag('1', 'tag1', true, true);
$this->tagManager->expects($this->any())
->method('canUserSeeTag')
->with($tag)
diff --git a/apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php b/apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php
index ab5253147a7..a9368794cc2 100644
--- a/apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php
+++ b/apps/dav/tests/unit/SystemTag/SystemTagPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -20,6 +21,7 @@ use OCP\SystemTag\ISystemTag;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagAlreadyExistsException;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Tree;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
@@ -32,67 +34,26 @@ class SystemTagPluginTest extends \Test\TestCase {
public const CANASSIGN_PROPERTYNAME = SystemTagPlugin::CANASSIGN_PROPERTYNAME;
public const GROUPS_PROPERTYNAME = SystemTagPlugin::GROUPS_PROPERTYNAME;
- /**
- * @var \Sabre\DAV\Server
- */
- private $server;
-
- /**
- * @var \Sabre\DAV\Tree
- */
- private $tree;
-
- /**
- * @var ISystemTagManager
- */
- private $tagManager;
-
- /**
- * @var IGroupManager
- */
- private $groupManager;
-
- /**
- * @var IUserSession
- */
- private $userSession;
-
- /**
- * @var IRootFolder
- */
- private $rootFolder;
-
- /**
- * @var IUser
- */
- private $user;
-
- /**
- * @var SystemTagPlugin
- */
- private $plugin;
-
- /**
- * @var ISystemTagObjectMapper
- */
- private $tagMapper;
+ private \Sabre\DAV\Server $server;
+ private \Sabre\DAV\Tree&MockObject $tree;
+ private ISystemTagManager&MockObject $tagManager;
+ private IGroupManager&MockObject $groupManager;
+ private IUserSession&MockObject $userSession;
+ private IRootFolder&MockObject $rootFolder;
+ private IUser&MockObject $user;
+ private ISystemTagObjectMapper&MockObject $tagMapper;
+ private SystemTagPlugin $plugin;
protected function setUp(): void {
parent::setUp();
- $this->tree = $this->getMockBuilder(Tree::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->tree = $this->createMock(Tree::class);
$this->server = new \Sabre\DAV\Server($this->tree);
- $this->tagManager = $this->getMockBuilder(ISystemTagManager::class)
- ->getMock();
- $this->groupManager = $this->getMockBuilder(IGroupManager::class)
- ->getMock();
- $this->user = $this->getMockBuilder(IUser::class)
- ->getMock();
- $this->userSession = $this->getMockBuilder(IUserSession::class)
- ->getMock();
+ $this->tagManager = $this->createMock(ISystemTagManager::class);
+ $this->groupManager = $this->createMock(IGroupManager::class);
+ $this->user = $this->createMock(IUser::class);
+ $this->userSession = $this->createMock(IUserSession::class);
$this->userSession
->expects($this->any())
->method('getUser')
@@ -102,10 +63,8 @@ class SystemTagPluginTest extends \Test\TestCase {
->method('isLoggedIn')
->willReturn(true);
- $this->tagMapper = $this->getMockBuilder(ISystemTagObjectMapper::class)
- ->getMock();
- $this->rootFolder = $this->getMockBuilder(IRootFolder::class)
- ->getMock();
+ $this->tagMapper = $this->createMock(ISystemTagObjectMapper::class);
+ $this->rootFolder = $this->createMock(IRootFolder::class);
$this->plugin = new SystemTagPlugin(
$this->tagManager,
@@ -117,10 +76,10 @@ class SystemTagPluginTest extends \Test\TestCase {
$this->plugin->initialize($this->server);
}
- public function getPropertiesDataProvider() {
+ public static function getPropertiesDataProvider(): array {
return [
[
- new SystemTag(1, 'Test', true, true),
+ new SystemTag('1', 'Test', true, true),
[],
[
self::ID_PROPERTYNAME,
@@ -138,7 +97,7 @@ class SystemTagPluginTest extends \Test\TestCase {
]
],
[
- new SystemTag(1, 'Test', true, false),
+ new SystemTag('1', 'Test', true, false),
[],
[
self::ID_PROPERTYNAME,
@@ -156,7 +115,7 @@ class SystemTagPluginTest extends \Test\TestCase {
]
],
[
- new SystemTag(1, 'Test', true, false),
+ new SystemTag('1', 'Test', true, false),
['group1', 'group2'],
[
self::ID_PROPERTYNAME,
@@ -168,7 +127,7 @@ class SystemTagPluginTest extends \Test\TestCase {
]
],
[
- new SystemTag(1, 'Test', true, true),
+ new SystemTag('1', 'Test', true, true),
['group1', 'group2'],
[
self::ID_PROPERTYNAME,
@@ -186,7 +145,7 @@ class SystemTagPluginTest extends \Test\TestCase {
/**
* @dataProvider getPropertiesDataProvider
*/
- public function testGetProperties(ISystemTag $systemTag, $groups, $requestedProperties, $expectedProperties): void {
+ public function testGetProperties(ISystemTag $systemTag, array $groups, array $requestedProperties, array $expectedProperties): void {
$this->user->expects($this->any())
->method('getUID')
->willReturn('admin');
@@ -237,7 +196,7 @@ class SystemTagPluginTest extends \Test\TestCase {
public function testGetPropertiesForbidden(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
- $systemTag = new SystemTag(1, 'Test', true, false);
+ $systemTag = new SystemTag('1', 'Test', true, false);
$requestedProperties = [
self::ID_PROPERTYNAME,
self::GROUPS_PROPERTYNAME,
@@ -276,7 +235,7 @@ class SystemTagPluginTest extends \Test\TestCase {
}
public function testUpdatePropertiesAdmin(): void {
- $systemTag = new SystemTag(1, 'Test', true, false);
+ $systemTag = new SystemTag('1', 'Test', true, false);
$this->user->expects($this->any())
->method('getUID')
->willReturn('admin');
@@ -334,7 +293,7 @@ class SystemTagPluginTest extends \Test\TestCase {
public function testUpdatePropertiesForbidden(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
- $systemTag = new SystemTag(1, 'Test', true, false);
+ $systemTag = new SystemTag('1', 'Test', true, false);
$this->user->expects($this->any())
->method('getUID')
->willReturn('admin');
@@ -375,7 +334,7 @@ class SystemTagPluginTest extends \Test\TestCase {
$propPatch->commit();
}
- public function createTagInsufficientPermissionsProvider() {
+ public static function createTagInsufficientPermissionsProvider(): array {
return [
[true, false, ''],
[false, true, ''],
@@ -385,7 +344,7 @@ class SystemTagPluginTest extends \Test\TestCase {
/**
* @dataProvider createTagInsufficientPermissionsProvider
*/
- public function testCreateNotAssignableTagAsRegularUser($userVisible, $userAssignable, $groups): void {
+ public function testCreateNotAssignableTagAsRegularUser(bool $userVisible, bool $userAssignable, string $groups): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
$this->expectExceptionMessage('Not sufficient permissions');
@@ -408,9 +367,7 @@ class SystemTagPluginTest extends \Test\TestCase {
}
$requestData = json_encode($requestData);
- $node = $this->getMockBuilder(SystemTagsByIdCollection::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(SystemTagsByIdCollection::class);
$this->tagManager->expects($this->never())
->method('createTag');
$this->tagManager->expects($this->never())
@@ -421,12 +378,8 @@ class SystemTagPluginTest extends \Test\TestCase {
->with('/systemtags')
->willReturn($node);
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$request->expects($this->once())
->method('getPath')
@@ -445,7 +398,7 @@ class SystemTagPluginTest extends \Test\TestCase {
}
public function testCreateTagInByIdCollectionAsRegularUser(): void {
- $systemTag = new SystemTag(1, 'Test', true, false);
+ $systemTag = new SystemTag('1', 'Test', true, false);
$requestData = json_encode([
'name' => 'Test',
@@ -453,9 +406,7 @@ class SystemTagPluginTest extends \Test\TestCase {
'userAssignable' => true,
]);
- $node = $this->getMockBuilder(SystemTagsByIdCollection::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(SystemTagsByIdCollection::class);
$this->tagManager->expects($this->once())
->method('createTag')
->with('Test', true, true)
@@ -466,12 +417,8 @@ class SystemTagPluginTest extends \Test\TestCase {
->with('/systemtags')
->willReturn($node);
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$request->expects($this->once())
->method('getPath')
@@ -497,7 +444,7 @@ class SystemTagPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
- public function createTagProvider() {
+ public static function createTagProvider(): array {
return [
[true, false, ''],
[false, false, ''],
@@ -508,7 +455,7 @@ class SystemTagPluginTest extends \Test\TestCase {
/**
* @dataProvider createTagProvider
*/
- public function testCreateTagInByIdCollection($userVisible, $userAssignable, $groups): void {
+ public function testCreateTagInByIdCollection(bool $userVisible, bool $userAssignable, string $groups): void {
$this->user->expects($this->once())
->method('getUID')
->willReturn('admin');
@@ -518,7 +465,7 @@ class SystemTagPluginTest extends \Test\TestCase {
->with('admin')
->willReturn(true);
- $systemTag = new SystemTag(1, 'Test', true, false);
+ $systemTag = new SystemTag('1', 'Test', true, false);
$requestData = [
'name' => 'Test',
@@ -530,9 +477,7 @@ class SystemTagPluginTest extends \Test\TestCase {
}
$requestData = json_encode($requestData);
- $node = $this->getMockBuilder(SystemTagsByIdCollection::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(SystemTagsByIdCollection::class);
$this->tagManager->expects($this->once())
->method('createTag')
->with('Test', $userVisible, $userAssignable)
@@ -553,12 +498,8 @@ class SystemTagPluginTest extends \Test\TestCase {
->with('/systemtags')
->willReturn($node);
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$request->expects($this->once())
->method('getPath')
@@ -584,7 +525,7 @@ class SystemTagPluginTest extends \Test\TestCase {
$this->plugin->httpPost($request, $response);
}
- public function nodeClassProvider() {
+ public static function nodeClassProvider(): array {
return [
['\OCA\DAV\SystemTag\SystemTagsByIdCollection'],
['\OCA\DAV\SystemTag\SystemTagsObjectMappingCollection'],
@@ -601,7 +542,7 @@ class SystemTagPluginTest extends \Test\TestCase {
->with('admin')
->willReturn(true);
- $systemTag = new SystemTag(1, 'Test', true, false);
+ $systemTag = new SystemTag('1', 'Test', true, false);
$requestData = json_encode([
'name' => 'Test',
@@ -609,9 +550,7 @@ class SystemTagPluginTest extends \Test\TestCase {
'userAssignable' => false,
]);
- $node = $this->getMockBuilder(SystemTagsObjectMappingCollection::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(SystemTagsObjectMappingCollection::class);
$this->tagManager->expects($this->once())
->method('createTag')
@@ -627,12 +566,8 @@ class SystemTagPluginTest extends \Test\TestCase {
->method('createFile')
->with(1);
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$request->expects($this->once())
->method('getPath')
@@ -662,9 +597,7 @@ class SystemTagPluginTest extends \Test\TestCase {
public function testCreateTagToUnknownNode(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
- $node = $this->getMockBuilder(SystemTagsObjectMappingCollection::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock(SystemTagsObjectMappingCollection::class);
$this->tree->expects($this->any())
->method('getNodeForPath')
@@ -676,12 +609,8 @@ class SystemTagPluginTest extends \Test\TestCase {
$node->expects($this->never())
->method('createFile');
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$request->expects($this->once())
->method('getPath')
@@ -693,7 +622,7 @@ class SystemTagPluginTest extends \Test\TestCase {
/**
* @dataProvider nodeClassProvider
*/
- public function testCreateTagConflict($nodeClass): void {
+ public function testCreateTagConflict(string $nodeClass): void {
$this->expectException(\Sabre\DAV\Exception\Conflict::class);
$this->user->expects($this->once())
@@ -711,9 +640,7 @@ class SystemTagPluginTest extends \Test\TestCase {
'userAssignable' => false,
]);
- $node = $this->getMockBuilder($nodeClass)
- ->disableOriginalConstructor()
- ->getMock();
+ $node = $this->createMock($nodeClass);
$this->tagManager->expects($this->once())
->method('createTag')
->with('Test', true, false)
@@ -724,12 +651,8 @@ class SystemTagPluginTest extends \Test\TestCase {
->with('/systemtags')
->willReturn($node);
- $request = $this->getMockBuilder(RequestInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $response = $this->getMockBuilder(ResponseInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
$request->expects($this->once())
->method('getPath')
diff --git a/apps/dav/tests/unit/SystemTag/SystemTagsByIdCollectionTest.php b/apps/dav/tests/unit/SystemTag/SystemTagsByIdCollectionTest.php
index b26171650a2..a6c97af26b4 100644
--- a/apps/dav/tests/unit/SystemTag/SystemTagsByIdCollectionTest.php
+++ b/apps/dav/tests/unit/SystemTag/SystemTagsByIdCollectionTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -18,50 +19,36 @@ use OCP\SystemTag\TagNotFoundException;
use PHPUnit\Framework\MockObject\MockObject;
class SystemTagsByIdCollectionTest extends \Test\TestCase {
-
- /**
- * @var ISystemTagManager
- */
- private $tagManager;
-
- /**
- * @var IUser
- */
- private $user;
+ private ISystemTagManager&MockObject $tagManager;
+ private IUser&MockObject $user;
protected function setUp(): void {
parent::setUp();
- $this->tagManager = $this->getMockBuilder(ISystemTagManager::class)
- ->getMock();
+ $this->tagManager = $this->createMock(ISystemTagManager::class);
}
- public function getNode($isAdmin = true) {
- $this->user = $this->getMockBuilder(IUser::class)
- ->getMock();
+ public function getNode(bool $isAdmin = true) {
+ $this->user = $this->createMock(IUser::class);
$this->user->expects($this->any())
->method('getUID')
->willReturn('testuser');
- /** @var IUserSession|MockObject */
- $userSession = $this->getMockBuilder(IUserSession::class)
- ->getMock();
+ /** @var IUserSession&MockObject */
+ $userSession = $this->createMock(IUserSession::class);
$userSession->expects($this->any())
->method('getUser')
->willReturn($this->user);
- /** @var IGroupManager|MockObject */
- $groupManager = $this->getMockBuilder(IGroupManager::class)
- ->getMock();
+ /** @var IGroupManager&MockObject */
+ $groupManager = $this->createMock(IGroupManager::class);
$groupManager->expects($this->any())
->method('isAdmin')
->with('testuser')
->willReturn($isAdmin);
- /** @var ISystemTagObjectMapper|MockObject */
- $tagMapper = $this->getMockBuilder(ISystemTagObjectMapper::class)
- ->getMock();
-
+ /** @var ISystemTagObjectMapper&MockObject */
+ $tagMapper = $this->createMock(ISystemTagObjectMapper::class);
return new SystemTagsByIdCollection(
$this->tagManager,
$userSession,
@@ -70,18 +57,18 @@ class SystemTagsByIdCollectionTest extends \Test\TestCase {
);
}
- public function adminFlagProvider() {
+ public static function adminFlagProvider(): array {
return [[true], [false]];
}
-
+
public function testForbiddenCreateFile(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
$this->getNode()->createFile('555');
}
-
+
public function testForbiddenCreateDirectory(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
@@ -89,7 +76,7 @@ class SystemTagsByIdCollectionTest extends \Test\TestCase {
}
public function testGetChild(): void {
- $tag = new SystemTag(123, 'Test', true, false);
+ $tag = new SystemTag('123', 'Test', true, false);
$this->tagManager->expects($this->once())
->method('canUserSeeTag')
->with($tag)
@@ -107,7 +94,7 @@ class SystemTagsByIdCollectionTest extends \Test\TestCase {
$this->assertEquals($tag, $childNode->getSystemTag());
}
-
+
public function testGetChildInvalidName(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
@@ -119,7 +106,7 @@ class SystemTagsByIdCollectionTest extends \Test\TestCase {
$this->getNode()->getChild('invalid');
}
-
+
public function testGetChildNotFound(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
@@ -131,11 +118,11 @@ class SystemTagsByIdCollectionTest extends \Test\TestCase {
$this->getNode()->getChild('444');
}
-
+
public function testGetChildUserNotVisible(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
- $tag = new SystemTag(123, 'Test', false, false);
+ $tag = new SystemTag('123', 'Test', false, false);
$this->tagManager->expects($this->once())
->method('getTagsByIds')
@@ -146,8 +133,8 @@ class SystemTagsByIdCollectionTest extends \Test\TestCase {
}
public function testGetChildrenAdmin(): void {
- $tag1 = new SystemTag(123, 'One', true, false);
- $tag2 = new SystemTag(456, 'Two', true, true);
+ $tag1 = new SystemTag('123', 'One', true, false);
+ $tag2 = new SystemTag('456', 'Two', true, true);
$this->tagManager->expects($this->once())
->method('getAllTags')
@@ -165,8 +152,8 @@ class SystemTagsByIdCollectionTest extends \Test\TestCase {
}
public function testGetChildrenNonAdmin(): void {
- $tag1 = new SystemTag(123, 'One', true, false);
- $tag2 = new SystemTag(456, 'Two', true, true);
+ $tag1 = new SystemTag('123', 'One', true, false);
+ $tag2 = new SystemTag('456', 'Two', true, true);
$this->tagManager->expects($this->once())
->method('getAllTags')
@@ -191,7 +178,7 @@ class SystemTagsByIdCollectionTest extends \Test\TestCase {
$this->assertCount(0, $this->getNode()->getChildren());
}
- public function childExistsProvider() {
+ public static function childExistsProvider(): array {
return [
[true, true],
[false, false],
@@ -201,8 +188,8 @@ class SystemTagsByIdCollectionTest extends \Test\TestCase {
/**
* @dataProvider childExistsProvider
*/
- public function testChildExists($userVisible, $expectedResult): void {
- $tag = new SystemTag(123, 'One', $userVisible, false);
+ public function testChildExists(bool $userVisible, bool $expectedResult): void {
+ $tag = new SystemTag('123', 'One', $userVisible, false);
$this->tagManager->expects($this->once())
->method('canUserSeeTag')
->with($tag)
@@ -225,7 +212,7 @@ class SystemTagsByIdCollectionTest extends \Test\TestCase {
$this->assertFalse($this->getNode()->childExists('123'));
}
-
+
public function testChildExistsBadRequest(): void {
$this->expectException(\Sabre\DAV\Exception\BadRequest::class);
diff --git a/apps/dav/tests/unit/SystemTag/SystemTagsObjectMappingCollectionTest.php b/apps/dav/tests/unit/SystemTag/SystemTagsObjectMappingCollectionTest.php
index 66052847f16..59cd3955f1f 100644
--- a/apps/dav/tests/unit/SystemTag/SystemTagsObjectMappingCollectionTest.php
+++ b/apps/dav/tests/unit/SystemTag/SystemTagsObjectMappingCollectionTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -13,27 +14,24 @@ use OCP\IUser;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\SystemTag\TagNotFoundException;
+use PHPUnit\Framework\MockObject\MockObject;
class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
- private ISystemTagManager $tagManager;
- private ISystemTagObjectMapper $tagMapper;
- private IUser $user;
+ private ISystemTagManager&MockObject $tagManager;
+ private ISystemTagObjectMapper&MockObject $tagMapper;
+ private IUser&MockObject $user;
protected function setUp(): void {
parent::setUp();
- $this->tagManager = $this->getMockBuilder(ISystemTagManager::class)
- ->getMock();
- $this->tagMapper = $this->getMockBuilder(ISystemTagObjectMapper::class)
- ->getMock();
-
- $this->user = $this->getMockBuilder(IUser::class)
- ->getMock();
+ $this->tagManager = $this->createMock(ISystemTagManager::class);
+ $this->tagMapper = $this->createMock(ISystemTagObjectMapper::class);
+ $this->user = $this->createMock(IUser::class);
}
- public function getNode(array $writableNodeIds = []) {
+ public function getNode(array $writableNodeIds = []): SystemTagsObjectMappingCollection {
return new SystemTagsObjectMappingCollection(
- 111,
+ '111',
'files',
$this->user,
$this->tagManager,
@@ -86,7 +84,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
$this->getNode()->createFile('555');
}
- public function permissionsProvider() {
+ public static function permissionsProvider(): array {
return [
// invisible, tag does not exist for user
[false, true, '\Sabre\DAV\Exception\PreconditionFailed'],
@@ -98,7 +96,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
/**
* @dataProvider permissionsProvider
*/
- public function testAssignTagNoPermission($userVisible, $userAssignable, $expectedException): void {
+ public function testAssignTagNoPermission(bool $userVisible, bool $userAssignable, string $expectedException): void {
$tag = new SystemTag('1', 'Test', $userVisible, $userAssignable);
$this->tagManager->expects($this->once())
->method('canUserSeeTag')
@@ -146,7 +144,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
}
public function testGetChild(): void {
- $tag = new SystemTag(555, 'TheTag', true, false);
+ $tag = new SystemTag('555', 'TheTag', true, false);
$this->tagManager->expects($this->once())
->method('canUserSeeTag')
->with($tag)
@@ -172,7 +170,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
public function testGetChildNonVisible(): void {
$this->expectException(\Sabre\DAV\Exception\NotFound::class);
- $tag = new SystemTag(555, 'TheTag', false, false);
+ $tag = new SystemTag('555', 'TheTag', false, false);
$this->tagManager->expects($this->once())
->method('canUserSeeTag')
->with($tag)
@@ -228,9 +226,9 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
}
public function testGetChildren(): void {
- $tag1 = new SystemTag(555, 'TagOne', true, false);
- $tag2 = new SystemTag(556, 'TagTwo', true, true);
- $tag3 = new SystemTag(557, 'InvisibleTag', false, true);
+ $tag1 = new SystemTag('555', 'TagOne', true, false);
+ $tag2 = new SystemTag('556', 'TagTwo', true, true);
+ $tag3 = new SystemTag('557', 'InvisibleTag', false, true);
$this->tagMapper->expects($this->once())
->method('getTagIdsForObjects')
@@ -265,7 +263,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
}
public function testChildExistsWithVisibleTag(): void {
- $tag = new SystemTag(555, 'TagOne', true, false);
+ $tag = new SystemTag('555', 'TagOne', true, false);
$this->tagMapper->expects($this->once())
->method('haveTag')
@@ -286,7 +284,7 @@ class SystemTagsObjectMappingCollectionTest extends \Test\TestCase {
}
public function testChildExistsWithInvisibleTag(): void {
- $tag = new SystemTag(555, 'TagOne', false, false);
+ $tag = new SystemTag('555', 'TagOne', false, false);
$this->tagMapper->expects($this->once())
->method('haveTag')
diff --git a/apps/dav/tests/unit/SystemTag/SystemTagsObjectTypeCollectionTest.php b/apps/dav/tests/unit/SystemTag/SystemTagsObjectTypeCollectionTest.php
index ba9304d33fc..301eb528436 100644
--- a/apps/dav/tests/unit/SystemTag/SystemTagsObjectTypeCollectionTest.php
+++ b/apps/dav/tests/unit/SystemTag/SystemTagsObjectTypeCollectionTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -15,60 +16,39 @@ use OCP\IUser;
use OCP\IUserSession;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
+use PHPUnit\Framework\MockObject\MockObject;
class SystemTagsObjectTypeCollectionTest extends \Test\TestCase {
-
- /**
- * @var SystemTagsObjectTypeCollection
- */
- private $node;
-
- /**
- * @var ISystemTagManager
- */
- private $tagManager;
-
- /**
- * @var ISystemTagObjectMapper
- */
- private $tagMapper;
-
- /**
- * @var Folder
- */
- private $userFolder;
+ private ISystemTagManager&MockObject $tagManager;
+ private ISystemTagObjectMapper&MockObject $tagMapper;
+ private Folder&MockObject $userFolder;
+ private SystemTagsObjectTypeCollection $node;
protected function setUp(): void {
parent::setUp();
- $this->tagManager = $this->getMockBuilder(ISystemTagManager::class)
- ->getMock();
- $this->tagMapper = $this->getMockBuilder(ISystemTagObjectMapper::class)
- ->getMock();
+ $this->tagManager = $this->createMock(ISystemTagManager::class);
+ $this->tagMapper = $this->createMock(ISystemTagObjectMapper::class);
- $user = $this->getMockBuilder(IUser::class)
- ->getMock();
+ $user = $this->createMock(IUser::class);
$user->expects($this->any())
->method('getUID')
->willReturn('testuser');
- $userSession = $this->getMockBuilder(IUserSession::class)
- ->getMock();
+ $userSession = $this->createMock(IUserSession::class);
$userSession->expects($this->any())
->method('getUser')
->willReturn($user);
- $groupManager = $this->getMockBuilder(IGroupManager::class)
- ->getMock();
+ $groupManager = $this->createMock(IGroupManager::class);
$groupManager->expects($this->any())
->method('isAdmin')
->with('testuser')
->willReturn(true);
- $this->userFolder = $this->getMockBuilder(Folder::class)
- ->getMock();
+ $this->userFolder = $this->createMock(Folder::class);
$userFolder = $this->userFolder;
$closure = function ($name) use ($userFolder) {
- $node = $userFolder->getFirstNodeById(intval($name));
+ $node = $userFolder->getFirstNodeById((int)$name);
return $node !== null;
};
$writeAccessClosure = function ($name) use ($userFolder) {
diff --git a/apps/dav/tests/unit/Upload/AssemblyStreamTest.php b/apps/dav/tests/unit/Upload/AssemblyStreamTest.php
index 854d02bfc10..e0bc3c589bc 100644
--- a/apps/dav/tests/unit/Upload/AssemblyStreamTest.php
+++ b/apps/dav/tests/unit/Upload/AssemblyStreamTest.php
@@ -15,7 +15,11 @@ class AssemblyStreamTest extends \Test\TestCase {
/**
* @dataProvider providesNodes()
*/
- public function testGetContents($expected, $nodes): void {
+ public function testGetContents(string $expected, array $nodeData): void {
+ $nodes = [];
+ foreach ($nodeData as $data) {
+ $nodes[] = $this->buildNode(...$data);
+ }
$stream = AssemblyStream::wrap($nodes);
$content = stream_get_contents($stream);
@@ -25,7 +29,11 @@ class AssemblyStreamTest extends \Test\TestCase {
/**
* @dataProvider providesNodes()
*/
- public function testGetContentsFread($expected, $nodes, $chunkLength = 3): void {
+ public function testGetContentsFread(string $expected, array $nodeData, int $chunkLength = 3): void {
+ $nodes = [];
+ foreach ($nodeData as $data) {
+ $nodes[] = $this->buildNode(...$data);
+ }
$stream = AssemblyStream::wrap($nodes);
$content = '';
@@ -43,7 +51,12 @@ class AssemblyStreamTest extends \Test\TestCase {
/**
* @dataProvider providesNodes()
*/
- public function testSeek($expected, $nodes): void {
+ public function testSeek(string $expected, array $nodeData): void {
+ $nodes = [];
+ foreach ($nodeData as $data) {
+ $nodes[] = $this->buildNode(...$data);
+ }
+
$stream = AssemblyStream::wrap($nodes);
$offset = floor(strlen($expected) * 0.6);
@@ -55,75 +68,75 @@ class AssemblyStreamTest extends \Test\TestCase {
$this->assertEquals(substr($expected, $offset), $content);
}
- public function providesNodes() {
- $data8k = $this->makeData(8192);
- $dataLess8k = $this->makeData(8191);
+ public static function providesNodes(): array {
+ $data8k = self::makeData(8192);
+ $dataLess8k = self::makeData(8191);
$tonofnodes = [];
$tonofdata = '';
for ($i = 0; $i < 101; $i++) {
$thisdata = random_int(0, 100); // variable length and content
$tonofdata .= $thisdata;
- $tonofnodes[] = $this->buildNode((string)$i, (string)$thisdata);
+ $tonofnodes[] = [(string)$i, (string)$thisdata];
}
return[
'one node zero bytes' => [
'', [
- $this->buildNode('0', '')
+ ['0', ''],
]],
'one node only' => [
'1234567890', [
- $this->buildNode('0', '1234567890')
+ ['0', '1234567890'],
]],
'one node buffer boundary' => [
$data8k, [
- $this->buildNode('0', $data8k)
+ ['0', $data8k],
]],
'two nodes' => [
'1234567890', [
- $this->buildNode('1', '67890'),
- $this->buildNode('0', '12345')
+ ['1', '67890'],
+ ['0', '12345'],
]],
'two nodes end on buffer boundary' => [
$data8k . $data8k, [
- $this->buildNode('1', $data8k),
- $this->buildNode('0', $data8k)
+ ['1', $data8k],
+ ['0', $data8k],
]],
'two nodes with one on buffer boundary' => [
$data8k . $dataLess8k, [
- $this->buildNode('1', $dataLess8k),
- $this->buildNode('0', $data8k)
+ ['1', $dataLess8k],
+ ['0', $data8k],
]],
'two nodes on buffer boundary plus one byte' => [
$data8k . 'X' . $data8k, [
- $this->buildNode('1', $data8k),
- $this->buildNode('0', $data8k . 'X')
+ ['1', $data8k],
+ ['0', $data8k . 'X'],
]],
'two nodes on buffer boundary plus one byte at the end' => [
$data8k . $data8k . 'X', [
- $this->buildNode('1', $data8k . 'X'),
- $this->buildNode('0', $data8k)
+ ['1', $data8k . 'X'],
+ ['0', $data8k],
]],
'a ton of nodes' => [
$tonofdata, $tonofnodes
],
'one read over multiple nodes' => [
'1234567890', [
- $this->buildNode('0', '1234'),
- $this->buildNode('1', '5678'),
- $this->buildNode('2', '90'),
+ ['0', '1234'],
+ ['1', '5678'],
+ ['2', '90'],
], 10],
'two reads over multiple nodes' => [
'1234567890', [
- $this->buildNode('0', '1234'),
- $this->buildNode('1', '5678'),
- $this->buildNode('2', '90'),
+ ['0', '1234'],
+ ['1', '5678'],
+ ['2', '90'],
], 5],
];
}
- private function makeData($count) {
+ private static function makeData(int $count): string {
$data = '';
$base = '1234567890';
$j = 0;
@@ -137,10 +150,10 @@ class AssemblyStreamTest extends \Test\TestCase {
return $data;
}
- private function buildNode($name, $data) {
+ private function buildNode(string $name, string $data) {
$node = $this->getMockBuilder(File::class)
- ->setMethods(['getName', 'get', 'getSize'])
- ->getMockForAbstractClass();
+ ->onlyMethods(['getName', 'get', 'getSize'])
+ ->getMock();
$node->expects($this->any())
->method('getName')
diff --git a/apps/dav/tests/unit/Upload/ChunkingPluginTest.php b/apps/dav/tests/unit/Upload/ChunkingPluginTest.php
index 87feebf5d09..00ed7657dd3 100644
--- a/apps/dav/tests/unit/Upload/ChunkingPluginTest.php
+++ b/apps/dav/tests/unit/Upload/ChunkingPluginTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2017 ownCloud GmbH
@@ -10,40 +11,24 @@ namespace OCA\DAV\Tests\unit\Upload;
use OCA\DAV\Connector\Sabre\Directory;
use OCA\DAV\Upload\ChunkingPlugin;
use OCA\DAV\Upload\FutureFile;
+use PHPUnit\Framework\MockObject\MockObject;
use Sabre\DAV\Exception\NotFound;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
use Test\TestCase;
class ChunkingPluginTest extends TestCase {
- /**
- * @var \Sabre\DAV\Server | \PHPUnit\Framework\MockObject\MockObject
- */
- private $server;
-
- /**
- * @var \Sabre\DAV\Tree | \PHPUnit\Framework\MockObject\MockObject
- */
- private $tree;
-
- /**
- * @var ChunkingPlugin
- */
- private $plugin;
- /** @var RequestInterface | \PHPUnit\Framework\MockObject\MockObject */
- private $request;
- /** @var ResponseInterface | \PHPUnit\Framework\MockObject\MockObject */
- private $response;
+ private \Sabre\DAV\Server&MockObject $server;
+ private \Sabre\DAV\Tree&MockObject $tree;
+ private ChunkingPlugin $plugin;
+ private RequestInterface&MockObject $request;
+ private ResponseInterface&MockObject $response;
protected function setUp(): void {
parent::setUp();
- $this->server = $this->getMockBuilder('\Sabre\DAV\Server')
- ->disableOriginalConstructor()
- ->getMock();
- $this->tree = $this->getMockBuilder('\Sabre\DAV\Tree')
- ->disableOriginalConstructor()
- ->getMock();
+ $this->server = $this->createMock('\Sabre\DAV\Server');
+ $this->tree = $this->createMock('\Sabre\DAV\Tree');
$this->server->tree = $this->tree;
$this->plugin = new ChunkingPlugin();
@@ -78,14 +63,10 @@ class ChunkingPluginTest extends TestCase {
$this->tree->expects($this->exactly(2))
->method('getNodeForPath')
- ->withConsecutive(
- ['source'],
- ['target'],
- )
- ->willReturnOnConsecutiveCalls(
- $sourceNode,
- $targetNode,
- );
+ ->willReturnMap([
+ ['source', $sourceNode],
+ ['target', $targetNode],
+ ]);
$this->response->expects($this->never())
->method('setStatus');
@@ -98,16 +79,20 @@ class ChunkingPluginTest extends TestCase {
->method('getSize')
->willReturn(4);
+ $calls = [
+ ['source', $sourceNode],
+ ['target', new NotFound()],
+ ];
$this->tree->expects($this->exactly(2))
->method('getNodeForPath')
- ->withConsecutive(
- ['source'],
- ['target'],
- )
- ->willReturnOnConsecutiveCalls(
- $sourceNode,
- $this->throwException(new NotFound()),
- );
+ ->willReturnCallback(function (string $path) use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertSame($expected[0], $path);
+ if ($expected[1] instanceof \Throwable) {
+ throw $expected[1];
+ }
+ return $expected[1];
+ });
$this->tree->expects($this->any())
->method('nodeExists')
->with('target')
@@ -132,17 +117,21 @@ class ChunkingPluginTest extends TestCase {
->method('getSize')
->willReturn(4);
-
+ $calls = [
+ ['source', $sourceNode],
+ ['target', new NotFound()],
+ ];
$this->tree->expects($this->exactly(2))
->method('getNodeForPath')
- ->withConsecutive(
- ['source'],
- ['target'],
- )
- ->willReturnOnConsecutiveCalls(
- $sourceNode,
- $this->throwException(new NotFound()),
- );
+ ->willReturnCallback(function (string $path) use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertSame($expected[0], $path);
+ if ($expected[1] instanceof \Throwable) {
+ throw $expected[1];
+ }
+ return $expected[1];
+ });
+
$this->tree->expects($this->any())
->method('nodeExists')
->with('target')
@@ -175,17 +164,21 @@ class ChunkingPluginTest extends TestCase {
->method('getSize')
->willReturn(3);
-
+ $calls = [
+ ['source', $sourceNode],
+ ['target', new NotFound()],
+ ];
$this->tree->expects($this->exactly(2))
->method('getNodeForPath')
- ->withConsecutive(
- ['source'],
- ['target'],
- )
- ->willReturnOnConsecutiveCalls(
- $sourceNode,
- $this->throwException(new NotFound()),
- );
+ ->willReturnCallback(function (string $path) use (&$calls) {
+ $expected = array_shift($calls);
+ $this->assertSame($expected[0], $path);
+ if ($expected[1] instanceof \Throwable) {
+ throw $expected[1];
+ }
+ return $expected[1];
+ });
+
$this->request->expects($this->once())
->method('getHeader')
->with('OC-Total-Length')
diff --git a/apps/dav/tests/unit/Upload/FutureFileTest.php b/apps/dav/tests/unit/Upload/FutureFileTest.php
index 750670992eb..1409df937c0 100644
--- a/apps/dav/tests/unit/Upload/FutureFileTest.php
+++ b/apps/dav/tests/unit/Upload/FutureFileTest.php
@@ -1,5 +1,6 @@
<?php
+declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -45,7 +46,7 @@ class FutureFileTest extends \Test\TestCase {
public function testDelete(): void {
$d = $this->getMockBuilder(Directory::class)
->disableOriginalConstructor()
- ->setMethods(['delete'])
+ ->onlyMethods(['delete'])
->getMock();
$d->expects($this->once())
@@ -55,7 +56,7 @@ class FutureFileTest extends \Test\TestCase {
$f->delete();
}
-
+
public function testPut(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
@@ -63,7 +64,7 @@ class FutureFileTest extends \Test\TestCase {
$f->put('');
}
-
+
public function testSetName(): void {
$this->expectException(\Sabre\DAV\Exception\Forbidden::class);
@@ -71,13 +72,10 @@ class FutureFileTest extends \Test\TestCase {
$f->setName('');
}
- /**
- * @return FutureFile
- */
- private function mockFutureFile() {
+ private function mockFutureFile(): FutureFile {
$d = $this->getMockBuilder(Directory::class)
->disableOriginalConstructor()
- ->setMethods(['getETag', 'getLastModified', 'getChildren'])
+ ->onlyMethods(['getETag', 'getLastModified', 'getChildren'])
->getMock();
$d->expects($this->any())
diff --git a/apps/dav/tests/unit/Upload/UploadAutoMkcolPluginTest.php b/apps/dav/tests/unit/Upload/UploadAutoMkcolPluginTest.php
new file mode 100644
index 00000000000..9467b5df249
--- /dev/null
+++ b/apps/dav/tests/unit/Upload/UploadAutoMkcolPluginTest.php
@@ -0,0 +1,135 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\DAV\Tests\unit\Upload;
+
+use Generator;
+use OCA\DAV\Upload\UploadAutoMkcolPlugin;
+use PHPUnit\Framework\MockObject\MockObject;
+use Sabre\DAV\ICollection;
+use Sabre\DAV\INode;
+use Sabre\DAV\Server;
+use Sabre\DAV\Tree;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+use Test\TestCase;
+
+class UploadAutoMkcolPluginTest extends TestCase {
+
+ private Tree&MockObject $tree;
+ private RequestInterface&MockObject $request;
+ private ResponseInterface&MockObject $response;
+
+ public static function dataMissingHeaderShouldReturnTrue(): Generator {
+ yield 'missing X-NC-WebDAV-Auto-Mkcol header' => [null];
+ yield 'empty X-NC-WebDAV-Auto-Mkcol header' => [''];
+ yield 'invalid X-NC-WebDAV-Auto-Mkcol header' => ['enable'];
+ }
+
+ public function testBeforeMethodWithRootNodeNotAnICollectionShouldReturnTrue(): void {
+ $this->request->method('getHeader')->willReturn('1');
+ $this->request->expects(self::once())
+ ->method('getPath')
+ ->willReturn('/non-relevant/path.txt');
+ $this->tree->expects(self::once())
+ ->method('nodeExists')
+ ->with('/non-relevant')
+ ->willReturn(false);
+
+ $mockNode = $this->getMockBuilder(INode::class);
+ $this->tree->expects(self::once())
+ ->method('getNodeForPath')
+ ->willReturn($mockNode);
+
+ $return = $this->plugin->beforeMethod($this->request, $this->response);
+ $this->assertTrue($return);
+ }
+
+ /**
+ * @dataProvider dataMissingHeaderShouldReturnTrue
+ */
+ public function testBeforeMethodWithMissingHeaderShouldReturnTrue(?string $header): void {
+ $this->request->expects(self::once())
+ ->method('getHeader')
+ ->with('X-NC-WebDAV-Auto-Mkcol')
+ ->willReturn($header);
+
+ $this->request->expects(self::never())
+ ->method('getPath');
+
+ $return = $this->plugin->beforeMethod($this->request, $this->response);
+ self::assertTrue($return);
+ }
+
+ public function testBeforeMethodWithExistingPathShouldReturnTrue(): void {
+ $this->request->method('getHeader')->willReturn('1');
+ $this->request->expects(self::once())
+ ->method('getPath')
+ ->willReturn('/files/user/deep/image.jpg');
+ $this->tree->expects(self::once())
+ ->method('nodeExists')
+ ->with('/files/user/deep')
+ ->willReturn(true);
+
+ $this->tree->expects(self::never())
+ ->method('getNodeForPath');
+
+ $return = $this->plugin->beforeMethod($this->request, $this->response);
+ self::assertTrue($return);
+ }
+
+ public function testBeforeMethodShouldSucceed(): void {
+ $this->request->method('getHeader')->willReturn('1');
+ $this->request->expects(self::once())
+ ->method('getPath')
+ ->willReturn('/files/user/my/deep/path/image.jpg');
+ $this->tree->expects(self::once())
+ ->method('nodeExists')
+ ->with('/files/user/my/deep/path')
+ ->willReturn(false);
+
+ $mockNode = $this->createMock(ICollection::class);
+ $this->tree->expects(self::once())
+ ->method('getNodeForPath')
+ ->with('/files')
+ ->willReturn($mockNode);
+ $mockNode->expects(self::exactly(4))
+ ->method('childExists')
+ ->willReturnMap([
+ ['user', true],
+ ['my', true],
+ ['deep', false],
+ ['path', false],
+ ]);
+ $mockNode->expects(self::exactly(2))
+ ->method('createDirectory');
+ $mockNode->expects(self::exactly(4))
+ ->method('getChild')
+ ->willReturn($mockNode);
+
+ $return = $this->plugin->beforeMethod($this->request, $this->response);
+ self::assertTrue($return);
+ }
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $server = $this->createMock(Server::class);
+ $this->tree = $this->createMock(Tree::class);
+
+ $server->tree = $this->tree;
+ $this->plugin = new UploadAutoMkcolPlugin();
+
+ $this->request = $this->createMock(RequestInterface::class);
+ $this->response = $this->createMock(ResponseInterface::class);
+ $server->httpRequest = $this->request;
+ $server->httpResponse = $this->response;
+
+ $this->plugin->initialize($server);
+ }
+}
diff --git a/apps/dav/tests/unit/test_fixtures/example-event-default-expected.ics b/apps/dav/tests/unit/test_fixtures/example-event-default-expected.ics
new file mode 100644
index 00000000000..09606ca5ee4
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/example-event-default-expected.ics
@@ -0,0 +1,20 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Sabre//Sabre VObject 4.5.6//EN
+CALSCALE:GREGORIAN
+BEGIN:VEVENT
+UID:RANDOM-UID
+DTSTAMP:20250121T000000Z
+SUMMARY:Example event - open me!
+DTSTART:20250128T100000Z
+DTEND:20250128T110000Z
+DESCRIPTION:Welcome to Nextcloud Calendar!\n\nThis is a sample event - expl
+ ore the flexibility of planning with Nextcloud Calendar by making any edit
+ s you want!\n\nWith Nextcloud Calendar\, you can:\n- Create\, edit\, and m
+ anage events effortlessly.\n- Create multiple calendars and share them wit
+ h teammates\, friends\, or family.\n- Check availability and display your
+ busy times to others.\n- Seamlessly integrate with apps and devices via Ca
+ lDAV.\n- Customize your experience: schedule recurring events\, adjust not
+ ifications and other settings.
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/unit/test_fixtures/example-event-default-expected.ics.license b/apps/dav/tests/unit/test_fixtures/example-event-default-expected.ics.license
new file mode 100644
index 00000000000..23e2d6b1908
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/example-event-default-expected.ics.license
@@ -0,0 +1,2 @@
+SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/tests/unit/test_fixtures/example-event-expected.ics b/apps/dav/tests/unit/test_fixtures/example-event-expected.ics
new file mode 100644
index 00000000000..f9dfc37718e
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/example-event-expected.ics
@@ -0,0 +1,18 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+CALSCALE:GREGORIAN
+PRODID:-//IDN nextcloud.com//Calendar app 5.2.0-dev.1//EN
+BEGIN:VEVENT
+CREATED:20250128T091147Z
+DTSTAMP:20250128T091507Z
+LAST-MODIFIED:20250128T091507Z
+SEQUENCE:2
+STATUS:CONFIRMED
+SUMMARY:Welcome!
+DESCRIPTION:Welcome!!!
+LOCATION:Test
+UID:RANDOM-UID
+DTSTART:20250128T100000Z
+DTEND:20250128T110000Z
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/unit/test_fixtures/example-event-expected.ics.license b/apps/dav/tests/unit/test_fixtures/example-event-expected.ics.license
new file mode 100644
index 00000000000..23e2d6b1908
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/example-event-expected.ics.license
@@ -0,0 +1,2 @@
+SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/tests/unit/test_fixtures/example-event-with-attendees.ics b/apps/dav/tests/unit/test_fixtures/example-event-with-attendees.ics
new file mode 100644
index 00000000000..8018552f2a5
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/example-event-with-attendees.ics
@@ -0,0 +1,21 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+CALSCALE:GREGORIAN
+PRODID:-//IDN nextcloud.com//Calendar app 5.2.0-dev.1//EN
+BEGIN:VEVENT
+CREATED:20250128T091147Z
+DTSTAMP:20250128T091507Z
+LAST-MODIFIED:20250128T091507Z
+SEQUENCE:2
+UID:3b4df6a8-84df-43d5-baf9-377b43390b70
+DTSTART;VALUE=DATE:20250130
+DTEND;VALUE=DATE:20250131
+STATUS:CONFIRMED
+SUMMARY:Welcome!
+DESCRIPTION:Welcome!!!
+LOCATION:Test
+ATTENDEE;CN=user a;CUTYPE=INDIVIDUAL;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICI
+ PANT;RSVP=TRUE;LANGUAGE=en;SCHEDULE-STATUS=1.1:mailto:usera@imap.localhost
+ORGANIZER;CN=Admin Account:mailto:admin@imap.localhost
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/unit/test_fixtures/example-event-with-attendees.ics.license b/apps/dav/tests/unit/test_fixtures/example-event-with-attendees.ics.license
new file mode 100644
index 00000000000..23e2d6b1908
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/example-event-with-attendees.ics.license
@@ -0,0 +1,2 @@
+SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/apps/dav/tests/unit/test_fixtures/example-event.ics b/apps/dav/tests/unit/test_fixtures/example-event.ics
new file mode 100644
index 00000000000..6fc1848ea52
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/example-event.ics
@@ -0,0 +1,18 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+CALSCALE:GREGORIAN
+PRODID:-//IDN nextcloud.com//Calendar app 5.2.0-dev.1//EN
+BEGIN:VEVENT
+CREATED:20250128T091147Z
+DTSTAMP:20250128T091507Z
+LAST-MODIFIED:20250128T091507Z
+SEQUENCE:2
+UID:3b4df6a8-84df-43d5-baf9-377b43390b70
+STATUS:CONFIRMED
+SUMMARY:Welcome!
+DESCRIPTION:Welcome!!!
+LOCATION:Test
+DTSTART:20250204T100000Z
+DTEND:20250204T110000Z
+END:VEVENT
+END:VCALENDAR
diff --git a/apps/dav/tests/unit/test_fixtures/example-event.ics.license b/apps/dav/tests/unit/test_fixtures/example-event.ics.license
new file mode 100644
index 00000000000..23e2d6b1908
--- /dev/null
+++ b/apps/dav/tests/unit/test_fixtures/example-event.ics.license
@@ -0,0 +1,2 @@
+SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+SPDX-License-Identifier: AGPL-3.0-or-later