We are no longer offering accounts on this server. Consider https://gitlab.freedesktop.org/ as a place to host projects.

User.php 8.62 KB
Newer Older
tonyb486's avatar
tonyb486 committed
1 2
<?php

3
/* GNU FM -- a free network service for sharing your music listening habits
tonyb486's avatar
tonyb486 committed
4

5
   Copyright (C) 2009 Free Software Foundation, Inc
tonyb486's avatar
tonyb486 committed
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');
23 24
require_once($install_path . '/data/sanitize.php');
require_once($install_path . '/utils/human-time.php');
25
require_once($install_path . '/data/Server.php');
tonyb486's avatar
tonyb486 committed
26 27 28 29 30 31 32 33 34

/**
 * Represents User data
 *
 * General attributes are accessible as public variables.
 *
 */
class User {

35
	public $name, $email, $fullname, $bio, $location, $homepage, $error, $userlevel;
tobyink's avatar
tobyink committed
36
	public $id, $acctid, $avatar_uri, $location_uri, $webid_uri, $laconica_profile, $journal_rss;
clint's avatar
clint committed
37
	public $password, $has_identica, $created, $modified, $uniqueid, $anticommercial;
38 39 40 41 42 43

	/**
	 * User constructor
	 *
	 * @param string $name The name of the user to load
	 */
tobyink's avatar
tobyink committed
44
	function __construct($name, $data=null) {
tobyink's avatar
tobyink committed
45 46 47 48

		global $base_url;
		$base = preg_replace('#/$#', '', $base_url);

tobyink's avatar
tobyink committed
49 50 51 52
		if (is_array($data)) {
			$row = $data;
		}
		else {
clint's avatar
clint committed
53
			global $adodb;
Matt Lee's avatar
updates  
Matt Lee committed
54
			$query = 'SELECT * FROM Users WHERE lower(username) = ' . $adodb->qstr(strtolower($name)) . ' LIMIT 1';
clint's avatar
clint committed
55
			$adodb->SetFetchMode(ADODB_FETCH_ASSOC);
56
	                $row = $adodb->CacheGetRow(7200,$query);
clint's avatar
clint committed
57
			if (!$row) {
58
				throw new Exception('EUSER', 22);
clint's avatar
clint committed
59
	                }
tobyink's avatar
tobyink committed
60
		}
clint's avatar
clint committed
61

tobyink's avatar
tobyink committed
62
		if (is_array($row)) {
63
			$this->name         = $row['username'];
tobyink's avatar
tobyink committed
64
			$this->password     = $row['password'];
65 66 67 68 69 70 71
			$this->email	    = $row['email'];
			$this->fullname     = $row['fullname'];
			$this->homepage     = $row['homepage'];
			$this->bio	    = $row['bio'];
			$this->location     = $row['location'];
			$this->location_uri = $row['location_uri'];
			$this->userlevel    = $row['userlevel'];
72 73 74 75 76
			$this->id           = $row['webid_uri'];
			$this->webid_uri    = $row['webid_uri'];
			$this->avatar_uri   = $row['avatar_uri'];
			$this->laconica_profile = $row['laconica_profile'];
			$this->journal_rss  = $row['journal_rss'];
tobyink's avatar
tobyink committed
77
			$this->acctid       = $this->getURL() . '#acct';
78 79 80
			$this->created	    = $row['created'];
			$this->modified     = $row['modified'];
			$this->uniqueid     = $row['uniqueid'];
clint's avatar
clint committed
81
			$this->anticommercial     = $row['anticommercial'];
clint's avatar
clint committed
82

tobyink's avatar
tobyink committed
83
			$this->has_identica = preg_match('#^http://identi\.ca/#i', $this->laconica_profile);
clint's avatar
clint committed
84

tobyink's avatar
tobyink committed
85
			if (! preg_match('/\:/', $this->id))
tobyink's avatar
tobyink committed
86
				$this->id = $this->getURL() . '#me';
clint's avatar
clint committed
87
		}
88
	}
clint's avatar
clint committed
89 90


tobyink's avatar
tobyink committed
91 92
	public static function new_from_uniqueid_number ($uid)
	{
clint's avatar
clint committed
93 94 95 96 97 98
		global $adodb;
		$query = sprintf('SELECT * FROM Users WHERE uniqueid = %d', (int)$uid);
		$adodb->SetFetchMode(ADODB_FETCH_ASSOC);
		$row = $adodb->CacheGetRow(7200,$query);

		if($row) {
tobyink's avatar
tobyink committed
99
			return new User($row['username'], $row);
clint's avatar
clint committed
100 101
		} else {
			return false;
tobyink's avatar
tobyink committed
102 103
		}
	}
clint's avatar
clint committed
104

105 106
	function save ()
	{
clint's avatar
clint committed
107
		global $adodb;
clint's avatar
clint committed
108

tobyink's avatar
tobyink committed
109 110 111 112 113
		// It appears we just discard this data, but this is here for a reason!
		// getLocationDetails will fill in latitude,longitude details into the Places table in the database
		// if it's not already there. This is important as the location_uri field is a foreign key.
		if (!empty($this->location_uri))
			$dummy = Server::getLocationDetails($this->location_uri);
clint's avatar
clint committed
114

115 116 117 118 119 120 121 122 123 124 125 126 127
		$q = sprintf('UPDATE Users SET '
				. 'email=%s, '     # Send a confirmation email first??
				. 'password=%s, '
				. 'fullname=%s, '
				. 'homepage=%s, '
				. 'bio=%s, '
				. 'location=%s, '
				. 'userlevel=%d, '
				. 'webid_uri=%s, '
				. 'location_uri=%s, '
				. 'avatar_uri=%s, '
				. 'laconica_profile=%s, '
				. 'journal_rss=%s, '
clint's avatar
clint committed
128
				. 'anticommercial=%d, '
129 130
				. 'modified=%d '
				. 'WHERE username=%s'
clint's avatar
clint committed
131 132 133 134 135 136
				, $adodb->qstr($this->email)
				, $adodb->qstr($this->password)
				, $adodb->qstr($this->fullname)
				, $adodb->qstr($this->homepage)
				, $adodb->qstr($this->bio)
				, $adodb->qstr($this->location)
137
				, $this->userlevel
clint's avatar
clint committed
138 139 140 141 142
				, $adodb->qstr($this->id)
				, (empty($this->location_uri) ? 'NULL' : $adodb->qstr($this->location_uri))
				, $adodb->qstr($this->avatar_uri)
				, $adodb->qstr($this->laconica_profile)
				, $adodb->qstr($this->journal_rss)
clint's avatar
clint committed
143
				, (int)($this->anticommercial)
144
				, time()
clint's avatar
clint committed
145
				, $adodb->qstr($this->name));
clint's avatar
clint committed
146

147 148 149
		try {
			$res = $adodb->Execute($q);
		} catch (exception $e) {
150
			header('Content-Type: text/plain');
tobyink's avatar
tobyink committed
151 152 153
			exit;
		}

Matt Lee's avatar
updates  
Matt Lee committed
154
		$query = 'SELECT * FROM Users WHERE lower(username) = ' . $adodb->qstr(strtolower($this->name)) . ' LIMIT 1';
155 156
		$adodb->CacheFlush($query);

157 158
		return 1;
	}
159 160 161 162 163

