Refactor all calls to use TimelineRoot
parent
4a5408b846
commit
d9afbbe710
|
@ -25,6 +25,7 @@ namespace OCA\Memories\Controller;
|
||||||
|
|
||||||
use OCA\Memories\AppInfo\Application;
|
use OCA\Memories\AppInfo\Application;
|
||||||
use OCA\Memories\Db\TimelineQuery;
|
use OCA\Memories\Db\TimelineQuery;
|
||||||
|
use OCA\Memories\Db\TimelineRoot;
|
||||||
use OCA\Memories\Db\TimelineWrite;
|
use OCA\Memories\Db\TimelineWrite;
|
||||||
use OCA\Memories\Exif;
|
use OCA\Memories\Exif;
|
||||||
use OCP\App\IAppManager;
|
use OCP\App\IAppManager;
|
||||||
|
@ -88,12 +89,14 @@ class ApiBase extends Controller
|
||||||
return $user ? $user->getUID() : '';
|
return $user ? $user->getUID() : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the Folder object relevant to the request */
|
/** Get the TimelineRoot object relevant to the request */
|
||||||
protected function getRequestFolder()
|
protected function getRequestRoot()
|
||||||
{
|
{
|
||||||
|
$root = new TimelineRoot();
|
||||||
|
|
||||||
// Albums have no folder
|
// Albums have no folder
|
||||||
if ($this->request->getParam('album')) {
|
if ($this->request->getParam('album')) {
|
||||||
return null;
|
return $root;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public shared folder
|
// Public shared folder
|
||||||
|
@ -103,7 +106,9 @@ class ApiBase extends Controller
|
||||||
throw new \Exception('Share not found or invalid');
|
throw new \Exception('Share not found or invalid');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $share;
|
$root->addFolder($share);
|
||||||
|
|
||||||
|
return $root;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Anything else needs a user
|
// Anything else needs a user
|
||||||
|
@ -135,7 +140,13 @@ class ApiBase extends Controller
|
||||||
throw new \Exception('Folder not readable');
|
throw new \Exception('Folder not readable');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $folder;
|
// Don't add mount points for folder view
|
||||||
|
$root->addFolder($folder);
|
||||||
|
if (null === $folderPath) {
|
||||||
|
$root->addMountPoints();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $root;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -23,9 +23,9 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCA\Memories\Controller;
|
namespace OCA\Memories\Controller;
|
||||||
|
|
||||||
|
use OCA\Memories\Db\TimelineRoot;
|
||||||
use OCP\AppFramework\Http;
|
use OCP\AppFramework\Http;
|
||||||
use OCP\AppFramework\Http\JSONResponse;
|
use OCP\AppFramework\Http\JSONResponse;
|
||||||
use OCP\Files\Folder;
|
|
||||||
|
|
||||||
class DaysController extends ApiBase
|
class DaysController extends ApiBase
|
||||||
{
|
{
|
||||||
|
@ -42,10 +42,10 @@ class DaysController extends ApiBase
|
||||||
$uid = $this->getUid();
|
$uid = $this->getUid();
|
||||||
|
|
||||||
// Get the folder to show
|
// Get the folder to show
|
||||||
$folder = null;
|
$root = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$folder = $this->getRequestFolder();
|
$root = $this->getRequestRoot();
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_NOT_FOUND);
|
return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ class DaysController extends ApiBase
|
||||||
// Run actual query
|
// Run actual query
|
||||||
try {
|
try {
|
||||||
$list = $this->timelineQuery->getDays(
|
$list = $this->timelineQuery->getDays(
|
||||||
$folder,
|
$root,
|
||||||
$uid,
|
$uid,
|
||||||
$this->isRecursive(),
|
$this->isRecursive(),
|
||||||
$this->isArchive(),
|
$this->isArchive(),
|
||||||
|
@ -65,7 +65,7 @@ class DaysController extends ApiBase
|
||||||
$list = $this->timelineQuery->daysToMonths($list);
|
$list = $this->timelineQuery->daysToMonths($list);
|
||||||
} else {
|
} else {
|
||||||
// Preload some day responses
|
// Preload some day responses
|
||||||
$this->preloadDays($list, $uid, $folder);
|
$this->preloadDays($list, $uid, $root);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse response if requested. Folders still stay at top.
|
// Reverse response if requested. Folders still stay at top.
|
||||||
|
@ -75,7 +75,7 @@ class DaysController extends ApiBase
|
||||||
|
|
||||||
// Add subfolder info if querying non-recursively
|
// Add subfolder info if querying non-recursively
|
||||||
if (!$this->isRecursive()) {
|
if (!$this->isRecursive()) {
|
||||||
array_unshift($list, $this->getSubfoldersEntry($folder));
|
array_unshift($list, $this->getSubfoldersEntry($root->getFolder($root->getOneId())));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new JSONResponse($list, Http::STATUS_OK);
|
return new JSONResponse($list, Http::STATUS_OK);
|
||||||
|
@ -111,10 +111,10 @@ class DaysController extends ApiBase
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the folder to show
|
// Get the folder to show
|
||||||
$folder = null;
|
$root = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$folder = $this->getRequestFolder();
|
$root = $this->getRequestRoot();
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_NOT_FOUND);
|
return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ class DaysController extends ApiBase
|
||||||
// Run actual query
|
// Run actual query
|
||||||
try {
|
try {
|
||||||
$list = $this->timelineQuery->getDay(
|
$list = $this->timelineQuery->getDay(
|
||||||
$folder,
|
$root,
|
||||||
$uid,
|
$uid,
|
||||||
$dayIds,
|
$dayIds,
|
||||||
$this->isRecursive(),
|
$this->isRecursive(),
|
||||||
|
@ -239,9 +239,9 @@ class DaysController extends ApiBase
|
||||||
*
|
*
|
||||||
* @param array $days the days array
|
* @param array $days the days array
|
||||||
* @param string $uid User ID or blank for public shares
|
* @param string $uid User ID or blank for public shares
|
||||||
* @param null|Folder $folder the folder to search in
|
* @param TimelineRoot $root the root folder
|
||||||
*/
|
*/
|
||||||
private function preloadDays(array &$days, string $uid, &$folder)
|
private function preloadDays(array &$days, string $uid, TimelineRoot &$root)
|
||||||
{
|
{
|
||||||
$transforms = $this->getTransformations(false);
|
$transforms = $this->getTransformations(false);
|
||||||
$preloaded = 0;
|
$preloaded = 0;
|
||||||
|
@ -263,7 +263,7 @@ class DaysController extends ApiBase
|
||||||
|
|
||||||
if (\count($preloadDayIds) > 0) {
|
if (\count($preloadDayIds) > 0) {
|
||||||
$allDetails = $this->timelineQuery->getDay(
|
$allDetails = $this->timelineQuery->getDay(
|
||||||
$folder,
|
$root,
|
||||||
$uid,
|
$uid,
|
||||||
$preloadDayIds,
|
$preloadDayIds,
|
||||||
$this->isRecursive(),
|
$this->isRecursive(),
|
||||||
|
|
|
@ -49,14 +49,14 @@ class FacesController extends ApiBase
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this isn't the timeline folder then things aren't going to work
|
// If this isn't the timeline folder then things aren't going to work
|
||||||
$folder = $this->getRequestFolder();
|
$root = $this->getRequestRoot();
|
||||||
if (null === $folder) {
|
if ($root->isEmpty()) {
|
||||||
return new JSONResponse([], Http::STATUS_NOT_FOUND);
|
return new JSONResponse([], Http::STATUS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run actual query
|
// Run actual query
|
||||||
$list = $this->timelineQuery->getFaces(
|
$list = $this->timelineQuery->getFaces(
|
||||||
$folder,
|
$root,
|
||||||
);
|
);
|
||||||
|
|
||||||
return new JSONResponse($list, Http::STATUS_OK);
|
return new JSONResponse($list, Http::STATUS_OK);
|
||||||
|
@ -84,22 +84,23 @@ class FacesController extends ApiBase
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get folder to search for
|
// Get folder to search for
|
||||||
$folder = $this->getRequestFolder();
|
$root = $this->getRequestRoot();
|
||||||
if (null === $folder) {
|
if ($root->isEmpty()) {
|
||||||
return new JSONResponse([], Http::STATUS_NOT_FOUND);
|
return new JSONResponse([], Http::STATUS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run actual query
|
// Run actual query
|
||||||
$detections = $this->timelineQuery->getFacePreviewDetection($folder, (int) $id);
|
$detections = $this->timelineQuery->getFacePreviewDetection($root, (int) $id);
|
||||||
if (null === $detections || 0 === \count($detections)) {
|
if (null === $detections || 0 === \count($detections)) {
|
||||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the first detection that has a preview
|
// Find the first detection that has a preview
|
||||||
$preview = null;
|
$preview = null;
|
||||||
|
$userFolder = $this->rootFolder->getUserFolder($user->getUID());
|
||||||
foreach ($detections as &$detection) {
|
foreach ($detections as &$detection) {
|
||||||
// Get the file (also checks permissions)
|
// Get the file (also checks permissions)
|
||||||
$files = $folder->getById($detection['file_id']);
|
$files = $userFolder->getById($detection['file_id']);
|
||||||
if (0 === \count($files) || FileInfo::TYPE_FILE !== $files[0]->getType()) {
|
if (0 === \count($files) || FileInfo::TYPE_FILE !== $files[0]->getType()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,14 +46,14 @@ class TagsController extends ApiBase
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this isn't the timeline folder then things aren't going to work
|
// If this isn't the timeline folder then things aren't going to work
|
||||||
$folder = $this->getRequestFolder();
|
$root = $this->getRequestRoot();
|
||||||
if (null === $folder) {
|
if ($root->isEmpty()) {
|
||||||
return new JSONResponse([], Http::STATUS_NOT_FOUND);
|
return new JSONResponse([], Http::STATUS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run actual query
|
// Run actual query
|
||||||
$list = $this->timelineQuery->getTags(
|
$list = $this->timelineQuery->getTags(
|
||||||
$folder,
|
$root,
|
||||||
);
|
);
|
||||||
|
|
||||||
return new JSONResponse($list, Http::STATUS_OK);
|
return new JSONResponse($list, Http::STATUS_OK);
|
||||||
|
@ -77,8 +77,8 @@ class TagsController extends ApiBase
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this isn't the timeline folder then things aren't going to work
|
// If this isn't the timeline folder then things aren't going to work
|
||||||
$folder = $this->getRequestFolder();
|
$root = $this->getRequestRoot();
|
||||||
if (null === $folder) {
|
if ($root->isEmpty()) {
|
||||||
return new JSONResponse([], Http::STATUS_NOT_FOUND);
|
return new JSONResponse([], Http::STATUS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ class TagsController extends ApiBase
|
||||||
// Run actual query
|
// Run actual query
|
||||||
$list = $this->timelineQuery->getTagPreviews(
|
$list = $this->timelineQuery->getTagPreviews(
|
||||||
$tagName,
|
$tagName,
|
||||||
$folder,
|
$root,
|
||||||
);
|
);
|
||||||
|
|
||||||
return new JSONResponse($list, Http::STATUS_OK);
|
return new JSONResponse($list, Http::STATUS_OK);
|
||||||
|
|
|
@ -5,7 +5,6 @@ declare(strict_types=1);
|
||||||
namespace OCA\Memories\Db;
|
namespace OCA\Memories\Db;
|
||||||
|
|
||||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||||
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
|
||||||
|
@ -73,13 +72,10 @@ 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.
|
||||||
*
|
*
|
||||||
* @param null|Folder $folder The folder to get the days from
|
* @param TimelineRoot $root The root to get the days from
|
||||||
* @param bool $recursive Whether to get the days recursively
|
* @param bool $recursive Whether to get the days recursively
|
||||||
* @param bool $archive Whether to get the days only from the archive folder
|
* @param bool $archive Whether to get the days only from the archive folder
|
||||||
* @param array $queryTransforms An array of query transforms to apply to the query
|
* @param array $queryTransforms An array of query transforms to apply to the query
|
||||||
|
@ -87,7 +83,7 @@ trait TimelineQueryDays
|
||||||
* @return array The days response
|
* @return array The days response
|
||||||
*/
|
*/
|
||||||
public function getDays(
|
public function getDays(
|
||||||
&$folder,
|
TimelineRoot &$root,
|
||||||
string $uid,
|
string $uid,
|
||||||
bool $recursive,
|
bool $recursive,
|
||||||
bool $archive,
|
bool $archive,
|
||||||
|
@ -100,7 +96,7 @@ trait TimelineQueryDays
|
||||||
$query->select('m.dayid', $count)
|
$query->select('m.dayid', $count)
|
||||||
->from('memories', 'm')
|
->from('memories', 'm')
|
||||||
;
|
;
|
||||||
$query = $this->joinFilecache($query, $folder, $recursive, $archive);
|
$query = $this->joinFilecache($query, $root, $recursive, $archive);
|
||||||
|
|
||||||
// Group and sort by dayid
|
// Group and sort by dayid
|
||||||
$query->groupBy('m.dayid')
|
$query->groupBy('m.dayid')
|
||||||
|
@ -120,7 +116,7 @@ trait TimelineQueryDays
|
||||||
/**
|
/**
|
||||||
* Get the day response from the database for the timeline.
|
* Get the day response from the database for the timeline.
|
||||||
*
|
*
|
||||||
* @param null|Folder $folder The folder to get the day from
|
* @param TimelineRoot $root The root to get the day from
|
||||||
* @param string $uid The user id
|
* @param string $uid The user id
|
||||||
* @param int[] $day_ids The day ids to fetch
|
* @param int[] $day_ids The day ids to fetch
|
||||||
* @param bool $recursive If the query should be recursive
|
* @param bool $recursive If the query should be recursive
|
||||||
|
@ -131,7 +127,7 @@ trait TimelineQueryDays
|
||||||
* @return array An array of day responses
|
* @return array An array of day responses
|
||||||
*/
|
*/
|
||||||
public function getDay(
|
public function getDay(
|
||||||
&$folder,
|
TimelineRoot &$root,
|
||||||
string $uid,
|
string $uid,
|
||||||
$day_ids,
|
$day_ids,
|
||||||
bool $recursive,
|
bool $recursive,
|
||||||
|
@ -151,7 +147,7 @@ trait TimelineQueryDays
|
||||||
;
|
;
|
||||||
|
|
||||||
// JOIN with filecache for existing files
|
// JOIN with filecache for existing files
|
||||||
$query = $this->joinFilecache($query, $folder, $recursive, $archive);
|
$query = $this->joinFilecache($query, $root, $recursive, $archive);
|
||||||
$query->addSelect('f.etag', 'f.path', 'f.name AS basename');
|
$query->addSelect('f.etag', 'f.path', 'f.name AS basename');
|
||||||
|
|
||||||
// JOIN with mimetypes to get the mimetype
|
// JOIN with mimetypes to get the mimetype
|
||||||
|
@ -180,7 +176,7 @@ trait TimelineQueryDays
|
||||||
$rows = $cursor->fetchAll();
|
$rows = $cursor->fetchAll();
|
||||||
$cursor->closeCursor();
|
$cursor->closeCursor();
|
||||||
|
|
||||||
return $this->processDay($rows, $uid, $folder);
|
return $this->processDay($rows, $uid, $root);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -200,12 +196,8 @@ trait TimelineQueryDays
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the single day response.
|
* Process the single day response.
|
||||||
*
|
|
||||||
* @param array $day
|
|
||||||
* @param string $uid User or blank if not logged in
|
|
||||||
* @param null|Folder $folder
|
|
||||||
*/
|
*/
|
||||||
private function processDay(&$day, $uid, $folder)
|
private function processDay(array &$day, string $uid, TimelineRoot &$root)
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Path entry in database for folder.
|
* Path entry in database for folder.
|
||||||
|
@ -225,15 +217,15 @@ trait TimelineQueryDays
|
||||||
*/
|
*/
|
||||||
$defaultRootId = 0;
|
$defaultRootId = 0;
|
||||||
|
|
||||||
if (null !== $folder) {
|
if (!$root->isEmpty()) {
|
||||||
// Get root id of the top folder
|
// Get root id of the top folder
|
||||||
$defaultRootId = $folder->getId();
|
$defaultRootId = $root->getOneId();
|
||||||
|
|
||||||
// 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('fileid', 'path')
|
$query->select('fileid', 'path')
|
||||||
->from('filecache')
|
->from('filecache')
|
||||||
->where($query->expr()->in('fileid', $query->createNamedParameter(array_keys($this->topFolderPaths), IQueryBuilder::PARAM_INT_ARRAY)))
|
->where($query->expr()->in('fileid', $query->createNamedParameter($root->getIds(), IQueryBuilder::PARAM_INT_ARRAY)))
|
||||||
;
|
;
|
||||||
$paths = $query->executeQuery()->fetchAll();
|
$paths = $query->executeQuery()->fetchAll();
|
||||||
foreach ($paths as &$path) {
|
foreach ($paths as &$path) {
|
||||||
|
@ -244,7 +236,7 @@ trait TimelineQueryDays
|
||||||
// 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) && ($actualPath = $this->topFolderPaths[$fileid])) {
|
if (!empty($uid) && ($actualPath = $root->getFolderPath($fileid))) {
|
||||||
$actualPath = explode('/', $actualPath);
|
$actualPath = explode('/', $actualPath);
|
||||||
if (\count($actualPath) >= 3) {
|
if (\count($actualPath) >= 3) {
|
||||||
$tmp = $actualPath[1];
|
$tmp = $actualPath[1];
|
||||||
|
@ -317,10 +309,11 @@ trait TimelineQueryDays
|
||||||
*/
|
*/
|
||||||
private function addSubfolderJoinParams(
|
private function addSubfolderJoinParams(
|
||||||
IQueryBuilder &$query,
|
IQueryBuilder &$query,
|
||||||
|
TimelineRoot &$root,
|
||||||
bool $archive
|
bool $archive
|
||||||
) {
|
) {
|
||||||
// Add query parameters
|
// Add query parameters
|
||||||
$query->setParameter('topFolderIds', array_keys($this->topFolderPaths), IQueryBuilder::PARAM_INT_ARRAY);
|
$query->setParameter('topFolderIds', $root->getIds(), IQueryBuilder::PARAM_INT_ARRAY);
|
||||||
$query->setParameter('cteFoldersArchive', $archive, IQueryBuilder::PARAM_BOOL);
|
$query->setParameter('cteFoldersArchive', $archive, IQueryBuilder::PARAM_BOOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,44 +321,32 @@ trait TimelineQueryDays
|
||||||
* Inner join with oc_filecache.
|
* Inner join with oc_filecache.
|
||||||
*
|
*
|
||||||
* @param IQueryBuilder $query Query builder
|
* @param IQueryBuilder $query Query builder
|
||||||
* @param null|Folder $folder Either the top folder or null for all
|
* @param TimelineRoot $root Either the top folder or null for all
|
||||||
* @param bool $recursive Whether to get the days recursively
|
* @param bool $recursive Whether to get the days recursively
|
||||||
* @param bool $archive Whether to get the days only from the archive folder
|
* @param bool $archive Whether to get the days only from the archive folder
|
||||||
*/
|
*/
|
||||||
private function joinFilecache(
|
private function joinFilecache(
|
||||||
IQueryBuilder &$query,
|
IQueryBuilder &$query,
|
||||||
&$folder,
|
TimelineRoot &$root,
|
||||||
bool $recursive,
|
bool $recursive,
|
||||||
bool $archive
|
bool $archive
|
||||||
) {
|
) {
|
||||||
// Join with memories
|
// Join with memories
|
||||||
$baseOp = $query->expr()->eq('f.fileid', 'm.fileid');
|
$baseOp = $query->expr()->eq('f.fileid', 'm.fileid');
|
||||||
if (null === $folder) {
|
if ($root->isEmpty()) {
|
||||||
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, $archive);
|
$this->addSubfolderJoinParams($query, $root, $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');
|
$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($root->getOneId(), IQueryBuilder::PARAM_INT));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $query->innerJoin('m', 'filecache', 'f', $query->expr()->andX(
|
return $query->innerJoin('m', 'filecache', 'f', $query->expr()->andX(
|
||||||
|
|
|
@ -47,7 +47,7 @@ trait TimelineQueryFaces
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFaces(Folder $folder)
|
public function getFaces(TimelineRoot &$root)
|
||||||
{
|
{
|
||||||
$query = $this->connection->getQueryBuilder();
|
$query = $this->connection->getQueryBuilder();
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ trait TimelineQueryFaces
|
||||||
$query->innerJoin('rfd', 'memories', 'm', $query->expr()->eq('m.fileid', 'rfd.file_id'));
|
$query->innerJoin('rfd', 'memories', 'm', $query->expr()->eq('m.fileid', 'rfd.file_id'));
|
||||||
|
|
||||||
// WHERE these photos are in the user's requested folder recursively
|
// WHERE these photos are in the user's requested folder recursively
|
||||||
$query = $this->joinFilecache($query, $folder, true, false);
|
$query = $this->joinFilecache($query, $root, true, false);
|
||||||
|
|
||||||
// GROUP by ID of face cluster
|
// GROUP by ID of face cluster
|
||||||
$query->groupBy('rfc.id');
|
$query->groupBy('rfc.id');
|
||||||
|
@ -87,7 +87,7 @@ trait TimelineQueryFaces
|
||||||
return $faces;
|
return $faces;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFacePreviewDetection(Folder &$folder, int $id)
|
public function getFacePreviewDetection(TimelineRoot &$root, int $id)
|
||||||
{
|
{
|
||||||
$query = $this->connection->getQueryBuilder();
|
$query = $this->connection->getQueryBuilder();
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ trait TimelineQueryFaces
|
||||||
$query->innerJoin('rfd', 'memories', 'm', $query->expr()->eq('m.fileid', 'rfd.file_id'));
|
$query->innerJoin('rfd', 'memories', 'm', $query->expr()->eq('m.fileid', 'rfd.file_id'));
|
||||||
|
|
||||||
// WHERE these photos are in the user's requested folder recursively
|
// WHERE these photos are in the user's requested folder recursively
|
||||||
$query = $this->joinFilecache($query, $folder, true, false);
|
$query = $this->joinFilecache($query, $root, true, false);
|
||||||
|
|
||||||
// LIMIT results
|
// LIMIT results
|
||||||
$query->setMaxResults(15);
|
$query->setMaxResults(15);
|
||||||
|
|
|
@ -19,7 +19,9 @@ trait TimelineQueryFolders
|
||||||
$query->select('f.fileid', 'f.etag')->from('memories', 'm');
|
$query->select('f.fileid', 'f.etag')->from('memories', 'm');
|
||||||
|
|
||||||
// WHERE these photos are in the user's requested folder recursively
|
// WHERE these photos are in the user's requested folder recursively
|
||||||
$query = $this->joinFilecache($query, $folder, true, false);
|
$root = new TimelineRoot();
|
||||||
|
$root->addFolder($folder);
|
||||||
|
$query = $this->joinFilecache($query, $root, true, false);
|
||||||
|
|
||||||
// ORDER descending by fileid
|
// ORDER descending by fileid
|
||||||
$query->orderBy('f.fileid', 'DESC');
|
$query->orderBy('f.fileid', 'DESC');
|
||||||
|
|
|
@ -38,7 +38,7 @@ trait TimelineQueryTags
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTags(Folder $folder)
|
public function getTags(TimelineRoot &$root)
|
||||||
{
|
{
|
||||||
$query = $this->connection->getQueryBuilder();
|
$query = $this->connection->getQueryBuilder();
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ trait TimelineQueryTags
|
||||||
$query->innerJoin('stom', 'memories', 'm', $query->expr()->eq('m.objectid', 'stom.objectid'));
|
$query->innerJoin('stom', 'memories', 'm', $query->expr()->eq('m.objectid', 'stom.objectid'));
|
||||||
|
|
||||||
// WHERE these photos are in the user's requested folder recursively
|
// WHERE these photos are in the user's requested folder recursively
|
||||||
$query = $this->joinFilecache($query, $folder, true, false);
|
$query = $this->joinFilecache($query, $root, true, false);
|
||||||
|
|
||||||
// GROUP and ORDER by tag name
|
// GROUP and ORDER by tag name
|
||||||
$query->groupBy('st.id');
|
$query->groupBy('st.id');
|
||||||
|
@ -78,7 +78,7 @@ trait TimelineQueryTags
|
||||||
return $tags;
|
return $tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTagPreviews(string $tagName, Folder &$folder)
|
public function getTagPreviews(string $tagName, TimelineRoot &$root)
|
||||||
{
|
{
|
||||||
$query = $this->connection->getQueryBuilder();
|
$query = $this->connection->getQueryBuilder();
|
||||||
$tagId = $this->getSystemTagId($query, $tagName);
|
$tagId = $this->getSystemTagId($query, $tagName);
|
||||||
|
@ -99,7 +99,7 @@ trait TimelineQueryTags
|
||||||
$query->innerJoin('stom', 'memories', 'm', $query->expr()->eq('m.objectid', 'stom.objectid'));
|
$query->innerJoin('stom', 'memories', 'm', $query->expr()->eq('m.objectid', 'stom.objectid'));
|
||||||
|
|
||||||
// WHERE these photos are in the user's requested folder recursively
|
// WHERE these photos are in the user's requested folder recursively
|
||||||
$query = $this->joinFilecache($query, $folder, true, false);
|
$query = $this->joinFilecache($query, $root, true, false);
|
||||||
|
|
||||||
// MAX 4
|
// MAX 4
|
||||||
$query->setMaxResults(4);
|
$query->setMaxResults(4);
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace OCA\Memories\Db;
|
||||||
|
|
||||||
|
use OCP\Files\Folder;
|
||||||
|
|
||||||
|
class TimelineRoot
|
||||||
|
{
|
||||||
|
protected array $folders;
|
||||||
|
protected array $folderPaths;
|
||||||
|
|
||||||
|
/** Initialize */
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addFolder(Folder &$folder)
|
||||||
|
{
|
||||||
|
// Add top level folder
|
||||||
|
$id = $folder->getId();
|
||||||
|
$folderPath = $folder->getPath();
|
||||||
|
$this->folders[$id] = $folder;
|
||||||
|
$this->folderPaths[$id] = $folderPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add mountpoints recursively
|
||||||
|
public function addMountPoints()
|
||||||
|
{
|
||||||
|
$mp = [];
|
||||||
|
foreach ($this->folderPaths as $id => $folderPath) {
|
||||||
|
$mounts = \OC\Files\Filesystem::getMountManager()->findIn($folderPath);
|
||||||
|
foreach ($mounts as &$mount) {
|
||||||
|
$id = $mount->getStorageRootId();
|
||||||
|
$path = $mount->getMountPoint();
|
||||||
|
$mp[$id] = $path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->folderPaths += $mp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFolderPath(int $id)
|
||||||
|
{
|
||||||
|
return $this->folderPaths[$id];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIds()
|
||||||
|
{
|
||||||
|
return array_keys($this->folderPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOneId()
|
||||||
|
{
|
||||||
|
return array_key_first($this->folders);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFolder(int $id)
|
||||||
|
{
|
||||||
|
return $this->folders[$id];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isEmpty()
|
||||||
|
{
|
||||||
|
return empty($this->folderPaths);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue