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