Completed
Push — scanner_improvements ( 4bed41 )
by Pauli
10:32
created

AlbumMapper::removeCovers()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 25
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 16
nc 4
nop 2
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
 * @copyright Morris Jobke 2013, 2014
11
 */
12
13
namespace OCA\Music\Db;
14
15
use OCP\IDBConnection;
16
17
class AlbumMapper extends BaseMapper {
18
19
	public function __construct(IDBConnection $db){
20
		parent::__construct($db, 'music_albums', '\OCA\Music\Db\Album');
21
	}
22
23
	/**
24
	 * @param string $condition
25
	 * @return string
26
	 */
27
	private function makeSelectQuery($condition=null){
28
		return 'SELECT * FROM `*PREFIX*music_albums` `album`'.
29
			'WHERE `album`.`user_id` = ? ' . $condition;
30
	}
31
32
	/**
33
	 * returns all albums of a user
34
	 *
35
	 * @param string $userId the user ID
36
	 * @return Album[]
37
	 */
38
	public function findAll($userId){
39
		$sql = $this->makeSelectQuery('ORDER BY LOWER(`album`.`name`)');
40
		$params = array($userId);
41
		return $this->findEntities($sql, $params);
42
	}
43
44
	/**
45
	 * returns artist IDs mapped to album IDs
46
	 * does not include album_artist_id
47
	 *
48
	 * @param integer[] $albumIds IDs of the albums
49
	 * @return array the artist IDs of an album are accessible
50
	 * 				by the album ID inside of this array
51
	 */
52
	public function getAlbumArtistsByAlbumId($albumIds){
53
		$sql = 'SELECT DISTINCT `track`.`artist_id`, `track`.`album_id` '.
54
			'FROM `*PREFIX*music_tracks` `track`'.
55
			' WHERE `track`.`album_id` IN ' . $this->questionMarks(count($albumIds));
56
		$result = $this->execute($sql, $albumIds);
57
		$artists = array();
58
		while($row = $result->fetch()){
59
			if(!array_key_exists($row['album_id'], $artists)){
60
				$artists[$row['album_id']] = array();
61
			}
62
			$artists[$row['album_id']][] = $row['artist_id'];
63
		}
64
		return $artists;
65
	}
66
67
	/**
68
	 * returns albums of a specified artist
69
	 * The artist may be an album_artist or the artist of a track
70
	 *
71
	 * @param integer $artistId ID of the artist
72
	 * @param string $userId the user ID
73
	 * @return Album[]
74
	 */
75
	public function findAllByArtist($artistId, $userId){
76
		$sql = 'SELECT `album`.`name`, `album`.`year`, `album`.`id`, '.
77
			'`album`.`cover_file_id`, `album`.`mbid`, `album`.`disk`, '.
78
			'`album`.`mbid_group`, `album`.`mbid_group`, `album`.`hash`, '.
79
			'`album`.`album_artist_id` '.
80
			'FROM `*PREFIX*music_albums` `album` '.
81
			'WHERE `album`.`id` IN (SELECT DISTINCT `album`.`id` FROM '.
82
			'`*PREFIX*music_albums` `album` WHERE `album`.`album_artist_id` = ? AND '.
83
			'`album`.`user_id` = ? UNION SELECT `track`.`album_id` '.
84
			'FROM `*PREFIX*music_tracks` `track` WHERE `track`.`artist_id` = ? AND '.
85
			'`track`.`user_id` = ?) ORDER BY LOWER(`album`.`name`)';
86
		$params = array($artistId, $userId, $artistId, $userId);
87
		return $this->findEntities($sql, $params);
88
	}
89
90
	/**
91
	 * returns album that matches a name, a year and an album artist ID
92
	 *
93
	 * @param string|null $albumName name of the album
94
	 * @param string|integer|null $albumYear year of the album release
95
	 * @param string|integer|null $discNumber disk number of this album's disk
96
	 * @param integer|null $albumArtistId ID of the album artist
97
	 * @param string $userId the user ID
98
	 * @return Album[]
99
	 */
100
	public function findAlbum($albumName, $albumYear, $discNumber, $albumArtistId, $userId) {
101
		$sql = 'SELECT `album`.`name`, `album`.`year`, `album`.`disk`, `album`.`id`, '.
102
			'`album`.`cover_file_id`, `album`.`mbid`, `album`.`disk`, '.
103
			'`album`.`mbid_group`, `album`.`mbid_group`, `album`.`hash`, '.
104
			'`album`.`album_artist_id` '.
105
			'FROM `*PREFIX*music_albums` `album` '.
106
			'WHERE `album`.`user_id` = ? ';
107
		$params = array($userId);
108
109
		// add artist id check
110
		if ($albumArtistId === null) {
111
			$sql .= 'AND `album`.`album_artist_id` IS NULL ';
112
		} else {
113
			$sql .= 'AND `album`.`album_artist_id` = ? ';
114
			array_push($params, $albumArtistId);
115
		}
116
117
		// add album name check
118
		if ($albumName === null) {
119
			$sql .= 'AND `album`.`name` IS NULL ';
120
		} else {
121
			$sql .= 'AND `album`.`name` = ? ';
122
			array_push($params, $albumName);
123
		}
124
125
		// add album year check
126
		if ($albumYear === null) {
127
			$sql .= 'AND `album`.`year` IS NULL ';
128
		} else {
129
			$sql .= 'AND `album`.`year` = ? ';
130
			array_push($params, $albumYear);
131
		}
132
133
		// add disc number check
134
		if ($discNumber === null) {
135
			$sql .= 'AND `album`.`disk` IS NULL ';
136
		} else {
137
			$sql .= 'AND `album`.`disk` = ? ';
138
			array_push($params, $discNumber);
139
		}
140
141
		return $this->findEntity($sql, $params);
142
	}
143
144
	/**
145
	 * @param integer $coverFileId
146
	 * @param integer $folderId
147
	 * @return true if one or more albums were influenced
148
	 */
149
	public function updateFolderCover($coverFileId, $folderId){
150
		$sql = 'UPDATE `*PREFIX*music_albums`
151
				SET `cover_file_id` = ?
152
				WHERE `cover_file_id` IS NULL AND `id` IN (
153
					SELECT DISTINCT `tracks`.`album_id`
154
					FROM `*PREFIX*music_tracks` `tracks`
155
					JOIN `*PREFIX*filecache` `files` ON `tracks`.`file_id` = `files`.`fileid`
156
					WHERE `files`.`parent` = ?
157
				)';
158
		$params = array($coverFileId, $folderId);
159
		$result = $this->execute($sql, $params);
160
		return $result->rowCount() > 0;
161
	}
162
163
	/**
164
	 * @param integer $coverFileId
165
	 * @param integer $albumId
166
	 */
167
	public function setCover($coverFileId, $albumId){
168
		$sql = 'UPDATE `*PREFIX*music_albums`
169
				SET `cover_file_id` = ?
170
				WHERE `id` = ?';
171
		$params = array($coverFileId, $albumId);
172
		$this->execute($sql, $params);
173
	}
174
175
	/**
176
	 * @param integer[] $coverFileIds
177
	 * @param string|null $userId the user whose music library is targeted; all users are targeted if omitted
178
	 * @return string[] user IDs of the affected users; empty array if no album was modified
179
	 */
180
	public function removeCovers($coverFileIds, $userId=null){
181
		// find albums using the given file as cover
182
		$sql = 'SELECT `id`, `user_id` FROM `*PREFIX*music_albums` WHERE `cover_file_id` IN ' .
183
			$this->questionMarks(count($coverFileIds));
184
		$params = $coverFileIds;
185
		if ($userId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $userId of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
186
			$sql .= ' AND `user_id` = ?';
187
			$params[] = $userId;
188
		}
189
		$albums = $this->findEntities($sql, $params);
190
191
		// if any albums found, remove the cover from those
192
		$count = count($albums);
193
		if ($count) {
194
			$sql = 'UPDATE `*PREFIX*music_albums`
195
				SET `cover_file_id` = NULL
196
				WHERE `id` IN ' . $this->questionMarks($count);
197
			$params = array_map(function($a) { return $a->getId(); }, $albums);
198
			$result = $this->execute($sql, $params);
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
199
		}
200
201
		// get unique users from the modified albums
202
		$users = array_map(function($a) { return $a->getUserId(); }, $albums);
203
		return array_unique($users);
204
	}
205
206
	/**
207
	 * @return array of dictionaries with keys [albumId, userId, parentFolderId]
208
	 */
209
	public function getAlbumsWithoutCover(){
210
		$sql = 'SELECT DISTINCT `albums`.`id`, `albums`.`user_id`, `files`.`parent`
211
				FROM `*PREFIX*music_albums` `albums`
212
				JOIN `*PREFIX*music_tracks` `tracks` ON `albums`.`id` = `tracks`.`album_id`
213
				JOIN `*PREFIX*filecache` `files` ON `tracks`.`file_id` = `files`.`fileid`
214
				WHERE `albums`.`cover_file_id` IS NULL';
215
		$result = $this->execute($sql);
216
		$return = Array();
217
		while($row = $result->fetch()){
218
			$return[] = [
219
				'albumId' => $row['id'],
220
				'userId' => $row['user_id'],
221
				'parentFolderId' => $row['parent']
222
			];
223
		}
224
		return $return;
225
	}
226
227
	/**
228
	 * @param integer $albumId
229
	 * @param integer $parentFolderId
230
	 * @return true if a cover image was found and added for the album
231
	 */
232
	public function findAlbumCover($albumId, $parentFolderId){
233
		$return = false;
234
		$coverNames = array('cover', 'albumart', 'front', 'folder');
235
		$imagesSql = 'SELECT `fileid`, `name`
236
					FROM `*PREFIX*filecache`
237
					JOIN `*PREFIX*mimetypes` ON `*PREFIX*mimetypes`.`id` = `*PREFIX*filecache`.`mimetype`
238
					WHERE `parent` = ? AND `*PREFIX*mimetypes`.`mimetype` LIKE \'image%\'';
239
		$params = array($parentFolderId);
240
		$result = $this->execute($imagesSql, $params);
241
		$images = $result->fetchAll();
242
		if (count($images)) {
243
			usort($images, function ($imageA, $imageB) use ($coverNames) {
244
				$nameA = strtolower($imageA['name']);
245
				$nameB = strtolower($imageB['name']);
246
				$indexA = PHP_INT_MAX;
247
				$indexB = PHP_INT_MAX;
248
				foreach ($coverNames as $i => $coverName) {
249
					if ($indexA === PHP_INT_MAX && strpos($nameA, $coverName) === 0) {
250
						$indexA = $i;
251
					}
252
					if ($indexB === PHP_INT_MAX && strpos($nameB, $coverName) === 0) {
253
						$indexB = $i;
254
					}
255
					if ($indexA !== PHP_INT_MAX  && $indexB !== PHP_INT_MAX) {
256
						break;
257
					}
258
				}
259
				return $indexA > $indexB;
260
			});
261
			$imageId = $images[0]['fileid'];
262
			$this->setCover($imageId, $albumId);
263
			$return = true;
264
		}
265
		return $return;
266
	}
267
268
	/**
269
	 * Returns the count of albums an Artist is featured in
270
	 * @param integer $artistId
271
	 * @return integer
272
	 */
273
	public function countByArtist($artistId){
274
		$sql = 'SELECT COUNT(*) AS count FROM '.
275
			'(SELECT DISTINCT `track`.`album_id` FROM '.
276
			'`*PREFIX*music_tracks` `track` WHERE `track`.`artist_id` = ? '.
277
			'UNION SELECT `album`.`id` FROM '.
278
			'`*PREFIX*music_albums` `album` WHERE `album`.`album_artist_id` = ?) tmp';
279
		$params = array($artistId, $userId, $artistId, $userId);
0 ignored issues
show
Bug introduced by
The variable $userId does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
280
		$result = $this->execute($sql, $params);
281
		$row = $result->fetch();
282
		return $row['count'];
283
	}
284
285
	/**
286
	 * @param string $name
287
	 * @param string $userId
288
	 * @param bool $fuzzy
289
	 * @return Album[]
290
	 */
291 View Code Duplication
	public function findAllByName($name, $userId, $fuzzy = false){
292
		if ($fuzzy) {
293
			$condition = 'AND LOWER(`album`.`name`) LIKE LOWER(?) ';
294
			$name = '%' . $name . '%';
295
		} else {
296
			$condition = 'AND `album`.`name` = ? ';
297
		}
298
		$sql = $this->makeSelectQuery($condition . 'ORDER BY LOWER(`album`.`name`)');
299
		$params = array($userId, $name);
300
		return $this->findEntities($sql, $params);
301
	}
302
303
	public function findUniqueEntity(Album $album){
304
		return $this->findEntity(
305
				'SELECT * FROM `*PREFIX*music_albums` WHERE `user_id` = ? AND `hash` = ?',
306
				[$album->getUserId(), $album->getHash()]
307
		);
308
	}
309
}
310