Passed
Push — master ( 79d05c...01efb7 )
by Pauli
02:15
created

ApiController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 33
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 16
nc 1
nop 17
dl 0
loc 33
ccs 17
cts 17
cp 1
crap 1
rs 9.7333
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
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 - 2020
13
 */
14
15
namespace OCA\Music\Controller;
16
17
use \OCP\AppFramework\Controller;
0 ignored issues
show
Bug introduced by
The type OCP\AppFramework\Controller was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
use \OCP\AppFramework\Http;
0 ignored issues
show
Bug introduced by
The type OCP\AppFramework\Http was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
use \OCP\AppFramework\Http\DataDisplayResponse;
0 ignored issues
show
Bug introduced by
The type OCP\AppFramework\Http\DataDisplayResponse was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
20
use \OCP\AppFramework\Http\JSONResponse;
0 ignored issues
show
Bug introduced by
The type OCP\AppFramework\Http\JSONResponse was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
21
use \OCP\AppFramework\Http\RedirectResponse;
0 ignored issues
show
Bug introduced by
The type OCP\AppFramework\Http\RedirectResponse was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
22
use \OCP\Files\Folder;
0 ignored issues
show
Bug introduced by
The type OCP\Files\Folder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
23
use \OCP\IL10N;
0 ignored issues
show
Bug introduced by
The type OCP\IL10N was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
use \OCP\IRequest;
0 ignored issues
show
Bug introduced by
The type OCP\IRequest was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
use \OCP\IURLGenerator;
0 ignored issues
show
Bug introduced by
The type OCP\IURLGenerator was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
26
27
use \OCA\Music\AppFramework\BusinessLayer\BusinessLayerException;
28
use \OCA\Music\AppFramework\Core\Logger;
29
use \OCA\Music\BusinessLayer\AlbumBusinessLayer;
30
use \OCA\Music\BusinessLayer\ArtistBusinessLayer;
31
use \OCA\Music\BusinessLayer\GenreBusinessLayer;
32
use \OCA\Music\BusinessLayer\TrackBusinessLayer;
33
use \OCA\Music\Db\Album;
34
use \OCA\Music\Db\Artist;
35
use \OCA\Music\Db\Maintenance;
36
use \OCA\Music\Db\Track;
37
use \OCA\Music\Http\ErrorResponse;
38
use \OCA\Music\Http\FileResponse;
39
use \OCA\Music\Utility\CollectionHelper;
40
use \OCA\Music\Utility\CoverHelper;
41
use \OCA\Music\Utility\DetailsHelper;
42
use \OCA\Music\Utility\LastfmService;
43
use \OCA\Music\Utility\Scanner;
44
use \OCA\Music\Utility\Util;
45
46
class ApiController extends Controller {
47
48
	/** @var IL10N */
49
	private $l10n;
50
	/** @var TrackBusinessLayer */
51
	private $trackBusinessLayer;
52
	/** @var ArtistBusinessLayer */
53
	private $artistBusinessLayer;
54
	/** @var AlbumBusinessLayer */
55
	private $albumBusinessLayer;
56
	/** @var GenreBusinessLayer */
57
	private $genreBusinessLayer;
58
	/** @var Scanner */
59
	private $scanner;
60
	/** @var CollectionHelper */
61
	private $collectionHelper;
62
	/** @var CoverHelper */
63
	private $coverHelper;
64
	/** @var DetailsHelper */
65
	private $detailsHelper;
66
	/** @var LastfmService */
67
	private $lastfmService;
68
	/** @var Maintenance */
69
	private $maintenance;
70
	/** @var string */
71
	private $userId;
72
	/** @var IURLGenerator */
73
	private $urlGenerator;
74
	/** @var Folder */
75
	private $userFolder;
76
	/** @var Logger */
77
	private $logger;
78
79 16
	public function __construct($appname,
80
								IRequest $request,
81
								IURLGenerator $urlGenerator,
82
								TrackBusinessLayer $trackbusinesslayer,
83
								ArtistBusinessLayer $artistbusinesslayer,
84
								AlbumBusinessLayer $albumbusinesslayer,
85
								GenreBusinessLayer $genreBusinessLayer,
86
								Scanner $scanner,
87
								CollectionHelper $collectionHelper,
88
								CoverHelper $coverHelper,
89
								DetailsHelper $detailsHelper,
90
								LastfmService $lastfmService,
91
								Maintenance $maintenance,
92
								$userId,
93
								IL10N $l10n,
94
								/*Folder*/ $userFolder, // no type-hint as this may sometimes be null
95
								Logger $logger) {
96 16
		parent::__construct($appname, $request);
97 16
		$this->l10n = $l10n;
98 16
		$this->trackBusinessLayer = $trackbusinesslayer;
99 16
		$this->artistBusinessLayer = $artistbusinesslayer;
100 16
		$this->albumBusinessLayer = $albumbusinesslayer;
101 16
		$this->genreBusinessLayer = $genreBusinessLayer;
102 16
		$this->scanner = $scanner;
103 16
		$this->collectionHelper = $collectionHelper;
104 16
		$this->coverHelper = $coverHelper;
105 16
		$this->detailsHelper = $detailsHelper;
106 16
		$this->lastfmService = $lastfmService;
107 16
		$this->maintenance = $maintenance;
108 16
		$this->userId = $userId;
109 16
		$this->urlGenerator = $urlGenerator;
110 16
		$this->userFolder = $userFolder;
111 16
		$this->logger = $logger;
112 16
	}
113
114
	/**
115
	 * Extracts the id from an unique slug (id-slug)
116
	 * @param string $slug the slug
117
	 * @return integer the id
118
	 */
119 5
	protected static function getIdFromSlug($slug) {
120 5
		$split = \explode('-', $slug, 2);
121
122 5
		return (int)$split[0];
123
	}
124
125
	/**
126
	 * @NoAdminRequired
127
	 * @NoCSRFRequired
128
	 */
129
	public function prepareCollection() {
130
		$hash = $this->collectionHelper->getCachedJsonHash();
131
		if ($hash === null) {
132
			// build the collection but ignore the data for now
133
			$this->collectionHelper->getJson();
134
			$hash = $this->collectionHelper->getCachedJsonHash();
135
		}
136
		return new JSONResponse(['hash' => $hash]);
137
	}
138
139
	/**
140
	 * @NoAdminRequired
141
	 * @NoCSRFRequired
142
	 */
143
	public function collection() {
144
145
		$collectionJson = $this->collectionHelper->getJson();
146
		$response = new DataDisplayResponse($collectionJson);
147
		$response->addHeader('Content-Type', 'application/json; charset=utf-8');
148
149
		// Instruct the client to cache the result in case it requested the collection with
150
		// the correct hash. The hash could be incorrect if the collection would have changed
151
		// between calls to prepareCollection() and colletion().
152
		$requestHash = $this->request->getParam('hash');
153
		$actualHash = $this->collectionHelper->getCachedJsonHash();
154
		if (!empty($actualHash) && $requestHash === $actualHash) {
155
			self::setClientCaching($response, 90); // cache for 3 months
156
		}
157
158
		return $response;
159
	}
160
161
	/**
162
	 * @NoAdminRequired
163
	 * @NoCSRFRequired
164
	 */
165
	public function folders() {
166
		$folders = $this->trackBusinessLayer->findAllFolders($this->userId, $this->userFolder);
167
		return new JSONResponse($folders);
168
	}
169
170
	/**
171
	 * @NoAdminRequired
172
	 * @NoCSRFRequired
173
	 */
174
	public function genres() {
175
		$genres = $this->genreBusinessLayer->findAllWithTrackIds($this->userId);
176
		$unscanned =  $this->trackBusinessLayer->findFilesWithoutScannedGenre($this->userId);
177
		return new JSONResponse([
178
			'genres' => \array_map(function($g) {return $g->toApi();}, $genres),
179
			'unscanned' => $unscanned
180
		]);
181
	}
182
183
	/**
184
	 * @NoAdminRequired
185
	 * @NoCSRFRequired
186
	 */
187 3
	public function artists($fulltree, $albums) {
188 3
		$fulltree = \filter_var($fulltree, FILTER_VALIDATE_BOOLEAN);
189 3
		$includeAlbums = \filter_var($albums, FILTER_VALIDATE_BOOLEAN);
190
		/** @var Artist[] $artists */
191 3
		$artists = $this->artistBusinessLayer->findAll($this->userId);
192
193
		$artists = \array_map(function($a) use ($fulltree, $includeAlbums) {
194 3
			return $this->artistToApi($a, $includeAlbums || $fulltree, $fulltree);
195 3
		}, $artists);
196
197 3
		return new JSONResponse($artists);
198
	}
199
200
	/**
201
	 * @NoAdminRequired
202
	 * @NoCSRFRequired
203
	 */
204 2
	public function artist($artistIdOrSlug, $fulltree) {
205 2
		$fulltree = \filter_var($fulltree, FILTER_VALIDATE_BOOLEAN);
206 2
		$artistId = $this->getIdFromSlug($artistIdOrSlug);
207
		/** @var Artist $artist */
208 2
		$artist = $this->artistBusinessLayer->find($artistId, $this->userId);
209 2
		$artist = $this->artistToApi($artist, $fulltree, $fulltree);
210 2
		return new JSONResponse($artist);
211
	}
212
213
	/**
214
	 * Return given artist in Shia API format
215
	 * @param Artist $artist
216
	 * @param boolean $includeAlbums
217
	 * @param boolean $includeTracks (ignored if $includeAlbums==false)
218
	 * @return array
219
	 */
220 5
	private function artistToApi($artist, $includeAlbums, $includeTracks) {
221 5
		$artistInApi = $artist->toAPI($this->urlGenerator, $this->l10n);
222 5
		if ($includeAlbums) {
223 3
			$artistId = $artist->getId();
224 3
			$albums = $this->albumBusinessLayer->findAllByArtist($artistId, $this->userId);
225
226
			$artistInApi['albums'] = \array_map(function($a) use ($includeTracks) {
227 3
				return $this->albumToApi($a, $includeTracks, false);
228 3
			}, $albums);
229
		}
230 5
		return $artistInApi;
231
	}
232
233
	/**
234
	 * @NoAdminRequired
235
	 * @NoCSRFRequired
236
	 */
237 2
	public function albums($artist, $fulltree) {
238 2
		$fulltree = \filter_var($fulltree, FILTER_VALIDATE_BOOLEAN);
239 2
		if ($artist) {
240
			$albums = $this->albumBusinessLayer->findAllByArtist($artist, $this->userId);
241
		} else {
242 2
			$albums = $this->albumBusinessLayer->findAll($this->userId);
243
		}
244
245
		$albums = \array_map(function($a) use ($fulltree) {
246 2
			return $this->albumToApi($a, $fulltree, $fulltree);
247 2
		}, $albums);
248
249 2
		return new JSONResponse($albums);
250
	}
251
252
	/**
253
	 * @NoAdminRequired
254
	 * @NoCSRFRequired
255
	 */
256 2
	public function album($albumIdOrSlug, $fulltree) {
257 2
		$fulltree = \filter_var($fulltree, FILTER_VALIDATE_BOOLEAN);
258 2
		$albumId = $this->getIdFromSlug($albumIdOrSlug);
259 2
		$album = $this->albumBusinessLayer->find($albumId, $this->userId);
260 2
		$album = $this->albumToApi($album, $fulltree, $fulltree);
261 2
		return new JSONResponse($album);
262
	}
263
264
	/**
265
	 * Return given album in the Shiva API format
266
	 * @param Album $album
267
	 * @param boolean $includeTracks
268
	 * @param boolean $includeAlbums
269
	 * @return array
270
	 */
271 7
	private function albumToApi($album, $includeTracks, $includeArtists) {
272 7
		$albumInApi = $album->toAPI($this->urlGenerator, $this->l10n);
273
274 7
		if ($includeTracks) {
275 4
			$albumId = $album->getId();
276 4
			$tracks = $this->trackBusinessLayer->findAllByAlbum($albumId, $this->userId);
277
			$albumInApi['tracks'] = \array_map(function($t) {
278 4
				return $t->toAPI($this->urlGenerator);
279 4
			}, $tracks);
280
		}
281
282 7
		if ($includeArtists) {
283 2
			$artistIds = $album->getArtistIds();
284 2
			$artists = $this->artistBusinessLayer->findById($artistIds, $this->userId);
285 2
			$albumInApi['artists'] = \array_map(function($a) {
286 2
				return $a->toAPI($this->urlGenerator, $this->l10n);
287 2
			}, $artists);
288
		}
289
290 7
		return $albumInApi;
291
	}
292
293
	/**
294
	 * @NoAdminRequired
295
	 * @NoCSRFRequired
296
	 */
297 4
	public function tracks($artist, $album, $fulltree) {
298 4
		$fulltree = \filter_var($fulltree, FILTER_VALIDATE_BOOLEAN);
299 4
		if ($artist) {
300 1
			$tracks = $this->trackBusinessLayer->findAllByArtist($artist, $this->userId);
301 3
		} elseif ($album) {
302 1
			$tracks = $this->trackBusinessLayer->findAllByAlbum($album, $this->userId);
303
		} else {
304 2
			$tracks = $this->trackBusinessLayer->findAll($this->userId);
305
		}
306 4
		foreach ($tracks as &$track) {
307 4
			$artistId = $track->getArtistId();
308 4
			$albumId = $track->getAlbumId();
309 4
			$track = $track->toAPI($this->urlGenerator);
310 4
			if ($fulltree) {
311
				/** @var Artist $artist */
312 1
				$artist = $this->artistBusinessLayer->find($artistId, $this->userId);
313 1
				$track['artist'] = $artist->toAPI($this->urlGenerator, $this->l10n);
314 1
				$album = $this->albumBusinessLayer->find($albumId, $this->userId);
315 1
				$track['album'] = $album->toAPI($this->urlGenerator, $this->l10n);
316
			}
317
		}
318 4
		return new JSONResponse($tracks);
319
	}
320
321
	/**
322
	 * @NoAdminRequired
323
	 * @NoCSRFRequired
324
	 */
325 1
	public function track($trackIdOrSlug) {
326 1
		$trackId = $this->getIdFromSlug($trackIdOrSlug);
327
		/** @var Track $track */
328 1
		$track = $this->trackBusinessLayer->find($trackId, $this->userId);
329 1
		return new JSONResponse($track->toAPI($this->urlGenerator));
330
	}
331
332
	/**
333
	 * @NoAdminRequired
334
	 * @NoCSRFRequired
335
	 */
336 1
	public function trackByFileId($fileId) {
337 1
		$track = $this->trackBusinessLayer->findByFileId($fileId, $this->userId);
338 1
		if ($track !== null) {
339 1
			return new JSONResponse($track->toCollection($this->l10n));
340
		} else {
341
			return new ErrorResponse(Http::STATUS_NOT_FOUND);
342
		}
343
	}
344
345
	/**
346
	 * @NoAdminRequired
347
	 * @NoCSRFRequired
348
	 */
349
	public function getScanState() {
350
		return new JSONResponse([
351
			'unscannedFiles' => $this->scanner->getUnscannedMusicFileIds($this->userId),
352
			'scannedCount' => $this->trackBusinessLayer->count($this->userId)
353
		]);
354
	}
355
356
	/**
357
	 * @NoAdminRequired
358
	 * @UseSession to keep the session reserved while execution in progress
359
	 */
360
	public function scan($files, $finalize) {
361
		// extract the parameters
362
		$fileIds = \array_map('intval', \explode(',', $files));
363
		$finalize = \filter_var($finalize, FILTER_VALIDATE_BOOLEAN);
364
365
		$filesScanned = $this->scanner->scanFiles($this->userId, $this->userFolder, $fileIds);
366
367
		$coversUpdated = false;
368
		if ($finalize) {
369
			$coversUpdated = $this->scanner->findAlbumCovers($this->userId)
370
							|| $this->scanner->findArtistCovers($this->userId);
371
			$totalCount = $this->trackBusinessLayer->count($this->userId);
372
			$this->logger->log("Scanning finished, user $this->userId has $totalCount scanned tracks in total", 'info');
373
		}
374
375
		return new JSONResponse([
376
			'filesScanned' => $filesScanned,
377
			'coversUpdated' => $coversUpdated
378
		]);
379
	}
380
381
	/**
382
	 * @NoAdminRequired
383
	 * @UseSession to keep the session reserved while execution in progress
384
	 */
385
	public function resetScanned() {
386
		$this->maintenance->resetDb($this->userId);
387
		return new JSONResponse(['success' => true]);
388
	}
389
390
	/**
391
	 * @NoAdminRequired
392
	 * @NoCSRFRequired
393
	 */
394
	public function download($fileId) {
395
		$track = $this->trackBusinessLayer->findByFileId($fileId, $this->userId);
396
		if ($track === null) {
397
			return new ErrorResponse(Http::STATUS_NOT_FOUND, 'track not found');
398
		}
399
400
		$nodes = $this->userFolder->getById($track->getFileId());
401
		if (\count($nodes) > 0) {
402
			// get the first valid node
403
			$node = $nodes[0];
404
405
			$mime = $node->getMimeType();
406
			$content = $node->getContent();
407
			return new FileResponse(['mimetype' => $mime, 'content' => $content]);
408
		}
409
410
		return new ErrorResponse(Http::STATUS_NOT_FOUND, 'file not found');
411
	}
412
413
	/**
414
	 * @NoAdminRequired
415
	 * @NoCSRFRequired
416
	 */
417
	public function filePath($fileId) {
418
		$nodes = $this->userFolder->getById($fileId);
419
		if (\count($nodes) == 0) {
420
			return new ErrorResponse(Http::STATUS_NOT_FOUND);
421
		} else {
422
			$node = $nodes[0];
423
			$path = $this->userFolder->getRelativePath($node->getPath());
424
			return new JSONResponse(['path' => Util::urlEncodePath($path)]);
425
		}
426
	}
427
428
	/**
429
	 * @NoAdminRequired
430
	 * @NoCSRFRequired
431
	 */
432
	public function fileInfo($fileId) {
433
		$info = $this->scanner->getFileInfo($fileId, $this->userId, $this->userFolder);
434
		if ($info) {
435
			return new JSONResponse($info);
436
		} else {
437
			return new ErrorResponse(Http::STATUS_NOT_FOUND);
438
		}
439
	}
440
441
	/**
442
	 * @NoAdminRequired
443
	 * @NoCSRFRequired
444
	 */
445
	public function fileDetails($fileId) {
446
		$details = $this->detailsHelper->getDetails($fileId, $this->userFolder);
447
		if ($details) {
448
			// metadata extracted, attempt to include also the data from Last.fm
449
			$track = $this->trackBusinessLayer->findByFileId($fileId, $this->userId);
450
			if ($track) {
451
				$details['lastfm'] = $this->lastfmService->getTrackInfo($track->getId(), $this->userId);
452
			} else {
453
				$this->logger->log("Track with file ID $fileId was not found => can't fetch info from Last.fm", 'warn');
454
			}
455
456
			return new JSONResponse($details);
457
		} else {
458
			return new ErrorResponse(Http::STATUS_NOT_FOUND);
459
		}
460
	}
461
462
	/**
463
	 * @NoAdminRequired
464
	 * @NoCSRFRequired
465
	 */
466
	public function albumDetails($albumIdOrSlug) {
467
		try {
468
			$albumId = $this->getIdFromSlug($albumIdOrSlug);
469
			$info = $this->lastfmService->getAlbumInfo($albumId, $this->userId);
470
			return new JSONResponse($info);
471
		}
472
		catch (BusinessLayerException $e) {
473
			return new ErrorResponse(Http::STATUS_NOT_FOUND);
474
		}
475
	}
476
477
	/**
478
	 * @NoAdminRequired
479
	 * @NoCSRFRequired
480
	 */
481
	public function artistDetails($artistIdOrSlug) {
482
		try {
483
			$artistId = $this->getIdFromSlug($artistIdOrSlug);
484
			$info = $this->lastfmService->getArtistInfo($artistId, $this->userId);
485
			return new JSONResponse($info);
486
		}
487
		catch (BusinessLayerException $e) {
488
			return new ErrorResponse(Http::STATUS_NOT_FOUND);
489
		}
490
	}
491
492
	/**
493
	 * @NoAdminRequired
494
	 * @NoCSRFRequired
495
	 */
496
	public function albumCover($albumIdOrSlug, $originalSize) {
497
		try {
498
			$albumId = $this->getIdFromSlug($albumIdOrSlug);
499
			$album = $this->albumBusinessLayer->find($albumId, $this->userId);
500
			return $this->cover($album, $originalSize);
501
		} catch (BusinessLayerException $ex) {
502
			return new ErrorResponse(Http::STATUS_NOT_FOUND);
503
		}
504
	}
505
506
	/**
507
	 * @NoAdminRequired
508
	 * @NoCSRFRequired
509
	 */
510
	public function artistCover($artistIdOrSlug, $originalSize) {
511
		try {
512
			$artistId = $this->getIdFromSlug($artistIdOrSlug);
513
			$artist = $this->artistBusinessLayer->find($artistId, $this->userId);
514
			return $this->cover($artist, $originalSize);
515
		} catch (BusinessLayerException $ex) {
516
			return new ErrorResponse(Http::STATUS_NOT_FOUND);
517
		}
518
	}
519
520
	private function cover($entity, $originalSize) {
521
		$originalSize = \filter_var($originalSize, FILTER_VALIDATE_BOOLEAN);
522
523
		if ($originalSize) {
524
			// cover requested in original size, without scaling or cropping
525
			$cover = $this->coverHelper->getCover(
526
					$entity, $this->userId, $this->userFolder, CoverHelper::DO_NOT_CROP_OR_SCALE);
527
			if ($cover !== null) {
528
				return new FileResponse($cover);
529
			} else {
530
				return new ErrorResponse(Http::STATUS_NOT_FOUND);
531
			}
532
		}
533
		else {
534
			$coverAndHash = $this->coverHelper->getCoverAndHash($entity, $this->userId, $this->userFolder);
535
536
			if ($coverAndHash['hash'] !== null) {
537
				// Cover is in cache. Return a redirection response so that the client
538
				// will fetch the content through a cacheable route.
539
				$link = $this->urlGenerator->linkToRoute('music.api.cachedCover', ['hash' => $coverAndHash['hash']]);
540
				return new RedirectResponse($link);
541
			} else if ($coverAndHash['data'] !== null) {
542
				return new FileResponse($coverAndHash['data']);
543
			} else {
544
				return new ErrorResponse(Http::STATUS_NOT_FOUND);
545
			}
546
		}
547
	}
548
549
	/**
550
	 * @NoAdminRequired
551
	 * @NoCSRFRequired
552
	 */
553
	public function cachedCover($hash) {
554
		$coverData = $this->coverHelper->getCoverFromCache($hash, $this->userId);
555
556
		if ($coverData !== null) {
557
			$response =  new FileResponse($coverData);
558
			// instruct also the client-side to cache the result, this is safe
559
			// as the resource URI contains the image hash
560
			self::setClientCaching($response);
561
			return $response;
562
		} else {
563
			return new ErrorResponse(Http::STATUS_NOT_FOUND);
564
		}
565
	}
566
567
	private static function setClientCaching(&$httpResponse, $days=365) {
568
		$httpResponse->cacheFor($days * 24 * 60 * 60);
569
		$httpResponse->addHeader('Pragma', 'cache');
570
	}
571
}
572