summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
m---------3rdparty0
-rw-r--r--apps/accessibility/composer/autoload.php5
-rw-r--r--apps/accessibility/composer/composer/autoload_real.php2
-rw-r--r--apps/admin_audit/composer/autoload.php5
-rw-r--r--apps/admin_audit/composer/composer/autoload_real.php2
-rw-r--r--apps/cloud_federation_api/composer/autoload.php5
-rw-r--r--apps/cloud_federation_api/composer/composer/autoload_real.php2
-rw-r--r--apps/comments/composer/autoload.php5
-rw-r--r--apps/comments/composer/composer/autoload_real.php2
-rw-r--r--apps/contactsinteraction/composer/autoload.php5
-rw-r--r--apps/contactsinteraction/composer/composer/autoload_real.php2
-rw-r--r--apps/dav/composer/autoload.php5
-rw-r--r--apps/dav/composer/composer/autoload_real.php2
-rw-r--r--apps/dav/composer/composer/installed.php4
-rw-r--r--apps/dav/lib/Connector/Sabre/Directory.php5
-rw-r--r--apps/dav/lib/Connector/Sabre/File.php16
-rw-r--r--apps/dav/lib/Connector/Sabre/FilesPlugin.php53
-rw-r--r--apps/dav/lib/Files/FileSearchBackend.php59
-rw-r--r--apps/dav/lib/Files/LazySearchBackend.php24
-rw-r--r--apps/encryption/composer/autoload.php5
-rw-r--r--apps/encryption/composer/composer/autoload_real.php2
-rw-r--r--apps/federatedfilesharing/composer/autoload.php5
-rw-r--r--apps/federatedfilesharing/composer/composer/autoload_real.php2
-rw-r--r--apps/federation/composer/autoload.php5
-rw-r--r--apps/federation/composer/composer/autoload_real.php2
-rw-r--r--apps/files/composer/autoload.php5
-rw-r--r--apps/files/composer/composer/autoload_real.php2
-rw-r--r--apps/files_sharing/composer/autoload.php5
-rw-r--r--apps/files_sharing/composer/composer/autoload_real.php2
-rw-r--r--apps/files_trashbin/composer/autoload.php5
-rw-r--r--apps/files_trashbin/composer/composer/autoload_real.php2
-rw-r--r--apps/files_versions/composer/autoload.php5
-rw-r--r--apps/files_versions/composer/composer/autoload_real.php2
-rw-r--r--apps/lookup_server_connector/composer/autoload.php5
-rw-r--r--apps/lookup_server_connector/composer/composer/autoload_real.php2
-rw-r--r--apps/oauth2/composer/autoload.php5
-rw-r--r--apps/oauth2/composer/composer/autoload_real.php2
-rw-r--r--apps/provisioning_api/composer/autoload.php5
-rw-r--r--apps/provisioning_api/composer/composer/autoload_real.php2
-rw-r--r--apps/settings/composer/autoload.php5
-rw-r--r--apps/settings/composer/composer/autoload_real.php2
-rw-r--r--apps/sharebymail/composer/autoload.php5
-rw-r--r--apps/sharebymail/composer/composer/autoload_real.php2
-rw-r--r--apps/systemtags/composer/autoload.php5
-rw-r--r--apps/systemtags/composer/composer/autoload_real.php2
-rw-r--r--apps/testing/composer/autoload.php5
-rw-r--r--apps/testing/composer/composer/autoload_real.php2
-rw-r--r--apps/twofactor_backupcodes/composer/autoload.php5
-rw-r--r--apps/twofactor_backupcodes/composer/composer/autoload_real.php2
-rw-r--r--apps/updatenotification/composer/autoload.php5
-rw-r--r--apps/updatenotification/composer/composer/autoload_real.php2
-rw-r--r--apps/user_ldap/composer/autoload.php5
-rw-r--r--apps/user_ldap/composer/composer/autoload_real.php2
-rw-r--r--apps/user_status/composer/autoload.php5
-rw-r--r--apps/user_status/composer/composer/autoload_real.php2
-rw-r--r--apps/workflowengine/composer/autoload.php5
-rw-r--r--apps/workflowengine/composer/composer/autoload_real.php2
-rw-r--r--build/psalm-baseline.xml11
-rw-r--r--config/config.sample.php11
-rw-r--r--core/Application.php15
-rw-r--r--core/Migrations/Version240000Date20220404230027.php62
-rw-r--r--lib/composer/autoload.php5
-rw-r--r--lib/composer/composer/InstalledVersions.php4
-rw-r--r--lib/composer/composer/autoload_classmap.php9
-rw-r--r--lib/composer/composer/autoload_real.php2
-rw-r--r--lib/composer/composer/autoload_static.php9
-rw-r--r--lib/composer/composer/installed.php4
-rw-r--r--lib/private/Files/ObjectStore/NoopScanner.php2
-rw-r--r--lib/private/Metadata/Capabilities.php44
-rw-r--r--lib/private/Metadata/FileEventListener.php84
-rw-r--r--lib/private/Metadata/FileMetadata.php43
-rw-r--r--lib/private/Metadata/FileMetadataMapper.php105
-rw-r--r--lib/private/Metadata/IMetadataManager.php35
-rw-r--r--lib/private/Metadata/IMetadataProvider.php41
-rw-r--r--lib/private/Metadata/MetadataManager.php105
-rw-r--r--lib/private/Metadata/Provider/ExifProvider.php59
-rw-r--r--lib/private/Server.php12
-rw-r--r--lib/public/AppFramework/Db/Entity.php4
-rw-r--r--lib/public/AppFramework/Db/QBMapper.php2
-rw-r--r--lib/public/DB/QueryBuilder/IQueryBuilder.php5
-rw-r--r--lib/public/DB/Types.php6
-rw-r--r--tests/lib/AppFramework/Db/QBMapperTest.php21
-rw-r--r--tests/lib/DB/MigratorTest.php2
-rw-r--r--tests/lib/Metadata/FileMetadataMapperTest.php83
-rw-r--r--version.php2
85 files changed, 1043 insertions, 80 deletions
diff --git a/3rdparty b/3rdparty
-Subproject d80ec1fa2dad1c3ede272583e3c4f1f77f40141
+Subproject 6176112be9428026897d958dc2b558d1bde4fec
diff --git a/apps/accessibility/composer/autoload.php b/apps/accessibility/composer/autoload.php
index f624ded3950..6f896b45abc 100644
--- a/apps/accessibility/composer/autoload.php
+++ b/apps/accessibility/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitAccessibility::getLoader();
diff --git a/apps/accessibility/composer/composer/autoload_real.php b/apps/accessibility/composer/composer/autoload_real.php
index a08983b79fe..8b2b83d3139 100644
--- a/apps/accessibility/composer/composer/autoload_real.php
+++ b/apps/accessibility/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitAccessibility
spl_autoload_unregister(array('ComposerAutoloaderInitAccessibility', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitAccessibility::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitAccessibility::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/admin_audit/composer/autoload.php b/apps/admin_audit/composer/autoload.php
index 7970e9ebe12..d316fe42c51 100644
--- a/apps/admin_audit/composer/autoload.php
+++ b/apps/admin_audit/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitAdminAudit::getLoader();
diff --git a/apps/admin_audit/composer/composer/autoload_real.php b/apps/admin_audit/composer/composer/autoload_real.php
index ffbbdd4e269..bd7d1f99dd1 100644
--- a/apps/admin_audit/composer/composer/autoload_real.php
+++ b/apps/admin_audit/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitAdminAudit
spl_autoload_unregister(array('ComposerAutoloaderInitAdminAudit', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitAdminAudit::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitAdminAudit::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/cloud_federation_api/composer/autoload.php b/apps/cloud_federation_api/composer/autoload.php
index fcf0f062846..fc52f01bfaf 100644
--- a/apps/cloud_federation_api/composer/autoload.php
+++ b/apps/cloud_federation_api/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitCloudFederationAPI::getLoader();
diff --git a/apps/cloud_federation_api/composer/composer/autoload_real.php b/apps/cloud_federation_api/composer/composer/autoload_real.php
index 1c7ec9607c2..53093c129e3 100644
--- a/apps/cloud_federation_api/composer/composer/autoload_real.php
+++ b/apps/cloud_federation_api/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitCloudFederationAPI
spl_autoload_unregister(array('ComposerAutoloaderInitCloudFederationAPI', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitCloudFederationAPI::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitCloudFederationAPI::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/comments/composer/autoload.php b/apps/comments/composer/autoload.php
index c974072d6b7..46d800ddaa8 100644
--- a/apps/comments/composer/autoload.php
+++ b/apps/comments/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitComments::getLoader();
diff --git a/apps/comments/composer/composer/autoload_real.php b/apps/comments/composer/composer/autoload_real.php
index 8668cfb671e..7f9d22ca0a2 100644
--- a/apps/comments/composer/composer/autoload_real.php
+++ b/apps/comments/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitComments
spl_autoload_unregister(array('ComposerAutoloaderInitComments', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitComments::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitComments::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/contactsinteraction/composer/autoload.php b/apps/contactsinteraction/composer/autoload.php
index 7bf597cd9cd..748e5f45fe9 100644
--- a/apps/contactsinteraction/composer/autoload.php
+++ b/apps/contactsinteraction/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitContactsInteraction::getLoader();
diff --git a/apps/contactsinteraction/composer/composer/autoload_real.php b/apps/contactsinteraction/composer/composer/autoload_real.php
index 8ba09879f54..09f95c83645 100644
--- a/apps/contactsinteraction/composer/composer/autoload_real.php
+++ b/apps/contactsinteraction/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitContactsInteraction
spl_autoload_unregister(array('ComposerAutoloaderInitContactsInteraction', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitContactsInteraction::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitContactsInteraction::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/dav/composer/autoload.php b/apps/dav/composer/autoload.php
index 06b2e993e94..a3040af8caa 100644
--- a/apps/dav/composer/autoload.php
+++ b/apps/dav/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitDAV::getLoader();
diff --git a/apps/dav/composer/composer/autoload_real.php b/apps/dav/composer/composer/autoload_real.php
index 8416efa9d7e..4b2290344f5 100644
--- a/apps/dav/composer/composer/autoload_real.php
+++ b/apps/dav/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitDAV
spl_autoload_unregister(array('ComposerAutoloaderInitDAV', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitDAV::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitDAV::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/dav/composer/composer/installed.php b/apps/dav/composer/composer/installed.php
index baf72c4fb34..628db5d793b 100644
--- a/apps/dav/composer/composer/installed.php
+++ b/apps/dav/composer/composer/installed.php
@@ -5,7 +5,7 @@
'type' => 'library',
'install_path' => __DIR__ . '/../',
'aliases' => array(),
- 'reference' => 'e2c675724fc4ea50f1275bf0027b96f277c32578',
+ 'reference' => '9586920c0ec4016864a2219e838fb272127822d8',
'name' => '__root__',
'dev' => false,
),
@@ -16,7 +16,7 @@
'type' => 'library',
'install_path' => __DIR__ . '/../',
'aliases' => array(),
- 'reference' => 'e2c675724fc4ea50f1275bf0027b96f277c32578',
+ 'reference' => '9586920c0ec4016864a2219e838fb272127822d8',
'dev_requirement' => false,
),
),
diff --git a/apps/dav/lib/Connector/Sabre/Directory.php b/apps/dav/lib/Connector/Sabre/Directory.php
index 8b616b0cb8a..9e0b89596cd 100644
--- a/apps/dav/lib/Connector/Sabre/Directory.php
+++ b/apps/dav/lib/Connector/Sabre/Directory.php
@@ -34,6 +34,8 @@ namespace OCA\DAV\Connector\Sabre;
use OC\Files\Mount\MoveableMount;
use OC\Files\View;
+use OC\Metadata\FileMetadata;
+use OC\Metadata\MetadataGroup;
use OCA\DAV\Connector\Sabre\Exception\FileLocked;
use OCA\DAV\Connector\Sabre\Exception\Forbidden;
use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
@@ -73,6 +75,9 @@ class Directory extends \OCA\DAV\Connector\Sabre\Node implements \Sabre\DAV\ICol
*/
private $tree;
+ /** @var array<string, array<int, FileMetadata>> */
+ private array $metadata = [];
+
/**
* Sets up the node, expects a full path name
*
diff --git a/apps/dav/lib/Connector/Sabre/File.php b/apps/dav/lib/Connector/Sabre/File.php
index a46ca372be7..6c379984995 100644
--- a/apps/dav/lib/Connector/Sabre/File.php
+++ b/apps/dav/lib/Connector/Sabre/File.php
@@ -43,6 +43,7 @@ use OC\AppFramework\Http\Request;
use OC\Files\Filesystem;
use OC\Files\Stream\HashWrapper;
use OC\Files\View;
+use OC\Metadata\FileMetadata;
use OCA\DAV\AppInfo\Application;
use OCA\DAV\Connector\Sabre\Exception\EntityTooLarge;
use OCA\DAV\Connector\Sabre\Exception\FileLocked;
@@ -80,6 +81,9 @@ class File extends Node implements IFile {
protected IL10N $l10n;
+ /** @var array<string, FileMetadata> */
+ private array $metadata = [];
+
/**
* Sets up the node, expects a full path name
*
@@ -757,4 +761,16 @@ class File extends Node implements IFile {
public function getNode(): \OCP\Files\File {
return $this->node;
}
+
+ public function getMetadata(string $group): FileMetadata {
+ return $this->metadata[$group];
+ }
+
+ public function setMetadata(string $group, FileMetadata $metadata): void {
+ $this->metadata[$group] = $metadata;
+ }
+
+ public function hasMetadata(string $group) {
+ return array_key_exists($group, $this->metadata);
+ }
}
diff --git a/apps/dav/lib/Connector/Sabre/FilesPlugin.php b/apps/dav/lib/Connector/Sabre/FilesPlugin.php
index 180f05c0e7e..9c4f912610b 100644
--- a/apps/dav/lib/Connector/Sabre/FilesPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/FilesPlugin.php
@@ -34,6 +34,7 @@
namespace OCA\DAV\Connector\Sabre;
use OC\AppFramework\Http\Request;
+use OC\Metadata\IMetadataManager;
use OCP\Constants;
use OCP\Files\ForbiddenException;
use OCP\Files\StorageNotAvailableException;
@@ -41,6 +42,7 @@ use OCP\IConfig;
use OCP\IPreview;
use OCP\IRequest;
use OCP\IUserSession;
+use Psr\Log\LoggerInterface;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\IFile;
@@ -50,6 +52,7 @@ use Sabre\DAV\ServerPlugin;
use Sabre\DAV\Tree;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
+use Sabre\Uri;
class FilesPlugin extends ServerPlugin {
@@ -79,6 +82,7 @@ class FilesPlugin extends ServerPlugin {
public const SHARE_NOTE = '{http://nextcloud.org/ns}note';
public const SUBFOLDER_COUNT_PROPERTYNAME = '{http://nextcloud.org/ns}contained-folder-count';
public const SUBFILE_COUNT_PROPERTYNAME = '{http://nextcloud.org/ns}contained-file-count';
+ public const FILE_METADATA_SIZE = '{http://nextcloud.org/ns}file-metadata-size';
/**
* Reference to main server object
@@ -436,6 +440,29 @@ class FilesPlugin extends ServerPlugin {
$propFind->handle(self::UPLOAD_TIME_PROPERTYNAME, function () use ($node) {
return $node->getFileInfo()->getUploadTime();
});
+
+ if ($this->config->getSystemValueBool('enable_file_metadata', true)) {
+ $propFind->handle(self::FILE_METADATA_SIZE, function () use ($node) {
+ if (!str_starts_with($node->getFileInfo()->getMimetype(), 'image')) {
+ return json_encode((object)[]);
+ }
+
+ if ($node->hasMetadata('size')) {
+ $sizeMetadata = $node->getMetadata('size');
+ } else {
+ // This code path should not be called since we try to preload
+ // the metadata when loading the folder or the search results
+ // in one go
+ $metadataManager = \OC::$server->get(IMetadataManager::class);
+ $sizeMetadata = $metadataManager->fetchMetadataFor('size', [$node->getId()])[$node->getId()];
+
+ // TODO would be nice to display this in the profiler...
+ \OC::$server->get(LoggerInterface::class)->debug('Inefficient fetching of metadata');
+ }
+
+ return json_encode((object)$sizeMetadata->getMetadata());
+ });
+ }
}
if ($node instanceof Directory) {
@@ -448,6 +475,32 @@ class FilesPlugin extends ServerPlugin {
});
$requestProperties = $propFind->getRequestedProperties();
+
+ // TODO detect dynamically which metadata groups are requested and
+ // preload all of them and not just size
+ if ($this->config->getSystemValueBool('enable_file_metadata', true)
+ && in_array(self::FILE_METADATA_SIZE, $requestProperties, true)) {
+ // Preloading of the metadata
+ $fileIds = [];
+ foreach ($node->getChildren() as $child) {
+ /** @var \OCP\Files\Node|Node $child */
+ if (str_starts_with($child->getFileInfo()->getMimeType(), 'image/')) {
+ /** @var File $child */
+ $fileIds[] = $child->getFileInfo()->getId();
+ }
+ }
+ /** @var IMetaDataManager $metadataManager */
+ $metadataManager = \OC::$server->get(IMetadataManager::class);
+ $preloadedMetadata = $metadataManager->fetchMetadataFor('size', $fileIds);
+ foreach ($node->getChildren() as $child) {
+ /** @var \OCP\Files\Node|Node $child */
+ if (str_starts_with($child->getFileInfo()->getMimeType(), 'image')) {
+ /** @var File $child */
+ $child->setMetadata('size', $preloadedMetadata[$child->getFileInfo()->getId()]);
+ }
+ }
+ }
+
if (in_array(self::SUBFILE_COUNT_PROPERTYNAME, $requestProperties, true)
|| in_array(self::SUBFOLDER_COUNT_PROPERTYNAME, $requestProperties, true)) {
$nbFiles = 0;
diff --git a/apps/dav/lib/Files/FileSearchBackend.php b/apps/dav/lib/Files/FileSearchBackend.php
index 45e911db182..7ee82779849 100644
--- a/apps/dav/lib/Files/FileSearchBackend.php
+++ b/apps/dav/lib/Files/FileSearchBackend.php
@@ -30,6 +30,7 @@ use OC\Files\Search\SearchComparison;
use OC\Files\Search\SearchOrder;
use OC\Files\Search\SearchQuery;
use OC\Files\View;
+use OC\Metadata\IMetadataManager;
use OCA\DAV\Connector\Sabre\CachingTree;
use OCA\DAV\Connector\Sabre\Directory;
use OCA\DAV\Connector\Sabre\FilesPlugin;
@@ -44,6 +45,7 @@ use OCP\Files\Search\ISearchQuery;
use OCP\IUser;
use OCP\Share\IManager;
use Sabre\DAV\Exception\NotFound;
+use Sabre\DAV\INode;
use SearchDAV\Backend\ISearchBackend;
use SearchDAV\Backend\SearchPropertyDefinition;
use SearchDAV\Backend\SearchResult;
@@ -88,14 +90,12 @@ class FileSearchBackend implements ISearchBackend {
/**
* Search endpoint will be remote.php/dav
- *
- * @return string
*/
- public function getArbiterPath() {
+ public function getArbiterPath(): string {
return '';
}
- public function isValidScope($href, $depth, $path) {
+ public function isValidScope(string $href, $depth, ?string $path): bool {
// only allow scopes inside the dav server
if (is_null($path)) {
return false;
@@ -109,7 +109,7 @@ class FileSearchBackend implements ISearchBackend {
}
}
- public function getPropertyDefinitionsForScope($href, $path) {
+ public function getPropertyDefinitionsForScope(string $href, ?string $path): array {
// all valid scopes support the same schema
//todo dynamically load all propfind properties that are supported
@@ -124,23 +124,52 @@ class FileSearchBackend implements ISearchBackend {
new SearchPropertyDefinition(FilesPlugin::OWNER_ID_PROPERTYNAME, true, true, false),
// select only properties
- new SearchPropertyDefinition('{DAV:}resourcetype', false, true, false),
- new SearchPropertyDefinition('{DAV:}getcontentlength', false, true, false),
- new SearchPropertyDefinition(FilesPlugin::CHECKSUMS_PROPERTYNAME, false, true, false),
- new SearchPropertyDefinition(FilesPlugin::PERMISSIONS_PROPERTYNAME, false, true, false),
- new SearchPropertyDefinition(FilesPlugin::GETETAG_PROPERTYNAME, false, true, false),
- new SearchPropertyDefinition(FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME, false, true, false),
- new SearchPropertyDefinition(FilesPlugin::DATA_FINGERPRINT_PROPERTYNAME, false, true, false),
- new SearchPropertyDefinition(FilesPlugin::HAS_PREVIEW_PROPERTYNAME, false, true, false, SearchPropertyDefinition::DATATYPE_BOOLEAN),
- new SearchPropertyDefinition(FilesPlugin::FILEID_PROPERTYNAME, false, true, false, SearchPropertyDefinition::DATATYPE_NONNEGATIVE_INTEGER),
+ new SearchPropertyDefinition('{DAV:}resourcetype', true, false, false),
+ new SearchPropertyDefinition('{DAV:}getcontentlength', true, false, false),
+ new SearchPropertyDefinition(FilesPlugin::CHECKSUMS_PROPERTYNAME, true, false, false),
+ new SearchPropertyDefinition(FilesPlugin::PERMISSIONS_PROPERTYNAME, true, false, false),
+ new SearchPropertyDefinition(FilesPlugin::GETETAG_PROPERTYNAME, true, false, false),
+ new SearchPropertyDefinition(FilesPlugin::OWNER_DISPLAY_NAME_PROPERTYNAME, true, false, false),
+ new SearchPropertyDefinition(FilesPlugin::DATA_FINGERPRINT_PROPERTYNAME, true, false, false),
+ new SearchPropertyDefinition(FilesPlugin::HAS_PREVIEW_PROPERTYNAME, true, false, false, SearchPropertyDefinition::DATATYPE_BOOLEAN),
+ new SearchPropertyDefinition(FilesPlugin::FILE_METADATA_SIZE, true, false, false, SearchPropertyDefinition::DATATYPE_STRING),
+ new SearchPropertyDefinition(FilesPlugin::FILEID_PROPERTYNAME, true, false, false, SearchPropertyDefinition::DATATYPE_NONNEGATIVE_INTEGER),
];
}
/**
+ * @param INode[] $nodes
+ * @param string[] $requestProperties
+ */
+ public function preloadPropertyFor(array $nodes, array $requestProperties): void {
+ if (in_array(FilesPlugin::FILE_METADATA_SIZE, $requestProperties, true)) {
+ // Preloading of the metadata
+ $fileIds = [];
+ foreach ($nodes as $node) {
+ /** @var \OCP\Files\Node|\OCA\DAV\Connector\Sabre\Node $node */
+ if (str_starts_with($node->getFileInfo()->getMimeType(), 'image/')) {
+ /** @var \OCA\DAV\Connector\Sabre\File $node */
+ $fileIds[] = $node->getFileInfo()->getId();
+ }
+ }
+ /** @var IMetaDataManager $metadataManager */
+ $metadataManager = \OC::$server->get(IMetadataManager::class);
+ $preloadedMetadata = $metadataManager->fetchMetadataFor('size', $fileIds);
+ foreach ($nodes as $node) {
+ /** @var \OCP\Files\Node|\OCA\DAV\Connector\Sabre\Node $node */
+ if (str_starts_with($node->getFileInfo()->getMimeType(), 'image/')) {
+ /** @var \OCA\DAV\Connector\Sabre\File $node */
+ $node->setMetadata('size', $preloadedMetadata[$node->getFileInfo()->getId()]);
+ }
+ }
+ }
+ }
+
+ /**
* @param Query $search
* @return SearchResult[]
*/
- public function search(Query $search) {
+ public function search(Query $search): array {
if (count($search->from) !== 1) {
throw new \InvalidArgumentException('Searching more than one folder is not supported');
}
diff --git a/apps/dav/lib/Files/LazySearchBackend.php b/apps/dav/lib/Files/LazySearchBackend.php
index d84c11306e3..c3b2f27d72a 100644
--- a/apps/dav/lib/Files/LazySearchBackend.php
+++ b/apps/dav/lib/Files/LazySearchBackend.php
@@ -22,6 +22,7 @@
*/
namespace OCA\DAV\Files;
+use Sabre\DAV\INode;
use SearchDAV\Backend\ISearchBackend;
use SearchDAV\Query\Query;
@@ -35,7 +36,7 @@ class LazySearchBackend implements ISearchBackend {
$this->backend = $backend;
}
- public function getArbiterPath() {
+ public function getArbiterPath(): string {
if ($this->backend) {
return $this->backend->getArbiterPath();
} else {
@@ -43,27 +44,30 @@ class LazySearchBackend implements ISearchBackend {
}
}
- public function isValidScope($href, $depth, $path) {
+ public function isValidScope(string $href, $depth, ?string $path): bool {
if ($this->backend) {
return $this->backend->getArbiterPath();
- } else {
- return false;
}
+ return false;
}
- public function getPropertyDefinitionsForScope($href, $path) {
+ public function getPropertyDefinitionsForScope(string $href, ?String $path): array {
if ($this->backend) {
return $this->backend->getPropertyDefinitionsForScope($href, $path);
- } else {
- return [];
}
+ return [];
}
- public function search(Query $query) {
+ public function search(Query $query): array {
if ($this->backend) {
return $this->backend->search($query);
- } else {
- return [];
+ }
+ return [];
+ }
+
+ public function preloadPropertyFor(array $nodes, array $requestProperties): void {
+ if ($this->backend) {
+ $this->backend->preloadPropertyFor($nodes, $requestProperties);
}
}
}
diff --git a/apps/encryption/composer/autoload.php b/apps/encryption/composer/autoload.php
index 52febf19470..593ddde0eb0 100644
--- a/apps/encryption/composer/autoload.php
+++ b/apps/encryption/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitEncryption::getLoader();
diff --git a/apps/encryption/composer/composer/autoload_real.php b/apps/encryption/composer/composer/autoload_real.php
index 35091c9ed4a..aafe8533d3d 100644
--- a/apps/encryption/composer/composer/autoload_real.php
+++ b/apps/encryption/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitEncryption
spl_autoload_unregister(array('ComposerAutoloaderInitEncryption', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitEncryption::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitEncryption::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/federatedfilesharing/composer/autoload.php b/apps/federatedfilesharing/composer/autoload.php
index 5273607f74a..e839dd1bcdd 100644
--- a/apps/federatedfilesharing/composer/autoload.php
+++ b/apps/federatedfilesharing/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitFederatedFileSharing::getLoader();
diff --git a/apps/federatedfilesharing/composer/composer/autoload_real.php b/apps/federatedfilesharing/composer/composer/autoload_real.php
index 0a8c5bf9588..c6f34ef0a65 100644
--- a/apps/federatedfilesharing/composer/composer/autoload_real.php
+++ b/apps/federatedfilesharing/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitFederatedFileSharing
spl_autoload_unregister(array('ComposerAutoloaderInitFederatedFileSharing', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitFederatedFileSharing::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitFederatedFileSharing::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/federation/composer/autoload.php b/apps/federation/composer/autoload.php
index 45677794dd0..77ae3e1c118 100644
--- a/apps/federation/composer/autoload.php
+++ b/apps/federation/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitFederation::getLoader();
diff --git a/apps/federation/composer/composer/autoload_real.php b/apps/federation/composer/composer/autoload_real.php
index 40dc84ff20a..b3913e0ac70 100644
--- a/apps/federation/composer/composer/autoload_real.php
+++ b/apps/federation/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitFederation
spl_autoload_unregister(array('ComposerAutoloaderInitFederation', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitFederation::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitFederation::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/files/composer/autoload.php b/apps/files/composer/autoload.php
index 3aa13fa515d..cbac9333296 100644
--- a/apps/files/composer/autoload.php
+++ b/apps/files/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitFiles::getLoader();
diff --git a/apps/files/composer/composer/autoload_real.php b/apps/files/composer/composer/autoload_real.php
index 5b2c0e86043..e3e4d9e67ef 100644
--- a/apps/files/composer/composer/autoload_real.php
+++ b/apps/files/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitFiles
spl_autoload_unregister(array('ComposerAutoloaderInitFiles', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitFiles::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitFiles::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/files_sharing/composer/autoload.php b/apps/files_sharing/composer/autoload.php
index 0aa77c00af9..02b3c10c483 100644
--- a/apps/files_sharing/composer/autoload.php
+++ b/apps/files_sharing/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitFiles_Sharing::getLoader();
diff --git a/apps/files_sharing/composer/composer/autoload_real.php b/apps/files_sharing/composer/composer/autoload_real.php
index 24054045984..64a23094d9d 100644
--- a/apps/files_sharing/composer/composer/autoload_real.php
+++ b/apps/files_sharing/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitFiles_Sharing
spl_autoload_unregister(array('ComposerAutoloaderInitFiles_Sharing', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitFiles_Sharing::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitFiles_Sharing::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/files_trashbin/composer/autoload.php b/apps/files_trashbin/composer/autoload.php
index ae6d572163f..4e88a44133f 100644
--- a/apps/files_trashbin/composer/autoload.php
+++ b/apps/files_trashbin/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitFiles_Trashbin::getLoader();
diff --git a/apps/files_trashbin/composer/composer/autoload_real.php b/apps/files_trashbin/composer/composer/autoload_real.php
index b9a42591b0c..0d1aa13ee3c 100644
--- a/apps/files_trashbin/composer/composer/autoload_real.php
+++ b/apps/files_trashbin/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitFiles_Trashbin
spl_autoload_unregister(array('ComposerAutoloaderInitFiles_Trashbin', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitFiles_Trashbin::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitFiles_Trashbin::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/files_versions/composer/autoload.php b/apps/files_versions/composer/autoload.php
index 7bb72360fba..f75dc09160c 100644
--- a/apps/files_versions/composer/autoload.php
+++ b/apps/files_versions/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitFiles_Versions::getLoader();
diff --git a/apps/files_versions/composer/composer/autoload_real.php b/apps/files_versions/composer/composer/autoload_real.php
index e9e2ad95149..dad15f0b550 100644
--- a/apps/files_versions/composer/composer/autoload_real.php
+++ b/apps/files_versions/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitFiles_Versions
spl_autoload_unregister(array('ComposerAutoloaderInitFiles_Versions', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitFiles_Versions::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitFiles_Versions::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/lookup_server_connector/composer/autoload.php b/apps/lookup_server_connector/composer/autoload.php
index ab8f4ce80ff..521fd3630e4 100644
--- a/apps/lookup_server_connector/composer/autoload.php
+++ b/apps/lookup_server_connector/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitLookupServerConnector::getLoader();
diff --git a/apps/lookup_server_connector/composer/composer/autoload_real.php b/apps/lookup_server_connector/composer/composer/autoload_real.php
index 798f093c6e8..417958ba7f1 100644
--- a/apps/lookup_server_connector/composer/composer/autoload_real.php
+++ b/apps/lookup_server_connector/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitLookupServerConnector
spl_autoload_unregister(array('ComposerAutoloaderInitLookupServerConnector', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitLookupServerConnector::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitLookupServerConnector::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/oauth2/composer/autoload.php b/apps/oauth2/composer/autoload.php
index 276dedf42c2..c7fd27c188d 100644
--- a/apps/oauth2/composer/autoload.php
+++ b/apps/oauth2/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitOAuth2::getLoader();
diff --git a/apps/oauth2/composer/composer/autoload_real.php b/apps/oauth2/composer/composer/autoload_real.php
index 4d9e729ac26..0253518be84 100644
--- a/apps/oauth2/composer/composer/autoload_real.php
+++ b/apps/oauth2/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitOAuth2
spl_autoload_unregister(array('ComposerAutoloaderInitOAuth2', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitOAuth2::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitOAuth2::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/provisioning_api/composer/autoload.php b/apps/provisioning_api/composer/autoload.php
index 9734ee42b19..d01dfa2c74b 100644
--- a/apps/provisioning_api/composer/autoload.php
+++ b/apps/provisioning_api/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitProvisioning_API::getLoader();
diff --git a/apps/provisioning_api/composer/composer/autoload_real.php b/apps/provisioning_api/composer/composer/autoload_real.php
index bada942777d..a3b1fdeb247 100644
--- a/apps/provisioning_api/composer/composer/autoload_real.php
+++ b/apps/provisioning_api/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitProvisioning_API
spl_autoload_unregister(array('ComposerAutoloaderInitProvisioning_API', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitProvisioning_API::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitProvisioning_API::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/settings/composer/autoload.php b/apps/settings/composer/autoload.php
index 04ff46ee987..e7087dceec2 100644
--- a/apps/settings/composer/autoload.php
+++ b/apps/settings/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitSettings::getLoader();
diff --git a/apps/settings/composer/composer/autoload_real.php b/apps/settings/composer/composer/autoload_real.php
index 0e9941ee04d..865e01a7fd9 100644
--- a/apps/settings/composer/composer/autoload_real.php
+++ b/apps/settings/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitSettings
spl_autoload_unregister(array('ComposerAutoloaderInitSettings', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitSettings::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitSettings::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/sharebymail/composer/autoload.php b/apps/sharebymail/composer/autoload.php
index da43a4ff256..bef284b432f 100644
--- a/apps/sharebymail/composer/autoload.php
+++ b/apps/sharebymail/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitShareByMail::getLoader();
diff --git a/apps/sharebymail/composer/composer/autoload_real.php b/apps/sharebymail/composer/composer/autoload_real.php
index 47a2c20fd5e..cfbfdab1b1e 100644
--- a/apps/sharebymail/composer/composer/autoload_real.php
+++ b/apps/sharebymail/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitShareByMail
spl_autoload_unregister(array('ComposerAutoloaderInitShareByMail', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitShareByMail::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitShareByMail::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/systemtags/composer/autoload.php b/apps/systemtags/composer/autoload.php
index 30f4cd27d40..5f15d593150 100644
--- a/apps/systemtags/composer/autoload.php
+++ b/apps/systemtags/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitSystemTags::getLoader();
diff --git a/apps/systemtags/composer/composer/autoload_real.php b/apps/systemtags/composer/composer/autoload_real.php
index f9bc1f2eaff..340f7c9e6ed 100644
--- a/apps/systemtags/composer/composer/autoload_real.php
+++ b/apps/systemtags/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitSystemTags
spl_autoload_unregister(array('ComposerAutoloaderInitSystemTags', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitSystemTags::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitSystemTags::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/testing/composer/autoload.php b/apps/testing/composer/autoload.php
index dc2a7034ffa..1ac43d5c8e9 100644
--- a/apps/testing/composer/autoload.php
+++ b/apps/testing/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitTesting::getLoader();
diff --git a/apps/testing/composer/composer/autoload_real.php b/apps/testing/composer/composer/autoload_real.php
index 805c585644d..0d4fabd66a0 100644
--- a/apps/testing/composer/composer/autoload_real.php
+++ b/apps/testing/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitTesting
spl_autoload_unregister(array('ComposerAutoloaderInitTesting', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitTesting::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitTesting::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/twofactor_backupcodes/composer/autoload.php b/apps/twofactor_backupcodes/composer/autoload.php
index 03a8800c318..091a9b4fefa 100644
--- a/apps/twofactor_backupcodes/composer/autoload.php
+++ b/apps/twofactor_backupcodes/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitTwoFactorBackupCodes::getLoader();
diff --git a/apps/twofactor_backupcodes/composer/composer/autoload_real.php b/apps/twofactor_backupcodes/composer/composer/autoload_real.php
index 0c6e6b19f33..b063e83100f 100644
--- a/apps/twofactor_backupcodes/composer/composer/autoload_real.php
+++ b/apps/twofactor_backupcodes/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitTwoFactorBackupCodes
spl_autoload_unregister(array('ComposerAutoloaderInitTwoFactorBackupCodes', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitTwoFactorBackupCodes::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitTwoFactorBackupCodes::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/updatenotification/composer/autoload.php b/apps/updatenotification/composer/autoload.php
index 47cc4d587a5..e715564a5bd 100644
--- a/apps/updatenotification/composer/autoload.php
+++ b/apps/updatenotification/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitUpdateNotification::getLoader();
diff --git a/apps/updatenotification/composer/composer/autoload_real.php b/apps/updatenotification/composer/composer/autoload_real.php
index 89854cd42f4..b7569aff2d1 100644
--- a/apps/updatenotification/composer/composer/autoload_real.php
+++ b/apps/updatenotification/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitUpdateNotification
spl_autoload_unregister(array('ComposerAutoloaderInitUpdateNotification', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitUpdateNotification::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitUpdateNotification::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/user_ldap/composer/autoload.php b/apps/user_ldap/composer/autoload.php
index 24824c188e5..d1e331c189e 100644
--- a/apps/user_ldap/composer/autoload.php
+++ b/apps/user_ldap/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitUser_LDAP::getLoader();
diff --git a/apps/user_ldap/composer/composer/autoload_real.php b/apps/user_ldap/composer/composer/autoload_real.php
index 0e1a6558e55..6f0c636e7d5 100644
--- a/apps/user_ldap/composer/composer/autoload_real.php
+++ b/apps/user_ldap/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitUser_LDAP
spl_autoload_unregister(array('ComposerAutoloaderInitUser_LDAP', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitUser_LDAP::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitUser_LDAP::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/user_status/composer/autoload.php b/apps/user_status/composer/autoload.php
index b22563e6f83..a82d4105451 100644
--- a/apps/user_status/composer/autoload.php
+++ b/apps/user_status/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitUserStatus::getLoader();
diff --git a/apps/user_status/composer/composer/autoload_real.php b/apps/user_status/composer/composer/autoload_real.php
index 4ffa4b4201b..205d9780930 100644
--- a/apps/user_status/composer/composer/autoload_real.php
+++ b/apps/user_status/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitUserStatus
spl_autoload_unregister(array('ComposerAutoloaderInitUserStatus', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitUserStatus::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitUserStatus::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/apps/workflowengine/composer/autoload.php b/apps/workflowengine/composer/autoload.php
index 003e945ff82..74a2777acf2 100644
--- a/apps/workflowengine/composer/autoload.php
+++ b/apps/workflowengine/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitWorkflowEngine::getLoader();
diff --git a/apps/workflowengine/composer/composer/autoload_real.php b/apps/workflowengine/composer/composer/autoload_real.php
index 8ed8cb2a7b4..cdc2b8a55b4 100644
--- a/apps/workflowengine/composer/composer/autoload_real.php
+++ b/apps/workflowengine/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInitWorkflowEngine
spl_autoload_unregister(array('ComposerAutoloaderInitWorkflowEngine', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInitWorkflowEngine::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInitWorkflowEngine::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml
index 73891b59918..863226922d8 100644
--- a/build/psalm-baseline.xml
+++ b/build/psalm-baseline.xml
@@ -826,10 +826,6 @@
</InvalidScalarArgument>
</file>
<file src="apps/dav/lib/Files/FileSearchBackend.php">
- <InvalidArgument occurrences="2">
- <code>$argument</code>
- <code>$operator-&gt;arguments</code>
- </InvalidArgument>
<InvalidReturnStatement occurrences="1">
<code>$value</code>
</InvalidReturnStatement>
@@ -839,9 +835,6 @@
<ParamNameMismatch occurrences="1">
<code>$search</code>
</ParamNameMismatch>
- <UndefinedDocblockClass occurrences="1">
- <code>$operator-&gt;arguments[0]-&gt;name</code>
- </UndefinedDocblockClass>
<UndefinedPropertyFetch occurrences="1">
<code>$operator-&gt;arguments[0]-&gt;name</code>
</UndefinedPropertyFetch>
@@ -855,9 +848,7 @@
<InvalidReturnStatement occurrences="1">
<code>$this-&gt;backend-&gt;getArbiterPath()</code>
</InvalidReturnStatement>
- <InvalidReturnType occurrences="1">
- <code>isValidScope</code>
- </InvalidReturnType>
+ <InvalidReturnType occurrences="1"/>
</file>
<file src="apps/dav/lib/Files/RootCollection.php">
<UndefinedFunction occurrences="1">
diff --git a/config/config.sample.php b/config/config.sample.php
index 4d8dcfa5660..378d88168cd 100644
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -2125,4 +2125,15 @@ $CONFIG = [
* Defaults to ``true``
*/
'profile.enabled' => true,
+
+/**
+ * Enable file metadata collection
+ *
+ * This is helpful for the mobile clients and will enable a few optimization in
+ * the future for the preview generation.
+ *
+ * Note that when enabled, this data will be stored in the database and might increase
+ * the database storage.
+ */
+'enable_file_metadata' => true,
];
diff --git a/core/Application.php b/core/Application.php
index 545588ab208..34932cab183 100644
--- a/core/Application.php
+++ b/core/Application.php
@@ -48,12 +48,17 @@ use OC\DB\MissingColumnInformation;
use OC\DB\MissingIndexInformation;
use OC\DB\MissingPrimaryKeyInformation;
use OC\DB\SchemaWrapper;
+use OC\Metadata\FileEventListener;
use OCP\AppFramework\App;
use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\Events\Node\NodeDeletedEvent;
+use OCP\Files\Events\Node\NodeWrittenEvent;
+use OCP\Files\Events\NodeRemovedFromCache;
use OCP\IDBConnection;
use OCP\User\Events\BeforeUserDeletedEvent;
use OCP\User\Events\UserDeletedEvent;
use OCP\Util;
+use OCP\IConfig;
use Symfony\Component\EventDispatcher\GenericEvent;
/**
@@ -301,5 +306,15 @@ class Application extends App {
$eventDispatcher->addServiceListener(BeforeUserDeletedEvent::class, UserDeletedFilesCleanupListener::class);
$eventDispatcher->addServiceListener(UserDeletedEvent::class, UserDeletedFilesCleanupListener::class);
$eventDispatcher->addServiceListener(UserDeletedEvent::class, UserDeletedWebAuthnCleanupListener::class);
+
+ // Metadata
+ /** @var IConfig $config */
+ $config = $container->get(IConfig::class);
+ if ($config->getSystemValueBool('enable_file_metadata', true)) {
+ $eventDispatcher = \OC::$server->get(IEventDispatcher::class);
+ $eventDispatcher->addServiceListener(NodeDeletedEvent::class, FileEventListener::class);
+ $eventDispatcher->addServiceListener(NodeRemovedFromCache::class, FileEventListener::class);
+ $eventDispatcher->addServiceListener(NodeWrittenEvent::class, FileEventListener::class);
+ }
}
}
diff --git a/core/Migrations/Version240000Date20220404230027.php b/core/Migrations/Version240000Date20220404230027.php
new file mode 100644
index 00000000000..f45f8d5b500
--- /dev/null
+++ b/core/Migrations/Version240000Date20220404230027.php
@@ -0,0 +1,62 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
+ *
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Core\Migrations;
+
+use Closure;
+use OCP\DB\ISchemaWrapper;
+use OCP\DB\Types;
+use OCP\Migration\IOutput;
+use OCP\Migration\SimpleMigrationStep;
+
+/**
+ * Add oc_file_metadata table
+ * @see OC\Metadata\FileMetadata
+ */
+class Version240000Date20220404230027 extends SimpleMigrationStep {
+ /**
+ * @param IOutput $output
+ * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
+ * @param array $options
+ * @return null|ISchemaWrapper
+ */
+ public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
+ /** @var ISchemaWrapper $schema */
+ $schema = $schemaClosure();
+
+ if (!$schema->hasTable('file_metadata')) {
+ $table = $schema->createTable('file_metadata');
+ $table->addColumn('id', Types::INTEGER, [
+ 'notnull' => true,
+ ]);
+ $table->addColumn('group_name', Types::STRING, [
+ 'notnull' => true,
+ 'length' => 50,
+ ]);
+ $table->addColumn('metadata', Types::JSON, [
+ 'notnull' => true,
+ ]);
+ $table->setPrimaryKey(['id', 'group_name'], 'file_metadata_idx');
+ }
+ return $schema;
+ }
+}
diff --git a/lib/composer/autoload.php b/lib/composer/autoload.php
index 6de0160c0b5..a3d144b1777 100644
--- a/lib/composer/autoload.php
+++ b/lib/composer/autoload.php
@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
+if (PHP_VERSION_ID < 50600) {
+ echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ exit(1);
+}
+
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit53792487c5a8370acc0b06b1a864ff4c::getLoader();
diff --git a/lib/composer/composer/InstalledVersions.php b/lib/composer/composer/InstalledVersions.php
index d50e0c9fcc4..fc50a9f8622 100644
--- a/lib/composer/composer/InstalledVersions.php
+++ b/lib/composer/composer/InstalledVersions.php
@@ -264,7 +264,7 @@ class InstalledVersions
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
- if (substr(__DIR__, -8, 1) !== 'C') {
+ if (substr(__DIR__, -8, 1) !== 'C' && is_file(__DIR__ . '/installed.php')) {
self::$installed = include __DIR__ . '/installed.php';
} else {
self::$installed = array();
@@ -337,7 +337,7 @@ class InstalledVersions
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
- if (substr(__DIR__, -8, 1) !== 'C') {
+ if (substr(__DIR__, -8, 1) !== 'C' && is_file(__DIR__ . '/installed.php')) {
self::$installed = require __DIR__ . '/installed.php';
} else {
self::$installed = array();
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index acc0f6bf2ad..685fae9bef1 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -1021,6 +1021,7 @@ return array(
'OC\\Core\\Migrations\\Version23000Date20211203110726' => $baseDir . '/core/Migrations/Version23000Date20211203110726.php',
'OC\\Core\\Migrations\\Version23000Date20211213203940' => $baseDir . '/core/Migrations/Version23000Date20211213203940.php',
'OC\\Core\\Migrations\\Version240000Date20220202150027' => $baseDir . '/core/Migrations/Version240000Date20220202150027.php',
+ 'OC\\Core\\Migrations\\Version240000Date20220404230027' => $baseDir . '/core/Migrations/Version240000Date20220404230027.php',
'OC\\Core\\Migrations\\Version24000Date20211210141942' => $baseDir . '/core/Migrations/Version24000Date20211210141942.php',
'OC\\Core\\Migrations\\Version24000Date20211213081506' => $baseDir . '/core/Migrations/Version24000Date20211213081506.php',
'OC\\Core\\Migrations\\Version24000Date20211213081604' => $baseDir . '/core/Migrations/Version24000Date20211213081604.php',
@@ -1302,6 +1303,14 @@ return array(
'OC\\Memcache\\ProfilerWrapperCache' => $baseDir . '/lib/private/Memcache/ProfilerWrapperCache.php',
'OC\\Memcache\\Redis' => $baseDir . '/lib/private/Memcache/Redis.php',
'OC\\MemoryInfo' => $baseDir . '/lib/private/MemoryInfo.php',
+ 'OC\\Metadata\\Capabilities' => $baseDir . '/lib/private/Metadata/Capabilities.php',
+ 'OC\\Metadata\\FileEventListener' => $baseDir . '/lib/private/Metadata/FileEventListener.php',
+ 'OC\\Metadata\\FileMetadata' => $baseDir . '/lib/private/Metadata/FileMetadata.php',
+ 'OC\\Metadata\\FileMetadataMapper' => $baseDir . '/lib/private/Metadata/FileMetadataMapper.php',
+ 'OC\\Metadata\\IMetadataManager' => $baseDir . '/lib/private/Metadata/IMetadataManager.php',
+ 'OC\\Metadata\\IMetadataProvider' => $baseDir . '/lib/private/Metadata/IMetadataProvider.php',
+ 'OC\\Metadata\\MetadataManager' => $baseDir . '/lib/private/Metadata/MetadataManager.php',
+ 'OC\\Metadata\\Provider\\ExifProvider' => $baseDir . '/lib/private/Metadata/Provider/ExifProvider.php',
'OC\\Migration\\BackgroundRepair' => $baseDir . '/lib/private/Migration/BackgroundRepair.php',
'OC\\Migration\\ConsoleOutput' => $baseDir . '/lib/private/Migration/ConsoleOutput.php',
'OC\\Migration\\SimpleOutput' => $baseDir . '/lib/private/Migration/SimpleOutput.php',
diff --git a/lib/composer/composer/autoload_real.php b/lib/composer/composer/autoload_real.php
index 4b1ab7678ec..eecff48bcf9 100644
--- a/lib/composer/composer/autoload_real.php
+++ b/lib/composer/composer/autoload_real.php
@@ -27,7 +27,7 @@ class ComposerAutoloaderInit53792487c5a8370acc0b06b1a864ff4c
spl_autoload_unregister(array('ComposerAutoloaderInit53792487c5a8370acc0b06b1a864ff4c', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
- \Composer\Autoload\ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c::getInitializer($loader)();
+ call_user_func(\Composer\Autoload\ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c::getInitializer($loader));
$loader->register(true);
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 09e8d3a627e..7e778d73b83 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -1050,6 +1050,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Core\\Migrations\\Version23000Date20211203110726' => __DIR__ . '/../../..' . '/core/Migrations/Version23000Date20211203110726.php',
'OC\\Core\\Migrations\\Version23000Date20211213203940' => __DIR__ . '/../../..' . '/core/Migrations/Version23000Date20211213203940.php',
'OC\\Core\\Migrations\\Version240000Date20220202150027' => __DIR__ . '/../../..' . '/core/Migrations/Version240000Date20220202150027.php',
+ 'OC\\Core\\Migrations\\Version240000Date20220404230027' => __DIR__ . '/../../..' . '/core/Migrations/Version240000Date20220404230027.php',
'OC\\Core\\Migrations\\Version24000Date20211210141942' => __DIR__ . '/../../..' . '/core/Migrations/Version24000Date20211210141942.php',
'OC\\Core\\Migrations\\Version24000Date20211213081506' => __DIR__ . '/../../..' . '/core/Migrations/Version24000Date20211213081506.php',
'OC\\Core\\Migrations\\Version24000Date20211213081604' => __DIR__ . '/../../..' . '/core/Migrations/Version24000Date20211213081604.php',
@@ -1331,6 +1332,14 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Memcache\\ProfilerWrapperCache' => __DIR__ . '/../../..' . '/lib/private/Memcache/ProfilerWrapperCache.php',
'OC\\Memcache\\Redis' => __DIR__ . '/../../..' . '/lib/private/Memcache/Redis.php',
'OC\\MemoryInfo' => __DIR__ . '/../../..' . '/lib/private/MemoryInfo.php',
+ 'OC\\Metadata\\Capabilities' => __DIR__ . '/../../..' . '/lib/private/Metadata/Capabilities.php',
+ 'OC\\Metadata\\FileEventListener' => __DIR__ . '/../../..' . '/lib/private/Metadata/FileEventListener.php',
+ 'OC\\Metadata\\FileMetadata' => __DIR__ . '/../../..' . '/lib/private/Metadata/FileMetadata.php',
+ 'OC\\Metadata\\FileMetadataMapper' => __DIR__ . '/../../..' . '/lib/private/Metadata/FileMetadataMapper.php',
+ 'OC\\Metadata\\IMetadataManager' => __DIR__ . '/../../..' . '/lib/private/Metadata/IMetadataManager.php',
+ 'OC\\Metadata\\IMetadataProvider' => __DIR__ . '/../../..' . '/lib/private/Metadata/IMetadataProvider.php',
+ 'OC\\Metadata\\MetadataManager' => __DIR__ . '/../../..' . '/lib/private/Metadata/MetadataManager.php',
+ 'OC\\Metadata\\Provider\\ExifProvider' => __DIR__ . '/../../..' . '/lib/private/Metadata/Provider/ExifProvider.php',
'OC\\Migration\\BackgroundRepair' => __DIR__ . '/../../..' . '/lib/private/Migration/BackgroundRepair.php',
'OC\\Migration\\ConsoleOutput' => __DIR__ . '/../../..' . '/lib/private/Migration/ConsoleOutput.php',
'OC\\Migration\\SimpleOutput' => __DIR__ . '/../../..' . '/lib/private/Migration/SimpleOutput.php',
diff --git a/lib/composer/composer/installed.php b/lib/composer/composer/installed.php
index f12a8e00dbe..67a1ddfbd8c 100644
--- a/lib/composer/composer/installed.php
+++ b/lib/composer/composer/installed.php
@@ -5,7 +5,7 @@
'type' => 'library',
'install_path' => __DIR__ . '/../../../',
'aliases' => array(),
- 'reference' => '1225189f74d06606aafc4150d07584b90cea50dd',
+ 'reference' => '42c7886f80c7a5e767b192d07474114dd0848b16',
'name' => '__root__',
'dev' => false,
),
@@ -16,7 +16,7 @@
'type' => 'library',
'install_path' => __DIR__ . '/../../../',
'aliases' => array(),
- 'reference' => '1225189f74d06606aafc4150d07584b90cea50dd',
+ 'reference' => '42c7886f80c7a5e767b192d07474114dd0848b16',
'dev_requirement' => false,
),
),
diff --git a/lib/private/Files/ObjectStore/NoopScanner.php b/lib/private/Files/ObjectStore/NoopScanner.php
index 42e212271d5..3b8cbdb18bb 100644
--- a/lib/private/Files/ObjectStore/NoopScanner.php
+++ b/lib/private/Files/ObjectStore/NoopScanner.php
@@ -31,7 +31,7 @@ use OC\Files\Storage\Storage;
class NoopScanner extends Scanner {
public function __construct(Storage $storage) {
- //we don't need the storage, so do nothing here
+ // we don't need the storage, so do nothing here
}
/**
diff --git a/lib/private/Metadata/Capabilities.php b/lib/private/Metadata/Capabilities.php
new file mode 100644
index 00000000000..2fa0006f581
--- /dev/null
+++ b/lib/private/Metadata/Capabilities.php
@@ -0,0 +1,44 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
+ * @license AGPL-3.0-or-later
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Metadata;
+
+use OCP\Capabilities\IPublicCapability;
+use OCP\IConfig;
+
+class Capabilities implements IPublicCapability {
+ private IMetadataManager $manager;
+ private IConfig $config;
+
+ public function __construct(IMetadataManager $manager, IConfig $config) {
+ $this->manager = $manager;
+ $this->config = $config;
+ }
+
+ public function getCapabilities() {
+ if ($this->config->getSystemValueBool('enable_file_metadata', true)) {
+ return ['metadataAvailable' => $this->manager->getCapabilities()];
+ }
+
+ return [];
+ }
+}
diff --git a/lib/private/Metadata/FileEventListener.php b/lib/private/Metadata/FileEventListener.php
new file mode 100644
index 00000000000..fdec891c6e2
--- /dev/null
+++ b/lib/private/Metadata/FileEventListener.php
@@ -0,0 +1,84 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
+ * @license AGPL-3.0-or-later
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Metadata;
+
+use OC\Files\Filesystem;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\Files\Events\Node\NodeDeletedEvent;
+use OCP\Files\Events\Node\NodeWrittenEvent;
+use OCP\Files\Events\NodeRemovedFromCache;
+use OCP\Files\File;
+use OCP\Files\Node;
+use OCP\Files\NotFoundException;
+use OCP\Files\FileInfo;
+
+class FileEventListener implements IEventListener {
+ private IMetadataManager $manager;
+
+ public function __construct(IMetadataManager $manager) {
+ $this->manager = $manager;
+ }
+
+ private function shouldExtractMetadata(Node $node): bool {
+ try {
+ if ($node->getMimetype() === 'httpd/unix-directory') {
+ return false;
+ }
+ } catch (NotFoundException $e) {
+ return false;
+ }
+ if ($node->getSize(false) <= 0) {
+ return false;
+ }
+
+ $path = $node->getPath();
+ // TODO make this more dynamic, we have the same issue in other places
+ return !str_starts_with($path, 'appdata_') && !str_starts_with($path, 'files_versions/') && !str_starts_with($path, 'files_trashbin/');
+ }
+
+ public function handle(Event $event): void {
+ if ($event instanceof NodeRemovedFromCache) {
+ $view = Filesystem::getView();
+ $info = $view->getFileInfo($event->getPath());
+ if ($info && $info->getType() === FileInfo::TYPE_FILE) {
+ $this->manager->clearMetadata($info->getId());
+ }
+ }
+
+ if ($event instanceof NodeDeletedEvent) {
+ $node = $event->getNode();
+ if ($this->shouldExtractMetadata($node)) {
+ /** @var File $node */
+ $this->manager->clearMetadata($event->getNode()->getId());
+ }
+ }
+
+ if ($event instanceof NodeWrittenEvent) {
+ $node = $event->getNode();
+ if ($this->shouldExtractMetadata($node)) {
+ /** @var File $node */
+ $this->manager->generateMetadata($event->getNode(), false);
+ }
+ }
+ }
+}
diff --git a/lib/private/Metadata/FileMetadata.php b/lib/private/Metadata/FileMetadata.php
new file mode 100644
index 00000000000..c53f5d7f619
--- /dev/null
+++ b/lib/private/Metadata/FileMetadata.php
@@ -0,0 +1,43 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
+ *
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Metadata;
+
+use OCP\AppFramework\Db\Entity;
+use OCP\DB\Types;
+
+/**
+ * @method string getGroupName()
+ * @method void setGroupName(string $groupName)
+ * @method string getMetadata()
+ * @method void setMetadata(array $metadata)
+ * @see OC\Core\Migrations\Version240000Date20220404230027
+ */
+class FileMetadata extends Entity {
+ protected ?string $groupName = null;
+ protected ?array $metadata = null;
+
+ public function __construct() {
+ $this->addType('groupName', 'string');
+ $this->addType('metadata', Types::JSON);
+ }
+}
diff --git a/lib/private/Metadata/FileMetadataMapper.php b/lib/private/Metadata/FileMetadataMapper.php
new file mode 100644
index 00000000000..53f750ae540
--- /dev/null
+++ b/lib/private/Metadata/FileMetadataMapper.php
@@ -0,0 +1,105 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
+ * @license AGPL-3.0-or-later
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Metadata;
+
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Db\MultipleObjectsReturnedException;
+use OCP\AppFramework\Db\QBMapper;
+use OCP\DB\Exception;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+class FileMetadataMapper extends QBMapper {
+ public function __construct(IDBConnection $db) {
+ parent::__construct($db, 'file_metadata', FileMetadata::class);
+ }
+
+ /**
+ * @return FileMetadata[]
+ * @throws Exception
+ */
+ public function findForFile(int $fileId): array {
+ $qb = $this->db->getQueryBuilder();
+ $qb->select('*')
+ ->from($this->getTableName())
+ ->where($qb->expr()->eq('id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
+
+ return $this->findEntities($qb);
+ }
+
+ /**
+ * @throws DoesNotExistException
+ * @throws MultipleObjectsReturnedException
+ * @throws Exception
+ */
+ public function findForGroupForFile(int $fileId, string $groupName): FileMetadata {
+ $qb = $this->db->getQueryBuilder();
+ $qb->select('*')
+ ->from($this->getTableName())
+ ->where($qb->expr()->eq('id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT_ARRAY)))
+ ->andWhere($qb->expr()->eq('group_name', $qb->createNamedParameter($groupName, IQueryBuilder::PARAM_STR)));
+
+ return $this->findEntity($qb);
+ }
+
+ /**
+ * @return array<int, FileMetadata>
+ * @throws Exception
+ */
+ public function findForGroupForFiles(array $fileIds, string $groupName): array {
+ $qb = $this->db->getQueryBuilder();
+ $qb->select('*')
+ ->from($this->getTableName())
+ ->where($qb->expr()->in('id', $qb->createParameter('fileIds')))
+ ->andWhere($qb->expr()->eq('group_name', $qb->createNamedParameter($groupName, IQueryBuilder::PARAM_STR)));
+
+ $metadata = [];
+ foreach (array_chunk($fileIds, 1000) as $fileIdsChunk) {
+ $qb->setParameter('fileIds', $fileIdsChunk, IQueryBuilder::PARAM_INT_ARRAY);
+ /** @var FileMetadata[] $rawEntities */
+ $rawEntities = $this->findEntities($qb);
+ foreach ($rawEntities as $entity) {
+ $metadata[$entity->getId()] = $entity;
+ }
+ }
+
+ foreach ($fileIds as $id) {
+ if (isset($metadata[$id])) {
+ continue;
+ }
+ $empty = new FileMetadata();
+ $empty->setMetadata([]);
+ $empty->setGroupName($groupName);
+ $empty->setId($id);
+ $metadata[$id] = $empty;
+ }
+ return $metadata;
+ }
+
+ public function clear(int $fileId): void {
+ $qb = $this->db->getQueryBuilder();
+ $qb->delete($this->getTableName())
+ ->where($qb->expr()->eq('id', $qb->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
+
+ $qb->executeStatement();
+ }
+}
diff --git a/lib/private/Metadata/IMetadataManager.php b/lib/private/Metadata/IMetadataManager.php
new file mode 100644
index 00000000000..d2d37f15c25
--- /dev/null
+++ b/lib/private/Metadata/IMetadataManager.php
@@ -0,0 +1,35 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OC\Metadata;
+
+use OCP\Files\File;
+
+/**
+ * Interface to manage additional metadata for files
+ */
+interface IMetadataManager {
+ /**
+ * @param class-string<IMetadataProvider> $className
+ */
+ public function registerProvider(string $className): void;
+
+ /**
+ * Generate the metadata for one file
+ */
+ public function generateMetadata(File $file, bool $checkExisting = false): void;
+
+ /**
+ * Clear the metadata for one file
+ */
+ public function clearMetadata(int $fileId): void;
+
+ /** @return array<int, FileMetadata> */
+ public function fetchMetadataFor(string $group, array $fileIds): array;
+
+ /**
+ * Get the capabilites as an array of mimetype regex to the type provided
+ */
+ public function getCapabilities(): array;
+}
diff --git a/lib/private/Metadata/IMetadataProvider.php b/lib/private/Metadata/IMetadataProvider.php
new file mode 100644
index 00000000000..7cbe102a538
--- /dev/null
+++ b/lib/private/Metadata/IMetadataProvider.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace OC\Metadata;
+
+use OCP\Files\File;
+
+/**
+ * Interface for the metadata providers. If you want an application to provide
+ * some metadata, you can use this to store them.
+ */
+interface IMetadataProvider {
+ /**
+ * The list of groups that this metadata provider is able to provide.
+ *
+ * @return string[]
+ */
+ public static function groupsProvided(): array;
+
+ /**
+ * Check if the metadata provider is available. A metadata provider might be
+ * unavailable due to a php extension not being installed.
+ */
+ public static function isAvailable(): bool;
+
+ /**
+ * Get the mimetypes supported as a regex.
+ */
+ public static function getMimetypesSupported(): string;
+
+ /**
+ * Execute the extraction on the specified file. The metadata should be
+ * grouped by metadata
+ *
+ * Each group should be json serializable and the string representation
+ * shouldn't be longer than 4000 characters.
+ *
+ * @param File $file The file to extract the metadata from
+ * @param array<string, FileMetadata> An array containing all the metadata fetched.
+ */
+ public function execute(File $file): array;
+}
diff --git a/lib/private/Metadata/MetadataManager.php b/lib/private/Metadata/MetadataManager.php
new file mode 100644
index 00000000000..d1cb896febf
--- /dev/null
+++ b/lib/private/Metadata/MetadataManager.php
@@ -0,0 +1,105 @@
+<?php
+/**
+ * @copyright Copyright 2022 Carl Schwan <carl@carlschwan.eu>
+ * @license AGPL-3.0-or-later
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Metadata;
+
+use OC\Metadata\Provider\ExifProvider;
+use OCP\Files\File;
+use OCP\IConfig;
+use Psr\Log\LoggerInterface;
+
+class MetadataManager implements IMetadataManager {
+ /** @var array<string, IMetadataProvider> */
+ private array $providers;
+ private array $providerClasses;
+ private FileMetadataMapper $fileMetadataMapper;
+ private IConfig $config;
+ private LoggerInterface $logger;
+
+ public function __construct(
+ FileMetadataMapper $fileMetadataMapper,
+ IConfig $config,
+ LoggerInterface $logger
+ ) {
+ $this->providers = [];
+ $this->providerClasses = [];
+ $this->fileMetadataMapper = $fileMetadataMapper;
+ $this->config = $config;
+ $this->logger = $logger;
+
+ // TODO move to another place, where?
+ $this->registerProvider(ExifProvider::class);
+ }
+
+ /**
+ * @param class-string<IMetadataProvider> $className
+ */
+ public function registerProvider(string $className):void {
+ if (in_array($className, $this->providerClasses)) {
+ return;
+ }
+
+ if (call_user_func([$className, 'isAvailable'])) {
+ $this->providers[call_user_func([$className, 'getMimetypesSupported'])] = \OC::$server->get($className);
+ }
+ }
+
+ public function generateMetadata(File $file, bool $checkExisting = false): void {
+ $existingMetadataGroups = [];
+
+ if ($checkExisting) {
+ $existingMetadata = $this->fileMetadataMapper->findForFile($file->getId());
+ foreach ($existingMetadata as $metadata) {
+ $existingMetadataGroups[] = $metadata->getGroupName();
+ }
+ }
+
+ foreach ($this->providers as $supportedMimetype => $provider) {
+ if (preg_match($supportedMimetype, $file->getMimeType())) {
+ if (count(array_diff($provider::groupsProvided(), $existingMetadataGroups)) > 0) {
+ $metaDataGroup = $provider->execute($file);
+ foreach ($metaDataGroup as $group => $metadata) {
+ $this->fileMetadataMapper->insertOrUpdate($metadata);
+ }
+ }
+ }
+ }
+ }
+
+ public function clearMetadata(int $fileId): void {
+ $this->fileMetadataMapper->clear($fileId);
+ }
+
+ public function fetchMetadataFor(string $group, array $fileIds): array {
+ return $this->fileMetadataMapper->findForGroupForFiles($fileIds, $group);
+ }
+
+ public function getCapabilities(): array {
+ $capabilities = [];
+ foreach ($this->providers as $supportedMimetype => $provider) {
+ foreach ($provider::groupsProvided() as $group) {
+ if (isset($capabilities[$group])) {
+ $capabilities[$group][] = $supportedMimetype;
+ }
+ $capabilities[$group] = [$supportedMimetype];
+ }
+ }
+ return $capabilities;
+ }
+}
diff --git a/lib/private/Metadata/Provider/ExifProvider.php b/lib/private/Metadata/Provider/ExifProvider.php
new file mode 100644
index 00000000000..2e1eb1d4208
--- /dev/null
+++ b/lib/private/Metadata/Provider/ExifProvider.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace OC\Metadata\Provider;
+
+use OC\Metadata\FileMetadata;
+use OC\Metadata\IMetadataProvider;
+use OCP\Files\File;
+
+class ExifProvider implements IMetadataProvider {
+ public static function groupsProvided(): array {
+ return ['size'];
+ }
+
+ public static function isAvailable(): bool {
+ return extension_loaded('exif');
+ }
+
+ public function execute(File $file): array {
+ $fileDescriptor = $file->fopen('rb');
+ $data = @exif_read_data($fileDescriptor, 'ANY_TAG', true);
+
+ $size = new FileMetadata();
+ $size->setGroupName('size');
+ $size->setId($file->getId());
+ $size->setMetadata([]);
+
+ if (!$data) {
+ $sizeResult = getimagesizefromstring($file->getContent());
+ if ($sizeResult !== false) {
+ $size->setMetadata([
+ 'width' => $sizeResult[0],
+ 'height' => $sizeResult[1],
+ ]);
+ }
+
+ return [
+ 'size' => $size,
+ ];
+ }
+
+ if (array_key_exists('COMPUTED', $data)
+ && array_key_exists('Width', $data['COMPUTED'])
+ && array_key_exists('Height', $data['COMPUTED'])
+ ) {
+ $size->setMetadata([
+ 'width' => $data['COMPUTED']['Width'],
+ 'height' => $data['COMPUTED']['Height'],
+ ]);
+ }
+
+ return [
+ 'size' => $size,
+ ];
+ }
+
+ public static function getMimetypesSupported(): string {
+ return '/image\/.*/';
+ }
+}
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 7817d1beafe..e9d673d3746 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -122,6 +122,9 @@ use OC\Log\PsrLoggerAdapter;
use OC\Mail\Mailer;
use OC\Memcache\ArrayCache;
use OC\Memcache\Factory;
+use OC\Metadata\Capabilities as MetadataCapabilities;
+use OC\Metadata\IMetadataManager;
+use OC\Metadata\MetadataManager;
use OC\Notification\Manager;
use OC\OCS\DiscoveryService;
use OC\Preview\GeneratorHelper;
@@ -151,7 +154,6 @@ use OC\Template\JSCombiner;
use OCA\Theming\ImageManager;
use OCA\Theming\ThemingDefaults;
use OCA\Theming\Util;
-use OCA\WorkflowEngine\Service\Logger;
use OCP\Accounts\IAccountManager;
use OCP\App\IAppManager;
use OCP\Authentication\LoginCredentials\IStore;
@@ -241,15 +243,12 @@ use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
use OCP\Talk\IBroker;
use OCP\User\Events\BeforePasswordUpdatedEvent;
-use OCP\User\Events\BeforeUserCreatedEvent;
-use OCP\User\Events\BeforeUserDeletedEvent;
use OCP\User\Events\BeforeUserLoggedInEvent;
use OCP\User\Events\BeforeUserLoggedInWithCookieEvent;
use OCP\User\Events\BeforeUserLoggedOutEvent;
use OCP\User\Events\PasswordUpdatedEvent;
use OCP\User\Events\PostLoginEvent;
use OCP\User\Events\UserChangedEvent;
-use OCP\User\Events\UserDeletedEvent;
use OCP\User\Events\UserLoggedInEvent;
use OCP\User\Events\UserLoggedInWithCookieEvent;
use OCP\User\Events\UserLoggedOutEvent;
@@ -1163,6 +1162,9 @@ class Server extends ServerContainer implements IServerContainer {
$manager->registerCapability(function () use ($c) {
return $c->get(\OC\Security\Bruteforce\Capabilities::class);
});
+ $manager->registerCapability(function () use ($c) {
+ return $c->get(MetadataCapabilities::class);
+ });
return $manager;
});
/** @deprecated 19.0.0 */
@@ -1433,6 +1435,8 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerAlias(IBroker::class, Broker::class);
+ $this->registerAlias(IMetadataManager::class, MetadataManager::class);
+
$this->connectDispatcher();
}
diff --git a/lib/public/AppFramework/Db/Entity.php b/lib/public/AppFramework/Db/Entity.php
index 89e8f69859e..a059e3a27b0 100644
--- a/lib/public/AppFramework/Db/Entity.php
+++ b/lib/public/AppFramework/Db/Entity.php
@@ -120,6 +120,10 @@ abstract class Entity {
if (!$args[0] instanceof \DateTime) {
$args[0] = new \DateTime($args[0]);
}
+ } elseif ($type === 'json') {
+ if (!is_array($args[0])) {
+ $args[0] = json_decode($args[0], true);
+ }
} else {
settype($args[0], $type);
}
diff --git a/lib/public/AppFramework/Db/QBMapper.php b/lib/public/AppFramework/Db/QBMapper.php
index 5124650bc19..fa753a09dcf 100644
--- a/lib/public/AppFramework/Db/QBMapper.php
+++ b/lib/public/AppFramework/Db/QBMapper.php
@@ -253,6 +253,8 @@ abstract class QBMapper {
return IQueryBuilder::PARAM_LOB;
case 'datetime':
return IQueryBuilder::PARAM_DATE;
+ case 'json':
+ return IQueryBuilder::PARAM_JSON;
}
return IQueryBuilder::PARAM_STR;
diff --git a/lib/public/DB/QueryBuilder/IQueryBuilder.php b/lib/public/DB/QueryBuilder/IQueryBuilder.php
index 76754f7bf41..afca9e372ee 100644
--- a/lib/public/DB/QueryBuilder/IQueryBuilder.php
+++ b/lib/public/DB/QueryBuilder/IQueryBuilder.php
@@ -65,6 +65,11 @@ interface IQueryBuilder {
public const PARAM_DATE = 'datetime';
/**
+ * @since 24.0.0
+ */
+ public const PARAM_JSON = 'json';
+
+ /**
* @since 9.0.0
*/
public const PARAM_INT_ARRAY = Connection::PARAM_INT_ARRAY;
diff --git a/lib/public/DB/Types.php b/lib/public/DB/Types.php
index 4636ac3389f..31a474b03a0 100644
--- a/lib/public/DB/Types.php
+++ b/lib/public/DB/Types.php
@@ -110,4 +110,10 @@ final class Types {
* @since 21.0.0
*/
public const TIME = 'time';
+
+ /**
+ * @var string
+ * @since 24.0.0
+ */
+ public const JSON = 'json';
}
diff --git a/tests/lib/AppFramework/Db/QBMapperTest.php b/tests/lib/AppFramework/Db/QBMapperTest.php
index b03034056d2..96d319923b3 100644
--- a/tests/lib/AppFramework/Db/QBMapperTest.php
+++ b/tests/lib/AppFramework/Db/QBMapperTest.php
@@ -47,6 +47,7 @@ class QBTestEntity extends Entity {
protected $stringProp;
protected $integerProp;
protected $booleanProp;
+ protected $jsonProp;
public function __construct() {
$this->addType('intProp', 'int');
@@ -54,11 +55,10 @@ class QBTestEntity extends Entity {
$this->addType('stringProp', 'string');
$this->addType('integerProp', 'integer');
$this->addType('booleanProp', 'boolean');
+ $this->addType('jsonProp', 'json');
}
}
-;
-
/**
* Class QBTestMapper
*
@@ -69,7 +69,7 @@ class QBTestMapper extends QBMapper {
parent::__construct($db, 'table');
}
- public function getParameterTypeForPropertyForTest(Entity $entity, string $property): int {
+ public function getParameterTypeForPropertyForTest(Entity $entity, string $property) {
return parent::getParameterTypeForProperty($entity, $property);
}
}
@@ -171,6 +171,7 @@ class QBMapperTest extends \Test\TestCase {
$entity->setStringProp('string');
$entity->setIntegerProp(456);
$entity->setBooleanProp(false);
+ $entity->setJsonProp(["hello" => "world"]);
$idParam = $this->qb->createNamedParameter('id', IQueryBuilder::PARAM_INT);
$intParam = $this->qb->createNamedParameter('int_prop', IQueryBuilder::PARAM_INT);
@@ -178,8 +179,9 @@ class QBMapperTest extends \Test\TestCase {
$stringParam = $this->qb->createNamedParameter('string_prop', IQueryBuilder::PARAM_STR);
$integerParam = $this->qb->createNamedParameter('integer_prop', IQueryBuilder::PARAM_INT);
$booleanParam = $this->qb->createNamedParameter('boolean_prop', IQueryBuilder::PARAM_BOOL);
+ $jsonParam = $this->qb->createNamedParameter('json_prop', IQueryBuilder::PARAM_JSON);
- $this->qb->expects($this->exactly(6))
+ $this->qb->expects($this->exactly(7))
->method('createNamedParameter')
->withConsecutive(
[$this->equalTo(123), $this->equalTo(IQueryBuilder::PARAM_INT)],
@@ -187,17 +189,19 @@ class QBMapperTest extends \Test\TestCase {
[$this->equalTo('string'), $this->equalTo(IQueryBuilder::PARAM_STR)],
[$this->equalTo(456), $this->equalTo(IQueryBuilder::PARAM_INT)],
[$this->equalTo(false), $this->equalTo(IQueryBuilder::PARAM_BOOL)],
- [$this->equalTo(789), $this->equalTo(IQueryBuilder::PARAM_INT)]
+ [$this->equalTo(["hello" => "world"]), $this->equalTo(IQueryBuilder::PARAM_JSON)],
+ [$this->equalTo(789), $this->equalTo(IQueryBuilder::PARAM_INT)],
);
- $this->qb->expects($this->exactly(5))
+ $this->qb->expects($this->exactly(6))
->method('set')
->withConsecutive(
[$this->equalTo('int_prop'), $this->equalTo($intParam)],
[$this->equalTo('bool_prop'), $this->equalTo($boolParam)],
[$this->equalTo('string_prop'), $this->equalTo($stringParam)],
[$this->equalTo('integer_prop'), $this->equalTo($integerParam)],
- [$this->equalTo('boolean_prop'), $this->equalTo($booleanParam)]
+ [$this->equalTo('boolean_prop'), $this->equalTo($booleanParam)],
+ [$this->equalTo('json_prop'), $this->equalTo($jsonParam)]
);
$this->expr->expects($this->once())
@@ -227,6 +231,9 @@ class QBMapperTest extends \Test\TestCase {
$stringType = $this->mapper->getParameterTypeForPropertyForTest($entity, 'stringProp');
$this->assertEquals(IQueryBuilder::PARAM_STR, $stringType, 'String type property mapping incorrect');
+ $jsonType = $this->mapper->getParameterTypeForPropertyForTest($entity, 'jsonProp');
+ $this->assertEquals(IQueryBuilder::PARAM_JSON, $jsonType, 'JSON type property mapping incorrect');
+
$unknownType = $this->mapper->getParameterTypeForPropertyForTest($entity, 'someProp');
$this->assertEquals(IQueryBuilder::PARAM_STR, $unknownType, 'Unknown type property mapping incorrect');
}
diff --git a/tests/lib/DB/MigratorTest.php b/tests/lib/DB/MigratorTest.php
index 114cf03d7be..af44159efa3 100644
--- a/tests/lib/DB/MigratorTest.php
+++ b/tests/lib/DB/MigratorTest.php
@@ -267,6 +267,8 @@ class MigratorTest extends \Test\TestCase {
[ParameterType::INTEGER, 1234, Types::INTEGER, false],
[ParameterType::INTEGER, 0, Types::INTEGER, false], // Integer 0 is not stored as Null and therefor works
+
+ [ParameterType::STRING, '{"a": 2}', Types::JSON, false],
];
}
diff --git a/tests/lib/Metadata/FileMetadataMapperTest.php b/tests/lib/Metadata/FileMetadataMapperTest.php
new file mode 100644
index 00000000000..8e385351be2
--- /dev/null
+++ b/tests/lib/Metadata/FileMetadataMapperTest.php
@@ -0,0 +1,83 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2022 Carl Schwan <carl@carlschwan.eu>
+ * @license AGPL-3.0-or-later
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace Test\Metadata;
+
+use OC\Metadata\FileMetadataMapper;
+use OC\Metadata\FileMetadata;
+
+/**
+ * @group DB
+ * @package Test\DB\QueryBuilder
+ */
+class FileMetadataMapperTest extends \Test\TestCase {
+ /** @var IDBConnection */
+ protected $connection;
+
+ /** @var SystemConfig|\PHPUnit\Framework\MockObject\MockObject */
+ protected $config;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->connection = \OC::$server->getDatabaseConnection();
+ $this->mapper = new FileMetadataMapper($this->connection);
+ }
+
+ public function testFindForGroupForFiles() {
+ $file1 = new FileMetadata();
+ $file1->setId(1);
+ $file1->setGroupName('size');
+ $file1->setMetadata([]);
+
+ $file2 = new FileMetadata();
+ $file2->setId(2);
+ $file2->setGroupName('size');
+ $file2->setMetadata(['width' => 293, 'height' => 23]);
+
+ // not added, it's the default
+ $file3 = new FileMetadata();
+ $file3->setId(3);
+ $file3->setGroupName('size');
+ $file3->setMetadata([]);
+
+ $file4 = new FileMetadata();
+ $file4->setId(4);
+ $file4->setGroupName('size');
+ $file4->setMetadata(['complex' => ["yes", "maybe" => 34.0]]);
+
+ $this->mapper->insert($file1);
+ $this->mapper->insert($file2);
+ $this->mapper->insert($file4);
+
+ $files = $this->mapper->findForGroupForFiles([1, 2, 3, 4], 'size');
+
+ $this->assertEquals($files[1]->getMetadata(), $file1->getMetadata());
+ $this->assertEquals($files[2]->getMetadata(), $file2->getMetadata());
+ $this->assertEquals($files[3]->getMetadata(), $file3->getMetadata());
+ $this->assertEquals($files[4]->getMetadata(), $file4->getMetadata());
+
+ $this->mapper->clear(1);
+ $this->mapper->clear(2);
+ $this->mapper->clear(4);
+ }
+}
diff --git a/version.php b/version.php
index 8ceb2dd58c0..d805557260d 100644
--- a/version.php
+++ b/version.php
@@ -30,7 +30,7 @@
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
// when updating major/minor version number.
-$OC_Version = [24, 0, 0, 8];
+$OC_Version = [24, 0, 0, 9];
// The human readable string
$OC_VersionString = '24.0.0 beta 3';