summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--admin/preferences.php3
-rwxr-xr-xdocs/CHANGELOG6
-rw-r--r--lib/class/audioscrobbler.class.php228
-rw-r--r--lib/class/user.class.php140
-rw-r--r--lib/init.php3
-rw-r--r--lib/preferences.php24
-rw-r--r--modules/plugins/Lastfm.plugin.php77
-rw-r--r--stats.php92
-rw-r--r--templates/show_mpd_pl_box.inc.php29
-rw-r--r--templates/show_mpdpl.inc179
-rw-r--r--templates/show_mpdplay.inc174
-rw-r--r--templates/show_user_recommendations.inc.php60
-rw-r--r--templates/show_user_stats.inc.php60
-rw-r--r--templates/show_users.inc6
14 files changed, 626 insertions, 455 deletions
diff --git a/admin/preferences.php b/admin/preferences.php
index 27922ea5..ba4802e3 100644
--- a/admin/preferences.php
+++ b/admin/preferences.php
@@ -56,6 +56,7 @@ switch($action) {
$preferences = $temp_user->get_preferences();
}
else {
+ $fullname = _('Site');
init_preferences();
$GLOBALS['user']->set_preferences();
set_theme();
@@ -78,7 +79,7 @@ switch($action) {
break;
default:
$preferences = $temp_user->get_preferences();
- $fullname = "Site";
+ $fullname = _('Site');
break;
} // End Switch Action
diff --git a/docs/CHANGELOG b/docs/CHANGELOG
index 95ec1bdc..59f1244e 100755
--- a/docs/CHANGELOG
+++ b/docs/CHANGELOG
@@ -4,6 +4,12 @@
--------------------------------------------------------------------------
v.3.3.3-Beta1
+ - Added Recommendations based on Ratings to Stats page
+ - Encoded the LastFM password so that it isn't displayed or
+ stored in plain text.
+ - Fixed an issue with Admin -> Streaming -> Localplay Level
+ not correctly displaying the current setting
+ - Integrated LastFM plugin per user requests.
- Added /bin/delete_disabled.php.inc to delete any disabled
songs in your DB, defaults to Debug only mode
- Fixed display issue with players that ignore EXTINF in m3us
diff --git a/lib/class/audioscrobbler.class.php b/lib/class/audioscrobbler.class.php
new file mode 100644
index 00000000..68162c46
--- /dev/null
+++ b/lib/class/audioscrobbler.class.php
@@ -0,0 +1,228 @@
+<?php
+/*
+
+ Copyright (c) 2001 - 2006 Ampache.org
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License v2
+ as published by the Free Software Foundation.
+
+ 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+class scrobbler {
+
+ var $error_msg;
+ var $username;
+ var $password;
+ var $challenge;
+ var $submit_host;
+ var $submit_port;
+ var $submit_url;
+ var $queued_tracks;
+
+ /**
+ * Constructor
+ * This is the constructer it takes a username and password
+ */
+ function scrobbler($username, $password) {
+
+ $this->error_msg = '';
+ $this->username = trim($username);
+ $this->password = trim($password);
+ $this->challenge = '';
+ $this->queued_tracks = array();
+
+ } // scrobbler
+
+ /**
+ * get_error_msg
+ */
+ function get_error_msg() {
+
+ return $this->error_msg;
+
+ } // get_error_msg
+
+ /**
+ * get_queue_count
+ function get_queue_count() {
+
+ return count($this->queued_tracks);
+
+ } // get_queue_count
+
+ /**
+ * handshake
+ * This does a handshake with the audioscrobber server it doesn't pass the password, but
+ * it does pass the username and has a 10 second timeout
+ */
+ function handshake() {
+
+ $as_socket = @fsockopen('post.audioscrobbler.com', 80, $errno, $errstr, 10);
+ if(!$as_socket) {
+ $this->error_msg = $errstr;
+ return false;
+ }
+
+ $username = rawurlencode($this->username);
+
+ $get_string = "GET /?hs=true&p=1.1&c=m3a&v=0.1&u=$username HTTP/1.1\r\n";
+
+ fwrite($as_socket, $get_string);
+ fwrite($as_socket, "Host: post.audioscrobbler.com\r\n");
+ fwrite($as_socket, "Accept: */*\r\n\r\n");
+
+ $buffer = '';
+ while(!feof($as_socket)) {
+ $buffer .= fread($as_socket, 8192);
+ }
+ fclose($as_socket);
+ $split_response = preg_split("/\r\n\r\n/", $buffer);
+ if(!isset($split_response[1])) {
+ $this->error_msg = 'Did not receive a valid response';
+ return false;
+ }
+ $response = explode("\n", $split_response[1]);
+ if(substr($response[0], 0, 6) == 'FAILED') {
+ $this->error_msg = substr($response[0], 7);
+ return false;
+ }
+ if(substr($response[0], 0, 7) == 'BADUSER') {
+ $this->error_msg = 'Invalid Username';
+ return false;
+ }
+ if(substr($response[0], 0, 6) == 'UPDATE') {
+ $this->error_msg = 'You need to update your client: '.substr($response[0], 7);
+ return false;
+ }
+
+ if(preg_match('/http:\/\/(.*):(\d+)(.*)/', $response[3], $matches)) {
+ $this->submit_host = $matches[1];
+ $this->submit_port = $matches[2];
+ $this->submit_url = $matches[3];
+ } else {
+ $this->error_msg = 'Invalid POST URL returned, unable to continue';
+ return false;
+ }
+
+ $this->challenge = $response[2];
+ return true;
+
+ } // handshake
+
+ /**
+ * queue_track
+ * This queues the LastFM track by storing it in this object, it doesn't actually
+ * submit the track or talk to LastFM in anyway, kind of useless for our uses but its
+ * here, and that's how it is.
+ */
+ function queue_track($artist, $album, $track, $timestamp, $length) {
+ $date = gmdate('Y-m-d H:i:s', $timestamp);
+ $mydate = date('Y-m-d H:i:s T', $timestamp);
+
+ if($length < 30) {
+ debug_event('lastfm',"Not queuing track, too short",'5');
+ return false;
+ }
+
+ $newtrack = array();
+ $newtrack['artist'] = $artist;
+ $newtrack['album'] = $album;
+ $newtrack['track'] = $track;
+ $newtrack['length'] = $length;
+ $newtrack['time'] = $date;
+
+ $this->queued_tracks[$timestamp] = $newtrack;
+ return true;
+
+ } // queue_track
+ /**
+ * submit_tracks
+ * This actually talks to LastFM submiting the tracks that are queued up. It
+ * passed the md5'd password combinted with the challenge, which is then md5'd
+ */
+ function submit_tracks() {
+
+ // Check and make sure that we've got some queued tracks
+ if(!count($this->queued_tracks)) {
+ $this->error_msg = "No tracks to submit";
+ return false;
+ }
+
+ //sort array by timestamp
+ ksort($this->queued_tracks);
+
+ // build the query string
+ $query_str = 'u='.rawurlencode($this->username).'&s='.rawurlencode(md5($this->password.$this->challenge)).'&';
+
+ $i = 0;
+
+ foreach($this->queued_tracks as $track) {
+ $query_str .= "a[$i]=".rawurlencode($track['artist'])."&t[$i]=".rawurlencode($track['track'])."&b[$i]=".rawurlencode($track['album'])."&";
+ $query_str .= "m[$i]=&l[$i]=".rawurlencode($track['length'])."&i[$i]=".rawurlencode($track['time'])."&";
+ $i++;
+ }
+
+ $as_socket = @fsockopen($this->submit_host, $this->submit_port, $errno, $errstr, 10);
+
+ if(!$as_socket) {
+ $this->error_msg = $errstr;
+ return false;
+ }
+
+ $action = "POST ".$this->submit_url." HTTP/1.0\r\n";
+ fwrite($as_socket, $action);
+ fwrite($as_socket, "Host: ".$this->submit_host."\r\n");
+ fwrite($as_socket, "Accept: */*\r\n");
+ fwrite($as_socket, "Content-type: application/x-www-form-urlencoded\r\n");
+ fwrite($as_socket, "Content-length: ".strlen($query_str)."\r\n\r\n");
+
+ fwrite($as_socket, $query_str."\r\n\r\n");
+
+ $buffer = '';
+ while(!feof($as_socket)) {
+ $buffer .= fread($as_socket, 8192);
+ }
+ fclose($as_socket);
+
+ $split_response = preg_split("/\r\n\r\n/", $buffer);
+ if(!isset($split_response[1])) {
+ $this->error_msg = 'Did not receive a valid response';
+ return false;
+ }
+ $response = explode("\n", $split_response[1]);
+ if(!isset($response[0])) {
+ $this->error_msg = 'Unknown error submitting tracks'.
+ "\nDebug output:\n".$buffer;
+ return false;
+ }
+ if(substr($response[0], 0, 6) == 'FAILED') {
+ $this->error_msg = $response[0];
+ return false;
+ }
+ if(substr($response[0], 0, 7) == 'BADAUTH') {
+ $this->error_msg = 'Invalid username/password';
+ return false;
+ }
+ if(substr($response[0], 0, 2) != 'OK') {
+ $this->error_msg = 'Unknown error submitting tracks'.
+ "\nDebug output:\n".$buffer;
+ return false;
+ }
+
+ return true;
+
+ } // submit_tracks
+
+} // end audioscrobbler class
+?>
diff --git a/lib/class/user.class.php b/lib/class/user.class.php
index fefca81f..f662e7df 100644
--- a/lib/class/user.class.php
+++ b/lib/class/user.class.php
@@ -156,11 +156,10 @@ class User {
}
} // get_preferences
- /*!
- @function get_favorites
- @discussion returns an array of your $type
- favorites
- */
+ /**
+ * get_favorites
+ * returns an array of your $type favorites
+ */
function get_favorites($type) {
$web_path = conf('web_path');
@@ -209,6 +208,68 @@ class User {
} // get_favorites
+ /**
+ * get_recommendations
+ * This returns recommended objects of $type. The recommendations
+ * are based on voodoo economics,the phase of the moon and my current BAL.
+ */
+ function get_recommendations($type) {
+
+ /* First pull all of your ratings of this type */
+ $sql = "SELECT object_id,user_rating FROM ratings " .
+ "WHERE object_type='" . sql_escape($type) . "' AND user='" . sql_escape($this->id) . "'";
+ $db_results = mysql_query($sql,dbh());
+
+ while ($r = mysql_fetch_assoc($db_results)) {
+ /* Store the fact that you rated this */
+ $key = $r['object_id'];
+ $ratings[$key] = true;
+
+ /* Build a key'd array of users with this same rating */
+ $sql = "SELECT user FROM ratings WHERE object_type='" . sql_escape($type) . "' " .
+ "AND user !='" . sql_escape($this->id) . "' AND object_id='" . sql_escape($r['object_id']) . "' " .
+ "AND user_rating ='" . sql_escape($r['user_rating']) . "'";
+ $user_results = mysql_query($sql,dbh());
+
+ while ($user_info = mysql_fetch_assoc($user_results)) {
+ $key = $user_info['user'];
+ $users[$key]++;
+ }
+
+ } // end while
+
+ /* now we've got your ratings, and all users and the # of ratings that match your ratings
+ * sort the users[$key] array by value and then find things they've rated high (4+) that you
+ * haven't rated
+ */
+ asort($users);
+ $recommendations = array();
+
+ foreach ($users as $user_id=>$score) {
+
+ /* Find everything they've rated at 4+ */
+ $sql = "SELECT object_id,user_rating FROM ratings " .
+ "WHERE user='" . sql_escape($user_id) . "' AND user_rating >='4' AND object_type = '" . sql_escape($type) . "' ORDER BY user_rating DESC";
+ $db_results = mysql_query($sql,dbh());
+
+ while ($r = mysql_fetch_assoc($db_results)) {
+ $key = $r['object_id'];
+ if (isset($ratings[$key])) { continue; }
+
+ /* Let's only get 5 total for now */
+ if (count($recommendations) > 5) { return $recommendations; }
+
+ $recommendations[$key] = $r['user_rating'];
+
+ } // end while
+
+
+ } // end foreach users
+
+ return $recommendations;
+
+ } // get_recommendations
+
/*!
@function is_logged_in
@discussion checks to see if $this user is logged in
@@ -433,7 +494,7 @@ class User {
$song_info = new Song($song_id);
//FIXME:: User uid reference
$user = $this->uid;
-
+
if (!$song_info->file) { return false; }
$stats = new Stats();
@@ -442,6 +503,38 @@ class User {
$stats->insert('artist',$song_info->artist,$user);
$stats->insert('genre',$song_info->genre,$user);
+ /**
+ * Record this play to LastFM
+ * because it lags like the dickens try twice on everything
+ */
+ if (!empty($this->prefs['lastfm_user']) AND !empty($this->prefs['lastfm_pass'])) {
+ $song_info->format_song();
+ $lastfm = new scrobbler($this->prefs['lastfm_user'],$this->prefs['lastfm_pass']);
+ /* Attempt handshake */
+ $handshake = $lastfm->handshake();
+
+ /* We failed, try again */
+ if (!$handshake) { sleep(1); $handshake = $lastfm->handshake(); }
+
+ if ($handshake) {
+ if (!$lastfm->queue_track($song_info->f_artist_full,$song_info->f_album_full,$song_info->title,time(),$song_info->time)) {
+ debug_event('LastFM','Error: Queue Failed: ' . $lastfm->error_msg,'3');
+ }
+
+ $submit = $lastfm->submit_tracks();
+
+ /* Try again if it fails */
+ if (!$submit) { sleep(1); $submit = $lastfm->submit_tracks(); }
+
+ if (!$submit) {
+ debug_event('LastFM','Error Submit Failed: ' . $lastfm->error_msg,'3');
+ }
+ } // if handshake
+ else {
+ debug_event('LastFM','Error: Handshake failed with LastFM: ' . $lastfm->error_msg,'3');
+ }
+ } // record to LastFM
+
} // update_stats
/**
@@ -583,6 +676,41 @@ class User {
} // format_favorites
/**
+ * format_recommendations
+ * This takes an array of [object_id] = ratings
+ * and displays them in a semi-pretty format
+ */
+ function format_recommendations($items,$type) {
+
+ foreach ($items as $object_id=>$rating) {
+
+ switch ($type) {
+ case 'artist':
+ $object = new Artist($object_id);
+ $object->format_artist();
+ $name = $object->f_name;
+ break;
+ case 'album':
+ $object = new Album($object_id);
+ $object->format_album();
+ $name = $object->f_name;
+ break;
+ case 'song':
+ $object = new Song($object_id);
+ $object->format_song();
+ $name = $object->f_title;
+ break;
+ } // end switch on type
+ $results[] = "<li>$name -- $rating<br />\n</li>";
+
+ } // end foreach items
+
+
+ return $results;
+
+ } // format_recommendations
+
+ /**
* fix_preferences
* this makes sure that the specified user
* has all the correct preferences. This function
diff --git a/lib/init.php b/lib/init.php
index d645f0ae..abf43b39 100644
--- a/lib/init.php
+++ b/lib/init.php
@@ -172,6 +172,7 @@ if (conf('ratings')) {
require_once(conf('prefix') . '/lib/rating.lib.php');
}
+
// Classes
require_once(conf('prefix') . '/lib/class/localplay.class.php');
require_once(conf('prefix') . '/lib/class/plugin.class.php');
@@ -190,6 +191,8 @@ require_once(conf('prefix') . '/lib/class/access.class.php');
require_once(conf('prefix') . '/lib/class/error.class.php');
require_once(conf('prefix') . '/lib/class/genre.class.php');
require_once(conf('prefix') . '/lib/class/flag.class.php');
+require_once(conf('prefix') . '/lib/class/audioscrobbler.class.php');
+
/* Set a new Error Handler */
$old_error_handler = set_error_handler("ampache_error_handler");
diff --git a/lib/preferences.php b/lib/preferences.php
index 6d1d5a5a..62781048 100644
--- a/lib/preferences.php
+++ b/lib/preferences.php
@@ -123,10 +123,16 @@ function update_preferences($pref_id=0) {
case 'sample_rate':
$value = validate_bitrate($value);
break;
+ /* MD5 the LastFM so it's not plainTXT */
+ case 'lastfm_pass':
+ /* If it's our default blanking thing then don't use it */
+ if ($value == '******') { unset($_REQUEST[$name]); break; }
+ $value = md5($value);
+ break;
default:
break;
}
-
+
/* Run the update for this preference only if it's set */
if (isset($_REQUEST[$name])) {
update_preference($pref_id,$name,$id,$value);
@@ -221,10 +227,6 @@ function create_preference_input($name,$value) {
elseif ($value == '0') {
echo "Disabled";
}
- elseif ($name == 'upload_dir' || $name == 'quarantine_dir') {
- /* Show Nothing */
- echo "&nbsp;";
- }
else {
echo $value;
}
@@ -318,8 +320,8 @@ function create_preference_input($name,$value) {
echo "</select>\n";
break;
case 'localplay_level':
- if ($GLOBALS['user']->prefs['localplay_level'] == '2') { $is_full = 'selected="selected"'; }
- elseif ($GLOBALS['user']->prefs['localplay_level'] == '1') { $is_global = 'selected="selected"'; }
+ if ($value == '2') { $is_full = 'selected="selected"'; }
+ elseif ($value == '1') { $is_global = 'selected="selected"'; }
echo "<select name=\"$name\">\n";
echo "<option value=\"0\">" . _('Disabled') . "</option>\n";
echo "<option value=\"1\" $is_global>" . _('Global') . "</option>\n";
@@ -336,11 +338,9 @@ function create_preference_input($name,$value) {
} // foreach themes
echo "</select>\n";
break;
- case 'quarantine_dir':
- case 'upload_dir':
- if (!$GLOBALS['user']->has_access(100)) {
- break;
- }
+ case 'lastfm_pass':
+ echo "<input type=\"password\" size=\"16\" name=\"$name\" value=\"******\" />";
+ break;
default:
echo "<input type=\"text\" size=\"$len\" name=\"$name\" value=\"$value\" />";
break;
diff --git a/modules/plugins/Lastfm.plugin.php b/modules/plugins/Lastfm.plugin.php
new file mode 100644
index 00000000..cb833bea
--- /dev/null
+++ b/modules/plugins/Lastfm.plugin.php
@@ -0,0 +1,77 @@
+<?php
+/*
+
+ Copyright (c) 2001 - 2006 Ampache.org
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License v2
+ as published by the Free Software Foundation.
+
+ 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+class AmpacheLastfm {
+
+ var $name ='Last.FM';
+ var $description ='Records your played songs to your Last.FM Account';
+ var $url ='';
+ var $version ='000001';
+ var $min_ampache ='333001';
+ var $max_ampache ='333005';
+
+ /**
+ * Constructor
+ * This function does nothing...
+ */
+ function PluginLastfm() {
+
+ return true;
+
+ } // PluginLastfm
+
+ /**
+ * install
+ * This is a required plugin function it inserts the required preferences
+ * into Ampache
+ */
+ function install() {
+
+ /* We need to insert the new preferences */
+ $sql = "INSERT INTO preferences (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
+ "VALUES ('lastfm_user',' ','Last.FM Username','25','string','options')";
+ $db_results = mysql_query($sql,dbh());
+
+ $sql = "INSERT INTO preferences (`name`,`value`,`description`,`level`,`type`,`catagory`) " .
+ "VALUES ('lastfm_pass',' ','Last.FM Password','25','string','options')";
+ $db_results = mysql_query($sql,dbh());
+
+ fix_all_users_prefs();
+
+ } // install
+
+ /**
+ * uninstall
+ * This is a required plugin function it removes the required preferences from
+ * the database returning it to its origional form
+ */
+ function uninstall() {
+
+ /* We need to remove the preivously added preferences */
+ $sql = "DELETE FROM preferences WHERE name='lastfm_pass' OR name='lastfm_user'";
+ $db_results = mysql_query($sql,dbh());
+
+ fix_all_users_prefs();
+
+ } // uninstall
+
+} // end AmpacheLastfm
+?>
diff --git a/stats.php b/stats.php
index 48e58a63..6bd5e077 100644
--- a/stats.php
+++ b/stats.php
@@ -26,56 +26,46 @@
*/
require_once('lib/init.php');
-/* If we are a full admin then we can see other peoples stats! */
-if ($GLOBALS['user']->has_access(100) AND isset($_REQUEST['user_id'])) {
- $working_user = new User($_REQUEST['user_id']);
-}
-else {
- $working_user = $GLOBALS['user'];
-}
-
show_template('header');
-$title = $working_user->fullname . ' ' . _('Favorites') . ':';
+
+$action = scrub_in($_REQUEST['action']);
+
+/* Switch on the action to be performed */
+switch ($action) {
+ case 'user_stats':
+ /* Get em! */
+ $working_user = new User($_REQUEST['user_id']);
+
+ /* Pull favs */
+ $favorite_artists = $working_user->get_favorites('artist');
+ $favorite_albums = $working_user->get_favorites('album');
+ $favorite_songs = $working_user->get_favorites('song');
+
+ require_once(conf('prefix') . '/templates/show_user_stats.inc.php');
+
+ break;
+ /* Show their stats */
+ default:
+ /* Here's looking at you kid! */
+ $working_user = $GLOBALS['user'];
+
+ /* Pull favs */
+ $favorite_artists = $working_user->get_favorites('artist');
+ $favorite_albums = $working_user->get_favorites('album');
+ $favorite_songs = $working_user->get_favorites('song');
+
+ require_once(conf('prefix') . '/templates/show_user_stats.inc.php');
+
+ /* Build Recommendations from Ratings */
+ $recommended_artists = $working_user->get_recommendations('artist');
+ $recommended_albums = $working_user->get_recommendations('albums');
+ $recommended_songs = $working_user->get_recommendations('song');
+
+ require_once(conf('prefix') . '/templates/show_user_recommendations.inc.php');
+
+ break;
+} // end switch on action
+
+show_footer();
+
?>
-<?php require (conf('prefix') . '/templates/show_box_top.inc.php'); ?>
-<table cellpadding="5" cellspacing="5" border="0" width="100%">
- <tr>
- <td valign="top">
- <?php
- if ( $items = $working_user->get_favorites('artist') ) {
- $items = $working_user->format_favorites($items);
- show_info_box('Favorite Artists', 'artist', $items);
- }
- else {
- echo "<span class=\"error\">" . _('Not Enough Data') . "</span>";
- }
- ?>
- </td>
-
- <td valign="top">
- <?php
- if ( $items = $working_user->get_favorites('song') ) {
- $items = $working_user->format_favorites($items);
- show_info_box('Favorite Songs', 'your_song', $items);
- }
- else {
- echo "<span class=\"error\">" . _('Not Enough Data') . "</span>";
- }
- ?>
- </td>
-
- <td valign="top">
- <?php
- if ( $items = $working_user->get_favorites('album') ) {
- $items = $working_user->format_favorites($items);
- show_info_box('Favorite Albums', 'album', $items);
- }
- else {
- echo "<span class=\"error\">" . _('Not Enough Data') . "</span>";
- }
- ?>
- </td>
- </tr>
-</table>
-<?php require (conf('prefix') . '/templates/show_box_bottom.inc.php'); ?>
-<?php show_footer(); ?>
diff --git a/templates/show_mpd_pl_box.inc.php b/templates/show_mpd_pl_box.inc.php
deleted file mode 100644
index 429a2866..00000000
--- a/templates/show_mpd_pl_box.inc.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-/*
-
- Copyright (c) 2001 - 2005 Ampache.org
- All rights reserved.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- 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 General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-?>
-<table border="0" cellpadding="0" cellspacing="1" class="text-box">
-<tr align="center">
- <td >
- <?php show_playlist_dropdown($GLOBALS['playlist_id']); ?>
- </td>
-</tr>
-</table>
diff --git a/templates/show_mpdpl.inc b/templates/show_mpdpl.inc
deleted file mode 100644
index 50da3349..00000000
--- a/templates/show_mpdpl.inc
+++ /dev/null
@@ -1,179 +0,0 @@
-<?php
-/*
-
- Copyright (c) 2001 - 2006 Ampache.org
- All rights reserved.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- 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 General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-$web_path = conf('web_path');
-/*
-
-TTD:
-- It would be nice if flagged songs showed up in a flagged color (e.g. red).
-- Accept one or more parameters by which the caller specify which columns are displayed.
-- What is the best way to deal with the play pointer when stopped. MPD doesn't report a "position" but stop restarts at the song
- that was playing before the stop.
-
-*/
-
-
-$nopad = "style='padding: 0px 0px 0px 0px'";
-
-$myMpd = init_mpd();
-?>
-
-<form name="songs" action="<?php echo $web_path."/amp-mpd.php"; ?>" method="post" enctype="multipart/form-data">
-<table id= "mpdpl" border="0" cellpadding="0" cellspacing="1" class="tabledata">
-<tr>
- <td style="text-align:center" class="table-header">
- <b><?php echo _("MPD Server Playlist"); ?></b>
- </td>
-</tr>
-<tr>
- <td <?php echo $nopad ?>>
- <table cellspacing="0" cellpadding="0" border="0" width="100%">
- <tr class="table-header">
- <th><a href="#" onclick="check_songs(); return false;">Select</a>/<br /><a href="#" onclick="invert_songs(); return false;">Invert</a></th>
- <th align="left"><?php echo _("Song title"); ?></th>
- <th align="left"><?php echo _("Artist"); ?></th>
- <th align="left"><?php echo _("Album"); ?></th>
- <th align="right"><?php echo _("Track"); ?></th>
- <th align="right"><?php echo _("Time"); ?></th>
- <th><?php echo _("Genre"); ?></th>
- <th><?php echo _("Action"); ?></th>
- </tr>
- <?php
- $pl = $myMpd->playlist;
- if (is_null($pl)) { echo "ERROR: ".$myMpd->errStr."\n"; }
- else {
- $maxlen = strlen (count($pl));
- $condPL = conf('condPL');
- if ($condPL) {
- echo "<tr class=\"".flip_class()."\"><td colspan=\"8\" align=\"center\" style=\"padding: 3px 0px 3px 0px\">... Condensed Playlist ...</td></tr>";
- }
- else {
- echo "<tr><td>&nbsp;</td></tr>";
- }
-
- foreach ($pl as $id=>$entry) {
- if ( ($condPL) and (($id < $myMpd->current_track_id-1) or ($id > $myMpd->current_track_id + 10)) ) {
- continue;
- }
-
- unset($text_class);
- $track = $id+1;
- $len=strlen($track);
-
- while ($len < $maxlen) {
- $track = "0".$track;
- $len++;
- }
-
- $flip = flip_class();
- echo '<tr id="mpd_row'.$id .'" class ="'.
- ($id==$myMpd->current_track_id ? 'npsong': $flip). '">';
-
- $mpddir = conf('mpd_dir')."/";
-
- if (strtolower(conf('mpd_method')) == 'file') {
- $sql = "SELECT genre.name, song.genre, song.id, song.album, song.artist FROM song, genre WHERE file = \"".$mpddir.$entry['file']."\" AND song.genre=genre.id";
- $db_results = @mysql_query($sql,dbh());
- $r = @mysql_fetch_object ($db_results);
- $entry['genre'] = $r->name;
- }
- else {
- list($tmp, $id, $tmp) = preg_split("/(song=|&)/", $entry['file']);
- $r = new Song($id);
- $entry['Title'] = $r->title;
- $entry['Artist'] = $r->get_artist_name();
- $entry['Album'] = $r->get_album_name();
- $entry['genre'] = $r->get_genre_name();
- $entry['Time'] = $r->time;
- $entry['Track'] = $r->track;
- }
-
- $totaltime += $entry['Time'];
- ?>
- <td align="center"> <input type="checkbox" name="song[]" value="<?php echo $entry['Pos']?>" id="song_<?php echo $entry['Pos']; ?>"></input></td>
- <td align="left"> <?php echo $track.". ";?><a href="<?php echo $web_path; ?>/amp-mpd.php?action=skipto&amp;val=<?php echo $entry['Pos']; ?>" title=" <?php echo htmlspecialchars($entry['Title']); ?>"<?php echo $text_class; ?>><?php echo htmlspecialchars($entry['Title']); ?> </a></td>
- <td align="left"> <a href="<?php echo $web_path; ?>/artists.php?action=show&amp;artist=<?php echo htmlspecialchars($r->artist); ?>" title="More from <?php echo htmlspecialchars($entry['Artist']);?>"<?php echo $text_class; ?>><?php echo htmlspecialchars($entry['Artist']);?> </a></td>
- <td align="left"> <a href="<?php echo $web_path; ?>/albums.php?action=show&amp;album=<?php echo htmlspecialchars($r->album); ?>" title="More on <?php echo htmlspecialchars($entry['Album']); ?>"<?php echo $text_class; ?>><?php echo htmlspecialchars($entry['Album']); ?> </a></td>
- <td align="right"> <?php echo $entry['Track']; ?>&nbsp;&nbsp;</td>
- <td align="right"> <?php echo sprintf ("%d:%02d",$entry['Time']/60,$entry['Time']%60); ?>&nbsp;</td>
- <td align="left"> &nbsp;<?php echo $entry['genre']; ?></td>
- <td>
- <a href="<?php echo $web_path;?>/flag.php?song=<?php echo $r->id;?>&amp;action=flag" title="Flag '<?php echo htmlspecialchars($entry['file']);?>' by <?php echo htmlspecialchars($entry['Artist']);?>"<?php echo $text_class;?>>f</a>&nbsp;
- <a href="<?php echo $web_path;?>/amp-mpd.php?action=movenext&amp;val=<?php echo $entry['Pos'];?>" title="Move '<?php echo htmlspecialchars($entry['Title']);?>' to play next "<?php echo $text_class;?>>n</a>&nbsp;
- <a href="<?php echo $web_path;?>/amp-mpd.php?action=rem&amp;id=<?php echo $entry['Pos'];?>" title="Remove '<?php echo htmlspecialchars($entry['Title']);?>' from playlist "<?php echo $text_class;?>>x</a>
- </td>
- </tr>
- <?php
- }// foreach loop
- if (($condPL) && ($myMpd->current_track_id+10 <= $myMpd->playlistcount)) {
- echo "<tr class=\"".flip_class()."\"><td colspan=\"8\" align=\"center\" style=\"padding: 3px 0px 3px 0px\">... Condensed Playlist ...</td></tr>";
- }
- } //else
-
- $time = floor($totaltime/60) . ":" . sprintf("%02d", ($totaltime%60) );
- $num = count($pl);
- if ($condPL) {
- echo "<tr class=\"".flip_class()."\"><td colspan=\"8\" align=\"center\" style=\"padding: 3px 0px 3px 0px\">... Condensed Playlist ...</td></tr>";
- }
- else {
- echo "<tr><td>&nbsp;</td></tr>";
- }
- ?>
- <tr class="table-header" valign="middle">
- <td>
- <input type="hidden" name="action" value="plact" /> <button name="submit" value="submit" type="submit" style = "font-family: <?php echo conf('font')?>; font-size: <?php echo conf('font_size')?>px" title="Take Action on the checked songs">Do</button>
- </td>
- <td valign="middle">
- <select name="todo" style = "font-family: <?php echo conf('font')?>; font-size: <?php echo conf('font_size')?>px" size="1">
- <option>Add to Playlist</option>
- <option>Delete</option>
- <!--<option>Move Next</option> This isn't working yet -->
- </select>
- </td>
- <td valign="middle"><?php show_playlist_dropdown($GLOBALS['playlist_id']); ?></td>
- <td valign="middle"><?php echo $num; ?> song(s)</td>
- <td>&nbsp;</td>
- <td valign="middle" align="right" nowrap="nowrap"><?php echo $time; ?></td>
- <td>&nbsp;</td>
- <td>&nbsp;</td>
- </tr>
- </table>
- </td>
-</tr>
-<tr>
- <td align="center" valign="bottom" class="table-header">
- <i>
- [<a title="<?php echo _("Refresh the Playlist Window"); ?>" href="<?php echo $_SERVER['PHP_SELF']; ?>">refresh</a>]
- <?php if($myMpd->playlist_count > 0 ) {$un = (conf('condPL')) ? "un" : ""; ?>
- [<a title="<?php echo _("Click to shuffle (randomize) the playlist");?>" href="<?php echo $web_path; ?>/amp-mpd.php?action=shuffle"><?php echo _("shuffle")?></a>]
- [<a title="<?php echo _("Click to the clear the playlist");?>" href="<?php echo $web_path; ?>/amp-mpd.php?action=clear">clear</a>]
- <?php if($myMpd->playlist_count > 10) { ?>
- [<a title="<?php echo 'Click to '.$un.'condense playlist';?>" href="<?php echo $web_path; ?>/amp-mpd.php?action=condPL"><?php echo $un?>condense</a>]
- <?php } ?>
- [<a title="<?php echo _("Click to the remove all except the Now Playing");?>" href="<?php echo $web_path; ?>/amp-mpd.php?action=crop">crop</a>]
- <?php } ?>
- </i>
- </td>
-</tr>
-</table>
-<br />
-</form>
-
diff --git a/templates/show_mpdplay.inc b/templates/show_mpdplay.inc
deleted file mode 100644
index fd9c942d..00000000
--- a/templates/show_mpdplay.inc
+++ /dev/null
@@ -1,174 +0,0 @@
-<?php
-/*
-
- Copyright (c) 2001 - 2005 Ampache.org
- All rights reserved.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- 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 General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-/*!
- @header Show mpd controls, this doesn't
- include the playlist, status and what have you.
- this looks a goodbit like local_play
-*/
-$web_path = conf('web_path');
-global $condPL;
-?>
-
-<div align="center"><!-- Is this div neccesary??? or is the below table not needed???-->
-<table border="0" cellpadding="3" cellspacing="0"><!-- MPD Control table -->
-<tr>
-<td>
- <table id="mpd_control" border="0" cellpadding="0" cellspacing="0" class="even" align="center">
- <th class="table-header"><?php echo _("MPD Play Control"); ?></th>
- <tr>
- <td>
- <?php ${$myMpd->state} = "class='selected_button'";
- if (true) /* rigged to do AJAX for now; change to conf('AJAX') later*/ { ?>
- <!-- for testing <input type="button" value="times" onclick="timestuff();"/> -->
- <input type="button" value="|&lt; " onclick="startRequest('action=Prev');"/>
- <input type="button" <?php echo $stop ?> id="stop_button" value=" X " onclick="startRequest('action=stop');"/>
- <input type="button" <?php echo $play ?> id="play_button" value=" &gt; " onclick="startRequest('action=play');"/>
- <input type="button" <?php echo $pause ?> id="pause_button" value=" | | " onclick="startRequest('action=pause');"/>
- <input type="button" value=" &gt;|" onclick="startRequest('action=Next');"/>
- <?php
- }
- else { ?>
- <form action="<?php echo $web_path; ?>/amp-mpd.php" method="post" name="playcontrol" style="display:inline; white-space: nowrap">
- <!-- these used to have class="button" -->
- <input type="submit" title="<?php echo _("Prev"); ?>" name="action" value="|&lt; " />
- <input type="submit" title="<?php echo _("Stop"); ?>" name="action" value=" X " <?php echo $stop; ?> />
- <input type="submit" title="<?php echo _("Play"); ?>" name="action" value=" &gt; " <?php echo $play; ?> />
- <input type="submit" title="<?php echo _("Pause"); ?>" name="action" value=" | | " <?php echo $pause; ?> />
- <input type="submit" title="<?php echo _("Next"); ?>" name="action" value= " &gt;|" />
- </form>
- <?php } ?>
- </td>
- </tr>
- <tr>
- <td class="content"> Volume: <b><span id='volume'><?php echo $myMpd->volume ?></span>%</b></td>
- </tr>
- <tr>
- <td class="content">
- <?php
- if (true) /* rigged to do AJAX for now; change to conf('AJAX') later */ { ?>
- <input type="button" value="0" onclick="startRequest('action=setvol&amp;param1=0');"/>
- <input type="button" value="-25" onclick="startRequest('action=adjvol&amp;param1=-25');"/>
- <input type="button" value="-10" onclick="startRequest('action=adjvol&amp;param1=-10');"/>
- <input type="button" value="+10" onclick="startRequest('action=adjvol&amp;param1=10');"/>
- <input type="button" value="+25" onclick="startRequest('action=adjvol&amp;param1=25');"/>
- <?php
- }
- else { ?>
- [<a href="<?php echo $web_path; ?>/amp-mpd.php?action=setvol&amp;val=0">mute</a>
- <a href="<?php echo $web_path; ?>/amp-mpd.php?action=adjvol&amp;val=-25">-25</a>
- <a href="<?php echo $web_path; ?>/amp-mpd.php?action=adjvol&amp;val=-10">-10</a>
- <a href="<?php echo $web_path; ?>/amp-mpd.php?action=adjvol&amp;val=+10">+10</a>
- <a href="<?php echo $web_path; ?>/amp-mpd.php?action=adjvol&amp;val=+25">+25</a>] ';
- <?php } ?>
- </td>
- </tr>
- <tr>
- <td>
- <?php echo _("Loop"); ?>:
- <form action="<?php echo $web_path; ?>/amp-mpd.php?action=loop" method="post" name="repeatcontrol" style="display:inline;">
- <?php
- $repeat_name = "repeat_" . intval($myMpd->repeat);
- ${$repeat_name} = "style=\"background-color: black;color:white;\"";
- ?>
- &nbsp;&nbsp;&nbsp;&nbsp;
- <input class="button" type="submit" title="<?php echo _("On"); ?>" name="val" value="On" <?php echo $repeat_1; ?> />
- <input class="button" type="submit" title="<?php echo _("Off"); ?>" name="val" value="Off" <?php echo $repeat_0; ?> />
- </form>
- </td>
- </tr>
- <tr>
- <td>
- <?php echo _("Random"); ?>:
- <form action="<?php echo $web_path; ?>/amp-mpd.php?action=random" method="post" name="randomcontrol" style="display:inline;">
- <?php
- $random_name = "random_" . intval($myMpd->random);
- ${$random_name} = "style=\"background-color: black;color:white;\""; ?>
- <input class="button" type="submit" title="<?php echo _("On"); ?>" name="val" value="On" <?php echo $random_1; ?> />
- <input class="button" type="submit" title="<?php echo _("Off"); ?>" name="val" value="Off" <?php echo $random_0; ?> />
- </form>
- </td>
- </tr>
- <tr>
- <td class="content">&nbsp;</td>
- </tr>
- </table>
-</td>
-</tr>
-<tr>
-<td>
- <table id="mpd_np" <?php if (($myMpd->state == "stop") or ($myMpd->state == "pause")) { echo 'class="nodisplay"'; } ?> border="0" cellpadding="0" cellspacing="0">
- <tr>
- <td class="npsong"><b><?php echo _("Now Playing :")?></b></td>
- </tr>
- <tr>
- <td align="center" class="npsong"><?php
- if (!$myMpd->playlist[($myMpd->current_track_id)]['Title']) {
- list($tmp, $id, $tmp) = preg_split("/(song=|&)/", $myMpd->playlist[($myMpd->current_track_id)]['file']);
- $r = new Song($id);
- $myMpd->playlist[($myMpd->current_track_id)]['Title'] = $r->title;
- $myMpd->playlist[($myMpd->current_track_id)]['Artist'] = $r->get_artist_name();
- $myMpd->playlist[($myMpd->current_track_id)]['Album'] = $r->get_album_name();
- }
- echo "<span id='mpd_npinfo'>";
- echo ($myMpd->current_track_id+1).
- ". ".$myMpd->playlist[$myMpd->current_track_id]['Artist'].
- " - ".$myMpd->playlist[$myMpd->current_track_id]['Title'].
- " - ".$myMpd->playlist[$myMpd->current_track_id]['Album'].
- " - ".format_time($myMpd->playlist[$myMpd->current_track_id]['Time']);
- echo "</span>"; ?>
- </td>
- </tr>
- <tr>
- <td align="center" class="npsong">
- <span id="mpd_cur_track_pos"><?php echo format_time($myMpd->current_track_position)?></span>
- (<span id="mpd_pctplayed"><?php echo (round(($myMpd->current_track_position/$myMpd->current_track_length),2)*100)."</span>%) played" ?>
- </td>
- </tr>
- <tr>
- <td>
- <b><?php echo _("On Deck ")?><?php echo _("(in ").
- "<span id = 'mpd_on_deck_in'>".format_time($myMpd->current_track_length - $myMpd->current_track_position)."</span>)"?>
- </b>
- </td>
- </tr>
- <tr>
- <td align="center"><?php
- if (!$myMpd->playlist[($myMpd->current_track_id+1)]['Title']) {
- list($tmp, $id, $tmp) = preg_split("/(song=|&)/", $myMpd->playlist[($myMpd->current_track_id+1)]['file']);
- $r = new Song($id);
- $myMpd->playlist[($myMpd->current_track_id+1)]['Title'] = $r->title;
- $myMpd->playlist[($myMpd->current_track_id+1)]['Artist'] = $r->get_artist_name();
- $myMpd->playlist[($myMpd->current_track_id+1)]['Album'] = $r->get_album_name();
- }
- echo ($myMpd->current_track_id+2).
- ". ".$myMpd->playlist[($myMpd->current_track_id+1)]['Artist'].
- " - ".$myMpd->playlist[($myMpd->current_track_id+1)]['Title'].
- " - ".$myMpd->playlist[($myMpd->current_track_id+1)]['Album'].
- " - ".format_time($myMpd->playlist[($myMpd->current_track_id+1)]['Time']);?>
- </td>
- </tr>
- </table>
-</td>
-</tr>
-</table>
-</div>
diff --git a/templates/show_user_recommendations.inc.php b/templates/show_user_recommendations.inc.php
new file mode 100644
index 00000000..a89be09e
--- /dev/null
+++ b/templates/show_user_recommendations.inc.php
@@ -0,0 +1,60 @@
+<?php
+/*
+
+ Copyright (c) 2001 - 2006 Ampache.org
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License v2
+ as published by the Free Software Foundation.
+
+ 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+?>
+<?php show_box_top($working_user->fullname . ' ' . _('Recommendations')); ?>
+<table class="tabledata">
+<tr>
+ <td valign="top">
+ <?php
+ if (count($recommended_artists)) {
+ $items = $working_user->format_recommendations($recommended_artists,'artist');
+ show_info_box(_('Recommended Aritsts'),'artist',$items);
+ }
+ else {
+ echo "<span class=\"error\">" . _('Not Enough Data') . "</span>";
+ }
+ ?>
+ </td>
+ <td valign="top">
+ <?php
+ if (count($recommended_albums)) {
+ $items = $working_user->format_recommendations($recommended_albums,'album');
+ show_info_box(_('Recommended Albums'),'album',$items);
+ }
+ else {
+ echo "<span class=\"error\">" . _('Not Enough Data') . "</span>";
+ }
+ ?>
+ </td>
+ <td valign="top">
+ <?php
+ if (count($recommended_songs)) {
+ $items = $working_user->format_recommendations($recommended_songs,'song');
+ show_info_box(_('Recommended Songs'),'song',$items);
+ }
+ else {
+ echo "<span class=\"error\">" . _('Not Enough Data') . "</span>";
+ }
+ ?>
+ </td>
+</tr>
+</table>
+<?php show_box_bottom(); ?>
diff --git a/templates/show_user_stats.inc.php b/templates/show_user_stats.inc.php
new file mode 100644
index 00000000..ab962874
--- /dev/null
+++ b/templates/show_user_stats.inc.php
@@ -0,0 +1,60 @@
+<?php
+/*
+
+ Copyright (c) 2001 - 2006 Ampache.org
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License v2
+ as published by the Free Software Foundation.
+
+ 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+?>
+<?php show_box_top($working_user->fullname . ' ' . _('Favorites')); ?>
+<table class="tabledata">
+<tr>
+ <td valign="top">
+ <?php
+ if (count($favorite_artists)) {
+ $items = $working_user->format_favorites($favorite_artists);
+ show_info_box(_('Favorite Artists'),'artist',$items);
+ }
+ else {
+ echo "<span class=\"error\">" . _('Not Enough Data') . "</span>";
+ }
+ ?>
+ </td>
+ <td valign="top">
+ <?php
+ if (count($favorite_albums)) {
+ $items = $working_user->format_favorites($favorite_albums);
+ show_info_box(_('Favorite Albums'),'album',$items);
+ }
+ else {
+ echo "<span class=\"error\">" . _('Not Enough Data') . "</span>";
+ }
+ ?>
+ </td>
+ <td valign="top">
+ <?php
+ if (count($favorite_songs)) {
+ $items = $working_user->format_favorites($favorite_songs);
+ show_info_box(_('Favorite Songs'),'your_song',$items);
+ }
+ else {
+ echo "<span class=\"error\">" . _('Not Enough Data') . "</span>";
+ }
+ ?>
+ </td>
+</tr>
+</table>
+<?php show_box_bottom(); ?>
diff --git a/templates/show_users.inc b/templates/show_users.inc
index f0c4997c..6b7d3e14 100644
--- a/templates/show_users.inc
+++ b/templates/show_users.inc
@@ -99,17 +99,17 @@ while ($results = mysql_fetch_object($db_result)) {
<td>
- <a href="<?php echo $web_path; ?>/admin/users.php?action=edit&amp;user=<?php echo $user->username; ?>">
+ <a href="<?php echo $web_path; ?>/admin/users.php?action=edit&amp;user=<?php echo $user->id; ?>">
<?php echo get_user_icon('edit'); ?>
</a>
</td>
<td>
- <a href="<?php echo $web_path; ?>/admin/preferences.php?action=user&amp;user_id=<?php echo $user->username; ?>">
+ <a href="<?php echo $web_path; ?>/admin/preferences.php?action=user&amp;user_id=<?php echo $user->id; ?>">
<?php echo get_user_icon('preferences'); ?>
</a>
</td>
<td>
- <a href="<?php echo $web_path; ?>/stats.php?user_id=<?php echo $user->username; ?>">
+ <a href="<?php echo $web_path; ?>/stats.php?action=user_stats&amp;user_id=<?php echo $user->id; ?>">
<?php echo get_user_icon('statistics'); ?>
</a>
</td>