Add Albums view

Signed-off-by: Louis Chemineau <louis@chmn.me>
This commit is contained in:
Louis Chemineau 2022-07-27 11:47:27 +02:00
parent 0f2bcdaab7
commit c8bf3a52d6
139 changed files with 4746 additions and 1236 deletions

View File

@ -38,6 +38,14 @@ return [
'path' => '',
]
],
['name' => 'page#index', 'url' => '/folders/{path}', 'verb' => 'GET', 'postfix' => 'folders',
'requirements' => [
'path' => '.*',
],
'defaults' => [
'path' => '',
]
],
['name' => 'page#index', 'url' => '/shared/{path}', 'verb' => 'GET', 'postfix' => 'shared',
'requirements' => [
'path' => '.*',

View File

@ -17,6 +17,11 @@
"require-dev": {
"nextcloud/coding-standard": "^0.5.0",
"phpunit/phpunit": "^9",
"vimeo/psalm": "^4.22"
"vimeo/psalm": "^4.22",
"christophwurst/nextcloud": "dev-master",
"sabre/dav": "^4.2.1"
},
"require": {
"doctrine/dbal": "^3.4"
}
}

1168
composer.lock generated

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -33,7 +33,7 @@ class AlbumFile {
private int $mtime;
private string $etag;
private int $added;
/** @var array<int, FileMetadata> */
/** @var array<string, FileMetadata> */
private array $metaData = [];
public function __construct(
@ -74,7 +74,7 @@ class AlbumFile {
return $this->mtime;
}
public function getEtag() {
public function getEtag(): string {
return $this->etag;
}

View File

@ -48,7 +48,7 @@ class AlbumWithFiles {
* @return int[]
*/
public function getFileIds(): array {
return array_map(function(AlbumFile $file) {
return array_map(function (AlbumFile $file) {
return $file->getFileId();
}, $this->files);
}

View File

@ -24,5 +24,4 @@ declare(strict_types=1);
namespace OCA\Photos\Exception;
class AlreadyInAlbumException extends \Exception {
}

View File

@ -25,7 +25,6 @@ namespace OCA\Photos\Migration;
use Closure;
use Doctrine\DBAL\Types\Types;
use OC\DB\SchemaWrapper;
use OCP\DB\ISchemaWrapper;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;
@ -35,7 +34,7 @@ use OCP\Migration\SimpleMigrationStep;
*/
class Version20000Date20220727125801 extends SimpleMigrationStep {
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
/** @var SchemaWrapper $schema */
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
if (!$schema->hasTable("photos_albums")) {

View File

@ -39,6 +39,8 @@ class AlbumPhoto implements IFile {
private AlbumFile $file;
private Folder $userFolder;
public const TAG_FAVORITE = '_$!<Favorite>!$_';
public function __construct(AlbumMapper $albumMapper, AlbumInfo $album, AlbumFile $file, Folder $userFolder) {
$this->albumMapper = $albumMapper;
$this->album = $album;
@ -46,6 +48,9 @@ class AlbumPhoto implements IFile {
$this->userFolder = $userFolder;
}
/**
* @return void
*/
public function delete() {
$this->albumMapper->removeFile($this->album->getId(), $this->file->getFileId());
}
@ -54,6 +59,9 @@ class AlbumPhoto implements IFile {
return $this->file->getFileId() . "-" . $this->file->getName();
}
/**
* @return never
*/
public function setName($name) {
throw new Forbidden('Can\'t rename photos trough the album api');
}
@ -81,6 +89,20 @@ class AlbumPhoto implements IFile {
}
}
public function getFileId(): int {
return $this->file->getFileId();
}
public function getFileInfo(): Node {
$nodes = $this->userFolder->getById($this->file->getFileId());
$node = current($nodes);
if ($node) {
return $node;
} else {
throw new NotFoundException("Photo not found for user");
}
}
public function getContentType() {
return $this->file->getMimeType();
}
@ -96,4 +118,16 @@ class AlbumPhoto implements IFile {
public function getFile(): AlbumFile {
return $this->file;
}
public function isFavorite(): bool {
$tagManager = \OCP\Server::get(\OCP\ITagManager::class);
$tagger = $tagManager->load('files');
$tags = $tagger->getTagsForObjects([$this->getFileId()]);
if ($tags === false || empty($tags)) {
return false;
}
return array_search(self::TAG_FAVORITE, current($tags)) !== false;
}
}

View File

@ -52,6 +52,9 @@ class AlbumRoot implements ICollection, ICopyTarget {
$this->user = $user;
}
/**
* @return void
*/
public function delete() {
$this->albumMapper->delete($this->album->getAlbum()->getId());
}
@ -60,6 +63,9 @@ class AlbumRoot implements ICollection, ICopyTarget {
return basename($this->album->getAlbum()->getTitle());
}
/**
* @return void
*/
public function setName($name) {
$this->albumMapper->rename($this->album->getAlbum()->getId(), $name);
}
@ -68,6 +74,9 @@ class AlbumRoot implements ICollection, ICopyTarget {
throw new Forbidden('Not allowed to create files in this folder, copy files into this folder instead');
}
/**
* @return never
*/
public function createDirectory($name) {
throw new Forbidden('Not allowed to create directories in this folder');
}
@ -118,4 +127,35 @@ class AlbumRoot implements ICollection, ICopyTarget {
public function getAlbum(): AlbumWithFiles {
return $this->album;
}
public function getDateRange(): array {
$earliestDate = null;
$latestDate = null;
foreach ($this->getChildren() as $child) {
$childCreationDate = $child->getFileInfo()->getMtime();
if ($childCreationDate < $earliestDate || $earliestDate === null) {
$earliestDate = $childCreationDate;
}
if ($childCreationDate > $earliestDate || $latestDate === null) {
$latestDate = $childCreationDate;
}
}
return ['start' => $earliestDate, 'end' => $latestDate];
}
/**
* @return int|null
*/
public function getCover() {
$children = $this->getChildren();
if (count($children) > 0) {
return $children[0]->getFileId();
} else {
return null;
}
}
}

View File

@ -39,6 +39,11 @@ class AlbumsHome implements ICollection {
private IRootFolder $rootFolder;
private Folder $userFolder;
/**
* @var AlbumRoot[]
*/
private ?array $children = null;
public function __construct(
array $principalInfo,
AlbumMapper $albumMapper,
@ -52,6 +57,9 @@ class AlbumsHome implements ICollection {
$this->userFolder = $rootFolder->getUserFolder($user->getUID());
}
/**
* @return never
*/
public function delete() {
throw new Forbidden();
}
@ -60,6 +68,9 @@ class AlbumsHome implements ICollection {
return 'albums';
}
/**
* @return never
*/
public function setName($name) {
throw new Forbidden('Permission denied to rename this folder');
}
@ -68,6 +79,9 @@ class AlbumsHome implements ICollection {
throw new Forbidden('Not allowed to create files in this folder');
}
/**
* @return void
*/
public function createDirectory($name) {
$uid = $this->user->getUID();
$this->albumMapper->create($uid, $name);
@ -87,10 +101,14 @@ class AlbumsHome implements ICollection {
* @return AlbumRoot[]
*/
public function getChildren(): array {
$folders = $this->albumMapper->getForUserWithFiles($this->user->getUID());
return array_map(function (AlbumWithFiles $folder) {
return new AlbumRoot($this->albumMapper, $folder, $this->rootFolder, $this->userFolder, $this->user);
}, $folders);
if ($this->children === null) {
$folders = $this->albumMapper->getForUserWithFiles($this->user->getUID());
$this->children = array_map(function (AlbumWithFiles $folder) {
return new AlbumRoot($this->albumMapper, $folder, $this->rootFolder, $this->userFolder, $this->user);
}, $folders);
}
return $this->children;
}
public function childExists($name): bool {

Some files were not shown because too many files have changed in this diff Show More