Skip to content

Commit

Permalink
Add DAV endpoint for location grouping
Browse files Browse the repository at this point in the history
Signed-off-by: Louis Chemineau <louis@chmn.me>
  • Loading branch information
artonge committed Feb 22, 2023
1 parent 4ed1fc1 commit 43a965d
Show file tree
Hide file tree
Showing 10 changed files with 540 additions and 142 deletions.
2 changes: 1 addition & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<collection>OCA\Photos\Sabre\PublicRootCollection</collection>
</collections>
<plugins>
<plugin>OCA\Photos\Sabre\Album\PropFindPlugin</plugin>
<plugin>OCA\Photos\Sabre\PropFindPlugin</plugin>
</plugins>
</sabre>

Expand Down
103 changes: 11 additions & 92 deletions lib/Sabre/Album/AlbumPhoto.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,24 @@
use OCA\Photos\Album\AlbumFile;
use OCA\Photos\Album\AlbumInfo;
use OCA\Photos\Album\AlbumMapper;
use OCA\Photos\Sabre\CollectionPhoto;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\NotFoundException;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\IFile;

class AlbumPhoto implements IFile {
private AlbumMapper $albumMapper;
private AlbumInfo $album;
private AlbumFile $albumFile;
private IRootFolder $rootFolder;
class AlbumPhoto extends CollectionPhoto implements IFile {

public const TAG_FAVORITE = '_$!<Favorite>!$_';

public function __construct(AlbumMapper $albumMapper, AlbumInfo $album, AlbumFile $albumFile, IRootFolder $rootFolder) {
$this->albumMapper = $albumMapper;
$this->album = $album;
$this->albumFile = $albumFile;
$this->rootFolder = $rootFolder;
public function __construct(
private AlbumMapper $albumMapper,
private AlbumInfo $album,
private AlbumFile $albumFile,
private IRootFolder $rootFolder,
Folder $userFolder,
) {
parent::__construct($albumFile, $userFolder);
}

/**
Expand All @@ -55,36 +53,6 @@ public function delete() {
$this->albumMapper->removeFile($this->album->getId(), $this->albumFile->getFileId());
}

public function getName() {
return $this->albumFile->getFileId() . "-" . $this->albumFile->getName();
}

/**
* @return never
*/
public function setName($name) {
throw new Forbidden('Can\'t rename photos trough the album api');
}

public function getLastModified() {
return $this->albumFile->getMTime();
}

public function put($data) {
$nodes = $this->userFolder->getById($this->file->getFileId());
$node = current($nodes);
if ($node) {
/** @var Node $node */
if ($node instanceof File) {
return $node->putContent($data);
} else {
throw new NotFoundException("Photo is a folder");
}
} else {
throw new NotFoundException("Photo not found for user");
}
}

public function get() {
$nodes = $this->rootFolder
->getUserFolder($this->albumFile->getOwner() ?: $this->album->getUserId())
Expand All @@ -102,10 +70,6 @@ public function get() {
}
}

public function getFileId(): int {
return $this->albumFile->getFileId();
}

public function getFileInfo(): Node {
$nodes = $this->rootFolder
->getUserFolder($this->albumFile->getOwner() ?: $this->album->getUserId())
Expand All @@ -117,49 +81,4 @@ public function getFileInfo(): Node {
throw new NotFoundException("Photo not found for user");
}
}

public function getContentType() {
return $this->albumFile->getMimeType();
}

public function getETag() {
return $this->albumFile->getEtag();
}

public function getSize() {
return $this->albumFile->getSize();
}

public function getFile(): AlbumFile {
return $this->albumFile;
}

public function isFavorite(): bool {
$tagManager = \OCP\Server::get(\OCP\ITagManager::class);
$tagger = $tagManager->load('files');
if ($tagger === null) {
return false;
}
$tags = $tagger->getTagsForObjects([$this->getFileId()]);

if ($tags === false || empty($tags)) {
return false;
}

return array_search(self::TAG_FAVORITE, current($tags)) !== false;
}

public function setFavoriteState($favoriteState): bool {
$tagManager = \OCP\Server::get(\OCP\ITagManager::class);
$tagger = $tagManager->load('files');

switch ($favoriteState) {
case "0":
return $tagger->removeFromFavorites($this->albumFile->getFileId());
case "1":
return $tagger->addToFavorites($this->albumFile->getFileId());
default:
new \Exception('Favorite state is invalide, should be 0 or 1.');
}
}
}
4 changes: 2 additions & 2 deletions lib/Sabre/Album/AlbumRoot.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,14 @@ public function createDirectory($name) {

public function getChildren(): array {
return array_map(function (AlbumFile $file) {
return new AlbumPhoto($this->albumMapper, $this->album->getAlbum(), $file, $this->rootFolder);
return new AlbumPhoto($this->albumMapper, $this->album->getAlbum(), $file, $this->rootFolder, $this->rootFolder->getUserFolder($this->userId));
}, $this->album->getFiles());
}

public function getChild($name): AlbumPhoto {
foreach ($this->album->getFiles() as $file) {
if ($file->getFileId() . "-" . $file->getName() === $name) {
return new AlbumPhoto($this->albumMapper, $this->album->getAlbum(), $file, $this->rootFolder);
return new AlbumPhoto($this->albumMapper, $this->album->getAlbum(), $file, $this->rootFolder, $this->rootFolder->getUserFolder($this->userId));
}
}
throw new NotFound("$name not found");
Expand Down
119 changes: 119 additions & 0 deletions lib/Sabre/CollectionPhoto.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<?php

declare(strict_types=1);
/**
* @copyright Copyright (c) 2022 Robin Appelman <robin@icewind.nl>
*
* @license GNU AGPL version 3 or any later version
*
* 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\Photos\Sabre;

use OCA\Photos\DB\PhotosFile;
use OCP\Files\Node;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\NotFoundException;
use OCP\ITags;
use Sabre\DAV\Exception\Forbidden;

class CollectionPhoto {
public function __construct(
protected PhotosFile $file,
protected Folder $userFolder,
) {
}

public function getName() {
return $this->file->getFileId() . "-" . $this->file->getName();
}

/**
* @return never
*/
public function setName($name) {
throw new Forbidden('Can\'t rename photos trough this api');
}

public function getLastModified() {
return $this->file->getMTime();
}

public function put($data) {
$nodes = $this->userFolder->getById($this->file->getFileId());
$node = current($nodes);
if ($node) {
/** @var Node $node */
if ($node instanceof File) {
return $node->putContent($data);
} else {
throw new NotFoundException("Photo is a folder");
}
} else {
throw new NotFoundException("Photo not found for user");
}
}

public function getFileId(): int {
return $this->file->getFileId();
}

public function getContentType() {
return $this->file->getMimeType();
}

public function getETag() {
return $this->file->getEtag();
}

public function getSize() {
return $this->file->getSize();
}

public function getFile(): PhotosFile {
return $this->file;
}

public function isFavorite(): bool {
$tagManager = \OCP\Server::get(\OCP\ITagManager::class);
$tagger = $tagManager->load('files');
if ($tagger === null) {
return false;
}
$tags = $tagger->getTagsForObjects([$this->getFileId()]);

if ($tags === false || empty($tags)) {
return false;
}

return array_search(ITags::TAG_FAVORITE, current($tags)) !== false;
}

public function setFavoriteState($favoriteState): bool {
$tagManager = \OCP\Server::get(\OCP\ITagManager::class);
$tagger = $tagManager->load('files');

switch ($favoriteState) {
case "0":
return $tagger->removeFromFavorites($this->file->getFileId());
case "1":
return $tagger->addToFavorites($this->file->getFileId());
default:
new \Exception('Favorite state is invalide, should be 0 or 1.');
}
}
}
84 changes: 84 additions & 0 deletions lib/Sabre/Location/LocationPhoto.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

declare(strict_types=1);
/**
* @copyright Copyright (c) 2022 Louis Chemineau <louis@chmn.me>
*
* @author Louis Chemineau <louis@chmn.me>
*
* @license GNU AGPL version 3 or any later version
*
* 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\Photos\Sabre\Location;

use OCA\Photos\DB\Location\LocationFile;
use OCA\Photos\DB\Location\LocationInfo;
use OCA\Photos\Sabre\CollectionPhoto;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\NotFoundException;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\IFile;

class LocationPhoto extends CollectionPhoto implements IFile {
public function __construct(
private LocationInfo $locationInfo,
LocationFile $file,
private IRootFolder $rootFolder,
Folder $userFolder
) {
parent::__construct($file, $userFolder);
}

/**
* @return void
*/
public function delete() {
throw new Forbidden('Cannot remove from a location');
}

public function get() {
$nodes = $this->rootFolder
->getUserFolder($this->locationInfo->getUserId())
->getById($this->file->getFileId());
$node = current($nodes);
if ($node) {
/** @var Node $node */
if ($node instanceof File) {
return $node->fopen('r');
} else {
throw new NotFoundException("Photo is a folder");
}
} else {
throw new NotFoundException("Photo not found for user");
}
}

public function getFileInfo(): Node {
$nodes = $this->rootFolder
->getUserFolder($this->locationInfo->getUserId())
->getById($this->file->getFileId());
$node = current($nodes);
if ($node) {
return $node;
} else {
throw new NotFoundException("Photo not found for user");
}
}
}
Loading

0 comments on commit 43a965d

Please sign in to comment.