aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/dav/lib/Connector/Sabre/QuotaPlugin.php34
-rw-r--r--apps/federatedfilesharing/lib/FederatedShareProvider.php1
-rw-r--r--apps/files/appinfo/info.xml3
-rw-r--r--apps/files/composer/composer/autoload_classmap.php3
-rw-r--r--apps/files/composer/composer/autoload_static.php3
-rw-r--r--apps/files/lib/Command/Object/Info.php80
-rw-r--r--apps/files/lib/Command/Object/ListObject.php50
-rw-r--r--apps/files/lib/Command/Object/ObjectUtil.php21
-rw-r--r--apps/files/lib/Command/Object/Orphans.php79
-rw-r--r--apps/files_sharing/appinfo/info.xml1
-rw-r--r--apps/files_sharing/composer/composer/autoload_classmap.php1
-rw-r--r--apps/files_sharing/composer/composer/autoload_static.php1
-rw-r--r--apps/files_sharing/lib/Command/ListShares.php161
-rw-r--r--apps/files_sharing/tests/External/ManagerTest.php38
-rw-r--r--core/Command/Base.php52
-rw-r--r--lib/composer/composer/autoload_classmap.php1
-rw-r--r--lib/composer/composer/autoload_static.php1
-rw-r--r--lib/private/Files/Cache/CacheEntry.php4
-rw-r--r--lib/private/Files/ObjectStore/S3.php42
-rw-r--r--lib/public/Files/Cache/ICacheEntry.php8
-rw-r--r--lib/public/Files/ObjectStore/IObjectStoreMetaData.php38
-rw-r--r--lib/public/Template.php4
-rw-r--r--package-lock.json6
-rw-r--r--tests/Core/Command/Config/App/SetConfigTest.php4
-rw-r--r--tests/Core/Command/Config/System/SetConfigTest.php4
-rw-r--r--tests/Core/Command/Encryption/EnableTest.php42
-rw-r--r--tests/Core/Command/Log/ManageTest.php40
-rw-r--r--tests/Core/Command/User/AuthTokens/DeleteTest.php36
-rw-r--r--tests/Core/Controller/NavigationControllerTest.php30
-rw-r--r--tests/lib/AppFramework/Http/RequestIdTest.php6
-rw-r--r--tests/lib/AppFramework/Http/RequestTest.php176
-rw-r--r--tests/lib/Template/JSCombinerTest.php76
-rw-r--r--tests/lib/User/ManagerTest.php17
33 files changed, 791 insertions, 272 deletions
diff --git a/apps/dav/lib/Connector/Sabre/QuotaPlugin.php b/apps/dav/lib/Connector/Sabre/QuotaPlugin.php
index 9790fc99837..bbb378edc9b 100644
--- a/apps/dav/lib/Connector/Sabre/QuotaPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/QuotaPlugin.php
@@ -15,6 +15,8 @@ use OCP\Files\StorageNotAvailableException;
use Sabre\DAV\Exception\InsufficientStorage;
use Sabre\DAV\Exception\ServiceUnavailable;
use Sabre\DAV\INode;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
/**
* This plugin check user quota and deny creating files when they exceeds the quota.
@@ -55,6 +57,7 @@ class QuotaPlugin extends \Sabre\DAV\ServerPlugin {
$server->on('beforeWriteContent', [$this, 'beforeWriteContent'], 10);
$server->on('beforeCreateFile', [$this, 'beforeCreateFile'], 10);
+ $server->on('method:MKCOL', [$this, 'onCreateCollection'], 30);
$server->on('beforeMove', [$this, 'beforeMove'], 10);
$server->on('beforeCopy', [$this, 'beforeCopy'], 10);
}
@@ -89,6 +92,31 @@ class QuotaPlugin extends \Sabre\DAV\ServerPlugin {
}
/**
+ * Check quota before creating directory
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $response
+ * @return bool
+ * @throws InsufficientStorage
+ * @throws \Sabre\DAV\Exception\Forbidden
+ */
+ public function onCreateCollection(RequestInterface $request, ResponseInterface $response): bool {
+ try {
+ $destinationPath = $this->server->calculateUri($request->getUrl());
+ $quotaPath = $this->getPathForDestination($destinationPath);
+ } catch (\Exception $e) {
+ return true;
+ }
+ if ($quotaPath) {
+ // MKCOL does not have a Content-Length header, so we can use
+ // a fixed value for the quota check.
+ return $this->checkQuota($quotaPath, 4096, true);
+ }
+
+ return true;
+ }
+
+ /**
* Check quota before writing content
*
* @param string $uri target file URI
@@ -174,7 +202,7 @@ class QuotaPlugin extends \Sabre\DAV\ServerPlugin {
* @throws InsufficientStorage
* @return bool
*/
- public function checkQuota(string $path, $length = null) {
+ public function checkQuota(string $path, $length = null, $isDir = false) {
if ($length === null) {
$length = $this->getLength();
}
@@ -191,6 +219,10 @@ class QuotaPlugin extends \Sabre\DAV\ServerPlugin {
$freeSpace = $this->getFreeSpace($path);
if ($freeSpace >= 0 && $length > $freeSpace) {
+ if ($isDir) {
+ throw new InsufficientStorage("Insufficient space in $path. $freeSpace available. Cannot create directory");
+ }
+
throw new InsufficientStorage("Insufficient space in $path, $length required, $freeSpace available");
}
}
diff --git a/apps/federatedfilesharing/lib/FederatedShareProvider.php b/apps/federatedfilesharing/lib/FederatedShareProvider.php
index 379cd793116..d993b35845c 100644
--- a/apps/federatedfilesharing/lib/FederatedShareProvider.php
+++ b/apps/federatedfilesharing/lib/FederatedShareProvider.php
@@ -812,6 +812,7 @@ class FederatedShareProvider implements IShareProvider {
->setPermissions((int)$data['permissions'])
->setTarget($data['file_target'])
->setMailSend((bool)$data['mail_send'])
+ ->setStatus((int)$data['accepted'])
->setToken($data['token']);
$shareTime = new \DateTime();
diff --git a/apps/files/appinfo/info.xml b/apps/files/appinfo/info.xml
index cdcc79e47fb..95f6153e1d7 100644
--- a/apps/files/appinfo/info.xml
+++ b/apps/files/appinfo/info.xml
@@ -49,6 +49,9 @@
<command>OCA\Files\Command\Object\Delete</command>
<command>OCA\Files\Command\Object\Get</command>
<command>OCA\Files\Command\Object\Put</command>
+ <command>OCA\Files\Command\Object\Info</command>
+ <command>OCA\Files\Command\Object\ListObject</command>
+ <command>OCA\Files\Command\Object\Orphans</command>
</commands>
<settings>
diff --git a/apps/files/composer/composer/autoload_classmap.php b/apps/files/composer/composer/autoload_classmap.php
index 0d9e6aa2d77..a74df7ba3d2 100644
--- a/apps/files/composer/composer/autoload_classmap.php
+++ b/apps/files/composer/composer/autoload_classmap.php
@@ -35,7 +35,10 @@ return array(
'OCA\\Files\\Command\\Move' => $baseDir . '/../lib/Command/Move.php',
'OCA\\Files\\Command\\Object\\Delete' => $baseDir . '/../lib/Command/Object/Delete.php',
'OCA\\Files\\Command\\Object\\Get' => $baseDir . '/../lib/Command/Object/Get.php',
+ 'OCA\\Files\\Command\\Object\\Info' => $baseDir . '/../lib/Command/Object/Info.php',
+ 'OCA\\Files\\Command\\Object\\ListObject' => $baseDir . '/../lib/Command/Object/ListObject.php',
'OCA\\Files\\Command\\Object\\ObjectUtil' => $baseDir . '/../lib/Command/Object/ObjectUtil.php',
+ 'OCA\\Files\\Command\\Object\\Orphans' => $baseDir . '/../lib/Command/Object/Orphans.php',
'OCA\\Files\\Command\\Object\\Put' => $baseDir . '/../lib/Command/Object/Put.php',
'OCA\\Files\\Command\\Put' => $baseDir . '/../lib/Command/Put.php',
'OCA\\Files\\Command\\RepairTree' => $baseDir . '/../lib/Command/RepairTree.php',
diff --git a/apps/files/composer/composer/autoload_static.php b/apps/files/composer/composer/autoload_static.php
index 5ece9073178..1d79f38e35a 100644
--- a/apps/files/composer/composer/autoload_static.php
+++ b/apps/files/composer/composer/autoload_static.php
@@ -50,7 +50,10 @@ class ComposerStaticInitFiles
'OCA\\Files\\Command\\Move' => __DIR__ . '/..' . '/../lib/Command/Move.php',
'OCA\\Files\\Command\\Object\\Delete' => __DIR__ . '/..' . '/../lib/Command/Object/Delete.php',
'OCA\\Files\\Command\\Object\\Get' => __DIR__ . '/..' . '/../lib/Command/Object/Get.php',
+ 'OCA\\Files\\Command\\Object\\Info' => __DIR__ . '/..' . '/../lib/Command/Object/Info.php',
+ 'OCA\\Files\\Command\\Object\\ListObject' => __DIR__ . '/..' . '/../lib/Command/Object/ListObject.php',
'OCA\\Files\\Command\\Object\\ObjectUtil' => __DIR__ . '/..' . '/../lib/Command/Object/ObjectUtil.php',
+ 'OCA\\Files\\Command\\Object\\Orphans' => __DIR__ . '/..' . '/../lib/Command/Object/Orphans.php',
'OCA\\Files\\Command\\Object\\Put' => __DIR__ . '/..' . '/../lib/Command/Object/Put.php',
'OCA\\Files\\Command\\Put' => __DIR__ . '/..' . '/../lib/Command/Put.php',
'OCA\\Files\\Command\\RepairTree' => __DIR__ . '/..' . '/../lib/Command/RepairTree.php',
diff --git a/apps/files/lib/Command/Object/Info.php b/apps/files/lib/Command/Object/Info.php
new file mode 100644
index 00000000000..6748de37cfe
--- /dev/null
+++ b/apps/files/lib/Command/Object/Info.php
@@ -0,0 +1,80 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Files\Command\Object;
+
+use OC\Core\Command\Base;
+use OCP\Files\IMimeTypeDetector;
+use OCP\Files\ObjectStore\IObjectStoreMetaData;
+use OCP\Util;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class Info extends Base {
+ public function __construct(
+ private ObjectUtil $objectUtils,
+ private IMimeTypeDetector $mimeTypeDetector,
+ ) {
+ parent::__construct();
+ }
+
+ protected function configure(): void {
+ parent::configure();
+ $this
+ ->setName('files:object:info')
+ ->setDescription('Get the metadata of an object')
+ ->addArgument('object', InputArgument::REQUIRED, 'Object to get')
+ ->addOption('bucket', 'b', InputOption::VALUE_REQUIRED, "Bucket to get the object from, only required in cases where it can't be determined from the config");
+ }
+
+ public function execute(InputInterface $input, OutputInterface $output): int {
+ $object = $input->getArgument('object');
+ $objectStore = $this->objectUtils->getObjectStore($input->getOption('bucket'), $output);
+ if (!$objectStore) {
+ return self::FAILURE;
+ }
+
+ if (!$objectStore instanceof IObjectStoreMetaData) {
+ $output->writeln('<error>Configured object store does currently not support retrieve metadata</error>');
+ return self::FAILURE;
+ }
+
+ if (!$objectStore->objectExists($object)) {
+ $output->writeln("<error>Object $object does not exist</error>");
+ return self::FAILURE;
+ }
+
+ try {
+ $meta = $objectStore->getObjectMetaData($object);
+ } catch (\Exception $e) {
+ $msg = $e->getMessage();
+ $output->writeln("<error>Failed to read $object from object store: $msg</error>");
+ return self::FAILURE;
+ }
+
+ if ($input->getOption('output') === 'plain' && isset($meta['size'])) {
+ $meta['size'] = Util::humanFileSize($meta['size']);
+ }
+ if (isset($meta['mtime'])) {
+ $meta['mtime'] = $meta['mtime']->format(\DateTimeImmutable::ATOM);
+ }
+ if (!isset($meta['mimetype'])) {
+ $handle = $objectStore->readObject($object);
+ $head = fread($handle, 8192);
+ fclose($handle);
+ $meta['mimetype'] = $this->mimeTypeDetector->detectString($head);
+ }
+
+ $this->writeArrayInOutputFormat($input, $output, $meta);
+
+ return self::SUCCESS;
+ }
+
+}
diff --git a/apps/files/lib/Command/Object/ListObject.php b/apps/files/lib/Command/Object/ListObject.php
new file mode 100644
index 00000000000..5d30232e09f
--- /dev/null
+++ b/apps/files/lib/Command/Object/ListObject.php
@@ -0,0 +1,50 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Files\Command\Object;
+
+use OC\Core\Command\Base;
+use OCP\Files\ObjectStore\IObjectStoreMetaData;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class ListObject extends Base {
+ private const CHUNK_SIZE = 100;
+
+ public function __construct(
+ private readonly ObjectUtil $objectUtils,
+ ) {
+ parent::__construct();
+ }
+
+ protected function configure(): void {
+ parent::configure();
+ $this
+ ->setName('files:object:list')
+ ->setDescription('List all objects in the object store')
+ ->addOption('bucket', 'b', InputOption::VALUE_REQUIRED, "Bucket to list the objects from, only required in cases where it can't be determined from the config");
+ }
+
+ public function execute(InputInterface $input, OutputInterface $output): int {
+ $objectStore = $this->objectUtils->getObjectStore($input->getOption('bucket'), $output);
+ if (!$objectStore) {
+ return self::FAILURE;
+ }
+
+ if (!$objectStore instanceof IObjectStoreMetaData) {
+ $output->writeln('<error>Configured object store does currently not support listing objects</error>');
+ return self::FAILURE;
+ }
+ $objects = $objectStore->listObjects();
+ $objects = $this->objectUtils->formatObjects($objects, $input->getOption('output') === self::OUTPUT_FORMAT_PLAIN);
+ $this->writeStreamingTableInOutputFormat($input, $output, $objects, self::CHUNK_SIZE);
+
+ return self::SUCCESS;
+ }
+}
diff --git a/apps/files/lib/Command/Object/ObjectUtil.php b/apps/files/lib/Command/Object/ObjectUtil.php
index c4ab59608fb..5f053c2c42f 100644
--- a/apps/files/lib/Command/Object/ObjectUtil.php
+++ b/apps/files/lib/Command/Object/ObjectUtil.php
@@ -12,6 +12,7 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\ObjectStore\IObjectStore;
use OCP\IConfig;
use OCP\IDBConnection;
+use OCP\Util;
use Symfony\Component\Console\Output\OutputInterface;
class ObjectUtil {
@@ -91,4 +92,24 @@ class ObjectUtil {
return $fileId;
}
+
+ public function formatObjects(\Iterator $objects, bool $humanOutput): \Iterator {
+ foreach ($objects as $object) {
+ yield $this->formatObject($object, $humanOutput);
+ }
+ }
+
+ public function formatObject(array $object, bool $humanOutput): array {
+ $row = array_merge([
+ 'urn' => $object['urn'],
+ ], ($object['metadata'] ?? []));
+
+ if ($humanOutput && isset($row['size'])) {
+ $row['size'] = Util::humanFileSize($row['size']);
+ }
+ if (isset($row['mtime'])) {
+ $row['mtime'] = $row['mtime']->format(\DateTimeImmutable::ATOM);
+ }
+ return $row;
+ }
}
diff --git a/apps/files/lib/Command/Object/Orphans.php b/apps/files/lib/Command/Object/Orphans.php
new file mode 100644
index 00000000000..f7132540fc8
--- /dev/null
+++ b/apps/files/lib/Command/Object/Orphans.php
@@ -0,0 +1,79 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Files\Command\Object;
+
+use OC\Core\Command\Base;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\Files\ObjectStore\IObjectStoreMetaData;
+use OCP\IDBConnection;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class Orphans extends Base {
+ private const CHUNK_SIZE = 100;
+
+ private ?IQueryBuilder $query = null;
+
+ public function __construct(
+ private readonly ObjectUtil $objectUtils,
+ private readonly IDBConnection $connection,
+ ) {
+ parent::__construct();
+ }
+
+ private function getQuery(): IQueryBuilder {
+ if (!$this->query) {
+ $this->query = $this->connection->getQueryBuilder();
+ $this->query->select('fileid')
+ ->from('filecache')
+ ->where($this->query->expr()->eq('fileid', $this->query->createParameter('file_id')));
+ }
+ return $this->query;
+ }
+
+ protected function configure(): void {
+ parent::configure();
+ $this
+ ->setName('files:object:orphans')
+ ->setDescription('List all objects in the object store that don\'t have a matching entry in the database')
+ ->addOption('bucket', 'b', InputOption::VALUE_REQUIRED, "Bucket to list the objects from, only required in cases where it can't be determined from the config");
+ }
+
+ public function execute(InputInterface $input, OutputInterface $output): int {
+ $objectStore = $this->objectUtils->getObjectStore($input->getOption('bucket'), $output);
+ if (!$objectStore) {
+ return self::FAILURE;
+ }
+
+ if (!$objectStore instanceof IObjectStoreMetaData) {
+ $output->writeln('<error>Configured object store does currently not support listing objects</error>');
+ return self::FAILURE;
+ }
+ $prefixLength = strlen('urn:oid:');
+
+ $objects = $objectStore->listObjects('urn:oid:');
+ $orphans = new \CallbackFilterIterator($objects, function (array $object) use ($prefixLength) {
+ $fileId = (int)substr($object['urn'], $prefixLength);
+ return !$this->fileIdInDb($fileId);
+ });
+
+ $orphans = $this->objectUtils->formatObjects($orphans, $input->getOption('output') === self::OUTPUT_FORMAT_PLAIN);
+ $this->writeStreamingTableInOutputFormat($input, $output, $orphans, self::CHUNK_SIZE);
+
+ return self::SUCCESS;
+ }
+
+ private function fileIdInDb(int $fileId): bool {
+ $query = $this->getQuery();
+ $query->setParameter('file_id', $fileId, IQueryBuilder::PARAM_INT);
+ $result = $query->executeQuery();
+ return $result->fetchOne() !== false;
+ }
+}
diff --git a/apps/files_sharing/appinfo/info.xml b/apps/files_sharing/appinfo/info.xml
index c92559635ea..03078b54040 100644
--- a/apps/files_sharing/appinfo/info.xml
+++ b/apps/files_sharing/appinfo/info.xml
@@ -50,6 +50,7 @@ Turning the feature off removes shared files and folders on the server for all s
<command>OCA\Files_Sharing\Command\ExiprationNotification</command>
<command>OCA\Files_Sharing\Command\DeleteOrphanShares</command>
<command>OCA\Files_Sharing\Command\FixShareOwners</command>
+ <command>OCA\Files_Sharing\Command\ListShares</command>
</commands>
<settings>
diff --git a/apps/files_sharing/composer/composer/autoload_classmap.php b/apps/files_sharing/composer/composer/autoload_classmap.php
index 400df9c9771..8682fd5f238 100644
--- a/apps/files_sharing/composer/composer/autoload_classmap.php
+++ b/apps/files_sharing/composer/composer/autoload_classmap.php
@@ -28,6 +28,7 @@ return array(
'OCA\\Files_Sharing\\Command\\DeleteOrphanShares' => $baseDir . '/../lib/Command/DeleteOrphanShares.php',
'OCA\\Files_Sharing\\Command\\ExiprationNotification' => $baseDir . '/../lib/Command/ExiprationNotification.php',
'OCA\\Files_Sharing\\Command\\FixShareOwners' => $baseDir . '/../lib/Command/FixShareOwners.php',
+ 'OCA\\Files_Sharing\\Command\\ListShares' => $baseDir . '/../lib/Command/ListShares.php',
'OCA\\Files_Sharing\\Controller\\AcceptController' => $baseDir . '/../lib/Controller/AcceptController.php',
'OCA\\Files_Sharing\\Controller\\DeletedShareAPIController' => $baseDir . '/../lib/Controller/DeletedShareAPIController.php',
'OCA\\Files_Sharing\\Controller\\ExternalSharesController' => $baseDir . '/../lib/Controller/ExternalSharesController.php',
diff --git a/apps/files_sharing/composer/composer/autoload_static.php b/apps/files_sharing/composer/composer/autoload_static.php
index 02bb6d08bb5..3bf5bcdffda 100644
--- a/apps/files_sharing/composer/composer/autoload_static.php
+++ b/apps/files_sharing/composer/composer/autoload_static.php
@@ -43,6 +43,7 @@ class ComposerStaticInitFiles_Sharing
'OCA\\Files_Sharing\\Command\\DeleteOrphanShares' => __DIR__ . '/..' . '/../lib/Command/DeleteOrphanShares.php',
'OCA\\Files_Sharing\\Command\\ExiprationNotification' => __DIR__ . '/..' . '/../lib/Command/ExiprationNotification.php',
'OCA\\Files_Sharing\\Command\\FixShareOwners' => __DIR__ . '/..' . '/../lib/Command/FixShareOwners.php',
+ 'OCA\\Files_Sharing\\Command\\ListShares' => __DIR__ . '/..' . '/../lib/Command/ListShares.php',
'OCA\\Files_Sharing\\Controller\\AcceptController' => __DIR__ . '/..' . '/../lib/Controller/AcceptController.php',
'OCA\\Files_Sharing\\Controller\\DeletedShareAPIController' => __DIR__ . '/..' . '/../lib/Controller/DeletedShareAPIController.php',
'OCA\\Files_Sharing\\Controller\\ExternalSharesController' => __DIR__ . '/..' . '/../lib/Controller/ExternalSharesController.php',
diff --git a/apps/files_sharing/lib/Command/ListShares.php b/apps/files_sharing/lib/Command/ListShares.php
new file mode 100644
index 00000000000..2d5cdbf7812
--- /dev/null
+++ b/apps/files_sharing/lib/Command/ListShares.php
@@ -0,0 +1,161 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2025 Robin Appelman <robin@icewind.nl>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Files_Sharing\Command;
+
+use OC\Core\Command\Base;
+use OCP\Files\Folder;
+use OCP\Files\IRootFolder;
+use OCP\Files\Node;
+use OCP\Files\NotFoundException;
+use OCP\Share\IManager;
+use OCP\Share\IShare;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class ListShares extends Base {
+ /** @var array<string, Node> */
+ private array $fileCache = [];
+
+ private const SHARE_TYPE_NAMES = [
+ IShare::TYPE_USER => 'user',
+ IShare::TYPE_GROUP => 'group',
+ IShare::TYPE_LINK => 'link',
+ IShare::TYPE_EMAIL => 'email',
+ IShare::TYPE_REMOTE => 'remote',
+ IShare::TYPE_REMOTE_GROUP => 'group',
+ IShare::TYPE_ROOM => 'room',
+ IShare::TYPE_DECK => 'deck',
+ ];
+
+ public function __construct(
+ private readonly IManager $shareManager,
+ private readonly IRootFolder $rootFolder,
+ ) {
+ parent::__construct();
+ }
+
+ protected function configure() {
+ parent::configure();
+ $this
+ ->setName('share:list')
+ ->setDescription('List available shares')
+ ->addOption('owner', null, InputOption::VALUE_REQUIRED, 'only show shares owned by a specific user')
+ ->addOption('recipient', null, InputOption::VALUE_REQUIRED, 'only show shares with a specific recipient')
+ ->addOption('by', null, InputOption::VALUE_REQUIRED, 'only show shares with by as specific user')
+ ->addOption('file', null, InputOption::VALUE_REQUIRED, 'only show shares of a specific file')
+ ->addOption('parent', null, InputOption::VALUE_REQUIRED, 'only show shares of files inside a specific folder')
+ ->addOption('recursive', null, InputOption::VALUE_NONE, 'also show shares nested deep inside the specified parent folder')
+ ->addOption('type', null, InputOption::VALUE_REQUIRED, 'only show shares of a specific type')
+ ->addOption('status', null, InputOption::VALUE_REQUIRED, 'only show shares with a specific status');
+ }
+
+ public function execute(InputInterface $input, OutputInterface $output): int {
+ if ($input->getOption('recursive') && !$input->getOption('parent')) {
+ $output->writeln("<error>recursive option can't be used without parent option</error>");
+ return 1;
+ }
+
+ // todo: do some pre-filtering instead of first querying all shares
+ /** @var \Iterator<IShare> $allShares */
+ $allShares = $this->shareManager->getAllShares();
+ $shares = new \CallbackFilterIterator($allShares, function (IShare $share) use ($input) {
+ return $this->shouldShowShare($input, $share);
+ });
+ $shares = iterator_to_array($shares);
+ $data = array_map(function (IShare $share) {
+ return [
+ 'id' => $share->getId(),
+ 'file' => $share->getNodeId(),
+ 'target-path' => $share->getTarget(),
+ 'source-path' => $share->getNode()->getPath(),
+ 'owner' => $share->getShareOwner(),
+ 'recipient' => $share->getSharedWith(),
+ 'by' => $share->getSharedBy(),
+ 'type' => self::SHARE_TYPE_NAMES[$share->getShareType()] ?? 'unknown',
+ ];
+ }, $shares);
+
+ $this->writeTableInOutputFormat($input, $output, $data);
+ return 0;
+ }
+
+ private function getFileId(string $file): int {
+ if (is_numeric($file)) {
+ return (int)$file;
+ }
+ return $this->getFile($file)->getId();
+ }
+
+ private function getFile(string $file): Node {
+ if (isset($this->fileCache[$file])) {
+ return $this->fileCache[$file];
+ }
+
+ if (is_numeric($file)) {
+ $node = $this->rootFolder->getFirstNodeById((int)$file);
+ if (!$node) {
+ throw new NotFoundException("File with id $file not found");
+ }
+ } else {
+ $node = $this->rootFolder->get($file);
+ }
+ $this->fileCache[$file] = $node;
+ return $node;
+ }
+
+ private function getShareType(string $type): int {
+ foreach (self::SHARE_TYPE_NAMES as $shareType => $shareTypeName) {
+ if ($shareTypeName === $type) {
+ return $shareType;
+ }
+ }
+ throw new \Exception("Unknown share type $type");
+ }
+
+ private function shouldShowShare(InputInterface $input, IShare $share): bool {
+ if ($input->getOption('owner') && $share->getShareOwner() !== $input->getOption('owner')) {
+ return false;
+ }
+ if ($input->getOption('recipient') && $share->getSharedWith() !== $input->getOption('recipient')) {
+ return false;
+ }
+ if ($input->getOption('by') && $share->getSharedBy() !== $input->getOption('by')) {
+ return false;
+ }
+ if ($input->getOption('file') && $share->getNodeId() !== $this->getFileId($input->getOption('file'))) {
+ return false;
+ }
+ if ($input->getOption('parent')) {
+ $parent = $this->getFile($input->getOption('parent'));
+ if (!$parent instanceof Folder) {
+ throw new \Exception("Parent {$parent->getPath()} is not a folder");
+ }
+ $recursive = $input->getOption('recursive');
+ if (!$recursive) {
+ $shareCacheEntry = $share->getNodeCacheEntry();
+ if (!$shareCacheEntry) {
+ $shareCacheEntry = $share->getNode();
+ }
+ if ($shareCacheEntry->getParentId() !== $parent->getId()) {
+ return false;
+ }
+ } else {
+ $shareNode = $share->getNode();
+ if ($parent->getRelativePath($shareNode->getPath()) === null) {
+ return false;
+ }
+ }
+ }
+ if ($input->getOption('type') && $share->getShareType() !== $this->getShareType($input->getOption('type'))) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/apps/files_sharing/tests/External/ManagerTest.php b/apps/files_sharing/tests/External/ManagerTest.php
index c8566098707..611392c286e 100644
--- a/apps/files_sharing/tests/External/ManagerTest.php
+++ b/apps/files_sharing/tests/External/ManagerTest.php
@@ -19,6 +19,7 @@ use OCP\EventDispatcher\IEventDispatcher;
use OCP\Federation\ICloudFederationFactory;
use OCP\Federation\ICloudFederationProviderManager;
use OCP\Files\NotFoundException;
+use OCP\Http\Client\IClient;
use OCP\Http\Client\IClientService;
use OCP\Http\Client\IResponse;
use OCP\ICacheFactory;
@@ -254,12 +255,18 @@ class ManagerTest extends TestCase {
$this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}');
$this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}-1');
+ $newClientCalls = [];
+ $this->clientService
+ ->method('newClient')
+ ->willReturnCallback(function () use (&$newClientCalls): IClient {
+ if (!empty($newClientCalls)) {
+ return array_shift($newClientCalls);
+ }
+ return $this->createMock(IClient::class);
+ });
if (!$isGroup) {
- $client = $this->getMockBuilder('OCP\Http\Client\IClient')
- ->disableOriginalConstructor()->getMock();
- $this->clientService->expects($this->at(0))
- ->method('newClient')
- ->willReturn($client);
+ $client = $this->createMock(IClient::class);
+ $newClientCalls[] = $client;
$response = $this->createMock(IResponse::class);
$response->method('getBody')
->willReturn(json_encode([
@@ -311,11 +318,8 @@ class ManagerTest extends TestCase {
$this->assertNotMount('{{TemporaryMountPointName#' . $shareData1['name'] . '}}-1');
if (!$isGroup) {
- $client = $this->getMockBuilder('OCP\Http\Client\IClient')
- ->disableOriginalConstructor()->getMock();
- $this->clientService->expects($this->at(0))
- ->method('newClient')
- ->willReturn($client);
+ $client = $this->createMock(IClient::class);
+ $newClientCalls[] = $client;
$response = $this->createMock(IResponse::class);
$response->method('getBody')
->willReturn(json_encode([
@@ -367,16 +371,10 @@ class ManagerTest extends TestCase {
// no http requests here
$this->manager->removeGroupShares('group1');
} else {
- $client1 = $this->getMockBuilder('OCP\Http\Client\IClient')
- ->disableOriginalConstructor()->getMock();
- $client2 = $this->getMockBuilder('OCP\Http\Client\IClient')
- ->disableOriginalConstructor()->getMock();
- $this->clientService->expects($this->exactly(2))
- ->method('newClient')
- ->willReturnOnConsecutiveCalls(
- $client1,
- $client2,
- );
+ $client1 = $this->createMock(IClient::class);
+ $client2 = $this->createMock(IClient::class);
+ $newClientCalls[] = $client1;
+ $newClientCalls[] = $client2;
$response = $this->createMock(IResponse::class);
$response->method('getBody')
->willReturn(json_encode([
diff --git a/core/Command/Base.php b/core/Command/Base.php
index b915ae2ae4a..c9b6337b64a 100644
--- a/core/Command/Base.php
+++ b/core/Command/Base.php
@@ -88,6 +88,58 @@ class Base extends Command implements CompletionAwareInterface {
}
}
+ protected function writeStreamingTableInOutputFormat(InputInterface $input, OutputInterface $output, \Iterator $items, int $tableGroupSize): void {
+ switch ($input->getOption('output')) {
+ case self::OUTPUT_FORMAT_JSON:
+ case self::OUTPUT_FORMAT_JSON_PRETTY:
+ $this->writeStreamingJsonArray($input, $output, $items);
+ break;
+ default:
+ foreach ($this->chunkIterator($items, $tableGroupSize) as $chunk) {
+ $this->writeTableInOutputFormat($input, $output, $chunk);
+ }
+ break;
+ }
+ }
+
+ protected function writeStreamingJsonArray(InputInterface $input, OutputInterface $output, \Iterator $items): void {
+ $first = true;
+ $outputType = $input->getOption('output');
+
+ $output->writeln('[');
+ foreach ($items as $item) {
+ if (!$first) {
+ $output->writeln(',');
+ }
+ if ($outputType === self::OUTPUT_FORMAT_JSON_PRETTY) {
+ $output->write(json_encode($item, JSON_PRETTY_PRINT));
+ } else {
+ $output->write(json_encode($item));
+ }
+ $first = false;
+ }
+ $output->writeln("\n]");
+ }
+
+ public function chunkIterator(\Iterator $iterator, int $count): \Iterator {
+ $chunk = [];
+
+ for ($i = 0; $iterator->valid(); $i++) {
+ $chunk[] = $iterator->current();
+ $iterator->next();
+ if (count($chunk) == $count) {
+ // Got a full chunk, yield and start a new one
+ yield $chunk;
+ $chunk = [];
+ }
+ }
+
+ if (count($chunk)) {
+ // Yield the last chunk even if incomplete
+ yield $chunk;
+ }
+ }
+
/**
* @param mixed $item
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 2d0b62d749f..52e3075e413 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -456,6 +456,7 @@ return array(
'OCP\\Files\\Notify\\INotifyHandler' => $baseDir . '/lib/public/Files/Notify/INotifyHandler.php',
'OCP\\Files\\Notify\\IRenameChange' => $baseDir . '/lib/public/Files/Notify/IRenameChange.php',
'OCP\\Files\\ObjectStore\\IObjectStore' => $baseDir . '/lib/public/Files/ObjectStore/IObjectStore.php',
+ 'OCP\\Files\\ObjectStore\\IObjectStoreMetaData' => $baseDir . '/lib/public/Files/ObjectStore/IObjectStoreMetaData.php',
'OCP\\Files\\ObjectStore\\IObjectStoreMultiPartUpload' => $baseDir . '/lib/public/Files/ObjectStore/IObjectStoreMultiPartUpload.php',
'OCP\\Files\\ReservedWordException' => $baseDir . '/lib/public/Files/ReservedWordException.php',
'OCP\\Files\\Search\\ISearchBinaryOperator' => $baseDir . '/lib/public/Files/Search/ISearchBinaryOperator.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 64210bd5843..e98bc3e1aaa 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -505,6 +505,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Files\\Notify\\INotifyHandler' => __DIR__ . '/../../..' . '/lib/public/Files/Notify/INotifyHandler.php',
'OCP\\Files\\Notify\\IRenameChange' => __DIR__ . '/../../..' . '/lib/public/Files/Notify/IRenameChange.php',
'OCP\\Files\\ObjectStore\\IObjectStore' => __DIR__ . '/../../..' . '/lib/public/Files/ObjectStore/IObjectStore.php',
+ 'OCP\\Files\\ObjectStore\\IObjectStoreMetaData' => __DIR__ . '/../../..' . '/lib/public/Files/ObjectStore/IObjectStoreMetaData.php',
'OCP\\Files\\ObjectStore\\IObjectStoreMultiPartUpload' => __DIR__ . '/../../..' . '/lib/public/Files/ObjectStore/IObjectStoreMultiPartUpload.php',
'OCP\\Files\\ReservedWordException' => __DIR__ . '/../../..' . '/lib/public/Files/ReservedWordException.php',
'OCP\\Files\\Search\\ISearchBinaryOperator' => __DIR__ . '/../../..' . '/lib/public/Files/Search/ISearchBinaryOperator.php',
diff --git a/lib/private/Files/Cache/CacheEntry.php b/lib/private/Files/Cache/CacheEntry.php
index e9417c8012a..ab5bae316f4 100644
--- a/lib/private/Files/Cache/CacheEntry.php
+++ b/lib/private/Files/Cache/CacheEntry.php
@@ -110,6 +110,10 @@ class CacheEntry implements ICacheEntry {
return $this->data['upload_time'] ?? null;
}
+ public function getParentId(): int {
+ return $this->data['parent'];
+ }
+
public function getData() {
return $this->data;
}
diff --git a/lib/private/Files/ObjectStore/S3.php b/lib/private/Files/ObjectStore/S3.php
index 41ab75caf45..e970fb6ac14 100644
--- a/lib/private/Files/ObjectStore/S3.php
+++ b/lib/private/Files/ObjectStore/S3.php
@@ -3,14 +3,16 @@
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
+
namespace OC\Files\ObjectStore;
use Aws\Result;
use Exception;
use OCP\Files\ObjectStore\IObjectStore;
+use OCP\Files\ObjectStore\IObjectStoreMetaData;
use OCP\Files\ObjectStore\IObjectStoreMultiPartUpload;
-class S3 implements IObjectStore, IObjectStoreMultiPartUpload {
+class S3 implements IObjectStore, IObjectStoreMultiPartUpload, IObjectStoreMetaData {
use S3ConnectionTrait;
use S3ObjectTrait;
@@ -61,7 +63,7 @@ class S3 implements IObjectStore, IObjectStoreMultiPartUpload {
'Key' => $urn,
'UploadId' => $uploadId,
'MaxParts' => 1000,
- 'PartNumberMarker' => $partNumberMarker
+ 'PartNumberMarker' => $partNumberMarker,
] + $this->getSSECParameters());
$parts = array_merge($parts, $result->get('Parts') ?? []);
$isTruncated = $result->get('IsTruncated');
@@ -89,7 +91,41 @@ class S3 implements IObjectStore, IObjectStoreMultiPartUpload {
$this->getConnection()->abortMultipartUpload([
'Bucket' => $this->bucket,
'Key' => $urn,
- 'UploadId' => $uploadId
+ 'UploadId' => $uploadId,
]);
}
+
+ public function getObjectMetaData(string $urn): array {
+ $object = $this->getConnection()->headObject([
+ 'Bucket' => $this->bucket,
+ 'Key' => $urn
+ ] + $this->getSSECParameters())->toArray();
+ return [
+ 'mtime' => $object['LastModified'],
+ 'etag' => trim($object['ETag'], '"'),
+ 'size' => (int)($object['Size'] ?? $object['ContentLength']),
+ ];
+ }
+
+ public function listObjects(string $prefix = ''): \Iterator {
+ $results = $this->getConnection()->getPaginator('ListObjectsV2', [
+ 'Bucket' => $this->bucket,
+ 'Prefix' => $prefix,
+ ] + $this->getSSECParameters());
+
+ foreach ($results as $result) {
+ if (is_array($result['Contents'])) {
+ foreach ($result['Contents'] as $object) {
+ yield [
+ 'urn' => basename($object['Key']),
+ 'metadata' => [
+ 'mtime' => $object['LastModified'],
+ 'etag' => trim($object['ETag'], '"'),
+ 'size' => (int)($object['Size'] ?? $object['ContentLength']),
+ ],
+ ];
+ }
+ }
+ }
+ }
}
diff --git a/lib/public/Files/Cache/ICacheEntry.php b/lib/public/Files/Cache/ICacheEntry.php
index 11d91e74105..28e673071fd 100644
--- a/lib/public/Files/Cache/ICacheEntry.php
+++ b/lib/public/Files/Cache/ICacheEntry.php
@@ -161,4 +161,12 @@ interface ICacheEntry extends ArrayAccess {
* @since 25.0.0
*/
public function getUnencryptedSize(): int;
+
+ /**
+ * Get the file id of the parent folder
+ *
+ * @return int
+ * @since 32.0.0
+ */
+ public function getParentId(): int;
}
diff --git a/lib/public/Files/ObjectStore/IObjectStoreMetaData.php b/lib/public/Files/ObjectStore/IObjectStoreMetaData.php
new file mode 100644
index 00000000000..8359e83f573
--- /dev/null
+++ b/lib/public/Files/ObjectStore/IObjectStoreMetaData.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+namespace OCP\Files\ObjectStore;
+
+/**
+ * Interface IObjectStoreMetaData
+ *
+ * @psalm-type ObjectMetaData = array{mtime?: \DateTime, etag?: string, size?: int, mimetype?: string, filename?: string}
+ *
+ * @since 32.0.0
+ */
+interface IObjectStoreMetaData {
+ /**
+ * Get metadata for an object.
+ *
+ * @param string $urn
+ * @return ObjectMetaData
+ *
+ * @since 32.0.0
+ */
+ public function getObjectMetaData(string $urn): array;
+
+ /**
+ * List all objects in the object store.
+ *
+ * If the object store implementation can do it efficiently, the metadata for each object is also included.
+ *
+ * @param string $prefix
+ * @return \Iterator<array{urn: string, metadata: ?ObjectMetaData}>
+ *
+ * @since 32.0.0
+ */
+ public function listObjects(string $prefix = ''): \Iterator;
+}
diff --git a/lib/public/Template.php b/lib/public/Template.php
index 20783d31cb6..3b31ee10a54 100644
--- a/lib/public/Template.php
+++ b/lib/public/Template.php
@@ -7,6 +7,8 @@
*/
namespace OCP;
+use OCP\Template\ITemplate;
+
/*
* We have to require the functions file because this class contains aliases to the functions
*/
@@ -19,7 +21,7 @@ require_once __DIR__ . '/../private/Template/functions.php';
* @since 8.0.0
* @deprecated 32.0.0 Use \OCP\Template\ITemplateManager instead
*/
-class Template extends \OC_Template {
+class Template extends \OC_Template implements ITemplate {
/**
* Make OC_Helper::imagePath available as a simple function
*
diff --git a/package-lock.json b/package-lock.json
index c4103896861..3d56fba57a7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25363,9 +25363,9 @@
}
},
"node_modules/vite": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.0.tgz",
- "integrity": "sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==",
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.3.tgz",
+ "integrity": "sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==",
"dev": true,
"license": "MIT",
"dependencies": {
diff --git a/tests/Core/Command/Config/App/SetConfigTest.php b/tests/Core/Command/Config/App/SetConfigTest.php
index 1d599bf3234..ffb7e424a0a 100644
--- a/tests/Core/Command/Config/App/SetConfigTest.php
+++ b/tests/Core/Command/Config/App/SetConfigTest.php
@@ -41,7 +41,7 @@ class SetConfigTest extends TestCase {
}
- public function setData() {
+ public static function dataSet() {
return [
[
'name',
@@ -63,7 +63,7 @@ class SetConfigTest extends TestCase {
}
/**
- * @dataProvider setData
+ * @dataProvider dataSet
*
* @param string $configName
* @param mixed $newValue
diff --git a/tests/Core/Command/Config/System/SetConfigTest.php b/tests/Core/Command/Config/System/SetConfigTest.php
index 2905af5c3d7..6ab624b7918 100644
--- a/tests/Core/Command/Config/System/SetConfigTest.php
+++ b/tests/Core/Command/Config/System/SetConfigTest.php
@@ -39,7 +39,7 @@ class SetConfigTest extends TestCase {
}
- public function setData() {
+ public static function dataTest() {
return [
[['name'], 'newvalue', null, 'newvalue'],
[['a', 'b', 'c'], 'foobar', null, ['b' => ['c' => 'foobar']]],
@@ -48,7 +48,7 @@ class SetConfigTest extends TestCase {
}
/**
- * @dataProvider setData
+ * @dataProvider dataTest
*
* @param array $configNames
* @param string $newValue
diff --git a/tests/Core/Command/Encryption/EnableTest.php b/tests/Core/Command/Encryption/EnableTest.php
index 2d463452add..e4f8ae9eacf 100644
--- a/tests/Core/Command/Encryption/EnableTest.php
+++ b/tests/Core/Command/Encryption/EnableTest.php
@@ -45,7 +45,7 @@ class EnableTest extends TestCase {
}
- public function dataEnable() {
+ public static function dataEnable(): array {
return [
['no', null, [], true, 'Encryption enabled', 'No encryption module is loaded'],
['yes', null, [], false, 'Encryption is already enabled', 'No encryption module is loaded'],
@@ -57,15 +57,8 @@ class EnableTest extends TestCase {
/**
* @dataProvider dataEnable
- *
- * @param string $oldStatus
- * @param string $defaultModule
- * @param array $availableModules
- * @param bool $isUpdating
- * @param string $expectedString
- * @param string $expectedDefaultModuleString
*/
- public function testEnable($oldStatus, $defaultModule, $availableModules, $isUpdating, $expectedString, $expectedDefaultModuleString): void {
+ public function testEnable(string $oldStatus, ?string $defaultModule, array $availableModules, bool $isUpdating, string $expectedString, string $expectedDefaultModuleString): void {
if ($isUpdating) {
$this->config->expects($this->once())
->method('setAppValue')
@@ -79,27 +72,30 @@ class EnableTest extends TestCase {
if (empty($availableModules)) {
$this->config->expects($this->once())
->method('getAppValue')
- ->with('core', 'encryption_enabled', $this->anything())
- ->willReturn($oldStatus);
+ ->willReturnMap([
+ ['core', 'encryption_enabled', 'no', $oldStatus],
+ ]);
} else {
$this->config->expects($this->exactly(2))
->method('getAppValue')
- ->withConsecutive(
- ['core', 'encryption_enabled', $this->anything()],
- ['core', 'default_encryption_module', $this->anything()],
- )->willReturnOnConsecutiveCalls(
- $oldStatus,
- $defaultModule,
- );
+ ->willReturnMap([
+ ['core', 'encryption_enabled', 'no', $oldStatus],
+ ['core', 'default_encryption_module', null, $defaultModule],
+ ]);
}
+ $calls = [
+ [$expectedString, 0],
+ ['', 0],
+ [$expectedDefaultModuleString, 0],
+ ];
$this->consoleOutput->expects($this->exactly(3))
->method('writeln')
- ->withConsecutive(
- [$this->stringContains($expectedString)],
- [''],
- [$this->stringContains($expectedDefaultModuleString)],
- );
+ ->willReturnCallback(function (string $message, int $level) use (&$calls): void {
+ $call = array_shift($calls);
+ $this->assertStringContainsString($call[0], $message);
+ $this->assertSame($call[1], $level);
+ });
self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
}
diff --git a/tests/Core/Command/Log/ManageTest.php b/tests/Core/Command/Log/ManageTest.php
index b354bb17076..9a21fe6dc56 100644
--- a/tests/Core/Command/Log/ManageTest.php
+++ b/tests/Core/Command/Log/ManageTest.php
@@ -87,7 +87,7 @@ class ManageTest extends TestCase {
self::invokePrivate($this->command, 'validateTimezone', ['Mars/OlympusMons']);
}
- public function convertLevelStringProvider() {
+ public static function dataConvertLevelString(): array {
return [
['dEbug', 0],
['inFO', 1],
@@ -100,9 +100,9 @@ class ManageTest extends TestCase {
}
/**
- * @dataProvider convertLevelStringProvider
+ * @dataProvider dataConvertLevelString
*/
- public function testConvertLevelString($levelString, $expectedInt): void {
+ public function testConvertLevelString(string $levelString, int $expectedInt): void {
$this->assertEquals($expectedInt,
self::invokePrivate($this->command, 'convertLevelString', [$levelString])
);
@@ -115,7 +115,7 @@ class ManageTest extends TestCase {
self::invokePrivate($this->command, 'convertLevelString', ['abc']);
}
- public function convertLevelNumberProvider() {
+ public static function dataConvertLevelNumber(): array {
return [
[0, 'Debug'],
[1, 'Info'],
@@ -126,9 +126,9 @@ class ManageTest extends TestCase {
}
/**
- * @dataProvider convertLevelNumberProvider
+ * @dataProvider dataConvertLevelNumber
*/
- public function testConvertLevelNumber($levelNum, $expectedString): void {
+ public function testConvertLevelNumber(int $levelNum, string $expectedString): void {
$this->assertEquals($expectedString,
self::invokePrivate($this->command, 'convertLevelNumber', [$levelNum])
);
@@ -144,23 +144,23 @@ class ManageTest extends TestCase {
public function testGetConfiguration(): void {
$this->config->expects($this->exactly(3))
->method('getSystemValue')
- ->withConsecutive(
- ['log_type', 'file'],
- ['loglevel', 2],
- ['logtimezone', 'UTC'],
- )->willReturnOnConsecutiveCalls(
- 'log_type_value',
- 0,
- 'logtimezone_value'
- );
+ ->willReturnMap([
+ ['log_type', 'file', 'log_type_value'],
+ ['loglevel', 2, 0],
+ ['logtimezone', 'UTC', 'logtimezone_value'],
+ ]);
+ $calls = [
+ ['Enabled logging backend: log_type_value'],
+ ['Log level: Debug (0)'],
+ ['Log timezone: logtimezone_value'],
+ ];
$this->consoleOutput->expects($this->exactly(3))
->method('writeln')
- ->withConsecutive(
- ['Enabled logging backend: log_type_value'],
- ['Log level: Debug (0)'],
- ['Log timezone: logtimezone_value'],
- );
+ ->willReturnCallback(function (string $message) use (&$calls): void {
+ $call = array_shift($calls);
+ $this->assertStringContainsString($call[0], $message);
+ });
self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
}
diff --git a/tests/Core/Command/User/AuthTokens/DeleteTest.php b/tests/Core/Command/User/AuthTokens/DeleteTest.php
index 8588c1d5d54..1396fe53084 100644
--- a/tests/Core/Command/User/AuthTokens/DeleteTest.php
+++ b/tests/Core/Command/User/AuthTokens/DeleteTest.php
@@ -40,8 +40,10 @@ class DeleteTest extends TestCase {
public function testDeleteTokenById(): void {
$this->consoleInput->expects($this->exactly(2))
->method('getArgument')
- ->withConsecutive(['uid'], ['id'])
- ->willReturnOnConsecutiveCalls('user', 42);
+ ->willReturnMap([
+ ['uid', 'user'],
+ ['id', '42']
+ ]);
$this->consoleInput->expects($this->once())
->method('getOption')
@@ -59,8 +61,10 @@ class DeleteTest extends TestCase {
public function testDeleteTokenByIdRequiresTokenId(): void {
$this->consoleInput->expects($this->exactly(2))
->method('getArgument')
- ->withConsecutive(['uid'], ['id'])
- ->willReturnOnConsecutiveCalls('user', null);
+ ->willReturnMap([
+ ['uid', 'user'],
+ ['id', null]
+ ]);
$this->consoleInput->expects($this->once())
->method('getOption')
@@ -78,8 +82,10 @@ class DeleteTest extends TestCase {
public function testDeleteTokensLastUsedBefore(): void {
$this->consoleInput->expects($this->exactly(2))
->method('getArgument')
- ->withConsecutive(['uid'], ['id'])
- ->willReturnOnConsecutiveCalls('user', null);
+ ->willReturnMap([
+ ['uid', 'user'],
+ ['id', null]
+ ]);
$this->consoleInput->expects($this->once())
->method('getOption')
@@ -97,8 +103,10 @@ class DeleteTest extends TestCase {
public function testLastUsedBeforeAcceptsIso8601Expanded(): void {
$this->consoleInput->expects($this->exactly(2))
->method('getArgument')
- ->withConsecutive(['uid'], ['id'])
- ->willReturnOnConsecutiveCalls('user', null);
+ ->willReturnMap([
+ ['uid', 'user'],
+ ['id', null]
+ ]);
$this->consoleInput->expects($this->once())
->method('getOption')
@@ -116,8 +124,10 @@ class DeleteTest extends TestCase {
public function testLastUsedBeforeAcceptsYmd(): void {
$this->consoleInput->expects($this->exactly(2))
->method('getArgument')
- ->withConsecutive(['uid'], ['id'])
- ->willReturnOnConsecutiveCalls('user', null);
+ ->willReturnMap([
+ ['uid', 'user'],
+ ['id', null]
+ ]);
$this->consoleInput->expects($this->once())
->method('getOption')
@@ -135,8 +145,10 @@ class DeleteTest extends TestCase {
public function testIdAndLastUsedBeforeAreMutuallyExclusive(): void {
$this->consoleInput->expects($this->exactly(2))
->method('getArgument')
- ->withConsecutive(['uid'], ['id'])
- ->willReturnOnConsecutiveCalls('user', 42);
+ ->willReturnMap([
+ ['uid', 'user'],
+ ['id', '42']
+ ]);
$this->consoleInput->expects($this->once())
->method('getOption')
diff --git a/tests/Core/Controller/NavigationControllerTest.php b/tests/Core/Controller/NavigationControllerTest.php
index 4995bd2fed0..7ebfbc139cd 100644
--- a/tests/Core/Controller/NavigationControllerTest.php
+++ b/tests/Core/Controller/NavigationControllerTest.php
@@ -42,13 +42,14 @@ class NavigationControllerTest extends TestCase {
);
}
- public function dataGetNavigation() {
+ public static function dataGetNavigation(): array {
return [
- [false], [true]
+ [false],
+ [true],
];
}
/** @dataProvider dataGetNavigation */
- public function testGetAppNavigation($absolute): void {
+ public function testGetAppNavigation(bool $absolute): void {
$this->navigationManager->expects($this->once())
->method('getAll')
->with('link')
@@ -59,11 +60,10 @@ class NavigationControllerTest extends TestCase {
->willReturn('http://localhost/');
$this->urlGenerator->expects($this->exactly(2))
->method('getAbsoluteURL')
- ->withConsecutive(['/index.php/apps/files'], ['icon'])
- ->willReturnOnConsecutiveCalls(
- 'http://localhost/index.php/apps/files',
- 'http://localhost/icon'
- );
+ ->willReturnMap([
+ ['/index.php/apps/files', 'http://localhost/index.php/apps/files'],
+ ['icon', 'http://localhost/icon'],
+ ]);
$actual = $this->controller->getAppsNavigation($absolute);
$this->assertInstanceOf(DataResponse::class, $actual);
$this->assertEquals('http://localhost/index.php/apps/files', $actual->getData()[0]['href']);
@@ -77,7 +77,7 @@ class NavigationControllerTest extends TestCase {
}
/** @dataProvider dataGetNavigation */
- public function testGetSettingsNavigation($absolute): void {
+ public function testGetSettingsNavigation(bool $absolute): void {
$this->navigationManager->expects($this->once())
->method('getAll')
->with('settings')
@@ -88,14 +88,10 @@ class NavigationControllerTest extends TestCase {
->willReturn('http://localhost/');
$this->urlGenerator->expects($this->exactly(2))
->method('getAbsoluteURL')
- ->withConsecutive(
- ['/index.php/settings/user'],
- ['/core/img/settings.svg']
- )
- ->willReturnOnConsecutiveCalls(
- 'http://localhost/index.php/settings/user',
- 'http://localhost/core/img/settings.svg'
- );
+ ->willReturnMap([
+ ['/index.php/settings/user', 'http://localhost/index.php/settings/user'],
+ ['/core/img/settings.svg', 'http://localhost/core/img/settings.svg']
+ ]);
$actual = $this->controller->getSettingsNavigation($absolute);
$this->assertInstanceOf(DataResponse::class, $actual);
$this->assertEquals('http://localhost/index.php/settings/user', $actual->getData()[0]['href']);
diff --git a/tests/lib/AppFramework/Http/RequestIdTest.php b/tests/lib/AppFramework/Http/RequestIdTest.php
index b3cfe2a8f4a..9cfd3b1785c 100644
--- a/tests/lib/AppFramework/Http/RequestIdTest.php
+++ b/tests/lib/AppFramework/Http/RequestIdTest.php
@@ -49,11 +49,7 @@ class RequestIdTest extends \Test\TestCase {
$this->secureRandom->expects($this->once())
->method('generate')
->with('20')
- ->willReturnOnConsecutiveCalls(
- 'GeneratedByNextcloudItself1',
- 'GeneratedByNextcloudItself2',
- 'GeneratedByNextcloudItself3'
- );
+ ->willReturn('GeneratedByNextcloudItself1');
$this->assertSame('GeneratedByNextcloudItself1', $requestId->getId());
$this->assertSame('GeneratedByNextcloudItself1', $requestId->getId());
diff --git a/tests/lib/AppFramework/Http/RequestTest.php b/tests/lib/AppFramework/Http/RequestTest.php
index fe3614ab88e..781cca256ec 100644
--- a/tests/lib/AppFramework/Http/RequestTest.php
+++ b/tests/lib/AppFramework/Http/RequestTest.php
@@ -251,7 +251,7 @@ class RequestTest extends \Test\TestCase {
$this->assertSame('someothertestvalue', $result['propertyB']);
}
- public function notJsonDataProvider() {
+ public static function dataNotJsonData(): array {
return [
['this is not valid json'],
['"just a string"'],
@@ -260,9 +260,9 @@ class RequestTest extends \Test\TestCase {
}
/**
- * @dataProvider notJsonDataProvider
+ * @dataProvider dataNotJsonData
*/
- public function testNotJsonPost($testData): void {
+ public function testNotJsonPost(string $testData): void {
global $data;
$data = $testData;
$vars = [
@@ -544,7 +544,7 @@ class RequestTest extends \Test\TestCase {
$this->assertEquals('3', $request->getParams()['id']);
}
- public function dataGetRemoteAddress(): array {
+ public static function dataGetRemoteAddress(): array {
return [
'IPv4 without trusted remote' => [
[
@@ -714,14 +714,10 @@ class RequestTest extends \Test\TestCase {
public function testGetRemoteAddress(array $headers, array $trustedProxies, array $forwardedForHeaders, string $expected): void {
$this->config
->method('getSystemValue')
- ->withConsecutive(
- ['trusted_proxies'],
- ['forwarded_for_headers'],
- )
- ->willReturnOnConsecutiveCalls(
- $trustedProxies,
- $forwardedForHeaders,
- );
+ ->willReturnMap([
+ ['trusted_proxies', [], $trustedProxies],
+ ['forwarded_for_headers', ['HTTP_X_FORWARDED_FOR'], $forwardedForHeaders],
+ ]);
$request = new Request(
[
@@ -736,10 +732,7 @@ class RequestTest extends \Test\TestCase {
$this->assertSame($expected, $request->getRemoteAddress());
}
- /**
- * @return array
- */
- public function httpProtocolProvider() {
+ public static function dataHttpProtocol(): array {
return [
// Valid HTTP 1.0
['HTTP/1.0', 'HTTP/1.0'],
@@ -766,7 +759,7 @@ class RequestTest extends \Test\TestCase {
}
/**
- * @dataProvider httpProtocolProvider
+ * @dataProvider dataHttpProtocol
*
* @param mixed $input
* @param string $expected
@@ -956,7 +949,7 @@ class RequestTest extends \Test\TestCase {
}
/**
- * @dataProvider userAgentProvider
+ * @dataProvider dataUserAgent
* @param string $testAgent
* @param array $userAgent
* @param bool $matches
@@ -978,7 +971,7 @@ class RequestTest extends \Test\TestCase {
}
/**
- * @dataProvider userAgentProvider
+ * @dataProvider dataUserAgent
* @param string $testAgent
* @param array $userAgent
* @param bool $matches
@@ -995,10 +988,7 @@ class RequestTest extends \Test\TestCase {
$this->assertFalse($request->isUserAgent($userAgent));
}
- /**
- * @return array
- */
- public function userAgentProvider() {
+ public static function dataUserAgent(): array {
return [
[
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
@@ -1117,7 +1107,7 @@ class RequestTest extends \Test\TestCase {
];
}
- public function dataMatchClientVersion(): array {
+ public static function dataMatchClientVersion(): array {
return [
[
'Mozilla/5.0 (Android) Nextcloud-android/3.24.1',
@@ -1373,10 +1363,7 @@ class RequestTest extends \Test\TestCase {
$this->assertSame('', $request->getServerHost());
}
- /**
- * @return array
- */
- public function dataGetServerHostTrustedDomain() {
+ public static function dataGetServerHostTrustedDomain(): array {
return [
'is array' => ['my.trusted.host', ['my.trusted.host']],
'is array but undefined index 0' => ['my.trusted.host', [2 => 'my.trusted.host']],
@@ -1387,10 +1374,8 @@ class RequestTest extends \Test\TestCase {
/**
* @dataProvider dataGetServerHostTrustedDomain
- * @param $expected
- * @param $trustedDomain
*/
- public function testGetServerHostTrustedDomain($expected, $trustedDomain): void {
+ public function testGetServerHostTrustedDomain(string $expected, $trustedDomain): void {
$this->config
->method('getSystemValue')
->willReturnCallback(function ($key, $default) use ($trustedDomain) {
@@ -1499,7 +1484,7 @@ class RequestTest extends \Test\TestCase {
}
/**
- * @dataProvider genericPathInfoProvider
+ * @dataProvider dataGenericPathInfo
* @param string $requestUri
* @param string $scriptName
* @param string $expected
@@ -1522,7 +1507,7 @@ class RequestTest extends \Test\TestCase {
}
/**
- * @dataProvider genericPathInfoProvider
+ * @dataProvider dataGenericPathInfo
* @param string $requestUri
* @param string $scriptName
* @param string $expected
@@ -1545,7 +1530,7 @@ class RequestTest extends \Test\TestCase {
}
/**
- * @dataProvider rawPathInfoProvider
+ * @dataProvider dataRawPathInfo
* @param string $requestUri
* @param string $scriptName
* @param string $expected
@@ -1568,7 +1553,7 @@ class RequestTest extends \Test\TestCase {
}
/**
- * @dataProvider pathInfoProvider
+ * @dataProvider dataPathInfo
* @param string $requestUri
* @param string $scriptName
* @param string $expected
@@ -1590,10 +1575,7 @@ class RequestTest extends \Test\TestCase {
$this->assertSame($expected, $request->getPathInfo());
}
- /**
- * @return array
- */
- public function genericPathInfoProvider() {
+ public static function dataGenericPathInfo(): array {
return [
['/core/index.php?XDEBUG_SESSION_START=14600', '/core/index.php', ''],
['/index.php/apps/files/', 'index.php', '/apps/files/'],
@@ -1605,19 +1587,13 @@ class RequestTest extends \Test\TestCase {
];
}
- /**
- * @return array
- */
- public function rawPathInfoProvider() {
+ public static function dataRawPathInfo(): array {
return [
['/foo%2Fbar/subfolder', '', 'foo%2Fbar/subfolder'],
];
}
- /**
- * @return array
- */
- public function pathInfoProvider() {
+ public static function dataPathInfo(): array {
return [
['/foo%2Fbar/subfolder', '', 'foo/bar/subfolder'],
];
@@ -1645,7 +1621,7 @@ class RequestTest extends \Test\TestCase {
$this->assertSame('/test.php', $request->getRequestUri());
}
- public function providesGetRequestUriWithOverwriteData() {
+ public static function dataGetRequestUriWithOverwrite(): array {
return [
['/scriptname.php/some/PathInfo', '/owncloud/', ''],
['/scriptname.php/some/PathInfo', '/owncloud/', '123', '123.123.123.123'],
@@ -1653,7 +1629,7 @@ class RequestTest extends \Test\TestCase {
}
/**
- * @dataProvider providesGetRequestUriWithOverwriteData
+ * @dataProvider dataGetRequestUriWithOverwrite
*/
public function testGetRequestUriWithOverwrite($expectedUri, $overwriteWebRoot, $overwriteCondAddr, $remoteAddr = ''): void {
$this->config
@@ -1665,7 +1641,7 @@ class RequestTest extends \Test\TestCase {
]);
$request = $this->getMockBuilder(Request::class)
- ->setMethods(['getScriptName'])
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
@@ -1690,8 +1666,8 @@ class RequestTest extends \Test\TestCase {
public function testPassesCSRFCheckWithGet(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'get' => [
@@ -1720,8 +1696,8 @@ class RequestTest extends \Test\TestCase {
public function testPassesCSRFCheckWithPost(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'post' => [
@@ -1750,8 +1726,8 @@ class RequestTest extends \Test\TestCase {
public function testPassesCSRFCheckWithHeader(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
@@ -1780,8 +1756,8 @@ class RequestTest extends \Test\TestCase {
public function testPassesCSRFCheckWithGetAndWithoutCookies(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'get' => [
@@ -1804,8 +1780,8 @@ class RequestTest extends \Test\TestCase {
public function testPassesCSRFCheckWithPostAndWithoutCookies(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'post' => [
@@ -1828,8 +1804,8 @@ class RequestTest extends \Test\TestCase {
public function testPassesCSRFCheckWithHeaderAndWithoutCookies(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
@@ -1852,8 +1828,8 @@ class RequestTest extends \Test\TestCase {
public function testFailsCSRFCheckWithHeaderAndNotAllChecksPassing(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
@@ -1879,8 +1855,8 @@ class RequestTest extends \Test\TestCase {
public function testPassesStrictCookieCheckWithAllCookiesAndStrict(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName', 'getCookieParams'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName', 'getCookieParams'])
->setConstructorArgs([
[
'server' => [
@@ -1911,8 +1887,8 @@ class RequestTest extends \Test\TestCase {
public function testFailsStrictCookieCheckWithAllCookiesAndMissingStrict(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName', 'getCookieParams'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName', 'getCookieParams'])
->setConstructorArgs([
[
'server' => [
@@ -1944,7 +1920,7 @@ class RequestTest extends \Test\TestCase {
public function testGetCookieParams(): void {
/** @var Request $request */
$request = $this->getMockBuilder(Request::class)
- ->setMethods(['getScriptName'])
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[],
$this->requestId,
@@ -1959,8 +1935,8 @@ class RequestTest extends \Test\TestCase {
public function testPassesStrictCookieCheckWithAllCookies(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
@@ -1984,8 +1960,8 @@ class RequestTest extends \Test\TestCase {
public function testPassesStrictCookieCheckWithRandomCookies(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
@@ -2007,8 +1983,8 @@ class RequestTest extends \Test\TestCase {
public function testFailsStrictCookieCheckWithSessionCookie(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
@@ -2030,8 +2006,8 @@ class RequestTest extends \Test\TestCase {
public function testFailsStrictCookieCheckWithRememberMeCookie(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
@@ -2053,8 +2029,8 @@ class RequestTest extends \Test\TestCase {
public function testFailsCSRFCheckWithPostAndWithCookies(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'post' => [
@@ -2080,8 +2056,8 @@ class RequestTest extends \Test\TestCase {
public function testFailStrictCookieCheckWithOnlyLaxCookie(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
@@ -2104,8 +2080,8 @@ class RequestTest extends \Test\TestCase {
public function testFailStrictCookieCheckWithOnlyStrictCookie(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
@@ -2128,8 +2104,8 @@ class RequestTest extends \Test\TestCase {
public function testPassesLaxCookieCheck(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
@@ -2152,8 +2128,8 @@ class RequestTest extends \Test\TestCase {
public function testFailsLaxCookieCheckWithOnlyStrictCookie(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
@@ -2176,8 +2152,8 @@ class RequestTest extends \Test\TestCase {
public function testSkipCookieCheckForOCSRequests(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
@@ -2199,10 +2175,7 @@ class RequestTest extends \Test\TestCase {
$this->assertTrue($request->passesStrictCookieCheck());
}
- /**
- * @return array
- */
- public function invalidTokenDataProvider() {
+ public static function dataInvalidToken(): array {
return [
['InvalidSentToken'],
['InvalidSentToken:InvalidSecret'],
@@ -2211,13 +2184,12 @@ class RequestTest extends \Test\TestCase {
}
/**
- * @dataProvider invalidTokenDataProvider
- * @param string $invalidToken
+ * @dataProvider dataInvalidToken
*/
- public function testPassesCSRFCheckWithInvalidToken($invalidToken): void {
+ public function testPassesCSRFCheckWithInvalidToken(string $invalidToken): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
@@ -2243,8 +2215,8 @@ class RequestTest extends \Test\TestCase {
public function testPassesCSRFCheckWithoutTokenFail(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[],
$this->requestId,
@@ -2259,8 +2231,8 @@ class RequestTest extends \Test\TestCase {
public function testPassesCSRFCheckWithOCSAPIRequestHeader(): void {
/** @var Request $request */
- $request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
- ->setMethods(['getScriptName'])
+ $request = $this->getMockBuilder(Request::class)
+ ->onlyMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
diff --git a/tests/lib/Template/JSCombinerTest.php b/tests/lib/Template/JSCombinerTest.php
index 63a52f34047..e4e6594c05c 100644
--- a/tests/lib/Template/JSCombinerTest.php
+++ b/tests/lib/Template/JSCombinerTest.php
@@ -70,14 +70,10 @@ class JSCombinerTest extends \Test\TestCase {
$this->config
->expects($this->exactly(2))
->method('getValue')
- ->withConsecutive(
- ['debug'],
- ['installed']
- )
- ->willReturnOnConsecutiveCalls(
- false,
- false
- );
+ ->willReturnMap([
+ ['debug', false],
+ ['installed', false]
+ ]);
$actual = $this->jsCombiner->process(__DIR__, '/data/combine.json', 'awesomeapp');
$this->assertFalse($actual);
@@ -87,14 +83,10 @@ class JSCombinerTest extends \Test\TestCase {
$this->config
->expects($this->exactly(2))
->method('getValue')
- ->withConsecutive(
- ['debug'],
- ['installed']
- )
- ->willReturnOnConsecutiveCalls(
- false,
- true
- );
+ ->willReturnMap([
+ ['debug', '', false],
+ ['installed', '', true],
+ ]);
$folder = $this->createMock(ISimpleFolder::class);
$this->appData->expects($this->once())->method('getFolder')->with('awesomeapp')->willThrowException(new NotFoundException());
$this->appData->expects($this->once())->method('newFolder')->with('awesomeapp')->willReturn($folder);
@@ -127,14 +119,10 @@ class JSCombinerTest extends \Test\TestCase {
$this->config
->expects($this->exactly(2))
->method('getValue')
- ->withConsecutive(
- ['debug'],
- ['installed']
- )
- ->willReturnOnConsecutiveCalls(
- false,
- true
- );
+ ->willReturnMap([
+ ['debug', '', false],
+ ['installed', '', true],
+ ]);
$folder = $this->createMock(ISimpleFolder::class);
$this->appData->expects($this->once())->method('getFolder')->with('awesomeapp')->willReturn($folder);
$file = $this->createMock(ISimpleFile::class);
@@ -165,14 +153,10 @@ class JSCombinerTest extends \Test\TestCase {
$this->config
->expects($this->exactly(2))
->method('getValue')
- ->withConsecutive(
- ['debug'],
- ['installed']
- )
- ->willReturnOnConsecutiveCalls(
- false,
- true
- );
+ ->willReturnMap([
+ ['debug', '', false],
+ ['installed', '', true],
+ ]);
$folder = $this->createMock(ISimpleFolder::class);
$this->appData->expects($this->once())->method('getFolder')->with('awesomeapp')->willReturn($folder);
$file = $this->createMock(ISimpleFile::class);
@@ -206,14 +190,10 @@ class JSCombinerTest extends \Test\TestCase {
$this->config
->expects($this->exactly(2))
->method('getValue')
- ->withConsecutive(
- ['debug'],
- ['installed']
- )
- ->willReturnOnConsecutiveCalls(
- false,
- true
- );
+ ->willReturnMap([
+ ['debug', '', false],
+ ['installed', '', true],
+ ]);
$folder = $this->createMock(ISimpleFolder::class);
$this->appData->expects($this->once())
->method('getFolder')
@@ -395,15 +375,11 @@ class JSCombinerTest extends \Test\TestCase {
$folder->expects($this->exactly(3))
->method('getFile')
- ->withConsecutive(
- [$fileName],
- [$fileName . '.deps'],
- [$fileName . '.gzip']
- )->willReturnOnConsecutiveCalls(
- $file,
- $depsFile,
- $gzFile
- );
+ ->willReturnMap([
+ [$fileName, $file],
+ [$fileName . '.deps', $depsFile],
+ [$fileName . '.gzip', $gzFile]
+ ]);
$file->expects($this->once())
->method('putContent')
@@ -484,7 +460,7 @@ var b = \'world\';
$this->assertTrue($actual);
}
- public function dataGetCachedSCSS() {
+ public static function dataGetCachedSCSS(): array {
return [
['awesomeapp', 'core/js/foo.json', '/js/core/foo.js'],
['files', 'apps/files/js/foo.json', '/js/files/foo.js']
diff --git a/tests/lib/User/ManagerTest.php b/tests/lib/User/ManagerTest.php
index 53f57eee086..53d63ea6758 100644
--- a/tests/lib/User/ManagerTest.php
+++ b/tests/lib/User/ManagerTest.php
@@ -305,7 +305,7 @@ class ManagerTest extends TestCase {
$this->assertEquals('foo3', array_shift($result)->getUID());
}
- public function dataCreateUserInvalid() {
+ public static function dataCreateUserInvalid(): array {
return [
['te?st', 'foo', 'Only the following characters are allowed in a username:'
. ' "a-z", "A-Z", "0-9", spaces and "_.@-\'"'],
@@ -760,16 +760,11 @@ class ManagerTest extends TestCase {
$backend = $this->createMock(\Test\Util\User\Dummy::class);
$backend->expects($this->exactly(3))
->method('userExists')
- ->withConsecutive(
- [$this->equalTo('uid1')],
- [$this->equalTo('uid99')],
- [$this->equalTo('uid2')]
- )
- ->willReturnOnConsecutiveCalls(
- true,
- false,
- true
- );
+ ->willReturnMap([
+ ['uid1', true],
+ ['uid99', false],
+ ['uid2', true]
+ ]);
$manager = new \OC\User\Manager($config, $this->cacheFactory, $this->eventDispatcher, $this->logger);
$manager->registerBackend($backend);