Add get tags API

cache
Varun Patil 2022-10-06 14:37:18 -07:00
parent 90ccce5477
commit 994320f78e
5 changed files with 90 additions and 22 deletions

View File

@ -20,6 +20,7 @@ return [
['name' => 'api#days', 'url' => '/api/days', 'verb' => 'GET'], ['name' => 'api#days', 'url' => '/api/days', 'verb' => 'GET'],
['name' => 'api#dayPost', 'url' => '/api/days', 'verb' => 'POST'], ['name' => 'api#dayPost', 'url' => '/api/days', 'verb' => 'POST'],
['name' => 'api#day', 'url' => '/api/days/{id}', 'verb' => 'GET'], ['name' => 'api#day', 'url' => '/api/days/{id}', 'verb' => 'GET'],
['name' => 'api#tags', 'url' => '/api/tags', 'verb' => 'GET'],
['name' => 'api#imageInfo', 'url' => '/api/info/{id}', 'verb' => 'GET'], ['name' => 'api#imageInfo', 'url' => '/api/info/{id}', 'verb' => 'GET'],
['name' => 'api#imageEdit', 'url' => '/api/edit/{id}', 'verb' => 'PATCH'], ['name' => 'api#imageEdit', 'url' => '/api/edit/{id}', 'verb' => 'PATCH'],
['name' => 'api#archive', 'url' => '/api/archive/{id}', 'verb' => 'PATCH'], ['name' => 'api#archive', 'url' => '/api/archive/{id}', 'verb' => 'PATCH'],

View File

@ -261,6 +261,31 @@ class ApiController extends Controller {
]; ];
} }
/**
* @NoAdminRequired
*
* Get list of tags with counts of images
* @return JSONResponse
*/
public function tags(): JSONResponse {
$user = $this->userSession->getUser();
if (is_null($user)) {
return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED);
}
// If this isn't the timeline folder then things aren't going to work
$folder = $this->getRequestFolder();
if (is_null($folder)) {
return new JSONResponse([], Http::STATUS_NOT_FOUND);
}
// Run actual query
$list = $this->timelineQuery->getTags(
$folder,
);
return new JSONResponse($list, Http::STATUS_OK);
}
/** /**
* @NoAdminRequired * @NoAdminRequired
* *

View File

@ -8,6 +8,7 @@ use OCP\IDBConnection;
class TimelineQuery { class TimelineQuery {
use TimelineQueryDays; use TimelineQueryDays;
use TimelineQueryFilters; use TimelineQueryFilters;
use TimelineQueryTags;
protected IDBConnection $connection; protected IDBConnection $connection;

View File

@ -44,26 +44,4 @@ trait TimelineQueryFilters {
public function transformVideoFilter(IQueryBuilder &$query, string $userId) { public function transformVideoFilter(IQueryBuilder &$query, string $userId) {
$query->andWhere($query->expr()->eq('m.isvideo', $query->createNamedParameter('1'))); $query->andWhere($query->expr()->eq('m.isvideo', $query->createNamedParameter('1')));
} }
public function getSystemTagId(IQueryBuilder &$query, string $tagName) {
$sqb = $query->getConnection()->getQueryBuilder();
return $sqb->select('id')->from('systemtag')->where(
$sqb->expr()->andX(
$sqb->expr()->eq('name', $sqb->createNamedParameter($tagName)),
$sqb->expr()->eq('visibility', $sqb->createNamedParameter(1)),
))->executeQuery()->fetchOne();
}
public function transformTagFilter(IQueryBuilder &$query, string $userId, string $tagName) {
$tagId = $this->getSystemTagId($query, $tagName);
if ($tagId === FALSE) {
$tagId = 0; // cannot abort here; that will show up everything in the response
}
$query->innerJoin('m', 'systemtag_object_mapping', 'stom', $query->expr()->andX(
$query->expr()->eq('stom.objecttype', $query->createNamedParameter("files")),
$query->expr()->eq('stom.objectid', 'm.fileid'),
$query->expr()->eq('stom.systemtagid', $query->createNamedParameter($tagId)),
));
}
} }

View File

@ -0,0 +1,63 @@
<?php
declare(strict_types=1);
namespace OCA\Memories\Db;
use OCP\IDBConnection;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\Folder;
trait TimelineQueryTags {
protected IDBConnection $connection;
public function getSystemTagId(IQueryBuilder &$query, string $tagName) {
$sqb = $query->getConnection()->getQueryBuilder();
return $sqb->select('id')->from('systemtag')->where(
$sqb->expr()->andX(
$sqb->expr()->eq('name', $sqb->createNamedParameter($tagName)),
$sqb->expr()->eq('visibility', $sqb->createNamedParameter(1)),
))->executeQuery()->fetchOne();
}
public function transformTagFilter(IQueryBuilder &$query, string $userId, string $tagName) {
$tagId = $this->getSystemTagId($query, $tagName);
if ($tagId === FALSE) {
$tagId = 0; // cannot abort here; that will show up everything in the response
}
$query->innerJoin('m', 'systemtag_object_mapping', 'stom', $query->expr()->andX(
$query->expr()->eq('stom.objecttype', $query->createNamedParameter("files")),
$query->expr()->eq('stom.objectid', 'm.fileid'),
$query->expr()->eq('stom.systemtagid', $query->createNamedParameter($tagId)),
));
}
public function getTags(Folder $folder) {
$query = $this->connection->getQueryBuilder();
// SELECT visible tag name and count of photos
$count = $query->func()->count($query->createFunction('DISTINCT m.fileid'), 'count');
$query->select('st.name', $count)->from('systemtag', 'st')->where(
$query->expr()->eq('visibility', $query->createNamedParameter(1)),
);
// WHERE there are items with this tag
$query->innerJoin('st', 'systemtag_object_mapping', 'stom', $query->expr()->andX(
$query->expr()->eq('stom.systemtagid', 'st.id'),
$query->expr()->eq('stom.objecttype', $query->createNamedParameter("files")),
));
// WHERE these items are memories indexed photos
$query->innerJoin('stom', 'memories', 'm', $query->expr()->eq('m.fileid', 'stom.objectid'));
// WHERE these photos are in the user's requested folder recursively
$query->innerJoin('m', 'filecache', 'f', $this->getFilecacheJoinQuery($query, $folder, true, false));
// GROUP by tag name
$query->groupBy('st.name');
// FETCH all tags
$tags = $query->executeQuery()->fetchAll();
return $tags;
}
}