memories/lib/Controller/DaysController.php

270 lines
8.6 KiB
PHP
Raw Normal View History

2022-10-29 18:05:05 +00:00
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2022 Varun Patil <radialapps@gmail.com>
* @author Varun Patil <radialapps@gmail.com>
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace OCA\Memories\Controller;
use OCA\Memories\Exceptions;
use OCA\Memories\Util;
2022-10-29 18:05:05 +00:00
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse;
class DaysController extends GenericApiController
2022-10-29 18:05:05 +00:00
{
2022-11-07 04:48:10 +00:00
use FoldersTrait;
2022-10-29 18:05:05 +00:00
/**
* @NoAdminRequired
2022-11-07 04:48:10 +00:00
*
2022-10-29 18:05:05 +00:00
* @PublicPage
*/
public function days(): Http\Response
2022-10-29 18:05:05 +00:00
{
return Util::guardEx(function () {
$uid = $this->getShareToken() ? '' : Util::getUID();
2022-10-29 18:05:05 +00:00
$list = $this->timelineQuery->getDays(
$uid,
2022-11-03 22:39:48 +00:00
$this->isRecursive(),
$this->isArchive(),
2022-10-29 18:05:05 +00:00
$this->getTransformations(true),
);
2022-11-03 22:39:48 +00:00
if ($this->isMonthView()) {
// Group days together into months
$list = $this->timelineQuery->daysToMonths($list);
} else {
// Preload some day responses
$this->preloadDays($list, $uid);
2022-11-03 22:39:48 +00:00
}
2022-10-29 18:05:05 +00:00
2022-11-03 22:44:52 +00:00
// Reverse response if requested. Folders still stay at top.
if ($this->isReverse()) {
$list = array_reverse($list);
}
2022-10-29 18:05:05 +00:00
// Add subfolder info if querying non-recursively
2022-11-03 22:39:48 +00:00
if (!$this->isRecursive()) {
$root = $this->timelineQuery->root();
2022-11-16 07:45:01 +00:00
array_unshift($list, $this->getSubfoldersEntry($root->getFolder($root->getOneId())));
2022-10-29 18:05:05 +00:00
}
return new JSONResponse($list, Http::STATUS_OK);
});
2022-10-29 18:05:05 +00:00
}
/**
* @NoAdminRequired
*
* @PublicPage
*/
public function day(string $id): Http\Response
2022-10-29 18:05:05 +00:00
{
return Util::guardEx(function () use ($id) {
$uid = $this->getShareToken() ? '' : Util::getUID();
2022-10-29 18:05:05 +00:00
// Check for wildcard
$dayIds = [];
if ('*' === $id) {
$dayIds = null;
} else {
// Split at commas and convert all parts to int
$dayIds = array_map(fn ($p) => (int) $p, explode(',', $id));
}
2022-10-29 18:05:05 +00:00
// Check if $dayIds is empty
if (null !== $dayIds && 0 === \count($dayIds)) {
return new JSONResponse([], Http::STATUS_OK);
}
2022-10-29 18:05:05 +00:00
// Convert to actual dayIds if month view
if ($this->isMonthView()) {
$dayIds = $this->timelineQuery->monthIdToDayIds((int) $dayIds[0]);
}
2022-10-29 18:05:05 +00:00
// Run actual query
2022-10-29 18:05:05 +00:00
$list = $this->timelineQuery->getDay(
$uid,
2022-11-03 22:39:48 +00:00
$dayIds,
$this->isRecursive(),
$this->isArchive(),
2022-10-29 18:05:05 +00:00
$this->getTransformations(false),
);
2022-11-03 22:39:48 +00:00
// Force month id for dayId for month view
if ($this->isMonthView()) {
foreach ($list as &$photo) {
$photo['dayid'] = (int) $dayIds[0];
}
}
2022-11-03 22:44:52 +00:00
// Reverse response if requested.
if ($this->isReverse()) {
$list = array_reverse($list);
}
2022-10-29 18:05:05 +00:00
return new JSONResponse($list, Http::STATUS_OK);
});
2022-10-29 18:05:05 +00:00
}
2022-10-29 18:09:38 +00:00
/**
* @NoAdminRequired
*
* @PublicPage
*/
public function dayPost(): Http\Response
2022-10-29 18:09:38 +00:00
{
return Util::guardEx(function () {
$id = $this->request->getParam('body_ids');
if (null === $id) {
throw Exceptions::MissingParameter('body_ids');
}
2022-10-29 18:09:38 +00:00
return $this->day($id);
});
2022-10-29 18:09:38 +00:00
}
2023-02-08 21:53:38 +00:00
/**
* Get transformations depending on the request.
*
* @param bool $aggregateOnly Only apply transformations for aggregation (days call)
*/
private function getTransformations(bool $aggregateOnly)
{
$transforms = [];
// Filter for one album
if (($albumId = $this->request->getParam('album')) && Util::albumsIsEnabled()) {
$transforms[] = [$this->timelineQuery, 'transformAlbumFilter', $albumId];
2023-02-08 21:53:38 +00:00
}
// Other transforms not allowed for public shares
if (null === $this->userSession->getUser()) {
return $transforms;
}
// Filter only favorites
if ($this->request->getParam('fav')) {
$transforms[] = [$this->timelineQuery, 'transformFavoriteFilter'];
}
// Filter only videos
if ($this->request->getParam('vid')) {
$transforms[] = [$this->timelineQuery, 'transformVideoFilter'];
}
// Filter only for one face on Recognize
if (($recognize = $this->request->getParam('recognize')) && Util::recognizeIsEnabled()) {
$transforms[] = [$this->timelineQuery, 'transformPeopleRecognitionFilter', $recognize, $aggregateOnly];
2023-02-08 21:53:38 +00:00
$faceRect = $this->request->getParam('facerect');
if ($faceRect && !$aggregateOnly) {
$transforms[] = [$this->timelineQuery, 'transformPeopleRecognizeRect', $recognize];
}
}
// Filter only for one face on Face Recognition
if (($face = $this->request->getParam('facerecognition')) && Util::facerecognitionIsEnabled()) {
2023-02-08 21:53:38 +00:00
$currentModel = (int) $this->config->getAppValue('facerecognition', 'model', -1);
$transforms[] = [$this->timelineQuery, 'transformPeopleFaceRecognitionFilter', $currentModel, $face];
$faceRect = $this->request->getParam('facerect');
if ($faceRect && !$aggregateOnly) {
$transforms[] = [$this->timelineQuery, 'transformPeopleFaceRecognitionRect', $face];
}
}
// Filter only for one tag
if (($tagName = $this->request->getParam('tag')) && Util::tagsIsEnabled()) {
$transforms[] = [$this->timelineQuery, 'transformTagFilter', $tagName];
2023-02-08 21:53:38 +00:00
}
// Filter only for one place
if (($locationId = $this->request->getParam('place')) && Util::placesGISType() > 0) {
$transforms[] = [$this->timelineQuery, 'transformPlaceFilter', (int) $locationId];
2023-02-08 21:53:38 +00:00
}
// Filter geological bounds
$bounds = $this->request->getParam('mapbounds');
if ($bounds) {
$transforms[] = [$this->timelineQuery, 'transformMapBoundsFilter', $bounds];
}
// Limit number of responses for day query
$limit = $this->request->getParam('limit');
if ($limit) {
$transforms[] = [$this->timelineQuery, 'transformLimitDay', (int) $limit];
}
return $transforms;
}
2022-10-29 18:05:05 +00:00
/**
* Preload a few "day" at the start of "days" response.
*
* @param array $days the days array
* @param string $uid User ID or blank for public shares
2022-10-29 18:05:05 +00:00
*/
private function preloadDays(array &$days, string $uid)
2022-10-29 18:05:05 +00:00
{
$transforms = $this->getTransformations(false);
$preloaded = 0;
$preloadDayIds = [];
$preloadDays = [];
foreach ($days as &$day) {
if ($day['count'] <= 0) {
continue;
}
$preloaded += $day['count'];
$preloadDayIds[] = $day['dayid'];
$preloadDays[] = &$day;
if ($preloaded >= 50 || \count($preloadDayIds) > 5) { // should be enough
break;
}
}
if (\count($preloadDayIds) > 0) {
$allDetails = $this->timelineQuery->getDay(
$uid,
$preloadDayIds,
2022-11-03 22:39:48 +00:00
$this->isRecursive(),
$this->isArchive(),
2022-10-29 18:05:05 +00:00
$transforms,
);
// Group into dayid
$detailMap = [];
foreach ($allDetails as &$detail) {
$detailMap[$detail['dayid']][] = &$detail;
}
foreach ($preloadDays as &$day) {
$m = $detailMap[$day['dayid']];
if (isset($m) && null !== $m && \count($m) > 0) {
$day['detail'] = $m;
}
}
}
}
}