	/**
	 * Get a user's scrobbles ordered by time
	 *
	 * @param int $number The number of scrobbles to return
tonyb486's avatar
tonyb486 committed
164
	 * @return An array of scrobbles with human time
165 166
	 */
	function getScrobbles($number) {
clint's avatar
clint committed
167 168 169 170 171
		try {
			$data = Server::getRecentScrobbles($number, $this->uniqueid);
		} catch (exception $e) {
			throw (new Exception('Breakage while getting recent scrobbles'));
		}
172
		if(!isset($data)) { return array(); }
tonyb486's avatar
tonyb486 committed
173
		return $data;
174 175 176 177 178 179 180 181 182
	}

	/**
	 * Retrieve a user's avatar via the gravatar service
	 *
	 * @param int $size The desired size of the avatar (between 1 and 512 pixels)
	 * @return A URL to the user's avatar image
	 */
	function getAvatar($size=64) {
183 184
		if (!empty($this->avatar_uri))
			return $this->avatar_uri;
clint's avatar
clint committed
185

186
		return 'http://www.gravatar.com/avatar/' . md5($this->email) . '?s=' . $size . '&d=monsterid';
187
	}
188

189 190
	function getURL($component='profile') {
		return Server::getUserURL($this->name, $component);
191
	}
192

193 194 195 196 197
	/**
	 * Get a user's now-playing tracks
	 *
	 * @return An array of nowplaying data
	 */
198 199
	function getNowPlaying($number) {
		return Server::getNowPlaying($number, $this->name);
clint's avatar
clint committed
200 201
	}

202 203 204 205 206 207
	/**
	 * Log in to the gnukebox server
	 *
	 * @return A string containing the session key to be used for scrobbling
	 */
	function getScrobbleSession() {
clint's avatar
clint committed
208
		global $adodb;
209
		$session_id = md5(mt_rand() . time());
210 211
		$sql = 'INSERT INTO Scrobble_Sessions(userid, sessionid, client, expires) VALUES ('
			. ($this->uniqueid) . ','
clint's avatar
clint committed
212
			. $adodb->qstr($session_id) . ','
213
			. '\'lfm\','
clint's avatar
clint committed
214 215 216 217 218 219
			. (time() + 86400) . ')';
		if($adodb->Execute($sql)) {
			return $session_id;
		} else {
			return false;
		}
220 221 222 223 224 225 226 227 228
	}

