mirror of
https://github.com/nextcloud/server.git
synced 2026-04-27 09:08:22 -04:00
IFilesMetadata
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
This commit is contained in:
parent
e62e9e3dbf
commit
f497d8b6e5
15 changed files with 47 additions and 49 deletions
|
|
@ -41,6 +41,7 @@ use OCP\Files\IRootFolder;
|
|||
use OCP\Files\Search\ISearchBinaryOperator;
|
||||
use OCP\Files\Search\ISearchComparison;
|
||||
use OCP\Files\Search\ISearchQuery;
|
||||
use OCP\FilesMetadata\IFilesMetadataManager;
|
||||
use OCP\IUser;
|
||||
use OCP\Share\IManager;
|
||||
use SearchDAV\Backend\SearchPropertyDefinition;
|
||||
|
|
@ -114,7 +115,9 @@ class FileSearchBackendTest extends TestCase {
|
|||
->method('get')
|
||||
->willReturn($this->searchFolder);
|
||||
|
||||
$this->search = new FileSearchBackend($this->tree, $this->user, $this->rootFolder, $this->shareManager, $this->view);
|
||||
$filesMetadataManager = $this->createMock(IFilesMetadataManager::class);
|
||||
|
||||
$this->search = new FileSearchBackend($this->tree, $this->user, $this->rootFolder, $this->shareManager, $this->view, $filesMetadataManager);
|
||||
}
|
||||
|
||||
public function testSearchFilename(): void {
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ class Get extends Command {
|
|||
if ($input->getOption('reset')) {
|
||||
$this->filesMetadataManager->deleteMetadata($fileId);
|
||||
if (!$input->getOption('refresh')) {
|
||||
return 0;
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -114,6 +114,6 @@ class Get extends Command {
|
|||
$output->writeln(json_encode($metadata, JSON_PRETTY_PRINT));
|
||||
}
|
||||
|
||||
return 0;
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class SearchBuilder {
|
|||
return array_reduce($operator->getArguments(), function (array $fields, ISearchOperator $operator) {
|
||||
return array_unique(array_merge($fields, $this->extractRequestedFields($operator)));
|
||||
}, []);
|
||||
} elseif ($operator instanceof ISearchComparison && !$operator->isExtra()) {
|
||||
} elseif ($operator instanceof ISearchComparison && !$operator->getExtra()) {
|
||||
return [$operator->getField()];
|
||||
}
|
||||
return [];
|
||||
|
|
|
|||
|
|
@ -252,8 +252,6 @@ class Folder extends Node implements \OCP\Files\Folder {
|
|||
if ($order) {
|
||||
usort($files, function (FileInfo $a, FileInfo $b) use ($order) {
|
||||
foreach ($order as $orderField) {
|
||||
// needed !?
|
||||
// if ($orderField->isExtra()) { continue; }
|
||||
$cmp = $orderField->sortFileInfo($a, $b);
|
||||
if ($cmp !== 0) {
|
||||
return $cmp;
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class PathPrefixOptimizer extends QueryOptimizerStep {
|
|||
}
|
||||
|
||||
public function processOperator(ISearchOperator &$operator) {
|
||||
if (!$this->useHashEq && $operator instanceof ISearchComparison && !$operator->isExtra() && $operator->getField() === 'path' && $operator->getType() === ISearchComparison::COMPARE_EQUAL) {
|
||||
if (!$this->useHashEq && $operator instanceof ISearchComparison && !$operator->getExtra() && $operator->getField() === 'path' && $operator->getType() === ISearchComparison::COMPARE_EQUAL) {
|
||||
$operator->setQueryHint(ISearchComparison::HINT_PATH_EQ_HASH, false);
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ class PathPrefixOptimizer extends QueryOptimizerStep {
|
|||
private function operatorPairIsPathPrefix(ISearchOperator $like, ISearchOperator $equal): bool {
|
||||
return (
|
||||
$like instanceof ISearchComparison && $equal instanceof ISearchComparison &&
|
||||
!$like->isExtra() && !$equal->isExtra() && $like->getField() === 'path' && $equal->getField() === 'path' &&
|
||||
!$like->getExtra() && !$equal->getExtra() && $like->getField() === 'path' && $equal->getField() === 'path' &&
|
||||
$like->getType() === ISearchComparison::COMPARE_LIKE_CASE_SENSITIVE && $equal->getType() === ISearchComparison::COMPARE_EQUAL
|
||||
&& $like->getValue() === SearchComparison::escapeLikeParameter($equal->getValue()) . '/%'
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
|
||||
*
|
||||
|
|
@ -39,32 +41,32 @@ class SearchComparison implements ISearchComparison {
|
|||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getType() {
|
||||
public function getType(): string {
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getField() {
|
||||
public function getField(): string {
|
||||
return $this->field;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTime|int|string
|
||||
*/
|
||||
public function getValue() {
|
||||
public function getValue(): string|int|\DateTime {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 28.0.0
|
||||
*/
|
||||
public function getExtra(): string {
|
||||
return $this->extra;
|
||||
}
|
||||
|
||||
public function isExtra(): bool {
|
||||
return ($this->extra !== '');
|
||||
}
|
||||
|
||||
public function getQueryHint(string $name, $default) {
|
||||
return $this->hints[$name] ?? $default;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,14 +48,14 @@ class SearchOrder implements ISearchOrder {
|
|||
return $this->field;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 28.0.0
|
||||
*/
|
||||
public function getExtra(): string {
|
||||
return $this->extra;
|
||||
}
|
||||
|
||||
public function isExtra(): bool {
|
||||
return ($this->extra !== '');
|
||||
}
|
||||
|
||||
public function sortFileInfo(FileInfo $a, FileInfo $b): int {
|
||||
$cmp = $this->sortFileInfoNoDirection($a, $b);
|
||||
return $cmp * ($this->direction === ISearchOrder::DIRECTION_ASCENDING ? 1 : -1);
|
||||
|
|
|
|||
|
|
@ -242,6 +242,7 @@ class FilesMetadataManager implements IFilesMetadataManager {
|
|||
/**
|
||||
* @param string $key metadata key
|
||||
* @param string $type metadata type
|
||||
* @param bool $indexed TRUE if metadata can be search
|
||||
*
|
||||
* @inheritDoc
|
||||
* @since 28.0.0
|
||||
|
|
@ -253,17 +254,17 @@ class FilesMetadataManager implements IFilesMetadataManager {
|
|||
* @see IMetadataValueWrapper::TYPE_INT_LIST
|
||||
* @see IMetadataValueWrapper::TYPE_STRING
|
||||
*/
|
||||
public function initMetadataIndex(string $key, string $type): void {
|
||||
public function initMetadata(string $key, string $type, bool $indexed): void {
|
||||
$current = $this->getKnownMetadata();
|
||||
try {
|
||||
if ($current->getType($key) === $type && $current->isIndex($key)) {
|
||||
return; // if key exists, with same type and is already indexed, we do nothing.
|
||||
if ($current->getType($key) === $type && $indexed === $current->isIndex($key)) {
|
||||
return; // if key exists, with same type and indexed, we do nothing.
|
||||
}
|
||||
} catch (FilesMetadataNotFoundException) {
|
||||
// if value does not exist, we keep on the writing of course
|
||||
}
|
||||
|
||||
$current->import([$key => ['type' => $type, 'indexed' => true]]);
|
||||
$current->import([$key => ['type' => $type, 'indexed' => $indexed]]);
|
||||
$this->config->setAppValue('core', self::CONFIG_KEY, json_encode($current));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ use OCP\Files\IRootFolder;
|
|||
use OCP\Files\NotPermittedException;
|
||||
use OCP\FilesMetadata\Event\MetadataLiveEvent;
|
||||
use OCP\FilesMetadata\IFilesMetadataManager;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Simple background job, created when requested by an app during the
|
||||
|
|
@ -47,6 +48,7 @@ class UpdateSingleMetadata extends QueuedJob {
|
|||
ITimeFactory $time,
|
||||
private IRootFolder $rootFolder,
|
||||
private FilesMetadataManager $filesMetadataManager,
|
||||
private LoggerInterface $logger
|
||||
) {
|
||||
parent::__construct($time);
|
||||
}
|
||||
|
|
@ -60,7 +62,8 @@ class UpdateSingleMetadata extends QueuedJob {
|
|||
$file = array_shift($node);
|
||||
$this->filesMetadataManager->refreshMetadata($file, IFilesMetadataManager::PROCESS_BACKGROUND);
|
||||
}
|
||||
} catch (NotPermittedException|NoUserException $e) {
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->warning('issue while running UpdateSingleMetadata', ['exception' => $e, 'userId' => $userId, 'fileId' => $fileId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ use OCP\EventDispatcher\Event;
|
|||
use OCP\EventDispatcher\IEventListener;
|
||||
use OCP\Files\Events\Node\NodeDeletedEvent;
|
||||
use OCP\FilesMetadata\IFilesMetadataManager;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Handle file deletion event and remove stored metadata related to the deleted file
|
||||
|
|
@ -39,6 +40,7 @@ use OCP\FilesMetadata\IFilesMetadataManager;
|
|||
class MetadataDelete implements IEventListener {
|
||||
public function __construct(
|
||||
private IFilesMetadataManager $filesMetadataManager,
|
||||
private LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
@ -56,6 +58,7 @@ class MetadataDelete implements IEventListener {
|
|||
$this->filesMetadataManager->deleteMetadata($nodeId);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->logger->warning('issue while running MetadataDelete', ['exception' => $e]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ use OCP\EventDispatcher\IEventListener;
|
|||
use OCP\Files\Events\Node\NodeCreatedEvent;
|
||||
use OCP\Files\Events\Node\NodeWrittenEvent;
|
||||
use OCP\FilesMetadata\IFilesMetadataManager;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Handle file creation/modification events and initiate a new event related to the created/edited file.
|
||||
|
|
@ -42,6 +43,7 @@ use OCP\FilesMetadata\IFilesMetadataManager;
|
|||
class MetadataUpdate implements IEventListener {
|
||||
public function __construct(
|
||||
private IFilesMetadataManager $filesMetadataManager,
|
||||
private LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
@ -56,6 +58,7 @@ class MetadataUpdate implements IEventListener {
|
|||
try {
|
||||
$this->filesMetadataManager->refreshMetadata($event->getNode());
|
||||
} catch (Exception $e) {
|
||||
$this->logger->warning('issue while running MetadataUpdate', ['exception' => $e]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ interface ISearchComparison extends ISearchOperator {
|
|||
* @return string
|
||||
* @since 12.0.0
|
||||
*/
|
||||
public function getType();
|
||||
public function getType(): string;
|
||||
|
||||
/**
|
||||
* Get the name of the field to compare with
|
||||
|
|
@ -54,8 +54,7 @@ interface ISearchComparison extends ISearchOperator {
|
|||
* @return string
|
||||
* @since 12.0.0
|
||||
*/
|
||||
public function getField();
|
||||
|
||||
public function getField(): string;
|
||||
|
||||
/**
|
||||
* extra means data are not related to the main files table
|
||||
|
|
@ -65,19 +64,11 @@ interface ISearchComparison extends ISearchOperator {
|
|||
*/
|
||||
public function getExtra(): string;
|
||||
|
||||
/**
|
||||
* returns if data are 'extra' or not
|
||||
*
|
||||
* @return bool
|
||||
* @since 28.0.0
|
||||
*/
|
||||
public function isExtra(): bool;
|
||||
|
||||
/**
|
||||
* Get the value to compare the field with
|
||||
*
|
||||
* @return string|integer|\DateTime
|
||||
* @since 12.0.0
|
||||
*/
|
||||
public function getValue();
|
||||
public function getValue(): string|int|\DateTime;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,15 +57,6 @@ interface ISearchOrder {
|
|||
*/
|
||||
public function getExtra(): string;
|
||||
|
||||
/**
|
||||
* returns if data are 'extra' or not
|
||||
*
|
||||
* @return bool
|
||||
* @since 28.0.0
|
||||
*/
|
||||
public function isExtra(): bool;
|
||||
|
||||
|
||||
/**
|
||||
* Apply the sorting on 2 FileInfo objects
|
||||
*
|
||||
|
|
|
|||
|
|
@ -38,10 +38,9 @@ use OCP\FilesMetadata\Model\IMetadataQuery;
|
|||
* @since 28.0.0
|
||||
*/
|
||||
interface IFilesMetadataManager {
|
||||
/**
|
||||
* @since 28.0.0
|
||||
*/
|
||||
/** @since 28.0.0 */
|
||||
public const PROCESS_LIVE = 1;
|
||||
/** @since 28.0.0 */
|
||||
public const PROCESS_BACKGROUND = 2;
|
||||
|
||||
/**
|
||||
|
|
@ -128,10 +127,13 @@ interface IFilesMetadataManager {
|
|||
/**
|
||||
* initiate a metadata key with its type.
|
||||
* The call is mandatory before using the metadata property in a webdav request.
|
||||
* It is not needed to only use this method when the app is enabled: the method can be
|
||||
* called each time during the app loading as the metadata will only be initiated if not known
|
||||
*
|
||||
* @param string $key metadata key
|
||||
* @param string $type metadata type
|
||||
* @param bool $indexed TRUE if metadata can be search
|
||||
* @since 28.0.0
|
||||
*/
|
||||
public function initMetadataIndex(string $key, string $type): void;
|
||||
public function initMetadata(string $key, string $type, bool $indexed): void;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ namespace OCP\FilesMetadata\Model;
|
|||
* @since 28.0.0
|
||||
*/
|
||||
interface IMetadataQuery {
|
||||
/** @since 28.0.0 */
|
||||
public const EXTRA = 'metadata';
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue