Skip to content

Commit 77fda9a

Browse files
committed
Add DAV endpoint for location grouping
Signed-off-by: Louis Chemineau <[email protected]>
1 parent 4ed1fc1 commit 77fda9a

File tree

10 files changed

+540
-144
lines changed

10 files changed

+540
-144
lines changed

appinfo/info.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
<collection>OCA\Photos\Sabre\PublicRootCollection</collection>
4242
</collections>
4343
<plugins>
44-
<plugin>OCA\Photos\Sabre\Album\PropFindPlugin</plugin>
44+
<plugin>OCA\Photos\Sabre\PropFindPlugin</plugin>
4545
</plugins>
4646
</sabre>
4747

lib/Sabre/Album/AlbumPhoto.php

Lines changed: 11 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -26,26 +26,23 @@
2626
use OCA\Photos\Album\AlbumFile;
2727
use OCA\Photos\Album\AlbumInfo;
2828
use OCA\Photos\Album\AlbumMapper;
29+
use OCA\Photos\Sabre\CollectionPhoto;
2930
use OCP\Files\IRootFolder;
3031
use OCP\Files\Node;
3132
use OCP\Files\File;
33+
use OCP\Files\Folder;
3234
use OCP\Files\NotFoundException;
33-
use Sabre\DAV\Exception\Forbidden;
3435
use Sabre\DAV\IFile;
3536

36-
class AlbumPhoto implements IFile {
37-
private AlbumMapper $albumMapper;
38-
private AlbumInfo $album;
39-
private AlbumFile $albumFile;
40-
private IRootFolder $rootFolder;
41-
42-
public const TAG_FAVORITE = '_$!<Favorite>!$_';
43-
44-
public function __construct(AlbumMapper $albumMapper, AlbumInfo $album, AlbumFile $albumFile, IRootFolder $rootFolder) {
45-
$this->albumMapper = $albumMapper;
46-
$this->album = $album;
47-
$this->albumFile = $albumFile;
48-
$this->rootFolder = $rootFolder;
37+
class AlbumPhoto extends CollectionPhoto implements IFile {
38+
public function __construct(
39+
private AlbumMapper $albumMapper,
40+
private AlbumInfo $album,
41+
private AlbumFile $albumFile,
42+
private IRootFolder $rootFolder,
43+
Folder $userFolder,
44+
) {
45+
parent::__construct($albumFile, $userFolder);
4946
}
5047

5148
/**
@@ -55,36 +52,6 @@ public function delete() {
5552
$this->albumMapper->removeFile($this->album->getId(), $this->albumFile->getFileId());
5653
}
5754

58-
public function getName() {
59-
return $this->albumFile->getFileId() . "-" . $this->albumFile->getName();
60-
}
61-
62-
/**
63-
* @return never
64-
*/
65-
public function setName($name) {
66-
throw new Forbidden('Can\'t rename photos trough the album api');
67-
}
68-
69-
public function getLastModified() {
70-
return $this->albumFile->getMTime();
71-
}
72-
73-
public function put($data) {
74-
$nodes = $this->userFolder->getById($this->file->getFileId());
75-
$node = current($nodes);
76-
if ($node) {
77-
/** @var Node $node */
78-
if ($node instanceof File) {
79-
return $node->putContent($data);
80-
} else {
81-
throw new NotFoundException("Photo is a folder");
82-
}
83-
} else {
84-
throw new NotFoundException("Photo not found for user");
85-
}
86-
}
87-
8855
public function get() {
8956
$nodes = $this->rootFolder
9057
->getUserFolder($this->albumFile->getOwner() ?: $this->album->getUserId())
@@ -102,10 +69,6 @@ public function get() {
10269
}
10370
}
10471

105-
public function getFileId(): int {
106-
return $this->albumFile->getFileId();
107-
}
108-
10972
public function getFileInfo(): Node {
11073
$nodes = $this->rootFolder
11174
->getUserFolder($this->albumFile->getOwner() ?: $this->album->getUserId())
@@ -117,49 +80,4 @@ public function getFileInfo(): Node {
11780
throw new NotFoundException("Photo not found for user");
11881
}
11982
}
120-
121-
public function getContentType() {
122-
return $this->albumFile->getMimeType();
123-
}
124-
125-
public function getETag() {
126-
return $this->albumFile->getEtag();
127-
}
128-
129-
public function getSize() {
130-
return $this->albumFile->getSize();
131-
}
132-
133-
public function getFile(): AlbumFile {
134-
return $this->albumFile;
135-
}
136-
137-
public function isFavorite(): bool {
138-
$tagManager = \OCP\Server::get(\OCP\ITagManager::class);
139-
$tagger = $tagManager->load('files');
140-
if ($tagger === null) {
141-
return false;
142-
}
143-
$tags = $tagger->getTagsForObjects([$this->getFileId()]);
144-
145-
if ($tags === false || empty($tags)) {
146-
return false;
147-
}
148-
149-
return array_search(self::TAG_FAVORITE, current($tags)) !== false;
150-
}
151-
152-
public function setFavoriteState($favoriteState): bool {
153-
$tagManager = \OCP\Server::get(\OCP\ITagManager::class);
154-
$tagger = $tagManager->load('files');
155-
156-
switch ($favoriteState) {
157-
case "0":
158-
return $tagger->removeFromFavorites($this->albumFile->getFileId());
159-
case "1":
160-
return $tagger->addToFavorites($this->albumFile->getFileId());
161-
default:
162-
new \Exception('Favorite state is invalide, should be 0 or 1.');
163-
}
164-
}
16583
}

lib/Sabre/Album/AlbumRoot.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,14 +129,14 @@ public function createDirectory($name) {
129129

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

136136
public function getChild($name): AlbumPhoto {
137137
foreach ($this->album->getFiles() as $file) {
138138
if ($file->getFileId() . "-" . $file->getName() === $name) {
139-
return new AlbumPhoto($this->albumMapper, $this->album->getAlbum(), $file, $this->rootFolder);
139+
return new AlbumPhoto($this->albumMapper, $this->album->getAlbum(), $file, $this->rootFolder, $this->rootFolder->getUserFolder($this->userId));
140140
}
141141
}
142142
throw new NotFound("$name not found");

lib/Sabre/CollectionPhoto.php

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* @copyright Copyright (c) 2022 Robin Appelman <[email protected]>
6+
*
7+
* @license GNU AGPL version 3 or any later version
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Affero General Public License as
11+
* published by the Free Software Foundation, either version 3 of the
12+
* License, or (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU Affero General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Affero General Public License
20+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
*
22+
*/
23+
24+
namespace OCA\Photos\Sabre;
25+
26+
use OCA\Photos\DB\PhotosFile;
27+
use OCP\Files\Node;
28+
use OCP\Files\File;
29+
use OCP\Files\Folder;
30+
use OCP\Files\NotFoundException;
31+
use OCP\ITags;
32+
use Sabre\DAV\Exception\Forbidden;
33+
34+
class CollectionPhoto {
35+
public function __construct(
36+
protected PhotosFile $file,
37+
protected Folder $userFolder,
38+
) {
39+
}
40+
41+
public function getName() {
42+
return $this->file->getFileId() . "-" . $this->file->getName();
43+
}
44+
45+
/**
46+
* @return never
47+
*/
48+
public function setName($name) {
49+
throw new Forbidden('Can\'t rename photos trough this api');
50+
}
51+
52+
public function getLastModified() {
53+
return $this->file->getMTime();
54+
}
55+
56+
public function put($data) {
57+
$nodes = $this->userFolder->getById($this->file->getFileId());
58+
$node = current($nodes);
59+
if ($node) {
60+
/** @var Node $node */
61+
if ($node instanceof File) {
62+
return $node->putContent($data);
63+
} else {
64+
throw new NotFoundException("Photo is a folder");
65+
}
66+
} else {
67+
throw new NotFoundException("Photo not found for user");
68+
}
69+
}
70+
71+
public function getFileId(): int {
72+
return $this->file->getFileId();
73+
}
74+
75+
public function getContentType() {
76+
return $this->file->getMimeType();
77+
}
78+
79+
public function getETag() {
80+
return $this->file->getEtag();
81+
}
82+
83+
public function getSize() {
84+
return $this->file->getSize();
85+
}
86+
87+
public function getFile(): PhotosFile {
88+
return $this->file;
89+
}
90+
91+
public function isFavorite(): bool {
92+
$tagManager = \OCP\Server::get(\OCP\ITagManager::class);
93+
$tagger = $tagManager->load('files');
94+
if ($tagger === null) {
95+
return false;
96+
}
97+
$tags = $tagger->getTagsForObjects([$this->getFileId()]);
98+
99+
if ($tags === false || empty($tags)) {
100+
return false;
101+
}
102+
103+
return array_search(ITags::TAG_FAVORITE, current($tags)) !== false;
104+
}
105+
106+
public function setFavoriteState($favoriteState): bool {
107+
$tagManager = \OCP\Server::get(\OCP\ITagManager::class);
108+
$tagger = $tagManager->load('files');
109+
110+
switch ($favoriteState) {
111+
case "0":
112+
return $tagger->removeFromFavorites($this->file->getFileId());
113+
case "1":
114+
return $tagger->addToFavorites($this->file->getFileId());
115+
default:
116+
new \Exception('Favorite state is invalide, should be 0 or 1.');
117+
}
118+
}
119+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* @copyright Copyright (c) 2022 Louis Chemineau <[email protected]>
6+
*
7+
* @author Louis Chemineau <[email protected]>
8+
*
9+
* @license GNU AGPL version 3 or any later version
10+
*
11+
* This program is free software: you can redistribute it and/or modify
12+
* it under the terms of the GNU Affero General Public License as
13+
* published by the Free Software Foundation, either version 3 of the
14+
* License, or (at your option) any later version.
15+
*
16+
* This program is distributed in the hope that it will be useful,
17+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+
* GNU Affero General Public License for more details.
20+
*
21+
* You should have received a copy of the GNU Affero General Public License
22+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
23+
*
24+
*/
25+
26+
namespace OCA\Photos\Sabre\Location;
27+
28+
use OCA\Photos\DB\Location\LocationFile;
29+
use OCA\Photos\DB\Location\LocationInfo;
30+
use OCA\Photos\Sabre\CollectionPhoto;
31+
use OCP\Files\IRootFolder;
32+
use OCP\Files\Node;
33+
use OCP\Files\File;
34+
use OCP\Files\Folder;
35+
use OCP\Files\NotFoundException;
36+
use Sabre\DAV\Exception\Forbidden;
37+
use Sabre\DAV\IFile;
38+
39+
class LocationPhoto extends CollectionPhoto implements IFile {
40+
public function __construct(
41+
private LocationInfo $locationInfo,
42+
LocationFile $file,
43+
private IRootFolder $rootFolder,
44+
Folder $userFolder
45+
) {
46+
parent::__construct($file, $userFolder);
47+
}
48+
49+
/**
50+
* @return void
51+
*/
52+
public function delete() {
53+
throw new Forbidden('Cannot remove from a location');
54+
}
55+
56+
public function get() {
57+
$nodes = $this->rootFolder
58+
->getUserFolder($this->locationInfo->getUserId())
59+
->getById($this->file->getFileId());
60+
$node = current($nodes);
61+
if ($node) {
62+
/** @var Node $node */
63+
if ($node instanceof File) {
64+
return $node->fopen('r');
65+
} else {
66+
throw new NotFoundException("Photo is a folder");
67+
}
68+
} else {
69+
throw new NotFoundException("Photo not found for user");
70+
}
71+
}
72+
73+
public function getFileInfo(): Node {
74+
$nodes = $this->rootFolder
75+
->getUserFolder($this->locationInfo->getUserId())
76+
->getById($this->file->getFileId());
77+
$node = current($nodes);
78+
if ($node) {
79+
return $node;
80+
} else {
81+
throw new NotFoundException("Photo not found for user");
82+
}
83+
}
84+
}

0 commit comments

Comments
 (0)