Album.php 11.4 KB
Newer Older
1 2
<?php

3
/* GNU FM -- a free network service for sharing your music listening habits
4

5
   Copyright (C) 2009 Free Software Foundation, Inc
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

22
require_once($install_path . '/database.php');
elleo's avatar
elleo committed
23 24
require_once($install_path . '/data/Artist.php');
require_once($install_path . '/data/Track.php');
25
require_once($install_path . '/data/Tag.php');
26
require_once($install_path . '/utils/resolve-external.php');
27
require_once($install_path . '/utils/linkeddata.php');
28 29 30 31

/**
 * Represents album data
 *
clint's avatar
clint committed
32
 * General album attributes are accessible as public variables.
33 34 35 36
 * Lists of tracks are only generated when requested.
 */
class Album {

elleo's avatar
elleo committed
37
	public $name, $artist_name, $mbid, $releasedate, $image;
38
	public $id;
39 40 41 42 43 44 45

	/**
	 * Album constructor
	 *
	 * @param string name The name of the album to load
	 * @param string artist The name of the artist who recorded this album
	 */
46
	function __construct($name, $artist) {
clint's avatar
clint committed
47 48
		global $adodb;
		$adodb->SetFetchMode(ADODB_FETCH_ASSOC);
49
		$this->query = 	'SELECT name, artist_name, mbid, image, releasedate FROM Album WHERE '
50
			. 'lower(name) = lower(' . $adodb->qstr($name) . ') AND '
51 52
			. 'lower(artist_name) = lower(' . $adodb->qstr($artist) . ')';
		$r = $adodb->CacheGetRow(1200, $this->query);
53
		if (!$r) {
54
			throw new Exception('No such album: ' . $name);
elleo's avatar
elleo committed
55
		} else {
clint's avatar
clint committed
56
			$row = sanitize($r);
57 58 59 60
			$this->name = $row['name'];
			$this->mbid = $row['mbid'];
			$this->artist_name = $row['artist_name'];
			$this->releasedate = $row['releasedate'];
elleo's avatar
elleo committed
61
			$this->image = resolve_external_url($row['image']);
62

63 64
			$this->id = identifierAlbum(null, $this->artist_name, null, $this->name, null, null, null, $this->mbid);

65 66 67
			$this->track_query = 'SELECT name, artist_name FROM Track WHERE artist_name = '
				. $adodb->qstr($this->artist_name) . ' AND album_name = '
				. $adodb->qstr($this->name);
68

69
			if ($this->image == '') {
70 71
				$this->image = false;
			}
72
		}
elleo's avatar
elleo committed
73 74 75

	}

76 77 78 79 80 81
	/**
	 * Create a new Album
	 *
	 * @param string $name The name of the album
	 * @param string $artist_name The name of the artist who recorded this album
	 * @param string $image The URL to this album's cover image (optional)
Jonas Haraldsson's avatar
Jonas Haraldsson committed
82
	 * @return Album Album object corresponding to the newly created album
83
	 */
84
	public static function create($name, $artist_name, $image = '') {
85 86 87 88 89 90 91
		global $adodb;

		$adodb->Execute('INSERT INTO Album (name, artist_name, image) VALUES ('
			. $adodb->qstr($name) . ', '
			. $adodb->qstr($artist_name) . ', '
			. $adodb->qstr($image) . ')');

92 93 94 95 96 97
		try {
			$artist = new Artist($artist_name);
			$artist->clearAlbumCache();
		} catch (Exception $e) {
			// No such artist.
		}
98 99 100 101

		return new Album($name, $artist_name);
	}

102 103 104 105 106 107 108 109
	/**
	 * Clears the track cache
	 */
	function clearTrackCache() {
		global $adodb;
		$adodb->CacheFlush($this->track_query);
	}

110 111 112 113 114 115 116 117
	/**
	 * Clear the cache of the album information
	 */
	function clearCache() {
		global $adodb;
		$adodb->CacheFlush($this->query);
	}

Jonas Haraldsson's avatar
Jonas Haraldsson committed
118 119 120 121 122
	/**
	 * Retrieves total play count for all tracks on this album
	 * 
	 * @return int Number of plays
	 */
elleo's avatar
elleo committed
123
	function getPlayCount() {
clint's avatar
clint committed
124 125 126 127 128 129 130
		global $adodb;
		$adodb->SetFetchMode(ADODB_FETCH_ASSOC);
		try {
		$count = $adodb->CacheGetOne(600,
			'SELECT COUNT(*) AS scrobbles FROM Scrobbles JOIN Track ON Scrobbles.track = Track.name WHERE Scrobbles.artist = '
			. $adodb->qstr($this->artist_name) . ' AND Track.album_name ='
			. $adodb->qstr($this->name));
131
		} catch (Exception $e) {
132
			reportError($res->getMessage());
clint's avatar
clint committed
133 134 135
			$c = 0;
		}
		if (!$count) {
elleo's avatar
elleo committed
136
			$c = 0;
137
		} else {
clint's avatar
clint committed
138
			$c = $count;
elleo's avatar
elleo committed
139
		}
elleo's avatar
elleo committed
140
		return $c;
141 142 143 144 145
	}

	/**
	 * Retrieves all the tracks in an album
	 *
Jonas Haraldsson's avatar
Jonas Haraldsson committed
146
	 * @return array Track objects
147 148
	 */
	function getTracks() {
clint's avatar
clint committed
149 150
		global $adodb;
		$adodb->SetFetchMode(ADODB_FETCH_ASSOC);
151
		$res = $adodb->CacheGetAll(600, $this->track_query);
152
		foreach ($res as &$row) {
153
			$tracks[] = new Track($row['name'], $row['artist_name']);
elleo's avatar
elleo committed
154 155 156
		}

		return $tracks;
157 158
	}

159 160 161
	/**
	 * Gives the URL for this album
	 *
Jonas Haraldsson's avatar
Jonas Haraldsson committed
162
	 * @return string The URL of this album
163 164
	 */
	function getURL() {
jurgbohn's avatar
jurgbohn committed
165
		return Server::getAlbumURL($this->artist_name, $this->name);
166 167
	}

168 169 170
	/**
	 * Gives the URL for managers to add a new track to this album
	 *
Jonas Haraldsson's avatar
Jonas Haraldsson committed
171
	 * @return string The URL for adding tracks to this album
172 173 174 175 176
	 */
	function getAddTrackURL() {
		return Server::getAddTrackURL($this->artist_name, $this->name);
	}

177
	/**
Jonas Haraldsson's avatar
Jonas Haraldsson committed
178 179
	 * Get the top tags for this album, ordered by tag count
	 *
180 181 182
	 * @param int $limit The number of tags to return (default is 10)
	 * @param int $offset The position of the first tag to return (default is 0)
	 * @param int $cache Caching period of query in seconds (default is 600)
Jonas Haraldsson's avatar
Jonas Haraldsson committed
183
	 * @return array Tag details ((tag, freq) .. )
184
	 */
185 186
	function getTopTags($limit=10, $offset=0, $cache=600) {
		return Tag::_getTagData($cache, $limit, $offset, null, $this->artist_name, $this->name);
187 188
	}

189 190 191 192 193 194 195
	/**
	 * Get a specific user's tags for this album.
	 *
	 * @param int $userid Get tags for this user
	 * @param int $limit The number of tags to return (default is 10)
	 * @param int $offset The position of the first tag to return (default is 0)
	 * @param int $cache Caching period of query in seconds (default is 600)
Jonas Haraldsson's avatar
Jonas Haraldsson committed
196
	 * @return array Tag details ((tag, freq) .. )
197 198 199 200 201 202 203
	 */
	function getTags($userid, $limit=10, $offset=0, $cache=600) {
		if(isset($userid)) {
			return Tag::_getTagData($cache, $limit, $offset, $userid, $this->artist_name, $this->name);
		}
	}

204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
	/**
	 * Set the cover art for this artist.
	 *
	 * @param string $image The URL of the image to use.
	 */
	function setImage($image) {
		global $adodb;
		$adodb->Execute('UPDATE Album SET image=' . $adodb->qstr($image) 
			. ' WHERE artist_name = ' . $adodb->qstr($this->artist_name)
			. ' AND name = ' . $adodb->qstr($this->name));
		$this->clearCache();
	}

	function getEditURL() {
		return Server::getAlbumEditURL($this->artist_name, $this->name);
	}

221
	/**
222
	 * Return Album Art URL from Wikipedia
Jonas Haraldsson's avatar
Jonas Haraldsson committed
223 224 225 226 227 228 229 230
	 *
	 * @deprecated mb_convert_case fails and wikipedia returns 403. 20120307 kabniel
	 *
	 * @param string $album_name Album name
	 * @param string $artist_name Artist name
	 * @param bool $save Save info to Album table.
	 * @param string $api_url Wikipedia API URL
	 * @return array An object with the url and usage_url properties
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
	 */
	function WikipediaAlbumArt ($album_name, $artist_name, $save = false, $api_url = 'http://en.wikipedia.org/w/api.php') {
		global $adodb;
		/*
		 * Search query string
		 */
		$album_name  = mb_convert_case($album_name, 'UTF-8');
		$artist_name = mb_convert_case($artist_name, 'UTF-8');
		$get_params  = array(
			'action'    => 'query',
			'format'    => 'php',
			'redirects' => true,
			'list'      => 'search',
			'srsearch'  => "$album_name $artist_name album",
			'srlimit'   => 10
		);
247

248
		try {
249 250 251 252
			if (is_null($album_name)) {
				throw new Exception('No album name provided.');
			}

253
			$search_url = $api_url . '?' . http_build_query($get_params);
254

255 256
			$open = fopen($search_url, 'r');

257 258 259 260
			if ($open == false) {
				throw new Exception('Can\'t open Search URL');
			}

261 262
			$search_results = unserialize(stream_get_contents($open));
			fclose($open);
263 264

			if (!isset($search_results['query']['search']) || count($search_results['query']['search']) == 0) {
265
				return false;
266 267
			}

268
			$results = array();
269

270 271
			foreach ($search_results['query']['search'] as $id => $page) {
				switch ($page['title']) {
272
				case $album_name:
273 274
					$weight = 0.5;
					break;
275
				case "$album_name (album)":
276 277
					$weight = 0.75;
					break;
278
				case "$album_name ($artist_name album)":
279 280 281 282 283
					$weight = 1;
					break;
				default:
					$weight = 0;
				}
284 285

				if ($weight > 0) {
286
					$results[$page['title']] = $weight;
287
				}
288
			}
289

290 291 292 293 294 295
			if (count($results) > 0) {
				# order by weight
				# highest gets on bottom
				asort($results);
				end($results);
				$possible_cover = key($results);
296

297 298 299 300 301 302 303 304 305 306
				# Cover search query string
				$cover_params = array(
					'action'    => 'query',
					'format'    => 'php',
					'redirects' => true,
					'generator' => 'images',
					'titles'    => $possible_cover,
					'prop'      => 'imageinfo',
					'iiprop'    => 'url'
				);
307

308 309
				$cover_search_url = $api_url . '?' . http_build_query($cover_params);
				$open_cover_url   = fopen($cover_search_url, 'r');
310 311 312 313

				if ($open_cover_url == false) {
					throw new Exception ('Can\'t open Cover Search URL');
				}
314 315
				$cover_search_results = unserialize(stream_get_contents($open_cover_url));
				fclose($open_cover_url);
316 317

				if (!isset($cover_search_results['query']['pages']) || count($cover_search_results['query']['pages']) == 0) {
318
					return false;
319 320
				}

321
				foreach ($cover_search_results['query']['pages'] as $image_id => $image) {
322
					# Wikipedia covers are mostly JPEG images.
323 324 325 326 327 328
					# Gets the first image (hard guess!)
					if (preg_match('/\.jpg$/i', $image['title']) == 1) {
						$cover = $image['imageinfo'][0];
						break;
					}
				}
329

330 331 332 333 334 335 336 337 338
				/*
				 * Save the info if $save = true
				 */
				if ($save) {
					$adodb->SetFetchMode(ADODB_FETCH_ASSOC);
					$album   = $adodb->qstr($album_name);
					$artist  = $adodb->qstr($artist_name);
					$license = $adodb->qstr($cover['descriptionurl']);
					$image   = $adodb->qstr($cover['url']);
339

340
					$sql = ('UPDATE Album SET image = '
341
						. ($image) . ', '
342 343 344
						. ' artwork_license = '
						. ($license) . ' WHERE artist_name = '. ($artist)
						. ' AND name = '	. ($album));
345

346 347
					$res = $adodb->Execute($sql);
				}
348 349

				return $cover['url'];
350 351 352
			} else {
				return false;
			}
353

354 355

		} catch (Exception $e) {
356 357
			reportError($e->getMessage());
		}
358

359 360
		return $album_art_url;
	}
clint's avatar
clint committed
361

362
}
363

Jonas Haraldsson's avatar
Jonas Haraldsson committed
364 365 366 367 368 369 370 371
/**
 * Retrieves and saves the URL to cover art for an album
 *
 * @deprecated amazonaws.com returns error 400. 20120307 kabniel
 *
 * @param string $artist Artist name
 * @param string $album Album name
 */
372
function go_get_album_art($artist, $album){
clint's avatar
clint committed
373 374
	global $adodb;
	$adodb->SetFetchMode(ADODB_FETCH_ASSOC);
375

376
	$Access_Key_ID = '1EST86JB355JBS3DFE82'; // this is mattl's personal key :)
377

378
	$SearchIndex = 'Music';
379
	$Keywords = rawurlencode($artist . ' ' . $album);
380 381 382
	$Operation = 'ItemSearch';
	$Version = '2007-07-16';
	$ResponseGroup = 'ItemAttributes,Images';
383
	$request =
384 385 386 387 388 389 390 391 392 393 394
		'http://ecs.amazonaws.com/onca/xml'
		. '?Service=AWSECommerceService'
		. '&AssociateTag=' . $Associate_tag
		. '&AWSAccessKeyId=' . $Access_Key_ID
		. '&Operation=' . $Operation
		. '&Version=' . $Version
		. '&SearchIndex=' . $SearchIndex
		. '&Keywords=' . $Keywords
		. '&ResponseGroup=' . $ResponseGroup;

	$aws_xml = simplexml_load_file($request) or die('xml response not loading');
mattl's avatar
mattl committed
395

396 397
	$image = $aws_xml->Items->Item->MediumImage->URL;
	$URI = $aws_xml->Items->Item->DetailPageURL;
clint's avatar
clint committed
398

399
	if ($image) {
mattl's avatar
mattl committed
400

401 402 403
		if ($license == '') {
			$license = 'amazon';
		}
mattl's avatar
mattl committed
404

clint's avatar
clint committed
405 406 407 408
		$license = $adodb->qstr($license);
		$image = $adodb->qstr($image);
		$album = $adodb->qstr($album);
		$artist = $adodb->qstr($artist);
mattl's avatar
mattl committed
409

410 411 412
		$sql = ('UPDATE Album SET image = '
			. ($image) . ', '
			. ' artwork_license = '
clint's avatar
clint committed
413
			. ($license) . ' WHERE artist_name = '. ($artist)
414
			. ' AND name = '	. ($album));
mattl's avatar
mattl committed
415

clint's avatar
clint committed
416 417
		try {
			$res = $adodb->Execute($sql);
418
		} catch (Exception $e) {
clint's avatar
clint committed
419
			die('FAILED ' . $e->getMessage() . ' query was :' . $sql);
420 421
		}
	}
mattl's avatar
mattl committed
422
}