aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/admin_audit/lib/Actions/Files.php23
-rw-r--r--apps/admin_audit/lib/AppInfo/Application.php8
-rw-r--r--apps/comments/tests/Unit/Activity/ListenerTest.php40
-rw-r--r--apps/comments/tests/Unit/AppInfo/ApplicationTest.php19
-rw-r--r--apps/comments/tests/Unit/Collaboration/CommentersSorterTest.php9
-rw-r--r--apps/comments/tests/Unit/Controller/NotificationsTest.php30
-rw-r--r--apps/comments/tests/Unit/EventHandlerTest.php49
-rw-r--r--apps/comments/tests/Unit/Notification/ListenerTest.php82
-rw-r--r--apps/comments/tests/Unit/Notification/NotifierTest.php37
-rw-r--r--apps/contactsinteraction/tests/Db/RecentContactMapperTest.php8
-rw-r--r--apps/dashboard/tests/DashboardServiceTest.php8
-rw-r--r--apps/dav/appinfo/info.xml2
-rw-r--r--apps/dav/composer/composer/autoload_classmap.php2
-rw-r--r--apps/dav/composer/composer/autoload_static.php2
-rw-r--r--apps/dav/l10n/de.js8
-rw-r--r--apps/dav/l10n/de.json8
-rw-r--r--apps/dav/l10n/de_DE.js8
-rw-r--r--apps/dav/l10n/de_DE.json8
-rw-r--r--apps/dav/l10n/et_EE.js1
-rw-r--r--apps/dav/l10n/et_EE.json1
-rw-r--r--apps/dav/lib/CalDAV/CalDavBackend.php40
-rw-r--r--apps/dav/lib/CalDAV/Calendar.php8
-rw-r--r--apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php12
-rw-r--r--apps/dav/lib/CardDAV/CardDavBackend.php2
-rw-r--r--apps/dav/lib/Command/ClearCalendarUnshares.php114
-rw-r--r--apps/dav/lib/Command/ListCalendarShares.php131
-rw-r--r--apps/dav/lib/Connector/Sabre/Principal.php6
-rw-r--r--apps/dav/lib/Connector/Sabre/ServerFactory.php3
-rw-r--r--apps/dav/lib/DAV/Sharing/Backend.php49
-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/Events/CalendarShareUpdatedEvent.php11
-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/CalDAV/CalDavBackendTest.php45
-rw-r--r--apps/dav/tests/unit/CalDAV/CalendarTest.php26
-rw-r--r--apps/dav/tests/unit/Command/ListCalendarSharesTest.php172
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php5
-rw-r--r--apps/dav/tests/unit/DAV/Sharing/BackendTest.php22
-rw-r--r--apps/dav/tests/unit/DAV/Sharing/SharingServiceTest.php58
-rw-r--r--apps/files/l10n/ar.js1
-rw-r--r--apps/files/l10n/ar.json1
-rw-r--r--apps/files/l10n/ast.js1
-rw-r--r--apps/files/l10n/ast.json1
-rw-r--r--apps/files/l10n/bg.js1
-rw-r--r--apps/files/l10n/bg.json1
-rw-r--r--apps/files/l10n/ca.js1
-rw-r--r--apps/files/l10n/ca.json1
-rw-r--r--apps/files/l10n/cs.js2
-rw-r--r--apps/files/l10n/cs.json2
-rw-r--r--apps/files/l10n/da.js1
-rw-r--r--apps/files/l10n/da.json1
-rw-r--r--apps/files/l10n/de.js21
-rw-r--r--apps/files/l10n/de.json21
-rw-r--r--apps/files/l10n/de_DE.js11
-rw-r--r--apps/files/l10n/de_DE.json11
-rw-r--r--apps/files/l10n/el.js1
-rw-r--r--apps/files/l10n/el.json1
-rw-r--r--apps/files/l10n/en_GB.js3
-rw-r--r--apps/files/l10n/en_GB.json3
-rw-r--r--apps/files/l10n/es.js3
-rw-r--r--apps/files/l10n/es.json3
-rw-r--r--apps/files/l10n/es_EC.js1
-rw-r--r--apps/files/l10n/es_EC.json1
-rw-r--r--apps/files/l10n/es_MX.js1
-rw-r--r--apps/files/l10n/es_MX.json1
-rw-r--r--apps/files/l10n/et_EE.js25
-rw-r--r--apps/files/l10n/et_EE.json25
-rw-r--r--apps/files/l10n/eu.js1
-rw-r--r--apps/files/l10n/eu.json1
-rw-r--r--apps/files/l10n/fa.js1
-rw-r--r--apps/files/l10n/fa.json1
-rw-r--r--apps/files/l10n/fi.js1
-rw-r--r--apps/files/l10n/fi.json1
-rw-r--r--apps/files/l10n/fr.js1
-rw-r--r--apps/files/l10n/fr.json1
-rw-r--r--apps/files/l10n/ga.js3
-rw-r--r--apps/files/l10n/ga.json3
-rw-r--r--apps/files/l10n/gl.js1
-rw-r--r--apps/files/l10n/gl.json1
-rw-r--r--apps/files/l10n/hu.js1
-rw-r--r--apps/files/l10n/hu.json1
-rw-r--r--apps/files/l10n/id.js1
-rw-r--r--apps/files/l10n/id.json1
-rw-r--r--apps/files/l10n/is.js1
-rw-r--r--apps/files/l10n/is.json1
-rw-r--r--apps/files/l10n/it.js3
-rw-r--r--apps/files/l10n/it.json3
-rw-r--r--apps/files/l10n/ja.js1
-rw-r--r--apps/files/l10n/ja.json1
-rw-r--r--apps/files/l10n/ka.js1
-rw-r--r--apps/files/l10n/ka.json1
-rw-r--r--apps/files/l10n/ko.js1
-rw-r--r--apps/files/l10n/ko.json1
-rw-r--r--apps/files/l10n/lt_LT.js1
-rw-r--r--apps/files/l10n/lt_LT.json1
-rw-r--r--apps/files/l10n/mk.js1
-rw-r--r--apps/files/l10n/mk.json1
-rw-r--r--apps/files/l10n/nb.js1
-rw-r--r--apps/files/l10n/nb.json1
-rw-r--r--apps/files/l10n/nl.js1
-rw-r--r--apps/files/l10n/nl.json1
-rw-r--r--apps/files/l10n/pl.js3
-rw-r--r--apps/files/l10n/pl.json3
-rw-r--r--apps/files/l10n/pt_BR.js9
-rw-r--r--apps/files/l10n/pt_BR.json9
-rw-r--r--apps/files/l10n/pt_PT.js1
-rw-r--r--apps/files/l10n/pt_PT.json1
-rw-r--r--apps/files/l10n/ro.js1
-rw-r--r--apps/files/l10n/ro.json1
-rw-r--r--apps/files/l10n/ru.js1
-rw-r--r--apps/files/l10n/ru.json1
-rw-r--r--apps/files/l10n/sc.js1
-rw-r--r--apps/files/l10n/sc.json1
-rw-r--r--apps/files/l10n/sk.js1
-rw-r--r--apps/files/l10n/sk.json1
-rw-r--r--apps/files/l10n/sl.js55
-rw-r--r--apps/files/l10n/sl.json55
-rw-r--r--apps/files/l10n/sr.js3
-rw-r--r--apps/files/l10n/sr.json3
-rw-r--r--apps/files/l10n/sv.js3
-rw-r--r--apps/files/l10n/sv.json3
-rw-r--r--apps/files/l10n/th.js1
-rw-r--r--apps/files/l10n/th.json1
-rw-r--r--apps/files/l10n/tr.js1
-rw-r--r--apps/files/l10n/tr.json1
-rw-r--r--apps/files/l10n/ug.js1
-rw-r--r--apps/files/l10n/ug.json1
-rw-r--r--apps/files/l10n/uk.js1
-rw-r--r--apps/files/l10n/uk.json1
-rw-r--r--apps/files/l10n/vi.js1
-rw-r--r--apps/files/l10n/vi.json1
-rw-r--r--apps/files/l10n/zh_CN.js4
-rw-r--r--apps/files/l10n/zh_CN.json4
-rw-r--r--apps/files/l10n/zh_HK.js3
-rw-r--r--apps/files/l10n/zh_HK.json3
-rw-r--r--apps/files/l10n/zh_TW.js3
-rw-r--r--apps/files/l10n/zh_TW.json3
-rw-r--r--apps/files/lib/Command/Copy.php7
-rw-r--r--apps/files/lib/Command/Move.php7
-rw-r--r--apps/files/lib/Command/SanitizeFilenames.php50
-rw-r--r--apps/files/lib/Command/TransferOwnership.php46
-rw-r--r--apps/files/lib/Service/OwnershipTransferService.php79
-rw-r--r--apps/files/lib/Service/UserConfig.php6
-rw-r--r--apps/files/src/components/FileEntry.vue46
-rw-r--r--apps/files/src/components/FileEntry/FileEntryPreview.vue12
-rw-r--r--apps/files/src/components/FilesListTableFooter.vue8
-rw-r--r--apps/files/src/components/FilesListTableHeader.vue12
-rw-r--r--apps/files/src/components/FilesListVirtual.vue19
-rw-r--r--apps/files/src/store/renaming.ts10
-rw-r--r--apps/files/src/store/userconfig.ts1
-rw-r--r--apps/files/src/types.ts1
-rw-r--r--apps/files/src/views/Settings.vue5
-rw-r--r--apps/files_external/l10n/de.js8
-rw-r--r--apps/files_external/l10n/de.json8
-rw-r--r--apps/files_external/l10n/de_DE.js8
-rw-r--r--apps/files_external/l10n/de_DE.json8
-rw-r--r--apps/files_external/tests/Storage/FtpTest.php2
-rw-r--r--apps/files_external/tests/Storage/SmbTest.php2
-rw-r--r--apps/files_sharing/l10n/de.js6
-rw-r--r--apps/files_sharing/l10n/de.json6
-rw-r--r--apps/files_sharing/l10n/de_DE.js4
-rw-r--r--apps/files_sharing/l10n/de_DE.json4
-rw-r--r--apps/files_sharing/l10n/ga.js3
-rw-r--r--apps/files_sharing/l10n/ga.json3
-rw-r--r--apps/files_sharing/lib/Cache.php2
-rw-r--r--apps/files_sharing/lib/Controller/PublicPreviewController.php14
-rw-r--r--apps/files_sharing/lib/External/Scanner.php3
-rw-r--r--apps/files_sharing/openapi.json23
-rw-r--r--apps/files_sharing/src/views/SharingDetailsTab.vue3
-rw-r--r--apps/files_sharing/tests/Controller/PublicPreviewControllerTest.php4
-rw-r--r--apps/files_sharing/tests/EncryptedSizePropagationTest.php11
-rw-r--r--apps/files_sharing/tests/TestCase.php4
-rw-r--r--apps/files_trashbin/l10n/de.js12
-rw-r--r--apps/files_trashbin/l10n/de.json12
-rw-r--r--apps/files_trashbin/l10n/de_DE.js6
-rw-r--r--apps/files_trashbin/l10n/de_DE.json6
-rw-r--r--apps/files_trashbin/lib/Command/CleanUp.php3
-rw-r--r--apps/files_trashbin/lib/Command/Size.php9
-rw-r--r--apps/files_trashbin/tests/TrashbinTest.php20
-rw-r--r--apps/files_versions/appinfo/routes.php10
-rw-r--r--apps/files_versions/lib/Listener/FileEventsListener.php9
-rw-r--r--apps/files_versions/lib/Versions/LegacyVersionsBackend.php12
-rw-r--r--apps/files_versions/tests/VersioningTest.php10
-rw-r--r--apps/settings/l10n/de.js12
-rw-r--r--apps/settings/l10n/de.json12
-rw-r--r--apps/settings/l10n/de_DE.js14
-rw-r--r--apps/settings/l10n/de_DE.json14
-rw-r--r--apps/settings/l10n/ru.js1
-rw-r--r--apps/settings/l10n/ru.json1
-rw-r--r--apps/settings/lib/Settings/Admin/Mail.php3
-rw-r--r--apps/settings/lib/Settings/Personal/PersonalInfo.php5
-rw-r--r--apps/settings/lib/UserMigration/AccountMigrator.php5
-rw-r--r--apps/systemtags/l10n/de.js2
-rw-r--r--apps/systemtags/l10n/de.json2
-rw-r--r--apps/systemtags/l10n/de_DE.js2
-rw-r--r--apps/systemtags/l10n/de_DE.json2
-rw-r--r--apps/theming/l10n/de.js2
-rw-r--r--apps/theming/l10n/de.json2
-rw-r--r--apps/theming/l10n/de_DE.js2
-rw-r--r--apps/theming/l10n/de_DE.json2
-rw-r--r--apps/twofactor_backupcodes/tests/Db/BackupCodeMapperTest.php12
-rw-r--r--apps/twofactor_backupcodes/tests/Service/BackupCodeStorageTest.php13
-rw-r--r--apps/twofactor_backupcodes/tests/Unit/Activity/ProviderTest.php21
-rw-r--r--apps/twofactor_backupcodes/tests/Unit/BackgroundJob/CheckBackupCodeTest.php24
-rw-r--r--apps/twofactor_backupcodes/tests/Unit/BackgroundJob/RememberBackupCodesJobTest.php25
-rw-r--r--apps/twofactor_backupcodes/tests/Unit/Controller/SettingsControllerTest.php27
-rw-r--r--apps/twofactor_backupcodes/tests/Unit/Listener/ActivityPublisherTest.php11
-rw-r--r--apps/twofactor_backupcodes/tests/Unit/Listener/ClearNotificationsTest.php9
-rw-r--r--apps/twofactor_backupcodes/tests/Unit/Listener/ProviderDisabledTest.php5
-rw-r--r--apps/twofactor_backupcodes/tests/Unit/Listener/ProviderEnabledTest.php5
-rw-r--r--apps/twofactor_backupcodes/tests/Unit/Listener/RegistryUpdaterTest.php13
-rw-r--r--apps/twofactor_backupcodes/tests/Unit/Migration/CheckBackupCodeTest.php9
-rw-r--r--apps/twofactor_backupcodes/tests/Unit/Notification/NotifierTest.php19
-rw-r--r--apps/twofactor_backupcodes/tests/Unit/Service/BackupCodeStorageTest.php21
-rw-r--r--apps/updatenotification/composer/autoload.php5
-rw-r--r--apps/updatenotification/composer/composer/autoload_classmap.php1
-rw-r--r--apps/updatenotification/composer/composer/autoload_static.php1
-rw-r--r--apps/updatenotification/lib/AppInfo/Application.php2
-rw-r--r--apps/updatenotification/lib/BackgroundJob/UpdateAvailableNotifications.php40
-rw-r--r--apps/updatenotification/lib/Command/Check.php16
-rw-r--r--apps/updatenotification/lib/Controller/APIController.php19
-rw-r--r--apps/updatenotification/lib/Controller/AdminController.php5
-rw-r--r--apps/updatenotification/lib/Manager.php2
-rw-r--r--apps/updatenotification/lib/Migration/Version011901Date20240305120000.php58
-rw-r--r--apps/updatenotification/lib/Notification/Notifier.php24
-rw-r--r--apps/updatenotification/lib/Settings/Admin.php10
-rw-r--r--apps/updatenotification/lib/UpdateChecker.php1
-rw-r--r--apps/updatenotification/tests/BackgroundJob/ResetTokenTest.php6
-rw-r--r--apps/updatenotification/tests/BackgroundJob/UpdateAvailableNotificationsTest.php54
-rw-r--r--apps/updatenotification/tests/Controller/AdminControllerTest.php14
-rw-r--r--apps/updatenotification/tests/Notification/NotifierTest.php21
-rw-r--r--apps/updatenotification/tests/Settings/AdminTest.php104
-rw-r--r--apps/user_ldap/lib/User/User.php4
-rw-r--r--apps/user_status/tests/Unit/BackgroundJob/ClearOldStatusesBackgroundJobTest.php13
-rw-r--r--apps/user_status/tests/Unit/CapabilitiesTest.php13
-rw-r--r--apps/user_status/tests/Unit/Connector/UserStatusProviderTest.php9
-rw-r--r--apps/user_status/tests/Unit/Controller/PredefinedStatusControllerTest.php12
-rw-r--r--apps/user_status/tests/Unit/Controller/StatusesControllerTest.php9
-rw-r--r--apps/user_status/tests/Unit/Controller/UserStatusControllerTest.php68
-rw-r--r--apps/user_status/tests/Unit/Dashboard/UserStatusWidgetTest.php33
-rw-r--r--apps/user_status/tests/Unit/Db/UserStatusMapperTest.php16
-rw-r--r--apps/user_status/tests/Unit/Listener/UserDeletedListenerTest.php9
-rw-r--r--apps/user_status/tests/Unit/Listener/UserLiveStatusListenerTest.php37
-rw-r--r--apps/user_status/tests/Unit/Service/PredefinedStatusServiceTest.php33
-rw-r--r--apps/user_status/tests/Unit/Service/StatusServiceTest.php86
-rw-r--r--apps/webhook_listeners/tests/Db/WebhookListenerMapperTest.php2
-rw-r--r--apps/workflowengine/tests/Check/AbstractStringCheckTest.php38
-rw-r--r--apps/workflowengine/tests/Check/RequestRemoteAddressTest.php43
-rw-r--r--apps/workflowengine/tests/Check/RequestTimeTest.php46
-rw-r--r--apps/workflowengine/tests/Check/RequestUserAgentTest.php26
252 files changed, 2047 insertions, 1394 deletions
diff --git a/apps/admin_audit/lib/Actions/Files.php b/apps/admin_audit/lib/Actions/Files.php
index f07ed254272..7be4a7cd581 100644
--- a/apps/admin_audit/lib/Actions/Files.php
+++ b/apps/admin_audit/lib/Actions/Files.php
@@ -10,7 +10,6 @@ namespace OCA\AdminAudit\Actions;
use OC\Files\Node\NonExistingFile;
use OCP\Files\Events\Node\BeforeNodeDeletedEvent;
use OCP\Files\Events\Node\BeforeNodeReadEvent;
-use OCP\Files\Events\Node\BeforeNodeRenamedEvent;
use OCP\Files\Events\Node\NodeCopiedEvent;
use OCP\Files\Events\Node\NodeCreatedEvent;
use OCP\Files\Events\Node\NodeRenamedEvent;
@@ -26,9 +25,6 @@ use Psr\Log\LoggerInterface;
* @package OCA\AdminAudit\Actions
*/
class Files extends Action {
-
- private array $renamedNodes = [];
-
/**
* Logs file read actions
*/
@@ -55,28 +51,13 @@ class Files extends Action {
/**
* Logs rename actions of files
*/
- public function beforeRename(BeforeNodeRenamedEvent $event): void {
- try {
- $source = $event->getSource();
- $this->renamedNodes[$source->getId()] = $source;
- } catch (InvalidPathException|NotFoundException $e) {
- Server::get(LoggerInterface::class)->error(
- 'Exception thrown in file rename: ' . $e->getMessage(), ['app' => 'admin_audit', 'exception' => $e]
- );
- return;
- }
- }
-
- /**
- * Logs rename actions of files
- */
public function afterRename(NodeRenamedEvent $event): void {
try {
$target = $event->getTarget();
- $originalSource = $this->renamedNodes[$target->getId()];
+ $source = $event->getSource();
$params = [
'newid' => $target->getId(),
- 'oldpath' => $originalSource->getPath(),
+ 'oldpath' => $source->getPath(),
'newpath' => $target->getPath(),
];
} catch (InvalidPathException|NotFoundException $e) {
diff --git a/apps/admin_audit/lib/AppInfo/Application.php b/apps/admin_audit/lib/AppInfo/Application.php
index baf73b92b0d..63a1d065bc8 100644
--- a/apps/admin_audit/lib/AppInfo/Application.php
+++ b/apps/admin_audit/lib/AppInfo/Application.php
@@ -42,7 +42,6 @@ use OCP\Console\ConsoleEvent;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Events\Node\BeforeNodeDeletedEvent;
use OCP\Files\Events\Node\BeforeNodeReadEvent;
-use OCP\Files\Events\Node\BeforeNodeRenamedEvent;
use OCP\Files\Events\Node\NodeCopiedEvent;
use OCP\Files\Events\Node\NodeCreatedEvent;
use OCP\Files\Events\Node\NodeRenamedEvent;
@@ -171,13 +170,6 @@ class Application extends App implements IBootstrap {
$fileActions = new Files($logger);
$eventDispatcher->addListener(
- BeforeNodeRenamedEvent::class,
- function (BeforeNodeRenamedEvent $event) use ($fileActions): void {
- $fileActions->beforeRename($event);
- }
- );
-
- $eventDispatcher->addListener(
NodeRenamedEvent::class,
function (NodeRenamedEvent $event) use ($fileActions): void {
$fileActions->afterRename($event);
diff --git a/apps/comments/tests/Unit/Activity/ListenerTest.php b/apps/comments/tests/Unit/Activity/ListenerTest.php
index 70dec741978..675a28a16b1 100644
--- a/apps/comments/tests/Unit/Activity/ListenerTest.php
+++ b/apps/comments/tests/Unit/Activity/ListenerTest.php
@@ -1,4 +1,7 @@
<?php
+
+declare(strict_types=1);
+
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -20,30 +23,17 @@ use OCP\Files\Node;
use OCP\IUser;
use OCP\IUserSession;
use OCP\Share\IShareHelper;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class ListenerTest extends TestCase {
-
- /** @var Listener */
- protected $listener;
-
- /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $activityManager;
-
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- protected $session;
-
- /** @var IAppManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $appManager;
-
- /** @var IMountProviderCollection|\PHPUnit\Framework\MockObject\MockObject */
- protected $mountProviderCollection;
-
- /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject */
- protected $rootFolder;
-
- /** @var IShareHelper|\PHPUnit\Framework\MockObject\MockObject */
- protected $shareHelper;
+ protected IManager&MockObject $activityManager;
+ protected IUserSession&MockObject $session;
+ protected IAppManager&MockObject $appManager;
+ protected IMountProviderCollection&MockObject $mountProviderCollection;
+ protected IRootFolder&MockObject $rootFolder;
+ protected IShareHelper&MockObject $shareHelper;
+ protected Listener $listener;
protected function setUp(): void {
parent::setUp();
@@ -76,7 +66,7 @@ class ListenerTest extends TestCase {
->method('getObjectType')
->willReturn('files');
- /** @var CommentsEvent|\PHPUnit\Framework\MockObject\MockObject $event */
+ /** @var CommentsEvent|MockObject $event */
$event = $this->createMock(CommentsEvent::class);
$event->expects($this->any())
->method('getComment')
@@ -85,13 +75,13 @@ class ListenerTest extends TestCase {
->method('getEvent')
->willReturn(CommentsEvent::EVENT_ADD);
- /** @var IUser|\PHPUnit\Framework\MockObject\MockObject $ownerUser */
+ /** @var IUser|MockObject $ownerUser */
$ownerUser = $this->createMock(IUser::class);
$ownerUser->expects($this->any())
->method('getUID')
->willReturn('937393');
- /** @var \PHPUnit\Framework\MockObject\MockObject $mount */
+ /** @var MockObject $mount */
$mount = $this->createMock(ICachedMountFileInfo::class);
$mount->expects($this->any())
->method('getUser')
@@ -133,7 +123,7 @@ class ListenerTest extends TestCase {
->method('getUser')
->willReturn($ownerUser);
- /** @var \PHPUnit\Framework\MockObject\MockObject $activity */
+ /** @var MockObject $activity */
$activity = $this->createMock(IEvent::class);
$activity->expects($this->exactly(count($al['users'])))
->method('setAffectedUser');
diff --git a/apps/comments/tests/Unit/AppInfo/ApplicationTest.php b/apps/comments/tests/Unit/AppInfo/ApplicationTest.php
index abd5b188d44..119db5333b5 100644
--- a/apps/comments/tests/Unit/AppInfo/ApplicationTest.php
+++ b/apps/comments/tests/Unit/AppInfo/ApplicationTest.php
@@ -1,5 +1,7 @@
<?php
+declare(strict_types=1);
+
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -7,7 +9,12 @@
*/
namespace OCA\Comments\Tests\Unit\AppInfo;
+use OCA\Comments\Activity\Filter;
+use OCA\Comments\Activity\Listener;
+use OCA\Comments\Activity\Provider;
+use OCA\Comments\Activity\Setting;
use OCA\Comments\AppInfo\Application;
+use OCA\Comments\Controller\NotificationsController;
use OCA\Comments\Notification\Notifier;
use OCP\IUserManager;
use OCP\IUserSession;
@@ -38,12 +45,12 @@ class ApplicationTest extends TestCase {
$c = $app->getContainer();
$services = [
- 'OCA\Comments\Controller\NotificationsController',
- 'OCA\Comments\Activity\Filter',
- 'OCA\Comments\Activity\Listener',
- 'OCA\Comments\Activity\Provider',
- 'OCA\Comments\Activity\Setting',
- 'OCA\Comments\Notification\Listener',
+ NotificationsController::class,
+ Filter::class,
+ Listener::class,
+ Provider::class,
+ Setting::class,
+ \OCA\Comments\Notification\Listener::class,
Notifier::class,
];
diff --git a/apps/comments/tests/Unit/Collaboration/CommentersSorterTest.php b/apps/comments/tests/Unit/Collaboration/CommentersSorterTest.php
index c0de0016c31..525bf5e67c8 100644
--- a/apps/comments/tests/Unit/Collaboration/CommentersSorterTest.php
+++ b/apps/comments/tests/Unit/Collaboration/CommentersSorterTest.php
@@ -8,13 +8,12 @@ namespace OCA\Comments\Tests\Unit\Collaboration;
use OCA\Comments\Collaboration\CommentersSorter;
use OCP\Comments\IComment;
use OCP\Comments\ICommentsManager;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class CommentersSorterTest extends TestCase {
- /** @var ICommentsManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $commentsManager;
- /** @var CommentersSorter */
- protected $sorter;
+ protected ICommentsManager&MockObject $commentsManager;
+ protected CommentersSorter $sorter;
protected function setUp(): void {
parent::setUp();
@@ -55,7 +54,7 @@ class CommentersSorterTest extends TestCase {
$this->assertEquals($data['expected'], $workArray);
}
- public function sortDataProvider() {
+ public static function sortDataProvider(): array {
return [[
[
#1 – sort properly and otherwise keep existing order
diff --git a/apps/comments/tests/Unit/Controller/NotificationsTest.php b/apps/comments/tests/Unit/Controller/NotificationsTest.php
index ccd808895c8..59d0b9ccb00 100644
--- a/apps/comments/tests/Unit/Controller/NotificationsTest.php
+++ b/apps/comments/tests/Unit/Controller/NotificationsTest.php
@@ -1,5 +1,7 @@
<?php
+declare(strict_types=1);
+
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
@@ -22,26 +24,16 @@ use OCP\IUser;
use OCP\IUserSession;
use OCP\Notification\IManager;
use OCP\Notification\INotification;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class NotificationsTest extends TestCase {
- /** @var NotificationsController */
- protected $notificationsController;
-
- /** @var ICommentsManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $commentsManager;
-
- /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject */
- protected $rootFolder;
-
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- protected $session;
-
- /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $notificationManager;
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- protected $urlGenerator;
+ protected ICommentsManager&MockObject $commentsManager;
+ protected IRootFolder&MockObject $rootFolder;
+ protected IUserSession&MockObject $session;
+ protected IManager&MockObject $notificationManager;
+ protected IURLGenerator&MockObject $urlGenerator;
+ protected NotificationsController $notificationsController;
protected function setUp(): void {
parent::setUp();
@@ -81,10 +73,6 @@ class NotificationsTest extends TestCase {
$this->urlGenerator->expects($this->exactly(2))
->method('linkToRoute')
- ->withConsecutive(
- ['comments.Notifications.view', ['id' => '42']],
- ['core.login.showLoginForm', ['redirect_url' => 'link-to-comment']]
- )
->willReturnMap([
['comments.Notifications.view', ['id' => '42'], 'link-to-comment'],
['core.login.showLoginForm', ['redirect_url' => 'link-to-comment'], 'link-to-login'],
diff --git a/apps/comments/tests/Unit/EventHandlerTest.php b/apps/comments/tests/Unit/EventHandlerTest.php
index 83ce1af57da..df2876e20a3 100644
--- a/apps/comments/tests/Unit/EventHandlerTest.php
+++ b/apps/comments/tests/Unit/EventHandlerTest.php
@@ -1,4 +1,7 @@
<?php
+
+declare(strict_types=1);
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -10,43 +13,32 @@ use OCA\Comments\Listener\CommentsEventListener;
use OCA\Comments\Notification\Listener as NotificationListener;
use OCP\Comments\CommentsEvent;
use OCP\Comments\IComment;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class EventHandlerTest extends TestCase {
- /** @var CommentsEventListener */
- protected $eventHandler;
-
- /** @var ActivityListener|\PHPUnit\Framework\MockObject\MockObject */
- protected $activityListener;
-
- /** @var NotificationListener|\PHPUnit\Framework\MockObject\MockObject */
- protected $notificationListener;
+ protected ActivityListener&MockObject $activityListener;
+ protected NotificationListener&MockObject $notificationListener;
+ protected CommentsEventListener $eventHandler;
protected function setUp(): void {
parent::setUp();
- $this->activityListener = $this->getMockBuilder(ActivityListener::class)
- ->disableOriginalConstructor()
- ->getMock();
-
- $this->notificationListener = $this->getMockBuilder(NotificationListener::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->activityListener = $this->createMock(ActivityListener::class);
+ $this->notificationListener = $this->createMock(NotificationListener::class);
$this->eventHandler = new CommentsEventListener($this->activityListener, $this->notificationListener);
}
public function testNotFiles(): void {
- /** @var IComment|\PHPUnit\Framework\MockObject\MockObject $comment */
- $comment = $this->getMockBuilder(IComment::class)->getMock();
+ /** @var IComment|MockObject $comment */
+ $comment = $this->createMock(IComment::class);
$comment->expects($this->once())
->method('getObjectType')
->willReturn('smiles');
- /** @var CommentsEvent|\PHPUnit\Framework\MockObject\MockObject $event */
- $event = $this->getMockBuilder(CommentsEvent::class)
- ->disableOriginalConstructor()
- ->getMock();
+ /** @var CommentsEvent|MockObject $event */
+ $event = $this->createMock(CommentsEvent::class);
$event->expects($this->once())
->method('getComment')
->willReturn($comment);
@@ -56,7 +48,7 @@ class EventHandlerTest extends TestCase {
$this->eventHandler->handle($event);
}
- public function handledProvider() {
+ public static function handledProvider(): array {
return [
[CommentsEvent::EVENT_DELETE],
[CommentsEvent::EVENT_UPDATE],
@@ -67,19 +59,16 @@ class EventHandlerTest extends TestCase {
/**
* @dataProvider handledProvider
- * @param string $eventType
*/
- public function testHandled($eventType): void {
- /** @var IComment|\PHPUnit\Framework\MockObject\MockObject $comment */
- $comment = $this->getMockBuilder(IComment::class)->getMock();
+ public function testHandled(string $eventType): void {
+ /** @var IComment|MockObject $comment */
+ $comment = $this->createMock(IComment::class);
$comment->expects($this->once())
->method('getObjectType')
->willReturn('files');
- /** @var CommentsEvent|\PHPUnit\Framework\MockObject\MockObject $event */
- $event = $this->getMockBuilder(CommentsEvent::class)
- ->disableOriginalConstructor()
- ->getMock();
+ /** @var CommentsEvent|MockObject $event */
+ $event = $this->createMock(CommentsEvent::class);
$event->expects($this->atLeastOnce())
->method('getComment')
->willReturn($comment);
diff --git a/apps/comments/tests/Unit/Notification/ListenerTest.php b/apps/comments/tests/Unit/Notification/ListenerTest.php
index a9175b7e203..ae5a3c40bc6 100644
--- a/apps/comments/tests/Unit/Notification/ListenerTest.php
+++ b/apps/comments/tests/Unit/Notification/ListenerTest.php
@@ -14,25 +14,19 @@ use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\Notification\IManager;
use OCP\Notification\INotification;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class ListenerTest extends TestCase {
- /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $notificationManager;
-
- /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $userManager;
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- protected $urlGenerator;
-
- /** @var Listener */
- protected $listener;
+ protected IManager&MockObject $notificationManager;
+ protected IUserManager&MockObject $userManager;
+ protected IURLGenerator&MockObject $urlGenerator;
+ protected Listener $listener;
protected function setUp(): void {
parent::setUp();
- $this->notificationManager = $this->createMock(\OCP\Notification\IManager::class);
+ $this->notificationManager = $this->createMock(IManager::class);
$this->userManager = $this->createMock(IUserManager::class);
$this->listener = new Listener(
@@ -41,7 +35,7 @@ class ListenerTest extends TestCase {
);
}
- public function eventProvider() {
+ public static function eventProvider(): array {
return [
[CommentsEvent::EVENT_ADD, 'notify'],
[CommentsEvent::EVENT_UPDATE, 'notify'],
@@ -56,8 +50,8 @@ class ListenerTest extends TestCase {
* @param string $notificationMethod
*/
public function testEvaluate($eventType, $notificationMethod): void {
- /** @var IComment|\PHPUnit\Framework\MockObject\MockObject $comment */
- $comment = $this->getMockBuilder(IComment::class)->getMock();
+ /** @var IComment|MockObject $comment */
+ $comment = $this->createMock(IComment::class);
$comment->expects($this->any())
->method('getObjectType')
->willReturn('files');
@@ -78,10 +72,8 @@ class ListenerTest extends TestCase {
->method('getId')
->willReturn('1234');
- /** @var CommentsEvent|\PHPUnit\Framework\MockObject\MockObject $event */
- $event = $this->getMockBuilder(CommentsEvent::class)
- ->disableOriginalConstructor()
- ->getMock();
+ /** @var CommentsEvent|MockObject $event */
+ $event = $this->createMock(CommentsEvent::class);
$event->expects($this->once())
->method('getComment')
->willReturn($comment);
@@ -89,8 +81,8 @@ class ListenerTest extends TestCase {
->method(('getEvent'))
->willReturn($eventType);
- /** @var INotification|\PHPUnit\Framework\MockObject\MockObject $notification */
- $notification = $this->getMockBuilder(INotification::class)->getMock();
+ /** @var INotification|MockObject $notification */
+ $notification = $this->createMock(INotification::class);
$notification->expects($this->any())
->method($this->anything())
->willReturn($notification);
@@ -106,26 +98,24 @@ class ListenerTest extends TestCase {
$this->userManager->expects($this->exactly(6))
->method('userExists')
- ->withConsecutive(
- ['foobar'],
- ['barfoo'],
- ['foo@bar.com'],
- ['bar@foo.org@foobar.io'],
- ['23452-4333-54353-2342'],
- ['yolo']
- )
- ->willReturn(true);
+ ->willReturnMap([
+ ['foobar', true],
+ ['barfoo', true],
+ ['foo@bar.com', true],
+ ['bar@foo.org@foobar.io', true],
+ ['23452-4333-54353-2342', true],
+ ['yolo', true]
+ ]);
$this->listener->evaluate($event);
}
/**
* @dataProvider eventProvider
- * @param string $eventType
*/
- public function testEvaluateNoMentions($eventType): void {
- /** @var IComment|\PHPUnit\Framework\MockObject\MockObject $comment */
- $comment = $this->getMockBuilder(IComment::class)->getMock();
+ public function testEvaluateNoMentions(string $eventType): void {
+ /** @var IComment|MockObject $comment */
+ $comment = $this->createMock(IComment::class);
$comment->expects($this->any())
->method('getObjectType')
->willReturn('files');
@@ -136,10 +126,8 @@ class ListenerTest extends TestCase {
->method('getMentions')
->willReturn([]);
- /** @var CommentsEvent|\PHPUnit\Framework\MockObject\MockObject $event */
- $event = $this->getMockBuilder(CommentsEvent::class)
- ->disableOriginalConstructor()
- ->getMock();
+ /** @var CommentsEvent|MockObject $event */
+ $event = $this->createMock(CommentsEvent::class);
$event->expects($this->once())
->method('getComment')
->willReturn($comment);
@@ -161,8 +149,8 @@ class ListenerTest extends TestCase {
}
public function testEvaluateUserDoesNotExist(): void {
- /** @var IComment|\PHPUnit\Framework\MockObject\MockObject $comment */
- $comment = $this->getMockBuilder(IComment::class)->getMock();
+ /** @var IComment|MockObject $comment */
+ $comment = $this->createMock(IComment::class);
$comment->expects($this->any())
->method('getObjectType')
->willReturn('files');
@@ -176,10 +164,8 @@ class ListenerTest extends TestCase {
->method('getId')
->willReturn('1234');
- /** @var CommentsEvent|\PHPUnit\Framework\MockObject\MockObject $event */
- $event = $this->getMockBuilder(CommentsEvent::class)
- ->disableOriginalConstructor()
- ->getMock();
+ /** @var CommentsEvent|MockObject $event */
+ $event = $this->createMock(CommentsEvent::class);
$event->expects($this->once())
->method('getComment')
->willReturn($comment);
@@ -187,8 +173,8 @@ class ListenerTest extends TestCase {
->method(('getEvent'))
->willReturn(CommentsEvent::EVENT_ADD);
- /** @var INotification|\PHPUnit\Framework\MockObject\MockObject $notification */
- $notification = $this->getMockBuilder(INotification::class)->getMock();
+ /** @var INotification|MockObject $notification */
+ $notification = $this->createMock(INotification::class);
$notification->expects($this->any())
->method($this->anything())
->willReturn($notification);
@@ -203,9 +189,7 @@ class ListenerTest extends TestCase {
$this->userManager->expects($this->once())
->method('userExists')
- ->withConsecutive(
- ['foobar']
- )
+ ->with('foobar')
->willReturn(false);
$this->listener->evaluate($event);
diff --git a/apps/comments/tests/Unit/Notification/NotifierTest.php b/apps/comments/tests/Unit/Notification/NotifierTest.php
index 87b87e646af..37cad0b43df 100644
--- a/apps/comments/tests/Unit/Notification/NotifierTest.php
+++ b/apps/comments/tests/Unit/Notification/NotifierTest.php
@@ -1,4 +1,7 @@
<?php
+
+declare(strict_types=1);
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -23,26 +26,16 @@ use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class NotifierTest extends TestCase {
- /** @var Notifier */
- protected $notifier;
- /** @var IFactory|MockObject */
- protected $l10nFactory;
- /** @var IL10N|MockObject */
- protected $l;
- /** @var IRootFolder|MockObject */
- protected $folder;
- /** @var ICommentsManager|MockObject */
- protected $commentsManager;
- /** @var IURLGenerator|MockObject */
- protected $url;
- /** @var IUserManager|MockObject */
- protected $userManager;
- /** @var INotification|MockObject */
- protected $notification;
- /** @var IComment|MockObject */
- protected $comment;
- /** @var string */
- protected $lc = 'tlh_KX';
+ protected IFactory&MockObject $l10nFactory;
+ protected IL10N&MockObject $l;
+ protected IRootFolder&MockObject $folder;
+ protected ICommentsManager&MockObject $commentsManager;
+ protected IURLGenerator&MockObject $url;
+ protected IUserManager&MockObject $userManager;
+ protected INotification&MockObject $notification;
+ protected IComment&MockObject $comment;
+ protected Notifier $notifier;
+ protected string $lc = 'tlh_KX';
protected function setUp(): void {
parent::setUp();
@@ -75,9 +68,8 @@ class NotifierTest extends TestCase {
public function testPrepareSuccess(): void {
$fileName = 'Gre\'thor.odp';
$displayName = 'Huraga';
- $message = '@Huraga mentioned you in a comment on "Gre\'thor.odp"';
- /** @var Node|MockObject $node */
+ /** @var Node&MockObject $node */
$node = $this->createMock(Node::class);
$node
->expects($this->atLeastOnce())
@@ -192,7 +184,6 @@ class NotifierTest extends TestCase {
public function testPrepareSuccessDeletedUser(): void {
$fileName = 'Gre\'thor.odp';
- $message = 'You were mentioned on "Gre\'thor.odp", in a comment by an account that has since been deleted';
/** @var Node|MockObject $node */
$node = $this->createMock(Node::class);
diff --git a/apps/contactsinteraction/tests/Db/RecentContactMapperTest.php b/apps/contactsinteraction/tests/Db/RecentContactMapperTest.php
index 89e192d9da7..f5df27820d7 100644
--- a/apps/contactsinteraction/tests/Db/RecentContactMapperTest.php
+++ b/apps/contactsinteraction/tests/Db/RecentContactMapperTest.php
@@ -21,12 +21,8 @@ use Test\TestCase;
* @group DB
*/
class RecentContactMapperTest extends TestCase {
-
- /** @var RecentContactMapper */
- private $recentContactMapper;
-
- /** @var ITimeFactory */
- private $time;
+ private RecentContactMapper $recentContactMapper;
+ private ITimeFactory $time;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/dashboard/tests/DashboardServiceTest.php b/apps/dashboard/tests/DashboardServiceTest.php
index c603b88e7ff..ebcd06cdf03 100644
--- a/apps/dashboard/tests/DashboardServiceTest.php
+++ b/apps/dashboard/tests/DashboardServiceTest.php
@@ -40,7 +40,7 @@ class DashboardServiceTest extends TestCase {
);
}
- public function testGetBirthdate() {
+ public function testGetBirthdate(): void {
$user = $this->createMock(IUser::class);
$this->userManager->method('get')
->willReturn($user);
@@ -61,7 +61,7 @@ class DashboardServiceTest extends TestCase {
$this->assertEquals('2024-12-10T00:00:00.000Z', $birthdate);
}
- public function testGetBirthdatePropertyDoesNotExist() {
+ public function testGetBirthdatePropertyDoesNotExist(): void {
$user = $this->createMock(IUser::class);
$this->userManager->method('get')
->willReturn($user);
@@ -75,7 +75,7 @@ class DashboardServiceTest extends TestCase {
$this->assertEquals('', $birthdate);
}
- public function testGetBirthdateUserNotFound() {
+ public function testGetBirthdateUserNotFound(): void {
$this->userManager->method('get')
->willReturn(null);
@@ -84,7 +84,7 @@ class DashboardServiceTest extends TestCase {
$this->assertEquals('', $birthdate);
}
- public function testGetBirthdateNoUserId() {
+ public function testGetBirthdateNoUserId(): void {
$service = new DashboardService(
$this->config,
null,
diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml
index ac8886555f6..e0f4608e8c2 100644
--- a/apps/dav/appinfo/info.xml
+++ b/apps/dav/appinfo/info.xml
@@ -55,6 +55,7 @@
</repair-steps>
<commands>
+ <command>OCA\DAV\Command\ClearCalendarUnshares</command>
<command>OCA\DAV\Command\CreateAddressBook</command>
<command>OCA\DAV\Command\CreateCalendar</command>
<command>OCA\DAV\Command\CreateSubscription</command>
@@ -63,6 +64,7 @@
<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/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php
index 466ef98d433..913f5b46d98 100644
--- a/apps/dav/composer/composer/autoload_classmap.php
+++ b/apps/dav/composer/composer/autoload_classmap.php
@@ -155,6 +155,7 @@ 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\\CreateAddressBook' => $baseDir . '/../lib/Command/CreateAddressBook.php',
'OCA\\DAV\\Command\\CreateCalendar' => $baseDir . '/../lib/Command/CreateCalendar.php',
'OCA\\DAV\\Command\\CreateSubscription' => $baseDir . '/../lib/Command/CreateSubscription.php',
@@ -163,6 +164,7 @@ return array(
'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',
diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php
index 995d27adc2d..6369511343e 100644
--- a/apps/dav/composer/composer/autoload_static.php
+++ b/apps/dav/composer/composer/autoload_static.php
@@ -170,6 +170,7 @@ 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\\CreateAddressBook' => __DIR__ . '/..' . '/../lib/Command/CreateAddressBook.php',
'OCA\\DAV\\Command\\CreateCalendar' => __DIR__ . '/..' . '/../lib/Command/CreateCalendar.php',
'OCA\\DAV\\Command\\CreateSubscription' => __DIR__ . '/..' . '/../lib/Command/CreateSubscription.php',
@@ -178,6 +179,7 @@ class ComposerStaticInitDAV
'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',
diff --git a/apps/dav/l10n/de.js b/apps/dav/l10n/de.js
index cf6e45c577d..d6569cdc4f9 100644
--- a/apps/dav/l10n/de.js
+++ b/apps/dav/l10n/de.js
@@ -274,10 +274,10 @@ 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",
@@ -291,7 +291,7 @@ OC.L10N.register(
"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.",
"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}.",
diff --git a/apps/dav/l10n/de.json b/apps/dav/l10n/de.json
index 6fceefcf9a7..e3a6f980ba1 100644
--- a/apps/dav/l10n/de.json
+++ b/apps/dav/l10n/de.json
@@ -272,10 +272,10 @@
"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",
@@ -289,7 +289,7 @@
"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.",
"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}.",
diff --git a/apps/dav/l10n/de_DE.js b/apps/dav/l10n/de_DE.js
index f513d35cdc9..1072d8f9ff2 100644
--- a/apps/dav/l10n/de_DE.js
+++ b/apps/dav/l10n/de_DE.js
@@ -274,7 +274,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",
@@ -284,16 +284,16 @@ OC.L10N.register(
"Time zone:" : "Zeitzone:",
"to" : "an",
"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.",
"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",
diff --git a/apps/dav/l10n/de_DE.json b/apps/dav/l10n/de_DE.json
index e27822fbaa6..721cee8c91a 100644
--- a/apps/dav/l10n/de_DE.json
+++ b/apps/dav/l10n/de_DE.json
@@ -272,7 +272,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",
@@ -282,16 +282,16 @@
"Time zone:" : "Zeitzone:",
"to" : "an",
"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.",
"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",
diff --git a/apps/dav/l10n/et_EE.js b/apps/dav/l10n/et_EE.js
index cfa243264fa..69f941b3daa 100644
--- a/apps/dav/l10n/et_EE.js
+++ b/apps/dav/l10n/et_EE.js
@@ -180,6 +180,7 @@ OC.L10N.register(
"Delete slot" : "Kustuta ajavahemik",
"No working hours set" : "Tööajad on sisestamata",
"Add slot" : "Lisa ajavahemik",
+ "Weekdays" : "Nädalapäevad",
"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.",
"Availability" : "Saadavus",
"Absence" : "Äraolek",
diff --git a/apps/dav/l10n/et_EE.json b/apps/dav/l10n/et_EE.json
index 51f4d2bc914..2eed43d0c8f 100644
--- a/apps/dav/l10n/et_EE.json
+++ b/apps/dav/l10n/et_EE.json
@@ -178,6 +178,7 @@
"Delete slot" : "Kustuta ajavahemik",
"No working hours set" : "Tööajad on sisestamata",
"Add slot" : "Lisa ajavahemik",
+ "Weekdays" : "Nädalapäevad",
"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.",
"Availability" : "Saadavus",
"Absence" : "Äraolek",
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php
index e69fe9ed3f0..5643e89d797 100644
--- a/apps/dav/lib/CalDAV/CalDavBackend.php
+++ b/apps/dav/lib/CalDAV/CalDavBackend.php
@@ -90,6 +90,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;
@@ -374,7 +387,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')
@@ -651,7 +664,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);
@@ -3671,4 +3685,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 789fe4b55c0..1d88d04a5e3 100644
--- a/apps/dav/lib/CalDAV/Calendar.php
+++ b/apps/dav/lib/CalDAV/Calendar.php
@@ -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;
}
diff --git a/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php b/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php
index e1bd2f5be29..236039e4890 100644
--- a/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php
+++ b/apps/dav/lib/CalDAV/ResourceBooking/AbstractPrincipalBackend.php
@@ -25,12 +25,6 @@ use function array_values;
abstract class AbstractPrincipalBackend implements BackendInterface {
- /** @var ProxyMapper */
- private $proxyMapper;
-
- /** @var string */
- private $principalPrefix;
-
/** @var string */
private $dbTableName;
@@ -45,13 +39,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';
diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php
index b15ed607076..de209754ae4 100644
--- a/apps/dav/lib/CardDAV/CardDavBackend.php
+++ b/apps/dav/lib/CardDAV/CardDavBackend.php
@@ -137,7 +137,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'])
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/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/Connector/Sabre/Principal.php b/apps/dav/lib/Connector/Sabre/Principal.php
index 67edb1c4035..e49c61f6e1f 100644
--- a/apps/dav/lib/Connector/Sabre/Principal.php
+++ b/apps/dav/lib/Connector/Sabre/Principal.php
@@ -41,9 +41,6 @@ class Principal implements BackendInterface {
/** @var bool */
private $hasCircles;
- /** @var ProxyMapper */
- private $proxyMapper;
-
/** @var KnownUserService */
private $knownUserService;
@@ -54,7 +51,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 +59,6 @@ class Principal implements BackendInterface {
) {
$this->principalPrefix = trim($principalPrefix, '/');
$this->hasGroups = $this->hasCircles = ($principalPrefix === 'principals/users/');
- $this->proxyMapper = $proxyMapper;
$this->knownUserService = $knownUserService;
}
diff --git a/apps/dav/lib/Connector/Sabre/ServerFactory.php b/apps/dav/lib/Connector/Sabre/ServerFactory.php
index bdd13b7f44e..214412e1744 100644
--- a/apps/dav/lib/Connector/Sabre/ServerFactory.php
+++ b/apps/dav/lib/Connector/Sabre/ServerFactory.php
@@ -15,6 +15,7 @@ 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;
@@ -150,7 +151,7 @@ class ServerFactory {
);
// Mount the share collection at /public.php/dav/shares/<share token>
- $rootCollection->addChild(new \OCA\DAV\Files\Sharing\RootCollection(
+ $rootCollection->addChild(new RootCollection(
$root,
$userPrincipalBackend,
'principals/shares',
diff --git a/apps/dav/lib/DAV/Sharing/Backend.php b/apps/dav/lib/DAV/Sharing/Backend.php
index 06a082628d3..de0d6891b7c 100644
--- a/apps/dav/lib/DAV/Sharing/Backend.php
+++ b/apps/dav/lib/DAV/Sharing/Backend.php
@@ -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/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/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/CalDAV/CalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
index 61c03c9e4c1..825d798e7e1 100644
--- a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
@@ -17,6 +17,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;
@@ -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');
@@ -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/CalendarTest.php b/apps/dav/tests/unit/CalDAV/CalendarTest.php
index 6433af8c340..7f2d0052162 100644
--- a/apps/dav/tests/unit/CalDAV/CalendarTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalendarTest.php
@@ -43,12 +43,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 +62,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',
diff --git a/apps/dav/tests/unit/Command/ListCalendarSharesTest.php b/apps/dav/tests/unit/Command/ListCalendarSharesTest.php
new file mode 100644
index 00000000000..3b3f3a1519e
--- /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\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/Connector/Sabre/DirectoryTest.php b/apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php
index f6c19787e94..7fefe3e06da 100644
--- a/apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php
@@ -15,6 +15,7 @@ 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;
@@ -286,7 +287,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())
@@ -342,7 +343,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())
diff --git a/apps/dav/tests/unit/DAV/Sharing/BackendTest.php b/apps/dav/tests/unit/DAV/Sharing/BackendTest.php
index 344d57d1808..dd2681d149f 100644
--- a/apps/dav/tests/unit/DAV/Sharing/BackendTest.php
+++ b/apps/dav/tests/unit/DAV/Sharing/BackendTest.php
@@ -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/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/files/l10n/ar.js b/apps/files/l10n/ar.js
index c753ed59ac9..59a1b312fa6 100644
--- a/apps/files/l10n/ar.js
+++ b/apps/files/l10n/ar.js
@@ -95,6 +95,7 @@ OC.L10N.register(
"Invalid filename." : "اسم ملف غير صحيح.",
"Renamed \"{oldName}\" to \"{newName}\"" : "تمت إعادة تسمية \"{oldName}\" إلى \"{newName}\"",
"Rename file" : "إعادة تسمية الملف",
+ "Folder" : "مجلد",
"Pending" : "قيد الانتظار",
"Unknown date" : "تاريخ غير معروف",
"Clear filter" : "إزالة التصفية",
diff --git a/apps/files/l10n/ar.json b/apps/files/l10n/ar.json
index 8d3759847a6..36243f82425 100644
--- a/apps/files/l10n/ar.json
+++ b/apps/files/l10n/ar.json
@@ -93,6 +93,7 @@
"Invalid filename." : "اسم ملف غير صحيح.",
"Renamed \"{oldName}\" to \"{newName}\"" : "تمت إعادة تسمية \"{oldName}\" إلى \"{newName}\"",
"Rename file" : "إعادة تسمية الملف",
+ "Folder" : "مجلد",
"Pending" : "قيد الانتظار",
"Unknown date" : "تاريخ غير معروف",
"Clear filter" : "إزالة التصفية",
diff --git a/apps/files/l10n/ast.js b/apps/files/l10n/ast.js
index 302c1031c93..c16944eac33 100644
--- a/apps/files/l10n/ast.js
+++ b/apps/files/l10n/ast.js
@@ -75,6 +75,7 @@ OC.L10N.register(
"This node is unavailable" : "Esti noyu nun ta disponible",
"Renamed \"{oldName}\" to \"{newName}\"" : "Renomóse «{oldName}» a «{newName}»",
"Rename file" : "Renomar el ficheru",
+ "Folder" : "Carpeta",
"Pending" : "Pendiente",
"Modified" : "Modificóse",
"Type" : "Tipu",
diff --git a/apps/files/l10n/ast.json b/apps/files/l10n/ast.json
index 48489d78e7f..5a2aa7d692d 100644
--- a/apps/files/l10n/ast.json
+++ b/apps/files/l10n/ast.json
@@ -73,6 +73,7 @@
"This node is unavailable" : "Esti noyu nun ta disponible",
"Renamed \"{oldName}\" to \"{newName}\"" : "Renomóse «{oldName}» a «{newName}»",
"Rename file" : "Renomar el ficheru",
+ "Folder" : "Carpeta",
"Pending" : "Pendiente",
"Modified" : "Modificóse",
"Type" : "Tipu",
diff --git a/apps/files/l10n/bg.js b/apps/files/l10n/bg.js
index c5b2ee13859..164f4523d76 100644
--- a/apps/files/l10n/bg.js
+++ b/apps/files/l10n/bg.js
@@ -63,6 +63,7 @@ OC.L10N.register(
"Favorite" : "Любими",
"Filename" : "Име на файла",
"Folder name" : "Име на папка",
+ "Folder" : "Папка",
"Pending" : "Чакащо",
"Clear filter" : "Изчстиване на филтър",
"Modified" : "Промяна",
diff --git a/apps/files/l10n/bg.json b/apps/files/l10n/bg.json
index 05bc7cbbde2..d653ef6c367 100644
--- a/apps/files/l10n/bg.json
+++ b/apps/files/l10n/bg.json
@@ -61,6 +61,7 @@
"Favorite" : "Любими",
"Filename" : "Име на файла",
"Folder name" : "Име на папка",
+ "Folder" : "Папка",
"Pending" : "Чакащо",
"Clear filter" : "Изчстиване на филтър",
"Modified" : "Промяна",
diff --git a/apps/files/l10n/ca.js b/apps/files/l10n/ca.js
index cae1855ec9c..c68e0c6de8e 100644
--- a/apps/files/l10n/ca.js
+++ b/apps/files/l10n/ca.js
@@ -95,6 +95,7 @@ OC.L10N.register(
"Invalid filename." : "Nom de fitxer no vàlid.",
"Renamed \"{oldName}\" to \"{newName}\"" : "S'ha canviat el nom de «{oldName}» a «{newName}»",
"Rename file" : "Canvia el nom del fitxer",
+ "Folder" : "Carpeta",
"Pending" : "Pendent",
"Unknown date" : "Data desconeguda",
"Clear filter" : "Esborra el filtre",
diff --git a/apps/files/l10n/ca.json b/apps/files/l10n/ca.json
index 78d3d8ff275..64c9ce4052f 100644
--- a/apps/files/l10n/ca.json
+++ b/apps/files/l10n/ca.json
@@ -93,6 +93,7 @@
"Invalid filename." : "Nom de fitxer no vàlid.",
"Renamed \"{oldName}\" to \"{newName}\"" : "S'ha canviat el nom de «{oldName}» a «{newName}»",
"Rename file" : "Canvia el nom del fitxer",
+ "Folder" : "Carpeta",
"Pending" : "Pendent",
"Unknown date" : "Data desconeguda",
"Clear filter" : "Esborra el filtre",
diff --git a/apps/files/l10n/cs.js b/apps/files/l10n/cs.js
index acf20a0af79..b6c83a08aee 100644
--- a/apps/files/l10n/cs.js
+++ b/apps/files/l10n/cs.js
@@ -43,8 +43,6 @@ OC.L10N.register(
"Files" : "Soubory",
"A file or folder has been <strong>changed</strong>" : "Soubor nebo složka byla <strong>změněna</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "Oblíbený soubor nebo složka byla <strong>změněna</strong>",
- "%1$s (renamed)" : "%1$s (přejmenované)",
- "renamed file" : "přejmenovaný soubor",
"Failed to authorize" : "Nepodařilo se získat pověření",
"Invalid folder path" : "Neplatný popis umístění složky",
"Folder not found" : "Složka nenalezena",
diff --git a/apps/files/l10n/cs.json b/apps/files/l10n/cs.json
index fec4ee94d64..1ee66b0e9c8 100644
--- a/apps/files/l10n/cs.json
+++ b/apps/files/l10n/cs.json
@@ -41,8 +41,6 @@
"Files" : "Soubory",
"A file or folder has been <strong>changed</strong>" : "Soubor nebo složka byla <strong>změněna</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "Oblíbený soubor nebo složka byla <strong>změněna</strong>",
- "%1$s (renamed)" : "%1$s (přejmenované)",
- "renamed file" : "přejmenovaný soubor",
"Failed to authorize" : "Nepodařilo se získat pověření",
"Invalid folder path" : "Neplatný popis umístění složky",
"Folder not found" : "Složka nenalezena",
diff --git a/apps/files/l10n/da.js b/apps/files/l10n/da.js
index d8e418c1945..929d5ad55f2 100644
--- a/apps/files/l10n/da.js
+++ b/apps/files/l10n/da.js
@@ -95,6 +95,7 @@ OC.L10N.register(
"Invalid filename." : "Ugyldigt filnavn.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Omdøbte \"{oldName}\" til \"{newName}\"",
"Rename file" : "Omdøb fil",
+ "Folder" : "Mappe",
"Pending" : "Afventer",
"Unknown date" : "Ukendt dato",
"Clear filter" : "Ryd filter",
diff --git a/apps/files/l10n/da.json b/apps/files/l10n/da.json
index a78f64dd320..0d031b957c0 100644
--- a/apps/files/l10n/da.json
+++ b/apps/files/l10n/da.json
@@ -93,6 +93,7 @@
"Invalid filename." : "Ugyldigt filnavn.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Omdøbte \"{oldName}\" til \"{newName}\"",
"Rename file" : "Omdøb fil",
+ "Folder" : "Mappe",
"Pending" : "Afventer",
"Unknown date" : "Ukendt dato",
"Clear filter" : "Ryd filter",
diff --git a/apps/files/l10n/de.js b/apps/files/l10n/de.js
index 10df3dbd1cb..a4a71d0087f 100644
--- a/apps/files/l10n/de.js
+++ b/apps/files/l10n/de.js
@@ -43,8 +43,6 @@ OC.L10N.register(
"Files" : "Dateien",
"A file or folder has been <strong>changed</strong>" : "Eine Datei oder ein Ordner wurde <strong>geändert</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "Eine favorisierte Datei oder ein Ordner wurde <strong>geändert</strong>",
- "%1$s (renamed)" : "%1$s (umbenannt)",
- "renamed file" : "Umbenannte Datei",
"Failed to authorize" : "Autorisierung fehlgeschlagen",
"Invalid folder path" : "Ungültiger Order-Pfad",
"Folder not found" : "Ordner nicht gefunden",
@@ -99,6 +97,7 @@ OC.L10N.register(
"Invalid filename." : "Ungültiger Dateiname.",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" in \"{newName}\" umbenannt",
"Rename file" : "Datei umbenennen",
+ "Folder" : "Ordner",
"Pending" : "Ausstehend",
"Unknown date" : "Unbekanntes Datum",
"Clear filter" : "Filter zurücksetzen",
@@ -123,7 +122,7 @@ OC.L10N.register(
"{count} selected" : "{count} ausgewählt",
"{usedQuotaByte} used" : "{usedQuotaByte} verwendet",
"{used} of {quota} used" : "{used} von {quota} verwendet",
- "{relative}% used" : "{relative}% verwendet",
+ "{relative}% used" : "{relative} % verwendet",
"Could not refresh storage stats" : "Die Speicherstatistik konnte nicht aktualisiert werden",
"Your storage is full, files can not be updated or synced anymore!" : "Der Speicher ist voll, daher können keine Dateien mehr aktualisiert oder synchronisiert werden!",
"Storage information" : "Speicherinformation",
@@ -161,7 +160,7 @@ OC.L10N.register(
"Shared by link" : "Über einen Link geteilt",
"Shared" : "Geteilt",
"Switch to list view" : "Zur Listenansicht wechseln",
- "Switch to grid view" : "Zur Rasteransicht wechseln",
+ "Switch to grid view" : "Zur Kachelansicht wechseln",
"The file could not be found" : "Die Datei konnte nicht gefunden werden",
"Upload was cancelled by user" : "Das Hochladen wurde vom Benutzer abgebrochen.",
"Not enough free space" : "Nicht genügend freier Speicherplatz",
@@ -188,11 +187,11 @@ OC.L10N.register(
"Sort folders before files" : "Ordner vor Dateien sortieren",
"Show hidden files" : "Versteckte Dateien anzeigen",
"Crop image previews" : "Bildvorschauen zuschneiden",
- "Enable the grid view" : "Rasteransicht aktivieren",
- "Enable folder tree" : "Baumstruktur für Ordner aktivieren",
+ "Enable the grid view" : "Kachelansicht aktivieren",
+ "Enable folder tree" : "Ordnerstruktur aktivieren",
"Additional settings" : "Zusätzliche Einstellungen",
"WebDAV" : "WebDAV",
- "WebDAV URL" : "WebDAV URL",
+ "WebDAV URL" : "WebDAV-URL",
"Copy to clipboard" : "In die Zwischenablage kopieren",
"Use this address to access your Files via WebDAV" : "Diese Adresse benutzen, um über WebDAV auf deine Dateien zuzugreifen",
"If you have enabled 2FA, you must create and use a new app password by clicking here." : "Wenn du 2FA aktiviert hast, musst du ein neues App-Passwort erstellen und verwenden, indem du hier klickst.",
@@ -215,8 +214,8 @@ OC.L10N.register(
"Navigate to the parent folder" : "In den übergeordneten Ordner navigieren",
"Navigate to the file above" : "Zur obigen Datei navigieren",
"Navigate to the file below" : "Zur unteren Datei navigieren",
- "Navigate to the file on the left (in grid mode)" : "Zur Datei links navigieren (In der Kachelansicht)",
- "Navigate to the file on the right (in grid mode)" : "Zur Datei rechts navigieren (In der Kachelansicht)",
+ "Navigate to the file on the left (in grid mode)" : "Zur Datei links navigieren (in der Kachelansicht)",
+ "Navigate to the file on the right (in grid mode)" : "Zur Datei rechts navigieren (in der Kachelansicht)",
"View" : "Ansehen",
"Toggle the grid view" : "Kachelansicht umschalten",
"Open the sidebar for a file" : "Seitenleiste für eine Datei öffnen",
@@ -359,7 +358,7 @@ OC.L10N.register(
"File could not be found" : "Datei konnte nicht gefunden werden",
"Download" : "Herunterladen",
"Show list view" : "Listenansicht anzeigen",
- "Show grid view" : "Rasteransicht anzeigen",
+ "Show grid view" : "Kachelansicht anzeigen",
"Close" : "Schließen",
"Could not create folder \"{dir}\"" : "Der Ordner konnte nicht erstellt werden \"{dir}\"",
"This will stop your current uploads." : "Hiermit werden die aktuellen Uploads angehalten.",
@@ -413,7 +412,7 @@ OC.L10N.register(
"New" : "Neu",
"New file/folder menu" : "Menü für neue Datei/Ordner",
"Select file range" : "Dateibereich auswählen",
- "{used}%" : "{used}%",
+ "{used}%" : "{used} %",
"{used} used" : "{used} verwendet",
"\"{name}\" is an invalid file name." : "\"{name}\" ist kein gültiger Dateiname.",
"File name cannot be empty." : "Der Dateiname darf nicht leer sein.",
diff --git a/apps/files/l10n/de.json b/apps/files/l10n/de.json
index bb2e08cd416..8c460f60c44 100644
--- a/apps/files/l10n/de.json
+++ b/apps/files/l10n/de.json
@@ -41,8 +41,6 @@
"Files" : "Dateien",
"A file or folder has been <strong>changed</strong>" : "Eine Datei oder ein Ordner wurde <strong>geändert</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "Eine favorisierte Datei oder ein Ordner wurde <strong>geändert</strong>",
- "%1$s (renamed)" : "%1$s (umbenannt)",
- "renamed file" : "Umbenannte Datei",
"Failed to authorize" : "Autorisierung fehlgeschlagen",
"Invalid folder path" : "Ungültiger Order-Pfad",
"Folder not found" : "Ordner nicht gefunden",
@@ -97,6 +95,7 @@
"Invalid filename." : "Ungültiger Dateiname.",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" in \"{newName}\" umbenannt",
"Rename file" : "Datei umbenennen",
+ "Folder" : "Ordner",
"Pending" : "Ausstehend",
"Unknown date" : "Unbekanntes Datum",
"Clear filter" : "Filter zurücksetzen",
@@ -121,7 +120,7 @@
"{count} selected" : "{count} ausgewählt",
"{usedQuotaByte} used" : "{usedQuotaByte} verwendet",
"{used} of {quota} used" : "{used} von {quota} verwendet",
- "{relative}% used" : "{relative}% verwendet",
+ "{relative}% used" : "{relative} % verwendet",
"Could not refresh storage stats" : "Die Speicherstatistik konnte nicht aktualisiert werden",
"Your storage is full, files can not be updated or synced anymore!" : "Der Speicher ist voll, daher können keine Dateien mehr aktualisiert oder synchronisiert werden!",
"Storage information" : "Speicherinformation",
@@ -159,7 +158,7 @@
"Shared by link" : "Über einen Link geteilt",
"Shared" : "Geteilt",
"Switch to list view" : "Zur Listenansicht wechseln",
- "Switch to grid view" : "Zur Rasteransicht wechseln",
+ "Switch to grid view" : "Zur Kachelansicht wechseln",
"The file could not be found" : "Die Datei konnte nicht gefunden werden",
"Upload was cancelled by user" : "Das Hochladen wurde vom Benutzer abgebrochen.",
"Not enough free space" : "Nicht genügend freier Speicherplatz",
@@ -186,11 +185,11 @@
"Sort folders before files" : "Ordner vor Dateien sortieren",
"Show hidden files" : "Versteckte Dateien anzeigen",
"Crop image previews" : "Bildvorschauen zuschneiden",
- "Enable the grid view" : "Rasteransicht aktivieren",
- "Enable folder tree" : "Baumstruktur für Ordner aktivieren",
+ "Enable the grid view" : "Kachelansicht aktivieren",
+ "Enable folder tree" : "Ordnerstruktur aktivieren",
"Additional settings" : "Zusätzliche Einstellungen",
"WebDAV" : "WebDAV",
- "WebDAV URL" : "WebDAV URL",
+ "WebDAV URL" : "WebDAV-URL",
"Copy to clipboard" : "In die Zwischenablage kopieren",
"Use this address to access your Files via WebDAV" : "Diese Adresse benutzen, um über WebDAV auf deine Dateien zuzugreifen",
"If you have enabled 2FA, you must create and use a new app password by clicking here." : "Wenn du 2FA aktiviert hast, musst du ein neues App-Passwort erstellen und verwenden, indem du hier klickst.",
@@ -213,8 +212,8 @@
"Navigate to the parent folder" : "In den übergeordneten Ordner navigieren",
"Navigate to the file above" : "Zur obigen Datei navigieren",
"Navigate to the file below" : "Zur unteren Datei navigieren",
- "Navigate to the file on the left (in grid mode)" : "Zur Datei links navigieren (In der Kachelansicht)",
- "Navigate to the file on the right (in grid mode)" : "Zur Datei rechts navigieren (In der Kachelansicht)",
+ "Navigate to the file on the left (in grid mode)" : "Zur Datei links navigieren (in der Kachelansicht)",
+ "Navigate to the file on the right (in grid mode)" : "Zur Datei rechts navigieren (in der Kachelansicht)",
"View" : "Ansehen",
"Toggle the grid view" : "Kachelansicht umschalten",
"Open the sidebar for a file" : "Seitenleiste für eine Datei öffnen",
@@ -357,7 +356,7 @@
"File could not be found" : "Datei konnte nicht gefunden werden",
"Download" : "Herunterladen",
"Show list view" : "Listenansicht anzeigen",
- "Show grid view" : "Rasteransicht anzeigen",
+ "Show grid view" : "Kachelansicht anzeigen",
"Close" : "Schließen",
"Could not create folder \"{dir}\"" : "Der Ordner konnte nicht erstellt werden \"{dir}\"",
"This will stop your current uploads." : "Hiermit werden die aktuellen Uploads angehalten.",
@@ -411,7 +410,7 @@
"New" : "Neu",
"New file/folder menu" : "Menü für neue Datei/Ordner",
"Select file range" : "Dateibereich auswählen",
- "{used}%" : "{used}%",
+ "{used}%" : "{used} %",
"{used} used" : "{used} verwendet",
"\"{name}\" is an invalid file name." : "\"{name}\" ist kein gültiger Dateiname.",
"File name cannot be empty." : "Der Dateiname darf nicht leer sein.",
diff --git a/apps/files/l10n/de_DE.js b/apps/files/l10n/de_DE.js
index 894db3c84d3..b65015e0f68 100644
--- a/apps/files/l10n/de_DE.js
+++ b/apps/files/l10n/de_DE.js
@@ -43,8 +43,6 @@ OC.L10N.register(
"Files" : "Dateien",
"A file or folder has been <strong>changed</strong>" : "Eine Datei oder ein Ordner wurde <strong>geändert</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "Eine favorisierte Datei oder ein Ordner wurde <strong>geändert</strong>",
- "%1$s (renamed)" : "%1$s (umbenannt)",
- "renamed file" : "Umbenannte Datei",
"Failed to authorize" : "Autorisierung fehlgeschlagen",
"Invalid folder path" : "Ungültiger Order-Pfad",
"Folder not found" : "Ordner nicht gefunden",
@@ -99,6 +97,7 @@ OC.L10N.register(
"Invalid filename." : "Ungültiger Dateiname.",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" in \"{newName}\" umbenannt",
"Rename file" : "Datei umbenennen",
+ "Folder" : "Ordner",
"Pending" : "Ausstehend",
"Unknown date" : "Unbekanntes Datum",
"Clear filter" : "Filter zurücksetzen",
@@ -123,7 +122,7 @@ OC.L10N.register(
"{count} selected" : "{count} ausgewählt",
"{usedQuotaByte} used" : "{usedQuotaByte} verwendet",
"{used} of {quota} used" : "{used} von {quota} verwendet",
- "{relative}% used" : "{relative}% verwendet",
+ "{relative}% used" : "{relative} % verwendet",
"Could not refresh storage stats" : "Die Speicherstatistik konnte nicht aktualisiert werden",
"Your storage is full, files can not be updated or synced anymore!" : "Ihr Speicher ist voll, daher können keine Dateien mehr aktualisiert oder synchronisiert werden!",
"Storage information" : "Speicherinformation",
@@ -215,8 +214,8 @@ OC.L10N.register(
"Navigate to the parent folder" : "In den übergeordneten Ordner navigieren",
"Navigate to the file above" : "Zur obigen Datei navigieren",
"Navigate to the file below" : "Zur unteren Datei navigieren",
- "Navigate to the file on the left (in grid mode)" : "Zur Datei links navigieren (In der Kachelansicht)",
- "Navigate to the file on the right (in grid mode)" : "Zur Datei rechts navigieren (In der Kachelansicht)",
+ "Navigate to the file on the left (in grid mode)" : "Zur Datei links navigieren (in der Kachelansicht)",
+ "Navigate to the file on the right (in grid mode)" : "Zur Datei rechts navigieren (in der Kachelansicht)",
"View" : "Ansicht",
"Toggle the grid view" : "Kachelansicht umschalten",
"Open the sidebar for a file" : "Seitenleiste für eine Datei öffnen",
@@ -413,7 +412,7 @@ OC.L10N.register(
"New" : "Neu",
"New file/folder menu" : "Menü für neue Datei/Ordner",
"Select file range" : "Dateibereich auswählen",
- "{used}%" : "{used}%",
+ "{used}%" : "{used} %",
"{used} used" : "{used} verwendet",
"\"{name}\" is an invalid file name." : "\"{name}\" ist kein gültiger Dateiname.",
"File name cannot be empty." : "Der Dateiname darf nicht leer sein.",
diff --git a/apps/files/l10n/de_DE.json b/apps/files/l10n/de_DE.json
index b67179d0c0d..3818398effb 100644
--- a/apps/files/l10n/de_DE.json
+++ b/apps/files/l10n/de_DE.json
@@ -41,8 +41,6 @@
"Files" : "Dateien",
"A file or folder has been <strong>changed</strong>" : "Eine Datei oder ein Ordner wurde <strong>geändert</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "Eine favorisierte Datei oder ein Ordner wurde <strong>geändert</strong>",
- "%1$s (renamed)" : "%1$s (umbenannt)",
- "renamed file" : "Umbenannte Datei",
"Failed to authorize" : "Autorisierung fehlgeschlagen",
"Invalid folder path" : "Ungültiger Order-Pfad",
"Folder not found" : "Ordner nicht gefunden",
@@ -97,6 +95,7 @@
"Invalid filename." : "Ungültiger Dateiname.",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" in \"{newName}\" umbenannt",
"Rename file" : "Datei umbenennen",
+ "Folder" : "Ordner",
"Pending" : "Ausstehend",
"Unknown date" : "Unbekanntes Datum",
"Clear filter" : "Filter zurücksetzen",
@@ -121,7 +120,7 @@
"{count} selected" : "{count} ausgewählt",
"{usedQuotaByte} used" : "{usedQuotaByte} verwendet",
"{used} of {quota} used" : "{used} von {quota} verwendet",
- "{relative}% used" : "{relative}% verwendet",
+ "{relative}% used" : "{relative} % verwendet",
"Could not refresh storage stats" : "Die Speicherstatistik konnte nicht aktualisiert werden",
"Your storage is full, files can not be updated or synced anymore!" : "Ihr Speicher ist voll, daher können keine Dateien mehr aktualisiert oder synchronisiert werden!",
"Storage information" : "Speicherinformation",
@@ -213,8 +212,8 @@
"Navigate to the parent folder" : "In den übergeordneten Ordner navigieren",
"Navigate to the file above" : "Zur obigen Datei navigieren",
"Navigate to the file below" : "Zur unteren Datei navigieren",
- "Navigate to the file on the left (in grid mode)" : "Zur Datei links navigieren (In der Kachelansicht)",
- "Navigate to the file on the right (in grid mode)" : "Zur Datei rechts navigieren (In der Kachelansicht)",
+ "Navigate to the file on the left (in grid mode)" : "Zur Datei links navigieren (in der Kachelansicht)",
+ "Navigate to the file on the right (in grid mode)" : "Zur Datei rechts navigieren (in der Kachelansicht)",
"View" : "Ansicht",
"Toggle the grid view" : "Kachelansicht umschalten",
"Open the sidebar for a file" : "Seitenleiste für eine Datei öffnen",
@@ -411,7 +410,7 @@
"New" : "Neu",
"New file/folder menu" : "Menü für neue Datei/Ordner",
"Select file range" : "Dateibereich auswählen",
- "{used}%" : "{used}%",
+ "{used}%" : "{used} %",
"{used} used" : "{used} verwendet",
"\"{name}\" is an invalid file name." : "\"{name}\" ist kein gültiger Dateiname.",
"File name cannot be empty." : "Der Dateiname darf nicht leer sein.",
diff --git a/apps/files/l10n/el.js b/apps/files/l10n/el.js
index 9a250f3895c..e7660c639ba 100644
--- a/apps/files/l10n/el.js
+++ b/apps/files/l10n/el.js
@@ -79,6 +79,7 @@ OC.L10N.register(
"Invalid filename." : "Μη έγκυρο όνομα αρχείου",
"Renamed \"{oldName}\" to \"{newName}\"" : "Μετονομασία του \"{oldName}\" σε \"{newName}\"",
"Rename file" : "Μετονομασία αρχείου",
+ "Folder" : "Φάκελος",
"Pending" : "Εκκρεμεί",
"Clear filter" : "Εκκαθάριση φίλτρου",
"Modified" : "Τροποποιήθηκε",
diff --git a/apps/files/l10n/el.json b/apps/files/l10n/el.json
index 43eaae3d1cb..08140644385 100644
--- a/apps/files/l10n/el.json
+++ b/apps/files/l10n/el.json
@@ -77,6 +77,7 @@
"Invalid filename." : "Μη έγκυρο όνομα αρχείου",
"Renamed \"{oldName}\" to \"{newName}\"" : "Μετονομασία του \"{oldName}\" σε \"{newName}\"",
"Rename file" : "Μετονομασία αρχείου",
+ "Folder" : "Φάκελος",
"Pending" : "Εκκρεμεί",
"Clear filter" : "Εκκαθάριση φίλτρου",
"Modified" : "Τροποποιήθηκε",
diff --git a/apps/files/l10n/en_GB.js b/apps/files/l10n/en_GB.js
index 2b4acc4cb16..fd8ec312af7 100644
--- a/apps/files/l10n/en_GB.js
+++ b/apps/files/l10n/en_GB.js
@@ -43,8 +43,6 @@ OC.L10N.register(
"Files" : "Files",
"A file or folder has been <strong>changed</strong>" : "A file or folder has been <strong>changed</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "A favourite file or folder has been <strong>changed</strong>",
- "%1$s (renamed)" : "%1$s (renamed)",
- "renamed file" : "renamed file",
"Failed to authorize" : "Failed to authorize",
"Invalid folder path" : "Invalid folder path",
"Folder not found" : "Folder not found",
@@ -99,6 +97,7 @@ OC.L10N.register(
"Invalid filename." : "Invalid filename.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Renamed \"{oldName}\" to \"{newName}\"",
"Rename file" : "Rename file",
+ "Folder" : "Folder",
"Pending" : "Pending",
"Unknown date" : "Unknown date",
"Clear filter" : "Clear filter",
diff --git a/apps/files/l10n/en_GB.json b/apps/files/l10n/en_GB.json
index 1a34f016d41..912befe3b81 100644
--- a/apps/files/l10n/en_GB.json
+++ b/apps/files/l10n/en_GB.json
@@ -41,8 +41,6 @@
"Files" : "Files",
"A file or folder has been <strong>changed</strong>" : "A file or folder has been <strong>changed</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "A favourite file or folder has been <strong>changed</strong>",
- "%1$s (renamed)" : "%1$s (renamed)",
- "renamed file" : "renamed file",
"Failed to authorize" : "Failed to authorize",
"Invalid folder path" : "Invalid folder path",
"Folder not found" : "Folder not found",
@@ -97,6 +95,7 @@
"Invalid filename." : "Invalid filename.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Renamed \"{oldName}\" to \"{newName}\"",
"Rename file" : "Rename file",
+ "Folder" : "Folder",
"Pending" : "Pending",
"Unknown date" : "Unknown date",
"Clear filter" : "Clear filter",
diff --git a/apps/files/l10n/es.js b/apps/files/l10n/es.js
index edb4acfd4f5..6a81757f167 100644
--- a/apps/files/l10n/es.js
+++ b/apps/files/l10n/es.js
@@ -43,8 +43,6 @@ OC.L10N.register(
"Files" : "Archivos",
"A file or folder has been <strong>changed</strong>" : "Se ha <strong>modificado</strong> un archivo o carpeta",
"A favorite file or folder has been <strong>changed</strong>" : "Un archivo o carpeta favorito ha sido <strong>cambiado</strong>",
- "%1$s (renamed)" : "%1$s (renombrado)",
- "renamed file" : "archivo renombrado",
"Failed to authorize" : "Fallo al autorizar",
"Invalid folder path" : "Ruta de carpeta inválida",
"Folder not found" : "Carpeta no encontrada",
@@ -98,6 +96,7 @@ OC.L10N.register(
"Invalid filename." : "Nombre de archivo inválido.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Renombrado \"{oldName}\" a \"{newName}\"",
"Rename file" : "Renombrar archivo",
+ "Folder" : "Carpeta",
"Pending" : "Pendiente",
"Unknown date" : "Fecha desconocida",
"Clear filter" : "Borrar filtro",
diff --git a/apps/files/l10n/es.json b/apps/files/l10n/es.json
index d9940c3968d..1fc8796f0c8 100644
--- a/apps/files/l10n/es.json
+++ b/apps/files/l10n/es.json
@@ -41,8 +41,6 @@
"Files" : "Archivos",
"A file or folder has been <strong>changed</strong>" : "Se ha <strong>modificado</strong> un archivo o carpeta",
"A favorite file or folder has been <strong>changed</strong>" : "Un archivo o carpeta favorito ha sido <strong>cambiado</strong>",
- "%1$s (renamed)" : "%1$s (renombrado)",
- "renamed file" : "archivo renombrado",
"Failed to authorize" : "Fallo al autorizar",
"Invalid folder path" : "Ruta de carpeta inválida",
"Folder not found" : "Carpeta no encontrada",
@@ -96,6 +94,7 @@
"Invalid filename." : "Nombre de archivo inválido.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Renombrado \"{oldName}\" a \"{newName}\"",
"Rename file" : "Renombrar archivo",
+ "Folder" : "Carpeta",
"Pending" : "Pendiente",
"Unknown date" : "Fecha desconocida",
"Clear filter" : "Borrar filtro",
diff --git a/apps/files/l10n/es_EC.js b/apps/files/l10n/es_EC.js
index aa4efb62385..aeeba4b15d5 100644
--- a/apps/files/l10n/es_EC.js
+++ b/apps/files/l10n/es_EC.js
@@ -65,6 +65,7 @@ OC.L10N.register(
"Folder name" : "Nombre de la carpeta",
"Renamed \"{oldName}\" to \"{newName}\"" : "Cambiaste el nombre de \"{oldName}\" a \"{newName}\".",
"Rename file" : "Renombrar archivo.",
+ "Folder" : "Carpeta",
"Pending" : "Pendiente",
"Clear filter" : "Borrar filtro",
"Modified" : "Modificado",
diff --git a/apps/files/l10n/es_EC.json b/apps/files/l10n/es_EC.json
index 0c9f72aa1b6..cab16362f3b 100644
--- a/apps/files/l10n/es_EC.json
+++ b/apps/files/l10n/es_EC.json
@@ -63,6 +63,7 @@
"Folder name" : "Nombre de la carpeta",
"Renamed \"{oldName}\" to \"{newName}\"" : "Cambiaste el nombre de \"{oldName}\" a \"{newName}\".",
"Rename file" : "Renombrar archivo.",
+ "Folder" : "Carpeta",
"Pending" : "Pendiente",
"Clear filter" : "Borrar filtro",
"Modified" : "Modificado",
diff --git a/apps/files/l10n/es_MX.js b/apps/files/l10n/es_MX.js
index 2d95872c46a..d57707ff578 100644
--- a/apps/files/l10n/es_MX.js
+++ b/apps/files/l10n/es_MX.js
@@ -87,6 +87,7 @@ OC.L10N.register(
"Invalid filename." : "Nombre de archivo inválido",
"Renamed \"{oldName}\" to \"{newName}\"" : "Renombrado \"{oldName}\" a \"{newName}\"",
"Rename file" : "Renombrar archivo",
+ "Folder" : "Carpeta",
"Pending" : "Pendiente",
"Unknown date" : "Fecha desconocida",
"Clear filter" : "Limpiar filtro",
diff --git a/apps/files/l10n/es_MX.json b/apps/files/l10n/es_MX.json
index 7bbc8a846f9..900561d5fb7 100644
--- a/apps/files/l10n/es_MX.json
+++ b/apps/files/l10n/es_MX.json
@@ -85,6 +85,7 @@
"Invalid filename." : "Nombre de archivo inválido",
"Renamed \"{oldName}\" to \"{newName}\"" : "Renombrado \"{oldName}\" a \"{newName}\"",
"Rename file" : "Renombrar archivo",
+ "Folder" : "Carpeta",
"Pending" : "Pendiente",
"Unknown date" : "Fecha desconocida",
"Clear filter" : "Limpiar filtro",
diff --git a/apps/files/l10n/et_EE.js b/apps/files/l10n/et_EE.js
index 1b29b50ecac..78db65694c1 100644
--- a/apps/files/l10n/et_EE.js
+++ b/apps/files/l10n/et_EE.js
@@ -29,22 +29,20 @@ OC.L10N.register(
"{user} deleted an encrypted file in {file}" : "Kasutaja {user} kustutas krüpteeritud faili {file}",
"You restored {file}" : "Sa taastasid faili {file}",
"{user} restored {file}" : "Kasutaja {user} taastas faili {file}",
- "You renamed {oldfile} (hidden) to {newfile} (hidden)" : "Sa nimetasid faili {oldfile} (peidetud) ümber, uus nimi {newfile} (peidetud)",
- "You renamed {oldfile} (hidden) to {newfile}" : "Sa nimetasid faili {oldfile} (peidetud) ümber, uus nimi {newfile}",
- "You renamed {oldfile} to {newfile} (hidden)" : "Sa nimetasid faili {oldfile} ümber, uus nimi {newfile} (peidetud)",
- "You renamed {oldfile} to {newfile}" : "Sa nimetasid faili {oldfile} ümber, uus nimi {newfile}",
- "{user} renamed {oldfile} (hidden) to {newfile} (hidden)" : "Kasutaja {user} nimetas faili {oldfile} (peidetud) ümber, uus nimi {newfile} (peidetud)",
- "{user} renamed {oldfile} (hidden) to {newfile}" : "Kasutaja {user} nimetas faili {oldfile} (peidetud) ümber, uus nimi {newfile}",
- "{user} renamed {oldfile} to {newfile} (hidden)" : "Kasutaja {user} nimetas faili {oldfile} ümber, uus nimi {newfile} (peidetud)",
- "{user} renamed {oldfile} to {newfile}" : "Kasutaja {user} nimetas faili {oldfile} ümber, uus nimi {newfile}",
+ "You renamed {oldfile} (hidden) to {newfile} (hidden)" : "Sa muutsid „{oldfile}“ (peidetud) faili nime, uus nimi on „{newfile}“ (peidetud)",
+ "You renamed {oldfile} (hidden) to {newfile}" : "Sa muutsid „{oldfile}“ (peidetud) faili nime, uus nimi on „{newfile}“",
+ "You renamed {oldfile} to {newfile} (hidden)" : "Sa muutsid „{oldfile}“ faili nime, uus nimi on „{newfile}“ (peidetud)",
+ "You renamed {oldfile} to {newfile}" : "Sa muutsid „{oldfile}“ faili nime, uus nimi on „{newfile}“",
+ "{user} renamed {oldfile} (hidden) to {newfile} (hidden)" : "Kasutaja {user} muutis „{oldfile}“ (peidetud) faili nime, uus nimi on „{newfile}“ (peidetud)",
+ "{user} renamed {oldfile} (hidden) to {newfile}" : "Kasutaja {user} muutis (peidetud) „{oldfile}“ faili nime, uus nimi on „{newfile}“",
+ "{user} renamed {oldfile} to {newfile} (hidden)" : "Kasutaja {user} muutis „{oldfile}“ faili nime, uus nimi on „{newfile}“ (peidetud)",
+ "{user} renamed {oldfile} to {newfile}" : "Kasutaja {user} muutis „{oldfile}“ faili nime, uus nimi on „{newfile}“",
"You moved {oldfile} to {newfile}" : "Sa liigutasid faili: {oldfile} nüüd {newfile}",
"{user} moved {oldfile} to {newfile}" : "{user} liigutas faili: {oldfile} nüüd {newfile}",
"A file has been added to or removed from your <strong>favorites</strong>" : "Fail lisati su <strong>lemmikutesse</strong> või eemaldati sealt",
"Files" : "Failid",
"A file or folder has been <strong>changed</strong>" : "Fail või kaust on <strong>muudetud</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "Lemmikuks märgitud faili või kausta on <strong>muudetud</strong>",
- "%1$s (renamed)" : "%1$s (nimi on muudetud)",
- "renamed file" : "muudetud nimega fail",
"Failed to authorize" : "Autoriseerimine ei õnnestunud",
"Invalid folder path" : "Kausta vigane asukoht",
"Folder not found" : "Kausta ei leidu",
@@ -99,6 +97,7 @@ OC.L10N.register(
"Invalid filename." : "Vigane failinimi.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Failinimi on muutunud „{oldName}“ ⇨ „{newName}“",
"Rename file" : "Muuda failinime",
+ "Folder" : "Kaust",
"Pending" : "Ootel",
"Unknown date" : "Tundmatu kuupäev",
"Clear filter" : "Tühjenda filter",
@@ -287,7 +286,7 @@ OC.L10N.register(
"The file should now open on your device. If it doesn't, please check that you have the desktop app installed." : "Fail peaks nüüd sinu seadmes või arvutis olema avatud. Kui see nii pole, siis palun kontrolli, et töölauarakendus on paigaldatud.",
"Retry and close" : "Proovi uuesti ja sulge",
"Open online" : "Ava võrgust",
- "Failed to redirect to client" : "Kliendi ümbersuunamine ebaõnnestus",
+ "Failed to redirect to client" : "Kliendi ümbersuunamine ei õnnestunud",
"Open locally" : "Ava kohalikust andmeruumist",
"Rename" : "Muuda nime",
"Open details" : "Ava üksikasjad",
@@ -396,9 +395,9 @@ OC.L10N.register(
"Copied {origin} inside {destination}" : "{origin} kopeeritud kausta {destination}",
"Copied {origin} and {nbfiles} other files inside {destination}" : "{origin} ja {nbfiles} teist faili kopeeritud kausta {destination}",
"{newName} already exists" : "{newName} on juba olemas",
- "Could not rename \"{fileName}\", it does not exist any more" : "\"{fileName}\" ümbernimetamine ebaõnnestus, seda pole enam olemas",
+ "Could not rename \"{fileName}\", it does not exist any more" : "„{fileName}“ faili nime muutmine ei õnnestunud, seda pole enam olemas",
"The name \"{targetName}\" is already used in the folder \"{dir}\". Please choose a different name." : "Nimi \"{targetName}\" on juba \"{dir}\" kaustas kasutusel. Palun vali teine nimi.",
- "Could not rename \"{fileName}\"" : "\"{fileName}\" ümbernimetamine ebaõnnestus",
+ "Could not rename \"{fileName}\"" : "„{fileName}“ faili nime muutmine ei õnnestunud",
"Could not create file \"{file}\"" : "Faili \"{file}\" loomine ebaõnnestus",
"Could not create file \"{file}\" because it already exists" : "Faili \"{file}\" loomine ebaõnnestus, sest see on juba olemas",
"Could not create folder \"{dir}\" because it already exists" : "Kausta \"{dir}\" loomine ebaõnnestus, sest see on juba olemas",
diff --git a/apps/files/l10n/et_EE.json b/apps/files/l10n/et_EE.json
index 58cb0b8a894..428758f0287 100644
--- a/apps/files/l10n/et_EE.json
+++ b/apps/files/l10n/et_EE.json
@@ -27,22 +27,20 @@
"{user} deleted an encrypted file in {file}" : "Kasutaja {user} kustutas krüpteeritud faili {file}",
"You restored {file}" : "Sa taastasid faili {file}",
"{user} restored {file}" : "Kasutaja {user} taastas faili {file}",
- "You renamed {oldfile} (hidden) to {newfile} (hidden)" : "Sa nimetasid faili {oldfile} (peidetud) ümber, uus nimi {newfile} (peidetud)",
- "You renamed {oldfile} (hidden) to {newfile}" : "Sa nimetasid faili {oldfile} (peidetud) ümber, uus nimi {newfile}",
- "You renamed {oldfile} to {newfile} (hidden)" : "Sa nimetasid faili {oldfile} ümber, uus nimi {newfile} (peidetud)",
- "You renamed {oldfile} to {newfile}" : "Sa nimetasid faili {oldfile} ümber, uus nimi {newfile}",
- "{user} renamed {oldfile} (hidden) to {newfile} (hidden)" : "Kasutaja {user} nimetas faili {oldfile} (peidetud) ümber, uus nimi {newfile} (peidetud)",
- "{user} renamed {oldfile} (hidden) to {newfile}" : "Kasutaja {user} nimetas faili {oldfile} (peidetud) ümber, uus nimi {newfile}",
- "{user} renamed {oldfile} to {newfile} (hidden)" : "Kasutaja {user} nimetas faili {oldfile} ümber, uus nimi {newfile} (peidetud)",
- "{user} renamed {oldfile} to {newfile}" : "Kasutaja {user} nimetas faili {oldfile} ümber, uus nimi {newfile}",
+ "You renamed {oldfile} (hidden) to {newfile} (hidden)" : "Sa muutsid „{oldfile}“ (peidetud) faili nime, uus nimi on „{newfile}“ (peidetud)",
+ "You renamed {oldfile} (hidden) to {newfile}" : "Sa muutsid „{oldfile}“ (peidetud) faili nime, uus nimi on „{newfile}“",
+ "You renamed {oldfile} to {newfile} (hidden)" : "Sa muutsid „{oldfile}“ faili nime, uus nimi on „{newfile}“ (peidetud)",
+ "You renamed {oldfile} to {newfile}" : "Sa muutsid „{oldfile}“ faili nime, uus nimi on „{newfile}“",
+ "{user} renamed {oldfile} (hidden) to {newfile} (hidden)" : "Kasutaja {user} muutis „{oldfile}“ (peidetud) faili nime, uus nimi on „{newfile}“ (peidetud)",
+ "{user} renamed {oldfile} (hidden) to {newfile}" : "Kasutaja {user} muutis (peidetud) „{oldfile}“ faili nime, uus nimi on „{newfile}“",
+ "{user} renamed {oldfile} to {newfile} (hidden)" : "Kasutaja {user} muutis „{oldfile}“ faili nime, uus nimi on „{newfile}“ (peidetud)",
+ "{user} renamed {oldfile} to {newfile}" : "Kasutaja {user} muutis „{oldfile}“ faili nime, uus nimi on „{newfile}“",
"You moved {oldfile} to {newfile}" : "Sa liigutasid faili: {oldfile} nüüd {newfile}",
"{user} moved {oldfile} to {newfile}" : "{user} liigutas faili: {oldfile} nüüd {newfile}",
"A file has been added to or removed from your <strong>favorites</strong>" : "Fail lisati su <strong>lemmikutesse</strong> või eemaldati sealt",
"Files" : "Failid",
"A file or folder has been <strong>changed</strong>" : "Fail või kaust on <strong>muudetud</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "Lemmikuks märgitud faili või kausta on <strong>muudetud</strong>",
- "%1$s (renamed)" : "%1$s (nimi on muudetud)",
- "renamed file" : "muudetud nimega fail",
"Failed to authorize" : "Autoriseerimine ei õnnestunud",
"Invalid folder path" : "Kausta vigane asukoht",
"Folder not found" : "Kausta ei leidu",
@@ -97,6 +95,7 @@
"Invalid filename." : "Vigane failinimi.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Failinimi on muutunud „{oldName}“ ⇨ „{newName}“",
"Rename file" : "Muuda failinime",
+ "Folder" : "Kaust",
"Pending" : "Ootel",
"Unknown date" : "Tundmatu kuupäev",
"Clear filter" : "Tühjenda filter",
@@ -285,7 +284,7 @@
"The file should now open on your device. If it doesn't, please check that you have the desktop app installed." : "Fail peaks nüüd sinu seadmes või arvutis olema avatud. Kui see nii pole, siis palun kontrolli, et töölauarakendus on paigaldatud.",
"Retry and close" : "Proovi uuesti ja sulge",
"Open online" : "Ava võrgust",
- "Failed to redirect to client" : "Kliendi ümbersuunamine ebaõnnestus",
+ "Failed to redirect to client" : "Kliendi ümbersuunamine ei õnnestunud",
"Open locally" : "Ava kohalikust andmeruumist",
"Rename" : "Muuda nime",
"Open details" : "Ava üksikasjad",
@@ -394,9 +393,9 @@
"Copied {origin} inside {destination}" : "{origin} kopeeritud kausta {destination}",
"Copied {origin} and {nbfiles} other files inside {destination}" : "{origin} ja {nbfiles} teist faili kopeeritud kausta {destination}",
"{newName} already exists" : "{newName} on juba olemas",
- "Could not rename \"{fileName}\", it does not exist any more" : "\"{fileName}\" ümbernimetamine ebaõnnestus, seda pole enam olemas",
+ "Could not rename \"{fileName}\", it does not exist any more" : "„{fileName}“ faili nime muutmine ei õnnestunud, seda pole enam olemas",
"The name \"{targetName}\" is already used in the folder \"{dir}\". Please choose a different name." : "Nimi \"{targetName}\" on juba \"{dir}\" kaustas kasutusel. Palun vali teine nimi.",
- "Could not rename \"{fileName}\"" : "\"{fileName}\" ümbernimetamine ebaõnnestus",
+ "Could not rename \"{fileName}\"" : "„{fileName}“ faili nime muutmine ei õnnestunud",
"Could not create file \"{file}\"" : "Faili \"{file}\" loomine ebaõnnestus",
"Could not create file \"{file}\" because it already exists" : "Faili \"{file}\" loomine ebaõnnestus, sest see on juba olemas",
"Could not create folder \"{dir}\" because it already exists" : "Kausta \"{dir}\" loomine ebaõnnestus, sest see on juba olemas",
diff --git a/apps/files/l10n/eu.js b/apps/files/l10n/eu.js
index 3d4490c17f8..2cabb2838b0 100644
--- a/apps/files/l10n/eu.js
+++ b/apps/files/l10n/eu.js
@@ -91,6 +91,7 @@ OC.L10N.register(
"Invalid filename." : "Fitxategi-izen baliogabea.",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" \"{newName}\"(e)ra berrizendatu da.",
"Rename file" : "Berrizendatu fitxategia",
+ "Folder" : "Karpeta",
"Pending" : "Zain",
"Unknown date" : "Data ezezaguna",
"Clear filter" : "Garbitu iragazkia",
diff --git a/apps/files/l10n/eu.json b/apps/files/l10n/eu.json
index 1d9f645f996..e684f2741d7 100644
--- a/apps/files/l10n/eu.json
+++ b/apps/files/l10n/eu.json
@@ -89,6 +89,7 @@
"Invalid filename." : "Fitxategi-izen baliogabea.",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" \"{newName}\"(e)ra berrizendatu da.",
"Rename file" : "Berrizendatu fitxategia",
+ "Folder" : "Karpeta",
"Pending" : "Zain",
"Unknown date" : "Data ezezaguna",
"Clear filter" : "Garbitu iragazkia",
diff --git a/apps/files/l10n/fa.js b/apps/files/l10n/fa.js
index 13087186570..c71a442bcc6 100644
--- a/apps/files/l10n/fa.js
+++ b/apps/files/l10n/fa.js
@@ -68,6 +68,7 @@ OC.L10N.register(
"This node is unavailable" : "گره شما در دسترس نیست",
"Renamed \"{oldName}\" to \"{newName}\"" : "تغییر نام \"{oldName}\" به \"{newName}\"",
"Rename file" : "تغییر نام فایل",
+ "Folder" : "پوشه",
"Pending" : "در انتظار",
"Clear filter" : "پاک کردن پالایه",
"Modified" : "تاریخ",
diff --git a/apps/files/l10n/fa.json b/apps/files/l10n/fa.json
index dd93cc9e2b2..bdc6488c9e8 100644
--- a/apps/files/l10n/fa.json
+++ b/apps/files/l10n/fa.json
@@ -66,6 +66,7 @@
"This node is unavailable" : "گره شما در دسترس نیست",
"Renamed \"{oldName}\" to \"{newName}\"" : "تغییر نام \"{oldName}\" به \"{newName}\"",
"Rename file" : "تغییر نام فایل",
+ "Folder" : "پوشه",
"Pending" : "در انتظار",
"Clear filter" : "پاک کردن پالایه",
"Modified" : "تاریخ",
diff --git a/apps/files/l10n/fi.js b/apps/files/l10n/fi.js
index 893c3061df0..a207528e026 100644
--- a/apps/files/l10n/fi.js
+++ b/apps/files/l10n/fi.js
@@ -87,6 +87,7 @@ OC.L10N.register(
"Invalid filename." : "Epäkelpo tiedostonimi.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Kohteen \"{oldName}\" uudeksi nimeksi asetettiin \"{newName}\"",
"Rename file" : "Nimeä tiedosto uudelleen",
+ "Folder" : "Kansio",
"Pending" : "Odottaa",
"Unknown date" : "Tuntematon päivämäärä",
"Clear filter" : "Tyhjennä suodatin",
diff --git a/apps/files/l10n/fi.json b/apps/files/l10n/fi.json
index b3459c5ae0e..b9b238376e3 100644
--- a/apps/files/l10n/fi.json
+++ b/apps/files/l10n/fi.json
@@ -85,6 +85,7 @@
"Invalid filename." : "Epäkelpo tiedostonimi.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Kohteen \"{oldName}\" uudeksi nimeksi asetettiin \"{newName}\"",
"Rename file" : "Nimeä tiedosto uudelleen",
+ "Folder" : "Kansio",
"Pending" : "Odottaa",
"Unknown date" : "Tuntematon päivämäärä",
"Clear filter" : "Tyhjennä suodatin",
diff --git a/apps/files/l10n/fr.js b/apps/files/l10n/fr.js
index e89de99e567..6e5809bbed8 100644
--- a/apps/files/l10n/fr.js
+++ b/apps/files/l10n/fr.js
@@ -95,6 +95,7 @@ OC.L10N.register(
"Invalid filename." : "Nom de fichier invalide.",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" renommé en \"{newName}\"",
"Rename file" : "Renommer le fichier",
+ "Folder" : "Dossier",
"Pending" : "En attente",
"Unknown date" : "Date inconnue",
"Clear filter" : "Supprimer le filtre",
diff --git a/apps/files/l10n/fr.json b/apps/files/l10n/fr.json
index 52124d3e7eb..6d03efc424b 100644
--- a/apps/files/l10n/fr.json
+++ b/apps/files/l10n/fr.json
@@ -93,6 +93,7 @@
"Invalid filename." : "Nom de fichier invalide.",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" renommé en \"{newName}\"",
"Rename file" : "Renommer le fichier",
+ "Folder" : "Dossier",
"Pending" : "En attente",
"Unknown date" : "Date inconnue",
"Clear filter" : "Supprimer le filtre",
diff --git a/apps/files/l10n/ga.js b/apps/files/l10n/ga.js
index abcbbb78d80..232c98146f3 100644
--- a/apps/files/l10n/ga.js
+++ b/apps/files/l10n/ga.js
@@ -71,6 +71,8 @@ OC.L10N.register(
"Transferred from %1$s on %2$s" : "Aistrithe ó %1$s ar %2$s",
"Files compatibility" : "Comhoiriúnacht comhaid",
"Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Ceadaigh comhaid a shrianadh lena chinntiú gur féidir comhaid a shioncronú le gach cliant. De réir réamhshocraithe ceadaítear gach comhadainm atá bailí ar POSIX (m.sh. Linux nó macOS).",
+ "After enabling the Windows compatible filenames, existing files cannot be modified anymore but can be renamed to valid new names by their owner." : "Tar éis na hainmneacha comhad atá comhoiriúnach le Windows a chumasú, ní féidir comhaid atá ann cheana a mhodhnú a thuilleadh ach is féidir lena n-úinéir iad a athainmniú go hainmneacha nua bailí.",
+ "It is also possible to migrate files automatically after enabling this setting, please refer to the documentation about the occ command." : "Is féidir comhaid a aistriú go huathoibríoch freisin tar éis an socrú seo a chumasú, féach ar an doiciméadú faoin ordú occ.",
"Enforce Windows compatibility" : "Comhoiriúnacht Windows a fhorfheidhmiú",
"This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "Cuirfidh sé seo bac ar ainmneacha comhaid nach bhfuil bailí ar chórais Windows, ar nós ainmneacha forchoimeádta nó carachtair speisialta a úsáid. Ach ní chuirfidh sé seo i bhfeidhm comhoiriúnacht íogaireacht cáis.",
"File Management" : "Bainistíocht Comhad",
@@ -95,6 +97,7 @@ OC.L10N.register(
"Invalid filename." : "Ainm comhaid neamhbhailí.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Athainmnithe \"{oldName}\" go \"{newName}\"",
"Rename file" : "Athainmnigh an comhad",
+ "Folder" : "Fillteán",
"Pending" : "Ar feitheamh",
"Unknown date" : "Dáta anaithnid",
"Clear filter" : "Glan an scagaire",
diff --git a/apps/files/l10n/ga.json b/apps/files/l10n/ga.json
index 9122bb3f7b4..db09fb79b39 100644
--- a/apps/files/l10n/ga.json
+++ b/apps/files/l10n/ga.json
@@ -69,6 +69,8 @@
"Transferred from %1$s on %2$s" : "Aistrithe ó %1$s ar %2$s",
"Files compatibility" : "Comhoiriúnacht comhaid",
"Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Ceadaigh comhaid a shrianadh lena chinntiú gur féidir comhaid a shioncronú le gach cliant. De réir réamhshocraithe ceadaítear gach comhadainm atá bailí ar POSIX (m.sh. Linux nó macOS).",
+ "After enabling the Windows compatible filenames, existing files cannot be modified anymore but can be renamed to valid new names by their owner." : "Tar éis na hainmneacha comhad atá comhoiriúnach le Windows a chumasú, ní féidir comhaid atá ann cheana a mhodhnú a thuilleadh ach is féidir lena n-úinéir iad a athainmniú go hainmneacha nua bailí.",
+ "It is also possible to migrate files automatically after enabling this setting, please refer to the documentation about the occ command." : "Is féidir comhaid a aistriú go huathoibríoch freisin tar éis an socrú seo a chumasú, féach ar an doiciméadú faoin ordú occ.",
"Enforce Windows compatibility" : "Comhoiriúnacht Windows a fhorfheidhmiú",
"This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "Cuirfidh sé seo bac ar ainmneacha comhaid nach bhfuil bailí ar chórais Windows, ar nós ainmneacha forchoimeádta nó carachtair speisialta a úsáid. Ach ní chuirfidh sé seo i bhfeidhm comhoiriúnacht íogaireacht cáis.",
"File Management" : "Bainistíocht Comhad",
@@ -93,6 +95,7 @@
"Invalid filename." : "Ainm comhaid neamhbhailí.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Athainmnithe \"{oldName}\" go \"{newName}\"",
"Rename file" : "Athainmnigh an comhad",
+ "Folder" : "Fillteán",
"Pending" : "Ar feitheamh",
"Unknown date" : "Dáta anaithnid",
"Clear filter" : "Glan an scagaire",
diff --git a/apps/files/l10n/gl.js b/apps/files/l10n/gl.js
index 966bf2caca8..8262941c787 100644
--- a/apps/files/l10n/gl.js
+++ b/apps/files/l10n/gl.js
@@ -95,6 +95,7 @@ OC.L10N.register(
"Invalid filename." : "Nome de ficheiro incorrecto.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Cambiouse o nome de «{oldName}» a «{newName}»",
"Rename file" : "Cambiar o nome do ficheiro",
+ "Folder" : "Cartafol",
"Pending" : "Pendentes",
"Unknown date" : "Data descoñecida",
"Clear filter" : "Limpar o filtro",
diff --git a/apps/files/l10n/gl.json b/apps/files/l10n/gl.json
index b5e856b1f96..2e7c5c6a531 100644
--- a/apps/files/l10n/gl.json
+++ b/apps/files/l10n/gl.json
@@ -93,6 +93,7 @@
"Invalid filename." : "Nome de ficheiro incorrecto.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Cambiouse o nome de «{oldName}» a «{newName}»",
"Rename file" : "Cambiar o nome do ficheiro",
+ "Folder" : "Cartafol",
"Pending" : "Pendentes",
"Unknown date" : "Data descoñecida",
"Clear filter" : "Limpar o filtro",
diff --git a/apps/files/l10n/hu.js b/apps/files/l10n/hu.js
index f5387c65f47..10ab2b1a997 100644
--- a/apps/files/l10n/hu.js
+++ b/apps/files/l10n/hu.js
@@ -94,6 +94,7 @@ OC.L10N.register(
"Invalid filename." : "Érvénytelen fájlnév.",
"Renamed \"{oldName}\" to \"{newName}\"" : "A(z) „{oldName}” átnevezve erre: „{newName}”",
"Rename file" : "Fájl átnevezése",
+ "Folder" : "Mappa",
"Pending" : "Függőben",
"Unknown date" : "Ismeretlen dátum",
"Clear filter" : "Szűrő törlése",
diff --git a/apps/files/l10n/hu.json b/apps/files/l10n/hu.json
index 88d8c7644b4..999670b9d3a 100644
--- a/apps/files/l10n/hu.json
+++ b/apps/files/l10n/hu.json
@@ -92,6 +92,7 @@
"Invalid filename." : "Érvénytelen fájlnév.",
"Renamed \"{oldName}\" to \"{newName}\"" : "A(z) „{oldName}” átnevezve erre: „{newName}”",
"Rename file" : "Fájl átnevezése",
+ "Folder" : "Mappa",
"Pending" : "Függőben",
"Unknown date" : "Ismeretlen dátum",
"Clear filter" : "Szűrő törlése",
diff --git a/apps/files/l10n/id.js b/apps/files/l10n/id.js
index fbee6b01369..26b58d44082 100644
--- a/apps/files/l10n/id.js
+++ b/apps/files/l10n/id.js
@@ -61,6 +61,7 @@ OC.L10N.register(
"Favorite" : "Favorit",
"Filename" : "Nama berkas",
"Folder name" : "Nama folder",
+ "Folder" : "Folder",
"Pending" : "Tertunda",
"Clear filter" : "Bersihkan filter",
"Modified" : "Dimodifikasi",
diff --git a/apps/files/l10n/id.json b/apps/files/l10n/id.json
index 2d3ab467148..124d61723c6 100644
--- a/apps/files/l10n/id.json
+++ b/apps/files/l10n/id.json
@@ -59,6 +59,7 @@
"Favorite" : "Favorit",
"Filename" : "Nama berkas",
"Folder name" : "Nama folder",
+ "Folder" : "Folder",
"Pending" : "Tertunda",
"Clear filter" : "Bersihkan filter",
"Modified" : "Dimodifikasi",
diff --git a/apps/files/l10n/is.js b/apps/files/l10n/is.js
index 8d76f72e3b7..ee87ac2320d 100644
--- a/apps/files/l10n/is.js
+++ b/apps/files/l10n/is.js
@@ -94,6 +94,7 @@ OC.L10N.register(
"Invalid filename." : "Ógilt skráarheiti.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Endurnefndi \"{oldName}\" sem \"{newName}\"",
"Rename file" : "Endurnefna skrá",
+ "Folder" : "Mappa",
"Pending" : "Í bið",
"Unknown date" : "Óþekkt dagsetning",
"Clear filter" : "Hreinsa síu",
diff --git a/apps/files/l10n/is.json b/apps/files/l10n/is.json
index 5a983457262..ba82fae1a98 100644
--- a/apps/files/l10n/is.json
+++ b/apps/files/l10n/is.json
@@ -92,6 +92,7 @@
"Invalid filename." : "Ógilt skráarheiti.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Endurnefndi \"{oldName}\" sem \"{newName}\"",
"Rename file" : "Endurnefna skrá",
+ "Folder" : "Mappa",
"Pending" : "Í bið",
"Unknown date" : "Óþekkt dagsetning",
"Clear filter" : "Hreinsa síu",
diff --git a/apps/files/l10n/it.js b/apps/files/l10n/it.js
index 4277802cb80..a98cb8fe96d 100644
--- a/apps/files/l10n/it.js
+++ b/apps/files/l10n/it.js
@@ -43,8 +43,6 @@ OC.L10N.register(
"Files" : "File",
"A file or folder has been <strong>changed</strong>" : "Un file o una cartella è stato <strong>modificato</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "Un file preferito o una cartella è stato <strong>modificato</strong>",
- "%1$s (renamed)" : "%1$s (rinominato)",
- "renamed file" : "file rinominato",
"Failed to authorize" : "Impossibile dare l'autorizzazione",
"Invalid folder path" : "Percorso della cartella non valido",
"Folder not found" : "Cartella non trovata",
@@ -99,6 +97,7 @@ OC.L10N.register(
"Invalid filename." : "Nome di file non valido.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Rinominato \"{oldName}\" in \"{newName}\"",
"Rename file" : "Rinomina file",
+ "Folder" : "Cartella",
"Pending" : "In corso",
"Unknown date" : "Data sconosciuta",
"Clear filter" : "Pulisci il filtro",
diff --git a/apps/files/l10n/it.json b/apps/files/l10n/it.json
index 80c8044307b..f645e6940bc 100644
--- a/apps/files/l10n/it.json
+++ b/apps/files/l10n/it.json
@@ -41,8 +41,6 @@
"Files" : "File",
"A file or folder has been <strong>changed</strong>" : "Un file o una cartella è stato <strong>modificato</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "Un file preferito o una cartella è stato <strong>modificato</strong>",
- "%1$s (renamed)" : "%1$s (rinominato)",
- "renamed file" : "file rinominato",
"Failed to authorize" : "Impossibile dare l'autorizzazione",
"Invalid folder path" : "Percorso della cartella non valido",
"Folder not found" : "Cartella non trovata",
@@ -97,6 +95,7 @@
"Invalid filename." : "Nome di file non valido.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Rinominato \"{oldName}\" in \"{newName}\"",
"Rename file" : "Rinomina file",
+ "Folder" : "Cartella",
"Pending" : "In corso",
"Unknown date" : "Data sconosciuta",
"Clear filter" : "Pulisci il filtro",
diff --git a/apps/files/l10n/ja.js b/apps/files/l10n/ja.js
index 5d4430cdfd2..3d61616343b 100644
--- a/apps/files/l10n/ja.js
+++ b/apps/files/l10n/ja.js
@@ -95,6 +95,7 @@ OC.L10N.register(
"Invalid filename." : "無効なファイル名。",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" から \"{newName}\" に名前を変更済み",
"Rename file" : "ファイル名の変更",
+ "Folder" : "フォルダー",
"Pending" : "保留中",
"Unknown date" : "不明な日付",
"Clear filter" : "フィルターをクリア",
diff --git a/apps/files/l10n/ja.json b/apps/files/l10n/ja.json
index 9d405b87359..e778a19f0bb 100644
--- a/apps/files/l10n/ja.json
+++ b/apps/files/l10n/ja.json
@@ -93,6 +93,7 @@
"Invalid filename." : "無効なファイル名。",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" から \"{newName}\" に名前を変更済み",
"Rename file" : "ファイル名の変更",
+ "Folder" : "フォルダー",
"Pending" : "保留中",
"Unknown date" : "不明な日付",
"Clear filter" : "フィルターをクリア",
diff --git a/apps/files/l10n/ka.js b/apps/files/l10n/ka.js
index deb242a4764..cfe5550e1b9 100644
--- a/apps/files/l10n/ka.js
+++ b/apps/files/l10n/ka.js
@@ -69,6 +69,7 @@ OC.L10N.register(
"This node is unavailable" : "This node is unavailable",
"Renamed \"{oldName}\" to \"{newName}\"" : "Renamed \"{oldName}\" to \"{newName}\"",
"Rename file" : "Rename file",
+ "Folder" : "Folder",
"Pending" : "Pending",
"Clear filter" : "Clear filter",
"Modified" : "Modified",
diff --git a/apps/files/l10n/ka.json b/apps/files/l10n/ka.json
index c9f27cb09d4..62a87193a52 100644
--- a/apps/files/l10n/ka.json
+++ b/apps/files/l10n/ka.json
@@ -67,6 +67,7 @@
"This node is unavailable" : "This node is unavailable",
"Renamed \"{oldName}\" to \"{newName}\"" : "Renamed \"{oldName}\" to \"{newName}\"",
"Rename file" : "Rename file",
+ "Folder" : "Folder",
"Pending" : "Pending",
"Clear filter" : "Clear filter",
"Modified" : "Modified",
diff --git a/apps/files/l10n/ko.js b/apps/files/l10n/ko.js
index fff5a010699..9a628f603bb 100644
--- a/apps/files/l10n/ko.js
+++ b/apps/files/l10n/ko.js
@@ -95,6 +95,7 @@ OC.L10N.register(
"Invalid filename." : "잘못된 파일 이름",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" 에서 \"{newName}\"(으)로 이름 변경함",
"Rename file" : "파일 이름 바꾸기",
+ "Folder" : "폴더",
"Pending" : "대기 중",
"Unknown date" : "알 수 없는 날짜",
"Clear filter" : "필터 지우기",
diff --git a/apps/files/l10n/ko.json b/apps/files/l10n/ko.json
index f8249b85406..10b720f7f8c 100644
--- a/apps/files/l10n/ko.json
+++ b/apps/files/l10n/ko.json
@@ -93,6 +93,7 @@
"Invalid filename." : "잘못된 파일 이름",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" 에서 \"{newName}\"(으)로 이름 변경함",
"Rename file" : "파일 이름 바꾸기",
+ "Folder" : "폴더",
"Pending" : "대기 중",
"Unknown date" : "알 수 없는 날짜",
"Clear filter" : "필터 지우기",
diff --git a/apps/files/l10n/lt_LT.js b/apps/files/l10n/lt_LT.js
index 595b4e82a05..e0687e17887 100644
--- a/apps/files/l10n/lt_LT.js
+++ b/apps/files/l10n/lt_LT.js
@@ -76,6 +76,7 @@ OC.L10N.register(
"Invalid filename." : "Neteisingas failo pavadinimas.",
"Renamed \"{oldName}\" to \"{newName}\"" : "„{oldName}“ pervadintas į „{newName}“",
"Rename file" : "Pervadinti failą",
+ "Folder" : "Aplankas",
"Pending" : "Laukiantis",
"Unknown date" : "Nežinoma data",
"Clear filter" : "Išvalyti filtrą",
diff --git a/apps/files/l10n/lt_LT.json b/apps/files/l10n/lt_LT.json
index 3e86f7bbdf5..c118a408467 100644
--- a/apps/files/l10n/lt_LT.json
+++ b/apps/files/l10n/lt_LT.json
@@ -74,6 +74,7 @@
"Invalid filename." : "Neteisingas failo pavadinimas.",
"Renamed \"{oldName}\" to \"{newName}\"" : "„{oldName}“ pervadintas į „{newName}“",
"Rename file" : "Pervadinti failą",
+ "Folder" : "Aplankas",
"Pending" : "Laukiantis",
"Unknown date" : "Nežinoma data",
"Clear filter" : "Išvalyti filtrą",
diff --git a/apps/files/l10n/mk.js b/apps/files/l10n/mk.js
index b0d9db8ffd1..0eebc8c5376 100644
--- a/apps/files/l10n/mk.js
+++ b/apps/files/l10n/mk.js
@@ -84,6 +84,7 @@ OC.L10N.register(
"This node is unavailable" : "Нодот е недостапен",
"Renamed \"{oldName}\" to \"{newName}\"" : "Преименувано \"{oldName}\" во \"{newName}\"",
"Rename file" : "Преименувај датотека",
+ "Folder" : "Папка",
"Pending" : "Чека",
"Clear filter" : "Исчисти филтри",
"Modified" : "Променето",
diff --git a/apps/files/l10n/mk.json b/apps/files/l10n/mk.json
index 9a7349b9d52..4c970bba5ff 100644
--- a/apps/files/l10n/mk.json
+++ b/apps/files/l10n/mk.json
@@ -82,6 +82,7 @@
"This node is unavailable" : "Нодот е недостапен",
"Renamed \"{oldName}\" to \"{newName}\"" : "Преименувано \"{oldName}\" во \"{newName}\"",
"Rename file" : "Преименувај датотека",
+ "Folder" : "Папка",
"Pending" : "Чека",
"Clear filter" : "Исчисти филтри",
"Modified" : "Променето",
diff --git a/apps/files/l10n/nb.js b/apps/files/l10n/nb.js
index ad344dee0b2..c05d7df2dba 100644
--- a/apps/files/l10n/nb.js
+++ b/apps/files/l10n/nb.js
@@ -92,6 +92,7 @@ OC.L10N.register(
"Invalid filename." : "Ugyldig filnavn.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Omdøpte \"{oldName}\" tl \"{newName}\"",
"Rename file" : "Gi fil nytt navn",
+ "Folder" : "Mappe",
"Pending" : "Venter",
"Unknown date" : "Ukjent dato",
"Clear filter" : "Tøm filter",
diff --git a/apps/files/l10n/nb.json b/apps/files/l10n/nb.json
index b7b87dd5806..20d1464f445 100644
--- a/apps/files/l10n/nb.json
+++ b/apps/files/l10n/nb.json
@@ -90,6 +90,7 @@
"Invalid filename." : "Ugyldig filnavn.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Omdøpte \"{oldName}\" tl \"{newName}\"",
"Rename file" : "Gi fil nytt navn",
+ "Folder" : "Mappe",
"Pending" : "Venter",
"Unknown date" : "Ukjent dato",
"Clear filter" : "Tøm filter",
diff --git a/apps/files/l10n/nl.js b/apps/files/l10n/nl.js
index 740d9e7e6c0..f1576a4e645 100644
--- a/apps/files/l10n/nl.js
+++ b/apps/files/l10n/nl.js
@@ -95,6 +95,7 @@ OC.L10N.register(
"Invalid filename." : "Ongeldige bestandsnaam",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" hernoemd naar \"{newName}\"",
"Rename file" : "Bestand hernoemen",
+ "Folder" : "Map",
"Pending" : "In behandeling",
"Unknown date" : "Onbekende datum",
"Clear filter" : "Filter leegmaken",
diff --git a/apps/files/l10n/nl.json b/apps/files/l10n/nl.json
index 8125282712b..edbd2421acb 100644
--- a/apps/files/l10n/nl.json
+++ b/apps/files/l10n/nl.json
@@ -93,6 +93,7 @@
"Invalid filename." : "Ongeldige bestandsnaam",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" hernoemd naar \"{newName}\"",
"Rename file" : "Bestand hernoemen",
+ "Folder" : "Map",
"Pending" : "In behandeling",
"Unknown date" : "Onbekende datum",
"Clear filter" : "Filter leegmaken",
diff --git a/apps/files/l10n/pl.js b/apps/files/l10n/pl.js
index 88f77ae9d76..d2d3541974d 100644
--- a/apps/files/l10n/pl.js
+++ b/apps/files/l10n/pl.js
@@ -43,8 +43,6 @@ OC.L10N.register(
"Files" : "Pliki",
"A file or folder has been <strong>changed</strong>" : "Plik lub katalog został <strong>zmieniony</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "Ulubiony plik lub katalog został <strong>zmieniony</strong>",
- "%1$s (renamed)" : "%1$s (zmieniona nazwa)",
- "renamed file" : "zmieniona nazwa pliku",
"Failed to authorize" : "Błąd autoryzacji",
"Invalid folder path" : "Nieprawidłowa ścieżka katalogu",
"Folder not found" : "Nie znaleziono katalogu",
@@ -98,6 +96,7 @@ OC.L10N.register(
"Invalid filename." : "Nieprawidłowa nazwa pliku.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Zmieniono nazwę \"{oldName}\" na \"{newName}\"",
"Rename file" : "Zmień nazwę pliku",
+ "Folder" : "Katalog",
"Pending" : "Oczekujące",
"Unknown date" : "Nieznana data",
"Clear filter" : "Wyczyść filtr",
diff --git a/apps/files/l10n/pl.json b/apps/files/l10n/pl.json
index 0fc336bd1bb..18d1ea4ba19 100644
--- a/apps/files/l10n/pl.json
+++ b/apps/files/l10n/pl.json
@@ -41,8 +41,6 @@
"Files" : "Pliki",
"A file or folder has been <strong>changed</strong>" : "Plik lub katalog został <strong>zmieniony</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "Ulubiony plik lub katalog został <strong>zmieniony</strong>",
- "%1$s (renamed)" : "%1$s (zmieniona nazwa)",
- "renamed file" : "zmieniona nazwa pliku",
"Failed to authorize" : "Błąd autoryzacji",
"Invalid folder path" : "Nieprawidłowa ścieżka katalogu",
"Folder not found" : "Nie znaleziono katalogu",
@@ -96,6 +94,7 @@
"Invalid filename." : "Nieprawidłowa nazwa pliku.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Zmieniono nazwę \"{oldName}\" na \"{newName}\"",
"Rename file" : "Zmień nazwę pliku",
+ "Folder" : "Katalog",
"Pending" : "Oczekujące",
"Unknown date" : "Nieznana data",
"Clear filter" : "Wyczyść filtr",
diff --git a/apps/files/l10n/pt_BR.js b/apps/files/l10n/pt_BR.js
index 27571901b39..3308568155b 100644
--- a/apps/files/l10n/pt_BR.js
+++ b/apps/files/l10n/pt_BR.js
@@ -43,8 +43,6 @@ OC.L10N.register(
"Files" : "Arquivos",
"A file or folder has been <strong>changed</strong>" : "Um arquivo ou pasta foi <strong>modificado</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "Um arquivo ou pasta favorita foi <strong>modificado</strong>",
- "%1$s (renamed)" : "%1$s (renomeado)",
- "renamed file" : "arquivo renomeado",
"Failed to authorize" : "Falha ao autorizar",
"Invalid folder path" : "Caminho de pasta inválido",
"Folder not found" : "Pasta não encontrada",
@@ -99,6 +97,7 @@ OC.L10N.register(
"Invalid filename." : "Nome de arquivo inválido.",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" foi renomeado para \"{newName}\"",
"Rename file" : "Renomear arquivo",
+ "Folder" : "Pasta",
"Pending" : "Pendente",
"Unknown date" : "Data desconhecida",
"Clear filter" : "Limpar filtro",
@@ -185,7 +184,7 @@ OC.L10N.register(
"Clipboard is not available" : "A área de transferência não está disponível",
"WebDAV URL copied to clipboard" : "URL de WebDAV copiado para a área de transferência",
"Sort favorites first" : "Ordenar favoritos primeiro",
- "Sort folders before files" : "Classifique as pastas antes dos arquivos",
+ "Sort folders before files" : "Ordenar pastas antes de arquivos",
"Show hidden files" : "Mostrar arquivos ocultos",
"Crop image previews" : "Cortar visualizações de imagem",
"Enable the grid view" : "Ativar a visualização em grade",
@@ -324,7 +323,7 @@ OC.L10N.register(
"Some files could not be moved" : "Alguns arquivos não puderam ser movidos",
"Files copied successfully" : "Arquivos copiados com sucesso",
"Files moved successfully" : "Arquivos movidos com sucesso",
- "Conflicts resolution skipped" : "Resolução de conflitos ignorada",
+ "Conflicts resolution skipped" : "Resolução de conflitos pulada",
"Upload cancelled" : "Upload cancelado",
"This operation is forbidden" : "Esta operação é proibida",
"This directory is unavailable, please check the logs or contact the administrator" : "Este diretório não está disponível, por favor verifique os logs ou contacte o administrador",
@@ -458,7 +457,7 @@ OC.L10N.register(
"Favor" : "Favor",
"Not favored" : "Não favoritado",
"Submitting fields…" : "Enviando campos…",
- "Filter filenames…" : "Filtrar nomes de arquivos...",
+ "Filter filenames…" : "Filtrar nomes de arquivos…",
"{count} files could not be converted" : "{count} arquivos não puderam ser convertidos",
"{count} files successfully converted" : "{count} arquivos convertidos com sucesso"
},
diff --git a/apps/files/l10n/pt_BR.json b/apps/files/l10n/pt_BR.json
index fcf3d2d7425..ceec9ac85f4 100644
--- a/apps/files/l10n/pt_BR.json
+++ b/apps/files/l10n/pt_BR.json
@@ -41,8 +41,6 @@
"Files" : "Arquivos",
"A file or folder has been <strong>changed</strong>" : "Um arquivo ou pasta foi <strong>modificado</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "Um arquivo ou pasta favorita foi <strong>modificado</strong>",
- "%1$s (renamed)" : "%1$s (renomeado)",
- "renamed file" : "arquivo renomeado",
"Failed to authorize" : "Falha ao autorizar",
"Invalid folder path" : "Caminho de pasta inválido",
"Folder not found" : "Pasta não encontrada",
@@ -97,6 +95,7 @@
"Invalid filename." : "Nome de arquivo inválido.",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" foi renomeado para \"{newName}\"",
"Rename file" : "Renomear arquivo",
+ "Folder" : "Pasta",
"Pending" : "Pendente",
"Unknown date" : "Data desconhecida",
"Clear filter" : "Limpar filtro",
@@ -183,7 +182,7 @@
"Clipboard is not available" : "A área de transferência não está disponível",
"WebDAV URL copied to clipboard" : "URL de WebDAV copiado para a área de transferência",
"Sort favorites first" : "Ordenar favoritos primeiro",
- "Sort folders before files" : "Classifique as pastas antes dos arquivos",
+ "Sort folders before files" : "Ordenar pastas antes de arquivos",
"Show hidden files" : "Mostrar arquivos ocultos",
"Crop image previews" : "Cortar visualizações de imagem",
"Enable the grid view" : "Ativar a visualização em grade",
@@ -322,7 +321,7 @@
"Some files could not be moved" : "Alguns arquivos não puderam ser movidos",
"Files copied successfully" : "Arquivos copiados com sucesso",
"Files moved successfully" : "Arquivos movidos com sucesso",
- "Conflicts resolution skipped" : "Resolução de conflitos ignorada",
+ "Conflicts resolution skipped" : "Resolução de conflitos pulada",
"Upload cancelled" : "Upload cancelado",
"This operation is forbidden" : "Esta operação é proibida",
"This directory is unavailable, please check the logs or contact the administrator" : "Este diretório não está disponível, por favor verifique os logs ou contacte o administrador",
@@ -456,7 +455,7 @@
"Favor" : "Favor",
"Not favored" : "Não favoritado",
"Submitting fields…" : "Enviando campos…",
- "Filter filenames…" : "Filtrar nomes de arquivos...",
+ "Filter filenames…" : "Filtrar nomes de arquivos…",
"{count} files could not be converted" : "{count} arquivos não puderam ser convertidos",
"{count} files successfully converted" : "{count} arquivos convertidos com sucesso"
},"pluralForm" :"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
diff --git a/apps/files/l10n/pt_PT.js b/apps/files/l10n/pt_PT.js
index b3200a71984..e886d15e416 100644
--- a/apps/files/l10n/pt_PT.js
+++ b/apps/files/l10n/pt_PT.js
@@ -87,6 +87,7 @@ OC.L10N.register(
"Invalid filename." : "Nome de ficheiro inválido",
"Renamed \"{oldName}\" to \"{newName}\"" : "Renomeado de \"{oldName}\" para \"{newName}\"",
"Rename file" : "Renomear ficheiro",
+ "Folder" : "Pasta",
"Pending" : "Pendente",
"Clear filter" : "Limpar filtro",
"Modified" : "Modificado",
diff --git a/apps/files/l10n/pt_PT.json b/apps/files/l10n/pt_PT.json
index 2374d49b10c..fbfd1f8b17e 100644
--- a/apps/files/l10n/pt_PT.json
+++ b/apps/files/l10n/pt_PT.json
@@ -85,6 +85,7 @@
"Invalid filename." : "Nome de ficheiro inválido",
"Renamed \"{oldName}\" to \"{newName}\"" : "Renomeado de \"{oldName}\" para \"{newName}\"",
"Rename file" : "Renomear ficheiro",
+ "Folder" : "Pasta",
"Pending" : "Pendente",
"Clear filter" : "Limpar filtro",
"Modified" : "Modificado",
diff --git a/apps/files/l10n/ro.js b/apps/files/l10n/ro.js
index 3a9734aeb78..e9a3ad15038 100644
--- a/apps/files/l10n/ro.js
+++ b/apps/files/l10n/ro.js
@@ -68,6 +68,7 @@ OC.L10N.register(
"This node is unavailable" : "Acest nod este indisponibil",
"Renamed \"{oldName}\" to \"{newName}\"" : "A fost redenumit \"{oldName}\" cu \"{newName}\"",
"Rename file" : "Redenumire fișier",
+ "Folder" : "Director",
"Pending" : "În așteptare",
"Clear filter" : "Șterge filtrul",
"Modified" : "Modificat",
diff --git a/apps/files/l10n/ro.json b/apps/files/l10n/ro.json
index 578cc0ba164..d724774b53d 100644
--- a/apps/files/l10n/ro.json
+++ b/apps/files/l10n/ro.json
@@ -66,6 +66,7 @@
"This node is unavailable" : "Acest nod este indisponibil",
"Renamed \"{oldName}\" to \"{newName}\"" : "A fost redenumit \"{oldName}\" cu \"{newName}\"",
"Rename file" : "Redenumire fișier",
+ "Folder" : "Director",
"Pending" : "În așteptare",
"Clear filter" : "Șterge filtrul",
"Modified" : "Modificat",
diff --git a/apps/files/l10n/ru.js b/apps/files/l10n/ru.js
index d5e6686c379..19a5884ab39 100644
--- a/apps/files/l10n/ru.js
+++ b/apps/files/l10n/ru.js
@@ -95,6 +95,7 @@ OC.L10N.register(
"Invalid filename." : "Недопустимое имя файла.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Переименовано «{oldName}» в \"{newName}\"",
"Rename file" : "Переименовать файл",
+ "Folder" : "Каталог",
"Pending" : "Ожидается",
"Unknown date" : "Неизвестная дата",
"Clear filter" : "Сбросить фильтр",
diff --git a/apps/files/l10n/ru.json b/apps/files/l10n/ru.json
index e60b7d59675..a6f6a5d1f86 100644
--- a/apps/files/l10n/ru.json
+++ b/apps/files/l10n/ru.json
@@ -93,6 +93,7 @@
"Invalid filename." : "Недопустимое имя файла.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Переименовано «{oldName}» в \"{newName}\"",
"Rename file" : "Переименовать файл",
+ "Folder" : "Каталог",
"Pending" : "Ожидается",
"Unknown date" : "Неизвестная дата",
"Clear filter" : "Сбросить фильтр",
diff --git a/apps/files/l10n/sc.js b/apps/files/l10n/sc.js
index ce6a33178ab..c069340f269 100644
--- a/apps/files/l10n/sc.js
+++ b/apps/files/l10n/sc.js
@@ -66,6 +66,7 @@ OC.L10N.register(
"Folder name" : "Nùmene de sa cartella",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" s'est torradu a numenare comente \"{newName}\"",
"Rename file" : "Torra a numenare s'archìviu",
+ "Folder" : "Cartella",
"Pending" : "In suspesu",
"Clear filter" : "Lìmpia filtru",
"Modified" : "Modificadu",
diff --git a/apps/files/l10n/sc.json b/apps/files/l10n/sc.json
index b62a8bfe963..3966e3006c1 100644
--- a/apps/files/l10n/sc.json
+++ b/apps/files/l10n/sc.json
@@ -64,6 +64,7 @@
"Folder name" : "Nùmene de sa cartella",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" s'est torradu a numenare comente \"{newName}\"",
"Rename file" : "Torra a numenare s'archìviu",
+ "Folder" : "Cartella",
"Pending" : "In suspesu",
"Clear filter" : "Lìmpia filtru",
"Modified" : "Modificadu",
diff --git a/apps/files/l10n/sk.js b/apps/files/l10n/sk.js
index b1cc68855dc..96931816ccb 100644
--- a/apps/files/l10n/sk.js
+++ b/apps/files/l10n/sk.js
@@ -95,6 +95,7 @@ OC.L10N.register(
"Invalid filename." : "Chybný názov súboru.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Premenované z \"{oldName}\" na \"{newName}\"",
"Rename file" : "Premenovať súbor",
+ "Folder" : "Priečinok",
"Pending" : "Čaká",
"Unknown date" : "Neznámy dátum",
"Clear filter" : "Vyčistiť filter",
diff --git a/apps/files/l10n/sk.json b/apps/files/l10n/sk.json
index ea475f6befa..c7959344aeb 100644
--- a/apps/files/l10n/sk.json
+++ b/apps/files/l10n/sk.json
@@ -93,6 +93,7 @@
"Invalid filename." : "Chybný názov súboru.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Premenované z \"{oldName}\" na \"{newName}\"",
"Rename file" : "Premenovať súbor",
+ "Folder" : "Priečinok",
"Pending" : "Čaká",
"Unknown date" : "Neznámy dátum",
"Clear filter" : "Vyčistiť filter",
diff --git a/apps/files/l10n/sl.js b/apps/files/l10n/sl.js
index df903ce2c02..8d0f4ad1972 100644
--- a/apps/files/l10n/sl.js
+++ b/apps/files/l10n/sl.js
@@ -48,6 +48,7 @@ OC.L10N.register(
"Folder not found" : "Mape ni mogoče najti",
"The file cannot be found" : "Datoteke ni mogoče najti.",
"The destination path does not exist: %1$s" : "Cilja pot ne obstaja: %1$s",
+ "You do not have permission to create a file at the specified location" : "Nimate pravice za stvarjenje datoteke na podani lokaciji",
"The file could not be converted." : "Datoteke ni mogoče pretvoriti.",
"Could not get relative path to converted file" : "Ni mogoče pridobiti relativne poti do pretvorjene datoteke.",
"Favorite files" : "Priljubljene datoteke",
@@ -59,6 +60,7 @@ OC.L10N.register(
"Incoming ownership transfer from {user}" : "Vpisana je zahteva za prenos lastništva uporabnika {user}",
"Do you want to accept {path}?\n\nNote: The transfer process after accepting may take up to 1 hour." : "Ali želite sprejeti pot {path}?\n\nOpomba: po sprejetju lahko prenos traja tudi več kot 1 uro.",
"Ownership transfer denied" : "Prenos lastništva je spodletel",
+ "Your ownership transfer of {path} was denied by {user}." : "Prenos lastništva za {path} je onemogočil {user}.",
"Ownership transfer failed" : "Prenos lastništva je spodletel",
"Your ownership transfer of {path} to {user} failed." : "Prenos lastništva mesta {path} na uporabnika {user} je spodletel.",
"The ownership transfer of {path} from {user} failed." : "Prenos lastništva mesta {path} na uporabnika {user} je spodletel.",
@@ -66,17 +68,26 @@ OC.L10N.register(
"Your ownership transfer of {path} to {user} has completed." : "Prenos lastništva poti {path} na uporabnika {user} je končan.",
"The ownership transfer of {path} from {user} has completed." : "Prenos lastništva poti {path} z uporabnika {user} je končan.",
"in %s" : "v %s",
+ "Transferred from %1$s on %2$s" : "Preneseno iz %1$s na %2$s",
"Files compatibility" : "Skladnost datotek",
+ "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Dovoli omejitev imen datotek za zagotovitev sinhronizacije datotek z vsemi odjemalci. Privzeto je dovoljenje za vsa imena datotek na POSIX (tj. Linux ali macOS).",
+ "After enabling the Windows compatible filenames, existing files cannot be modified anymore but can be renamed to valid new names by their owner." : "Po vklopu imen, ki so združljiva z WIndows, obstoječih datotek ni več mogoče spreminjati, jih pa lahko lastnik preimenuje v ustrezno ime.",
+ "It is also possible to migrate files automatically after enabling this setting, please refer to the documentation about the occ command." : "Datoteke lahko po vklopu te možnosti tudi same migrirajo. Preverite dokumentacijo o ukazu occ.",
"Enforce Windows compatibility" : "Vsili skladnost s sistemom Windows",
+ "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "To bo blokiralo imena datotek, ki niso ustrezna za Windows sisteme, kot so rezervirana imena ali posebni znaki, ne bo pa to vsililo združljivosti pri razlikovanju velikih in malih črk imena.",
"File Management" : "Upravljanje datotek",
"Home" : "Začetni pogled",
"Target folder does not exist any more" : "Ciljna mapa ne obstaja več",
"Reload current directory" : "Ponovno naloži trenutno mapo",
"Go to the \"{dir}\" directory" : "Pojdi v mapo »{dir}«",
"Current directory path" : "Trenutna pot mape",
+ "Your have used your space quota and cannot upload files anymore" : "Porabili ste svojo količino prostora in datotek več ne morete nalagati",
+ "You do not have permission to upload or create files here." : "Nimate pravic za ustvarjanje ali nalaganje datotek na to mesto.",
"Drag and drop files here to upload" : "Za pošiljanje potegnite in spustite datoteke na to mesto",
"Favorite" : "Priljubljene",
"Back" : "Nazaj",
+ "Toggle selection for file \"{displayName}\"" : "Preklopi izbor za datoteko \"{displayName}\"",
+ "Toggle selection for folder \"{displayName}\"" : "Preklopi izbor za mapo \"{displayName}\"",
"File is loading" : "Poteka nalaganje datoteke",
"Folder is loading" : "mape",
"Filename" : "Ime datoteke",
@@ -86,20 +97,26 @@ OC.L10N.register(
"Invalid filename." : "Neveljavno ime datoteke",
"Renamed \"{oldName}\" to \"{newName}\"" : "Preimenuj »{oldName}« to »{newName}«",
"Rename file" : "Preimenuj datoteke",
+ "Folder" : "Mapa",
"Pending" : "Na čakanju ...",
+ "Unknown date" : "Neznani datum",
"Clear filter" : "Počisti filter",
"Modified" : "Spremenjeno",
"Type" : "Vrsta",
"Active filters" : "Dejavni filtri",
"Remove filter" : "Odstrani filter",
"Total rows summary" : "Skupni povzetek vrstic",
+ "Toggle selection for all files and folders" : "Preklopi izbor za vse datoteke in mape",
"Name" : "Ime",
"Size" : "Velikost",
+ "\"{displayName}\" failed on some elements" : "\"{displayName}\" ni uspel za nekatere elemente",
"\"{displayName}\" batch action executed successfully" : "Paketno dejanje »{displayName}« je uspešno izvedeno",
"\"{displayName}\" action failed" : "Dejanje »{displayName}« je spodletelo",
"Actions" : "Dejanja",
"(selected)" : "(izbrano)",
"List of files and folders." : "Seznam datotek in map",
+ "You have used your space quota and cannot upload files anymore." : "Porabili ste svojo količino prostora in datotek več ne morete nalagati",
+ "Column headers with buttons are sortable." : "Naslove stolpcev z gumbi je mogoče sortirati.",
"This list is not fully rendered for performance reasons. The files will be rendered as you navigate through the list." : "Seznam datotek ni v celoti izpisan zaradi zagotavljanja hitrosti in odzivnosti sistema. Predmeti se bodo dopolnjevali med brskanjem.",
"File not found" : "Datoteke ni mogoče najti",
"{count} selected" : "{count} izbranih",
@@ -133,6 +150,9 @@ OC.L10N.register(
"Use {new}" : "Uporabi {new}",
"Remove extension" : "Odstrani pripono",
"Change file extension" : "Spremeni pripono datoteke",
+ "Changing the file extension from \"{old}\" to \"{new}\" may render the file unreadable." : "Sprememba končnice datoteke iz \"{old}\" v \"{new}\" lahko naredi datoteko neberljivo.",
+ "Removing the file extension \"{old}\" may render the file unreadable." : "Odstranitev končnice datoteke \"{old}\" lahko naredi datoteko neberljivo.",
+ "Adding the file extension \"{new}\" may render the file unreadable." : "Dadajanje končnice datoteke \"{new}\" lahko naredi datoteko neberljivo.",
"Do not show this dialog again." : "Pogovornega okna ne pokaži več.",
"Select file or folder to link to" : "Izbor datoteke ali mape za povezavo",
"Choose {file}" : "Izberite datoteko {file}",
@@ -141,9 +161,12 @@ OC.L10N.register(
"Shared" : "V souporabi",
"Switch to list view" : "Preklopi na seznamski pogled",
"Switch to grid view" : "Preklopi na mrežni pogled",
+ "The file could not be found" : "Datoteke ni mogoče najti.",
"Upload was cancelled by user" : "Uporabnik je pošiljanje preklical",
"Not enough free space" : "Ni dovolj prostora",
"Operation is blocked by access control" : "Opravilo je zaustavljeno prek nadzora dostopa",
+ "Error during upload: {message}" : "Napaka med nalaganjem: {message}",
+ "Error during upload, status code {status}" : "Napaka med nalaganje s kodo stanja {status}",
"Unknown error during upload" : "Med pošiljanjem je prišlo do neznane napake",
"\"{displayName}\" action executed successfully" : "Dejanje »{displayName}« je uspešno izvedeno",
"Loading current folder" : "Poteka nalaganje trenutne mape",
@@ -151,11 +174,13 @@ OC.L10N.register(
"No files in here" : "V mapi ni datotek",
"Upload some content or sync with your devices!" : "Uvozite vsebino, ali pa omogočite usklajevanje z napravami!",
"Go back" : "Skoči nazaj",
+ "Filter file names …" : "Filtriraj imena datotek...",
"Views" : "Pogledi",
"Files settings" : "Nastavitve datotek",
"Your files" : "Osebne datoteke",
"Open in files" : "Odpri datoteko v mapi",
"File cannot be accessed" : "Do datoteke dostop ni mogoč",
+ "The file could not be found or you do not have permissions to view it. Ask the sender to share it." : "Datoteke ni bilo mogoče najti ali pa nimate ustreznih dovoljenj za ogled. Prosite pošiljatelja, da jo deli.",
"Clipboard is not available" : "Odložišče ni na voljo",
"WebDAV URL copied to clipboard" : "Naslov URL WebDAV je kopiran v odložišče",
"Sort favorites first" : "Razvrsti najprej priljubljene",
@@ -170,7 +195,12 @@ OC.L10N.register(
"Copy to clipboard" : "Kopiraj v odložišče",
"Use this address to access your Files via WebDAV" : "Uporabite ta naslov za dostop do datotek z uporabo WebDAV",
"If you have enabled 2FA, you must create and use a new app password by clicking here." : "Če je omogočen sistem dvostopenjskega overjanja 2FA, je treba ustvariti in uporabiti novo geslo programa s klikom na to mesto.",
+ "Warnings" : "Opozorila",
+ "Prevent warning dialogs from open or reenable them." : "Preprečite odpiranje dialogov z opozorili ali jih ponovno omogočite.",
+ "Show a warning dialog when changing a file extension." : "Prikaži opozorilo ob spreminjanju končnice datoteke.",
"Keyboard shortcuts" : "Tipkovne bližnjice",
+ "Speed up your Files experience with these quick shortcuts." : "Pospešite uporabo upravljalnika Files s temi bližnjicami.",
+ "Open the actions menu for a file" : "Odpri meni dejanj za datoteko",
"Rename a file" : "Preimenuj datoteko",
"Delete a file" : "Izbriši datoteko",
"Favorite or remove a file from favorites" : "Označi ali odstrani koz priljubljeno",
@@ -181,7 +211,14 @@ OC.L10N.register(
"Select or deselect a file" : "Izberi ali odstrani izbor datoteke",
"Select a range of files" : "Izbor obsega datotek",
"Navigation" : "Krmarjenje",
+ "Navigate to the parent folder" : "Pojdi na nadrejeni imenik",
+ "Navigate to the file above" : "Pojdi na datoteko zgoraj",
+ "Navigate to the file below" : "Pojdi na doatoteko spodaj",
+ "Navigate to the file on the left (in grid mode)" : "Pojdi na datoteko na levi (v mrežnem načinu)",
+ "Navigate to the file on the right (in grid mode)" : "Pojdi na datoteko na desni (v mrežnem načinu)",
"View" : "Pogled",
+ "Toggle the grid view" : "Preklopi mrežni način",
+ "Open the sidebar for a file" : "Odpri stranski pano datoteke",
"Show those shortcuts" : "Pokaži tipkovne bližnjice",
"You" : "Jaz",
"Shared multiple times with different people" : "V več souporabah z različnimi uporabniki",
@@ -221,8 +258,12 @@ OC.L10N.register(
"Delete folder" : "Izbriši mapo",
"Delete folders" : "Izbriši mape",
"Delete" : "Izbriši",
+ "_You are about to permanently delete {count} item_::_You are about to permanently delete {count} items_" : ["Za stalno boste izbrisali {count} predmet","Za stalno boste izbrisali {count} predmeta","Za stalno boste izbrisali {count} predmete","Za stalno boste izbrisali {count} predmetov"],
+ "_You are about to delete {count} item_::_You are about to delete {count} items_" : ["Izbrisali boste {count} predmet","Izbrisali boste {count} predmeta","Izbrisali boste {count} predmete","Izbrisali boste {count} predmetov"],
"Confirm deletion" : "Potrdi brisanje",
"Cancel" : "Prekliči",
+ "Moving \"{source}\" to \"{destination}\" …" : "Premik \"{source}\" v \"{destination}\"...",
+ "Copying \"{source}\" to \"{destination}\" …" : "Kopiranje \"{source}\" v \"{destination}\"...",
"You cannot move a file/folder onto itself or into a subfolder of itself" : "Mape ali datoteke ni mogoče premakniti samo vase oziroma v podmapo same sebe",
"(copy)" : "(kopija)",
"(copy %n)" : "(kopija %n)",
@@ -237,10 +278,13 @@ OC.L10N.register(
"Move" : "Premakni",
"Move or copy operation failed" : "Opravilo kopiranja oziroma premikanja je spodletelo",
"Move or copy" : "Premakni ali kopiraj",
+ "Cancelled move or copy of \"{filename}\"." : "Prekinjeno premikanje ali kopiranje za \"{filename}\".",
"Cancelled move or copy operation" : "Opravilo kopiranje in premikanja je preklicano",
"Open folder {displayName}" : "Odpri mapo {displayName}",
"Open in Files" : "Open in Files",
"Open file locally" : "Odpri datoteko krajevno",
+ "The file should now open on your device. If it doesn't, please check that you have the desktop app installed." : "Datoteka bi se sedaj morala odpreti z vaše naprave. Če se to ne zgodi, preverite namestitev namizne aplikacije.",
+ "Retry and close" : "Ponovno poskusi in zapri",
"Open online" : "Odpri v brskalniku",
"Failed to redirect to client" : "Preusmerjanje odjemalca je spodletelo",
"Open locally" : "Odpri krajevno",
@@ -268,7 +312,10 @@ OC.L10N.register(
"New template folder" : "Nova mapa predlog",
"In folder" : "V mapi",
"Search in folder: {folder}" : "Išči v mapi: {folder}",
+ "One of the dropped files could not be processed" : "Eno od podanih datotek ni bilo mogoče obdelati",
+ "Your browser does not support the Filesystem API. Directories will not be uploaded" : "Brskalnik ne podpira API datotečnega sistema. Mape ne bodo naložene",
"No files to upload" : "Ni datotek za pošiljanje",
+ "Unable to create the directory {directory}" : "Mape {directory} ni mogoče ustvariti",
"Some files could not be uploaded" : "Nekaterih datotek ni bilo mogoče poslati",
"Files uploaded successfully" : "Datoteke so uspešno poslane v oblak",
"No files to process" : "Ni datotek za obdelavo",
@@ -286,13 +333,20 @@ OC.L10N.register(
"_%n folder_::_%n folders_" : ["%n mapa","%n mapi","%n mape","%n mape"],
"_%n hidden_::_%n hidden_" : ["%n skrita","%n skriti","%n skrite","%n skritih"],
"Filename must not be empty." : "Ime datoteke ne sme biti prazno.",
+ "\"{char}\" is not allowed inside a filename." : "Znak \"{char}\" ni dovoljen v imenu datotek.",
+ "\"{segment}\" is a reserved name and not allowed for filenames." : "\"{segment}\" je rezervirano ime in ni dovoljeno za ime datoteke.",
+ "\"{extension}\" is not an allowed filetype." : "\"{extension}\" ni dovoljena vrsta končnice.",
+ "Filenames must not end with \"{extension}\"." : "Imena datotek naj nimajo končnice \"{extension}\".",
+ "List of favorite files and folders." : "Seznam priljubljenih datotek in map.",
"No favorites yet" : "Ni še dodanih priljubljenih predmetov",
"Files and folders you mark as favorite will show up here" : "Datoteke ali mape, ki so označene kot priljubljene, bodo zbrane na tem mestu.",
"All files" : "Vse datoteke",
"List of your files and folders." : "Seznam datotek in map.",
"All folders" : "Vse mape",
"Personal files" : "Osebne datoteke",
+ "List of your files and folders that are not shared." : "Seznam datotek in map, ki niso v skupni rabi.",
"No personal files found" : "Ni najdenih zasebnih datotek",
+ "Files that are not shared will show up here." : "Datoteke, ki niso v skupni rabi, bodo prikazane tukaj.",
"Recent" : "Nedavne",
"List of recently modified files and folders." : "Seznam nedavno spremenjenih datotek in map.",
"No recently modified files" : "Ni nedavno spremenjenih datotek",
@@ -381,6 +435,7 @@ OC.L10N.register(
"Upload file" : "Pošlji datoteko",
"Not favorited" : "Ni priljubljeno",
"An error occurred while trying to update the tags" : "Prišlo je do napake med posodabljanjem oznak",
+ "You don't have permission to upload or create files here." : "Nimate pravic za nalaganje ali ustvarjanje datotek na tem mestu.",
"Storage informations" : "Podrobnosti shrambe",
"Choose file" : "Izbor datotek",
"Go to the previous folder" : "Skoči na predhodno mapo",
diff --git a/apps/files/l10n/sl.json b/apps/files/l10n/sl.json
index e3cd9759f08..579b32d200f 100644
--- a/apps/files/l10n/sl.json
+++ b/apps/files/l10n/sl.json
@@ -46,6 +46,7 @@
"Folder not found" : "Mape ni mogoče najti",
"The file cannot be found" : "Datoteke ni mogoče najti.",
"The destination path does not exist: %1$s" : "Cilja pot ne obstaja: %1$s",
+ "You do not have permission to create a file at the specified location" : "Nimate pravice za stvarjenje datoteke na podani lokaciji",
"The file could not be converted." : "Datoteke ni mogoče pretvoriti.",
"Could not get relative path to converted file" : "Ni mogoče pridobiti relativne poti do pretvorjene datoteke.",
"Favorite files" : "Priljubljene datoteke",
@@ -57,6 +58,7 @@
"Incoming ownership transfer from {user}" : "Vpisana je zahteva za prenos lastništva uporabnika {user}",
"Do you want to accept {path}?\n\nNote: The transfer process after accepting may take up to 1 hour." : "Ali želite sprejeti pot {path}?\n\nOpomba: po sprejetju lahko prenos traja tudi več kot 1 uro.",
"Ownership transfer denied" : "Prenos lastništva je spodletel",
+ "Your ownership transfer of {path} was denied by {user}." : "Prenos lastništva za {path} je onemogočil {user}.",
"Ownership transfer failed" : "Prenos lastništva je spodletel",
"Your ownership transfer of {path} to {user} failed." : "Prenos lastništva mesta {path} na uporabnika {user} je spodletel.",
"The ownership transfer of {path} from {user} failed." : "Prenos lastništva mesta {path} na uporabnika {user} je spodletel.",
@@ -64,17 +66,26 @@
"Your ownership transfer of {path} to {user} has completed." : "Prenos lastništva poti {path} na uporabnika {user} je končan.",
"The ownership transfer of {path} from {user} has completed." : "Prenos lastništva poti {path} z uporabnika {user} je končan.",
"in %s" : "v %s",
+ "Transferred from %1$s on %2$s" : "Preneseno iz %1$s na %2$s",
"Files compatibility" : "Skladnost datotek",
+ "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Dovoli omejitev imen datotek za zagotovitev sinhronizacije datotek z vsemi odjemalci. Privzeto je dovoljenje za vsa imena datotek na POSIX (tj. Linux ali macOS).",
+ "After enabling the Windows compatible filenames, existing files cannot be modified anymore but can be renamed to valid new names by their owner." : "Po vklopu imen, ki so združljiva z WIndows, obstoječih datotek ni več mogoče spreminjati, jih pa lahko lastnik preimenuje v ustrezno ime.",
+ "It is also possible to migrate files automatically after enabling this setting, please refer to the documentation about the occ command." : "Datoteke lahko po vklopu te možnosti tudi same migrirajo. Preverite dokumentacijo o ukazu occ.",
"Enforce Windows compatibility" : "Vsili skladnost s sistemom Windows",
+ "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "To bo blokiralo imena datotek, ki niso ustrezna za Windows sisteme, kot so rezervirana imena ali posebni znaki, ne bo pa to vsililo združljivosti pri razlikovanju velikih in malih črk imena.",
"File Management" : "Upravljanje datotek",
"Home" : "Začetni pogled",
"Target folder does not exist any more" : "Ciljna mapa ne obstaja več",
"Reload current directory" : "Ponovno naloži trenutno mapo",
"Go to the \"{dir}\" directory" : "Pojdi v mapo »{dir}«",
"Current directory path" : "Trenutna pot mape",
+ "Your have used your space quota and cannot upload files anymore" : "Porabili ste svojo količino prostora in datotek več ne morete nalagati",
+ "You do not have permission to upload or create files here." : "Nimate pravic za ustvarjanje ali nalaganje datotek na to mesto.",
"Drag and drop files here to upload" : "Za pošiljanje potegnite in spustite datoteke na to mesto",
"Favorite" : "Priljubljene",
"Back" : "Nazaj",
+ "Toggle selection for file \"{displayName}\"" : "Preklopi izbor za datoteko \"{displayName}\"",
+ "Toggle selection for folder \"{displayName}\"" : "Preklopi izbor za mapo \"{displayName}\"",
"File is loading" : "Poteka nalaganje datoteke",
"Folder is loading" : "mape",
"Filename" : "Ime datoteke",
@@ -84,20 +95,26 @@
"Invalid filename." : "Neveljavno ime datoteke",
"Renamed \"{oldName}\" to \"{newName}\"" : "Preimenuj »{oldName}« to »{newName}«",
"Rename file" : "Preimenuj datoteke",
+ "Folder" : "Mapa",
"Pending" : "Na čakanju ...",
+ "Unknown date" : "Neznani datum",
"Clear filter" : "Počisti filter",
"Modified" : "Spremenjeno",
"Type" : "Vrsta",
"Active filters" : "Dejavni filtri",
"Remove filter" : "Odstrani filter",
"Total rows summary" : "Skupni povzetek vrstic",
+ "Toggle selection for all files and folders" : "Preklopi izbor za vse datoteke in mape",
"Name" : "Ime",
"Size" : "Velikost",
+ "\"{displayName}\" failed on some elements" : "\"{displayName}\" ni uspel za nekatere elemente",
"\"{displayName}\" batch action executed successfully" : "Paketno dejanje »{displayName}« je uspešno izvedeno",
"\"{displayName}\" action failed" : "Dejanje »{displayName}« je spodletelo",
"Actions" : "Dejanja",
"(selected)" : "(izbrano)",
"List of files and folders." : "Seznam datotek in map",
+ "You have used your space quota and cannot upload files anymore." : "Porabili ste svojo količino prostora in datotek več ne morete nalagati",
+ "Column headers with buttons are sortable." : "Naslove stolpcev z gumbi je mogoče sortirati.",
"This list is not fully rendered for performance reasons. The files will be rendered as you navigate through the list." : "Seznam datotek ni v celoti izpisan zaradi zagotavljanja hitrosti in odzivnosti sistema. Predmeti se bodo dopolnjevali med brskanjem.",
"File not found" : "Datoteke ni mogoče najti",
"{count} selected" : "{count} izbranih",
@@ -131,6 +148,9 @@
"Use {new}" : "Uporabi {new}",
"Remove extension" : "Odstrani pripono",
"Change file extension" : "Spremeni pripono datoteke",
+ "Changing the file extension from \"{old}\" to \"{new}\" may render the file unreadable." : "Sprememba končnice datoteke iz \"{old}\" v \"{new}\" lahko naredi datoteko neberljivo.",
+ "Removing the file extension \"{old}\" may render the file unreadable." : "Odstranitev končnice datoteke \"{old}\" lahko naredi datoteko neberljivo.",
+ "Adding the file extension \"{new}\" may render the file unreadable." : "Dadajanje končnice datoteke \"{new}\" lahko naredi datoteko neberljivo.",
"Do not show this dialog again." : "Pogovornega okna ne pokaži več.",
"Select file or folder to link to" : "Izbor datoteke ali mape za povezavo",
"Choose {file}" : "Izberite datoteko {file}",
@@ -139,9 +159,12 @@
"Shared" : "V souporabi",
"Switch to list view" : "Preklopi na seznamski pogled",
"Switch to grid view" : "Preklopi na mrežni pogled",
+ "The file could not be found" : "Datoteke ni mogoče najti.",
"Upload was cancelled by user" : "Uporabnik je pošiljanje preklical",
"Not enough free space" : "Ni dovolj prostora",
"Operation is blocked by access control" : "Opravilo je zaustavljeno prek nadzora dostopa",
+ "Error during upload: {message}" : "Napaka med nalaganjem: {message}",
+ "Error during upload, status code {status}" : "Napaka med nalaganje s kodo stanja {status}",
"Unknown error during upload" : "Med pošiljanjem je prišlo do neznane napake",
"\"{displayName}\" action executed successfully" : "Dejanje »{displayName}« je uspešno izvedeno",
"Loading current folder" : "Poteka nalaganje trenutne mape",
@@ -149,11 +172,13 @@
"No files in here" : "V mapi ni datotek",
"Upload some content or sync with your devices!" : "Uvozite vsebino, ali pa omogočite usklajevanje z napravami!",
"Go back" : "Skoči nazaj",
+ "Filter file names …" : "Filtriraj imena datotek...",
"Views" : "Pogledi",
"Files settings" : "Nastavitve datotek",
"Your files" : "Osebne datoteke",
"Open in files" : "Odpri datoteko v mapi",
"File cannot be accessed" : "Do datoteke dostop ni mogoč",
+ "The file could not be found or you do not have permissions to view it. Ask the sender to share it." : "Datoteke ni bilo mogoče najti ali pa nimate ustreznih dovoljenj za ogled. Prosite pošiljatelja, da jo deli.",
"Clipboard is not available" : "Odložišče ni na voljo",
"WebDAV URL copied to clipboard" : "Naslov URL WebDAV je kopiran v odložišče",
"Sort favorites first" : "Razvrsti najprej priljubljene",
@@ -168,7 +193,12 @@
"Copy to clipboard" : "Kopiraj v odložišče",
"Use this address to access your Files via WebDAV" : "Uporabite ta naslov za dostop do datotek z uporabo WebDAV",
"If you have enabled 2FA, you must create and use a new app password by clicking here." : "Če je omogočen sistem dvostopenjskega overjanja 2FA, je treba ustvariti in uporabiti novo geslo programa s klikom na to mesto.",
+ "Warnings" : "Opozorila",
+ "Prevent warning dialogs from open or reenable them." : "Preprečite odpiranje dialogov z opozorili ali jih ponovno omogočite.",
+ "Show a warning dialog when changing a file extension." : "Prikaži opozorilo ob spreminjanju končnice datoteke.",
"Keyboard shortcuts" : "Tipkovne bližnjice",
+ "Speed up your Files experience with these quick shortcuts." : "Pospešite uporabo upravljalnika Files s temi bližnjicami.",
+ "Open the actions menu for a file" : "Odpri meni dejanj za datoteko",
"Rename a file" : "Preimenuj datoteko",
"Delete a file" : "Izbriši datoteko",
"Favorite or remove a file from favorites" : "Označi ali odstrani koz priljubljeno",
@@ -179,7 +209,14 @@
"Select or deselect a file" : "Izberi ali odstrani izbor datoteke",
"Select a range of files" : "Izbor obsega datotek",
"Navigation" : "Krmarjenje",
+ "Navigate to the parent folder" : "Pojdi na nadrejeni imenik",
+ "Navigate to the file above" : "Pojdi na datoteko zgoraj",
+ "Navigate to the file below" : "Pojdi na doatoteko spodaj",
+ "Navigate to the file on the left (in grid mode)" : "Pojdi na datoteko na levi (v mrežnem načinu)",
+ "Navigate to the file on the right (in grid mode)" : "Pojdi na datoteko na desni (v mrežnem načinu)",
"View" : "Pogled",
+ "Toggle the grid view" : "Preklopi mrežni način",
+ "Open the sidebar for a file" : "Odpri stranski pano datoteke",
"Show those shortcuts" : "Pokaži tipkovne bližnjice",
"You" : "Jaz",
"Shared multiple times with different people" : "V več souporabah z različnimi uporabniki",
@@ -219,8 +256,12 @@
"Delete folder" : "Izbriši mapo",
"Delete folders" : "Izbriši mape",
"Delete" : "Izbriši",
+ "_You are about to permanently delete {count} item_::_You are about to permanently delete {count} items_" : ["Za stalno boste izbrisali {count} predmet","Za stalno boste izbrisali {count} predmeta","Za stalno boste izbrisali {count} predmete","Za stalno boste izbrisali {count} predmetov"],
+ "_You are about to delete {count} item_::_You are about to delete {count} items_" : ["Izbrisali boste {count} predmet","Izbrisali boste {count} predmeta","Izbrisali boste {count} predmete","Izbrisali boste {count} predmetov"],
"Confirm deletion" : "Potrdi brisanje",
"Cancel" : "Prekliči",
+ "Moving \"{source}\" to \"{destination}\" …" : "Premik \"{source}\" v \"{destination}\"...",
+ "Copying \"{source}\" to \"{destination}\" …" : "Kopiranje \"{source}\" v \"{destination}\"...",
"You cannot move a file/folder onto itself or into a subfolder of itself" : "Mape ali datoteke ni mogoče premakniti samo vase oziroma v podmapo same sebe",
"(copy)" : "(kopija)",
"(copy %n)" : "(kopija %n)",
@@ -235,10 +276,13 @@
"Move" : "Premakni",
"Move or copy operation failed" : "Opravilo kopiranja oziroma premikanja je spodletelo",
"Move or copy" : "Premakni ali kopiraj",
+ "Cancelled move or copy of \"{filename}\"." : "Prekinjeno premikanje ali kopiranje za \"{filename}\".",
"Cancelled move or copy operation" : "Opravilo kopiranje in premikanja je preklicano",
"Open folder {displayName}" : "Odpri mapo {displayName}",
"Open in Files" : "Open in Files",
"Open file locally" : "Odpri datoteko krajevno",
+ "The file should now open on your device. If it doesn't, please check that you have the desktop app installed." : "Datoteka bi se sedaj morala odpreti z vaše naprave. Če se to ne zgodi, preverite namestitev namizne aplikacije.",
+ "Retry and close" : "Ponovno poskusi in zapri",
"Open online" : "Odpri v brskalniku",
"Failed to redirect to client" : "Preusmerjanje odjemalca je spodletelo",
"Open locally" : "Odpri krajevno",
@@ -266,7 +310,10 @@
"New template folder" : "Nova mapa predlog",
"In folder" : "V mapi",
"Search in folder: {folder}" : "Išči v mapi: {folder}",
+ "One of the dropped files could not be processed" : "Eno od podanih datotek ni bilo mogoče obdelati",
+ "Your browser does not support the Filesystem API. Directories will not be uploaded" : "Brskalnik ne podpira API datotečnega sistema. Mape ne bodo naložene",
"No files to upload" : "Ni datotek za pošiljanje",
+ "Unable to create the directory {directory}" : "Mape {directory} ni mogoče ustvariti",
"Some files could not be uploaded" : "Nekaterih datotek ni bilo mogoče poslati",
"Files uploaded successfully" : "Datoteke so uspešno poslane v oblak",
"No files to process" : "Ni datotek za obdelavo",
@@ -284,13 +331,20 @@
"_%n folder_::_%n folders_" : ["%n mapa","%n mapi","%n mape","%n mape"],
"_%n hidden_::_%n hidden_" : ["%n skrita","%n skriti","%n skrite","%n skritih"],
"Filename must not be empty." : "Ime datoteke ne sme biti prazno.",
+ "\"{char}\" is not allowed inside a filename." : "Znak \"{char}\" ni dovoljen v imenu datotek.",
+ "\"{segment}\" is a reserved name and not allowed for filenames." : "\"{segment}\" je rezervirano ime in ni dovoljeno za ime datoteke.",
+ "\"{extension}\" is not an allowed filetype." : "\"{extension}\" ni dovoljena vrsta končnice.",
+ "Filenames must not end with \"{extension}\"." : "Imena datotek naj nimajo končnice \"{extension}\".",
+ "List of favorite files and folders." : "Seznam priljubljenih datotek in map.",
"No favorites yet" : "Ni še dodanih priljubljenih predmetov",
"Files and folders you mark as favorite will show up here" : "Datoteke ali mape, ki so označene kot priljubljene, bodo zbrane na tem mestu.",
"All files" : "Vse datoteke",
"List of your files and folders." : "Seznam datotek in map.",
"All folders" : "Vse mape",
"Personal files" : "Osebne datoteke",
+ "List of your files and folders that are not shared." : "Seznam datotek in map, ki niso v skupni rabi.",
"No personal files found" : "Ni najdenih zasebnih datotek",
+ "Files that are not shared will show up here." : "Datoteke, ki niso v skupni rabi, bodo prikazane tukaj.",
"Recent" : "Nedavne",
"List of recently modified files and folders." : "Seznam nedavno spremenjenih datotek in map.",
"No recently modified files" : "Ni nedavno spremenjenih datotek",
@@ -379,6 +433,7 @@
"Upload file" : "Pošlji datoteko",
"Not favorited" : "Ni priljubljeno",
"An error occurred while trying to update the tags" : "Prišlo je do napake med posodabljanjem oznak",
+ "You don't have permission to upload or create files here." : "Nimate pravic za nalaganje ali ustvarjanje datotek na tem mestu.",
"Storage informations" : "Podrobnosti shrambe",
"Choose file" : "Izbor datotek",
"Go to the previous folder" : "Skoči na predhodno mapo",
diff --git a/apps/files/l10n/sr.js b/apps/files/l10n/sr.js
index 5be69357590..472eed0ffb4 100644
--- a/apps/files/l10n/sr.js
+++ b/apps/files/l10n/sr.js
@@ -43,8 +43,6 @@ OC.L10N.register(
"Files" : "Фајлови",
"A file or folder has been <strong>changed</strong>" : "Фајл или фасцикла су <strong>измењени</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "Омиљени фајл или фасцикла су <strong>измењени</strong>",
- "%1$s (renamed)" : "%1$s (преименован)",
- "renamed file" : "преименован фајл",
"Failed to authorize" : "Није успело добијање дозволе",
"Invalid folder path" : "Неисправна путања фолдера",
"Folder not found" : "Није пронађен фолдер",
@@ -98,6 +96,7 @@ OC.L10N.register(
"Invalid filename." : "Неисправно име фајла.",
"Renamed \"{oldName}\" to \"{newName}\"" : "„{oldName}” је промењено на „{newName}”",
"Rename file" : "Промени назив фајла",
+ "Folder" : "Фасцикла",
"Pending" : "На чекању",
"Unknown date" : "Непознат датум",
"Clear filter" : "Очисти филтер",
diff --git a/apps/files/l10n/sr.json b/apps/files/l10n/sr.json
index 52c41a7612e..8d9da0774b6 100644
--- a/apps/files/l10n/sr.json
+++ b/apps/files/l10n/sr.json
@@ -41,8 +41,6 @@
"Files" : "Фајлови",
"A file or folder has been <strong>changed</strong>" : "Фајл или фасцикла су <strong>измењени</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "Омиљени фајл или фасцикла су <strong>измењени</strong>",
- "%1$s (renamed)" : "%1$s (преименован)",
- "renamed file" : "преименован фајл",
"Failed to authorize" : "Није успело добијање дозволе",
"Invalid folder path" : "Неисправна путања фолдера",
"Folder not found" : "Није пронађен фолдер",
@@ -96,6 +94,7 @@
"Invalid filename." : "Неисправно име фајла.",
"Renamed \"{oldName}\" to \"{newName}\"" : "„{oldName}” је промењено на „{newName}”",
"Rename file" : "Промени назив фајла",
+ "Folder" : "Фасцикла",
"Pending" : "На чекању",
"Unknown date" : "Непознат датум",
"Clear filter" : "Очисти филтер",
diff --git a/apps/files/l10n/sv.js b/apps/files/l10n/sv.js
index d7c920ed474..2847bc373c7 100644
--- a/apps/files/l10n/sv.js
+++ b/apps/files/l10n/sv.js
@@ -43,8 +43,6 @@ OC.L10N.register(
"Files" : "Filer",
"A file or folder has been <strong>changed</strong>" : "En ny fil eller mapp har blivit <strong>ändrad</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "En favorit-fil eller mapp har blivit <strong>ändrad</strong>",
- "%1$s (renamed)" : "%1$s (omdöpt)",
- "renamed file" : "omdöpt fil",
"Failed to authorize" : "Det gick inte att auktorisera",
"Invalid folder path" : "Ogiltig mappsökväg",
"Folder not found" : "Mappen hittades inte",
@@ -99,6 +97,7 @@ OC.L10N.register(
"Invalid filename." : "Ogiltigt filnamn.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Bytte namn på \"{oldName}\" till \"{newName}\"",
"Rename file" : "Byt namn på fil",
+ "Folder" : "Mapp",
"Pending" : "Väntar",
"Unknown date" : "Okänt datum",
"Clear filter" : "Rensa filter",
diff --git a/apps/files/l10n/sv.json b/apps/files/l10n/sv.json
index 79cf7d6f062..affd94daa75 100644
--- a/apps/files/l10n/sv.json
+++ b/apps/files/l10n/sv.json
@@ -41,8 +41,6 @@
"Files" : "Filer",
"A file or folder has been <strong>changed</strong>" : "En ny fil eller mapp har blivit <strong>ändrad</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "En favorit-fil eller mapp har blivit <strong>ändrad</strong>",
- "%1$s (renamed)" : "%1$s (omdöpt)",
- "renamed file" : "omdöpt fil",
"Failed to authorize" : "Det gick inte att auktorisera",
"Invalid folder path" : "Ogiltig mappsökväg",
"Folder not found" : "Mappen hittades inte",
@@ -97,6 +95,7 @@
"Invalid filename." : "Ogiltigt filnamn.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Bytte namn på \"{oldName}\" till \"{newName}\"",
"Rename file" : "Byt namn på fil",
+ "Folder" : "Mapp",
"Pending" : "Väntar",
"Unknown date" : "Okänt datum",
"Clear filter" : "Rensa filter",
diff --git a/apps/files/l10n/th.js b/apps/files/l10n/th.js
index b71698fcb09..c6bef3b89d3 100644
--- a/apps/files/l10n/th.js
+++ b/apps/files/l10n/th.js
@@ -62,6 +62,7 @@ OC.L10N.register(
"Favorite" : "รายการโปรด",
"Filename" : "ชื่อไฟล์",
"Folder name" : "ชื่อโฟลเดอร์",
+ "Folder" : "โฟลเดอร์",
"Pending" : "อยู่ระหว่างดำเนินการ",
"Modified" : "แก้ไขเมื่อ",
"Type" : "ประเภท",
diff --git a/apps/files/l10n/th.json b/apps/files/l10n/th.json
index c2f1cac7d30..08b39c447ec 100644
--- a/apps/files/l10n/th.json
+++ b/apps/files/l10n/th.json
@@ -60,6 +60,7 @@
"Favorite" : "รายการโปรด",
"Filename" : "ชื่อไฟล์",
"Folder name" : "ชื่อโฟลเดอร์",
+ "Folder" : "โฟลเดอร์",
"Pending" : "อยู่ระหว่างดำเนินการ",
"Modified" : "แก้ไขเมื่อ",
"Type" : "ประเภท",
diff --git a/apps/files/l10n/tr.js b/apps/files/l10n/tr.js
index e699bf8bd42..caa474b97b0 100644
--- a/apps/files/l10n/tr.js
+++ b/apps/files/l10n/tr.js
@@ -95,6 +95,7 @@ OC.L10N.register(
"Invalid filename." : "Dosya adı geçersiz.",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" adı \"{newName}\" olarak değiştirildi",
"Rename file" : "Dosyayı yeniden adlandır",
+ "Folder" : "Klasör",
"Pending" : "Bekliyor",
"Unknown date" : "Tarih bilinmiyor",
"Clear filter" : "Süzgeci temizle",
diff --git a/apps/files/l10n/tr.json b/apps/files/l10n/tr.json
index b3ac67f9b5a..61e693c225d 100644
--- a/apps/files/l10n/tr.json
+++ b/apps/files/l10n/tr.json
@@ -93,6 +93,7 @@
"Invalid filename." : "Dosya adı geçersiz.",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" adı \"{newName}\" olarak değiştirildi",
"Rename file" : "Dosyayı yeniden adlandır",
+ "Folder" : "Klasör",
"Pending" : "Bekliyor",
"Unknown date" : "Tarih bilinmiyor",
"Clear filter" : "Süzgeci temizle",
diff --git a/apps/files/l10n/ug.js b/apps/files/l10n/ug.js
index 68779c47617..aea2933b5e4 100644
--- a/apps/files/l10n/ug.js
+++ b/apps/files/l10n/ug.js
@@ -86,6 +86,7 @@ OC.L10N.register(
"Invalid filename." : "ئىناۋەتسىز ھۆججەت ئىسمى.",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" غا \"{newName}\" غا ئۆزگەرتىلدى",
"Rename file" : "ھۆججەتنىڭ نامىنى ئۆزگەرتىش",
+ "Folder" : "قىسقۇچ",
"Pending" : "كۈتۈۋاتىدۇ",
"Clear filter" : "سۈزگۈچنى تازىلاش",
"Modified" : "ئۆزگەرتكەن",
diff --git a/apps/files/l10n/ug.json b/apps/files/l10n/ug.json
index 46b7379c84f..f524c4e77be 100644
--- a/apps/files/l10n/ug.json
+++ b/apps/files/l10n/ug.json
@@ -84,6 +84,7 @@
"Invalid filename." : "ئىناۋەتسىز ھۆججەت ئىسمى.",
"Renamed \"{oldName}\" to \"{newName}\"" : "\"{oldName}\" غا \"{newName}\" غا ئۆزگەرتىلدى",
"Rename file" : "ھۆججەتنىڭ نامىنى ئۆزگەرتىش",
+ "Folder" : "قىسقۇچ",
"Pending" : "كۈتۈۋاتىدۇ",
"Clear filter" : "سۈزگۈچنى تازىلاش",
"Modified" : "ئۆزگەرتكەن",
diff --git a/apps/files/l10n/uk.js b/apps/files/l10n/uk.js
index 4518b372a0f..bfb02d10ecc 100644
--- a/apps/files/l10n/uk.js
+++ b/apps/files/l10n/uk.js
@@ -95,6 +95,7 @@ OC.L10N.register(
"Invalid filename." : "Недійсне ім'я файлу.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Перейменовано \"{oldName}\" на \"{newName}\"",
"Rename file" : "Перейменувати файл",
+ "Folder" : "Каталог",
"Pending" : "Очікування",
"Unknown date" : "Невідома дата",
"Clear filter" : "Очистити фільтр",
diff --git a/apps/files/l10n/uk.json b/apps/files/l10n/uk.json
index c27feb57fd8..cdde9673fb9 100644
--- a/apps/files/l10n/uk.json
+++ b/apps/files/l10n/uk.json
@@ -93,6 +93,7 @@
"Invalid filename." : "Недійсне ім'я файлу.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Перейменовано \"{oldName}\" на \"{newName}\"",
"Rename file" : "Перейменувати файл",
+ "Folder" : "Каталог",
"Pending" : "Очікування",
"Unknown date" : "Невідома дата",
"Clear filter" : "Очистити фільтр",
diff --git a/apps/files/l10n/vi.js b/apps/files/l10n/vi.js
index 69ec719ef14..a8e39aa2527 100644
--- a/apps/files/l10n/vi.js
+++ b/apps/files/l10n/vi.js
@@ -87,6 +87,7 @@ OC.L10N.register(
"Invalid filename." : "Tên tập tin không hợp lệ.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Đã đổi tên \"{oldName}\" thành \"{newName}\"",
"Rename file" : "Đổi tên tệp tin",
+ "Folder" : "Thư mục",
"Pending" : "Đang chờ",
"Clear filter" : "Xóa bộ lọc",
"Modified" : "Đã thay đổi vào:",
diff --git a/apps/files/l10n/vi.json b/apps/files/l10n/vi.json
index f5b09c82247..272a1e3eebc 100644
--- a/apps/files/l10n/vi.json
+++ b/apps/files/l10n/vi.json
@@ -85,6 +85,7 @@
"Invalid filename." : "Tên tập tin không hợp lệ.",
"Renamed \"{oldName}\" to \"{newName}\"" : "Đã đổi tên \"{oldName}\" thành \"{newName}\"",
"Rename file" : "Đổi tên tệp tin",
+ "Folder" : "Thư mục",
"Pending" : "Đang chờ",
"Clear filter" : "Xóa bộ lọc",
"Modified" : "Đã thay đổi vào:",
diff --git a/apps/files/l10n/zh_CN.js b/apps/files/l10n/zh_CN.js
index 003a12b2320..24c6af3046f 100644
--- a/apps/files/l10n/zh_CN.js
+++ b/apps/files/l10n/zh_CN.js
@@ -43,8 +43,6 @@ OC.L10N.register(
"Files" : "文件",
"A file or folder has been <strong>changed</strong>" : "文件或文件夹已经被<strong>修改</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "一个收藏的文件或文件夹已经被<strong>修改</strong>",
- "%1$s (renamed)" : "%1$s(已重命名)",
- "renamed file" : "已重命名文件",
"Failed to authorize" : "授权失败",
"Invalid folder path" : "无效文件夹路径",
"Folder not found" : "未找到文件夹",
@@ -73,6 +71,7 @@ OC.L10N.register(
"Transferred from %1$s on %2$s" : "从 %1$s 转移至 %2$s",
"Files compatibility" : "文件兼容性",
"Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "允许限制文件名称以确保文件可以与所有客户端同步。默认状态下,所有POSIX(例如 Linux 或 macOS)系统有效的文件名都是被允许的。",
+ "After enabling the Windows compatible filenames, existing files cannot be modified anymore but can be renamed to valid new names by their owner." : "启用与 Windows 兼容的文件名后,无法再修改现有文件,但可以由其所有者重命名为有效的新名称。",
"It is also possible to migrate files automatically after enabling this setting, please refer to the documentation about the occ command." : "启用此设置后,也可以自动迁移文件,请参阅有关 occ 命令的文档。",
"Enforce Windows compatibility" : "强制 Windows 兼容性",
"This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "这将阻止在 Windows 系统中无效的文件名称,比如使用保留字符。但这不会强制大小写敏感性兼容。",
@@ -98,6 +97,7 @@ OC.L10N.register(
"Invalid filename." : "无效文件名称。",
"Renamed \"{oldName}\" to \"{newName}\"" : "已将“{oldName}”重命名为“{newName}”",
"Rename file" : "重命名文件",
+ "Folder" : "文件夹",
"Pending" : "等待",
"Unknown date" : "未知日期",
"Clear filter" : "清除筛选",
diff --git a/apps/files/l10n/zh_CN.json b/apps/files/l10n/zh_CN.json
index aab018cfab8..6fb7facb3b6 100644
--- a/apps/files/l10n/zh_CN.json
+++ b/apps/files/l10n/zh_CN.json
@@ -41,8 +41,6 @@
"Files" : "文件",
"A file or folder has been <strong>changed</strong>" : "文件或文件夹已经被<strong>修改</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "一个收藏的文件或文件夹已经被<strong>修改</strong>",
- "%1$s (renamed)" : "%1$s(已重命名)",
- "renamed file" : "已重命名文件",
"Failed to authorize" : "授权失败",
"Invalid folder path" : "无效文件夹路径",
"Folder not found" : "未找到文件夹",
@@ -71,6 +69,7 @@
"Transferred from %1$s on %2$s" : "从 %1$s 转移至 %2$s",
"Files compatibility" : "文件兼容性",
"Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "允许限制文件名称以确保文件可以与所有客户端同步。默认状态下,所有POSIX(例如 Linux 或 macOS)系统有效的文件名都是被允许的。",
+ "After enabling the Windows compatible filenames, existing files cannot be modified anymore but can be renamed to valid new names by their owner." : "启用与 Windows 兼容的文件名后,无法再修改现有文件,但可以由其所有者重命名为有效的新名称。",
"It is also possible to migrate files automatically after enabling this setting, please refer to the documentation about the occ command." : "启用此设置后,也可以自动迁移文件,请参阅有关 occ 命令的文档。",
"Enforce Windows compatibility" : "强制 Windows 兼容性",
"This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "这将阻止在 Windows 系统中无效的文件名称,比如使用保留字符。但这不会强制大小写敏感性兼容。",
@@ -96,6 +95,7 @@
"Invalid filename." : "无效文件名称。",
"Renamed \"{oldName}\" to \"{newName}\"" : "已将“{oldName}”重命名为“{newName}”",
"Rename file" : "重命名文件",
+ "Folder" : "文件夹",
"Pending" : "等待",
"Unknown date" : "未知日期",
"Clear filter" : "清除筛选",
diff --git a/apps/files/l10n/zh_HK.js b/apps/files/l10n/zh_HK.js
index 85ce0a40cc1..5b593dc8428 100644
--- a/apps/files/l10n/zh_HK.js
+++ b/apps/files/l10n/zh_HK.js
@@ -43,8 +43,6 @@ OC.L10N.register(
"Files" : "檔案",
"A file or folder has been <strong>changed</strong>" : "檔案或資料夾有所<strong>更改</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "收藏的檔案或資料夾有所<strong>更改</strong>",
- "%1$s (renamed)" : "%1$s(已重新命名)",
- "renamed file" : "已重新命名的檔案",
"Failed to authorize" : "無法授權",
"Invalid folder path" : "無效的資料夾路徑",
"Folder not found" : "找不到資料夾",
@@ -99,6 +97,7 @@ OC.L10N.register(
"Invalid filename." : "檔案名稱無效。",
"Renamed \"{oldName}\" to \"{newName}\"" : "已將「{oldName}」重新命名為「{newName}」",
"Rename file" : "重新命名檔案",
+ "Folder" : "資料夾",
"Pending" : "待定的",
"Unknown date" : "日期不詳",
"Clear filter" : "清空過濾器",
diff --git a/apps/files/l10n/zh_HK.json b/apps/files/l10n/zh_HK.json
index b65a2360b35..927fc7dc8ef 100644
--- a/apps/files/l10n/zh_HK.json
+++ b/apps/files/l10n/zh_HK.json
@@ -41,8 +41,6 @@
"Files" : "檔案",
"A file or folder has been <strong>changed</strong>" : "檔案或資料夾有所<strong>更改</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "收藏的檔案或資料夾有所<strong>更改</strong>",
- "%1$s (renamed)" : "%1$s(已重新命名)",
- "renamed file" : "已重新命名的檔案",
"Failed to authorize" : "無法授權",
"Invalid folder path" : "無效的資料夾路徑",
"Folder not found" : "找不到資料夾",
@@ -97,6 +95,7 @@
"Invalid filename." : "檔案名稱無效。",
"Renamed \"{oldName}\" to \"{newName}\"" : "已將「{oldName}」重新命名為「{newName}」",
"Rename file" : "重新命名檔案",
+ "Folder" : "資料夾",
"Pending" : "待定的",
"Unknown date" : "日期不詳",
"Clear filter" : "清空過濾器",
diff --git a/apps/files/l10n/zh_TW.js b/apps/files/l10n/zh_TW.js
index 40cdfe0c710..af800f5614f 100644
--- a/apps/files/l10n/zh_TW.js
+++ b/apps/files/l10n/zh_TW.js
@@ -43,8 +43,6 @@ OC.L10N.register(
"Files" : "檔案",
"A file or folder has been <strong>changed</strong>" : "檔案或資料夾已被<strong>變更</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "一個喜愛的檔案或資料夾已<strong>變更</strong>",
- "%1$s (renamed)" : "%1$s(已重新命名)",
- "renamed file" : "已重新命名檔案",
"Failed to authorize" : "授權失敗",
"Invalid folder path" : "無效的資料夾路徑",
"Folder not found" : "找不到資料夾",
@@ -99,6 +97,7 @@ OC.L10N.register(
"Invalid filename." : "無效的檔案名稱。",
"Renamed \"{oldName}\" to \"{newName}\"" : "已將「{oldName}」重新命名為「{newName}」",
"Rename file" : "重新命名檔案",
+ "Folder" : "資料夾",
"Pending" : "待處理",
"Unknown date" : "未知日期",
"Clear filter" : "清除過濾條件",
diff --git a/apps/files/l10n/zh_TW.json b/apps/files/l10n/zh_TW.json
index 543e4cc4e00..3c1c8d347fa 100644
--- a/apps/files/l10n/zh_TW.json
+++ b/apps/files/l10n/zh_TW.json
@@ -41,8 +41,6 @@
"Files" : "檔案",
"A file or folder has been <strong>changed</strong>" : "檔案或資料夾已被<strong>變更</strong>",
"A favorite file or folder has been <strong>changed</strong>" : "一個喜愛的檔案或資料夾已<strong>變更</strong>",
- "%1$s (renamed)" : "%1$s(已重新命名)",
- "renamed file" : "已重新命名檔案",
"Failed to authorize" : "授權失敗",
"Invalid folder path" : "無效的資料夾路徑",
"Folder not found" : "找不到資料夾",
@@ -97,6 +95,7 @@
"Invalid filename." : "無效的檔案名稱。",
"Renamed \"{oldName}\" to \"{newName}\"" : "已將「{oldName}」重新命名為「{newName}」",
"Rename file" : "重新命名檔案",
+ "Folder" : "資料夾",
"Pending" : "待處理",
"Unknown date" : "未知日期",
"Clear filter" : "清除過濾條件",
diff --git a/apps/files/lib/Command/Copy.php b/apps/files/lib/Command/Copy.php
index e51a1689907..ad0dfa90de1 100644
--- a/apps/files/lib/Command/Copy.php
+++ b/apps/files/lib/Command/Copy.php
@@ -19,10 +19,9 @@ use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;
class Copy extends Command {
- private FileUtils $fileUtils;
-
- public function __construct(FileUtils $fileUtils) {
- $this->fileUtils = $fileUtils;
+ public function __construct(
+ private FileUtils $fileUtils,
+ ) {
parent::__construct();
}
diff --git a/apps/files/lib/Command/Move.php b/apps/files/lib/Command/Move.php
index cd9e56f8e29..29dd8860b2a 100644
--- a/apps/files/lib/Command/Move.php
+++ b/apps/files/lib/Command/Move.php
@@ -20,10 +20,9 @@ use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;
class Move extends Command {
- private FileUtils $fileUtils;
-
- public function __construct(FileUtils $fileUtils) {
- $this->fileUtils = $fileUtils;
+ public function __construct(
+ private FileUtils $fileUtils,
+ ) {
parent::__construct();
}
diff --git a/apps/files/lib/Command/SanitizeFilenames.php b/apps/files/lib/Command/SanitizeFilenames.php
index ea01afd20d6..a404f0b3fd9 100644
--- a/apps/files/lib/Command/SanitizeFilenames.php
+++ b/apps/files/lib/Command/SanitizeFilenames.php
@@ -27,7 +27,7 @@ use Symfony\Component\Console\Output\OutputInterface;
class SanitizeFilenames extends Base {
private OutputInterface $output;
- private string $charReplacement;
+ private ?string $charReplacement;
private bool $dryRun;
public function __construct(
@@ -43,10 +43,6 @@ class SanitizeFilenames extends Base {
protected function configure(): void {
parent::configure();
- $forbiddenCharacter = $this->filenameValidator->getForbiddenCharacters();
- $charReplacement = array_diff([' ', '_', '-'], $forbiddenCharacter);
- $charReplacement = reset($charReplacement) ?: '';
-
$this
->setName('files:sanitize-filenames')
->setDescription('Renames files to match naming constraints')
@@ -65,16 +61,25 @@ class SanitizeFilenames extends Base {
'c',
mode: InputOption::VALUE_REQUIRED,
description: 'Replacement for invalid character (by default space, underscore or dash is used)',
- default: $charReplacement,
);
}
protected function execute(InputInterface $input, OutputInterface $output): int {
$this->charReplacement = $input->getOption('char-replacement');
- if ($this->charReplacement === '' || mb_strlen($this->charReplacement) > 1) {
- $output->writeln('<error>No character replacement given</error>');
- return 1;
+ // check if replacement is needed
+ $c = $this->filenameValidator->getForbiddenCharacters();
+ if (count($c) > 0) {
+ try {
+ $this->filenameValidator->sanitizeFilename($c[0], $this->charReplacement);
+ } catch (\InvalidArgumentException) {
+ if ($this->charReplacement === null) {
+ $output->writeln('<error>Character replacement required</error>');
+ } else {
+ $output->writeln('<error>Invalid character replacement given</error>');
+ }
+ return 1;
+ }
}
$this->dryRun = $input->getOption('dry-run');
@@ -115,8 +120,8 @@ class SanitizeFilenames extends Base {
try {
$oldName = $node->getName();
- if (!$this->filenameValidator->isFilenameValid($oldName)) {
- $newName = $this->sanitizeName($oldName);
+ $newName = $this->filenameValidator->sanitizeFilename($oldName, $this->charReplacement);
+ if ($oldName !== $newName) {
$newName = $folder->getNonExistingName($newName);
$path = rtrim(dirname($node->getPath()), '/');
@@ -142,27 +147,4 @@ class SanitizeFilenames extends Base {
}
}
- private function sanitizeName(string $name): string {
- $l10n = $this->l10nFactory->get('files');
-
- foreach ($this->filenameValidator->getForbiddenExtensions() as $extension) {
- if (str_ends_with($name, $extension)) {
- $name = substr($name, 0, strlen($name) - strlen($extension));
- }
- }
-
- $basename = substr($name, 0, strpos($name, '.', 1) ?: null);
- if (in_array($basename, $this->filenameValidator->getForbiddenBasenames())) {
- $name = str_replace($basename, $l10n->t('%1$s (renamed)', [$basename]), $name);
- }
-
- if ($name === '') {
- $name = $l10n->t('renamed file');
- }
-
- $forbiddenCharacter = $this->filenameValidator->getForbiddenCharacters();
- $name = str_replace($forbiddenCharacter, $this->charReplacement, $name);
-
- return $name;
- }
}
diff --git a/apps/files/lib/Command/TransferOwnership.php b/apps/files/lib/Command/TransferOwnership.php
index edc73e62c38..104a8fb4985 100644
--- a/apps/files/lib/Command/TransferOwnership.php
+++ b/apps/files/lib/Command/TransferOwnership.php
@@ -11,20 +11,26 @@ namespace OCA\Files\Command;
use OCA\Files\Exception\TransferOwnershipException;
use OCA\Files\Service\OwnershipTransferService;
+use OCA\Files_External\Config\ConfigAdapter;
+use OCP\Files\Mount\IMountManager;
+use OCP\Files\Mount\IMountPoint;
use OCP\IConfig;
use OCP\IUser;
use OCP\IUserManager;
use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Question\ConfirmationQuestion;
class TransferOwnership extends Command {
public function __construct(
private IUserManager $userManager,
private OwnershipTransferService $transferService,
private IConfig $config,
+ private IMountManager $mountManager,
) {
parent::__construct();
}
@@ -60,6 +66,16 @@ class TransferOwnership extends Command {
InputOption::VALUE_OPTIONAL,
'transfer incoming user file shares to destination user. Usage: --transfer-incoming-shares=1 (value required)',
'2'
+ )->addOption(
+ 'include-external-storage',
+ null,
+ InputOption::VALUE_NONE,
+ 'include files on external storages, this will _not_ setup an external storage for the target user, but instead moves all the files from the external storages into the target users home directory',
+ )->addOption(
+ 'force-include-external-storage',
+ null,
+ InputOption::VALUE_NONE,
+ 'don\'t ask for confirmation for transferring external storages',
);
}
@@ -87,6 +103,31 @@ class TransferOwnership extends Command {
return self::FAILURE;
}
+ $path = ltrim($input->getOption('path'), '/');
+ $includeExternalStorage = $input->getOption('include-external-storage');
+ if ($includeExternalStorage) {
+ $mounts = $this->mountManager->findIn('/' . rtrim($sourceUserObject->getUID() . '/files/' . $path, '/'));
+ /** @var IMountPoint[] $mounts */
+ $mounts = array_filter($mounts, fn ($mount) => $mount->getMountProvider() === ConfigAdapter::class);
+ if (count($mounts) > 0) {
+ $output->writeln(count($mounts) . ' external storages will be transferred:');
+ foreach ($mounts as $mount) {
+ $output->writeln(' - <info>' . $mount->getMountPoint() . '</info>');
+ }
+ $output->writeln('');
+ $output->writeln('<comment>Any other users with access to these external storages will lose access to the files.</comment>');
+ $output->writeln('');
+ if (!$input->getOption('force-include-external-storage')) {
+ /** @var QuestionHelper $helper */
+ $helper = $this->getHelper('question');
+ $question = new ConfirmationQuestion('Are you sure you want to transfer external storages? (y/N) ', false);
+ if (!$helper->ask($input, $output, $question)) {
+ return self::FAILURE;
+ }
+ }
+ }
+ }
+
try {
$includeIncomingArgument = $input->getOption('transfer-incoming-shares');
@@ -112,11 +153,12 @@ class TransferOwnership extends Command {
$this->transferService->transfer(
$sourceUserObject,
$destinationUserObject,
- ltrim($input->getOption('path'), '/'),
+ $path,
$output,
$input->getOption('move') === true,
false,
- $includeIncoming
+ $includeIncoming,
+ $includeExternalStorage,
);
} catch (TransferOwnershipException $e) {
$output->writeln('<error>' . $e->getMessage() . '</error>');
diff --git a/apps/files/lib/Service/OwnershipTransferService.php b/apps/files/lib/Service/OwnershipTransferService.php
index 7f6681a9b89..b3a36ee13e5 100644
--- a/apps/files/lib/Service/OwnershipTransferService.php
+++ b/apps/files/lib/Service/OwnershipTransferService.php
@@ -15,10 +15,11 @@ use OC\Files\View;
use OC\User\NoUserException;
use OCA\Encryption\Util;
use OCA\Files\Exception\TransferOwnershipException;
+use OCA\Files_External\Config\ConfigAdapter;
use OCP\Encryption\IManager as IEncryptionManager;
+use OCP\Files\Config\IHomeMountProvider;
use OCP\Files\Config\IUserMountCache;
use OCP\Files\FileInfo;
-use OCP\Files\IHomeStorage;
use OCP\Files\InvalidPathException;
use OCP\Files\IRootFolder;
use OCP\Files\Mount\IMountManager;
@@ -70,6 +71,7 @@ class OwnershipTransferService {
bool $move = false,
bool $firstLogin = false,
bool $transferIncomingShares = false,
+ bool $includeExternalStorage = false,
): void {
$output = $output ?? new NullOutput();
$sourceUid = $sourceUser->getUID();
@@ -149,7 +151,8 @@ class OwnershipTransferService {
$sourcePath,
$finalTarget,
$view,
- $output
+ $output,
+ $includeExternalStorage,
);
$sizeDifference = $sourceSize - $view->getFileInfo($finalTarget)->getSize();
@@ -215,11 +218,14 @@ class OwnershipTransferService {
*
* @throws TransferOwnershipException
*/
- protected function analyse(string $sourceUid,
+ protected function analyse(
+ string $sourceUid,
string $destinationUid,
string $sourcePath,
View $view,
- OutputInterface $output): void {
+ OutputInterface $output,
+ bool $includeExternalStorage = false,
+ ): void {
$output->writeln('Validating quota');
$sourceFileInfo = $view->getFileInfo($sourcePath, false);
if ($sourceFileInfo === false) {
@@ -247,17 +253,22 @@ class OwnershipTransferService {
$encryptedFiles[] = $sourceFileInfo;
} else {
$this->walkFiles($view, $sourcePath,
- function (FileInfo $fileInfo) use ($progress, $masterKeyEnabled, &$encryptedFiles) {
+ function (FileInfo $fileInfo) use ($progress, $masterKeyEnabled, &$encryptedFiles, $includeExternalStorage) {
if ($fileInfo->getType() === FileInfo::TYPE_FOLDER) {
+ $mount = $fileInfo->getMountPoint();
// only analyze into folders from main storage,
- if (!$fileInfo->getStorage()->instanceOfStorage(IHomeStorage::class)) {
+ if (
+ $mount->getMountProvider() instanceof IHomeMountProvider ||
+ ($includeExternalStorage && $mount->getMountProvider() instanceof ConfigAdapter)
+ ) {
+ if ($fileInfo->isEncrypted()) {
+ /* Encrypted folder means e2ee encrypted, we cannot transfer it */
+ $encryptedFiles[] = $fileInfo;
+ }
+ return true;
+ } else {
return false;
}
- if ($fileInfo->isEncrypted()) {
- /* Encrypted folder means e2ee encrypted, we cannot transfer it */
- $encryptedFiles[] = $fileInfo;
- }
- return true;
}
$progress->advance();
if ($fileInfo->isEncrypted() && !$masterKeyEnabled) {
@@ -399,11 +410,14 @@ class OwnershipTransferService {
/**
* @throws TransferOwnershipException
*/
- protected function transferFiles(string $sourceUid,
+ protected function transferFiles(
+ string $sourceUid,
string $sourcePath,
string $finalTarget,
View $view,
- OutputInterface $output): void {
+ OutputInterface $output,
+ bool $includeExternalStorage,
+ ): void {
$output->writeln("Transferring files to $finalTarget ...");
// This change will help user to transfer the folder specified using --path option.
@@ -412,15 +426,50 @@ class OwnershipTransferService {
$view->mkdir($finalTarget);
$finalTarget = $finalTarget . '/' . basename($sourcePath);
}
- if ($view->rename($sourcePath, $finalTarget, ['checkSubMounts' => false]) === false) {
- throw new TransferOwnershipException('Could not transfer files.', 1);
+ $sourceInfo = $view->getFileInfo($sourcePath);
+
+ /// handle the external storages mounted at the root, or the admin specifying an external storage with --path
+ if ($sourceInfo->getInternalPath() === '' && $includeExternalStorage) {
+ $this->moveMountContents($view, $sourcePath, $finalTarget);
+ } else {
+ if ($view->rename($sourcePath, $finalTarget, ['checkSubMounts' => false]) === false) {
+ throw new TransferOwnershipException('Could not transfer files.', 1);
+ }
+ }
+
+ if ($includeExternalStorage) {
+ $nestedMounts = $this->mountManager->findIn($sourcePath);
+ foreach ($nestedMounts as $mount) {
+ if ($mount->getMountProvider() === ConfigAdapter::class) {
+ $relativePath = substr(trim($mount->getMountPoint(), '/'), strlen($sourcePath));
+ $this->moveMountContents($view, $mount->getMountPoint(), $finalTarget . $relativePath);
+ }
+ }
}
+
if (!is_dir("$sourceUid/files")) {
// because the files folder is moved away we need to recreate it
$view->mkdir("$sourceUid/files");
}
}
+ private function moveMountContents(View $rootView, string $source, string $target) {
+ if ($rootView->copy($source, $target)) {
+ // just doing `rmdir` on the mountpoint would cause it to try and unmount the storage
+ // we need to empty the contents instead
+ $content = $rootView->getDirectoryContent($source);
+ foreach ($content as $item) {
+ if ($item->getType() === FileInfo::TYPE_FOLDER) {
+ $rootView->rmdir($item->getPath());
+ } else {
+ $rootView->unlink($item->getPath());
+ }
+ }
+ } else {
+ throw new TransferOwnershipException("Could not transfer $source to $target");
+ }
+ }
+
/**
* @param string $targetLocation New location of the transfered node
* @param array<array{share: IShare, suffix: string}> $shares previously collected share information
diff --git a/apps/files/lib/Service/UserConfig.php b/apps/files/lib/Service/UserConfig.php
index b01caf9f960..a2f2f1c1d14 100644
--- a/apps/files/lib/Service/UserConfig.php
+++ b/apps/files/lib/Service/UserConfig.php
@@ -54,6 +54,12 @@ class UserConfig {
'default' => true,
'allowed' => [true, false],
],
+ [
+ // Whether to show the mime column or not
+ 'key' => 'show_mime_column',
+ 'default' => false,
+ 'allowed' => [true, false],
+ ]
];
protected ?IUser $user = null;
diff --git a/apps/files/src/components/FileEntry.vue b/apps/files/src/components/FileEntry.vue
index 9642c4709d8..d66c3fa0ed7 100644
--- a/apps/files/src/components/FileEntry.vue
+++ b/apps/files/src/components/FileEntry.vue
@@ -49,6 +49,15 @@
:opened.sync="openedMenu"
:source="source" />
+ <!-- Mime -->
+ <td v-if="isMimeAvailable"
+ :title="mime"
+ class="files-list__row-mime"
+ data-cy-files-list-row-mime
+ @click="openDetailsIfAvailable">
+ <span>{{ mime }}</span>
+ </td>
+
<!-- Size -->
<td v-if="!compact && isSizeAvailable"
:style="sizeOpacity"
@@ -85,9 +94,10 @@
</template>
<script lang="ts">
-import { formatFileSize } from '@nextcloud/files'
+import { FileType, formatFileSize } from '@nextcloud/files'
import { useHotKey } from '@nextcloud/vue/composables/useHotKey'
import { defineComponent } from 'vue'
+import { t } from '@nextcloud/l10n'
import NcDateTime from '@nextcloud/vue/components/NcDateTime'
import { useNavigation } from '../composables/useNavigation.ts'
@@ -123,6 +133,10 @@ export default defineComponent({
],
props: {
+ isMimeAvailable: {
+ type: Boolean,
+ default: false,
+ },
isSizeAvailable: {
type: Boolean,
default: false,
@@ -186,6 +200,36 @@ export default defineComponent({
return this.currentView.columns || []
},
+ mime() {
+ if (this.source.type === FileType.Folder) {
+ return this.t('files', 'Folder')
+ }
+
+ if (!this.source.mime || this.source.mime === 'application/octet-stream') {
+ return t('files', 'Unknown file type')
+ }
+
+ if (window.OC?.MimeTypeList?.names?.[this.source.mime]) {
+ return window.OC.MimeTypeList.names[this.source.mime]
+ }
+
+ const baseType = this.source.mime.split('/')[0]
+ const ext = this.source?.extension?.toUpperCase().replace(/^\./, '') || ''
+ if (baseType === 'image') {
+ return t('files', '{ext} image', { ext })
+ }
+ if (baseType === 'video') {
+ return t('files', '{ext} video', { ext })
+ }
+ if (baseType === 'audio') {
+ return t('files', '{ext} audio', { ext })
+ }
+ if (baseType === 'text') {
+ return t('files', '{ext} text', { ext })
+ }
+
+ return this.source.mime
+ },
size() {
const size = this.source.size
if (size === undefined || isNaN(size) || size < 0) {
diff --git a/apps/files/src/components/FileEntry/FileEntryPreview.vue b/apps/files/src/components/FileEntry/FileEntryPreview.vue
index 2d5844f851f..506677b49af 100644
--- a/apps/files/src/components/FileEntry/FileEntryPreview.vue
+++ b/apps/files/src/components/FileEntry/FileEntryPreview.vue
@@ -21,6 +21,7 @@
class="files-list__row-icon-blurhash"
aria-hidden="true" />
<img v-if="backgroundFailed !== true"
+ :key="source.fileid"
ref="previewImg"
alt=""
class="files-list__row-icon-preview"
@@ -147,6 +148,17 @@ export default defineComponent({
return null
}
+ if (this.source.attributes['has-preview'] !== true
+ && this.source.mime !== undefined
+ && this.source.mime !== 'application/octet-stream'
+ ) {
+ const previewUrl = generateUrl('/core/mimeicon?mime={mime}', {
+ mime: this.source.mime,
+ })
+ const url = new URL(window.location.origin + previewUrl)
+ return url.href
+ }
+
try {
const previewUrl = this.source.attributes.previewUrl
|| (this.isPublic
diff --git a/apps/files/src/components/FilesListTableFooter.vue b/apps/files/src/components/FilesListTableFooter.vue
index 63d692c100d..9e8cdc159ee 100644
--- a/apps/files/src/components/FilesListTableFooter.vue
+++ b/apps/files/src/components/FilesListTableFooter.vue
@@ -21,6 +21,10 @@
<!-- Actions -->
<td class="files-list__row-actions" />
+ <!-- Mime -->
+ <td v-if="isMimeAvailable"
+ class="files-list__column files-list__row-mime" />
+
<!-- Size -->
<td v-if="isSizeAvailable"
class="files-list__column files-list__row-size">
@@ -60,6 +64,10 @@ export default defineComponent({
type: View,
required: true,
},
+ isMimeAvailable: {
+ type: Boolean,
+ default: false,
+ },
isMtimeAvailable: {
type: Boolean,
default: false,
diff --git a/apps/files/src/components/FilesListTableHeader.vue b/apps/files/src/components/FilesListTableHeader.vue
index 341d5e1347d..23e631199eb 100644
--- a/apps/files/src/components/FilesListTableHeader.vue
+++ b/apps/files/src/components/FilesListTableHeader.vue
@@ -24,6 +24,14 @@
<!-- Actions -->
<th class="files-list__row-actions" />
+ <!-- Mime -->
+ <th v-if="isMimeAvailable"
+ class="files-list__column files-list__row-mime"
+ :class="{ 'files-list__column--sortable': isMimeAvailable }"
+ :aria-sort="ariaSortForMode('mime')">
+ <FilesListTableHeaderButton :name="t('files', 'File type')" mode="mime" />
+ </th>
+
<!-- Size -->
<th v-if="isSizeAvailable"
class="files-list__column files-list__row-size"
@@ -83,6 +91,10 @@ export default defineComponent({
],
props: {
+ isMimeAvailable: {
+ type: Boolean,
+ default: false,
+ },
isMtimeAvailable: {
type: Boolean,
default: false,
diff --git a/apps/files/src/components/FilesListVirtual.vue b/apps/files/src/components/FilesListVirtual.vue
index 93f567f25a4..8fdc87b154c 100644
--- a/apps/files/src/components/FilesListVirtual.vue
+++ b/apps/files/src/components/FilesListVirtual.vue
@@ -9,6 +9,7 @@
:data-sources="nodes"
:grid-mode="userConfig.grid_view"
:extra-props="{
+ isMimeAvailable,
isMtimeAvailable,
isSizeAvailable,
nodes,
@@ -39,6 +40,7 @@
<!-- Table header and sort buttons -->
<FilesListTableHeader ref="thead"
:files-list-width="fileListWidth"
+ :is-mime-available="isMimeAvailable"
:is-mtime-available="isMtimeAvailable"
:is-size-available="isSizeAvailable"
:nodes="nodes" />
@@ -48,6 +50,7 @@
<template #footer>
<FilesListTableFooter :current-view="currentView"
:files-list-width="fileListWidth"
+ :is-mime-available="isMimeAvailable"
:is-mtime-available="isMtimeAvailable"
:is-size-available="isSizeAvailable"
:nodes="nodes"
@@ -155,6 +158,16 @@ export default defineComponent({
return this.userConfigStore.userConfig
},
+ isMimeAvailable() {
+ if (!this.userConfig.show_mime_column) {
+ return false
+ }
+ // Hide mime column on narrow screens
+ if (this.fileListWidth < 1024) {
+ return false
+ }
+ return this.nodes.some(node => node.mime !== undefined || node.mime !== 'application/octet-stream')
+ },
isMtimeAvailable() {
// Hide mtime column on narrow screens
if (this.fileListWidth < 768) {
@@ -829,10 +842,12 @@ export default defineComponent({
margin-inline-end: 7px;
}
+ .files-list__row-mime,
.files-list__row-mtime,
.files-list__row-size {
color: var(--color-text-maxcontrast);
}
+
.files-list__row-size {
width: calc(var(--row-height) * 1.5);
// Right align content/text
@@ -843,6 +858,10 @@ export default defineComponent({
width: calc(var(--row-height) * 2);
}
+ .files-list__row-mime {
+ width: calc(var(--row-height) * 2.5);
+ }
+
.files-list__row-column-custom {
width: calc(var(--row-height) * 2);
}
diff --git a/apps/files/src/store/renaming.ts b/apps/files/src/store/renaming.ts
index 2ac9e06ba16..fc61be3bd3b 100644
--- a/apps/files/src/store/renaming.ts
+++ b/apps/files/src/store/renaming.ts
@@ -14,6 +14,7 @@ import { defineStore } from 'pinia'
import logger from '../logger'
import Vue, { defineAsyncComponent, ref } from 'vue'
import { useUserConfigStore } from './userconfig'
+import { fetchNode } from '../services/WebdavClient'
export const useRenamingStore = defineStore('renaming', () => {
/**
@@ -48,7 +49,7 @@ export const useRenamingStore = defineStore('renaming', () => {
}
isRenaming.value = true
- const node = renamingNode.value
+ let node = renamingNode.value
Vue.set(node, 'status', NodeStatus.LOADING)
const userConfig = useUserConfigStore()
@@ -86,6 +87,13 @@ export const useRenamingStore = defineStore('renaming', () => {
},
})
+ // Update mime type if extension changed
+ // as other related informations might have changed
+ // on the backend but it is really hard to know on the front
+ if (oldExtension !== newExtension) {
+ node = await fetchNode(node.path)
+ }
+
// Success 🎉
emit('files:node:updated', node)
emit('files:node:renamed', node)
diff --git a/apps/files/src/store/userconfig.ts b/apps/files/src/store/userconfig.ts
index d84a5e0d935..d136561c2e5 100644
--- a/apps/files/src/store/userconfig.ts
+++ b/apps/files/src/store/userconfig.ts
@@ -17,6 +17,7 @@ const initialUserConfig = loadState<UserConfig>('files', 'config', {
sort_favorites_first: true,
sort_folders_first: true,
grid_view: false,
+ show_mime_column: true,
show_dialog_file_extension: true,
})
diff --git a/apps/files/src/types.ts b/apps/files/src/types.ts
index 4bf8a557f49..db3de13d4eb 100644
--- a/apps/files/src/types.ts
+++ b/apps/files/src/types.ts
@@ -58,6 +58,7 @@ export interface UserConfig {
sort_favorites_first: boolean
sort_folders_first: boolean
grid_view: boolean
+ show_mime_column: boolean
}
export interface UserConfigStore {
userConfig: UserConfig
diff --git a/apps/files/src/views/Settings.vue b/apps/files/src/views/Settings.vue
index 872b8a8e6d3..a9967fdbef9 100644
--- a/apps/files/src/views/Settings.vue
+++ b/apps/files/src/views/Settings.vue
@@ -24,6 +24,11 @@
@update:checked="setConfig('show_hidden', $event)">
{{ t('files', 'Show hidden files') }}
</NcCheckboxRadioSwitch>
+ <NcCheckboxRadioSwitch data-cy-files-settings-setting="show_mime_column"
+ :checked="userConfig.show_mime_column"
+ @update:checked="setConfig('show_mime_column', $event)">
+ {{ t('files', 'Show file type column') }}
+ </NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch data-cy-files-settings-setting="crop_image_previews"
:checked="userConfig.crop_image_previews"
@update:checked="setConfig('crop_image_previews', $event)">
diff --git a/apps/files_external/l10n/de.js b/apps/files_external/l10n/de.js
index 719065c6e6a..1ae634dfb0e 100644
--- a/apps/files_external/l10n/de.js
+++ b/apps/files_external/l10n/de.js
@@ -33,7 +33,7 @@ OC.L10N.register(
"Client ID" : "Client-ID",
"Client secret" : "Geheime Zeichenkette des Clients",
"OpenStack v2" : "OpenStack v2",
- "Login" : "Anmelden",
+ "Login" : "Anmeldename",
"Password" : "Passwort",
"Tenant name" : "Name des Mieters",
"Identity endpoint URL" : "Identität Endpunkt-URL",
@@ -117,7 +117,7 @@ OC.L10N.register(
"External mount error" : "Fehler beim Einbinden des externen Speichers",
"List of external storage." : "Liste der externen Speicher.",
"There is no external storage configured. You can configure them in your Personal settings." : "Es ist kein externer Speicher eingerichtet. Du kannst diese in deinen persönlichen Einstellungen konfigurieren.",
- "There is no external storage configured and you don't have the permission to configure them." : "Es ist kein externer Speicher eingerichtet und du hast nicht die Berechtigung, einen solchen einzurichten.",
+ "There is no external storage configured and you don't have the permission to configure them." : "Es ist kein externer Speicher eingerichtet oder du hast keine Berechtigung, einen solchen einzurichten.",
"No external storage" : "Kein externer Speicher",
"Storage type" : "Speichertyp",
"Unknown" : "Unbekannt",
@@ -146,7 +146,7 @@ OC.L10N.register(
"Save" : "Speichern",
"Failed to save global credentials" : "Globale Anmeldeinformationen konnten nicht gespeichert werden",
"Failed to save global credentials: {message}" : "Globale Anmeldeinformationen konnten nicht gespeichert werden: {message}",
- "No external storage configured or you don't have the permission to configure them" : "Es ist kein externer Speicher eingerichtet oder du hast keine Berechtigung dies zu tun.",
+ "No external storage configured or you don't have the permission to configure them" : "Es ist kein externer Speicher eingerichtet oder du hast keine Berechtigung, diesen einzurichten.",
"Open documentation" : "Dokumentation öffnen",
"External storage enables you to mount external storage services and devices as secondary Nextcloud storage devices. You may also allow people to mount their own external storage services." : "Externer Speicher erlaubt es, externe Speicherdienste und Geräte als Zweitspeicher-Geräte in Nextcloud einzubinden. Es kann Personen erlaubt werden eigene externe Speicherdienste einzubinden.",
"Folder name" : "Ordnername",
@@ -157,6 +157,6 @@ OC.L10N.register(
"All people" : "Alle Personen",
"Advanced settings" : "Erweiterte Einstellungen",
"Allow people to mount external storage" : "Personen erlauben, externen Speicher einzubinden",
- "Global credentials can be used to authenticate with multiple external storages that have the same credentials." : "Globale Anmeldeinformationen können zur Anmeldung bei mehreren externen Speichern mit denselben Anmeldeinformationen verwendet werden."
+ "Global credentials can be used to authenticate with multiple external storages that have the same credentials." : "Globale Anmeldeinformationen können zur Authentifizierung bei mehreren externen Speichern verwendet werden, die dieselben Anmeldeinformationen haben."
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_external/l10n/de.json b/apps/files_external/l10n/de.json
index d6448798ae4..86d08fb5c73 100644
--- a/apps/files_external/l10n/de.json
+++ b/apps/files_external/l10n/de.json
@@ -31,7 +31,7 @@
"Client ID" : "Client-ID",
"Client secret" : "Geheime Zeichenkette des Clients",
"OpenStack v2" : "OpenStack v2",
- "Login" : "Anmelden",
+ "Login" : "Anmeldename",
"Password" : "Passwort",
"Tenant name" : "Name des Mieters",
"Identity endpoint URL" : "Identität Endpunkt-URL",
@@ -115,7 +115,7 @@
"External mount error" : "Fehler beim Einbinden des externen Speichers",
"List of external storage." : "Liste der externen Speicher.",
"There is no external storage configured. You can configure them in your Personal settings." : "Es ist kein externer Speicher eingerichtet. Du kannst diese in deinen persönlichen Einstellungen konfigurieren.",
- "There is no external storage configured and you don't have the permission to configure them." : "Es ist kein externer Speicher eingerichtet und du hast nicht die Berechtigung, einen solchen einzurichten.",
+ "There is no external storage configured and you don't have the permission to configure them." : "Es ist kein externer Speicher eingerichtet oder du hast keine Berechtigung, einen solchen einzurichten.",
"No external storage" : "Kein externer Speicher",
"Storage type" : "Speichertyp",
"Unknown" : "Unbekannt",
@@ -144,7 +144,7 @@
"Save" : "Speichern",
"Failed to save global credentials" : "Globale Anmeldeinformationen konnten nicht gespeichert werden",
"Failed to save global credentials: {message}" : "Globale Anmeldeinformationen konnten nicht gespeichert werden: {message}",
- "No external storage configured or you don't have the permission to configure them" : "Es ist kein externer Speicher eingerichtet oder du hast keine Berechtigung dies zu tun.",
+ "No external storage configured or you don't have the permission to configure them" : "Es ist kein externer Speicher eingerichtet oder du hast keine Berechtigung, diesen einzurichten.",
"Open documentation" : "Dokumentation öffnen",
"External storage enables you to mount external storage services and devices as secondary Nextcloud storage devices. You may also allow people to mount their own external storage services." : "Externer Speicher erlaubt es, externe Speicherdienste und Geräte als Zweitspeicher-Geräte in Nextcloud einzubinden. Es kann Personen erlaubt werden eigene externe Speicherdienste einzubinden.",
"Folder name" : "Ordnername",
@@ -155,6 +155,6 @@
"All people" : "Alle Personen",
"Advanced settings" : "Erweiterte Einstellungen",
"Allow people to mount external storage" : "Personen erlauben, externen Speicher einzubinden",
- "Global credentials can be used to authenticate with multiple external storages that have the same credentials." : "Globale Anmeldeinformationen können zur Anmeldung bei mehreren externen Speichern mit denselben Anmeldeinformationen verwendet werden."
+ "Global credentials can be used to authenticate with multiple external storages that have the same credentials." : "Globale Anmeldeinformationen können zur Authentifizierung bei mehreren externen Speichern verwendet werden, die dieselben Anmeldeinformationen haben."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_external/l10n/de_DE.js b/apps/files_external/l10n/de_DE.js
index d0541618efe..dfe6f0bc387 100644
--- a/apps/files_external/l10n/de_DE.js
+++ b/apps/files_external/l10n/de_DE.js
@@ -33,7 +33,7 @@ OC.L10N.register(
"Client ID" : "Client-ID",
"Client secret" : "Geheime Zeichenkette des Clients",
"OpenStack v2" : "OpenStack v2",
- "Login" : "Anmelden",
+ "Login" : "Anmeldename",
"Password" : "Passwort",
"Tenant name" : "Name des Mieters",
"Identity endpoint URL" : "Identität Endpunkt-URL",
@@ -117,7 +117,7 @@ OC.L10N.register(
"External mount error" : "Fehler beim Einbinden des externen Speichers",
"List of external storage." : "Liste der externen Speicher.",
"There is no external storage configured. You can configure them in your Personal settings." : "Es ist kein externer Speicher eingerichtet. Sie können diese in Ihren persönlichen Einstellungen konfigurieren.",
- "There is no external storage configured and you don't have the permission to configure them." : "Es ist kein externer Speicher eingerichtet und Sie haben nicht die Berechtigung, einen solchen einzurichten.",
+ "There is no external storage configured and you don't have the permission to configure them." : "Es ist kein externer Speicher eingerichtet und Sie haben keine Berechtigung, einen solchen einzurichten.",
"No external storage" : "Kein externer Speicher",
"Storage type" : "Speichertyp",
"Unknown" : "Unbekannt",
@@ -146,7 +146,7 @@ OC.L10N.register(
"Save" : "Speichern",
"Failed to save global credentials" : "Globale Anmeldeinformationen konnten nicht gespeichert werden",
"Failed to save global credentials: {message}" : "Globale Anmeldeinformationen konnten nicht gespeichert werden: {message}",
- "No external storage configured or you don't have the permission to configure them" : "Es ist kein externer Speicher eingerichtet oder Sie haben keine Berechtigung diesen einzurichten",
+ "No external storage configured or you don't have the permission to configure them" : "Es ist kein externer Speicher eingerichtet oder Sie haben keine Berechtigung, diesen einzurichten.",
"Open documentation" : "Dokumentation öffnen",
"External storage enables you to mount external storage services and devices as secondary Nextcloud storage devices. You may also allow people to mount their own external storage services." : "Externer Speicher erlaubt es, externe Speicherdienste und Geräte als Zweitspeicher-Geräte in Nextcloud einzubinden. Es kann Personen erlaubt werden eigene externe Speicherdienste einzubinden.",
"Folder name" : "Ordnername",
@@ -157,6 +157,6 @@ OC.L10N.register(
"All people" : "Alle Personen",
"Advanced settings" : "Erweiterte Einstellungen",
"Allow people to mount external storage" : "Personen erlauben, externen Speicher einzubinden",
- "Global credentials can be used to authenticate with multiple external storages that have the same credentials." : "Globale Zugangsdaten können für die Authentifizierung für mehrere externe Speicher verwendet werden, solange sie identische Zugangsdaten benötigen."
+ "Global credentials can be used to authenticate with multiple external storages that have the same credentials." : "Globale Anmeldeinformationen können zur Authentifizierung bei mehreren externen Speichern verwendet werden, die dieselben Anmeldeinformationen haben."
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_external/l10n/de_DE.json b/apps/files_external/l10n/de_DE.json
index e5fc8adb012..e51c610c829 100644
--- a/apps/files_external/l10n/de_DE.json
+++ b/apps/files_external/l10n/de_DE.json
@@ -31,7 +31,7 @@
"Client ID" : "Client-ID",
"Client secret" : "Geheime Zeichenkette des Clients",
"OpenStack v2" : "OpenStack v2",
- "Login" : "Anmelden",
+ "Login" : "Anmeldename",
"Password" : "Passwort",
"Tenant name" : "Name des Mieters",
"Identity endpoint URL" : "Identität Endpunkt-URL",
@@ -115,7 +115,7 @@
"External mount error" : "Fehler beim Einbinden des externen Speichers",
"List of external storage." : "Liste der externen Speicher.",
"There is no external storage configured. You can configure them in your Personal settings." : "Es ist kein externer Speicher eingerichtet. Sie können diese in Ihren persönlichen Einstellungen konfigurieren.",
- "There is no external storage configured and you don't have the permission to configure them." : "Es ist kein externer Speicher eingerichtet und Sie haben nicht die Berechtigung, einen solchen einzurichten.",
+ "There is no external storage configured and you don't have the permission to configure them." : "Es ist kein externer Speicher eingerichtet und Sie haben keine Berechtigung, einen solchen einzurichten.",
"No external storage" : "Kein externer Speicher",
"Storage type" : "Speichertyp",
"Unknown" : "Unbekannt",
@@ -144,7 +144,7 @@
"Save" : "Speichern",
"Failed to save global credentials" : "Globale Anmeldeinformationen konnten nicht gespeichert werden",
"Failed to save global credentials: {message}" : "Globale Anmeldeinformationen konnten nicht gespeichert werden: {message}",
- "No external storage configured or you don't have the permission to configure them" : "Es ist kein externer Speicher eingerichtet oder Sie haben keine Berechtigung diesen einzurichten",
+ "No external storage configured or you don't have the permission to configure them" : "Es ist kein externer Speicher eingerichtet oder Sie haben keine Berechtigung, diesen einzurichten.",
"Open documentation" : "Dokumentation öffnen",
"External storage enables you to mount external storage services and devices as secondary Nextcloud storage devices. You may also allow people to mount their own external storage services." : "Externer Speicher erlaubt es, externe Speicherdienste und Geräte als Zweitspeicher-Geräte in Nextcloud einzubinden. Es kann Personen erlaubt werden eigene externe Speicherdienste einzubinden.",
"Folder name" : "Ordnername",
@@ -155,6 +155,6 @@
"All people" : "Alle Personen",
"Advanced settings" : "Erweiterte Einstellungen",
"Allow people to mount external storage" : "Personen erlauben, externen Speicher einzubinden",
- "Global credentials can be used to authenticate with multiple external storages that have the same credentials." : "Globale Zugangsdaten können für die Authentifizierung für mehrere externe Speicher verwendet werden, solange sie identische Zugangsdaten benötigen."
+ "Global credentials can be used to authenticate with multiple external storages that have the same credentials." : "Globale Anmeldeinformationen können zur Authentifizierung bei mehreren externen Speichern verwendet werden, die dieselben Anmeldeinformationen haben."
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_external/tests/Storage/FtpTest.php b/apps/files_external/tests/Storage/FtpTest.php
index c6a1d8f77ba..81b92e0fae9 100644
--- a/apps/files_external/tests/Storage/FtpTest.php
+++ b/apps/files_external/tests/Storage/FtpTest.php
@@ -45,7 +45,7 @@ class FtpTest extends \Test\Files\Storage\Storage {
/**
* ftp has no proper way to handle spaces at the end of file names
*/
- public function directoryProvider() {
+ public static function directoryProvider(): array {
return array_filter(parent::directoryProvider(), function ($item) {
return substr($item[0], -1) !== ' ';
});
diff --git a/apps/files_external/tests/Storage/SmbTest.php b/apps/files_external/tests/Storage/SmbTest.php
index d5a83905112..51737d05dc6 100644
--- a/apps/files_external/tests/Storage/SmbTest.php
+++ b/apps/files_external/tests/Storage/SmbTest.php
@@ -49,7 +49,7 @@ class SmbTest extends \Test\Files\Storage\Storage {
parent::tearDown();
}
- public function directoryProvider() {
+ public static function directoryProvider(): array {
// doesn't support leading/trailing spaces
return [['folder']];
}
diff --git a/apps/files_sharing/l10n/de.js b/apps/files_sharing/l10n/de.js
index f547ac5d350..f6aa0685ab2 100644
--- a/apps/files_sharing/l10n/de.js
+++ b/apps/files_sharing/l10n/de.js
@@ -54,7 +54,7 @@ OC.L10N.register(
"{actor} removed you from the share named {file}" : "{actor} hat dich aus der Freigabe von {file} entfernt",
"Share for file {file} with {user} expired" : "Freigabe für die Datei {file} mit {user} abgelaufen",
"Share for file {file} expired" : "Freigabe für die Datei {file} abgelaufen",
- "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Öffentlich oder per E-Mail geteilte Datei oder Ordner wurde <strong>heruntergeladen</strong>",
+ "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Öffentlich oder per E-Mail geteilte Datei oder geteilter Ordner wurde <strong>heruntergeladen</strong>",
"Files have been <strong>uploaded</strong> to a folder shared by mail or by public link" : "Dateien wurden in einen per E-Mail oder über einen öffentlichen Link freigegebenen Ordner <strong>hochgeladen</strong>",
"A file or folder was shared from <strong>another server</strong>" : "Eine Datei oder ein Ordner wurde von <strong>einem anderen Server</strong> geteilt",
"Sharing" : "Teilen",
@@ -356,10 +356,10 @@ OC.L10N.register(
"List of files that you shared with others." : "Liste der Dateien, die du mit anderen geteilt hast",
"Nothing shared yet" : "Noch nichts geteilt",
"Files and folders you shared will show up here" : "Von dir geteilte Dateien und Ordner werden hier angezeigt",
- "Shared by link" : "Geteilt über einen Link",
+ "Shared by link" : "Über einen Link geteilt",
"List of files that are shared by link." : "Liste der Dateien, die mittels Link geteilt wurden.",
"No shared links" : "Keine geteilten Links",
- "Files and folders you shared by link will show up here" : "Von dir per Link geteilte Dateien werden hier angezeigt",
+ "Files and folders you shared by link will show up here" : "Von dir mittels Link geteilte Dateien und Ordner werden hier angezeigt werden",
"File requests" : "Dateianfragen",
"List of file requests." : "Liste der Dateianfragen.",
"No file requests" : "Keine Dateianfragen",
diff --git a/apps/files_sharing/l10n/de.json b/apps/files_sharing/l10n/de.json
index ec1399b28fa..52b17773dbd 100644
--- a/apps/files_sharing/l10n/de.json
+++ b/apps/files_sharing/l10n/de.json
@@ -52,7 +52,7 @@
"{actor} removed you from the share named {file}" : "{actor} hat dich aus der Freigabe von {file} entfernt",
"Share for file {file} with {user} expired" : "Freigabe für die Datei {file} mit {user} abgelaufen",
"Share for file {file} expired" : "Freigabe für die Datei {file} abgelaufen",
- "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Öffentlich oder per E-Mail geteilte Datei oder Ordner wurde <strong>heruntergeladen</strong>",
+ "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Öffentlich oder per E-Mail geteilte Datei oder geteilter Ordner wurde <strong>heruntergeladen</strong>",
"Files have been <strong>uploaded</strong> to a folder shared by mail or by public link" : "Dateien wurden in einen per E-Mail oder über einen öffentlichen Link freigegebenen Ordner <strong>hochgeladen</strong>",
"A file or folder was shared from <strong>another server</strong>" : "Eine Datei oder ein Ordner wurde von <strong>einem anderen Server</strong> geteilt",
"Sharing" : "Teilen",
@@ -354,10 +354,10 @@
"List of files that you shared with others." : "Liste der Dateien, die du mit anderen geteilt hast",
"Nothing shared yet" : "Noch nichts geteilt",
"Files and folders you shared will show up here" : "Von dir geteilte Dateien und Ordner werden hier angezeigt",
- "Shared by link" : "Geteilt über einen Link",
+ "Shared by link" : "Über einen Link geteilt",
"List of files that are shared by link." : "Liste der Dateien, die mittels Link geteilt wurden.",
"No shared links" : "Keine geteilten Links",
- "Files and folders you shared by link will show up here" : "Von dir per Link geteilte Dateien werden hier angezeigt",
+ "Files and folders you shared by link will show up here" : "Von dir mittels Link geteilte Dateien und Ordner werden hier angezeigt werden",
"File requests" : "Dateianfragen",
"List of file requests." : "Liste der Dateianfragen.",
"No file requests" : "Keine Dateianfragen",
diff --git a/apps/files_sharing/l10n/de_DE.js b/apps/files_sharing/l10n/de_DE.js
index b8928cb36b9..1269c6a0cfb 100644
--- a/apps/files_sharing/l10n/de_DE.js
+++ b/apps/files_sharing/l10n/de_DE.js
@@ -54,7 +54,7 @@ OC.L10N.register(
"{actor} removed you from the share named {file}" : "{actor} hat Sie aus der Freigabe von {file} entfernt",
"Share for file {file} with {user} expired" : "Freigabe der Datei {file} für {user} abgelaufen",
"Share for file {file} expired" : "Freigabe für die Datei {file} abgelaufen",
- "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Öffentlich oder per E-Mail geteilte Datei / Ordner wurde <strong>heruntergeladen</strong>",
+ "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Öffentlich oder per E-Mail geteilte Datei oder geteilter Ordner wurde <strong>heruntergeladen</strong>",
"Files have been <strong>uploaded</strong> to a folder shared by mail or by public link" : "Dateien wurden in einen per E-Mail oder über einen öffentlichen Link freigegebenen Ordner <strong>hochgeladen</strong>",
"A file or folder was shared from <strong>another server</strong>" : "Eine Datei oder ein Ordner wurde von <strong>einem anderen Server</strong> geteilt",
"Sharing" : "Teilen",
@@ -356,7 +356,7 @@ OC.L10N.register(
"List of files that you shared with others." : "Liste der Dateien, die Sie mit anderen geteilt haben.",
"Nothing shared yet" : "Noch nichts geteilt",
"Files and folders you shared will show up here" : "Von Ihnen geteilte Dateien und Ordner werden hier angezeigt werden",
- "Shared by link" : "Geteilt über einen Link",
+ "Shared by link" : "Über einen Link geteilt",
"List of files that are shared by link." : "Liste der Dateien, die mittels Link geteilt wurden.",
"No shared links" : "Keine geteilten Links",
"Files and folders you shared by link will show up here" : "Von Ihnen mittels Link geteilte Dateien und Ordner werden hier angezeigt werden",
diff --git a/apps/files_sharing/l10n/de_DE.json b/apps/files_sharing/l10n/de_DE.json
index 1a2c0380c70..0a61a725d3e 100644
--- a/apps/files_sharing/l10n/de_DE.json
+++ b/apps/files_sharing/l10n/de_DE.json
@@ -52,7 +52,7 @@
"{actor} removed you from the share named {file}" : "{actor} hat Sie aus der Freigabe von {file} entfernt",
"Share for file {file} with {user} expired" : "Freigabe der Datei {file} für {user} abgelaufen",
"Share for file {file} expired" : "Freigabe für die Datei {file} abgelaufen",
- "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Öffentlich oder per E-Mail geteilte Datei / Ordner wurde <strong>heruntergeladen</strong>",
+ "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Öffentlich oder per E-Mail geteilte Datei oder geteilter Ordner wurde <strong>heruntergeladen</strong>",
"Files have been <strong>uploaded</strong> to a folder shared by mail or by public link" : "Dateien wurden in einen per E-Mail oder über einen öffentlichen Link freigegebenen Ordner <strong>hochgeladen</strong>",
"A file or folder was shared from <strong>another server</strong>" : "Eine Datei oder ein Ordner wurde von <strong>einem anderen Server</strong> geteilt",
"Sharing" : "Teilen",
@@ -354,7 +354,7 @@
"List of files that you shared with others." : "Liste der Dateien, die Sie mit anderen geteilt haben.",
"Nothing shared yet" : "Noch nichts geteilt",
"Files and folders you shared will show up here" : "Von Ihnen geteilte Dateien und Ordner werden hier angezeigt werden",
- "Shared by link" : "Geteilt über einen Link",
+ "Shared by link" : "Über einen Link geteilt",
"List of files that are shared by link." : "Liste der Dateien, die mittels Link geteilt wurden.",
"No shared links" : "Keine geteilten Links",
"Files and folders you shared by link will show up here" : "Von Ihnen mittels Link geteilte Dateien und Ordner werden hier angezeigt werden",
diff --git a/apps/files_sharing/l10n/ga.js b/apps/files_sharing/l10n/ga.js
index 0d41d4d1235..f8ddae9a8ea 100644
--- a/apps/files_sharing/l10n/ga.js
+++ b/apps/files_sharing/l10n/ga.js
@@ -313,7 +313,9 @@ OC.L10N.register(
"Use this method to share files with individuals or teams within your organization. If the recipient already has access to the share but cannot locate it, you can send them the internal share link for easy access." : "Bain úsáid as an modh seo chun comhaid a roinnt le daoine aonair nó le foirne laistigh de d'eagraíocht. Má tá rochtain ag an bhfaighteoir ar an sciar cheana féin ach nach féidir leis í a aimsiú, is féidir leat an nasc scaire inmheánach a sheoladh chucu le go mbeidh rochtain éasca air.",
"Use this method to share files with individuals or organizations outside your organization. Files and folders can be shared via public share links and email addresses. You can also share to other Nextcloud accounts hosted on different instances using their federated cloud ID." : "Bain úsáid as an modh seo chun comhaid a roinnt le daoine aonair nó le heagraíochtaí lasmuigh de d'eagraíocht. Is féidir comhaid agus fillteáin a roinnt trí naisc scaireanna poiblí agus seoltaí ríomhphoist. Is féidir leat a roinnt freisin le cuntais Nextcloud eile arna óstáil ar chásanna éagsúla ag baint úsáide as a n-ID néil cónasctha.",
"Shares that are not part of the internal or external shares. This can be shares from apps or other sources." : "Scaireanna nach cuid de na scaireanna inmheánacha nó seachtracha iad. Is féidir gur scaireanna iad seo ó aipeanna nó ó fhoinsí eile.",
+ "Share with accounts, teams, federated cloud IDs" : "Comhroinn le cuntais, foirne, agus aitheantóirí scamall cónaidhme",
"Share with accounts and teams" : "Roinn le cuntais agus foirne",
+ "Email, federated cloud ID" : "Ríomhphost, ID scamall cónaidhme",
"Unable to load the shares list" : "Ní féidir an liosta scaireanna a lódáil",
"Expires {relativetime}" : "In éag {relativetime}",
"this share just expired." : "tá an sciar seo díreach imithe in éag.",
@@ -422,6 +424,7 @@ OC.L10N.register(
"You are not allowed to edit link shares that you don't own" : "Níl cead agat scaireanna naisc nach leatsa a chur in eagar",
"_1 email address already added_::_{count} email addresses already added_" : ["1 seoladh ríomhphoist curtha leis cheana féin","{count} seoladh ríomhphoist curtha leis cheana","{count} seoladh ríomhphoist curtha leis cheana","{count} seoladh ríomhphoist curtha leis cheana","{count} seoladh ríomhphoist curtha leis cheana"],
"_1 email address added_::_{count} email addresses added_" : ["Cuireadh 1 seoladh ríomhphoist leis","{count} seoladh ríomhphoist curtha leis","{count} seoladh ríomhphoist curtha leis","{count} seoladh ríomhphoist curtha leis","{count} seoladh ríomhphoist curtha leis"],
+ "Share with accounts, teams, federated cloud id" : "Comhroinn le cuntais, foirne, aitheantas scamall cónaidhme",
"Email, federated cloud id" : "Ríomhphost, aitheantas scamall cónaidhme"
},
"nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4);");
diff --git a/apps/files_sharing/l10n/ga.json b/apps/files_sharing/l10n/ga.json
index 418aa49ccc3..f556e802f52 100644
--- a/apps/files_sharing/l10n/ga.json
+++ b/apps/files_sharing/l10n/ga.json
@@ -311,7 +311,9 @@
"Use this method to share files with individuals or teams within your organization. If the recipient already has access to the share but cannot locate it, you can send them the internal share link for easy access." : "Bain úsáid as an modh seo chun comhaid a roinnt le daoine aonair nó le foirne laistigh de d'eagraíocht. Má tá rochtain ag an bhfaighteoir ar an sciar cheana féin ach nach féidir leis í a aimsiú, is féidir leat an nasc scaire inmheánach a sheoladh chucu le go mbeidh rochtain éasca air.",
"Use this method to share files with individuals or organizations outside your organization. Files and folders can be shared via public share links and email addresses. You can also share to other Nextcloud accounts hosted on different instances using their federated cloud ID." : "Bain úsáid as an modh seo chun comhaid a roinnt le daoine aonair nó le heagraíochtaí lasmuigh de d'eagraíocht. Is féidir comhaid agus fillteáin a roinnt trí naisc scaireanna poiblí agus seoltaí ríomhphoist. Is féidir leat a roinnt freisin le cuntais Nextcloud eile arna óstáil ar chásanna éagsúla ag baint úsáide as a n-ID néil cónasctha.",
"Shares that are not part of the internal or external shares. This can be shares from apps or other sources." : "Scaireanna nach cuid de na scaireanna inmheánacha nó seachtracha iad. Is féidir gur scaireanna iad seo ó aipeanna nó ó fhoinsí eile.",
+ "Share with accounts, teams, federated cloud IDs" : "Comhroinn le cuntais, foirne, agus aitheantóirí scamall cónaidhme",
"Share with accounts and teams" : "Roinn le cuntais agus foirne",
+ "Email, federated cloud ID" : "Ríomhphost, ID scamall cónaidhme",
"Unable to load the shares list" : "Ní féidir an liosta scaireanna a lódáil",
"Expires {relativetime}" : "In éag {relativetime}",
"this share just expired." : "tá an sciar seo díreach imithe in éag.",
@@ -420,6 +422,7 @@
"You are not allowed to edit link shares that you don't own" : "Níl cead agat scaireanna naisc nach leatsa a chur in eagar",
"_1 email address already added_::_{count} email addresses already added_" : ["1 seoladh ríomhphoist curtha leis cheana féin","{count} seoladh ríomhphoist curtha leis cheana","{count} seoladh ríomhphoist curtha leis cheana","{count} seoladh ríomhphoist curtha leis cheana","{count} seoladh ríomhphoist curtha leis cheana"],
"_1 email address added_::_{count} email addresses added_" : ["Cuireadh 1 seoladh ríomhphoist leis","{count} seoladh ríomhphoist curtha leis","{count} seoladh ríomhphoist curtha leis","{count} seoladh ríomhphoist curtha leis","{count} seoladh ríomhphoist curtha leis"],
+ "Share with accounts, teams, federated cloud id" : "Comhroinn le cuntais, foirne, aitheantas scamall cónaidhme",
"Email, federated cloud id" : "Ríomhphost, aitheantas scamall cónaidhme"
},"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/files_sharing/lib/Cache.php b/apps/files_sharing/lib/Cache.php
index ccc93eb0952..024df5d3f43 100644
--- a/apps/files_sharing/lib/Cache.php
+++ b/apps/files_sharing/lib/Cache.php
@@ -68,7 +68,7 @@ class Cache extends CacheJail {
return $this->root;
}
- protected function getGetUnjailedRoot(): string {
+ public function getGetUnjailedRoot(): string {
return $this->sourceRootInfo->getPath();
}
diff --git a/apps/files_sharing/lib/Controller/PublicPreviewController.php b/apps/files_sharing/lib/Controller/PublicPreviewController.php
index 91dead57e80..16886e930fa 100644
--- a/apps/files_sharing/lib/Controller/PublicPreviewController.php
+++ b/apps/files_sharing/lib/Controller/PublicPreviewController.php
@@ -11,6 +11,7 @@ use OCP\AppFramework\Http\Attribute\OpenAPI;
use OCP\AppFramework\Http\Attribute\PublicPage;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\FileDisplayResponse;
+use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\PublicShareController;
use OCP\Constants;
use OCP\Files\Folder;
@@ -18,6 +19,7 @@ use OCP\Files\NotFoundException;
use OCP\IPreview;
use OCP\IRequest;
use OCP\ISession;
+use OCP\Preview\IMimeIconProvider;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager as ShareManager;
use OCP\Share\IShare;
@@ -33,6 +35,7 @@ class PublicPreviewController extends PublicShareController {
private ShareManager $shareManager,
ISession $session,
private IPreview $previewManager,
+ private IMimeIconProvider $mimeIconProvider,
) {
parent::__construct($appName, $request, $session);
}
@@ -63,9 +66,11 @@ class PublicPreviewController extends PublicShareController {
* @param int $x Width of the preview
* @param int $y Height of the preview
* @param bool $a Whether to not crop the preview
- * @return FileDisplayResponse<Http::STATUS_OK, array{Content-Type: string}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, list<empty>, array{}>
+ * @param bool $mimeFallback Whether to fallback to the mime icon if no preview is available
+ * @return FileDisplayResponse<Http::STATUS_OK, array{Content-Type: string}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, list<empty>, array{}>|RedirectResponse<Http::STATUS_SEE_OTHER, array{}>
*
* 200: Preview returned
+ * 303: Redirect to the mime icon url if mimeFallback is true
* 400: Getting preview is not possible
* 403: Getting preview is not allowed
* 404: Share or preview not found
@@ -79,6 +84,7 @@ class PublicPreviewController extends PublicShareController {
int $x = 32,
int $y = 32,
$a = false,
+ bool $mimeFallback = false,
) {
$cacheForSeconds = 60 * 60 * 24; // 1 day
@@ -124,6 +130,12 @@ class PublicPreviewController extends PublicShareController {
$response->cacheFor($cacheForSeconds);
return $response;
} catch (NotFoundException $e) {
+ // If we have no preview enabled, we can redirect to the mime icon if any
+ if ($mimeFallback) {
+ if ($url = $this->mimeIconProvider->getMimeIconUrl($file->getMimeType())) {
+ return new RedirectResponse($url);
+ }
+ }
return new DataResponse([], Http::STATUS_NOT_FOUND);
} catch (\InvalidArgumentException $e) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
diff --git a/apps/files_sharing/lib/External/Scanner.php b/apps/files_sharing/lib/External/Scanner.php
index e45d3723923..2b0741b4b96 100644
--- a/apps/files_sharing/lib/External/Scanner.php
+++ b/apps/files_sharing/lib/External/Scanner.php
@@ -6,6 +6,7 @@
*/
namespace OCA\Files_Sharing\External;
+use OC\Files\Cache\CacheEntry;
use OC\ForbiddenException;
use OCP\Files\NotFoundException;
use OCP\Files\StorageInvalidException;
@@ -29,7 +30,7 @@ class Scanner extends \OC\Files\Cache\Scanner {
* @param string $file file to scan
* @param int $reuseExisting
* @param int $parentId
- * @param \OC\Files\Cache\CacheEntry|array|null|false $cacheData existing data in the cache for the file to be scanned
+ * @param CacheEntry|array|null|false $cacheData existing data in the cache for the file to be scanned
* @param bool $lock set to false to disable getting an additional read lock during scanning
* @param array|null $data the metadata for the file, as returned by the storage
* @return array|null an array of metadata of the scanned file
diff --git a/apps/files_sharing/openapi.json b/apps/files_sharing/openapi.json
index e70764a59f2..68420dde80e 100644
--- a/apps/files_sharing/openapi.json
+++ b/apps/files_sharing/openapi.json
@@ -1477,6 +1477,19 @@
1
]
}
+ },
+ {
+ "name": "mimeFallback",
+ "in": "query",
+ "description": "Whether to fallback to the mime icon if no preview is available",
+ "schema": {
+ "type": "integer",
+ "default": 0,
+ "enum": [
+ 0,
+ 1
+ ]
+ }
}
],
"responses": {
@@ -1514,6 +1527,16 @@
"schema": {}
}
}
+ },
+ "303": {
+ "description": "Redirect to the mime icon url if mimeFallback is true",
+ "headers": {
+ "Location": {
+ "schema": {
+ "type": "string"
+ }
+ }
+ }
}
}
}
diff --git a/apps/files_sharing/src/views/SharingDetailsTab.vue b/apps/files_sharing/src/views/SharingDetailsTab.vue
index 5b778223c8b..8912ff340b7 100644
--- a/apps/files_sharing/src/views/SharingDetailsTab.vue
+++ b/apps/files_sharing/src/views/SharingDetailsTab.vue
@@ -905,8 +905,9 @@ export default {
this.advancedSectionAccordionExpanded = true
}
- if (this.share.note) {
+ if (this.isValidShareAttribute(this.share.note)) {
this.writeNoteToRecipientIsChecked = true
+ this.advancedSectionAccordionExpanded = true
}
},
diff --git a/apps/files_sharing/tests/Controller/PublicPreviewControllerTest.php b/apps/files_sharing/tests/Controller/PublicPreviewControllerTest.php
index bd64cfc60b4..9750274ff62 100644
--- a/apps/files_sharing/tests/Controller/PublicPreviewControllerTest.php
+++ b/apps/files_sharing/tests/Controller/PublicPreviewControllerTest.php
@@ -18,6 +18,7 @@ use OCP\Files\SimpleFS\ISimpleFile;
use OCP\IPreview;
use OCP\IRequest;
use OCP\ISession;
+use OCP\Preview\IMimeIconProvider;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IAttributes;
use OCP\Share\IManager;
@@ -52,7 +53,8 @@ class PublicPreviewControllerTest extends TestCase {
$this->request,
$this->shareManager,
$this->createMock(ISession::class),
- $this->previewManager
+ $this->previewManager,
+ $this->createMock(IMimeIconProvider::class),
);
}
diff --git a/apps/files_sharing/tests/EncryptedSizePropagationTest.php b/apps/files_sharing/tests/EncryptedSizePropagationTest.php
index 1430e5f17ac..a416cd14715 100644
--- a/apps/files_sharing/tests/EncryptedSizePropagationTest.php
+++ b/apps/files_sharing/tests/EncryptedSizePropagationTest.php
@@ -17,13 +17,22 @@ use Test\Traits\EncryptionTrait;
class EncryptedSizePropagationTest extends SizePropagationTest {
use EncryptionTrait;
+ protected function setUp(): void {
+ parent::setUp();
+ $this->config->setAppValue('encryption', 'useMasterKey', '0');
+ }
+
protected function setupUser($name, $password = '') {
$this->createUser($name, $password);
$tmpFolder = Server::get(ITempManager::class)->getTemporaryFolder();
$this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
- $this->config->setAppValue('encryption', 'useMasterKey', '0');
$this->setupForUser($name, $password);
$this->loginWithEncryption($name);
return new View('/' . $name . '/files');
}
+
+ protected function loginHelper($user, $create = false, $password = false) {
+ $this->setupForUser($user, $password);
+ parent::loginHelper($user, $create, $password);
+ }
}
diff --git a/apps/files_sharing/tests/TestCase.php b/apps/files_sharing/tests/TestCase.php
index 647a591db8d..34e2d71fb02 100644
--- a/apps/files_sharing/tests/TestCase.php
+++ b/apps/files_sharing/tests/TestCase.php
@@ -108,7 +108,7 @@ abstract class TestCase extends \Test\TestCase {
Server::get(DisplayNameCache::class)->clear();
//login as user1
- self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
+ $this->loginHelper(self::TEST_FILES_SHARING_API_USER1);
$this->data = 'foobar';
$this->view = new View('/' . self::TEST_FILES_SHARING_API_USER1 . '/files');
@@ -173,7 +173,7 @@ abstract class TestCase extends \Test\TestCase {
* @param bool $create
* @param bool $password
*/
- protected static function loginHelper($user, $create = false, $password = false) {
+ protected function loginHelper($user, $create = false, $password = false) {
if ($password === false) {
$password = $user;
}
diff --git a/apps/files_trashbin/l10n/de.js b/apps/files_trashbin/l10n/de.js
index e5fc521180e..30f503f52d9 100644
--- a/apps/files_trashbin/l10n/de.js
+++ b/apps/files_trashbin/l10n/de.js
@@ -3,22 +3,22 @@ OC.L10N.register(
{
"restored" : "Wiederhergestellt",
"Deleted files" : "Gelöschte Dateien",
- "Deleted files and folders in the trash bin (may expire during export if you are low on storage space)" : "Gelöschte Dateien und Ordner im Papierkorb (können während des Exports gelöscht werden, wenn der Speicherplatz knapp wird)",
- "This application enables people to restore files that were deleted from the system." : "Diese Anwendung ermöglicht es Benutzern, Dateien die vom System gelöscht wurden wieder herzustellen.",
- "This application enables people to restore files that were deleted from the system. It displays a list of deleted files in the web interface, and has options to restore those deleted files back to the people file directories or remove them permanently from the system. Restoring a file also restores related file versions, if the versions application is enabled. When a file is deleted from a share, it can be restored in the same manner, though it is no longer shared. By default, these files remain in the trash bin for 30 days.\nTo prevent an account from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation." : "Diese Anwendung ermöglicht es Personen, Dateien wiederherzustellen, die aus dem System gelöscht wurden. Es zeigt eine Liste der gelöschten Dateien in der Web-Oberfläche an und bietet die Möglichkeit, diese gelöschten Dateien in die Verzeichnisse der Personen wiederherzustellen oder sie dauerhaft aus dem System zu entfernen. Beim Wiederherstellen einer Datei werden auch die zugehörigen Dateiversionen wiederhergestellt, sofern die Versionsanwendung aktiviert ist. Wenn eine Datei aus einer Freigabe gelöscht wird, kann sie auf dem gleichen Weg wiederhergestellt werden, ist jedoch nicht mehr geteilt. Standardmäßig verbleiben gelöschte Dateien 30 Tage lang im Papierkorb.\nUm zu verhindern, dass einem Konto der Speicherplatz ausgeht, nutzt die Anwendung für gelöschte Dateien maximal 50% des aktuell verfügbaren freien Kontingents. Wenn die gelöschten Dateien dieses Limit überschreiten, löscht die Anwendung die ältesten Dateien, bis sie unter dieses Limit fällt. Weitere Informationen findest du in der Dokumentation zu gelöschten Dateien.",
+ "Deleted files and folders in the trash bin (may expire during export if you are low on storage space)" : "Gelöschte Dateien und Ordner im Papierkorb (können während des Exports ablaufen, wenn der Speicherplatz knapp wird)",
+ "This application enables people to restore files that were deleted from the system." : "Diese Anwendung ermöglicht es Personen, Dateien wiederherzustellen, die vom System gelöscht wurden.",
+ "This application enables people to restore files that were deleted from the system. It displays a list of deleted files in the web interface, and has options to restore those deleted files back to the people file directories or remove them permanently from the system. Restoring a file also restores related file versions, if the versions application is enabled. When a file is deleted from a share, it can be restored in the same manner, though it is no longer shared. By default, these files remain in the trash bin for 30 days.\nTo prevent an account from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation." : "Diese Anwendung ermöglicht es Personen, Dateien wiederherzustellen, die aus dem System gelöscht wurden. Es zeigt eine Liste der gelöschten Dateien in der Web-Oberfläche an und bietet die Möglichkeit, diese gelöschten Dateien in die Verzeichnisse der Personen wiederherzustellen oder sie dauerhaft aus dem System zu entfernen. Beim Wiederherstellen einer Datei werden auch die zugehörigen Dateiversionen wiederhergestellt, sofern die Versionsanwendung aktiviert ist. Wenn eine Datei aus einer Freigabe gelöscht wird, kann sie auf dem gleichen Weg wiederhergestellt werden, ist jedoch nicht mehr geteilt. Standardmäßig verbleiben gelöschte Dateien 30 Tage lang im Papierkorb.\nUm zu verhindern, dass einem Konto der Speicherplatz ausgeht, nutzt die Anwendung für gelöschte Dateien maximal 50 % des aktuell verfügbaren freien Kontingents. Wenn die gelöschten Dateien dieses Limit überschreiten, löscht die Anwendung die ältesten Dateien, bis sie unter dieses Limit fällt. Weitere Informationen findest du in der Dokumentation zu gelöschten Dateien.",
"Restore" : "Wiederherstellen",
"Empty deleted files" : "Gelöschte Dateien leeren",
"Confirm permanent deletion" : "Endgültiges Löschen bestätigen",
- "Are you sure you want to permanently delete all files and folders in the trash? This cannot be undone." : "Möchtest Du wirklich alle Dateien und Ordner im Papierkorb endgültig löschen? Dies kann nicht rückgängig gemacht werden.",
+ "Are you sure you want to permanently delete all files and folders in the trash? This cannot be undone." : "Möchtest du wirklich alle Dateien und Ordner im Papierkorb endgültig löschen? Dies kann nicht rückgängig gemacht werden.",
"Cancel" : "Abbrechen",
"Deletion cancelled" : "Löschen abgebrochen",
"Original location" : "Ursprünglicher Ort",
"Deleted by" : "Gelöscht von",
- "Deleted" : "gelöscht",
+ "Deleted" : "Gelöscht",
"A long time ago" : "Vor langer Zeit",
"Unknown" : "Unbekannt",
"All files" : "Alle Dateien",
- "You" : "Du",
+ "You" : "Dir",
"List of files that have been deleted." : "Liste der gelöschten Dateien.",
"No deleted files" : "Keine gelöschten Dateien",
"Files and folders you have deleted will show up here" : "Die von dir gelöschten Dateien und Ordner werden hier angezeigt"
diff --git a/apps/files_trashbin/l10n/de.json b/apps/files_trashbin/l10n/de.json
index bfa65bb5d0d..9017b23b0ca 100644
--- a/apps/files_trashbin/l10n/de.json
+++ b/apps/files_trashbin/l10n/de.json
@@ -1,22 +1,22 @@
{ "translations": {
"restored" : "Wiederhergestellt",
"Deleted files" : "Gelöschte Dateien",
- "Deleted files and folders in the trash bin (may expire during export if you are low on storage space)" : "Gelöschte Dateien und Ordner im Papierkorb (können während des Exports gelöscht werden, wenn der Speicherplatz knapp wird)",
- "This application enables people to restore files that were deleted from the system." : "Diese Anwendung ermöglicht es Benutzern, Dateien die vom System gelöscht wurden wieder herzustellen.",
- "This application enables people to restore files that were deleted from the system. It displays a list of deleted files in the web interface, and has options to restore those deleted files back to the people file directories or remove them permanently from the system. Restoring a file also restores related file versions, if the versions application is enabled. When a file is deleted from a share, it can be restored in the same manner, though it is no longer shared. By default, these files remain in the trash bin for 30 days.\nTo prevent an account from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation." : "Diese Anwendung ermöglicht es Personen, Dateien wiederherzustellen, die aus dem System gelöscht wurden. Es zeigt eine Liste der gelöschten Dateien in der Web-Oberfläche an und bietet die Möglichkeit, diese gelöschten Dateien in die Verzeichnisse der Personen wiederherzustellen oder sie dauerhaft aus dem System zu entfernen. Beim Wiederherstellen einer Datei werden auch die zugehörigen Dateiversionen wiederhergestellt, sofern die Versionsanwendung aktiviert ist. Wenn eine Datei aus einer Freigabe gelöscht wird, kann sie auf dem gleichen Weg wiederhergestellt werden, ist jedoch nicht mehr geteilt. Standardmäßig verbleiben gelöschte Dateien 30 Tage lang im Papierkorb.\nUm zu verhindern, dass einem Konto der Speicherplatz ausgeht, nutzt die Anwendung für gelöschte Dateien maximal 50% des aktuell verfügbaren freien Kontingents. Wenn die gelöschten Dateien dieses Limit überschreiten, löscht die Anwendung die ältesten Dateien, bis sie unter dieses Limit fällt. Weitere Informationen findest du in der Dokumentation zu gelöschten Dateien.",
+ "Deleted files and folders in the trash bin (may expire during export if you are low on storage space)" : "Gelöschte Dateien und Ordner im Papierkorb (können während des Exports ablaufen, wenn der Speicherplatz knapp wird)",
+ "This application enables people to restore files that were deleted from the system." : "Diese Anwendung ermöglicht es Personen, Dateien wiederherzustellen, die vom System gelöscht wurden.",
+ "This application enables people to restore files that were deleted from the system. It displays a list of deleted files in the web interface, and has options to restore those deleted files back to the people file directories or remove them permanently from the system. Restoring a file also restores related file versions, if the versions application is enabled. When a file is deleted from a share, it can be restored in the same manner, though it is no longer shared. By default, these files remain in the trash bin for 30 days.\nTo prevent an account from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation." : "Diese Anwendung ermöglicht es Personen, Dateien wiederherzustellen, die aus dem System gelöscht wurden. Es zeigt eine Liste der gelöschten Dateien in der Web-Oberfläche an und bietet die Möglichkeit, diese gelöschten Dateien in die Verzeichnisse der Personen wiederherzustellen oder sie dauerhaft aus dem System zu entfernen. Beim Wiederherstellen einer Datei werden auch die zugehörigen Dateiversionen wiederhergestellt, sofern die Versionsanwendung aktiviert ist. Wenn eine Datei aus einer Freigabe gelöscht wird, kann sie auf dem gleichen Weg wiederhergestellt werden, ist jedoch nicht mehr geteilt. Standardmäßig verbleiben gelöschte Dateien 30 Tage lang im Papierkorb.\nUm zu verhindern, dass einem Konto der Speicherplatz ausgeht, nutzt die Anwendung für gelöschte Dateien maximal 50 % des aktuell verfügbaren freien Kontingents. Wenn die gelöschten Dateien dieses Limit überschreiten, löscht die Anwendung die ältesten Dateien, bis sie unter dieses Limit fällt. Weitere Informationen findest du in der Dokumentation zu gelöschten Dateien.",
"Restore" : "Wiederherstellen",
"Empty deleted files" : "Gelöschte Dateien leeren",
"Confirm permanent deletion" : "Endgültiges Löschen bestätigen",
- "Are you sure you want to permanently delete all files and folders in the trash? This cannot be undone." : "Möchtest Du wirklich alle Dateien und Ordner im Papierkorb endgültig löschen? Dies kann nicht rückgängig gemacht werden.",
+ "Are you sure you want to permanently delete all files and folders in the trash? This cannot be undone." : "Möchtest du wirklich alle Dateien und Ordner im Papierkorb endgültig löschen? Dies kann nicht rückgängig gemacht werden.",
"Cancel" : "Abbrechen",
"Deletion cancelled" : "Löschen abgebrochen",
"Original location" : "Ursprünglicher Ort",
"Deleted by" : "Gelöscht von",
- "Deleted" : "gelöscht",
+ "Deleted" : "Gelöscht",
"A long time ago" : "Vor langer Zeit",
"Unknown" : "Unbekannt",
"All files" : "Alle Dateien",
- "You" : "Du",
+ "You" : "Dir",
"List of files that have been deleted." : "Liste der gelöschten Dateien.",
"No deleted files" : "Keine gelöschten Dateien",
"Files and folders you have deleted will show up here" : "Die von dir gelöschten Dateien und Ordner werden hier angezeigt"
diff --git a/apps/files_trashbin/l10n/de_DE.js b/apps/files_trashbin/l10n/de_DE.js
index f790c296f4a..291f3733b02 100644
--- a/apps/files_trashbin/l10n/de_DE.js
+++ b/apps/files_trashbin/l10n/de_DE.js
@@ -4,8 +4,8 @@ OC.L10N.register(
"restored" : "Wiederhergestellt",
"Deleted files" : "Gelöschte Dateien",
"Deleted files and folders in the trash bin (may expire during export if you are low on storage space)" : "Gelöschte Dateien und Ordner im Papierkorb (können während des Exports ablaufen, wenn der Speicherplatz knapp wird)",
- "This application enables people to restore files that were deleted from the system." : "Diese Anwendung ermöglicht Personen, Dateien wiederherzustellen, die vom System gelöscht wurden.",
- "This application enables people to restore files that were deleted from the system. It displays a list of deleted files in the web interface, and has options to restore those deleted files back to the people file directories or remove them permanently from the system. Restoring a file also restores related file versions, if the versions application is enabled. When a file is deleted from a share, it can be restored in the same manner, though it is no longer shared. By default, these files remain in the trash bin for 30 days.\nTo prevent an account from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation." : "Diese Anwendung ermöglicht es Personen, Dateien wiederherzustellen, die aus dem System gelöscht wurden. Es zeigt eine Liste der gelöschten Dateien in der Web-Oberfläche an und bietet die Möglichkeit, diese gelöschten Dateien in die Verzeichnisse der Personen wiederherzustellen oder sie dauerhaft aus dem System zu entfernen. Beim Wiederherstellen einer Datei werden auch die zugehörigen Dateiversionen wiederhergestellt, sofern die Versionsanwendung aktiviert ist. Wenn eine Datei aus einer Freigabe gelöscht wird, kann sie auf dem gleichen Weg wiederhergestellt werden, ist jedoch nicht mehr geteilt. Standardmäßig verbleiben gelöschte Dateien 30 Tage lang im Papierkorb.\nUm zu verhindern, dass einem Konto der Speicherplatz ausgeht, nutzt die Anwendung für gelöschte Dateien maximal 50% des aktuell verfügbaren freien Kontingents. Wenn die gelöschten Dateien dieses Limit überschreiten, löscht die Anwendung die ältesten Dateien, bis sie unter dieses Limit fällt. Weitere Informationen finden Sie in der Dokumentation zu gelöschten Dateien.",
+ "This application enables people to restore files that were deleted from the system." : "Diese Anwendung ermöglicht es Personen, Dateien wiederherzustellen, die vom System gelöscht wurden.",
+ "This application enables people to restore files that were deleted from the system. It displays a list of deleted files in the web interface, and has options to restore those deleted files back to the people file directories or remove them permanently from the system. Restoring a file also restores related file versions, if the versions application is enabled. When a file is deleted from a share, it can be restored in the same manner, though it is no longer shared. By default, these files remain in the trash bin for 30 days.\nTo prevent an account from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation." : "Diese Anwendung ermöglicht es Personen, Dateien wiederherzustellen, die aus dem System gelöscht wurden. Es zeigt eine Liste der gelöschten Dateien in der Web-Oberfläche an und bietet die Möglichkeit, diese gelöschten Dateien in die Verzeichnisse der Personen wiederherzustellen oder sie dauerhaft aus dem System zu entfernen. Beim Wiederherstellen einer Datei werden auch die zugehörigen Dateiversionen wiederhergestellt, sofern die Versionsanwendung aktiviert ist. Wenn eine Datei aus einer Freigabe gelöscht wird, kann sie auf dem gleichen Weg wiederhergestellt werden, ist jedoch nicht mehr geteilt. Standardmäßig verbleiben gelöschte Dateien 30 Tage lang im Papierkorb.\nUm zu verhindern, dass einem Konto der Speicherplatz ausgeht, nutzt die Anwendung für gelöschte Dateien maximal 50 % des aktuell verfügbaren freien Kontingents. Wenn die gelöschten Dateien dieses Limit überschreiten, löscht die Anwendung die ältesten Dateien, bis sie unter dieses Limit fällt. Weitere Informationen finden Sie in der Dokumentation zu gelöschten Dateien.",
"Restore" : "Wiederherstellen",
"Empty deleted files" : "Gelöschte Dateien leeren",
"Confirm permanent deletion" : "Endgültiges Löschen bestätigen",
@@ -18,7 +18,7 @@ OC.L10N.register(
"A long time ago" : "Vor langer Zeit",
"Unknown" : "Unbekannt",
"All files" : "Alle Dateien",
- "You" : "Sie",
+ "You" : "Ihnen",
"List of files that have been deleted." : "Liste der gelöschten Dateien.",
"No deleted files" : "Keine gelöschten Dateien",
"Files and folders you have deleted will show up here" : "Die von Ihnen gelöschten Dateien und Ordner werden hier angezeigt"
diff --git a/apps/files_trashbin/l10n/de_DE.json b/apps/files_trashbin/l10n/de_DE.json
index 74b1b262e57..645f7a146a0 100644
--- a/apps/files_trashbin/l10n/de_DE.json
+++ b/apps/files_trashbin/l10n/de_DE.json
@@ -2,8 +2,8 @@
"restored" : "Wiederhergestellt",
"Deleted files" : "Gelöschte Dateien",
"Deleted files and folders in the trash bin (may expire during export if you are low on storage space)" : "Gelöschte Dateien und Ordner im Papierkorb (können während des Exports ablaufen, wenn der Speicherplatz knapp wird)",
- "This application enables people to restore files that were deleted from the system." : "Diese Anwendung ermöglicht Personen, Dateien wiederherzustellen, die vom System gelöscht wurden.",
- "This application enables people to restore files that were deleted from the system. It displays a list of deleted files in the web interface, and has options to restore those deleted files back to the people file directories or remove them permanently from the system. Restoring a file also restores related file versions, if the versions application is enabled. When a file is deleted from a share, it can be restored in the same manner, though it is no longer shared. By default, these files remain in the trash bin for 30 days.\nTo prevent an account from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation." : "Diese Anwendung ermöglicht es Personen, Dateien wiederherzustellen, die aus dem System gelöscht wurden. Es zeigt eine Liste der gelöschten Dateien in der Web-Oberfläche an und bietet die Möglichkeit, diese gelöschten Dateien in die Verzeichnisse der Personen wiederherzustellen oder sie dauerhaft aus dem System zu entfernen. Beim Wiederherstellen einer Datei werden auch die zugehörigen Dateiversionen wiederhergestellt, sofern die Versionsanwendung aktiviert ist. Wenn eine Datei aus einer Freigabe gelöscht wird, kann sie auf dem gleichen Weg wiederhergestellt werden, ist jedoch nicht mehr geteilt. Standardmäßig verbleiben gelöschte Dateien 30 Tage lang im Papierkorb.\nUm zu verhindern, dass einem Konto der Speicherplatz ausgeht, nutzt die Anwendung für gelöschte Dateien maximal 50% des aktuell verfügbaren freien Kontingents. Wenn die gelöschten Dateien dieses Limit überschreiten, löscht die Anwendung die ältesten Dateien, bis sie unter dieses Limit fällt. Weitere Informationen finden Sie in der Dokumentation zu gelöschten Dateien.",
+ "This application enables people to restore files that were deleted from the system." : "Diese Anwendung ermöglicht es Personen, Dateien wiederherzustellen, die vom System gelöscht wurden.",
+ "This application enables people to restore files that were deleted from the system. It displays a list of deleted files in the web interface, and has options to restore those deleted files back to the people file directories or remove them permanently from the system. Restoring a file also restores related file versions, if the versions application is enabled. When a file is deleted from a share, it can be restored in the same manner, though it is no longer shared. By default, these files remain in the trash bin for 30 days.\nTo prevent an account from running out of disk space, the Deleted files app will not utilize more than 50% of the currently available free quota for deleted files. If the deleted files exceed this limit, the app deletes the oldest files until it gets below this limit. More information is available in the Deleted Files documentation." : "Diese Anwendung ermöglicht es Personen, Dateien wiederherzustellen, die aus dem System gelöscht wurden. Es zeigt eine Liste der gelöschten Dateien in der Web-Oberfläche an und bietet die Möglichkeit, diese gelöschten Dateien in die Verzeichnisse der Personen wiederherzustellen oder sie dauerhaft aus dem System zu entfernen. Beim Wiederherstellen einer Datei werden auch die zugehörigen Dateiversionen wiederhergestellt, sofern die Versionsanwendung aktiviert ist. Wenn eine Datei aus einer Freigabe gelöscht wird, kann sie auf dem gleichen Weg wiederhergestellt werden, ist jedoch nicht mehr geteilt. Standardmäßig verbleiben gelöschte Dateien 30 Tage lang im Papierkorb.\nUm zu verhindern, dass einem Konto der Speicherplatz ausgeht, nutzt die Anwendung für gelöschte Dateien maximal 50 % des aktuell verfügbaren freien Kontingents. Wenn die gelöschten Dateien dieses Limit überschreiten, löscht die Anwendung die ältesten Dateien, bis sie unter dieses Limit fällt. Weitere Informationen finden Sie in der Dokumentation zu gelöschten Dateien.",
"Restore" : "Wiederherstellen",
"Empty deleted files" : "Gelöschte Dateien leeren",
"Confirm permanent deletion" : "Endgültiges Löschen bestätigen",
@@ -16,7 +16,7 @@
"A long time ago" : "Vor langer Zeit",
"Unknown" : "Unbekannt",
"All files" : "Alle Dateien",
- "You" : "Sie",
+ "You" : "Ihnen",
"List of files that have been deleted." : "Liste der gelöschten Dateien.",
"No deleted files" : "Keine gelöschten Dateien",
"Files and folders you have deleted will show up here" : "Die von Ihnen gelöschten Dateien und Ordner werden hier angezeigt"
diff --git a/apps/files_trashbin/lib/Command/CleanUp.php b/apps/files_trashbin/lib/Command/CleanUp.php
index daaa4003f7a..e9b4fa8ae60 100644
--- a/apps/files_trashbin/lib/Command/CleanUp.php
+++ b/apps/files_trashbin/lib/Command/CleanUp.php
@@ -11,6 +11,7 @@ use OCP\Files\IRootFolder;
use OCP\IDBConnection;
use OCP\IUserBackend;
use OCP\IUserManager;
+use OCP\Util;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidOptionException;
use Symfony\Component\Console\Input\InputArgument;
@@ -96,7 +97,7 @@ class CleanUp extends Command {
$node = $this->rootFolder->get($path);
if ($verbose) {
- $output->writeln('Deleting <info>' . \OC_Helper::humanFileSize($node->getSize()) . "</info> in trash for <info>$uid</info>.");
+ $output->writeln('Deleting <info>' . Util::humanFileSize($node->getSize()) . "</info> in trash for <info>$uid</info>.");
}
$node->delete();
if ($this->rootFolder->nodeExists($path)) {
diff --git a/apps/files_trashbin/lib/Command/Size.php b/apps/files_trashbin/lib/Command/Size.php
index 11699ce25ea..9c19d4d92b3 100644
--- a/apps/files_trashbin/lib/Command/Size.php
+++ b/apps/files_trashbin/lib/Command/Size.php
@@ -13,6 +13,7 @@ use OCP\Command\IBus;
use OCP\IConfig;
use OCP\IUser;
use OCP\IUserManager;
+use OCP\Util;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -45,7 +46,7 @@ class Size extends Base {
$size = $input->getArgument('size');
if ($size) {
- $parsedSize = \OC_Helper::computerFileSize($size);
+ $parsedSize = Util::computerFileSize($size);
if ($parsedSize === false) {
$output->writeln('<error>Failed to parse input size</error>');
return -1;
@@ -70,7 +71,7 @@ class Size extends Base {
if ($globalSize < 0) {
$globalHumanSize = 'default (50% of available space)';
} else {
- $globalHumanSize = \OC_Helper::humanFileSize($globalSize);
+ $globalHumanSize = Util::humanFileSize($globalSize);
}
if ($user) {
@@ -79,7 +80,7 @@ class Size extends Base {
if ($userSize < 0) {
$userHumanSize = ($globalSize < 0) ? $globalHumanSize : "default($globalHumanSize)";
} else {
- $userHumanSize = \OC_Helper::humanFileSize($userSize);
+ $userHumanSize = Util::humanFileSize($userSize);
}
if ($input->getOption('output') == self::OUTPUT_FORMAT_PLAIN) {
@@ -106,7 +107,7 @@ class Size extends Base {
if (count($userValues)) {
$output->writeln('Per-user sizes:');
$this->writeArrayInOutputFormat($input, $output, array_map(function ($size) {
- return \OC_Helper::humanFileSize($size);
+ return Util::humanFileSize($size);
}, $userValues));
} else {
$output->writeln('No per-user sizes configured');
diff --git a/apps/files_trashbin/tests/TrashbinTest.php b/apps/files_trashbin/tests/TrashbinTest.php
index d16e90f74e9..3d2ceee0dcd 100644
--- a/apps/files_trashbin/tests/TrashbinTest.php
+++ b/apps/files_trashbin/tests/TrashbinTest.php
@@ -12,6 +12,7 @@ use OC\Files\Filesystem;
use OC\Files\Storage\Local;
use OC\Files\View;
use OC\SystemConfig;
+use OC\User\Database;
use OCA\Files_Sharing\AppInfo\Application;
use OCA\Files_Trashbin\AppInfo\Application as TrashbinApplication;
use OCA\Files_Trashbin\Expiration;
@@ -59,7 +60,7 @@ class TrashbinTest extends \Test\TestCase {
// reset backend
Server::get(IUserManager::class)->clearBackends();
- Server::get(IUserManager::class)->registerBackend(new \OC\User\Database());
+ Server::get(IUserManager::class)->registerBackend(new Database());
// clear share hooks
\OC_Hook::clear('OCP\\Share');
@@ -115,8 +116,11 @@ class TrashbinTest extends \Test\TestCase {
Server::get(IAppManager::class)->enableApp('files_trashbin');
$config = Server::get(IConfig::class);
- $mockConfig = $this->createMock(IConfig::class);
- $mockConfig
+ $mockConfig = $this->getMockBuilder(AllConfig::class)
+ ->onlyMethods(['getSystemValue'])
+ ->setConstructorArgs([Server::get(SystemConfig::class)])
+ ->getMock();
+ $mockConfig->expects($this->any())
->method('getSystemValue')
->willReturnCallback(static function ($key, $default) use ($config) {
if ($key === 'filesystem_check_changes') {
@@ -125,16 +129,6 @@ class TrashbinTest extends \Test\TestCase {
return $config->getSystemValue($key, $default);
}
});
- $mockConfig
- ->method('getUserValue')
- ->willReturnCallback(static function ($userId, $appName, $key, $default = '') use ($config) {
- return $config->getUserValue($userId, $appName, $key, $default);
- });
- $mockConfig
- ->method('getAppValue')
- ->willReturnCallback(static function ($appName, $key, $default = '') use ($config) {
- return $config->getAppValue($appName, $key, $default);
- });
$this->overwriteService(AllConfig::class, $mockConfig);
$this->trashRoot1 = '/' . self::TEST_TRASHBIN_USER1 . '/files_trashbin';
diff --git a/apps/files_versions/appinfo/routes.php b/apps/files_versions/appinfo/routes.php
index b7058b222f8..11b5e0c783f 100644
--- a/apps/files_versions/appinfo/routes.php
+++ b/apps/files_versions/appinfo/routes.php
@@ -6,16 +6,6 @@
*/
namespace OCA\Files_Versions\AppInfo;
-use OCP\Route\IRouter;
-
-/** @var IRouter $this */
-$this->create('files_versions_download', 'apps/files_versions/download.php')
- ->actionInclude('files_versions/download.php');
-$this->create('files_versions_ajax_getVersions', 'apps/files_versions/ajax/getVersions.php')
- ->actionInclude('files_versions/ajax/getVersions.php');
-$this->create('files_versions_ajax_rollbackVersion', 'apps/files_versions/ajax/rollbackVersion.php')
- ->actionInclude('files_versions/ajax/rollbackVersion.php');
-
return [
'routes' => [
[
diff --git a/apps/files_versions/lib/Listener/FileEventsListener.php b/apps/files_versions/lib/Listener/FileEventsListener.php
index d847c60ec64..4b7385d6e2d 100644
--- a/apps/files_versions/lib/Listener/FileEventsListener.php
+++ b/apps/files_versions/lib/Listener/FileEventsListener.php
@@ -36,6 +36,7 @@ use OCP\Files\Folder;
use OCP\Files\IMimeTypeLoader;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
+use OCP\Files\NotFoundException;
use OCP\IUserSession;
use Psr\Log\LoggerInterface;
@@ -250,7 +251,7 @@ class FileEventsListener implements IEventListener {
/**
* Erase versions of deleted file
*
- * This function is connected to the delete signal of OC_Filesystem
+ * This function is connected to the NodeDeletedEvent event
* cleanup the versions directory if the actual file gets deleted
*/
public function remove_hook(Node $node): void {
@@ -282,7 +283,7 @@ class FileEventsListener implements IEventListener {
/**
* rename/move versions of renamed/moved files
*
- * This function is connected to the rename signal of OC_Filesystem and adjust the name and location
+ * This function is connected to the NodeRenamedEvent event and adjust the name and location
* of the stored versions along the actual file
*/
public function rename_hook(Node $source, Node $target): void {
@@ -301,7 +302,7 @@ class FileEventsListener implements IEventListener {
/**
* copy versions of copied files
*
- * This function is connected to the copy signal of OC_Filesystem and copies the
+ * This function is connected to the NodeCopiedEvent event and copies the
* the stored versions to the new location
*/
public function copy_hook(Node $source, Node $target): void {
@@ -378,7 +379,7 @@ class FileEventsListener implements IEventListener {
try {
$owner = $node->getOwner()?->getUid();
- } catch (\OCP\Files\NotFoundException) {
+ } catch (NotFoundException) {
$owner = null;
}
diff --git a/apps/files_versions/lib/Versions/LegacyVersionsBackend.php b/apps/files_versions/lib/Versions/LegacyVersionsBackend.php
index 92b326b6cd3..59a10a0775d 100644
--- a/apps/files_versions/lib/Versions/LegacyVersionsBackend.php
+++ b/apps/files_versions/lib/Versions/LegacyVersionsBackend.php
@@ -367,16 +367,20 @@ class LegacyVersionsBackend implements IVersionBackend, IDeletableVersionBackend
* @inheritdoc
*/
public function clearVersionsForFile(IUser $user, Node $source, Node $target): void {
- $userFolder = $this->rootFolder->getUserFolder($user->getUID());
+ $userId = $user->getUID();
+ $userFolder = $this->rootFolder->getUserFolder($userId);
$relativePath = $userFolder->getRelativePath($source->getPath());
if ($relativePath === null) {
throw new Exception('Relative path not found for node with path: ' . $source->getPath());
}
- $versions = Storage::getVersions($user->getUID(), $relativePath);
- /** @var Folder versionFolder */
- $versionFolder = $this->rootFolder->get('admin/files_versions');
+ $versionFolder = $this->rootFolder->get($userId . '/files_versions');
+ if (!$versionFolder instanceof Folder) {
+ throw new Exception('User versions folder does not exist');
+ }
+
+ $versions = Storage::getVersions($userId, $relativePath);
foreach ($versions as $version) {
$versionFolder->get($version['path'] . '.v' . (int)$version['version'])->delete();
}
diff --git a/apps/files_versions/tests/VersioningTest.php b/apps/files_versions/tests/VersioningTest.php
index f294390a593..eaa0a02e261 100644
--- a/apps/files_versions/tests/VersioningTest.php
+++ b/apps/files_versions/tests/VersioningTest.php
@@ -83,7 +83,10 @@ class VersioningTest extends \Test\TestCase {
parent::setUp();
$config = Server::get(IConfig::class);
- $mockConfig = $this->createMock(IConfig::class);
+ $mockConfig = $this->getMockBuilder(AllConfig::class)
+ ->onlyMethods(['getSystemValue'])
+ ->setConstructorArgs([Server::get(SystemConfig::class)])
+ ->getMock();
$mockConfig->expects($this->any())
->method('getSystemValue')
->willReturnCallback(function ($key, $default) use ($config) {
@@ -427,8 +430,9 @@ class VersioningTest extends \Test\TestCase {
$this->rootView->file_put_contents($v2, 'version2');
// move file into the shared folder as recipient
- Filesystem::rename('/test.txt', '/folder1/test.txt');
+ $success = Filesystem::rename('/test.txt', '/folder1/test.txt');
+ $this->assertTrue($success);
$this->assertFalse($this->rootView->file_exists($v1));
$this->assertFalse($this->rootView->file_exists($v2));
@@ -808,7 +812,7 @@ class VersioningTest extends \Test\TestCase {
$eventDispatcher = Server::get(IEventDispatcher::class);
$eventFired = false;
- $eventDispatcher->addListener(VersionRestoredEvent::class, function ($event) use (&$eventFired, $t2) {
+ $eventDispatcher->addListener(VersionRestoredEvent::class, function ($event) use (&$eventFired, $t2): void {
$eventFired = true;
$this->assertEquals('/sub/test.txt', $event->getVersion()->getVersionPath());
$this->assertTrue($event->getVersion()->getRevisionId() > 0);
diff --git a/apps/settings/l10n/de.js b/apps/settings/l10n/de.js
index 37a1ff21e33..66150d7a47b 100644
--- a/apps/settings/l10n/de.js
+++ b/apps/settings/l10n/de.js
@@ -437,7 +437,7 @@ OC.L10N.register(
"Search groups…" : "Suche Gruppen…",
"List of groups. This list is not fully populated for performance reasons. The groups will be loaded as you navigate or search through the list." : "Liste der Gruppen. Diese Liste ist aus Leistungsgründen nicht vollständig gefüllt. Die Gruppen werden während des Navigierens oder Suchens geladen.",
"Loading groups…" : "Lade Gruppen…",
- "Could not load app discover section" : "Der App-Erkennungsabschnitt konnte nicht geladen werden",
+ "Could not load app discover section" : "Der Menüpunkt \"Endecken\" konnte nicht geladen werden.",
"Could not render element" : "Element konnte nicht dargestellt werden",
"Nothing to show" : "Nichts anzuzeigen",
"Could not load section content from app store." : "Abschnittsinhalt konnte nicht aus dem App Store geladen werden.",
@@ -647,14 +647,14 @@ OC.L10N.register(
"Edit your Profile visibility" : "Sichtbarkeit des Profils anpassen",
"Unable to update profile enabled state" : "Der Status „Profil aktiviert“ kann nicht aktualisiert werden.",
"Enable profile" : "Profil aktivieren",
- "The more restrictive setting of either visibility or scope is respected on your Profile. For example, if visibility is set to \"Show to everyone\" and scope is set to \"Private\", \"Private\" is respected." : "Die restriktivere Einstellung von Sichtbarkeit oder Bereich wird in deinem Profil berücksichtigt. Wenn beispielsweise die Sichtbarkeit auf \"Für jeden sichtbar\" und der Bereich auf \"Privat\" festgelegt ist, wird \"Privat\" respektiert.",
+ "The more restrictive setting of either visibility or scope is respected on your Profile. For example, if visibility is set to \"Show to everyone\" and scope is set to \"Private\", \"Private\" is respected." : "Die restriktivere Einstellung von Sichtbarkeit oder Bereich wird in deinem Profil berücksichtigt. Wenn beispielsweise die Sichtbarkeit auf \"Für alle sichtbar\" und der Bereich auf \"Privat\" festgelegt ist, wird \"Privat\" respektiert.",
"Unable to update visibility of {displayId}" : "Sichtbarkeit von {displayId} kann nicht aktualisiert werden",
"she/her" : "sie/ihr",
"he/him" : "er/sein",
"they/them" : "sie/sie",
"Your role" : "Deine Funktion",
"Your X (formerly Twitter) handle" : "Dein X (früher Twitter)-Handle",
- "Your website" : "Deine Internetseite",
+ "Your website" : "Deine Webseite",
"Invalid value" : "Ungültiger Wert",
"Unable to update {property}" : "{property} konnte nicht aktualisiert werden.",
"No {property} set" : "Keine {property} eingestellt",
@@ -804,8 +804,8 @@ OC.L10N.register(
"Locale" : "Gebietsschema",
"First day of week" : "Erster Tag der Woche",
"Not available as this property is required for core functionality including file sharing and calendar invitations" : "Nicht verfügbar, da diese Eigenschaft für Kernfunktionen wie Dateifreigabe und Kalendereinladungen erforderlich ist.",
- "Not available as federation has been disabled for your account, contact your system administration if you have any questions" : "Nicht verfügbar, da Federation für dein Konto deaktiviert ist. Wende dich an deine Administration, wenn du Fragen hast.",
- "Not available as publishing account specific data to the lookup server is not allowed, contact your system administration if you have any questions" : "Nicht verfügbar, da die Veröffentlichung benutzerspezifischer Daten auf dem Lookup-Server nicht zulässig ist. Bei Fragen bitte an die Systemadministration wenden..",
+ "Not available as federation has been disabled for your account, contact your system administration if you have any questions" : "Nicht verfügbar, da Federation für dein Konto deaktiviert ist. Wende dich bei Fragen an deine Systemadministration.",
+ "Not available as publishing account specific data to the lookup server is not allowed, contact your system administration if you have any questions" : "Nicht verfügbar, da die Veröffentlichung kontospezifischer Daten auf dem Lookup-Server nicht zulässig ist. Wende dich bei Fragen an deine Systemadministration.",
"Discover" : "Entdecken",
"Your apps" : "Deine Apps",
"Active apps" : "Aktive Apps",
@@ -814,7 +814,7 @@ OC.L10N.register(
"App bundles" : "App-Pakete",
"Featured apps" : "Vorgestellte Apps",
"Supported apps" : "Unterstützte Apps",
- "Show to everyone" : "Für jeden sichtbar",
+ "Show to everyone" : "Für alle sichtbar",
"Show to logged in accounts only" : "Nur angemeldeten Konten anzeigen",
"Hide" : "Ausblenden",
"Manually installed apps cannot be updated" : "Manuell installierte Apps können nicht aktualisiert werden",
diff --git a/apps/settings/l10n/de.json b/apps/settings/l10n/de.json
index 2b43ac861a5..c25dbf707bd 100644
--- a/apps/settings/l10n/de.json
+++ b/apps/settings/l10n/de.json
@@ -435,7 +435,7 @@
"Search groups…" : "Suche Gruppen…",
"List of groups. This list is not fully populated for performance reasons. The groups will be loaded as you navigate or search through the list." : "Liste der Gruppen. Diese Liste ist aus Leistungsgründen nicht vollständig gefüllt. Die Gruppen werden während des Navigierens oder Suchens geladen.",
"Loading groups…" : "Lade Gruppen…",
- "Could not load app discover section" : "Der App-Erkennungsabschnitt konnte nicht geladen werden",
+ "Could not load app discover section" : "Der Menüpunkt \"Endecken\" konnte nicht geladen werden.",
"Could not render element" : "Element konnte nicht dargestellt werden",
"Nothing to show" : "Nichts anzuzeigen",
"Could not load section content from app store." : "Abschnittsinhalt konnte nicht aus dem App Store geladen werden.",
@@ -645,14 +645,14 @@
"Edit your Profile visibility" : "Sichtbarkeit des Profils anpassen",
"Unable to update profile enabled state" : "Der Status „Profil aktiviert“ kann nicht aktualisiert werden.",
"Enable profile" : "Profil aktivieren",
- "The more restrictive setting of either visibility or scope is respected on your Profile. For example, if visibility is set to \"Show to everyone\" and scope is set to \"Private\", \"Private\" is respected." : "Die restriktivere Einstellung von Sichtbarkeit oder Bereich wird in deinem Profil berücksichtigt. Wenn beispielsweise die Sichtbarkeit auf \"Für jeden sichtbar\" und der Bereich auf \"Privat\" festgelegt ist, wird \"Privat\" respektiert.",
+ "The more restrictive setting of either visibility or scope is respected on your Profile. For example, if visibility is set to \"Show to everyone\" and scope is set to \"Private\", \"Private\" is respected." : "Die restriktivere Einstellung von Sichtbarkeit oder Bereich wird in deinem Profil berücksichtigt. Wenn beispielsweise die Sichtbarkeit auf \"Für alle sichtbar\" und der Bereich auf \"Privat\" festgelegt ist, wird \"Privat\" respektiert.",
"Unable to update visibility of {displayId}" : "Sichtbarkeit von {displayId} kann nicht aktualisiert werden",
"she/her" : "sie/ihr",
"he/him" : "er/sein",
"they/them" : "sie/sie",
"Your role" : "Deine Funktion",
"Your X (formerly Twitter) handle" : "Dein X (früher Twitter)-Handle",
- "Your website" : "Deine Internetseite",
+ "Your website" : "Deine Webseite",
"Invalid value" : "Ungültiger Wert",
"Unable to update {property}" : "{property} konnte nicht aktualisiert werden.",
"No {property} set" : "Keine {property} eingestellt",
@@ -802,8 +802,8 @@
"Locale" : "Gebietsschema",
"First day of week" : "Erster Tag der Woche",
"Not available as this property is required for core functionality including file sharing and calendar invitations" : "Nicht verfügbar, da diese Eigenschaft für Kernfunktionen wie Dateifreigabe und Kalendereinladungen erforderlich ist.",
- "Not available as federation has been disabled for your account, contact your system administration if you have any questions" : "Nicht verfügbar, da Federation für dein Konto deaktiviert ist. Wende dich an deine Administration, wenn du Fragen hast.",
- "Not available as publishing account specific data to the lookup server is not allowed, contact your system administration if you have any questions" : "Nicht verfügbar, da die Veröffentlichung benutzerspezifischer Daten auf dem Lookup-Server nicht zulässig ist. Bei Fragen bitte an die Systemadministration wenden..",
+ "Not available as federation has been disabled for your account, contact your system administration if you have any questions" : "Nicht verfügbar, da Federation für dein Konto deaktiviert ist. Wende dich bei Fragen an deine Systemadministration.",
+ "Not available as publishing account specific data to the lookup server is not allowed, contact your system administration if you have any questions" : "Nicht verfügbar, da die Veröffentlichung kontospezifischer Daten auf dem Lookup-Server nicht zulässig ist. Wende dich bei Fragen an deine Systemadministration.",
"Discover" : "Entdecken",
"Your apps" : "Deine Apps",
"Active apps" : "Aktive Apps",
@@ -812,7 +812,7 @@
"App bundles" : "App-Pakete",
"Featured apps" : "Vorgestellte Apps",
"Supported apps" : "Unterstützte Apps",
- "Show to everyone" : "Für jeden sichtbar",
+ "Show to everyone" : "Für alle sichtbar",
"Show to logged in accounts only" : "Nur angemeldeten Konten anzeigen",
"Hide" : "Ausblenden",
"Manually installed apps cannot be updated" : "Manuell installierte Apps können nicht aktualisiert werden",
diff --git a/apps/settings/l10n/de_DE.js b/apps/settings/l10n/de_DE.js
index 49c20c8e722..5388ff52529 100644
--- a/apps/settings/l10n/de_DE.js
+++ b/apps/settings/l10n/de_DE.js
@@ -2,7 +2,7 @@ OC.L10N.register(
"settings",
{
"Private" : "Privat",
- "Only visible to people matched via phone number integration through Talk on mobile" : "Nur sichtbar für Personen, die über Rufnummernintegration von Talk on mobile abgeglichen wurden.",
+ "Only visible to people matched via phone number integration through Talk on mobile" : "Nur sichtbar für Personen, die über die Rufnummernintegration von Talk auf dem Smartphone abgeglichen wurden.",
"Local" : "Lokal",
"Only visible to people on this instance and guests" : "Nur für Personen dieser Instanz und Gästen sichtbar",
"Federated" : "Federated",
@@ -626,7 +626,7 @@ OC.L10N.register(
"Unable to add additional email address" : "Zusätzliche E-Mail-Adresse kann nicht hinzugefügt werden",
"Unable to update additional email address" : "Zusätzliche E-Mail-Adresse konnte nicht aktualisiert werden",
"Unable to delete additional email address" : "Zusätzliche E-Mail-Adresse konnte nicht gelöscht werden",
- "Primary email for password reset and notifications" : "Primäre E-Mail-Adresse für Benachrichtigungen und Passwort-Zurücksetzen",
+ "Primary email for password reset and notifications" : "Primäre E-Mail-Adresse für Benachrichtigungen und zum Zurücksetzen des Passworts",
"No email address set" : "Keine E-Mail-Adresse angegeben",
"Your handle" : "Dein Online-Name",
"Derived from your locale ({weekDayName})" : "Abgeleitet von Ihrem Gebietsschema ({weekDayName})",
@@ -644,10 +644,10 @@ OC.L10N.register(
"Your city" : "Ihre Stadt",
"Your organisation" : "Ihre Organisation",
"Your phone number" : "Ihre Telefonnummer",
- "Edit your Profile visibility" : "Bearbeiten Sie die Sichtbarkeit Ihres Profils",
+ "Edit your Profile visibility" : "Sichtbarkeit des Profils anpassen",
"Unable to update profile enabled state" : "Der Status für aktiviertes Profil konnte nicht aktualisiert werden",
"Enable profile" : "Profil aktivieren",
- "The more restrictive setting of either visibility or scope is respected on your Profile. For example, if visibility is set to \"Show to everyone\" and scope is set to \"Private\", \"Private\" is respected." : "Die restriktivere Einstellung von Sichtbarkeit oder Bereich wird in Ihrem Profil berücksichtigt. Wenn beispielsweise die Sichtbarkeit auf \"Für alle anzeigen\" und der Bereich auf \"Privat\" festgelegt ist, wird \"Privat\" respektiert.",
+ "The more restrictive setting of either visibility or scope is respected on your Profile. For example, if visibility is set to \"Show to everyone\" and scope is set to \"Private\", \"Private\" is respected." : "Die restriktivere Einstellung von Sichtbarkeit oder Bereich wird in Ihrem Profil berücksichtigt. Wenn beispielsweise die Sichtbarkeit auf \"Für alle sichtbar\" und der Bereich auf \"Privat\" festgelegt ist, wird \"Privat\" respektiert.",
"Unable to update visibility of {displayId}" : "Sichtbarkeit von {displayId} kann nicht aktualisiert werden",
"she/her" : "sie/ihr",
"he/him" : "er/sein",
@@ -684,7 +684,7 @@ OC.L10N.register(
"Either password or email is required" : "Passwort oder E-Mail-Adresse ist erforderlich",
"Password (required)" : "Passwort (erforderlich)",
"Email (required)" : "E-Mail-Adresse (erforderlich)",
- "Email" : "E-Mail",
+ "Email" : "E-Mail-Adresse",
"Member of the following groups (required)" : "Mitglied der folgenden Gruppen (erforderlich)",
"Member of the following groups" : "Mitglied der folgenden Gruppen",
"Set account groups" : "Kontengruppen setzen",
@@ -804,7 +804,7 @@ OC.L10N.register(
"Locale" : "Gebietsschema",
"First day of week" : "Erster Tag der Woche",
"Not available as this property is required for core functionality including file sharing and calendar invitations" : "Nicht verfügbar, da diese Eigenschaft für Kernfunktionen wie Dateifreigabe und Kalendereinladungen erforderlich ist.",
- "Not available as federation has been disabled for your account, contact your system administration if you have any questions" : "Nicht verfügbar, da Federation für Ihr Konto deaktiviert ist. Bitte wenden Sie sich an Ihre Administration, wenn Sie Fragen haben",
+ "Not available as federation has been disabled for your account, contact your system administration if you have any questions" : "Nicht verfügbar, da Federation für Ihr Konto deaktiviert ist. Wenden Sie sich bei Fragen an Ihre Systemadministration.",
"Not available as publishing account specific data to the lookup server is not allowed, contact your system administration if you have any questions" : "Nicht verfügbar, da die Veröffentlichung kontospezifischer Daten auf dem Lookup-Server nicht zulässig ist. Wenden Sie sich bei Fragen an Ihre Systemadministration.",
"Discover" : "Entdecken",
"Your apps" : "Ihre Apps",
@@ -814,7 +814,7 @@ OC.L10N.register(
"App bundles" : "App-Pakete",
"Featured apps" : "Vorgestellte Apps",
"Supported apps" : "Unterstützte Apps",
- "Show to everyone" : "Jedem anzeigen",
+ "Show to everyone" : "Für alle sichtbar",
"Show to logged in accounts only" : "Nur angemeldeten Konten anzeigen",
"Hide" : "Ausblenden",
"Manually installed apps cannot be updated" : "Manuell installierte Apps können nicht aktualisiert werden",
diff --git a/apps/settings/l10n/de_DE.json b/apps/settings/l10n/de_DE.json
index 85ed8fe4a63..0f35dc26f55 100644
--- a/apps/settings/l10n/de_DE.json
+++ b/apps/settings/l10n/de_DE.json
@@ -1,6 +1,6 @@
{ "translations": {
"Private" : "Privat",
- "Only visible to people matched via phone number integration through Talk on mobile" : "Nur sichtbar für Personen, die über Rufnummernintegration von Talk on mobile abgeglichen wurden.",
+ "Only visible to people matched via phone number integration through Talk on mobile" : "Nur sichtbar für Personen, die über die Rufnummernintegration von Talk auf dem Smartphone abgeglichen wurden.",
"Local" : "Lokal",
"Only visible to people on this instance and guests" : "Nur für Personen dieser Instanz und Gästen sichtbar",
"Federated" : "Federated",
@@ -624,7 +624,7 @@
"Unable to add additional email address" : "Zusätzliche E-Mail-Adresse kann nicht hinzugefügt werden",
"Unable to update additional email address" : "Zusätzliche E-Mail-Adresse konnte nicht aktualisiert werden",
"Unable to delete additional email address" : "Zusätzliche E-Mail-Adresse konnte nicht gelöscht werden",
- "Primary email for password reset and notifications" : "Primäre E-Mail-Adresse für Benachrichtigungen und Passwort-Zurücksetzen",
+ "Primary email for password reset and notifications" : "Primäre E-Mail-Adresse für Benachrichtigungen und zum Zurücksetzen des Passworts",
"No email address set" : "Keine E-Mail-Adresse angegeben",
"Your handle" : "Dein Online-Name",
"Derived from your locale ({weekDayName})" : "Abgeleitet von Ihrem Gebietsschema ({weekDayName})",
@@ -642,10 +642,10 @@
"Your city" : "Ihre Stadt",
"Your organisation" : "Ihre Organisation",
"Your phone number" : "Ihre Telefonnummer",
- "Edit your Profile visibility" : "Bearbeiten Sie die Sichtbarkeit Ihres Profils",
+ "Edit your Profile visibility" : "Sichtbarkeit des Profils anpassen",
"Unable to update profile enabled state" : "Der Status für aktiviertes Profil konnte nicht aktualisiert werden",
"Enable profile" : "Profil aktivieren",
- "The more restrictive setting of either visibility or scope is respected on your Profile. For example, if visibility is set to \"Show to everyone\" and scope is set to \"Private\", \"Private\" is respected." : "Die restriktivere Einstellung von Sichtbarkeit oder Bereich wird in Ihrem Profil berücksichtigt. Wenn beispielsweise die Sichtbarkeit auf \"Für alle anzeigen\" und der Bereich auf \"Privat\" festgelegt ist, wird \"Privat\" respektiert.",
+ "The more restrictive setting of either visibility or scope is respected on your Profile. For example, if visibility is set to \"Show to everyone\" and scope is set to \"Private\", \"Private\" is respected." : "Die restriktivere Einstellung von Sichtbarkeit oder Bereich wird in Ihrem Profil berücksichtigt. Wenn beispielsweise die Sichtbarkeit auf \"Für alle sichtbar\" und der Bereich auf \"Privat\" festgelegt ist, wird \"Privat\" respektiert.",
"Unable to update visibility of {displayId}" : "Sichtbarkeit von {displayId} kann nicht aktualisiert werden",
"she/her" : "sie/ihr",
"he/him" : "er/sein",
@@ -682,7 +682,7 @@
"Either password or email is required" : "Passwort oder E-Mail-Adresse ist erforderlich",
"Password (required)" : "Passwort (erforderlich)",
"Email (required)" : "E-Mail-Adresse (erforderlich)",
- "Email" : "E-Mail",
+ "Email" : "E-Mail-Adresse",
"Member of the following groups (required)" : "Mitglied der folgenden Gruppen (erforderlich)",
"Member of the following groups" : "Mitglied der folgenden Gruppen",
"Set account groups" : "Kontengruppen setzen",
@@ -802,7 +802,7 @@
"Locale" : "Gebietsschema",
"First day of week" : "Erster Tag der Woche",
"Not available as this property is required for core functionality including file sharing and calendar invitations" : "Nicht verfügbar, da diese Eigenschaft für Kernfunktionen wie Dateifreigabe und Kalendereinladungen erforderlich ist.",
- "Not available as federation has been disabled for your account, contact your system administration if you have any questions" : "Nicht verfügbar, da Federation für Ihr Konto deaktiviert ist. Bitte wenden Sie sich an Ihre Administration, wenn Sie Fragen haben",
+ "Not available as federation has been disabled for your account, contact your system administration if you have any questions" : "Nicht verfügbar, da Federation für Ihr Konto deaktiviert ist. Wenden Sie sich bei Fragen an Ihre Systemadministration.",
"Not available as publishing account specific data to the lookup server is not allowed, contact your system administration if you have any questions" : "Nicht verfügbar, da die Veröffentlichung kontospezifischer Daten auf dem Lookup-Server nicht zulässig ist. Wenden Sie sich bei Fragen an Ihre Systemadministration.",
"Discover" : "Entdecken",
"Your apps" : "Ihre Apps",
@@ -812,7 +812,7 @@
"App bundles" : "App-Pakete",
"Featured apps" : "Vorgestellte Apps",
"Supported apps" : "Unterstützte Apps",
- "Show to everyone" : "Jedem anzeigen",
+ "Show to everyone" : "Für alle sichtbar",
"Show to logged in accounts only" : "Nur angemeldeten Konten anzeigen",
"Hide" : "Ausblenden",
"Manually installed apps cannot be updated" : "Manuell installierte Apps können nicht aktualisiert werden",
diff --git a/apps/settings/l10n/ru.js b/apps/settings/l10n/ru.js
index f6a2ba501b8..58f1e7bcb9c 100644
--- a/apps/settings/l10n/ru.js
+++ b/apps/settings/l10n/ru.js
@@ -562,6 +562,7 @@ OC.L10N.register(
"Profile" : "Профиль",
"Enable or disable profile by default for new accounts." : "Включите или отключите профиль по умолчанию для новых учетных записей.",
"Failed to save setting" : "Не удалось сохранить параметры",
+ "{app}'s declarative setting field: {name}" : "{app} поле декларативной настройки: {name}",
"Unable to update server side encryption config" : "Не удалось обновить параметры шифрования на стороне сервера",
"Server-side encryption" : "Шифрование на стороне сервера",
"Server-side encryption makes it possible to encrypt files which are uploaded to this server. This comes with limitations like a performance penalty, so enable this only if needed." : "Шифрование на стороне сервера позволяет шифровать файлы, которые загружаются на этот сервер. Это связано с ограничениями, такими как снижение производительности, поэтому включите его только в случае необходимости.",
diff --git a/apps/settings/l10n/ru.json b/apps/settings/l10n/ru.json
index 0fecb762e22..48fea024a39 100644
--- a/apps/settings/l10n/ru.json
+++ b/apps/settings/l10n/ru.json
@@ -560,6 +560,7 @@
"Profile" : "Профиль",
"Enable or disable profile by default for new accounts." : "Включите или отключите профиль по умолчанию для новых учетных записей.",
"Failed to save setting" : "Не удалось сохранить параметры",
+ "{app}'s declarative setting field: {name}" : "{app} поле декларативной настройки: {name}",
"Unable to update server side encryption config" : "Не удалось обновить параметры шифрования на стороне сервера",
"Server-side encryption" : "Шифрование на стороне сервера",
"Server-side encryption makes it possible to encrypt files which are uploaded to this server. This comes with limitations like a performance penalty, so enable this only if needed." : "Шифрование на стороне сервера позволяет шифровать файлы, которые загружаются на этот сервер. Это связано с ограничениями, такими как снижение производительности, поэтому включите его только в случае необходимости.",
diff --git a/apps/settings/lib/Settings/Admin/Mail.php b/apps/settings/lib/Settings/Admin/Mail.php
index 728be01f3d8..566cdea310f 100644
--- a/apps/settings/lib/Settings/Admin/Mail.php
+++ b/apps/settings/lib/Settings/Admin/Mail.php
@@ -9,6 +9,7 @@ use OCP\AppFramework\Http\TemplateResponse;
use OCP\IBinaryFinder;
use OCP\IConfig;
use OCP\IL10N;
+use OCP\Server;
use OCP\Settings\IDelegatedSettings;
class Mail implements IDelegatedSettings {
@@ -26,7 +27,7 @@ class Mail implements IDelegatedSettings {
* @return TemplateResponse
*/
public function getForm() {
- $finder = \OCP\Server::get(IBinaryFinder::class);
+ $finder = Server::get(IBinaryFinder::class);
$parameters = [
// Mail
diff --git a/apps/settings/lib/Settings/Personal/PersonalInfo.php b/apps/settings/lib/Settings/Personal/PersonalInfo.php
index 1032f97361b..84b379f2e87 100644
--- a/apps/settings/lib/Settings/Personal/PersonalInfo.php
+++ b/apps/settings/lib/Settings/Personal/PersonalInfo.php
@@ -29,6 +29,7 @@ use OCP\L10N\IFactory;
use OCP\Notification\IManager;
use OCP\Server;
use OCP\Settings\ISettings;
+use OCP\Util;
class PersonalInfo implements ISettings {
@@ -71,7 +72,7 @@ class PersonalInfo implements ISettings {
if ($storageInfo['quota'] === FileInfo::SPACE_UNLIMITED) {
$totalSpace = $this->l->t('Unlimited');
} else {
- $totalSpace = \OC_Helper::humanFileSize($storageInfo['total']);
+ $totalSpace = Util::humanFileSize($storageInfo['total']);
}
$messageParameters = $this->getMessageParameters($account);
@@ -88,7 +89,7 @@ class PersonalInfo implements ISettings {
'groups' => $this->getGroups($user),
'quota' => $storageInfo['quota'],
'totalSpace' => $totalSpace,
- 'usage' => \OC_Helper::humanFileSize($storageInfo['used']),
+ 'usage' => Util::humanFileSize($storageInfo['used']),
'usageRelative' => round($storageInfo['relative']),
'displayName' => $this->getProperty($account, IAccountManager::PROPERTY_DISPLAYNAME),
'emailMap' => $this->getEmailMap($account),
diff --git a/apps/settings/lib/UserMigration/AccountMigrator.php b/apps/settings/lib/UserMigration/AccountMigrator.php
index 15ac06687b6..1c51aec5104 100644
--- a/apps/settings/lib/UserMigration/AccountMigrator.php
+++ b/apps/settings/lib/UserMigration/AccountMigrator.php
@@ -35,8 +35,6 @@ class AccountMigrator implements IMigrator, ISizeEstimationMigrator {
private ProfileManager $profileManager;
- private ProfileConfigMapper $configMapper;
-
private const PATH_ROOT = Application::APP_ID . '/';
private const PATH_ACCOUNT_FILE = AccountMigrator::PATH_ROOT . 'account.json';
@@ -49,11 +47,10 @@ class AccountMigrator implements IMigrator, ISizeEstimationMigrator {
private IAccountManager $accountManager,
private IAvatarManager $avatarManager,
ProfileManager $profileManager,
- ProfileConfigMapper $configMapper,
+ private ProfileConfigMapper $configMapper,
private IL10N $l10n,
) {
$this->profileManager = $profileManager;
- $this->configMapper = $configMapper;
}
/**
diff --git a/apps/systemtags/l10n/de.js b/apps/systemtags/l10n/de.js
index bae01f498d9..06cc0e154ea 100644
--- a/apps/systemtags/l10n/de.js
+++ b/apps/systemtags/l10n/de.js
@@ -42,7 +42,7 @@ OC.L10N.register(
"Tags" : "Tags",
"All tagged %s …" : "Alle Schlagworte %s hinzugefügt …",
"tagged %s" : "Schlagwort %s hinzugefügt",
- "Collaborative tags" : "Kollaborative Tags",
+ "Collaborative tags" : "Kollaborative Schlagworte",
"Collaborative tagging functionality which shares tags among people." : "Gemeinschaftliche Schlagwort-Funktionalität, welche Schlagworte unter den Benutzern teilt.",
"Collaborative tagging functionality which shares tags among people. Great for teams.\n\t(If you are a provider with a multi-tenancy installation, it is advised to deactivate this app as tags are shared.)" : "Schlagwort-Funktionalität für die Zusammenarbeit, die das Teilen von Schlagworten unter Benutzern ermöglicht. Sehr gut für Gruppen geeignet.\n\t(In eine Mehrkundeninstallation sollte diese App deaktiviert werden, da sonst die Schlagworte mit allen Kunden geteilt werden.)",
"Public" : "Öffentlich",
diff --git a/apps/systemtags/l10n/de.json b/apps/systemtags/l10n/de.json
index 83fc4b6daf6..8c2f25aa302 100644
--- a/apps/systemtags/l10n/de.json
+++ b/apps/systemtags/l10n/de.json
@@ -40,7 +40,7 @@
"Tags" : "Tags",
"All tagged %s …" : "Alle Schlagworte %s hinzugefügt …",
"tagged %s" : "Schlagwort %s hinzugefügt",
- "Collaborative tags" : "Kollaborative Tags",
+ "Collaborative tags" : "Kollaborative Schlagworte",
"Collaborative tagging functionality which shares tags among people." : "Gemeinschaftliche Schlagwort-Funktionalität, welche Schlagworte unter den Benutzern teilt.",
"Collaborative tagging functionality which shares tags among people. Great for teams.\n\t(If you are a provider with a multi-tenancy installation, it is advised to deactivate this app as tags are shared.)" : "Schlagwort-Funktionalität für die Zusammenarbeit, die das Teilen von Schlagworten unter Benutzern ermöglicht. Sehr gut für Gruppen geeignet.\n\t(In eine Mehrkundeninstallation sollte diese App deaktiviert werden, da sonst die Schlagworte mit allen Kunden geteilt werden.)",
"Public" : "Öffentlich",
diff --git a/apps/systemtags/l10n/de_DE.js b/apps/systemtags/l10n/de_DE.js
index 447cb344bce..531023ade74 100644
--- a/apps/systemtags/l10n/de_DE.js
+++ b/apps/systemtags/l10n/de_DE.js
@@ -89,7 +89,7 @@ OC.L10N.register(
"Failed to load selected tags" : "Ausgewählte Schlagworte konnten nicht geladen werden",
"Failed to select tag" : "Schlagwort konnte nicht ausgewählt werden",
"System admin disabled tag creation. You can only use existing ones." : "Die Systemadministration hat die Erstellung von Schlagworten deaktiviert. Sie können nur vorhandene Schlagworte verwenden.",
- "Loading collaborative tags …" : "Lade kollaborative Schlagworte …",
+ "Loading collaborative tags …" : "Kollaborative Schlagworte laden…",
"Search or create collaborative tags" : "Suchen oder erstellen von kollaborativen Schlagworten",
"No tags to select, type to create a new tag" : "Keine Schlagworte zur Auswahl, geben Sie ein, um ein neues Schlagwort zu erstellen",
"Unable to update setting" : "Einstellung konnte nicht aktualisiert werden",
diff --git a/apps/systemtags/l10n/de_DE.json b/apps/systemtags/l10n/de_DE.json
index cc905e232d5..adaff5ffc70 100644
--- a/apps/systemtags/l10n/de_DE.json
+++ b/apps/systemtags/l10n/de_DE.json
@@ -87,7 +87,7 @@
"Failed to load selected tags" : "Ausgewählte Schlagworte konnten nicht geladen werden",
"Failed to select tag" : "Schlagwort konnte nicht ausgewählt werden",
"System admin disabled tag creation. You can only use existing ones." : "Die Systemadministration hat die Erstellung von Schlagworten deaktiviert. Sie können nur vorhandene Schlagworte verwenden.",
- "Loading collaborative tags …" : "Lade kollaborative Schlagworte …",
+ "Loading collaborative tags …" : "Kollaborative Schlagworte laden…",
"Search or create collaborative tags" : "Suchen oder erstellen von kollaborativen Schlagworten",
"No tags to select, type to create a new tag" : "Keine Schlagworte zur Auswahl, geben Sie ein, um ein neues Schlagwort zu erstellen",
"Unable to update setting" : "Einstellung konnte nicht aktualisiert werden",
diff --git a/apps/theming/l10n/de.js b/apps/theming/l10n/de.js
index 702a47c76ec..3ecc474c96a 100644
--- a/apps/theming/l10n/de.js
+++ b/apps/theming/l10n/de.js
@@ -82,7 +82,7 @@ OC.L10N.register(
"Misc accessibility options" : "Verschiedene Barrierefreiheitsoptionen",
"Enable blur background filter (may increase GPU load)" : "Filter für unscharfes Hintergrundbild aktivieren (kann die GPU-Auslastung erhöhen)",
"Customization has been disabled by your administrator" : "Diese Anpassungsmöglichkeit wurde von deiner Administration deaktiviert",
- "Set a primary color to highlight important elements. The color used for elements such as primary buttons might differ a bit as it gets adjusted to fulfill accessibility requirements." : "Legen eine Primärfarbe fest, um wichtige Elemente hervorzuheben. Die für Elemente wie Primärschaltflächen verwendete Farbe kann etwas abweichen, da sie angepasst wird, um die Zugänglichkeitsanforderungen zu erfüllen.",
+ "Set a primary color to highlight important elements. The color used for elements such as primary buttons might differ a bit as it gets adjusted to fulfill accessibility requirements." : "Lege eine Primärfarbe fest, um wichtige Elemente hervorzuheben. Die für Elemente wie Primärschaltflächen verwendete Farbe kann etwas abweichen, da sie angepasst wird, um die Zugänglichkeitsanforderungen zu erfüllen.",
"Background and color" : "Hintergrund und Farbe",
"The background can be set to an image from the default set, a custom uploaded image, or a plain color." : "Als Hintergrund kann ein Bild aus dem Standardsatz, ein benutzerdefiniertes hochgeladenes Bild oder eine einfache Farbe ausgewählt werden.",
"Keyboard shortcuts" : "Tastaturkürzel",
diff --git a/apps/theming/l10n/de.json b/apps/theming/l10n/de.json
index 97051ce93c9..1d2b5fb9803 100644
--- a/apps/theming/l10n/de.json
+++ b/apps/theming/l10n/de.json
@@ -80,7 +80,7 @@
"Misc accessibility options" : "Verschiedene Barrierefreiheitsoptionen",
"Enable blur background filter (may increase GPU load)" : "Filter für unscharfes Hintergrundbild aktivieren (kann die GPU-Auslastung erhöhen)",
"Customization has been disabled by your administrator" : "Diese Anpassungsmöglichkeit wurde von deiner Administration deaktiviert",
- "Set a primary color to highlight important elements. The color used for elements such as primary buttons might differ a bit as it gets adjusted to fulfill accessibility requirements." : "Legen eine Primärfarbe fest, um wichtige Elemente hervorzuheben. Die für Elemente wie Primärschaltflächen verwendete Farbe kann etwas abweichen, da sie angepasst wird, um die Zugänglichkeitsanforderungen zu erfüllen.",
+ "Set a primary color to highlight important elements. The color used for elements such as primary buttons might differ a bit as it gets adjusted to fulfill accessibility requirements." : "Lege eine Primärfarbe fest, um wichtige Elemente hervorzuheben. Die für Elemente wie Primärschaltflächen verwendete Farbe kann etwas abweichen, da sie angepasst wird, um die Zugänglichkeitsanforderungen zu erfüllen.",
"Background and color" : "Hintergrund und Farbe",
"The background can be set to an image from the default set, a custom uploaded image, or a plain color." : "Als Hintergrund kann ein Bild aus dem Standardsatz, ein benutzerdefiniertes hochgeladenes Bild oder eine einfache Farbe ausgewählt werden.",
"Keyboard shortcuts" : "Tastaturkürzel",
diff --git a/apps/theming/l10n/de_DE.js b/apps/theming/l10n/de_DE.js
index c122e73ec49..b2c84dce2dc 100644
--- a/apps/theming/l10n/de_DE.js
+++ b/apps/theming/l10n/de_DE.js
@@ -50,7 +50,7 @@ OC.L10N.register(
"The default light appearance." : "Das helle Standarddesign.",
"Legal notice" : "Impressum",
"Privacy policy" : "Datenschutzerklärung",
- "Adjust the Nextcloud theme" : "Passe das Design von Nextcloud an",
+ "Adjust the Nextcloud theme" : "Passen Sie das Design von Nextcloud an",
"Name" : "Name",
"Web link" : "Internet-Link",
"a safe home for all your data" : "Ein sicheres Zuhause für Ihre Daten",
diff --git a/apps/theming/l10n/de_DE.json b/apps/theming/l10n/de_DE.json
index d62d9039ab4..d3064661462 100644
--- a/apps/theming/l10n/de_DE.json
+++ b/apps/theming/l10n/de_DE.json
@@ -48,7 +48,7 @@
"The default light appearance." : "Das helle Standarddesign.",
"Legal notice" : "Impressum",
"Privacy policy" : "Datenschutzerklärung",
- "Adjust the Nextcloud theme" : "Passe das Design von Nextcloud an",
+ "Adjust the Nextcloud theme" : "Passen Sie das Design von Nextcloud an",
"Name" : "Name",
"Web link" : "Internet-Link",
"a safe home for all your data" : "Ein sicheres Zuhause für Ihre Daten",
diff --git a/apps/twofactor_backupcodes/tests/Db/BackupCodeMapperTest.php b/apps/twofactor_backupcodes/tests/Db/BackupCodeMapperTest.php
index 6b668f53119..19cab51969b 100644
--- a/apps/twofactor_backupcodes/tests/Db/BackupCodeMapperTest.php
+++ b/apps/twofactor_backupcodes/tests/Db/BackupCodeMapperTest.php
@@ -19,15 +19,9 @@ use Test\TestCase;
* @group DB
*/
class BackupCodeMapperTest extends TestCase {
-
- /** @var IDBConnection */
- private $db;
-
- /** @var BackupCodeMapper */
- private $mapper;
-
- /** @var string */
- private $testUID = 'test123456';
+ private IDBConnection $db;
+ private BackupCodeMapper $mapper;
+ private string $testUID = 'test123456';
private function resetDB() {
$qb = $this->db->getQueryBuilder();
diff --git a/apps/twofactor_backupcodes/tests/Service/BackupCodeStorageTest.php b/apps/twofactor_backupcodes/tests/Service/BackupCodeStorageTest.php
index b556828b924..38d3bd55d11 100644
--- a/apps/twofactor_backupcodes/tests/Service/BackupCodeStorageTest.php
+++ b/apps/twofactor_backupcodes/tests/Service/BackupCodeStorageTest.php
@@ -13,21 +13,16 @@ use OCP\IUser;
use OCP\Notification\IManager;
use OCP\Notification\INotification;
use OCP\Server;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
/**
* @group DB
*/
class BackupCodeStorageTest extends TestCase {
-
- /** @var BackupCodeStorage */
- private $storage;
-
- /** @var string */
- private $testUID = 'test123456789';
-
- /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
- private $notificationManager;
+ private IManager&MockObject $notificationManager;
+ private string $testUID = 'test123456789';
+ private BackupCodeStorage $storage;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/twofactor_backupcodes/tests/Unit/Activity/ProviderTest.php b/apps/twofactor_backupcodes/tests/Unit/Activity/ProviderTest.php
index e41db8b0a32..a3c6d15902a 100644
--- a/apps/twofactor_backupcodes/tests/Unit/Activity/ProviderTest.php
+++ b/apps/twofactor_backupcodes/tests/Unit/Activity/ProviderTest.php
@@ -15,21 +15,14 @@ use OCP\Activity\IManager;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\L10N\IFactory;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class ProviderTest extends TestCase {
-
- /** @var IFactory|\PHPUnit\Framework\MockObject\MockObject */
- private $l10n;
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- private $urlGenerator;
-
- /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
- private $activityManager;
-
- /** @var Provider */
- private $provider;
+ private IFactory&MockObject $l10n;
+ private IURLGenerator&MockObject $urlGenerator;
+ private IManager&MockObject $activityManager;
+ private Provider $provider;
protected function setUp(): void {
parent::setUp();
@@ -52,7 +45,7 @@ class ProviderTest extends TestCase {
$this->provider->parse($lang, $event);
}
- public function subjectData() {
+ public static function subjectData(): array {
return [
['codes_generated'],
];
@@ -61,7 +54,7 @@ class ProviderTest extends TestCase {
/**
* @dataProvider subjectData
*/
- public function testParse($subject): void {
+ public function testParse(string $subject): void {
$lang = 'ru';
$event = $this->createMock(IEvent::class);
$l = $this->createMock(IL10N::class);
diff --git a/apps/twofactor_backupcodes/tests/Unit/BackgroundJob/CheckBackupCodeTest.php b/apps/twofactor_backupcodes/tests/Unit/BackgroundJob/CheckBackupCodeTest.php
index 5b8281e278e..87bc65e4309 100644
--- a/apps/twofactor_backupcodes/tests/Unit/BackgroundJob/CheckBackupCodeTest.php
+++ b/apps/twofactor_backupcodes/tests/Unit/BackgroundJob/CheckBackupCodeTest.php
@@ -20,24 +20,12 @@ use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class CheckBackupCodeTest extends TestCase {
-
- /** @var IUserManager|MockObject */
- private $userManager;
-
- /** @var IJobList|MockObject */
- private $jobList;
-
- /** @var IRegistry|MockObject */
- private $registry;
-
- /** @var Manager|MockObject */
- private $manager;
-
- /** @var IUser|MockObject */
- private $user;
-
- /** @var CheckBackupCodes */
- private $checkBackupCodes;
+ private IUserManager&MockObject $userManager;
+ private IJobList&MockObject $jobList;
+ private IRegistry&MockObject $registry;
+ private Manager&MockObject $manager;
+ private IUser&MockObject $user;
+ private CheckBackupCodes $checkBackupCodes;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/twofactor_backupcodes/tests/Unit/BackgroundJob/RememberBackupCodesJobTest.php b/apps/twofactor_backupcodes/tests/Unit/BackgroundJob/RememberBackupCodesJobTest.php
index 31b7d514246..16a0e8012f7 100644
--- a/apps/twofactor_backupcodes/tests/Unit/BackgroundJob/RememberBackupCodesJobTest.php
+++ b/apps/twofactor_backupcodes/tests/Unit/BackgroundJob/RememberBackupCodesJobTest.php
@@ -17,27 +17,16 @@ use OCP\IUserManager;
use OCP\Notification\IManager;
use OCP\Notification\INotification;
use OCP\Server;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class RememberBackupCodesJobTest extends TestCase {
-
- /** @var IRegistry|\PHPUnit\Framework\MockObject\MockObject */
- private $registry;
-
- /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
- private $userManager;
-
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
- private $time;
-
- /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
- private $notificationManager;
-
- /** @var IJobList|\PHPUnit\Framework\MockObject\MockObject */
- private $jobList;
-
- /** @var RememberBackupCodesJob */
- private $job;
+ private IRegistry&MockObject $registry;
+ private IUserManager&MockObject $userManager;
+ private ITimeFactory&MockObject $time;
+ private IManager&MockObject $notificationManager;
+ private IJobList&MockObject $jobList;
+ private RememberBackupCodesJob $job;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/twofactor_backupcodes/tests/Unit/Controller/SettingsControllerTest.php b/apps/twofactor_backupcodes/tests/Unit/Controller/SettingsControllerTest.php
index 85b23e88fee..02c42b65148 100644
--- a/apps/twofactor_backupcodes/tests/Unit/Controller/SettingsControllerTest.php
+++ b/apps/twofactor_backupcodes/tests/Unit/Controller/SettingsControllerTest.php
@@ -14,36 +14,27 @@ use OCP\AppFramework\Http\JSONResponse;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class SettingsControllerTest extends TestCase {
-
- /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
- private $request;
-
- /** @var BackupCodeStorage|\PHPUnit\Framework\MockObject\MockObject */
- private $storage;
-
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- private $userSession;
-
- /** @var SettingsController */
- private $controller;
+ private IRequest&MockObject $request;
+ private BackupCodeStorage&MockObject $storage;
+ private IUserSession&MockObject $userSession;
+ private SettingsController $controller;
protected function setUp(): void {
parent::setUp();
- $this->request = $this->getMockBuilder(IRequest::class)->getMock();
- $this->storage = $this->getMockBuilder(BackupCodeStorage::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->userSession = $this->getMockBuilder(IUserSession::class)->getMock();
+ $this->request = $this->createMock(IRequest::class);
+ $this->storage = $this->createMock(BackupCodeStorage::class);
+ $this->userSession = $this->createMock(IUserSession::class);
$this->controller = new SettingsController('twofactor_backupcodes', $this->request, $this->storage, $this->userSession);
}
public function testCreateCodes(): void {
- $user = $this->getMockBuilder(IUser::class)->getMock();
+ $user = $this->createMock(IUser::class);
$codes = ['a', 'b'];
$this->userSession->expects($this->once())
diff --git a/apps/twofactor_backupcodes/tests/Unit/Listener/ActivityPublisherTest.php b/apps/twofactor_backupcodes/tests/Unit/Listener/ActivityPublisherTest.php
index 72ca91ed8eb..bd944dc2396 100644
--- a/apps/twofactor_backupcodes/tests/Unit/Listener/ActivityPublisherTest.php
+++ b/apps/twofactor_backupcodes/tests/Unit/Listener/ActivityPublisherTest.php
@@ -19,14 +19,9 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class ActivityPublisherTest extends TestCase {
- /** @var IManager|MockObject */
- private $activityManager;
-
- /** @var LoggerInterface */
- private $logger;
-
- /** @var ActivityPublisher */
- private $listener;
+ private IManager&MockObject $activityManager;
+ private LoggerInterface&MockObject $logger;
+ private ActivityPublisher $listener;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/twofactor_backupcodes/tests/Unit/Listener/ClearNotificationsTest.php b/apps/twofactor_backupcodes/tests/Unit/Listener/ClearNotificationsTest.php
index bbefbfbece1..fc80344ac57 100644
--- a/apps/twofactor_backupcodes/tests/Unit/Listener/ClearNotificationsTest.php
+++ b/apps/twofactor_backupcodes/tests/Unit/Listener/ClearNotificationsTest.php
@@ -15,15 +15,12 @@ use OCP\IUser;
use OCP\Notification\IManager;
use OCP\Notification\INotification;
use OCP\Server;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class ClearNotificationsTest extends TestCase {
-
- /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
- private $notificationManager;
-
- /** @var ClearNotifications */
- private $listener;
+ private IManager&MockObject $notificationManager;
+ private ClearNotifications $listener;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/twofactor_backupcodes/tests/Unit/Listener/ProviderDisabledTest.php b/apps/twofactor_backupcodes/tests/Unit/Listener/ProviderDisabledTest.php
index 7f7b5dc3011..ea4f530cab4 100644
--- a/apps/twofactor_backupcodes/tests/Unit/Listener/ProviderDisabledTest.php
+++ b/apps/twofactor_backupcodes/tests/Unit/Listener/ProviderDisabledTest.php
@@ -15,11 +15,12 @@ use OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserUnregistered;
use OCP\BackgroundJob\IJobList;
use OCP\EventDispatcher\Event;
use OCP\IUser;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class ProviderDisabledTest extends TestCase {
- private IRegistry $registy;
- private IJobList $jobList;
+ private IRegistry&MockObject $registy;
+ private IJobList&MockObject $jobList;
private ProviderDisabled $listener;
protected function setUp(): void {
diff --git a/apps/twofactor_backupcodes/tests/Unit/Listener/ProviderEnabledTest.php b/apps/twofactor_backupcodes/tests/Unit/Listener/ProviderEnabledTest.php
index 145944fccca..50aac6139c0 100644
--- a/apps/twofactor_backupcodes/tests/Unit/Listener/ProviderEnabledTest.php
+++ b/apps/twofactor_backupcodes/tests/Unit/Listener/ProviderEnabledTest.php
@@ -15,11 +15,12 @@ use OCP\Authentication\TwoFactorAuth\TwoFactorProviderForUserRegistered;
use OCP\BackgroundJob\IJobList;
use OCP\EventDispatcher\Event;
use OCP\IUser;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class ProviderEnabledTest extends TestCase {
- private IRegistry $registy;
- private IJobList $jobList;
+ private IRegistry&MockObject $registy;
+ private IJobList&MockObject $jobList;
private ProviderEnabled $listener;
protected function setUp(): void {
diff --git a/apps/twofactor_backupcodes/tests/Unit/Listener/RegistryUpdaterTest.php b/apps/twofactor_backupcodes/tests/Unit/Listener/RegistryUpdaterTest.php
index 4f724f888d7..86d890f0d5e 100644
--- a/apps/twofactor_backupcodes/tests/Unit/Listener/RegistryUpdaterTest.php
+++ b/apps/twofactor_backupcodes/tests/Unit/Listener/RegistryUpdaterTest.php
@@ -14,18 +14,13 @@ use OCA\TwoFactorBackupCodes\Provider\BackupCodesProvider;
use OCP\Authentication\TwoFactorAuth\IRegistry;
use OCP\EventDispatcher\Event;
use OCP\IUser;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class RegistryUpdaterTest extends TestCase {
-
- /** @var IRegistry */
- private $registry;
-
- /** @var BackupCodesProvider */
- private $provider;
-
- /** @var RegistryUpdater */
- private $listener;
+ private IRegistry&MockObject $registry;
+ private BackupCodesProvider&MockObject $provider;
+ private RegistryUpdater $listener;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/twofactor_backupcodes/tests/Unit/Migration/CheckBackupCodeTest.php b/apps/twofactor_backupcodes/tests/Unit/Migration/CheckBackupCodeTest.php
index bb959ff08b3..c68ab185116 100644
--- a/apps/twofactor_backupcodes/tests/Unit/Migration/CheckBackupCodeTest.php
+++ b/apps/twofactor_backupcodes/tests/Unit/Migration/CheckBackupCodeTest.php
@@ -11,15 +11,12 @@ namespace OCA\TwoFactorBackupCodes\Tests\Unit\Migration;
use OCA\TwoFactorBackupCodes\Migration\CheckBackupCodes;
use OCP\BackgroundJob\IJobList;
use OCP\Migration\IOutput;
+use PHPunit\Framework\MockObject\MockObject;
use Test\TestCase;
class CheckBackupCodeTest extends TestCase {
-
- /** @var IJobList|\PHPunit\Framework\MockObject\MockObject */
- private $jobList;
-
- /** @var CheckBackupCodes */
- private $checkBackupsCodes;
+ private IJobList&MockObject $jobList;
+ private CheckBackupCodes $checkBackupsCodes;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/twofactor_backupcodes/tests/Unit/Notification/NotifierTest.php b/apps/twofactor_backupcodes/tests/Unit/Notification/NotifierTest.php
index cbda9dd868b..b091d57dbd2 100644
--- a/apps/twofactor_backupcodes/tests/Unit/Notification/NotifierTest.php
+++ b/apps/twofactor_backupcodes/tests/Unit/Notification/NotifierTest.php
@@ -17,15 +17,10 @@ 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 $url;
- /** @var IL10N|MockObject */
- protected $l;
+ protected IFactory&MockObject $factory;
+ protected IURLGenerator&MockObject $url;
+ protected IL10N&MockObject $l;
+ protected Notifier $notifier;
protected function setUp(): void {
parent::setUp();
@@ -52,7 +47,7 @@ class NotifierTest extends TestCase {
public function testPrepareWrongApp(): void {
$this->expectException(\InvalidArgumentException::class);
- /** @var INotification|\PHPUnit\Framework\MockObject\MockObject $notification */
+ /** @var INotification|MockObject $notification */
$notification = $this->createMock(INotification::class);
$notification->expects($this->once())
->method('getApp')
@@ -67,7 +62,7 @@ class NotifierTest extends TestCase {
public function testPrepareWrongSubject(): void {
$this->expectException(\InvalidArgumentException::class);
- /** @var INotification|\PHPUnit\Framework\MockObject\MockObject $notification */
+ /** @var INotification|MockObject $notification */
$notification = $this->createMock(INotification::class);
$notification->expects($this->once())
->method('getApp')
@@ -80,7 +75,7 @@ class NotifierTest extends TestCase {
}
public function testPrepare(): void {
- /** @var INotification|\PHPUnit\Framework\MockObject\MockObject $notification */
+ /** @var INotification&MockObject $notification */
$notification = $this->createMock(INotification::class);
$notification->expects($this->once())
diff --git a/apps/twofactor_backupcodes/tests/Unit/Service/BackupCodeStorageTest.php b/apps/twofactor_backupcodes/tests/Unit/Service/BackupCodeStorageTest.php
index 67124a7a928..069e50b71fd 100644
--- a/apps/twofactor_backupcodes/tests/Unit/Service/BackupCodeStorageTest.php
+++ b/apps/twofactor_backupcodes/tests/Unit/Service/BackupCodeStorageTest.php
@@ -16,24 +16,15 @@ use OCP\EventDispatcher\IEventDispatcher;
use OCP\IUser;
use OCP\Security\IHasher;
use OCP\Security\ISecureRandom;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class BackupCodeStorageTest extends TestCase {
-
- /** @var BackupCodeMapper|\PHPUnit\Framework\MockObject\MockObject */
- private $mapper;
-
- /** @var ISecureRandom|\PHPUnit\Framework\MockObject\MockObject */
- private $random;
-
- /** @var IHasher|\PHPUnit\Framework\MockObject\MockObject */
- private $hasher;
-
- /** @var IEventDispatcher|\PHPUnit\Framework\MockObject\MockObject */
- private $eventDispatcher;
-
- /** @var BackupCodeStorage */
- private $storage;
+ private BackupCodeMapper&MockObject $mapper;
+ private ISecureRandom&MockObject $random;
+ private IHasher&MockObject $hasher;
+ private IEventDispatcher&MockObject $eventDispatcher;
+ private BackupCodeStorage $storage;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/updatenotification/composer/autoload.php b/apps/updatenotification/composer/autoload.php
index 36afdad067f..a1e9eceb11c 100644
--- a/apps/updatenotification/composer/autoload.php
+++ b/apps/updatenotification/composer/autoload.php
@@ -14,10 +14,7 @@ if (PHP_VERSION_ID < 50600) {
echo $err;
}
}
- trigger_error(
- $err,
- E_USER_ERROR
- );
+ throw new RuntimeException($err);
}
require_once __DIR__ . '/composer/autoload_real.php';
diff --git a/apps/updatenotification/composer/composer/autoload_classmap.php b/apps/updatenotification/composer/composer/autoload_classmap.php
index 4aa401f661e..a03003ef3b2 100644
--- a/apps/updatenotification/composer/composer/autoload_classmap.php
+++ b/apps/updatenotification/composer/composer/autoload_classmap.php
@@ -18,7 +18,6 @@ return array(
'OCA\\UpdateNotification\\Listener\\AppUpdateEventListener' => $baseDir . '/../lib/Listener/AppUpdateEventListener.php',
'OCA\\UpdateNotification\\Listener\\BeforeTemplateRenderedEventListener' => $baseDir . '/../lib/Listener/BeforeTemplateRenderedEventListener.php',
'OCA\\UpdateNotification\\Manager' => $baseDir . '/../lib/Manager.php',
- 'OCA\\UpdateNotification\\Migration\\Version011901Date20240305120000' => $baseDir . '/../lib/Migration/Version011901Date20240305120000.php',
'OCA\\UpdateNotification\\Notification\\AppUpdateNotifier' => $baseDir . '/../lib/Notification/AppUpdateNotifier.php',
'OCA\\UpdateNotification\\Notification\\Notifier' => $baseDir . '/../lib/Notification/Notifier.php',
'OCA\\UpdateNotification\\ResponseDefinitions' => $baseDir . '/../lib/ResponseDefinitions.php',
diff --git a/apps/updatenotification/composer/composer/autoload_static.php b/apps/updatenotification/composer/composer/autoload_static.php
index 9e1fdd09def..57eedf5e075 100644
--- a/apps/updatenotification/composer/composer/autoload_static.php
+++ b/apps/updatenotification/composer/composer/autoload_static.php
@@ -33,7 +33,6 @@ class ComposerStaticInitUpdateNotification
'OCA\\UpdateNotification\\Listener\\AppUpdateEventListener' => __DIR__ . '/..' . '/../lib/Listener/AppUpdateEventListener.php',
'OCA\\UpdateNotification\\Listener\\BeforeTemplateRenderedEventListener' => __DIR__ . '/..' . '/../lib/Listener/BeforeTemplateRenderedEventListener.php',
'OCA\\UpdateNotification\\Manager' => __DIR__ . '/..' . '/../lib/Manager.php',
- 'OCA\\UpdateNotification\\Migration\\Version011901Date20240305120000' => __DIR__ . '/..' . '/../lib/Migration/Version011901Date20240305120000.php',
'OCA\\UpdateNotification\\Notification\\AppUpdateNotifier' => __DIR__ . '/..' . '/../lib/Notification/AppUpdateNotifier.php',
'OCA\\UpdateNotification\\Notification\\Notifier' => __DIR__ . '/..' . '/../lib/Notification/Notifier.php',
'OCA\\UpdateNotification\\ResponseDefinitions' => __DIR__ . '/..' . '/../lib/ResponseDefinitions.php',
diff --git a/apps/updatenotification/lib/AppInfo/Application.php b/apps/updatenotification/lib/AppInfo/Application.php
index d34429e9e73..56012667bb4 100644
--- a/apps/updatenotification/lib/AppInfo/Application.php
+++ b/apps/updatenotification/lib/AppInfo/Application.php
@@ -73,7 +73,7 @@ class Application extends App implements IBootstrap {
}
if ($updateChecker->getUpdateState() !== []) {
- Util::addScript('updatenotification', 'update-notification-legacy');
+ Util::addScript(self::APP_NAME, 'update-notification-legacy');
$updateChecker->setInitialState();
}
}
diff --git a/apps/updatenotification/lib/BackgroundJob/UpdateAvailableNotifications.php b/apps/updatenotification/lib/BackgroundJob/UpdateAvailableNotifications.php
index 29bd5cb1426..8879bb0c223 100644
--- a/apps/updatenotification/lib/BackgroundJob/UpdateAvailableNotifications.php
+++ b/apps/updatenotification/lib/BackgroundJob/UpdateAvailableNotifications.php
@@ -10,6 +10,7 @@ namespace OCA\UpdateNotification\BackgroundJob;
use OC\Installer;
use OC\Updater\VersionCheck;
+use OCA\UpdateNotification\AppInfo\Application;
use OCP\App\IAppManager;
use OCP\AppFramework\Services\IAppConfig;
use OCP\AppFramework\Utility\ITimeFactory;
@@ -21,10 +22,15 @@ use OCP\Notification\IManager;
use OCP\ServerVersion;
class UpdateAvailableNotifications extends TimedJob {
- protected $connectionNotifications = [3, 7, 14, 30];
- /** @var string[] */
- protected $users;
+ /**
+ * Numbers of failed updater connection to report error as notification.
+ * @var list<int>
+ */
+ protected const CONNECTION_NOTIFICATIONS = [3, 7, 14, 30];
+
+ /** @var ?string[] */
+ protected $users = null;
public function __construct(
ITimeFactory $timeFactory,
@@ -66,7 +72,7 @@ class UpdateAvailableNotifications extends TimedJob {
/**
* Check for Nextcloud server update
*/
- protected function checkCoreUpdate() {
+ protected function checkCoreUpdate(): void {
if (!$this->config->getSystemValueBool('updatechecker', true)) {
// update checker is disabled so no core update check!
return;
@@ -82,7 +88,7 @@ class UpdateAvailableNotifications extends TimedJob {
$errors = 1 + $this->appConfig->getAppValueInt('update_check_errors', 0);
$this->appConfig->setAppValueInt('update_check_errors', $errors);
- if (\in_array($errors, $this->connectionNotifications, true)) {
+ if (\in_array($errors, self::CONNECTION_NOTIFICATIONS, true)) {
$this->sendErrorNotifications($errors);
}
} elseif (\is_array($status)) {
@@ -99,14 +105,14 @@ class UpdateAvailableNotifications extends TimedJob {
* Send a message to the admin when the update server could not be reached
* @param int $numDays
*/
- protected function sendErrorNotifications($numDays) {
+ protected function sendErrorNotifications($numDays): void {
$this->clearErrorNotifications();
$notification = $this->notificationManager->createNotification();
try {
- $notification->setApp('updatenotification')
+ $notification->setApp(Application::APP_NAME)
->setDateTime(new \DateTime())
- ->setObject('updatenotification', 'error')
+ ->setObject(Application::APP_NAME, 'error')
->setSubject('connection_error', ['days' => $numDays]);
foreach ($this->getUsersToNotify() as $uid) {
@@ -121,12 +127,12 @@ class UpdateAvailableNotifications extends TimedJob {
/**
* Remove error notifications again
*/
- protected function clearErrorNotifications() {
+ protected function clearErrorNotifications(): void {
$notification = $this->notificationManager->createNotification();
try {
- $notification->setApp('updatenotification')
+ $notification->setApp(Application::APP_NAME)
->setSubject('connection_error')
- ->setObject('updatenotification', 'error');
+ ->setObject(Application::APP_NAME, 'error');
} catch (\InvalidArgumentException $e) {
return;
}
@@ -136,7 +142,7 @@ class UpdateAvailableNotifications extends TimedJob {
/**
* Check all installed apps for updates
*/
- protected function checkAppUpdates() {
+ protected function checkAppUpdates(): void {
$apps = $this->appManager->getEnabledApps();
foreach ($apps as $app) {
$update = $this->isUpdateAvailable($app);
@@ -153,7 +159,7 @@ class UpdateAvailableNotifications extends TimedJob {
* @param string $version
* @param string $visibleVersion
*/
- protected function createNotifications($app, $version, $visibleVersion = '') {
+ protected function createNotifications($app, $version, $visibleVersion = ''): void {
$lastNotification = $this->appConfig->getAppValueString($app, '');
if ($lastNotification === $version) {
// We already notified about this update
@@ -167,7 +173,7 @@ class UpdateAvailableNotifications extends TimedJob {
$notification = $this->notificationManager->createNotification();
try {
- $notification->setApp('updatenotification')
+ $notification->setApp(Application::APP_NAME)
->setDateTime(new \DateTime())
->setObject($app, $version);
@@ -217,12 +223,12 @@ class UpdateAvailableNotifications extends TimedJob {
* @param string $app
* @param string $version
*/
- protected function deleteOutdatedNotifications($app, $version) {
+ protected function deleteOutdatedNotifications($app, $version): void {
$notification = $this->notificationManager->createNotification();
try {
- $notification->setApp('updatenotification')
+ $notification->setApp(Application::APP_NAME)
->setObject($app, $version);
- } catch (\InvalidArgumentException $e) {
+ } catch (\InvalidArgumentException) {
return;
}
$this->notificationManager->markProcessed($notification);
diff --git a/apps/updatenotification/lib/Command/Check.php b/apps/updatenotification/lib/Command/Check.php
index c7de570cd2c..d93e4935012 100644
--- a/apps/updatenotification/lib/Command/Check.php
+++ b/apps/updatenotification/lib/Command/Check.php
@@ -17,24 +17,12 @@ use Symfony\Component\Console\Output\OutputInterface;
class Check extends Command {
- /**
- * @var Installer $installer
- */
- private $installer;
-
- /**
- * @var AppManager $appManager
- */
- private $appManager;
-
public function __construct(
- AppManager $appManager,
+ private AppManager $appManager,
private UpdateChecker $updateChecker,
- Installer $installer,
+ private Installer $installer,
) {
parent::__construct();
- $this->installer = $installer;
- $this->appManager = $appManager;
}
protected function configure(): void {
diff --git a/apps/updatenotification/lib/Controller/APIController.php b/apps/updatenotification/lib/Controller/APIController.php
index c96a5101e0f..4360d814dd2 100644
--- a/apps/updatenotification/lib/Controller/APIController.php
+++ b/apps/updatenotification/lib/Controller/APIController.php
@@ -26,8 +26,7 @@ use OCP\L10N\IFactory;
*/
class APIController extends OCSController {
- /** @var string */
- protected $language;
+ protected ?string $language = null;
/**
* List of apps that were in the appstore but are now shipped and don't have
@@ -95,7 +94,7 @@ class APIController extends OCSController {
$this->appFetcher->setVersion($newVersion, 'future-apps.json', false);
// Apps available on the app store for that version
- $availableApps = array_map(static function (array $app) {
+ $availableApps = array_map(static function (array $app): string {
return $app['id'];
}, $this->appFetcher->get());
@@ -106,8 +105,6 @@ class APIController extends OCSController {
], Http::STATUS_NOT_FOUND);
}
- $this->language = $this->l10nFactory->getUserLanguage($this->userSession->getUser());
-
// Ignore apps that are deployed from git
$installedApps = array_filter($installedApps, function (string $appId) {
try {
@@ -139,14 +136,20 @@ class APIController extends OCSController {
*/
protected function getAppDetails(string $appId): array {
$app = $this->appManager->getAppInfo($appId, false, $this->language);
- /** @var ?string $name */
- $name = $app['name'];
+ $name = $app['name'] ?? $appId;
return [
'appId' => $appId,
- 'appName' => $name ?? $appId,
+ 'appName' => $name,
];
}
+ protected function getLanguage(): string {
+ if ($this->language === null) {
+ $this->language = $this->l10nFactory->getUserLanguage($this->userSession->getUser());
+ }
+ return $this->language;
+ }
+
/**
* Get changelog entry for an app
*
diff --git a/apps/updatenotification/lib/Controller/AdminController.php b/apps/updatenotification/lib/Controller/AdminController.php
index 6e7f9935d93..26745948890 100644
--- a/apps/updatenotification/lib/Controller/AdminController.php
+++ b/apps/updatenotification/lib/Controller/AdminController.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\UpdateNotification\Controller;
@@ -36,8 +37,8 @@ class AdminController extends Controller {
parent::__construct($appName, $request);
}
- private function isUpdaterEnabled() {
- return !$this->config->getSystemValue('upgrade.disable-web', false);
+ private function isUpdaterEnabled(): bool {
+ return !$this->config->getSystemValueBool('upgrade.disable-web');
}
/**
diff --git a/apps/updatenotification/lib/Manager.php b/apps/updatenotification/lib/Manager.php
index b6f455f93fe..ebc1c83a9b4 100644
--- a/apps/updatenotification/lib/Manager.php
+++ b/apps/updatenotification/lib/Manager.php
@@ -73,7 +73,7 @@ class Manager {
/**
* Retrieve a log entry from the changelog
- * @param string $path The path to the changlog file
+ * @param string $path The path to the changelog file
* @param string $version The version to query (make sure to only pass in "{major}.{minor}(.{patch}" format)
*/
protected function retrieveChangelogEntry(string $path, string $version): ?string {
diff --git a/apps/updatenotification/lib/Migration/Version011901Date20240305120000.php b/apps/updatenotification/lib/Migration/Version011901Date20240305120000.php
deleted file mode 100644
index 6c608df313d..00000000000
--- a/apps/updatenotification/lib/Migration/Version011901Date20240305120000.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\UpdateNotification\Migration;
-
-use OCA\UpdateNotification\BackgroundJob\ResetToken;
-use OCA\UpdateNotification\Notification\BackgroundJob;
-use OCA\UpdateNotification\ResetTokenBackgroundJob;
-use OCP\BackgroundJob\IJobList;
-use OCP\Migration\IOutput;
-use OCP\Migration\SimpleMigrationStep;
-
-/**
- * Drop this with Nextcloud 30
- */
-class Version011901Date20240305120000 extends SimpleMigrationStep {
-
- public function __construct(
- private IJobList $joblist,
- ) {
- }
-
- public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options): void {
- /**
- * Remove and replace the reset-updater-token background job
- * This class was renamed so it is now unknow but we still need to remove it
- * @psalm-suppress UndefinedClass, InvalidArgument
- */
- $hasOldResetToken = $this->joblist->has(ResetTokenBackgroundJob::class, null);
- $hasNewResetToken = $this->joblist->has(ResetToken::class, null);
- if ($hasOldResetToken) {
- /**
- * @psalm-suppress UndefinedClass, InvalidArgument
- */
- $this->joblist->remove(ResetTokenBackgroundJob::class);
- if (!$hasNewResetToken) {
- $this->joblist->add(ResetToken::class);
- }
- }
-
- /**
- * Remove the "has updates" background job, the new one is automatically started from the info.xml
- * @psalm-suppress UndefinedClass, InvalidArgument
- */
- if ($this->joblist->has(BackgroundJob::class, null)) {
- /**
- * @psalm-suppress UndefinedClass, InvalidArgument
- */
- $this->joblist->remove(BackgroundJob::class);
- }
- }
-}
diff --git a/apps/updatenotification/lib/Notification/Notifier.php b/apps/updatenotification/lib/Notification/Notifier.php
index 8ce6bfc2d3d..787675bd98d 100644
--- a/apps/updatenotification/lib/Notification/Notifier.php
+++ b/apps/updatenotification/lib/Notification/Notifier.php
@@ -8,8 +8,9 @@ declare(strict_types=1);
*/
namespace OCA\UpdateNotification\Notification;
+use OCA\UpdateNotification\AppInfo\Application;
use OCP\App\IAppManager;
-use OCP\IConfig;
+use OCP\AppFramework\Services\IAppConfig;
use OCP\IGroupManager;
use OCP\IURLGenerator;
use OCP\IUser;
@@ -28,17 +29,10 @@ class Notifier implements INotifier {
/**
* Notifier constructor.
- *
- * @param IURLGenerator $url
- * @param IConfig $config
- * @param IManager $notificationManager
- * @param IFactory $l10NFactory
- * @param IUserSession $userSession
- * @param IGroupManager $groupManager
*/
public function __construct(
protected IURLGenerator $url,
- protected IConfig $config,
+ protected IAppConfig $appConfig,
protected IManager $notificationManager,
protected IFactory $l10NFactory,
protected IUserSession $userSession,
@@ -56,7 +50,7 @@ class Notifier implements INotifier {
* @since 17.0.0
*/
public function getID(): string {
- return 'updatenotification';
+ return Application::APP_NAME;
}
/**
@@ -66,7 +60,7 @@ class Notifier implements INotifier {
* @since 17.0.0
*/
public function getName(): string {
- return $this->l10NFactory->get('updatenotification')->t('Update notifications');
+ return $this->l10NFactory->get(Application::APP_NAME)->t('Update notifications');
}
/**
@@ -78,7 +72,7 @@ class Notifier implements INotifier {
* @since 9.0.0
*/
public function prepare(INotification $notification, string $languageCode): INotification {
- if ($notification->getApp() !== 'updatenotification') {
+ if ($notification->getApp() !== Application::APP_NAME) {
throw new UnknownNotificationException('Unknown app id');
}
@@ -86,9 +80,9 @@ class Notifier implements INotifier {
throw new UnknownNotificationException('Unknown subject');
}
- $l = $this->l10NFactory->get('updatenotification', $languageCode);
+ $l = $this->l10NFactory->get(Application::APP_NAME, $languageCode);
if ($notification->getSubject() === 'connection_error') {
- $errors = (int)$this->config->getAppValue('updatenotification', 'update_check_errors', '0');
+ $errors = $this->appConfig->getAppValueInt('update_check_errors', 0);
if ($errors === 0) {
throw new AlreadyProcessedException();
}
@@ -133,7 +127,7 @@ class Notifier implements INotifier {
}
}
- $notification->setIcon($this->url->getAbsoluteURL($this->url->imagePath('updatenotification', 'notification.svg')));
+ $notification->setIcon($this->url->getAbsoluteURL($this->url->imagePath(Application::APP_NAME, 'notification.svg')));
return $notification;
}
diff --git a/apps/updatenotification/lib/Settings/Admin.php b/apps/updatenotification/lib/Settings/Admin.php
index dfd4de4180f..22228f1bccc 100644
--- a/apps/updatenotification/lib/Settings/Admin.php
+++ b/apps/updatenotification/lib/Settings/Admin.php
@@ -8,6 +8,7 @@ declare(strict_types=1);
*/
namespace OCA\UpdateNotification\Settings;
+use OCA\UpdateNotification\AppInfo\Application;
use OCA\UpdateNotification\UpdateChecker;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState;
@@ -17,9 +18,9 @@ use OCP\IDateTimeFormatter;
use OCP\IGroupManager;
use OCP\IUserManager;
use OCP\L10N\IFactory;
+use OCP\ServerVersion;
use OCP\Settings\ISettings;
use OCP\Support\Subscription\IRegistry;
-use OCP\Util;
use Psr\Log\LoggerInterface;
class Admin implements ISettings {
@@ -34,6 +35,7 @@ class Admin implements ISettings {
private IUserManager $userManager,
private LoggerInterface $logger,
private IInitialState $initialState,
+ private ServerVersion $serverVersion,
) {
}
@@ -47,14 +49,14 @@ class Admin implements ISettings {
'stable',
'production',
];
- $currentChannel = Util::getChannel();
+ $currentChannel = $this->serverVersion->getChannel();
if ($currentChannel === 'git') {
$channels[] = 'git';
}
$updateState = $this->updateChecker->getUpdateState();
- $notifyGroups = json_decode($this->config->getAppValue('updatenotification', 'notify_groups', '["admin"]'), true);
+ $notifyGroups = $this->appConfig->getValueArray(Application::APP_NAME, 'notify_groups', ['admin']);
$defaultUpdateServerURL = 'https://updates.nextcloud.com/updater_server/';
$updateServerURL = $this->config->getSystemValue('updater.server.url', $defaultUpdateServerURL);
@@ -112,7 +114,7 @@ class Admin implements ISettings {
}
/**
- * @param list<string> $groupIds
+ * @param string[] $groupIds
* @return list<array{id: string, displayname: string}>
*/
protected function getSelectedGroups(array $groupIds): array {
diff --git a/apps/updatenotification/lib/UpdateChecker.php b/apps/updatenotification/lib/UpdateChecker.php
index 76afc8f6a54..b206ba4a3e4 100644
--- a/apps/updatenotification/lib/UpdateChecker.php
+++ b/apps/updatenotification/lib/UpdateChecker.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\UpdateNotification;
diff --git a/apps/updatenotification/tests/BackgroundJob/ResetTokenTest.php b/apps/updatenotification/tests/BackgroundJob/ResetTokenTest.php
index 1b0fe0cbc59..c03d4c48827 100644
--- a/apps/updatenotification/tests/BackgroundJob/ResetTokenTest.php
+++ b/apps/updatenotification/tests/BackgroundJob/ResetTokenTest.php
@@ -16,9 +16,9 @@ use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class ResetTokenTest extends TestCase {
- private IConfig|MockObject $config;
- private IAppConfig|MockObject $appConfig;
- private ITimeFactory|MockObject $timeFactory;
+ private IConfig&MockObject $config;
+ private IAppConfig&MockObject $appConfig;
+ private ITimeFactory&MockObject $timeFactory;
private BackgroundJobResetToken $resetTokenBackgroundJob;
protected function setUp(): void {
diff --git a/apps/updatenotification/tests/BackgroundJob/UpdateAvailableNotificationsTest.php b/apps/updatenotification/tests/BackgroundJob/UpdateAvailableNotificationsTest.php
index 36c1d98f2dc..51237cf012e 100644
--- a/apps/updatenotification/tests/BackgroundJob/UpdateAvailableNotificationsTest.php
+++ b/apps/updatenotification/tests/BackgroundJob/UpdateAvailableNotificationsTest.php
@@ -26,14 +26,14 @@ use Test\TestCase;
class UpdateAvailableNotificationsTest extends TestCase {
private ServerVersion&MockObject $serverVersion;
- private IConfig|MockObject $config;
- private IManager|MockObject $notificationManager;
- private IGroupManager|MockObject $groupManager;
- private IAppManager|MockObject $appManager;
- private IAppConfig|MockObject $appConfig;
- private ITimeFactory|MockObject $timeFactory;
- private Installer|MockObject $installer;
- private VersionCheck|MockObject $versionCheck;
+ private IConfig&MockObject $config;
+ private IManager&MockObject $notificationManager;
+ private IGroupManager&MockObject $groupManager;
+ private IAppManager&MockObject $appManager;
+ private IAppConfig&MockObject $appConfig;
+ private ITimeFactory&MockObject $timeFactory;
+ private Installer&MockObject $installer;
+ private VersionCheck&MockObject $versionCheck;
protected function setUp(): void {
parent::setUp();
@@ -50,10 +50,9 @@ class UpdateAvailableNotificationsTest extends TestCase {
}
/**
- * @param array $methods
* @return UpdateAvailableNotifications|MockObject
*/
- protected function getJob(array $methods = []) {
+ protected function getJob(array $methods = []): UpdateAvailableNotifications {
if (empty($methods)) {
return new UpdateAvailableNotifications(
$this->timeFactory,
@@ -125,7 +124,7 @@ class UpdateAvailableNotificationsTest extends TestCase {
self::invokePrivate($job, 'run', [null]);
}
- public function dataCheckCoreUpdate(): array {
+ public static function dataCheckCoreUpdate(): array {
return [
['daily', null, null, null, null],
['git', null, null, null, null],
@@ -155,14 +154,8 @@ class UpdateAvailableNotificationsTest extends TestCase {
/**
* @dataProvider dataCheckCoreUpdate
- *
- * @param string $channel
- * @param mixed $versionCheck
- * @param null|string $version
- * @param null|string $readableVersion
- * @param null|int $errorDays
*/
- public function testCheckCoreUpdate(string $channel, $versionCheck, $version, $readableVersion, $errorDays): void {
+ public function testCheckCoreUpdate(string $channel, mixed $versionCheck, mixed $version, ?string $readableVersion, ?int $errorDays): void {
$job = $this->getJob([
'createNotifications',
'clearErrorNotifications',
@@ -223,7 +216,7 @@ class UpdateAvailableNotificationsTest extends TestCase {
self::invokePrivate($job, 'checkCoreUpdate');
}
- public function dataCheckAppUpdates(): array {
+ public static function dataCheckAppUpdates(): array {
return [
[
['app1', 'app2'],
@@ -240,10 +233,6 @@ class UpdateAvailableNotificationsTest extends TestCase {
/**
* @dataProvider dataCheckAppUpdates
- *
- * @param string[] $apps
- * @param array $isUpdateAvailable
- * @param array $notifications
*/
public function testCheckAppUpdates(array $apps, array $isUpdateAvailable, array $notifications): void {
$job = $this->getJob([
@@ -271,7 +260,7 @@ class UpdateAvailableNotificationsTest extends TestCase {
self::invokePrivate($job, 'checkAppUpdates');
}
- public function dataCreateNotifications(): array {
+ public static function dataCreateNotifications(): array {
return [
['app1', '1.0.0', '1.0.0', false, false, null, null],
['app2', '1.0.1', '1.0.0', '1.0.0', true, ['user1'], [['user1']]],
@@ -281,16 +270,8 @@ class UpdateAvailableNotificationsTest extends TestCase {
/**
* @dataProvider dataCreateNotifications
- *
- * @param string $app
- * @param string $version
- * @param string|false $lastNotification
- * @param string|false $callDelete
- * @param bool $createNotification
- * @param string[]|null $users
- * @param array|null $userNotifications
*/
- public function testCreateNotifications(string $app, string $version, $lastNotification, $callDelete, $createNotification, $users, $userNotifications): void {
+ public function testCreateNotifications(string $app, string $version, string|false $lastNotification, string|false $callDelete, bool $createNotification, ?array $users, ?array $userNotifications): void {
$job = $this->getJob([
'deleteOutdatedNotifications',
'getUsersToNotify',
@@ -363,7 +344,7 @@ class UpdateAvailableNotificationsTest extends TestCase {
self::invokePrivate($job, 'createNotifications', [$app, $version]);
}
- public function dataGetUsersToNotify(): array {
+ public static function dataGetUsersToNotify(): array {
return [
[['g1', 'g2'], ['g1' => null, 'g2' => ['u1', 'u2']], ['u1', 'u2']],
[['g3', 'g4'], ['g3' => ['u1', 'u2'], 'g4' => ['u2', 'u3']], ['u1', 'u2', 'u3']],
@@ -372,9 +353,6 @@ class UpdateAvailableNotificationsTest extends TestCase {
/**
* @dataProvider dataGetUsersToNotify
- * @param string[] $groups
- * @param array $groupUsers
- * @param string[] $expected
*/
public function testGetUsersToNotify(array $groups, array $groupUsers, array $expected): void {
$job = $this->getJob();
@@ -408,7 +386,7 @@ class UpdateAvailableNotificationsTest extends TestCase {
$this->assertEquals($expected, $result);
}
- public function dataDeleteOutdatedNotifications(): array {
+ public static function dataDeleteOutdatedNotifications(): array {
return [
['app1', '1.1.0'],
['app2', '1.2.0'],
diff --git a/apps/updatenotification/tests/Controller/AdminControllerTest.php b/apps/updatenotification/tests/Controller/AdminControllerTest.php
index 877a0276373..2263495fc14 100644
--- a/apps/updatenotification/tests/Controller/AdminControllerTest.php
+++ b/apps/updatenotification/tests/Controller/AdminControllerTest.php
@@ -22,13 +22,13 @@ use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class AdminControllerTest extends TestCase {
- private IRequest|MockObject $request;
- private IJobList|MockObject $jobList;
- private ISecureRandom|MockObject $secureRandom;
- private IConfig|MockObject $config;
- private ITimeFactory|MockObject $timeFactory;
- private IL10N|MockObject $l10n;
- private IAppConfig|MockObject $appConfig;
+ private IRequest&MockObject $request;
+ private IJobList&MockObject $jobList;
+ private ISecureRandom&MockObject $secureRandom;
+ private IConfig&MockObject $config;
+ private ITimeFactory&MockObject $timeFactory;
+ private IL10N&MockObject $l10n;
+ private IAppConfig&MockObject $appConfig;
private AdminController $adminController;
diff --git a/apps/updatenotification/tests/Notification/NotifierTest.php b/apps/updatenotification/tests/Notification/NotifierTest.php
index 45c4fc9960f..6d47d0c6b89 100644
--- a/apps/updatenotification/tests/Notification/NotifierTest.php
+++ b/apps/updatenotification/tests/Notification/NotifierTest.php
@@ -4,13 +4,14 @@ declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\UpdateNotification\Tests\Notification;
use OCA\UpdateNotification\Notification\Notifier;
use OCP\App\IAppManager;
-use OCP\IConfig;
+use OCP\AppFramework\Services\IAppConfig;
use OCP\IGroupManager;
use OCP\IURLGenerator;
use OCP\IUserSession;
@@ -25,7 +26,7 @@ use Test\TestCase;
class NotifierTest extends TestCase {
protected IURLGenerator&MockObject $urlGenerator;
- protected IConfig&MockObject $config;
+ protected IAppConfig&MockObject $appConfig;
protected IManager&MockObject $notificationManager;
protected IFactory&MockObject $l10nFactory;
protected IUserSession&MockObject $userSession;
@@ -37,7 +38,7 @@ class NotifierTest extends TestCase {
parent::setUp();
$this->urlGenerator = $this->createMock(IURLGenerator::class);
- $this->config = $this->createMock(IConfig::class);
+ $this->appConfig = $this->createMock(IAppConfig::class);
$this->notificationManager = $this->createMock(IManager::class);
$this->l10nFactory = $this->createMock(IFactory::class);
$this->userSession = $this->createMock(IUserSession::class);
@@ -48,13 +49,13 @@ class NotifierTest extends TestCase {
/**
* @param array $methods
- * @return Notifier|\PHPUnit\Framework\MockObject\MockObject
+ * @return Notifier|MockObject
*/
- protected function getNotifier(array $methods = []) {
+ protected function getNotifier(array $methods = []): Notifier {
if (empty($methods)) {
return new Notifier(
$this->urlGenerator,
- $this->config,
+ $this->appConfig,
$this->notificationManager,
$this->l10nFactory,
$this->userSession,
@@ -67,7 +68,7 @@ class NotifierTest extends TestCase {
return $this->getMockBuilder(Notifier::class)
->setConstructorArgs([
$this->urlGenerator,
- $this->config,
+ $this->appConfig,
$this->notificationManager,
$this->l10nFactory,
$this->userSession,
@@ -80,7 +81,7 @@ class NotifierTest extends TestCase {
}
}
- public function dataUpdateAlreadyInstalledCheck(): array {
+ public static function dataUpdateAlreadyInstalledCheck(): array {
return [
['1.1.0', '1.0.0', false],
['1.1.0', '1.1.0', true],
@@ -90,10 +91,6 @@ class NotifierTest extends TestCase {
/**
* @dataProvider dataUpdateAlreadyInstalledCheck
- *
- * @param string $versionNotification
- * @param string $versionInstalled
- * @param bool $exception
*/
public function testUpdateAlreadyInstalledCheck(string $versionNotification, string $versionInstalled, bool $exception): void {
$notifier = $this->getNotifier();
diff --git a/apps/updatenotification/tests/Settings/AdminTest.php b/apps/updatenotification/tests/Settings/AdminTest.php
index 3652c8f9081..cb815bc8b69 100644
--- a/apps/updatenotification/tests/Settings/AdminTest.php
+++ b/apps/updatenotification/tests/Settings/AdminTest.php
@@ -4,10 +4,12 @@ declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\UpdateNotification\Tests\Settings;
+use OCA\UpdateNotification\AppInfo\Application;
use OCA\UpdateNotification\Settings\Admin;
use OCA\UpdateNotification\UpdateChecker;
use OCP\AppFramework\Http\TemplateResponse;
@@ -20,34 +22,25 @@ use OCP\IGroupManager;
use OCP\IUserManager;
use OCP\L10N\IFactory;
use OCP\L10N\ILanguageIterator;
+use OCP\ServerVersion;
use OCP\Support\Subscription\IRegistry;
-use OCP\Util;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Test\TestCase;
class AdminTest extends TestCase {
- /** @var IFactory|\PHPUnit\Framework\MockObject\MockObject */
- protected $l10nFactory;
- /** @var Admin */
- private $admin;
- /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
- private $config;
- /** @var IAppConfig|\PHPUnit\Framework\MockObject\MockObject */
- private $appConfig;
- /** @var UpdateChecker|\PHPUnit\Framework\MockObject\MockObject */
- private $updateChecker;
- /** @var IGroupManager|\PHPUnit\Framework\MockObject\MockObject */
- private $groupManager;
- /** @var IDateTimeFormatter|\PHPUnit\Framework\MockObject\MockObject */
- private $dateTimeFormatter;
- /** @var IRegistry|\PHPUnit\Framework\MockObject\MockObject */
- private $subscriptionRegistry;
- /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
- private $userManager;
- /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
- private $logger;
- /** IInitialState|\PHPUnit\Framework\MockObject\MockObject */
- private $initialState;
+ private IFactory&MockObject $l10nFactory;
+ private IConfig&MockObject $config;
+ private IAppConfig&MockObject $appConfig;
+ private UpdateChecker&MockObject $updateChecker;
+ private IGroupManager&MockObject $groupManager;
+ private IDateTimeFormatter&MockObject $dateTimeFormatter;
+ private IRegistry&MockObject $subscriptionRegistry;
+ private IUserManager&MockObject $userManager;
+ private LoggerInterface&MockObject $logger;
+ private IInitialState&MockObject $initialState;
+ private ServerVersion&MockObject $serverVersion;
+ private Admin $admin;
protected function setUp(): void {
parent::setUp();
@@ -62,6 +55,7 @@ class AdminTest extends TestCase {
$this->userManager = $this->createMock(IUserManager::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->initialState = $this->createMock(IInitialState::class);
+ $this->serverVersion = $this->createMock(ServerVersion::class);
$this->admin = new Admin(
$this->config,
@@ -73,11 +67,15 @@ class AdminTest extends TestCase {
$this->subscriptionRegistry,
$this->userManager,
$this->logger,
- $this->initialState
+ $this->initialState,
+ $this->serverVersion,
);
}
public function testGetFormWithUpdate(): void {
+ $this->serverVersion->expects(self::atLeastOnce())
+ ->method('getChannel')
+ ->willReturn('daily');
$this->userManager
->expects($this->once())
->method('countUsersTotal')
@@ -88,20 +86,16 @@ class AdminTest extends TestCase {
'stable',
'production',
];
- $currentChannel = Util::getChannel();
- if ($currentChannel === 'git') {
- $channels[] = 'git';
- }
$this->appConfig
->expects($this->once())
->method('getValueInt')
->with('core', 'lastupdatedat', 0)
->willReturn(12345);
- $this->config
+ $this->appConfig
->expects($this->once())
- ->method('getAppValue')
- ->with('updatenotification', 'notify_groups', '["admin"]')
- ->willReturn('["admin"]');
+ ->method('getValueArray')
+ ->with(Application::APP_NAME, 'notify_groups', ['admin'])
+ ->willReturn(['admin']);
$this->config
->method('getSystemValue')
->willReturnMap([
@@ -154,7 +148,7 @@ class AdminTest extends TestCase {
'isNewVersionAvailable' => true,
'isUpdateChecked' => true,
'lastChecked' => 'LastCheckedReturnValue',
- 'currentChannel' => Util::getChannel(),
+ 'currentChannel' => 'daily',
'channels' => $channels,
'newVersion' => '8.1.2',
'newVersionString' => 'Nextcloud 8.1.2',
@@ -172,11 +166,14 @@ class AdminTest extends TestCase {
'hasValidSubscription' => true,
]);
- $expected = new TemplateResponse('updatenotification', 'admin', [], '');
+ $expected = new TemplateResponse(Application::APP_NAME, 'admin', [], '');
$this->assertEquals($expected, $this->admin->getForm());
}
public function testGetFormWithUpdateAndChangedUpdateServer(): void {
+ $this->serverVersion->expects(self::atLeastOnce())
+ ->method('getChannel')
+ ->willReturn('beta');
$this->userManager
->expects($this->once())
->method('countUsersTotal')
@@ -187,10 +184,6 @@ class AdminTest extends TestCase {
'stable',
'production',
];
- $currentChannel = Util::getChannel();
- if ($currentChannel === 'git') {
- $channels[] = 'git';
- }
$this->appConfig
->expects($this->once())
@@ -202,11 +195,11 @@ class AdminTest extends TestCase {
->method('getSystemValueBool')
->with('updatechecker', true)
->willReturn(true);
- $this->config
+ $this->appConfig
->expects($this->once())
- ->method('getAppValue')
- ->with('updatenotification', 'notify_groups', '["admin"]')
- ->willReturn('["admin"]');
+ ->method('getValueArray')
+ ->with(Application::APP_NAME, 'notify_groups', ['admin'])
+ ->willReturn(['admin']);
$this->config
->method('getSystemValue')
->willReturnMap([
@@ -254,7 +247,7 @@ class AdminTest extends TestCase {
'isNewVersionAvailable' => true,
'isUpdateChecked' => true,
'lastChecked' => 'LastCheckedReturnValue',
- 'currentChannel' => Util::getChannel(),
+ 'currentChannel' => 'beta',
'channels' => $channels,
'newVersion' => '8.1.2',
'newVersionString' => 'Nextcloud 8.1.2',
@@ -272,11 +265,14 @@ class AdminTest extends TestCase {
'hasValidSubscription' => true,
]);
- $expected = new TemplateResponse('updatenotification', 'admin', [], '');
+ $expected = new TemplateResponse(Application::APP_NAME, 'admin', [], '');
$this->assertEquals($expected, $this->admin->getForm());
}
public function testGetFormWithUpdateAndCustomersUpdateServer(): void {
+ $this->serverVersion->expects(self::atLeastOnce())
+ ->method('getChannel')
+ ->willReturn('production');
$this->userManager
->expects($this->once())
->method('countUsersTotal')
@@ -287,10 +283,6 @@ class AdminTest extends TestCase {
'stable',
'production',
];
- $currentChannel = Util::getChannel();
- if ($currentChannel === 'git') {
- $channels[] = 'git';
- }
$this->appConfig
->expects($this->once())
@@ -302,11 +294,11 @@ class AdminTest extends TestCase {
->method('getSystemValueBool')
->with('updatechecker', true)
->willReturn(true);
- $this->config
- ->expects($this->once())
- ->method('getAppValue')
- ->with('updatenotification', 'notify_groups', '["admin"]')
- ->willReturn('["admin"]');
+ $this->appConfig
+ ->expects(self::once())
+ ->method('getValueArray')
+ ->with(Application::APP_NAME, 'notify_groups', ['admin'])
+ ->willReturn(['admin']);
$this->config
->method('getSystemValue')
->willReturnMap([
@@ -354,7 +346,7 @@ class AdminTest extends TestCase {
'isNewVersionAvailable' => true,
'isUpdateChecked' => true,
'lastChecked' => 'LastCheckedReturnValue',
- 'currentChannel' => Util::getChannel(),
+ 'currentChannel' => 'production',
'channels' => $channels,
'newVersion' => '8.1.2',
'newVersionString' => 'Nextcloud 8.1.2',
@@ -372,7 +364,7 @@ class AdminTest extends TestCase {
'hasValidSubscription' => true,
]);
- $expected = new TemplateResponse('updatenotification', 'admin', [], '');
+ $expected = new TemplateResponse(Application::APP_NAME, 'admin', [], '');
$this->assertEquals($expected, $this->admin->getForm());
}
@@ -401,7 +393,7 @@ class AdminTest extends TestCase {
$this->assertSame(11, $this->admin->getPriority());
}
- public function changesProvider() {
+ public static function changesProvider(): array {
return [
[ #0, all info, en
[
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index f97867e98d4..1dff026e7d8 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -515,7 +515,7 @@ class User {
* fetch all the user's attributes in one call and use the fetched values in this function.
* The expected value for that parameter is a string describing the quota for the user. Valid
* values are 'none' (unlimited), 'default' (the Nextcloud's default quota), '1234' (quota in
- * bytes), '1234 MB' (quota in MB - check the \OC_Helper::computerFileSize method for more info)
+ * bytes), '1234 MB' (quota in MB - check the \OCP\Util::computerFileSize method for more info)
*
* fetches the quota from LDAP and stores it as Nextcloud user value
* @param ?string $valueFromLDAP the quota attribute's value can be passed,
@@ -563,7 +563,7 @@ class User {
}
private function verifyQuotaValue(string $quotaValue): bool {
- return $quotaValue === 'none' || $quotaValue === 'default' || \OC_Helper::computerFileSize($quotaValue) !== false;
+ return $quotaValue === 'none' || $quotaValue === 'default' || Util::computerFileSize($quotaValue) !== false;
}
/**
diff --git a/apps/user_status/tests/Unit/BackgroundJob/ClearOldStatusesBackgroundJobTest.php b/apps/user_status/tests/Unit/BackgroundJob/ClearOldStatusesBackgroundJobTest.php
index 90c85bcdaac..66142082343 100644
--- a/apps/user_status/tests/Unit/BackgroundJob/ClearOldStatusesBackgroundJobTest.php
+++ b/apps/user_status/tests/Unit/BackgroundJob/ClearOldStatusesBackgroundJobTest.php
@@ -11,18 +11,13 @@ namespace OCA\UserStatus\Tests\BackgroundJob;
use OCA\UserStatus\BackgroundJob\ClearOldStatusesBackgroundJob;
use OCA\UserStatus\Db\UserStatusMapper;
use OCP\AppFramework\Utility\ITimeFactory;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class ClearOldStatusesBackgroundJobTest extends TestCase {
-
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
- private $time;
-
- /** @var UserStatusMapper|\PHPUnit\Framework\MockObject\MockObject */
- private $mapper;
-
- /** @var ClearOldStatusesBackgroundJob */
- private $job;
+ private ITimeFactory&MockObject $time;
+ private UserStatusMapper&MockObject $mapper;
+ private ClearOldStatusesBackgroundJob $job;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/user_status/tests/Unit/CapabilitiesTest.php b/apps/user_status/tests/Unit/CapabilitiesTest.php
index 9e72d49fe31..ef721eaa90b 100644
--- a/apps/user_status/tests/Unit/CapabilitiesTest.php
+++ b/apps/user_status/tests/Unit/CapabilitiesTest.php
@@ -10,15 +10,12 @@ namespace OCA\UserStatus\Tests;
use OCA\UserStatus\Capabilities;
use OCP\IEmojiHelper;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class CapabilitiesTest extends TestCase {
-
- /** @var IEmojiHelper|\PHPUnit\Framework\MockObject\MockObject */
- private $emojiHelper;
-
- /** @var Capabilities */
- private $capabilities;
+ private IEmojiHelper&MockObject $emojiHelper;
+ private Capabilities $capabilities;
protected function setUp(): void {
parent::setUp();
@@ -28,8 +25,6 @@ class CapabilitiesTest extends TestCase {
}
/**
- * @param bool $supportsEmojis
- *
* @dataProvider getCapabilitiesDataProvider
*/
public function testGetCapabilities(bool $supportsEmojis): void {
@@ -46,7 +41,7 @@ class CapabilitiesTest extends TestCase {
], $this->capabilities->getCapabilities());
}
- public function getCapabilitiesDataProvider(): array {
+ public static function getCapabilitiesDataProvider(): array {
return [
[true],
[false],
diff --git a/apps/user_status/tests/Unit/Connector/UserStatusProviderTest.php b/apps/user_status/tests/Unit/Connector/UserStatusProviderTest.php
index 7e2da883af4..df6c55488d5 100644
--- a/apps/user_status/tests/Unit/Connector/UserStatusProviderTest.php
+++ b/apps/user_status/tests/Unit/Connector/UserStatusProviderTest.php
@@ -11,15 +11,12 @@ namespace OCA\UserStatus\Tests\Connector;
use OCA\UserStatus\Connector\UserStatusProvider;
use OCA\UserStatus\Db\UserStatus;
use OCA\UserStatus\Service\StatusService;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class UserStatusProviderTest extends TestCase {
-
- /** @var \PHPUnit\Framework\MockObject\MockObject */
- private $service;
-
- /** @var UserStatusProvider */
- private $provider;
+ private StatusService&MockObject $service;
+ private UserStatusProvider $provider;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/user_status/tests/Unit/Controller/PredefinedStatusControllerTest.php b/apps/user_status/tests/Unit/Controller/PredefinedStatusControllerTest.php
index 5709cdc89cf..0f96f41a524 100644
--- a/apps/user_status/tests/Unit/Controller/PredefinedStatusControllerTest.php
+++ b/apps/user_status/tests/Unit/Controller/PredefinedStatusControllerTest.php
@@ -11,15 +11,12 @@ namespace OCA\UserStatus\Tests\Controller;
use OCA\UserStatus\Controller\PredefinedStatusController;
use OCA\UserStatus\Service\PredefinedStatusService;
use OCP\IRequest;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class PredefinedStatusControllerTest extends TestCase {
-
- /** @var PredefinedStatusService|\PHPUnit\Framework\MockObject\MockObject */
- private $service;
-
- /** @var PredefinedStatusController */
- private $controller;
+ private PredefinedStatusService&MockObject $service;
+ private PredefinedStatusController $controller;
protected function setUp(): void {
parent::setUp();
@@ -27,8 +24,7 @@ class PredefinedStatusControllerTest extends TestCase {
$request = $this->createMock(IRequest::class);
$this->service = $this->createMock(PredefinedStatusService::class);
- $this->controller = new PredefinedStatusController('user_status', $request,
- $this->service);
+ $this->controller = new PredefinedStatusController('user_status', $request, $this->service);
}
public function testFindAll(): void {
diff --git a/apps/user_status/tests/Unit/Controller/StatusesControllerTest.php b/apps/user_status/tests/Unit/Controller/StatusesControllerTest.php
index fe3e1c56a7e..76d337879c3 100644
--- a/apps/user_status/tests/Unit/Controller/StatusesControllerTest.php
+++ b/apps/user_status/tests/Unit/Controller/StatusesControllerTest.php
@@ -14,15 +14,12 @@ use OCA\UserStatus\Service\StatusService;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\OCS\OCSNotFoundException;
use OCP\IRequest;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class StatusesControllerTest extends TestCase {
-
- /** @var StatusService|\PHPUnit\Framework\MockObject\MockObject */
- private $service;
-
- /** @var StatusesController */
- private $controller;
+ private StatusService&MockObject $service;
+ private StatusesController $controller;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/user_status/tests/Unit/Controller/UserStatusControllerTest.php b/apps/user_status/tests/Unit/Controller/UserStatusControllerTest.php
index 26b29bcc74c..45ee9c4fdba 100644
--- a/apps/user_status/tests/Unit/Controller/UserStatusControllerTest.php
+++ b/apps/user_status/tests/Unit/Controller/UserStatusControllerTest.php
@@ -21,22 +21,16 @@ use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\OCS\OCSBadRequestException;
use OCP\AppFramework\OCS\OCSNotFoundException;
use OCP\IRequest;
+use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Test\TestCase;
use Throwable;
class UserStatusControllerTest extends TestCase {
- /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
- private $logger;
-
- /** @var StatusService|\PHPUnit\Framework\MockObject\MockObject */
- private $statusService;
-
- /** @var CalendarStatusService|\PHPUnit\Framework\MockObject\MockObject $calendarStatusService */
- private $calendarStatusService;
-
- /** @var UserStatusController */
- private $controller;
+ private LoggerInterface&MockObject $logger;
+ private StatusService&MockObject $statusService;
+ private CalendarStatusService&MockObject $calendarStatusService;
+ private UserStatusController $controller;
protected function setUp(): void {
parent::setUp();
@@ -94,19 +88,10 @@ class UserStatusControllerTest extends TestCase {
}
/**
- * @param string $statusType
- * @param string|null $statusIcon
- * @param string|null $message
- * @param int|null $clearAt
- * @param bool $expectSuccess
- * @param bool $expectException
- * @param Throwable|null $exception
- * @param bool $expectLogger
- * @param string|null $expectedLogMessage
- *
* @dataProvider setStatusDataProvider
*/
- public function testSetStatus(string $statusType,
+ public function testSetStatus(
+ string $statusType,
?string $statusIcon,
?string $message,
?int $clearAt,
@@ -114,7 +99,8 @@ class UserStatusControllerTest extends TestCase {
bool $expectException,
?Throwable $exception,
bool $expectLogger,
- ?string $expectedLogMessage): void {
+ ?string $expectedLogMessage,
+ ): void {
$userStatus = $this->getUserStatus();
if ($expectException) {
@@ -155,7 +141,7 @@ class UserStatusControllerTest extends TestCase {
}
}
- public function setStatusDataProvider(): array {
+ public static function setStatusDataProvider(): array {
return [
['busy', '👨🏽‍💻', 'Busy developing the status feature', 500, true, false, null, false, null],
['busy', '👨🏽‍💻', 'Busy developing the status feature', 500, false, true, new InvalidStatusTypeException('Original exception message'), true,
@@ -164,23 +150,17 @@ class UserStatusControllerTest extends TestCase {
}
/**
- * @param string $messageId
- * @param int|null $clearAt
- * @param bool $expectSuccess
- * @param bool $expectException
- * @param Throwable|null $exception
- * @param bool $expectLogger
- * @param string|null $expectedLogMessage
- *
* @dataProvider setPredefinedMessageDataProvider
*/
- public function testSetPredefinedMessage(string $messageId,
+ public function testSetPredefinedMessage(
+ string $messageId,
?int $clearAt,
bool $expectSuccess,
bool $expectException,
?Throwable $exception,
bool $expectLogger,
- ?string $expectedLogMessage): void {
+ ?string $expectedLogMessage,
+ ): void {
$userStatus = $this->getUserStatus();
if ($expectException) {
@@ -221,7 +201,7 @@ class UserStatusControllerTest extends TestCase {
}
}
- public function setPredefinedMessageDataProvider(): array {
+ public static function setPredefinedMessageDataProvider(): array {
return [
['messageId-42', 500, true, false, null, false, null],
['messageId-42', 500, false, true, new InvalidClearAtException('Original exception message'), true,
@@ -232,19 +212,10 @@ class UserStatusControllerTest extends TestCase {
}
/**
- * @param string|null $statusIcon
- * @param string $message
- * @param int|null $clearAt
- * @param bool $expectSuccess
- * @param bool $expectException
- * @param Throwable|null $exception
- * @param bool $expectLogger
- * @param string|null $expectedLogMessage
- * @param bool $expectSuccessAsReset
- *
* @dataProvider setCustomMessageDataProvider
*/
- public function testSetCustomMessage(?string $statusIcon,
+ public function testSetCustomMessage(
+ ?string $statusIcon,
string $message,
?int $clearAt,
bool $expectSuccess,
@@ -252,7 +223,8 @@ class UserStatusControllerTest extends TestCase {
?Throwable $exception,
bool $expectLogger,
?string $expectedLogMessage,
- bool $expectSuccessAsReset = false): void {
+ bool $expectSuccessAsReset = false,
+ ): void {
$userStatus = $this->getUserStatus();
if ($expectException) {
@@ -308,7 +280,7 @@ class UserStatusControllerTest extends TestCase {
}
}
- public function setCustomMessageDataProvider(): array {
+ public static function setCustomMessageDataProvider(): array {
return [
['👨🏽‍💻', 'Busy developing the status feature', 500, true, false, null, false, null],
['👨🏽‍💻', '', 500, true, false, null, false, null, false],
diff --git a/apps/user_status/tests/Unit/Dashboard/UserStatusWidgetTest.php b/apps/user_status/tests/Unit/Dashboard/UserStatusWidgetTest.php
index e776837fac8..8773b04c95f 100644
--- a/apps/user_status/tests/Unit/Dashboard/UserStatusWidgetTest.php
+++ b/apps/user_status/tests/Unit/Dashboard/UserStatusWidgetTest.php
@@ -16,33 +16,18 @@ use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\IUserSession;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class UserStatusWidgetTest extends TestCase {
-
- /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
- private $l10n;
-
- /** @var IDateTimeFormatter|\PHPUnit\Framework\MockObject\MockObject */
- private $dateTimeFormatter;
-
- /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */
- private $urlGenerator;
-
- /** @var IInitialState|\PHPUnit\Framework\MockObject\MockObject */
- private $initialState;
-
- /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
- private $userManager;
-
- /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
- private $userSession;
-
- /** @var StatusService|\PHPUnit\Framework\MockObject\MockObject */
- private $service;
-
- /** @var UserStatusWidget */
- private $widget;
+ private IL10N&MockObject $l10n;
+ private IDateTimeFormatter&MockObject $dateTimeFormatter;
+ private IURLGenerator&MockObject $urlGenerator;
+ private IInitialState&MockObject $initialState;
+ private IUserManager&MockObject $userManager;
+ private IUserSession&MockObject $userSession;
+ private StatusService&MockObject $service;
+ private UserStatusWidget $widget;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/user_status/tests/Unit/Db/UserStatusMapperTest.php b/apps/user_status/tests/Unit/Db/UserStatusMapperTest.php
index 46147c6a822..c9bda492210 100644
--- a/apps/user_status/tests/Unit/Db/UserStatusMapperTest.php
+++ b/apps/user_status/tests/Unit/Db/UserStatusMapperTest.php
@@ -15,9 +15,7 @@ use OCP\DB\Exception;
use Test\TestCase;
class UserStatusMapperTest extends TestCase {
-
- /** @var UserStatusMapper */
- private $mapper;
+ private UserStatusMapper $mapper;
protected function setUp(): void {
parent::setUp();
@@ -137,11 +135,6 @@ class UserStatusMapperTest extends TestCase {
}
/**
- * @param string $status
- * @param bool $isUserDefined
- * @param int $timestamp
- * @param bool $expectsClean
- *
* @dataProvider clearStatusesOlderThanDataProvider
*/
public function testClearStatusesOlderThan(string $status, bool $isUserDefined, int $timestamp, bool $expectsClean): void {
@@ -169,7 +162,7 @@ class UserStatusMapperTest extends TestCase {
}
}
- public function clearStatusesOlderThanDataProvider(): array {
+ public static function clearStatusesOlderThanDataProvider(): array {
return [
['offline', false, 6000, false],
['online', true, 6000, false],
@@ -231,7 +224,7 @@ class UserStatusMapperTest extends TestCase {
$this->mapper->insert($userStatus3);
}
- public function dataCreateBackupStatus(): array {
+ public static function dataCreateBackupStatus(): array {
return [
[false, false, false],
[true, false, true],
@@ -242,9 +235,6 @@ class UserStatusMapperTest extends TestCase {
/**
* @dataProvider dataCreateBackupStatus
- * @param bool $hasStatus
- * @param bool $hasBackup
- * @param bool $backupCreated
*/
public function testCreateBackupStatus(bool $hasStatus, bool $hasBackup, bool $backupCreated): void {
if ($hasStatus) {
diff --git a/apps/user_status/tests/Unit/Listener/UserDeletedListenerTest.php b/apps/user_status/tests/Unit/Listener/UserDeletedListenerTest.php
index 128b5c78c48..fbcea23338d 100644
--- a/apps/user_status/tests/Unit/Listener/UserDeletedListenerTest.php
+++ b/apps/user_status/tests/Unit/Listener/UserDeletedListenerTest.php
@@ -13,15 +13,12 @@ use OCA\UserStatus\Service\StatusService;
use OCP\EventDispatcher\GenericEvent;
use OCP\IUser;
use OCP\User\Events\UserDeletedEvent;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class UserDeletedListenerTest extends TestCase {
-
- /** @var StatusService|\PHPUnit\Framework\MockObject\MockObject */
- private $service;
-
- /** @var UserDeletedListener */
- private $listener;
+ private StatusService&MockObject $service;
+ private UserDeletedListener $listener;
protected function setUp(): void {
parent::setUp();
diff --git a/apps/user_status/tests/Unit/Listener/UserLiveStatusListenerTest.php b/apps/user_status/tests/Unit/Listener/UserLiveStatusListenerTest.php
index 421cce046df..c94315a7a93 100644
--- a/apps/user_status/tests/Unit/Listener/UserLiveStatusListenerTest.php
+++ b/apps/user_status/tests/Unit/Listener/UserLiveStatusListenerTest.php
@@ -11,7 +11,6 @@ namespace OCA\UserStatus\Tests\Listener;
use OCA\DAV\CalDAV\Status\StatusService as CalendarStatusService;
use OCA\UserStatus\Db\UserStatus;
use OCA\UserStatus\Db\UserStatusMapper;
-use OCA\UserStatus\Listener\UserDeletedListener;
use OCA\UserStatus\Listener\UserLiveStatusListener;
use OCA\UserStatus\Service\StatusService;
use OCP\AppFramework\Db\DoesNotExistException;
@@ -24,20 +23,13 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class UserLiveStatusListenerTest extends TestCase {
+ private UserStatusMapper&MockObject $mapper;
+ private StatusService&MockObject $statusService;
+ private ITimeFactory&MockObject $timeFactory;
+ private CalendarStatusService&MockObject $calendarStatusService;
- /** @var UserStatusMapper|MockObject */
- private $mapper;
- /** @var StatusService|MockObject */
- private $statusService;
- /** @var ITimeFactory|MockObject */
- private $timeFactory;
-
- /** @var UserDeletedListener */
- private $listener;
-
- private CalendarStatusService|MockObject $calendarStatusService;
-
- private LoggerInterface|MockObject $logger;
+ private LoggerInterface&MockObject $logger;
+ private UserLiveStatusListener $listener;
protected function setUp(): void {
parent::setUp();
@@ -58,25 +50,18 @@ class UserLiveStatusListenerTest extends TestCase {
}
/**
- * @param string $userId
- * @param string $previousStatus
- * @param int $previousTimestamp
- * @param bool $previousIsUserDefined
- * @param string $eventStatus
- * @param int $eventTimestamp
- * @param bool $expectExisting
- * @param bool $expectUpdate
- *
* @dataProvider handleEventWithCorrectEventDataProvider
*/
- public function testHandleWithCorrectEvent(string $userId,
+ public function testHandleWithCorrectEvent(
+ string $userId,
string $previousStatus,
int $previousTimestamp,
bool $previousIsUserDefined,
string $eventStatus,
int $eventTimestamp,
bool $expectExisting,
- bool $expectUpdate): void {
+ bool $expectUpdate,
+ ): void {
$userStatus = new UserStatus();
if ($expectExisting) {
@@ -143,7 +128,7 @@ class UserLiveStatusListenerTest extends TestCase {
}
}
- public function handleEventWithCorrectEventDataProvider(): array {
+ public static function handleEventWithCorrectEventDataProvider(): array {
return [
['john.doe', 'offline', 0, false, 'online', 5000, true, true],
['john.doe', 'offline', 0, false, 'online', 5000, false, true],
diff --git a/apps/user_status/tests/Unit/Service/PredefinedStatusServiceTest.php b/apps/user_status/tests/Unit/Service/PredefinedStatusServiceTest.php
index 12b34ed0b4d..091466637f0 100644
--- a/apps/user_status/tests/Unit/Service/PredefinedStatusServiceTest.php
+++ b/apps/user_status/tests/Unit/Service/PredefinedStatusServiceTest.php
@@ -10,15 +10,12 @@ namespace OCA\UserStatus\Tests\Service;
use OCA\UserStatus\Service\PredefinedStatusService;
use OCP\IL10N;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class PredefinedStatusServiceTest extends TestCase {
-
- /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
- protected $l10n;
-
- /** @var PredefinedStatusService */
- protected $service;
+ protected IL10N&MockObject $l10n;
+ protected PredefinedStatusService $service;
protected function setUp(): void {
parent::setUp();
@@ -97,9 +94,6 @@ class PredefinedStatusServiceTest extends TestCase {
}
/**
- * @param string $id
- * @param string|null $expectedIcon
- *
* @dataProvider getIconForIdDataProvider
*/
public function testGetIconForId(string $id, ?string $expectedIcon): void {
@@ -107,10 +101,7 @@ class PredefinedStatusServiceTest extends TestCase {
$this->assertEquals($expectedIcon, $actual);
}
- /**
- * @return array
- */
- public function getIconForIdDataProvider(): array {
+ public static function getIconForIdDataProvider(): array {
return [
['meeting', '📅'],
['commuting', '🚌'],
@@ -123,9 +114,6 @@ class PredefinedStatusServiceTest extends TestCase {
}
/**
- * @param string $id
- * @param string|null $expected
- *
* @dataProvider getTranslatedStatusForIdDataProvider
*/
public function testGetTranslatedStatusForId(string $id, ?string $expected): void {
@@ -136,10 +124,7 @@ class PredefinedStatusServiceTest extends TestCase {
$this->assertEquals($expected, $actual);
}
- /**
- * @return array
- */
- public function getTranslatedStatusForIdDataProvider(): array {
+ public static function getTranslatedStatusForIdDataProvider(): array {
return [
['meeting', 'In a meeting'],
['commuting', 'Commuting'],
@@ -152,9 +137,6 @@ class PredefinedStatusServiceTest extends TestCase {
}
/**
- * @param string $id
- * @param bool $expected
- *
* @dataProvider isValidIdDataProvider
*/
public function testIsValidId(string $id, bool $expected): void {
@@ -162,10 +144,7 @@ class PredefinedStatusServiceTest extends TestCase {
$this->assertEquals($expected, $actual);
}
- /**
- * @return array
- */
- public function isValidIdDataProvider(): array {
+ public static function isValidIdDataProvider(): array {
return [
['meeting', true],
['commuting', true],
diff --git a/apps/user_status/tests/Unit/Service/StatusServiceTest.php b/apps/user_status/tests/Unit/Service/StatusServiceTest.php
index 801d0cea0fc..7aeb1d48448 100644
--- a/apps/user_status/tests/Unit/Service/StatusServiceTest.php
+++ b/apps/user_status/tests/Unit/Service/StatusServiceTest.php
@@ -31,27 +31,13 @@ use Psr\Log\LoggerInterface;
use Test\TestCase;
class StatusServiceTest extends TestCase {
-
- /** @var UserStatusMapper|MockObject */
- private $mapper;
-
- /** @var ITimeFactory|MockObject */
- private $timeFactory;
-
- /** @var PredefinedStatusService|MockObject */
- private $predefinedStatusService;
-
- /** @var IEmojiHelper|MockObject */
- private $emojiHelper;
-
- /** @var IConfig|MockObject */
- private $config;
-
- /** @var IUserManager|MockObject */
- private $userManager;
-
- /** @var LoggerInterface|MockObject */
- private $logger;
+ private UserStatusMapper&MockObject $mapper;
+ private ITimeFactory&MockObject $timeFactory;
+ private PredefinedStatusService&MockObject $predefinedStatusService;
+ private IEmojiHelper&MockObject $emojiHelper;
+ private IConfig&MockObject $config;
+ private IUserManager&MockObject $userManager;
+ private LoggerInterface&MockObject $logger;
private StatusService $service;
@@ -236,20 +222,10 @@ class StatusServiceTest extends TestCase {
}
/**
- * @param string $userId
- * @param string $status
- * @param int|null $statusTimestamp
- * @param bool $isUserDefined
- * @param bool $expectExisting
- * @param bool $expectSuccess
- * @param bool $expectTimeFactory
- * @param bool $expectException
- * @param string|null $expectedExceptionClass
- * @param string|null $expectedExceptionMessage
- *
* @dataProvider setStatusDataProvider
*/
- public function testSetStatus(string $userId,
+ public function testSetStatus(
+ string $userId,
string $status,
?int $statusTimestamp,
bool $isUserDefined,
@@ -258,7 +234,8 @@ class StatusServiceTest extends TestCase {
bool $expectTimeFactory,
bool $expectException,
?string $expectedExceptionClass,
- ?string $expectedExceptionMessage): void {
+ ?string $expectedExceptionMessage,
+ ): void {
$userStatus = new UserStatus();
if ($expectExisting) {
@@ -309,7 +286,7 @@ class StatusServiceTest extends TestCase {
}
}
- public function setStatusDataProvider(): array {
+ public static function setStatusDataProvider(): array {
return [
['john.doe', 'online', 50, true, true, true, false, false, null, null],
['john.doe', 'online', 50, true, false, true, false, false, null, null],
@@ -368,19 +345,10 @@ class StatusServiceTest extends TestCase {
}
/**
- * @param string $userId
- * @param string $messageId
- * @param bool $isValidMessageId
- * @param int|null $clearAt
- * @param bool $expectExisting
- * @param bool $expectSuccess
- * @param bool $expectException
- * @param string|null $expectedExceptionClass
- * @param string|null $expectedExceptionMessage
- *
* @dataProvider setPredefinedMessageDataProvider
*/
- public function testSetPredefinedMessage(string $userId,
+ public function testSetPredefinedMessage(
+ string $userId,
string $messageId,
bool $isValidMessageId,
?int $clearAt,
@@ -388,7 +356,8 @@ class StatusServiceTest extends TestCase {
bool $expectSuccess,
bool $expectException,
?string $expectedExceptionClass,
- ?string $expectedExceptionMessage): void {
+ ?string $expectedExceptionMessage,
+ ): void {
$userStatus = new UserStatus();
if ($expectExisting) {
@@ -451,7 +420,7 @@ class StatusServiceTest extends TestCase {
}
}
- public function setPredefinedMessageDataProvider(): array {
+ public static function setPredefinedMessageDataProvider(): array {
return [
['john.doe', 'sick-leave', true, null, true, true, false, null, null],
['john.doe', 'sick-leave', true, null, false, true, false, null, null],
@@ -465,20 +434,10 @@ class StatusServiceTest extends TestCase {
}
/**
- * @param string $userId
- * @param string|null $statusIcon
- * @param bool $supportsEmoji
- * @param string $message
- * @param int|null $clearAt
- * @param bool $expectExisting
- * @param bool $expectSuccess
- * @param bool $expectException
- * @param string|null $expectedExceptionClass
- * @param string|null $expectedExceptionMessage
- *
* @dataProvider setCustomMessageDataProvider
*/
- public function testSetCustomMessage(string $userId,
+ public function testSetCustomMessage(
+ string $userId,
?string $statusIcon,
bool $supportsEmoji,
string $message,
@@ -487,7 +446,8 @@ class StatusServiceTest extends TestCase {
bool $expectSuccess,
bool $expectException,
?string $expectedExceptionClass,
- ?string $expectedExceptionMessage): void {
+ ?string $expectedExceptionMessage,
+ ): void {
$userStatus = new UserStatus();
if ($expectExisting) {
@@ -548,7 +508,7 @@ class StatusServiceTest extends TestCase {
}
}
- public function setCustomMessageDataProvider(): array {
+ public static function setCustomMessageDataProvider(): array {
return [
['john.doe', '😁', true, 'Custom message', null, true, true, false, null, null],
['john.doe', '😁', true, 'Custom message', null, false, true, false, null, null],
@@ -815,7 +775,7 @@ class StatusServiceTest extends TestCase {
$this->service->revertMultipleUserStatus(['john', 'nobackup', 'backuponly', 'nobackupanddnd'], 'call');
}
- public function dataSetUserStatus(): array {
+ public static function dataSetUserStatus(): array {
return [
[IUserStatus::MESSAGE_CALENDAR_BUSY, '', false],
diff --git a/apps/webhook_listeners/tests/Db/WebhookListenerMapperTest.php b/apps/webhook_listeners/tests/Db/WebhookListenerMapperTest.php
index be99bccb677..45d66090eae 100644
--- a/apps/webhook_listeners/tests/Db/WebhookListenerMapperTest.php
+++ b/apps/webhook_listeners/tests/Db/WebhookListenerMapperTest.php
@@ -44,7 +44,7 @@ class WebhookListenerMapperTest extends TestCase {
parent::tearDown();
}
- protected function pruneTables() {
+ protected function pruneTables(): void {
$query = $this->connection->getQueryBuilder();
$query->delete(WebhookListenerMapper::TABLE_NAME)->executeStatement();
}
diff --git a/apps/workflowengine/tests/Check/AbstractStringCheckTest.php b/apps/workflowengine/tests/Check/AbstractStringCheckTest.php
index 774f866bf12..d10fcfb4cc3 100644
--- a/apps/workflowengine/tests/Check/AbstractStringCheckTest.php
+++ b/apps/workflowengine/tests/Check/AbstractStringCheckTest.php
@@ -1,4 +1,7 @@
<?php
+
+declare(strict_types=1);
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -7,9 +10,10 @@ namespace OCA\WorkflowEngine\Tests\Check;
use OCA\WorkflowEngine\Check\AbstractStringCheck;
use OCP\IL10N;
+use PHPUnit\Framework\MockObject\MockObject;
class AbstractStringCheckTest extends \Test\TestCase {
- protected function getCheckMock() {
+ protected function getCheckMock(): AbstractStringCheck|MockObject {
$l = $this->getMockBuilder(IL10N::class)
->disableOriginalConstructor()
->getMock();
@@ -19,7 +23,7 @@ class AbstractStringCheckTest extends \Test\TestCase {
return sprintf($string, $args);
});
- $check = $this->getMockBuilder('OCA\WorkflowEngine\Check\AbstractStringCheck')
+ $check = $this->getMockBuilder(AbstractStringCheck::class)
->setConstructorArgs([
$l,
])
@@ -32,7 +36,7 @@ class AbstractStringCheckTest extends \Test\TestCase {
return $check;
}
- public function dataExecuteStringCheck() {
+ public static function dataExecuteStringCheck(): array {
return [
['is', 'same', 'same', true],
['is', 'different', 'not the same', false],
@@ -48,19 +52,15 @@ class AbstractStringCheckTest extends \Test\TestCase {
/**
* @dataProvider dataExecuteStringCheck
- * @param string $operation
- * @param string $checkValue
- * @param string $actualValue
- * @param bool $expected
*/
- public function testExecuteStringCheck($operation, $checkValue, $actualValue, $expected): void {
+ public function testExecuteStringCheck(string $operation, string $checkValue, string $actualValue, bool $expected): void {
$check = $this->getCheckMock();
/** @var AbstractStringCheck $check */
$this->assertEquals($expected, $this->invokePrivate($check, 'executeStringCheck', [$operation, $checkValue, $actualValue]));
}
- public function dataValidateCheck() {
+ public static function dataValidateCheck(): array {
return [
['is', '/Invalid(Regex/'],
['!is', '/Invalid(Regex/'],
@@ -71,10 +71,8 @@ class AbstractStringCheckTest extends \Test\TestCase {
/**
* @dataProvider dataValidateCheck
- * @param string $operator
- * @param string $value
*/
- public function testValidateCheck($operator, $value): void {
+ public function testValidateCheck(string $operator, string $value): void {
$check = $this->getCheckMock();
/** @var AbstractStringCheck $check */
@@ -83,7 +81,7 @@ class AbstractStringCheckTest extends \Test\TestCase {
$this->addToAssertionCount(1);
}
- public function dataValidateCheckInvalid() {
+ public static function dataValidateCheckInvalid(): array {
return [
['!!is', '', 1, 'The given operator is invalid'],
['less', '', 1, 'The given operator is invalid'],
@@ -94,12 +92,8 @@ class AbstractStringCheckTest extends \Test\TestCase {
/**
* @dataProvider dataValidateCheckInvalid
- * @param $operator
- * @param $value
- * @param $exceptionCode
- * @param $exceptionMessage
*/
- public function testValidateCheckInvalid($operator, $value, $exceptionCode, $exceptionMessage): void {
+ public function testValidateCheckInvalid(string $operator, string $value, int $exceptionCode, string $exceptionMessage): void {
$check = $this->getCheckMock();
try {
@@ -111,7 +105,7 @@ class AbstractStringCheckTest extends \Test\TestCase {
}
}
- public function dataMatch() {
+ public static function dataMatch(): array {
return [
['/valid/', 'valid', [], true],
['/valid/', 'valid', [md5('/valid/') => [md5('valid') => false]], false], // Cache hit
@@ -120,12 +114,8 @@ class AbstractStringCheckTest extends \Test\TestCase {
/**
* @dataProvider dataMatch
- * @param string $pattern
- * @param string $subject
- * @param array[] $matches
- * @param bool $expected
*/
- public function testMatch($pattern, $subject, $matches, $expected): void {
+ public function testMatch(string $pattern, string $subject, array $matches, bool $expected): void {
$check = $this->getCheckMock();
$this->invokePrivate($check, 'matches', [$matches]);
diff --git a/apps/workflowengine/tests/Check/RequestRemoteAddressTest.php b/apps/workflowengine/tests/Check/RequestRemoteAddressTest.php
index 47b9138819e..f2f8026e666 100644
--- a/apps/workflowengine/tests/Check/RequestRemoteAddressTest.php
+++ b/apps/workflowengine/tests/Check/RequestRemoteAddressTest.php
@@ -1,4 +1,7 @@
<?php
+
+declare(strict_types=1);
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -8,19 +11,14 @@ namespace OCA\WorkflowEngine\Tests\Check;
use OCA\WorkflowEngine\Check\RequestRemoteAddress;
use OCP\IL10N;
use OCP\IRequest;
+use PHPUnit\Framework\MockObject\MockObject;
class RequestRemoteAddressTest extends \Test\TestCase {
- /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
- protected $request;
+ protected IRequest&MockObject $request;
- /**
- * @return IL10N|\PHPUnit\Framework\MockObject\MockObject
- */
- protected function getL10NMock() {
- $l = $this->getMockBuilder(IL10N::class)
- ->disableOriginalConstructor()
- ->getMock();
+ protected function getL10NMock(): IL10N&MockObject {
+ $l = $this->createMock(IL10N::class);
$l->expects($this->any())
->method('t')
->willReturnCallback(function ($string, $args) {
@@ -32,11 +30,10 @@ class RequestRemoteAddressTest extends \Test\TestCase {
protected function setUp(): void {
parent::setUp();
- $this->request = $this->getMockBuilder(IRequest::class)
- ->getMock();
+ $this->request = $this->createMock(IRequest::class);
}
- public function dataExecuteCheckIPv4() {
+ public static function dataExecuteCheckIPv4(): array {
return [
['127.0.0.1/32', '127.0.0.1', true],
['127.0.0.1/32', '127.0.0.0', false],
@@ -49,11 +46,8 @@ class RequestRemoteAddressTest extends \Test\TestCase {
/**
* @dataProvider dataExecuteCheckIPv4
- * @param string $value
- * @param string $ip
- * @param bool $expected
*/
- public function testExecuteCheckMatchesIPv4($value, $ip, $expected): void {
+ public function testExecuteCheckMatchesIPv4(string $value, string $ip, bool $expected): void {
$check = new RequestRemoteAddress($this->getL10NMock(), $this->request);
$this->request->expects($this->once())
@@ -65,11 +59,8 @@ class RequestRemoteAddressTest extends \Test\TestCase {
/**
* @dataProvider dataExecuteCheckIPv4
- * @param string $value
- * @param string $ip
- * @param bool $expected
*/
- public function testExecuteCheckNotMatchesIPv4($value, $ip, $expected): void {
+ public function testExecuteCheckNotMatchesIPv4(string $value, string $ip, bool $expected): void {
$check = new RequestRemoteAddress($this->getL10NMock(), $this->request);
$this->request->expects($this->once())
@@ -79,7 +70,7 @@ class RequestRemoteAddressTest extends \Test\TestCase {
$this->assertEquals(!$expected, $check->executeCheck('!matchesIPv4', $value));
}
- public function dataExecuteCheckIPv6() {
+ public static function dataExecuteCheckIPv6(): array {
return [
['::1/128', '::1', true],
['::2/128', '::3', false],
@@ -93,11 +84,8 @@ class RequestRemoteAddressTest extends \Test\TestCase {
/**
* @dataProvider dataExecuteCheckIPv6
- * @param string $value
- * @param string $ip
- * @param bool $expected
*/
- public function testExecuteCheckMatchesIPv6($value, $ip, $expected): void {
+ public function testExecuteCheckMatchesIPv6(string $value, string $ip, bool $expected): void {
$check = new RequestRemoteAddress($this->getL10NMock(), $this->request);
$this->request->expects($this->once())
@@ -109,11 +97,8 @@ class RequestRemoteAddressTest extends \Test\TestCase {
/**
* @dataProvider dataExecuteCheckIPv6
- * @param string $value
- * @param string $ip
- * @param bool $expected
*/
- public function testExecuteCheckNotMatchesIPv6($value, $ip, $expected): void {
+ public function testExecuteCheckNotMatchesIPv6(string $value, string $ip, bool $expected): void {
$check = new RequestRemoteAddress($this->getL10NMock(), $this->request);
$this->request->expects($this->once())
diff --git a/apps/workflowengine/tests/Check/RequestTimeTest.php b/apps/workflowengine/tests/Check/RequestTimeTest.php
index 6b56bb9427a..21127d4d56e 100644
--- a/apps/workflowengine/tests/Check/RequestTimeTest.php
+++ b/apps/workflowengine/tests/Check/RequestTimeTest.php
@@ -1,4 +1,7 @@
<?php
+
+declare(strict_types=1);
+
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -8,19 +11,13 @@ namespace OCA\WorkflowEngine\Tests\Check;
use OCA\WorkflowEngine\Check\RequestTime;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IL10N;
+use PHPUnit\Framework\MockObject\MockObject;
class RequestTimeTest extends \Test\TestCase {
+ protected ITimeFactory&MockObject $timeFactory;
- /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
- protected $timeFactory;
-
- /**
- * @return IL10N|\PHPUnit\Framework\MockObject\MockObject
- */
- protected function getL10NMock() {
- $l = $this->getMockBuilder(IL10N::class)
- ->disableOriginalConstructor()
- ->getMock();
+ protected function getL10NMock(): IL10N&MockObject {
+ $l = $this->createMock(IL10N::class);
$l->expects($this->any())
->method('t')
->willReturnCallback(function ($string, $args) {
@@ -32,11 +29,10 @@ class RequestTimeTest extends \Test\TestCase {
protected function setUp(): void {
parent::setUp();
- $this->timeFactory = $this->getMockBuilder('OCP\AppFramework\Utility\ITimeFactory')
- ->getMock();
+ $this->timeFactory = $this->createMock(ITimeFactory::class);
}
- public function dataExecuteCheck() {
+ public static function dataExecuteCheck(): array {
return [
[json_encode(['08:00 Europe/Berlin', '17:00 Europe/Berlin']), 1467870105, false], // 2016-07-07T07:41:45+02:00
[json_encode(['08:00 Europe/Berlin', '17:00 Europe/Berlin']), 1467873705, true], // 2016-07-07T08:41:45+02:00
@@ -69,11 +65,8 @@ class RequestTimeTest extends \Test\TestCase {
/**
* @dataProvider dataExecuteCheck
- * @param string $value
- * @param int $timestamp
- * @param bool $expected
*/
- public function testExecuteCheckIn($value, $timestamp, $expected): void {
+ public function testExecuteCheckIn(string $value, int $timestamp, bool $expected): void {
$check = new RequestTime($this->getL10NMock(), $this->timeFactory);
$this->timeFactory->expects($this->once())
@@ -85,11 +78,8 @@ class RequestTimeTest extends \Test\TestCase {
/**
* @dataProvider dataExecuteCheck
- * @param string $value
- * @param int $timestamp
- * @param bool $expected
*/
- public function testExecuteCheckNotIn($value, $timestamp, $expected): void {
+ public function testExecuteCheckNotIn(string $value, int $timestamp, bool $expected): void {
$check = new RequestTime($this->getL10NMock(), $this->timeFactory);
$this->timeFactory->expects($this->once())
@@ -99,7 +89,7 @@ class RequestTimeTest extends \Test\TestCase {
$this->assertEquals(!$expected, $check->executeCheck('!in', $value));
}
- public function dataValidateCheck() {
+ public static function dataValidateCheck(): array {
return [
['in', '["08:00 Europe/Berlin","17:00 Europe/Berlin"]'],
['!in', '["08:00 Europe/Berlin","17:00 America/North_Dakota/Beulah"]'],
@@ -109,16 +99,14 @@ class RequestTimeTest extends \Test\TestCase {
/**
* @dataProvider dataValidateCheck
- * @param string $operator
- * @param string $value
*/
- public function testValidateCheck($operator, $value): void {
+ public function testValidateCheck(string $operator, string $value): void {
$check = new RequestTime($this->getL10NMock(), $this->timeFactory);
$check->validateCheck($operator, $value);
$this->addToAssertionCount(1);
}
- public function dataValidateCheckInvalid() {
+ public static function dataValidateCheckInvalid(): array {
return [
['!!in', '["08:00 Europe/Berlin","17:00 Europe/Berlin"]', 1, 'The given operator is invalid'],
['in', '["28:00 Europe/Berlin","17:00 Europe/Berlin"]', 2, 'The given time span is invalid'],
@@ -132,12 +120,8 @@ class RequestTimeTest extends \Test\TestCase {
/**
* @dataProvider dataValidateCheckInvalid
- * @param string $operator
- * @param string $value
- * @param int $exceptionCode
- * @param string $exceptionMessage
*/
- public function testValidateCheckInvalid($operator, $value, $exceptionCode, $exceptionMessage): void {
+ public function testValidateCheckInvalid(string $operator, string $value, int $exceptionCode, string $exceptionMessage): void {
$check = new RequestTime($this->getL10NMock(), $this->timeFactory);
try {
diff --git a/apps/workflowengine/tests/Check/RequestUserAgentTest.php b/apps/workflowengine/tests/Check/RequestUserAgentTest.php
index 30e389c8236..2fe96bf3bdb 100644
--- a/apps/workflowengine/tests/Check/RequestUserAgentTest.php
+++ b/apps/workflowengine/tests/Check/RequestUserAgentTest.php
@@ -1,4 +1,7 @@
<?php
+
+declare(strict_types=1);
+
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -9,24 +12,19 @@ use OCA\WorkflowEngine\Check\AbstractStringCheck;
use OCA\WorkflowEngine\Check\RequestUserAgent;
use OCP\IL10N;
use OCP\IRequest;
+use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class RequestUserAgentTest extends TestCase {
-
- /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
- protected $request;
-
- /** @var RequestUserAgent */
- protected $check;
+ protected IRequest&MockObject $request;
+ protected RequestUserAgent $check;
protected function setUp(): void {
parent::setUp();
$this->request = $this->createMock(IRequest::class);
- /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject $l */
- $l = $this->getMockBuilder(IL10N::class)
- ->disableOriginalConstructor()
- ->getMock();
+ /** @var IL10N&MockObject $l */
+ $l = $this->createMock(IL10N::class);
$l->expects($this->any())
->method('t')
->willReturnCallback(function ($string, $args) {
@@ -36,7 +34,7 @@ class RequestUserAgentTest extends TestCase {
$this->check = new RequestUserAgent($l, $this->request);
}
- public function dataExecuteCheck() {
+ public static function dataExecuteCheck(): array {
return [
['is', 'android', 'Mozilla/5.0 (Android) Nextcloud-android/2.2.0', true],
['is', 'android', 'Mozilla/5.0 (iOS) Nextcloud-iOS/2.2.0', false],
@@ -86,12 +84,8 @@ class RequestUserAgentTest extends TestCase {
/**
* @dataProvider dataExecuteCheck
- * @param string $operation
- * @param string $checkValue
- * @param string $actualValue
- * @param bool $expected
*/
- public function testExecuteCheck($operation, $checkValue, $actualValue, $expected): void {
+ public function testExecuteCheck(string $operation, string $checkValue, string $actualValue, bool $expected): void {
$this->request->expects($this->once())
->method('getHeader')
->willReturn($actualValue);