Add albums transform

old-stable24
Varun Patil 2022-10-26 16:20:28 -07:00
parent 50bb55536f
commit 8d97dc7914
4 changed files with 101 additions and 32 deletions

View File

@ -95,6 +95,12 @@ class ApiController extends Controller
return new JSONResponse(['message' => 'Folder not found'], Http::STATUS_NOT_FOUND);
}
// Remove folder if album
// Permissions will be checked during the transform
if ($this->request->getParam('album')) {
$folder = null;
}
// Run actual query
try {
$list = $this->timelineQuery->getDays(
@ -255,7 +261,6 @@ class ApiController extends Controller
/**
* @NoAdminRequired
* @NoCSRFRequired
*
* Get list of albums with counts of images
*/
@ -672,12 +677,18 @@ class ApiController extends Controller
// Filter only for one tag
if ($this->tagsIsEnabled()) {
$tagName = $this->request->getParam('tag');
if ($tagName) {
if ($tagName = $this->request->getParam('tag')) {
$transforms[] = [$this->timelineQuery, 'transformTagFilter', $tagName];
}
}
// Filter for one album
if ($this->albumsIsEnabled()) {
if ($albumId = $this->request->getParam('album')) {
$transforms[] = [$this->timelineQuery, 'transformAlbumFilter', $albumId];
}
}
// Limit number of responses for day query
$limit = $this->request->getParam('limit');
if ($limit) {
@ -687,8 +698,15 @@ class ApiController extends Controller
return $transforms;
}
/** Preload a few "day" at the start of "days" response */
private function preloadDays(array &$days, Folder &$folder, bool $recursive, bool $archive)
/**
* Preload a few "day" at the start of "days" response.
*
* @param array $days the days array
* @param null|Folder $folder the folder to search in
* @param bool $recursive search in subfolders
* @param bool $archive search in archive folder only
*/
private function preloadDays(array &$days, &$folder, bool $recursive, bool $archive)
{
$uid = $this->userSession->getUser()->getUID();
$transforms = $this->getTransformations(false);
@ -696,13 +714,15 @@ class ApiController extends Controller
$preloadDayIds = [];
$preloadDays = [];
foreach ($days as &$day) {
if ($day['count'] <= 0) continue;
if ($day['count'] <= 0) {
continue;
}
$preloaded += $day['count'];
$preloadDayIds[] = $day['dayid'];
$preloadDays[] = &$day;
if ($preloaded >= 50 || count($preloadDayIds) > 5) { // should be enough
if ($preloaded >= 50 || \count($preloadDayIds) > 5) { // should be enough
break;
}
}

View File

@ -8,11 +8,11 @@ use OCP\IDBConnection;
class TimelineQuery
{
use TimelineQueryAlbums;
use TimelineQueryDays;
use TimelineQueryFaces;
use TimelineQueryFilters;
use TimelineQueryTags;
use TimelineQueryAlbums;
protected IDBConnection $connection;

View File

@ -4,12 +4,28 @@ declare(strict_types=1);
namespace OCA\Memories\Db;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
trait TimelineQueryAlbums
{
protected IDBConnection $connection;
/** Transform only for album */
public function transformAlbumFilter(IQueryBuilder &$query, string $uid, string $albumId)
{
if (!$this->hasAlbumPermission($query->getConnection(), $uid, (int) $albumId)) {
throw new \Exception("Album {$albumId} not found");
}
// WHERE these are items with this album
$query->innerJoin('m', 'photos_albums_files', 'paf', $query->expr()->andX(
$query->expr()->eq('paf.album_id', $query->createNamedParameter($albumId)),
$query->expr()->eq('paf.file_id', 'm.fileid'),
));
}
/** Get list of albums */
public function getAlbums(string $uid)
{
$query = $this->connection->getQueryBuilder();
@ -20,7 +36,7 @@ trait TimelineQueryAlbums
$query->expr()->eq('user', $query->createNamedParameter($uid)),
);
// WHERE there are items with this tag
// WHERE these are items with this album
$query->innerJoin('pa', 'photos_albums_files', 'paf', $query->expr()->andX(
$query->expr()->eq('paf.album_id', 'pa.album_id'),
));
@ -29,7 +45,7 @@ trait TimelineQueryAlbums
$query->innerJoin('paf', 'memories', 'm', $query->expr()->eq('m.fileid', 'paf.file_id'));
// WHERE these photos are in the filecache
$query->innerJoin('m', 'filecache', 'f', $query->expr()->eq('m.fileid', 'f.fileid'),);
$query->innerJoin('m', 'filecache', 'f', $query->expr()->eq('m.fileid', 'f.fileid'));
// GROUP and ORDER by
$query->groupBy('pa.album_id');
@ -48,4 +64,30 @@ trait TimelineQueryAlbums
return $albums;
}
private function hasAlbumPermission(IDBConnection $conn, string $uid, int $albumId)
{
// Check if owner
$query = $conn->getQueryBuilder();
$query->select('album_id')->from('photos_albums')->where(
$query->expr()->andX(
$query->expr()->eq('album_id', $query->createNamedParameter($albumId, IQueryBuilder::PARAM_INT)),
$query->expr()->eq('user', $query->createNamedParameter($uid)),
)
);
if (false !== $query->executeQuery()->fetchOne()) {
return true;
}
// Check in collaborators
$query = $conn->getQueryBuilder();
$query->select('album_id')->from('photos_collaborators')->where(
$query->expr()->andX(
$query->expr()->eq('album_id', $query->createNamedParameter($albumId, IQueryBuilder::PARAM_INT)),
$query->expr()->eq('collaborator_id', $query->createNamedParameter($uid)),
)
);
return false !== $query->executeQuery()->fetchOne();
}
}

View File

@ -15,7 +15,7 @@ trait TimelineQueryDays
/**
* Get the days response from the database for the timeline.
*
* @param Folder $folder The folder to get the days from
* @param null|Folder $folder The folder to get the days from
* @param bool $recursive Whether to get the days recursively
* @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
@ -23,7 +23,7 @@ trait TimelineQueryDays
* @return array The days response
*/
public function getDays(
Folder &$folder,
&$folder,
string $uid,
bool $recursive,
bool $archive,
@ -56,7 +56,7 @@ trait TimelineQueryDays
/**
* Get the day response from the database for the timeline.
*
* @param Folder $folder The folder to get the day from
* @param null|Folder $folder The folder to get the day from
* @param string $uid The user id
* @param int[] $dayid The day id
* @param bool $recursive If the query should be recursive
@ -67,7 +67,7 @@ trait TimelineQueryDays
* @return array An array of day responses
*/
public function getDay(
Folder &$folder,
&$folder,
string $uid,
$day_ids,
bool $recursive,
@ -228,7 +228,7 @@ trait TimelineQueryDays
* Get the query for oc_filecache join.
*
* @param IQueryBuilder $query Query builder
* @param array|Folder $folder Either the top folder or array of folder Ids
* @param null|array|Folder $folder Either the top folder or array of folder Ids
* @param bool $recursive Whether to get the days recursively
* @param bool $archive Whether to get the days only from the archive folder
*/
@ -238,7 +238,14 @@ trait TimelineQueryDays
bool $recursive,
bool $archive
) {
$pathQuery = null;
// Join with memories
$baseOp = $query->expr()->eq('f.fileid', 'm.fileid');
if (null === $folder) {
return $baseOp; // No folder, get all
}
// Filter by folder (recursive or otherwise)
$pathOp = null;
if ($recursive) {
// Get all subfolder Ids recursively
$folderIds = [];
@ -250,15 +257,15 @@ trait TimelineQueryDays
}
// Join with folder IDs
$pathQuery = $query->expr()->in('f.parent', $query->createNamedParameter($folderIds, IQueryBuilder::PARAM_INT_ARRAY));
$pathOp = $query->expr()->in('f.parent', $query->createNamedParameter($folderIds, IQueryBuilder::PARAM_INT_ARRAY));
} else {
// If getting non-recursively folder only check for parent
$pathQuery = $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));
}
return $query->expr()->andX(
$query->expr()->eq('f.fileid', 'm.fileid'),
$pathQuery,
$baseOp,
$pathOp,
);
}
}