Passed
Pull Request — master (#1141)
by Pauli
04:07
created

AdvSearchController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 13
nc 1
nop 14
dl 0
loc 27
rs 9.8333
c 1
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 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 Pauli Järvinen <[email protected]>
10
 * @copyright Pauli Järvinen 2024
11
 */
12
13
namespace OCA\Music\Controller;
14
15
use OCP\AppFramework\Controller;
16
use OCP\AppFramework\Http;
17
use OCP\AppFramework\Http\JSONResponse;
18
use OCP\IRequest;
19
20
use OCA\Music\AppFramework\BusinessLayer\BusinessLayerException;
21
use OCA\Music\AppFramework\Core\Logger;
22
use OCA\Music\BusinessLayer\AlbumBusinessLayer;
23
use OCA\Music\BusinessLayer\ArtistBusinessLayer;
24
use OCA\Music\BusinessLayer\BookmarkBusinessLayer;
25
use OCA\Music\BusinessLayer\GenreBusinessLayer;
26
use OCA\Music\BusinessLayer\PlaylistBusinessLayer;
27
use OCA\Music\BusinessLayer\PodcastChannelBusinessLayer;
28
use OCA\Music\BusinessLayer\PodcastEpisodeBusinessLayer;
29
use OCA\Music\BusinessLayer\RadioStationBusinessLayer;
30
use OCA\Music\BusinessLayer\TrackBusinessLayer;
31
use OCA\Music\Db\SortBy;
32
use OCA\Music\Http\ErrorResponse;
33
use OCA\Music\Utility\Random;
34
use OCA\Music\Utility\Util;
35
36
class AdvSearchController extends Controller {
37
38
	private $albumBusinessLayer;
39
	private $artistBusinessLayer;
40
	private $bookmarkBusinessLayer;
41
	private $genreBusinessLayer;
42
	private $playlistBusinessLayer;
43
	private $podcastChannelBusinessLayer;
44
	private $podcastEpisodeBusinessLayer;
45
	private $radioStationBusinessLayer;
46
	private $trackBusinessLayer;
47
	private $userId;
48
	private $random;
49
	private $logger;
50
51
	public function __construct(string $appName,
52
								IRequest $request,
53
								AlbumBusinessLayer $albumBusinessLayer,
54
								ArtistBusinessLayer $artistBusinessLayer,
55
								BookmarkBusinessLayer $bookmarkBusinessLayer,
56
								GenreBusinessLayer $genreBusinessLayer,
57
								PlaylistBusinessLayer $playlistBusinessLayer,
58
								PodcastChannelBusinessLayer $podcastChannelBusinessLayer,
59
								PodcastEpisodeBusinessLayer $podcastEpisodeBusinessLayer,
60
								RadioStationBusinessLayer $radioStationBusinessLayer,
61
								TrackBusinessLayer $trackBusinessLayer,
62
								?string $userId, // null if this gets called after the user has logged out or on a public page
63
								Random $random,
64
								Logger $logger) {
65
		parent::__construct($appName, $request);
66
		$this->albumBusinessLayer = $albumBusinessLayer;
67
		$this->artistBusinessLayer = $artistBusinessLayer;
68
		$this->bookmarkBusinessLayer = $bookmarkBusinessLayer;
69
		$this->genreBusinessLayer = $genreBusinessLayer;
70
		$this->playlistBusinessLayer = $playlistBusinessLayer;
71
		$this->podcastChannelBusinessLayer = $podcastChannelBusinessLayer;
72
		$this->podcastEpisodeBusinessLayer = $podcastEpisodeBusinessLayer;
73
		$this->radioStationBusinessLayer = $radioStationBusinessLayer;
74
		$this->trackBusinessLayer = $trackBusinessLayer;
75
		$this->userId = $userId;
76
		$this->random = $random;
77
		$this->logger = $logger;
78
	}
79
80
	/**
81
	 * @NoAdminRequired
82
	 * @NoCSRFRequired
83
	 */
84
	public function search(string $entity, string $rules, string $conjunction='and', string $order='name', ?int $limit=null, ?int $offset=null) {
85
		$rules = \json_decode($rules, true);
86
87
		foreach ($rules as $rule) {
88
			if (empty($rule['rule'] || empty($rule['operator'] || !isset($rule['input'])))) {
89
				return new ErrorResponse(Http::STATUS_BAD_REQUEST, 'Invalid search rule');
90
			}
91
		}
92
93
		try {
94
			$businessLayer = $this->businessLayerForType($entity);
95
96
			if ($businessLayer !== null) {
97
				$entities = $businessLayer->findAllAdvanced(
98
					$conjunction, $rules, $this->userId, self::mapSortBy($order), ($order==='random') ? $this->random : null, $limit, $offset);
0 ignored issues
show
Bug introduced by
It seems like $this->userId can also be of type null; however, parameter $userId of OCA\Music\BusinessLayer\...ayer::findAllAdvanced() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

98
					$conjunction, $rules, /** @scrutinizer ignore-type */ $this->userId, self::mapSortBy($order), ($order==='random') ? $this->random : null, $limit, $offset);
Loading history...
Bug introduced by
It seems like $this->userId can also be of type null; however, parameter $userId of OCA\Music\AppFramework\B...ayer::findAllAdvanced() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

98
					$conjunction, $rules, /** @scrutinizer ignore-type */ $this->userId, self::mapSortBy($order), ($order==='random') ? $this->random : null, $limit, $offset);
Loading history...
99
				$entityIds = Util::extractIds($entities);
100
				return new JSONResponse([
101
					'id' => \md5($entity.\serialize($entityIds)), // use hash => identical results will have identical ID
102
					Util::snakeToCamelCase($entity).'Ids' => $entityIds
103
				]);
104
			} else {
105
				return new ErrorResponse(Http::STATUS_BAD_REQUEST, "Entity type '$entity' is not supported");
106
			}
107
		} catch (BusinessLayerException $e) {
108
			return new ErrorResponse(Http::STATUS_BAD_REQUEST, $e->getMessage());
109
		}
110
	}
111
112
	private function businessLayerForType($type) {
113
		$map = [
114
			'album' => $this->albumBusinessLayer,
115
			'artist' => $this->artistBusinessLayer,
116
			'bookmark' => $this->bookmarkBusinessLayer,
117
			'genre' => $this->genreBusinessLayer,
118
			'playlist' => $this->playlistBusinessLayer,
119
			'podcast_channel' => $this->podcastChannelBusinessLayer,
120
			'podcast_episode' => $this->podcastEpisodeBusinessLayer,
121
			'radio' => $this->radioStationBusinessLayer,
122
			'track' => $this->trackBusinessLayer,
123
		];
124
		return $map[$type] ?? null;
125
	}
126
127
	private static function mapSortBy(string $order) {
128
		$map = [
129
			'name'			=> SortBy::Name,
130
			'parent'		=> SortBy::Parent,
131
			'newest'		=> SortBy::Newest,
132
			'play_count'	=> SortBy::PlayCount,
133
			'last_played'	=> SortBy::LastPlayed,
134
			'rating'		=> SortBy::Rating,
135
		];
136
		return $map[$order] ?? SortBy::Name;
137
	}
138
139
}