Exclude mounts in nomedia
Signed-off-by: Varun Patil <varunpatil@ucla.edu>pull/579/head
parent
8ec21747f3
commit
3ada3d6510
|
@ -23,12 +23,17 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCA\Memories\Db;
|
namespace OCA\Memories\Db;
|
||||||
|
|
||||||
|
use OC\Files\Search\SearchComparison;
|
||||||
|
use OC\Files\Search\SearchQuery;
|
||||||
use OCA\Memories\Exceptions;
|
use OCA\Memories\Exceptions;
|
||||||
use OCA\Memories\Exif;
|
use OCA\Memories\Exif;
|
||||||
use OCA\Memories\Util;
|
use OCA\Memories\Util;
|
||||||
use OCP\Files\File;
|
use OCP\Files\File;
|
||||||
use OCP\Files\Folder;
|
use OCP\Files\Folder;
|
||||||
use OCP\Files\IRootFolder;
|
use OCP\Files\IRootFolder;
|
||||||
|
use OCP\Files\Search\ISearchComparison;
|
||||||
|
use OCP\ICache;
|
||||||
|
use OCP\ICacheFactory;
|
||||||
use OCP\IConfig;
|
use OCP\IConfig;
|
||||||
use OCP\IRequest;
|
use OCP\IRequest;
|
||||||
use OCP\IUserManager;
|
use OCP\IUserManager;
|
||||||
|
@ -42,19 +47,22 @@ class FsManager
|
||||||
protected IRootFolder $rootFolder;
|
protected IRootFolder $rootFolder;
|
||||||
protected AlbumsQuery $albumsQuery;
|
protected AlbumsQuery $albumsQuery;
|
||||||
protected IRequest $request;
|
protected IRequest $request;
|
||||||
|
protected ICache $nomediaCache;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
IConfig $config,
|
IConfig $config,
|
||||||
IUserSession $userSession,
|
IUserSession $userSession,
|
||||||
IRootFolder $rootFolder,
|
IRootFolder $rootFolder,
|
||||||
AlbumsQuery $albumsQuery,
|
AlbumsQuery $albumsQuery,
|
||||||
IRequest $request
|
IRequest $request,
|
||||||
|
ICacheFactory $cacheFactory
|
||||||
) {
|
) {
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
$this->userSession = $userSession;
|
$this->userSession = $userSession;
|
||||||
$this->rootFolder = $rootFolder;
|
$this->rootFolder = $rootFolder;
|
||||||
$this->albumsQuery = $albumsQuery;
|
$this->albumsQuery = $albumsQuery;
|
||||||
$this->request = $request;
|
$this->request = $request;
|
||||||
|
$this->nomediaCache = $cacheFactory->createLocal('memories:nomedia');
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the TimelineRoot object relevant to the request */
|
/** Get the TimelineRoot object relevant to the request */
|
||||||
|
@ -98,16 +106,30 @@ class FsManager
|
||||||
$folder = $userFolder->get(Exif::removeExtraSlash($folderPath));
|
$folder = $userFolder->get(Exif::removeExtraSlash($folderPath));
|
||||||
$root->addFolder($folder);
|
$root->addFolder($folder);
|
||||||
} else {
|
} else {
|
||||||
|
// Get timeline paths
|
||||||
$paths = Exif::getTimelinePaths($uid);
|
$paths = Exif::getTimelinePaths($uid);
|
||||||
if ($path = $this->request->getParam('timelinePath', null)) {
|
if ($path = $this->request->getParam('timelinePath', null)) {
|
||||||
$paths = [Exif::removeExtraSlash($path)];
|
$paths = [Exif::removeExtraSlash($path)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Combined etag, for cache invalidation.
|
||||||
|
// This is cheaper and more sensible than the root etag.
|
||||||
|
// The only time this breaks down is if the user places a .nomedia
|
||||||
|
// outside the timeline path; rely on expiration for that.
|
||||||
|
$cEtag = $uid;
|
||||||
|
|
||||||
// Multiple timeline path support
|
// Multiple timeline path support
|
||||||
foreach ($paths as $path) {
|
foreach ($paths as $path) {
|
||||||
$root->addFolder($userFolder->get($path));
|
$node = $userFolder->get($path);
|
||||||
|
$root->addFolder($node);
|
||||||
|
$cEtag .= $node->getEtag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add shares or external stores inside the current folders
|
||||||
$root->addMountPoints();
|
$root->addMountPoints();
|
||||||
|
|
||||||
|
// Exclude .nomedia folders
|
||||||
|
$root->excludePaths($this->getNoMediaFolders($userFolder, md5($cEtag)));
|
||||||
}
|
}
|
||||||
} catch (\OCP\Files\NotFoundException $e) {
|
} catch (\OCP\Files\NotFoundException $e) {
|
||||||
$msg = $e->getMessage();
|
$msg = $e->getMessage();
|
||||||
|
@ -118,6 +140,27 @@ class FsManager
|
||||||
return $root;
|
return $root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of folders with .nomedia file.
|
||||||
|
*
|
||||||
|
* @param Folder $root root folder
|
||||||
|
* @param string $key etag for cache key
|
||||||
|
*/
|
||||||
|
public function getNoMediaFolders(Folder $root, string $key): array
|
||||||
|
{
|
||||||
|
if (null !== ($paths = $this->nomediaCache->get($key))) {
|
||||||
|
return $paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
$comp = new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'name', '.nomedia');
|
||||||
|
$search = $root->search(new SearchQuery($comp, 0, 0, [], Util::getUser()));
|
||||||
|
|
||||||
|
$paths = array_map(fn (File $node) => \dirname($node->getPath()), $search);
|
||||||
|
$this->nomediaCache->set($key, $paths, 60 * 60); // 1 hour
|
||||||
|
|
||||||
|
return $paths;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a file with ID for the current user.
|
* Get a file with ID for the current user.
|
||||||
*
|
*
|
||||||
|
|
|
@ -154,6 +154,11 @@ trait TimelineQueryDays
|
||||||
$root = $this->root();
|
$root = $this->root();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Never join against an empty root
|
||||||
|
if (!$root || $root->isEmpty()) {
|
||||||
|
throw new \InvalidArgumentException('Timeline root is empty');
|
||||||
|
}
|
||||||
|
|
||||||
// Join with memories
|
// Join with memories
|
||||||
$baseOp = $query->expr()->eq('f.fileid', 'm.fileid');
|
$baseOp = $query->expr()->eq('f.fileid', 'm.fileid');
|
||||||
if ($root->isEmpty()) {
|
if ($root->isEmpty()) {
|
||||||
|
|
|
@ -14,6 +14,8 @@ class TimelineRoot
|
||||||
/** Initialize */
|
/** Initialize */
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
$this->folders = [];
|
||||||
|
$this->folderPaths = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,35 +33,42 @@ class TimelineRoot
|
||||||
*/
|
*/
|
||||||
public function addFolder(FileInfo $info)
|
public function addFolder(FileInfo $info)
|
||||||
{
|
{
|
||||||
$folderPath = $info->getPath();
|
$path = $info->getPath();
|
||||||
|
|
||||||
if (FileInfo::MIMETYPE_FOLDER !== $info->getMimetype()) {
|
if (FileInfo::MIMETYPE_FOLDER !== $info->getMimetype()) {
|
||||||
throw new \Exception("Not a folder: {$folderPath}");
|
throw new \Exception("Not a folder: {$path}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$info->isReadable()) {
|
if (!$info->isReadable()) {
|
||||||
throw new \Exception("Folder not readable: {$folderPath}");
|
throw new \Exception("Folder not readable: {$path}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add top level folder
|
// Add top level folder
|
||||||
$id = $info->getId();
|
$this->setFolder($info->getId(), $info, $path);
|
||||||
$this->folders[$id] = $info;
|
|
||||||
$this->folderPaths[$id] = $folderPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add mountpoints recursively
|
// Add mountpoints recursively
|
||||||
public function addMountPoints()
|
public function addMountPoints()
|
||||||
{
|
{
|
||||||
$mp = [];
|
$folders = [];
|
||||||
foreach ($this->folderPaths as $id => $folderPath) {
|
foreach ($this->folderPaths as $id => $folderPath) {
|
||||||
$mounts = \OC\Files\Filesystem::getMountManager()->findIn($folderPath);
|
$mounts = \OC\Files\Filesystem::getMountManager()->findIn($folderPath);
|
||||||
foreach ($mounts as &$mount) {
|
foreach ($mounts as $mount) {
|
||||||
$id = $mount->getStorageRootId();
|
$this->setFolder($mount->getStorageRootId(), null, $mount->getMountPoint());
|
||||||
$path = $mount->getMountPoint();
|
}
|
||||||
$mp[$id] = $path;
|
}
|
||||||
|
$this->folderPaths += $folders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function excludePaths(array $paths)
|
||||||
|
{
|
||||||
|
foreach ($paths as $path) {
|
||||||
|
foreach ($this->folderPaths as $id => $folderPath) {
|
||||||
|
if (str_starts_with($folderPath, $path)) {
|
||||||
|
unset($this->folderPaths[$id], $this->folders[$id]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->folderPaths += $mp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFolderPath(int $id)
|
public function getFolderPath(int $id)
|
||||||
|
@ -86,4 +95,15 @@ class TimelineRoot
|
||||||
{
|
{
|
||||||
return empty($this->folderPaths);
|
return empty($this->folderPaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function setFolder(int $id, ?FileInfo $fileInfo, ?string $path)
|
||||||
|
{
|
||||||
|
if (null !== $path) {
|
||||||
|
$this->folderPaths[$id] = $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $fileInfo) {
|
||||||
|
$this->folders[$id] = $fileInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue