Passed
Push — master ( 458bc4...32b27b )
by Pauli
03:16
created

ShivaApiController::randomItem()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 2
dl 0
loc 11
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
/**
4
 * ownCloud - Music app
5
 *
6
 * This file is licensed under the Affero General Public License version 3 or
7
 * later. See the COPYING file.
8
 *
9
 * @author Morris Jobke <[email protected]>
10
 * @author Pauli Järvinen <[email protected]>
11
 * @copyright Morris Jobke 2013, 2014
12
 * @copyright Pauli Järvinen 2017 - 2025
13
 */
14
15
namespace OCA\Music\Controller;
16
17
use OCP\AppFramework\Controller;
18
use OCP\AppFramework\Http;
19
use OCP\AppFramework\Http\JSONResponse;
20
use OCP\IL10N;
21
use OCP\IRequest;
22
use OCP\IURLGenerator;
23
24
use OCA\Music\AppFramework\BusinessLayer\BusinessLayer;
25
use OCA\Music\AppFramework\BusinessLayer\BusinessLayerException;
26
use OCA\Music\AppFramework\Core\Logger;
27
use OCA\Music\BusinessLayer\AlbumBusinessLayer;
28
use OCA\Music\BusinessLayer\ArtistBusinessLayer;
29
use OCA\Music\BusinessLayer\TrackBusinessLayer;
30
use OCA\Music\Db\Album;
31
use OCA\Music\Db\Artist;
32
use OCA\Music\Db\SortBy;
33
use OCA\Music\Db\Track;
34
use OCA\Music\Http\ErrorResponse;
35
use OCA\Music\Utility\Random;
36
37
class ShivaApiController extends Controller {
38
39
	private IL10N $l10n;
40
	private TrackBusinessLayer $trackBusinessLayer;
41
	private ArtistBusinessLayer $artistBusinessLayer;
42
	private AlbumBusinessLayer $albumBusinessLayer;
43
	private string $userId;
44
	private IURLGenerator $urlGenerator;
45
	private Logger $logger;
46
47
	public function __construct(string $appname,
48
								IRequest $request,
49
								IURLGenerator $urlGenerator,
50
								TrackBusinessLayer $trackBusinessLayer,
51
								ArtistBusinessLayer $artistBusinessLayer,
52
								AlbumBusinessLayer $albumBusinessLayer,
53
								?string $userId, // null if this gets called after the user has logged out
54
								IL10N $l10n,
55
								Logger $logger) {
56
		parent::__construct($appname, $request);
57
		$this->l10n = $l10n;
58
		$this->trackBusinessLayer = $trackBusinessLayer;
59
		$this->artistBusinessLayer = $artistBusinessLayer;
60
		$this->albumBusinessLayer = $albumBusinessLayer;
61
		$this->userId = $userId ?? '';
62
		$this->urlGenerator = $urlGenerator;
63
		$this->logger = $logger;
64
	}
65
66
	private static function shivaPageToLimits(?int $pageSize, ?int $page) : array {
67
		if (\is_int($page) && \is_int($pageSize) && $page > 0 && $pageSize > 0) {
68
			$limit = $pageSize;
69
			$offset = ($page - 1) * $pageSize;
70
		} else {
71
			$limit = $offset = null;
72
		}
73
		return [$limit, $offset];
74
	}
75
76
	/**
77
	 * @NoAdminRequired
78
	 * @NoCSRFRequired
79
	 */
80
	public function artists($fulltree, $albums, ?int $page_size=null, ?int $page=null) {
81
		$fulltree = \filter_var($fulltree, FILTER_VALIDATE_BOOLEAN);
82
		$includeAlbums = \filter_var($albums, FILTER_VALIDATE_BOOLEAN);
83
		list($limit, $offset) = self::shivaPageToLimits($page_size, $page);
84
85
		/** @var Artist[] $artists */
86
		$artists = $this->artistBusinessLayer->findAll($this->userId, SortBy::Name, $limit, $offset);
87
88
		$artists = \array_map(fn($a) => $this->artistToApi($a, $includeAlbums || $fulltree, $fulltree), $artists);
89
90
		return new JSONResponse($artists);
91
	}
92
93
	/**
94
	 * @NoAdminRequired
95
	 * @NoCSRFRequired
96
	 */
97
	public function artist(int $id, $fulltree) {
98
		$fulltree = \filter_var($fulltree, FILTER_VALIDATE_BOOLEAN);
99
		try {
100
			/** @var Artist $artist */
101
			$artist = $this->artistBusinessLayer->find($id, $this->userId);
102
			$artist = $this->artistToApi($artist, $fulltree, $fulltree);
103
			return new JSONResponse($artist);
104
		} catch (BusinessLayerException $e) {
105
			return new ErrorResponse(Http::STATUS_NOT_FOUND);
106
		}
107
	}
108
109
	/**
110
	 * Return given artist in Shia API format
111
	 * @param Artist $artist
112
	 * @param boolean $includeAlbums
113
	 * @param boolean $includeTracks (ignored if $includeAlbums==false)
114
	 * @return array
115
	 */
116
	private function artistToApi(Artist $artist, bool $includeAlbums, bool $includeTracks) : array {
117
		$artistInApi = $artist->toAPI($this->urlGenerator, $this->l10n);
118
		if ($includeAlbums) {
119
			$artistId = $artist->getId();
120
			$albums = $this->albumBusinessLayer->findAllByArtist($artistId, $this->userId);
121
122
			$artistInApi['albums'] = \array_map(fn($a) => $this->albumToApi($a, $includeTracks, false), $albums);
123
		}
124
		return $artistInApi;
125
	}
126
127
	/**
128
	 * @NoAdminRequired
129
	 * @NoCSRFRequired
130
	 */
131
	public function albums(?int $artist=null, $fulltree=null, ?int $page_size=null, ?int $page=null) {
132
		$fulltree = \filter_var($fulltree, FILTER_VALIDATE_BOOLEAN);
133
		list($limit, $offset) = self::shivaPageToLimits($page_size, $page);
134
135
		if ($artist !== null) {
136
			$albums = $this->albumBusinessLayer->findAllByArtist($artist, $this->userId, $limit, $offset);
137
		} else {
138
			$albums = $this->albumBusinessLayer->findAll($this->userId, SortBy::Name, $limit, $offset);
139
		}
140
141
		$albums = \array_map(fn($a) => $this->albumToApi($a, $fulltree, $fulltree), $albums);
142
143
		return new JSONResponse($albums);
144
	}
145
146
	/**
147
	 * @NoAdminRequired
148
	 * @NoCSRFRequired
149
	 */
150
	public function album(int $id, $fulltree) {
151
		$fulltree = \filter_var($fulltree, FILTER_VALIDATE_BOOLEAN);
152
		try {
153
			$album = $this->albumBusinessLayer->find($id, $this->userId);
154
			$album = $this->albumToApi($album, $fulltree, $fulltree);
155
			return new JSONResponse($album);
156
		} catch (BusinessLayerException $e) {
157
			return new ErrorResponse(Http::STATUS_NOT_FOUND);
158
		}
159
	}
160
161
	/**
162
	 * Return given album in the Shiva API format
163
	 */
164
	private function albumToApi(Album $album, bool $includeTracks, bool $includeArtists) : array {
165
		$albumInApi = $album->toAPI($this->urlGenerator, $this->l10n);
166
167
		if ($includeTracks) {
168
			$albumId = $album->getId();
169
			$tracks = $this->trackBusinessLayer->findAllByAlbum($albumId, $this->userId);
170
			$albumInApi['tracks'] = \array_map(fn($t) => $t->toAPI($this->urlGenerator), $tracks);
171
		}
172
173
		if ($includeArtists) {
174
			$artistIds = $album->getArtistIds();
175
			$artists = $this->artistBusinessLayer->findById($artistIds, $this->userId);
176
			$albumInApi['artists'] = \array_map(fn($a) => $a->toAPI($this->urlGenerator, $this->l10n), $artists);
177
		}
178
179
		return $albumInApi;
180
	}
181
182
	/**
183
	 * @NoAdminRequired
184
	 * @NoCSRFRequired
185
	 */
186
	public function tracks(?int $artist=null, ?int $album=null, $fulltree=null, ?int $page_size=null, ?int $page=null) {
187
		$fulltree = \filter_var($fulltree, FILTER_VALIDATE_BOOLEAN);
188
		list($limit, $offset) = self::shivaPageToLimits($page_size, $page);
189
190
		if ($album !== null) {
191
			$tracks = $this->trackBusinessLayer->findAllByAlbum($album, $this->userId, $artist, $limit, $offset);
192
		} elseif ($artist !== null) {
193
			$tracks = $this->trackBusinessLayer->findAllByArtist($artist, $this->userId, $limit, $offset);
194
		} else {
195
			$tracks = $this->trackBusinessLayer->findAll($this->userId, SortBy::Name, $limit, $offset);
196
		}
197
		foreach ($tracks as &$track) {
198
			$artistId = $track->getArtistId();
199
			$albumId = $track->getAlbumId();
200
			$track = $track->toAPI($this->urlGenerator);
201
			if ($fulltree) {
202
				$artist = $this->artistBusinessLayer->find($artistId, $this->userId);
203
				$track['artist'] = $artist->toAPI($this->urlGenerator, $this->l10n);
204
				$album = $this->albumBusinessLayer->find($albumId, $this->userId);
205
				$track['album'] = $album->toAPI($this->urlGenerator, $this->l10n);
206
			}
207
		}
208
		return new JSONResponse($tracks);
209
	}
210
211
	/**
212
	 * @NoAdminRequired
213
	 * @NoCSRFRequired
214
	 */
215
	public function track(int $id) {
216
		try {
217
			/** @var Track $track */
218
			$track = $this->trackBusinessLayer->find($id, $this->userId);
219
			return new JSONResponse($track->toAPI($this->urlGenerator));
220
		} catch (BusinessLayerException $e) {
221
			return new ErrorResponse(Http::STATUS_NOT_FOUND);
222
		}
223
	}
224
225
	/**
226
	 * @NoAdminRequired
227
	 * @NoCSRFRequired
228
	 */
229
	public function randomArtist() {
230
		return $this->randomItem($this->artistBusinessLayer, 'artist');
231
	}
232
233
	/**
234
	 * @NoAdminRequired
235
	 * @NoCSRFRequired
236
	 */
237
	public function randomAlbum() {
238
		return $this->randomItem($this->albumBusinessLayer, 'album');
239
	}
240
241
	/**
242
	 * @NoAdminRequired
243
	 * @NoCSRFRequired
244
	 */
245
	public function randomTrack() {
246
		return $this->randomItem($this->trackBusinessLayer, 'track');
247
	}
248
249
	private function randomItem(BusinessLayer $businessLayer, string $type) {
250
		$ids = $businessLayer->findAllIds($this->userId);
251
		$id = Random::pickItem($ids);
252
253
		if ($id !== null) {
254
			return new JSONResponse([
255
				'id' => $id,
256
				'uri' => $this->urlGenerator->linkToRoute("music.shivaApi.$type", ['id' => $id])
257
			]);
258
		} else {
259
			return new ErrorResponse(Http::STATUS_NOT_FOUND);
260
		}
261
	}
262
}
263