mirror of
https://github.com/nextcloud/server.git
synced 2026-04-04 00:25:45 -04:00
feat(recent-files): add nc:last_activity property to allow sorting by max between upload_time and mtime
Signed-off-by: Cristian Scheid <cristianscheid@gmail.com> Signed-off-by: nextcloud-command <nextcloud-command@users.noreply.github.com>
This commit is contained in:
parent
59527e59be
commit
9776782f4a
9 changed files with 35 additions and 4 deletions
|
|
@ -18,7 +18,7 @@ class Capabilities implements ICapability {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return array{dav: array{chunking: string, public_shares_chunking: bool, search_supports_creation_time: bool, search_supports_upload_time: bool, bulkupload?: string, absence-supported?: bool, absence-replacement?: bool}}
|
||||
* @return array{dav: array{chunking: string, public_shares_chunking: bool, search_supports_creation_time: bool, search_supports_upload_time: bool, search_supports_last_activity: bool, bulkupload?: string, absence-supported?: bool, absence-replacement?: bool}}
|
||||
*/
|
||||
public function getCapabilities() {
|
||||
$capabilities = [
|
||||
|
|
@ -27,6 +27,7 @@ class Capabilities implements ICapability {
|
|||
'public_shares_chunking' => true,
|
||||
'search_supports_creation_time' => true,
|
||||
'search_supports_upload_time' => true,
|
||||
'search_supports_last_activity' => true,
|
||||
]
|
||||
];
|
||||
if ($this->config->getSystemValueBool('bulkupload.enabled', true)) {
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ class FilesPlugin extends ServerPlugin {
|
|||
public const METADATA_ETAG_PROPERTYNAME = '{http://nextcloud.org/ns}metadata_etag';
|
||||
public const UPLOAD_TIME_PROPERTYNAME = '{http://nextcloud.org/ns}upload_time';
|
||||
public const CREATION_TIME_PROPERTYNAME = '{http://nextcloud.org/ns}creation_time';
|
||||
public const LAST_ACTIVITY_PROPERTYNAME = '{http://nextcloud.org/ns}last_activity';
|
||||
public const SHARE_NOTE = '{http://nextcloud.org/ns}note';
|
||||
public const SHARE_HIDE_DOWNLOAD_PROPERTYNAME = '{http://nextcloud.org/ns}hide-download';
|
||||
public const SUBFOLDER_COUNT_PROPERTYNAME = '{http://nextcloud.org/ns}contained-folder-count';
|
||||
|
|
@ -446,6 +447,11 @@ class FilesPlugin extends ServerPlugin {
|
|||
return $node->getFileInfo()->getCreationTime();
|
||||
});
|
||||
|
||||
$propFind->handle(self::LAST_ACTIVITY_PROPERTYNAME, function () use ($node) {
|
||||
$fileInfo = $node->getFileInfo();
|
||||
return max($fileInfo->getUploadTime(), $fileInfo->getMTime());
|
||||
});
|
||||
|
||||
foreach ($node->getFileInfo()->getMetadata() as $metadataKey => $metadataValue) {
|
||||
$propFind->handle(self::FILE_METADATA_PREFIX . $metadataKey, $metadataValue);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ class FileSearchBackend implements ISearchBackend {
|
|||
new SearchPropertyDefinition('{DAV:}getlastmodified', true, true, true, SearchPropertyDefinition::DATATYPE_DATETIME),
|
||||
new SearchPropertyDefinition('{DAV:}creationdate', true, true, true, SearchPropertyDefinition::DATATYPE_DATETIME),
|
||||
new SearchPropertyDefinition('{http://nextcloud.org/ns}upload_time', true, true, true, SearchPropertyDefinition::DATATYPE_DATETIME),
|
||||
new SearchPropertyDefinition('{http://nextcloud.org/ns}last_activity', true, false, true, SearchPropertyDefinition::DATATYPE_DATETIME),
|
||||
new SearchPropertyDefinition(FilesPlugin::SIZE_PROPERTYNAME, true, true, true, SearchPropertyDefinition::DATATYPE_NONNEGATIVE_INTEGER),
|
||||
new SearchPropertyDefinition(TagsPlugin::FAVORITE_PROPERTYNAME, true, true, true, SearchPropertyDefinition::DATATYPE_BOOLEAN),
|
||||
new SearchPropertyDefinition(FilesPlugin::INTERNAL_FILEID_PROPERTYNAME, true, true, false, SearchPropertyDefinition::DATATYPE_NONNEGATIVE_INTEGER),
|
||||
|
|
@ -304,6 +305,8 @@ class FileSearchBackend implements ISearchBackend {
|
|||
return $node->getNode()->getCreationTime();
|
||||
case '{http://nextcloud.org/ns}upload_time':
|
||||
return $node->getNode()->getUploadTime();
|
||||
case '{http://nextcloud.org/ns}last_activity':
|
||||
return max($node->getNode()->getUploadTime(), $node->getNode()->getMTime());
|
||||
case FilesPlugin::SIZE_PROPERTYNAME:
|
||||
return $node->getSize();
|
||||
case FilesPlugin::INTERNAL_FILEID_PROPERTYNAME:
|
||||
|
|
@ -332,6 +335,8 @@ class FileSearchBackend implements ISearchBackend {
|
|||
$direction = $order->order === Order::ASC ? ISearchOrder::DIRECTION_ASCENDING : ISearchOrder::DIRECTION_DESCENDING;
|
||||
if (str_starts_with($order->property->name, FilesPlugin::FILE_METADATA_PREFIX)) {
|
||||
return new SearchOrder($direction, substr($order->property->name, strlen(FilesPlugin::FILE_METADATA_PREFIX)), IMetadataQuery::EXTRA);
|
||||
} elseif ($order->property->name === FilesPlugin::LAST_ACTIVITY_PROPERTYNAME) {
|
||||
return new SearchOrder($direction, 'last_activity');
|
||||
} else {
|
||||
return new SearchOrder($direction, $this->mapPropertyNameToColumn($order->property));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@
|
|||
"chunking",
|
||||
"public_shares_chunking",
|
||||
"search_supports_creation_time",
|
||||
"search_supports_upload_time"
|
||||
"search_supports_upload_time",
|
||||
"search_supports_last_activity"
|
||||
],
|
||||
"properties": {
|
||||
"chunking": {
|
||||
|
|
@ -47,6 +48,9 @@
|
|||
"search_supports_upload_time": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"search_supports_last_activity": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"bulkupload": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ class CapabilitiesTest extends TestCase {
|
|||
'public_shares_chunking' => true,
|
||||
'search_supports_creation_time' => true,
|
||||
'search_supports_upload_time' => true,
|
||||
'search_supports_last_activity' => true,
|
||||
],
|
||||
];
|
||||
$this->assertSame($expected, $capabilities->getCapabilities());
|
||||
|
|
@ -55,6 +56,7 @@ class CapabilitiesTest extends TestCase {
|
|||
'public_shares_chunking' => true,
|
||||
'search_supports_creation_time' => true,
|
||||
'search_supports_upload_time' => true,
|
||||
'search_supports_last_activity' => true,
|
||||
'bulkupload' => '1.0',
|
||||
],
|
||||
];
|
||||
|
|
@ -78,6 +80,7 @@ class CapabilitiesTest extends TestCase {
|
|||
'public_shares_chunking' => true,
|
||||
'search_supports_creation_time' => true,
|
||||
'search_supports_upload_time' => true,
|
||||
'search_supports_last_activity' => true,
|
||||
'absence-supported' => true,
|
||||
'absence-replacement' => true,
|
||||
],
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export async function getContents(path = '/', options: { signal: AbortSignal }):
|
|||
const contentsResponse = await client.search('/', {
|
||||
signal: options.signal,
|
||||
details: true,
|
||||
data: getRecentSearch(lastTwoWeeksTimestamp, store.userConfig.recent_files_limit),
|
||||
data: getRecentSearch(lastTwoWeeksTimestamp, store.userConfig.recent_files_limit + 1),
|
||||
}) as ResponseDataDetailed<SearchResult>
|
||||
|
||||
const contents = contentsResponse.data.results
|
||||
|
|
|
|||
|
|
@ -352,6 +352,10 @@ class SearchBuilder {
|
|||
if ($field === 'mtime') {
|
||||
$field = $query->func()->add($field, $query->createNamedParameter(0));
|
||||
}
|
||||
|
||||
if ($field === 'last_activity') {
|
||||
$field = $query->func()->greatest('file.mtime', $query->createFunction('COALESCE(fe.upload_time, 0)'));
|
||||
}
|
||||
}
|
||||
$query->addOrderBy($field, $order->getDirection());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,10 @@ class SearchOrder implements ISearchOrder {
|
|||
return $a->getId() <=> $b->getId();
|
||||
case 'permissions':
|
||||
return $a->getPermissions() <=> $b->getPermissions();
|
||||
case 'last_activity':
|
||||
$timeA = max($a->getUploadTime(), $a->getMtime());
|
||||
$timeB = max($b->getUploadTime(), $b->getMtime());
|
||||
return $timeA <=> $timeB;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1506,7 +1506,8 @@
|
|||
"chunking",
|
||||
"public_shares_chunking",
|
||||
"search_supports_creation_time",
|
||||
"search_supports_upload_time"
|
||||
"search_supports_upload_time",
|
||||
"search_supports_last_activity"
|
||||
],
|
||||
"properties": {
|
||||
"chunking": {
|
||||
|
|
@ -1521,6 +1522,9 @@
|
|||
"search_supports_upload_time": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"search_supports_last_activity": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"bulkupload": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in a new issue