	/**
	 * Log in to the radio server
	 *
	 * @param string $station The station to be played
	 * @return A string containing the session key to be used for streaming
	 */
	function getRadioSession($station) {
229
		return Server::getRadioSession($station, $this->name);
230 231
	}

clint's avatar
clint committed
232 233 234 235 236
	/**
	 * get user's top 20 tracks
	 *
	 * @return user's top 20 tracks
	 */
clint's avatar
clint committed
237
	function getTopTracks($number=20, $since=null) {
clint's avatar
clint committed
238
		global $adodb;
clint's avatar
clint committed
239

clint's avatar
clint committed
240
		if ($since) {
clint's avatar
clint committed
241
			$query = 'SELECT COUNT(track) as freq, artist, album, track FROM Scrobbles WHERE userid = '.($this->uniqueid).' AND time > '.(int)($since).' GROUP BY artist,album,track ORDER BY freq DESC LIMIT ' . ($number);
clint's avatar
clint committed
242
		} else {
clint's avatar
clint committed
243
			$query = 'SELECT COUNT(track) as freq, artist, album, track FROM Scrobbles WHERE userid = '.($this->uniqueid).' GROUP BY artist,album,track ORDER BY freq DESC LIMIT ' . ($number);
clint's avatar
clint committed
244
		}
clint's avatar
clint committed
245 246
		$adodb->SetFetchMode(ADODB_FETCH_ASSOC);
		$data = $adodb->CacheGetAll(7200,$query);
clint's avatar
clint committed
247
		if (!$data) {
248
			throw new Exception('ERROR ' . $query);
clint's avatar
clint committed
249
		}
clint's avatar
clint committed
250

251 252
		$maxcount = 0;

clint's avatar
clint committed
253 254 255 256
		foreach($data as &$i) {
			$row = sanitize($i);
			$row['artisturl'] = Server::getArtistURL($row['artist']);
			$row['trackurl'] = Server::getTrackURL($row['artist'],$row['album'],$row['track']);
clint's avatar
clint committed
257 258
			if ((int)$row['freq'] > $maxcount) {
				$maxcount = (int)$row['freq'];
clint's avatar
clint committed
259 260 261
			}
			$result[] = $row;
		}
clint's avatar
clint committed
262

263
		if ($maxcount > 0) {
264
			foreach($result as &$row) {
clint's avatar
clint committed
265
				$row['width']=(int)(100 * ($row['freq']/$maxcount));
266 267 268
			}
		}

clint's avatar
clint committed
269
		return $result;
clint's avatar
clint committed
270
	}
clint's avatar
clint committed
271 272 273 274 275

	public function getTotalTracks($since=null) {
		global $adodb;

		if ($since) {
276
			$query = 'SELECT COUNT(*) FROM Scrobbles WHERE userid = '.($this->uniqueid).' AND time > '.(int)($since);
clint's avatar
clint committed
277
		} else {
278
			$query = 'SELECT COUNT(*) FROM Scrobbles WHERE userid = '.($this->uniqueid);
clint's avatar
clint committed
279 280
		}
		try {
clint's avatar
clint committed
281
			$tracks = $adodb->CacheGetOne(200, $query);
clint's avatar
clint committed
282 283 284 285 286 287
		} catch (exception $e) {
			$tracks = 0;
		}

		return $tracks;
	}
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304

	/**
	 * Get a user's most used tags
	 *
	 * @param int $limit The number of tags to return (default to 10)
	 * @return An array of tag details
	 */
	function getTopTags($limit=10) {
		global $adodb;

		$res = $adodb->CacheGetAll(600, 'SELECT tag, COUNT(tag) AS freq FROM tags WHERE ' 
			. ' userid = ' . $this->uniqueid
			. ' GROUP BY tag '
			. ' LIMIT ' . $limit);

		return $res;
	}
tonyb486's avatar
tonyb486 committed
305
}