Fix filename of recursive mounts

pull/221/head
Varun Patil 2022-11-15 21:05:11 -08:00
parent f1e9765814
commit 0c6d5a57b5
2 changed files with 70 additions and 32 deletions

View File

@ -9,16 +9,18 @@ use OCP\Files\Folder;
use OCP\IDBConnection; use OCP\IDBConnection;
const CTE_FOLDERS = // CTE to get all folders recursively in the given top folders excluding archive const CTE_FOLDERS = // CTE to get all folders recursively in the given top folders excluding archive
'WITH RECURSIVE *PREFIX*cte_folders(fileid) AS ( 'WITH RECURSIVE *PREFIX*cte_folders(fileid, rootid) AS (
SELECT SELECT
f.fileid f.fileid,
f.fileid AS rootid
FROM FROM
*PREFIX*filecache f *PREFIX*filecache f
WHERE WHERE
f.fileid IN (:topFolderIds) f.fileid IN (:topFolderIds)
UNION ALL UNION ALL
SELECT SELECT
f.fileid f.fileid,
c.rootid
FROM FROM
*PREFIX*filecache f *PREFIX*filecache f
INNER JOIN *PREFIX*cte_folders c INNER JOIN *PREFIX*cte_folders c
@ -65,6 +67,9 @@ trait TimelineQueryDays
{ {
protected IDBConnection $connection; protected IDBConnection $connection;
/** Map of rootid => mount point */
private $topFolderPaths = [];
/** /**
* Get the days response from the database for the timeline. * Get the days response from the database for the timeline.
* *
@ -196,30 +201,51 @@ trait TimelineQueryDays
*/ */
private function processDay(&$day, $uid, $folder) private function processDay(&$day, $uid, $folder)
{ {
$basePath = '#__#__#'; /**
$davPath = ''; * Path entry in database for folder.
* We need to splice this from the start of the file path.
*/
$internalPaths = [];
/**
* DAV paths for the folders.
* We need to prefix this to the start of the file path.
*/
$davPaths = [];
/**
* The root folder id for the folder.
* We fallback to this if rootid is not found
*/
$defaultRootId = 0;
if (null !== $folder) { if (null !== $folder) {
// Get root id of the top folder
$defaultRootId = $folder->getId();
// No way to get the internal path from the folder // No way to get the internal path from the folder
$query = $this->connection->getQueryBuilder(); $query = $this->connection->getQueryBuilder();
$query->select('path') $query->select('fileid', 'path')
->from('filecache') ->from('filecache')
->where($query->expr()->eq('fileid', $query->createNamedParameter($folder->getId(), IQueryBuilder::PARAM_INT))) ->where($query->expr()->in('fileid', $query->createNamedParameter(array_keys($this->topFolderPaths), IQueryBuilder::PARAM_INT_ARRAY)))
; ;
$path = $query->executeQuery()->fetchOne(); $paths = $query->executeQuery()->fetchAll();
$basePath = $path ?: $basePath; foreach ($paths as &$path) {
$fileid = (int) $path['fileid'];
$internalPaths[$fileid] = $path['path'];
// Get user facing path // Get DAV path.
// getPath looks like /user/files/... but we want /files/user/... // getPath looks like /user/files/... but we want /files/user/...
// Split at / and swap these // Split at / and swap these
// For public shares, we just give the relative path // For public shares, we just give the relative path
if (!empty($uid)) { if (!empty($uid) && ($actualPath = $this->topFolderPaths[$fileid])) {
$actualPath = $folder->getPath(); $actualPath = explode('/', $actualPath);
$actualPath = explode('/', $actualPath); if (\count($actualPath) >= 3) {
if (\count($actualPath) >= 3) { $tmp = $actualPath[1];
$tmp = $actualPath[1]; $actualPath[1] = $actualPath[2];
$actualPath[1] = $actualPath[2]; $actualPath[2] = $tmp;
$actualPath[2] = $tmp; $davPaths[$fileid] = implode('/', $actualPath);
$davPath = implode('/', $actualPath); }
} }
} }
} }
@ -245,9 +271,14 @@ trait TimelineQueryDays
// Check if path exists and starts with basePath and remove // Check if path exists and starts with basePath and remove
if (isset($row['path']) && !empty($row['path'])) { if (isset($row['path']) && !empty($row['path'])) {
$rootId = $row['rootid'] ?: $defaultRootId;
$basePath = $internalPaths[$rootId] ?: '#__#';
$davPath = $davPaths[$rootId] ?: '';
if (0 === strpos($row['path'], $basePath)) { if (0 === strpos($row['path'], $basePath)) {
$row['filename'] = $davPath.substr($row['path'], \strlen($basePath)); $row['filename'] = $davPath.substr($row['path'], \strlen($basePath));
} }
unset($row['path']); unset($row['path']);
} }
@ -280,18 +311,10 @@ trait TimelineQueryDays
*/ */
private function addSubfolderJoinParams( private function addSubfolderJoinParams(
IQueryBuilder &$query, IQueryBuilder &$query,
Folder &$folder,
bool $archive bool $archive
) { ) {
// Get storages recursively
$topFolderIds = [$folder->getId()];
$mounts = \OC\Files\Filesystem::getMountManager()->findIn($folder->getPath());
foreach ($mounts as &$mount) {
$topFolderIds[] = $mount->getStorageRootId();
}
// Add query parameters // Add query parameters
$query->setParameter('topFolderIds', $topFolderIds, IQueryBuilder::PARAM_INT_ARRAY); $query->setParameter('topFolderIds', array_keys($this->topFolderPaths), IQueryBuilder::PARAM_INT_ARRAY);
$query->setParameter('cteFoldersArchive', $archive, IQueryBuilder::PARAM_BOOL); $query->setParameter('cteFoldersArchive', $archive, IQueryBuilder::PARAM_BOOL);
} }
@ -315,12 +338,25 @@ trait TimelineQueryDays
return $query->innerJoin('m', 'filecache', 'f', $baseOp); return $query->innerJoin('m', 'filecache', 'f', $baseOp);
} }
// Create top folders paths for later processing
$this->topFolderPaths = [];
$this->topFolderPaths[$folder->getId()] = $folder->getPath();
// Filter by folder (recursive or otherwise) // Filter by folder (recursive or otherwise)
$pathOp = null; $pathOp = null;
if ($recursive) { if ($recursive) {
// Add mountpoints recursively
$this->mounts = \OC\Files\Filesystem::getMountManager()->findIn($folder->getPath());
foreach ($this->mounts as &$mount) {
$id = $mount->getStorageRootId();
$path = $mount->getMountPoint();
$this->topFolderPaths[$id] = $path;
}
// Join with folders CTE // Join with folders CTE
$this->addSubfolderJoinParams($query, $folder, $archive); $this->addSubfolderJoinParams($query, $archive);
$query->innerJoin('f', 'cte_folders', 'cte_f', $query->expr()->eq('f.parent', 'cte_f.fileid')); $query->innerJoin('f', 'cte_folders', 'cte_f', $query->expr()->eq('f.parent', 'cte_f.fileid'));
$query->addSelect('cte_f.rootid');
} else { } else {
// If getting non-recursively folder only check for parent // If getting non-recursively folder only check for parent
$pathOp = $query->expr()->eq('f.parent', $query->createNamedParameter($folder->getId(), IQueryBuilder::PARAM_INT)); $pathOp = $query->expr()->eq('f.parent', $query->createNamedParameter($folder->getId(), IQueryBuilder::PARAM_INT));

View File

@ -917,7 +917,9 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
head.day.detail.length === photos.length && head.day.detail.length === photos.length &&
head.day.detail.every( head.day.detail.every(
(p, i) => (p, i) =>
p.fileid === photos[i].fileid && p.etag === photos[i].etag p.fileid === photos[i].fileid &&
p.etag === photos[i].etag &&
p.filename === photos[i].filename
) )
) { ) {
continue; continue;